101e04c3fSmrg/* 201e04c3fSmrg Copyright (C) Intel Corp. 2006. All Rights Reserved. 301e04c3fSmrg Intel funded Tungsten Graphics to 401e04c3fSmrg develop this 3D driver. 501e04c3fSmrg 601e04c3fSmrg Permission is hereby granted, free of charge, to any person obtaining 701e04c3fSmrg a copy of this software and associated documentation files (the 801e04c3fSmrg "Software"), to deal in the Software without restriction, including 901e04c3fSmrg without limitation the rights to use, copy, modify, merge, publish, 1001e04c3fSmrg distribute, sublicense, and/or sell copies of the Software, and to 1101e04c3fSmrg permit persons to whom the Software is furnished to do so, subject to 1201e04c3fSmrg the following conditions: 1301e04c3fSmrg 1401e04c3fSmrg The above copyright notice and this permission notice (including the 1501e04c3fSmrg next paragraph) shall be included in all copies or substantial 1601e04c3fSmrg portions of the Software. 1701e04c3fSmrg 1801e04c3fSmrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1901e04c3fSmrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2001e04c3fSmrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2101e04c3fSmrg IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 2201e04c3fSmrg LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2301e04c3fSmrg OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2401e04c3fSmrg WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2501e04c3fSmrg 2601e04c3fSmrg **********************************************************************/ 2701e04c3fSmrg /* 2801e04c3fSmrg * Authors: 2901e04c3fSmrg * Keith Whitwell <keithw@vmware.com> 3001e04c3fSmrg */ 3101e04c3fSmrg 3201e04c3fSmrg 3301e04c3fSmrg#include "main/macros.h" 3401e04c3fSmrg#include "main/enums.h" 3501e04c3fSmrg#include "program/program.h" 3601e04c3fSmrg 3701e04c3fSmrg#include "brw_clip.h" 3801e04c3fSmrg 3901e04c3fSmrg 4001e04c3fSmrgstruct brw_reg get_tmp( struct brw_clip_compile *c ) 4101e04c3fSmrg{ 4201e04c3fSmrg struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0); 4301e04c3fSmrg 4401e04c3fSmrg if (++c->last_tmp > c->prog_data.total_grf) 4501e04c3fSmrg c->prog_data.total_grf = c->last_tmp; 4601e04c3fSmrg 4701e04c3fSmrg return tmp; 4801e04c3fSmrg} 4901e04c3fSmrg 5001e04c3fSmrgstatic void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp ) 5101e04c3fSmrg{ 5201e04c3fSmrg if (tmp.nr == c->last_tmp-1) 5301e04c3fSmrg c->last_tmp--; 5401e04c3fSmrg} 5501e04c3fSmrg 5601e04c3fSmrg 5701e04c3fSmrgstatic struct brw_reg make_plane_ud(GLuint x, GLuint y, GLuint z, GLuint w) 5801e04c3fSmrg{ 5901e04c3fSmrg return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x); 6001e04c3fSmrg} 6101e04c3fSmrg 6201e04c3fSmrg 6301e04c3fSmrgvoid brw_clip_init_planes( struct brw_clip_compile *c ) 6401e04c3fSmrg{ 6501e04c3fSmrg struct brw_codegen *p = &c->func; 6601e04c3fSmrg 6701e04c3fSmrg if (!c->key.nr_userclip) { 6801e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0, 0, 0xff, 1)); 6901e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0, 0, 1, 1)); 7001e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff, 0, 1)); 7101e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0, 1, 0, 1)); 7201e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff, 0, 0, 1)); 7301e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1, 0, 0, 1)); 7401e04c3fSmrg } 7501e04c3fSmrg} 7601e04c3fSmrg 7701e04c3fSmrg 7801e04c3fSmrg 7901e04c3fSmrg#define W 3 8001e04c3fSmrg 8101e04c3fSmrg/* Project 'pos' to screen space (or back again), overwrite with results: 8201e04c3fSmrg */ 8301e04c3fSmrgvoid brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos ) 8401e04c3fSmrg{ 8501e04c3fSmrg struct brw_codegen *p = &c->func; 8601e04c3fSmrg 8701e04c3fSmrg /* calc rhw 8801e04c3fSmrg */ 8901e04c3fSmrg brw_math_invert(p, get_element(pos, W), get_element(pos, W)); 9001e04c3fSmrg 9101e04c3fSmrg /* value.xyz *= value.rhw 9201e04c3fSmrg */ 9301e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_16); 9401e04c3fSmrg brw_MUL(p, brw_writemask(pos, WRITEMASK_XYZ), pos, 9501e04c3fSmrg brw_swizzle(pos, BRW_SWIZZLE_WWWW)); 9601e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_1); 9701e04c3fSmrg} 9801e04c3fSmrg 9901e04c3fSmrg 10001e04c3fSmrgstatic void brw_clip_project_vertex( struct brw_clip_compile *c, 10101e04c3fSmrg struct brw_indirect vert_addr ) 10201e04c3fSmrg{ 10301e04c3fSmrg struct brw_codegen *p = &c->func; 10401e04c3fSmrg struct brw_reg tmp = get_tmp(c); 10501e04c3fSmrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 10601e04c3fSmrg GLuint ndc_offset = brw_varying_to_offset(&c->vue_map, 10701e04c3fSmrg BRW_VARYING_SLOT_NDC); 10801e04c3fSmrg 10901e04c3fSmrg /* Fixup position. Extract from the original vertex and re-project 11001e04c3fSmrg * to screen space: 11101e04c3fSmrg */ 11201e04c3fSmrg brw_MOV(p, tmp, deref_4f(vert_addr, hpos_offset)); 11301e04c3fSmrg brw_clip_project_position(c, tmp); 11401e04c3fSmrg brw_MOV(p, deref_4f(vert_addr, ndc_offset), tmp); 11501e04c3fSmrg 11601e04c3fSmrg release_tmp(c, tmp); 11701e04c3fSmrg} 11801e04c3fSmrg 11901e04c3fSmrg 12001e04c3fSmrg 12101e04c3fSmrg 12201e04c3fSmrg/* Interpolate between two vertices and put the result into a0.0. 12301e04c3fSmrg * Increment a0.0 accordingly. 12401e04c3fSmrg * 12501e04c3fSmrg * Beware that dest_ptr can be equal to v0_ptr! 12601e04c3fSmrg */ 12701e04c3fSmrgvoid brw_clip_interp_vertex( struct brw_clip_compile *c, 12801e04c3fSmrg struct brw_indirect dest_ptr, 12901e04c3fSmrg struct brw_indirect v0_ptr, /* from */ 13001e04c3fSmrg struct brw_indirect v1_ptr, /* to */ 13101e04c3fSmrg struct brw_reg t0, 13201e04c3fSmrg bool force_edgeflag) 13301e04c3fSmrg{ 13401e04c3fSmrg struct brw_codegen *p = &c->func; 13501e04c3fSmrg struct brw_reg t_nopersp, v0_ndc_copy; 13601e04c3fSmrg GLuint slot; 13701e04c3fSmrg 13801e04c3fSmrg /* Just copy the vertex header: 13901e04c3fSmrg */ 14001e04c3fSmrg /* 14101e04c3fSmrg * After CLIP stage, only first 256 bits of the VUE are read 14201e04c3fSmrg * back on Ironlake, so needn't change it 14301e04c3fSmrg */ 14401e04c3fSmrg brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1); 14501e04c3fSmrg 14601e04c3fSmrg 14701e04c3fSmrg /* First handle the 3D and NDC interpolation, in case we 14801e04c3fSmrg * need noperspective interpolation. Doing it early has no 14901e04c3fSmrg * performance impact in any case. 15001e04c3fSmrg */ 15101e04c3fSmrg 15201e04c3fSmrg /* Take a copy of the v0 NDC coordinates, in case dest == v0. */ 15301e04c3fSmrg if (c->key.contains_noperspective_varying) { 15401e04c3fSmrg GLuint offset = brw_varying_to_offset(&c->vue_map, 15501e04c3fSmrg BRW_VARYING_SLOT_NDC); 15601e04c3fSmrg v0_ndc_copy = get_tmp(c); 15701e04c3fSmrg brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset)); 15801e04c3fSmrg } 15901e04c3fSmrg 16001e04c3fSmrg /* Compute the new 3D position 16101e04c3fSmrg * 16201e04c3fSmrg * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0 16301e04c3fSmrg */ 16401e04c3fSmrg { 16501e04c3fSmrg GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 16601e04c3fSmrg struct brw_reg tmp = get_tmp(c); 16701e04c3fSmrg brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0); 16801e04c3fSmrg brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0); 16901e04c3fSmrg brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp); 17001e04c3fSmrg release_tmp(c, tmp); 17101e04c3fSmrg } 17201e04c3fSmrg 17301e04c3fSmrg /* Recreate the projected (NDC) coordinate in the new vertex header */ 17401e04c3fSmrg brw_clip_project_vertex(c, dest_ptr); 17501e04c3fSmrg 17601e04c3fSmrg /* If we have noperspective attributes, 17701e04c3fSmrg * we need to compute the screen-space t 17801e04c3fSmrg */ 17901e04c3fSmrg if (c->key.contains_noperspective_varying) { 18001e04c3fSmrg GLuint delta = brw_varying_to_offset(&c->vue_map, 18101e04c3fSmrg BRW_VARYING_SLOT_NDC); 18201e04c3fSmrg struct brw_reg tmp = get_tmp(c); 18301e04c3fSmrg t_nopersp = get_tmp(c); 18401e04c3fSmrg 18501e04c3fSmrg /* t_nopersp = vec4(v1.xy, dest.xy) */ 18601e04c3fSmrg brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta)); 18701e04c3fSmrg brw_MOV(p, tmp, deref_4f(dest_ptr, delta)); 18801e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_16); 18901e04c3fSmrg brw_MOV(p, 19001e04c3fSmrg brw_writemask(t_nopersp, WRITEMASK_ZW), 19101e04c3fSmrg brw_swizzle(tmp, BRW_SWIZZLE_XYXY)); 19201e04c3fSmrg 19301e04c3fSmrg /* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */ 19401e04c3fSmrg brw_ADD(p, t_nopersp, t_nopersp, 19501e04c3fSmrg negate(brw_swizzle(v0_ndc_copy, BRW_SWIZZLE_XYXY))); 19601e04c3fSmrg 19701e04c3fSmrg /* Add the absolute values of the X and Y deltas so that if 19801e04c3fSmrg * the points aren't in the same place on the screen we get 19901e04c3fSmrg * nonzero values to divide. 20001e04c3fSmrg * 20101e04c3fSmrg * After that, we have vert1 - vert0 in t_nopersp.x and 20201e04c3fSmrg * vertnew - vert0 in t_nopersp.y 20301e04c3fSmrg * 20401e04c3fSmrg * t_nopersp = vec2(|v1.x -v0.x| + |v1.y -v0.y|, 20501e04c3fSmrg * |dest.x-v0.x| + |dest.y-v0.y|) 20601e04c3fSmrg */ 20701e04c3fSmrg brw_ADD(p, 20801e04c3fSmrg brw_writemask(t_nopersp, WRITEMASK_XY), 20901e04c3fSmrg brw_abs(brw_swizzle(t_nopersp, BRW_SWIZZLE_XZXZ)), 21001e04c3fSmrg brw_abs(brw_swizzle(t_nopersp, BRW_SWIZZLE_YWYW))); 21101e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_1); 21201e04c3fSmrg 21301e04c3fSmrg /* If the points are in the same place, just substitute a 21401e04c3fSmrg * value to avoid divide-by-zero 21501e04c3fSmrg */ 21601e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, 21701e04c3fSmrg vec1(t_nopersp), 21801e04c3fSmrg brw_imm_f(0)); 21901e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 22001e04c3fSmrg brw_MOV(p, t_nopersp, brw_imm_vf4(brw_float_to_vf(1.0), 22101e04c3fSmrg brw_float_to_vf(0.0), 22201e04c3fSmrg brw_float_to_vf(0.0), 22301e04c3fSmrg brw_float_to_vf(0.0))); 22401e04c3fSmrg brw_ENDIF(p); 22501e04c3fSmrg 22601e04c3fSmrg /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast it. */ 22701e04c3fSmrg brw_math_invert(p, get_element(t_nopersp, 0), get_element(t_nopersp, 0)); 22801e04c3fSmrg brw_MUL(p, vec1(t_nopersp), vec1(t_nopersp), 22901e04c3fSmrg vec1(suboffset(t_nopersp, 1))); 23001e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_16); 23101e04c3fSmrg brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, BRW_SWIZZLE_XXXX)); 23201e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_1); 23301e04c3fSmrg 23401e04c3fSmrg release_tmp(c, tmp); 23501e04c3fSmrg release_tmp(c, v0_ndc_copy); 23601e04c3fSmrg } 23701e04c3fSmrg 23801e04c3fSmrg /* Now we can iterate over each attribute 23901e04c3fSmrg * (could be done in pairs?) 24001e04c3fSmrg */ 24101e04c3fSmrg for (slot = 0; slot < c->vue_map.num_slots; slot++) { 24201e04c3fSmrg int varying = c->vue_map.slot_to_varying[slot]; 24301e04c3fSmrg GLuint delta = brw_vue_slot_to_offset(slot); 24401e04c3fSmrg 24501e04c3fSmrg /* HPOS, NDC already handled above */ 24601e04c3fSmrg if (varying == VARYING_SLOT_POS || varying == BRW_VARYING_SLOT_NDC) 24701e04c3fSmrg continue; 24801e04c3fSmrg 24901e04c3fSmrg 25001e04c3fSmrg if (varying == VARYING_SLOT_EDGE) { 25101e04c3fSmrg if (force_edgeflag) 25201e04c3fSmrg brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1)); 25301e04c3fSmrg else 25401e04c3fSmrg brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta)); 25501e04c3fSmrg } else if (varying == VARYING_SLOT_PSIZ) { 25601e04c3fSmrg /* PSIZ doesn't need interpolation because it isn't used by the 25701e04c3fSmrg * fragment shader. 25801e04c3fSmrg */ 25901e04c3fSmrg } else if (varying < VARYING_SLOT_MAX) { 26001e04c3fSmrg /* This is a true vertex result (and not a special value for the VUE 26101e04c3fSmrg * header), so interpolate: 26201e04c3fSmrg * 26301e04c3fSmrg * New = attr0 + t*attr1 - t*attr0 26401e04c3fSmrg * 26501e04c3fSmrg * Unless the attribute is flat shaded -- in which case just copy 26601e04c3fSmrg * from one of the sources (doesn't matter which; already copied from pv) 26701e04c3fSmrg */ 26801e04c3fSmrg GLuint interp = c->key.interp_mode[slot]; 26901e04c3fSmrg 27001e04c3fSmrg if (interp != INTERP_MODE_FLAT) { 27101e04c3fSmrg struct brw_reg tmp = get_tmp(c); 27201e04c3fSmrg struct brw_reg t = 27301e04c3fSmrg interp == INTERP_MODE_NOPERSPECTIVE ? t_nopersp : t0; 27401e04c3fSmrg 27501e04c3fSmrg brw_MUL(p, 27601e04c3fSmrg vec4(brw_null_reg()), 27701e04c3fSmrg deref_4f(v1_ptr, delta), 27801e04c3fSmrg t); 27901e04c3fSmrg 28001e04c3fSmrg brw_MAC(p, 28101e04c3fSmrg tmp, 28201e04c3fSmrg negate(deref_4f(v0_ptr, delta)), 28301e04c3fSmrg t); 28401e04c3fSmrg 28501e04c3fSmrg brw_ADD(p, 28601e04c3fSmrg deref_4f(dest_ptr, delta), 28701e04c3fSmrg deref_4f(v0_ptr, delta), 28801e04c3fSmrg tmp); 28901e04c3fSmrg 29001e04c3fSmrg release_tmp(c, tmp); 29101e04c3fSmrg } 29201e04c3fSmrg else { 29301e04c3fSmrg brw_MOV(p, 29401e04c3fSmrg deref_4f(dest_ptr, delta), 29501e04c3fSmrg deref_4f(v0_ptr, delta)); 29601e04c3fSmrg } 29701e04c3fSmrg } 29801e04c3fSmrg } 29901e04c3fSmrg 30001e04c3fSmrg if (c->vue_map.num_slots % 2) { 30101e04c3fSmrg GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots); 30201e04c3fSmrg 30301e04c3fSmrg brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0)); 30401e04c3fSmrg } 30501e04c3fSmrg 30601e04c3fSmrg if (c->key.contains_noperspective_varying) 30701e04c3fSmrg release_tmp(c, t_nopersp); 30801e04c3fSmrg} 30901e04c3fSmrg 31001e04c3fSmrgvoid brw_clip_emit_vue(struct brw_clip_compile *c, 31101e04c3fSmrg struct brw_indirect vert, 31201e04c3fSmrg enum brw_urb_write_flags flags, 31301e04c3fSmrg GLuint header) 31401e04c3fSmrg{ 31501e04c3fSmrg struct brw_codegen *p = &c->func; 31601e04c3fSmrg bool allocate = flags & BRW_URB_WRITE_ALLOCATE; 31701e04c3fSmrg 31801e04c3fSmrg brw_clip_ff_sync(c); 31901e04c3fSmrg 32001e04c3fSmrg /* Any URB entry that is allocated must subsequently be used or discarded, 32101e04c3fSmrg * so it doesn't make sense to mark EOT and ALLOCATE at the same time. 32201e04c3fSmrg */ 32301e04c3fSmrg assert(!(allocate && (flags & BRW_URB_WRITE_EOT))); 32401e04c3fSmrg 32501e04c3fSmrg /* Copy the vertex from vertn into m1..mN+1: 32601e04c3fSmrg */ 32701e04c3fSmrg brw_copy_from_indirect(p, brw_message_reg(1), vert, c->nr_regs); 32801e04c3fSmrg 32901e04c3fSmrg /* Overwrite PrimType and PrimStart in the message header, for 33001e04c3fSmrg * each vertex in turn: 33101e04c3fSmrg */ 33201e04c3fSmrg brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header)); 33301e04c3fSmrg 33401e04c3fSmrg 33501e04c3fSmrg /* Send each vertex as a separate write to the urb. This 33601e04c3fSmrg * is different to the concept in brw_sf_emit.c, where 33701e04c3fSmrg * subsequent writes are used to build up a single urb 33801e04c3fSmrg * entry. Each of these writes instantiates a separate 33901e04c3fSmrg * urb entry - (I think... what about 'allocate'?) 34001e04c3fSmrg */ 34101e04c3fSmrg brw_urb_WRITE(p, 34201e04c3fSmrg allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), 34301e04c3fSmrg 0, 34401e04c3fSmrg c->reg.R0, 34501e04c3fSmrg flags, 34601e04c3fSmrg c->nr_regs + 1, /* msg length */ 34701e04c3fSmrg allocate ? 1 : 0, /* response_length */ 34801e04c3fSmrg 0, /* urb offset */ 34901e04c3fSmrg BRW_URB_SWIZZLE_NONE); 35001e04c3fSmrg} 35101e04c3fSmrg 35201e04c3fSmrg 35301e04c3fSmrg 35401e04c3fSmrgvoid brw_clip_kill_thread(struct brw_clip_compile *c) 35501e04c3fSmrg{ 35601e04c3fSmrg struct brw_codegen *p = &c->func; 35701e04c3fSmrg 35801e04c3fSmrg brw_clip_ff_sync(c); 35901e04c3fSmrg /* Send an empty message to kill the thread and release any 36001e04c3fSmrg * allocated urb entry: 36101e04c3fSmrg */ 36201e04c3fSmrg brw_urb_WRITE(p, 36301e04c3fSmrg retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), 36401e04c3fSmrg 0, 36501e04c3fSmrg c->reg.R0, 36601e04c3fSmrg BRW_URB_WRITE_UNUSED | BRW_URB_WRITE_EOT_COMPLETE, 36701e04c3fSmrg 1, /* msg len */ 36801e04c3fSmrg 0, /* response len */ 36901e04c3fSmrg 0, 37001e04c3fSmrg BRW_URB_SWIZZLE_NONE); 37101e04c3fSmrg} 37201e04c3fSmrg 37301e04c3fSmrg 37401e04c3fSmrg 37501e04c3fSmrg 37601e04c3fSmrgstruct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c ) 37701e04c3fSmrg{ 37801e04c3fSmrg return brw_address(c->reg.fixed_planes); 37901e04c3fSmrg} 38001e04c3fSmrg 38101e04c3fSmrg 38201e04c3fSmrgstruct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c ) 38301e04c3fSmrg{ 38401e04c3fSmrg if (c->key.nr_userclip) { 38501e04c3fSmrg return brw_imm_uw(16); 38601e04c3fSmrg } 38701e04c3fSmrg else { 38801e04c3fSmrg return brw_imm_uw(4); 38901e04c3fSmrg } 39001e04c3fSmrg} 39101e04c3fSmrg 39201e04c3fSmrg 39301e04c3fSmrg/* Distribute flatshaded attributes from provoking vertex prior to 39401e04c3fSmrg * clipping. 39501e04c3fSmrg */ 39601e04c3fSmrgvoid brw_clip_copy_flatshaded_attributes( struct brw_clip_compile *c, 39701e04c3fSmrg GLuint to, GLuint from ) 39801e04c3fSmrg{ 39901e04c3fSmrg struct brw_codegen *p = &c->func; 40001e04c3fSmrg 40101e04c3fSmrg for (int i = 0; i < c->vue_map.num_slots; i++) { 40201e04c3fSmrg if (c->key.interp_mode[i] == INTERP_MODE_FLAT) { 40301e04c3fSmrg brw_MOV(p, 40401e04c3fSmrg byte_offset(c->reg.vertex[to], brw_vue_slot_to_offset(i)), 40501e04c3fSmrg byte_offset(c->reg.vertex[from], brw_vue_slot_to_offset(i))); 40601e04c3fSmrg } 40701e04c3fSmrg } 40801e04c3fSmrg} 40901e04c3fSmrg 41001e04c3fSmrg 41101e04c3fSmrg 41201e04c3fSmrgvoid brw_clip_init_clipmask( struct brw_clip_compile *c ) 41301e04c3fSmrg{ 41401e04c3fSmrg struct brw_codegen *p = &c->func; 41501e04c3fSmrg struct brw_reg incoming = get_element_ud(c->reg.R0, 2); 41601e04c3fSmrg 41701e04c3fSmrg /* Shift so that lowest outcode bit is rightmost: 41801e04c3fSmrg */ 41901e04c3fSmrg brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26)); 42001e04c3fSmrg 42101e04c3fSmrg if (c->key.nr_userclip) { 42201e04c3fSmrg struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD); 42301e04c3fSmrg 42401e04c3fSmrg /* Rearrange userclip outcodes so that they come directly after 42501e04c3fSmrg * the fixed plane bits. 42601e04c3fSmrg */ 4277ec681f3Smrg if (p->devinfo->ver == 5 || p->devinfo->is_g4x) 42801e04c3fSmrg brw_AND(p, tmp, incoming, brw_imm_ud(0xff<<14)); 42901e04c3fSmrg else 43001e04c3fSmrg brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14)); 43101e04c3fSmrg 43201e04c3fSmrg brw_SHR(p, tmp, tmp, brw_imm_ud(8)); 43301e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, tmp); 43401e04c3fSmrg 43501e04c3fSmrg release_tmp(c, tmp); 43601e04c3fSmrg } 43701e04c3fSmrg} 43801e04c3fSmrg 43901e04c3fSmrgvoid brw_clip_ff_sync(struct brw_clip_compile *c) 44001e04c3fSmrg{ 44101e04c3fSmrg struct brw_codegen *p = &c->func; 44201e04c3fSmrg 4437ec681f3Smrg if (p->devinfo->ver == 5) { 44401e04c3fSmrg brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1)); 44501e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_Z); 44601e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 44701e04c3fSmrg { 44801e04c3fSmrg brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1)); 44901e04c3fSmrg brw_ff_sync(p, 45001e04c3fSmrg c->reg.R0, 45101e04c3fSmrg 0, 45201e04c3fSmrg c->reg.R0, 45301e04c3fSmrg 1, /* allocate */ 45401e04c3fSmrg 1, /* response length */ 45501e04c3fSmrg 0 /* eot */); 45601e04c3fSmrg } 45701e04c3fSmrg brw_ENDIF(p); 45801e04c3fSmrg brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 45901e04c3fSmrg } 46001e04c3fSmrg} 46101e04c3fSmrg 46201e04c3fSmrgvoid brw_clip_init_ff_sync(struct brw_clip_compile *c) 46301e04c3fSmrg{ 46401e04c3fSmrg struct brw_codegen *p = &c->func; 46501e04c3fSmrg 4667ec681f3Smrg if (p->devinfo->ver == 5) { 46701e04c3fSmrg brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0)); 46801e04c3fSmrg } 46901e04c3fSmrg} 470