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#include "main/macros.h" 3301e04c3fSmrg#include "main/enums.h" 3401e04c3fSmrg#include "program/program.h" 3501e04c3fSmrg 3601e04c3fSmrg#include "brw_clip.h" 3701e04c3fSmrg 3801e04c3fSmrgstatic void release_tmps( struct brw_clip_compile *c ) 3901e04c3fSmrg{ 4001e04c3fSmrg c->last_tmp = c->first_tmp; 4101e04c3fSmrg} 4201e04c3fSmrg 4301e04c3fSmrg 4401e04c3fSmrgvoid brw_clip_tri_alloc_regs( struct brw_clip_compile *c, 4501e04c3fSmrg GLuint nr_verts ) 4601e04c3fSmrg{ 477ec681f3Smrg const struct intel_device_info *devinfo = c->func.devinfo; 4801e04c3fSmrg GLuint i = 0,j; 4901e04c3fSmrg 5001e04c3fSmrg /* Register usage is static, precompute here: 5101e04c3fSmrg */ 5201e04c3fSmrg c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++; 5301e04c3fSmrg 5401e04c3fSmrg if (c->key.nr_userclip) { 5501e04c3fSmrg c->reg.fixed_planes = brw_vec4_grf(i, 0); 5601e04c3fSmrg i += (6 + c->key.nr_userclip + 1) / 2; 5701e04c3fSmrg 5801e04c3fSmrg c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2; 5901e04c3fSmrg } 6001e04c3fSmrg else 6101e04c3fSmrg c->prog_data.curb_read_length = 0; 6201e04c3fSmrg 6301e04c3fSmrg 6401e04c3fSmrg /* Payload vertices plus space for more generated vertices: 6501e04c3fSmrg */ 6601e04c3fSmrg for (j = 0; j < nr_verts; j++) { 6701e04c3fSmrg c->reg.vertex[j] = brw_vec4_grf(i, 0); 6801e04c3fSmrg i += c->nr_regs; 6901e04c3fSmrg } 7001e04c3fSmrg 7101e04c3fSmrg if (c->vue_map.num_slots % 2 && nr_verts > 0) { 7201e04c3fSmrg /* The VUE has an odd number of slots so the last register is only half 7301e04c3fSmrg * used. Fill the second half with zero. 7401e04c3fSmrg */ 7501e04c3fSmrg for (j = 0; j < 3; j++) { 7601e04c3fSmrg GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots); 7701e04c3fSmrg 7801e04c3fSmrg brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0)); 7901e04c3fSmrg } 8001e04c3fSmrg } 8101e04c3fSmrg 8201e04c3fSmrg c->reg.t = brw_vec1_grf(i, 0); 8301e04c3fSmrg c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D); 8401e04c3fSmrg c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD); 8501e04c3fSmrg c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD); 8601e04c3fSmrg c->reg.plane_equation = brw_vec4_grf(i, 4); 8701e04c3fSmrg i++; 8801e04c3fSmrg 8901e04c3fSmrg c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */ 9001e04c3fSmrg c->reg.dp = brw_vec1_grf(i, 4); 9101e04c3fSmrg i++; 9201e04c3fSmrg 9301e04c3fSmrg c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); 9401e04c3fSmrg i++; 9501e04c3fSmrg 9601e04c3fSmrg c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); 9701e04c3fSmrg i++; 9801e04c3fSmrg 9901e04c3fSmrg c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); 10001e04c3fSmrg i++; 10101e04c3fSmrg 10201e04c3fSmrg if (!c->key.nr_userclip) { 10301e04c3fSmrg c->reg.fixed_planes = brw_vec8_grf(i, 0); 10401e04c3fSmrg i++; 10501e04c3fSmrg } 10601e04c3fSmrg 10701e04c3fSmrg if (c->key.do_unfilled) { 10801e04c3fSmrg c->reg.dir = brw_vec4_grf(i, 0); 10901e04c3fSmrg c->reg.offset = brw_vec4_grf(i, 4); 11001e04c3fSmrg i++; 11101e04c3fSmrg c->reg.tmp0 = brw_vec4_grf(i, 0); 11201e04c3fSmrg c->reg.tmp1 = brw_vec4_grf(i, 4); 11301e04c3fSmrg i++; 11401e04c3fSmrg } 11501e04c3fSmrg 11601e04c3fSmrg c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); 11701e04c3fSmrg c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W); 11801e04c3fSmrg i++; 11901e04c3fSmrg 1207ec681f3Smrg if (devinfo->ver == 5) { 12101e04c3fSmrg c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); 12201e04c3fSmrg i++; 12301e04c3fSmrg } 12401e04c3fSmrg 12501e04c3fSmrg c->first_tmp = i; 12601e04c3fSmrg c->last_tmp = i; 12701e04c3fSmrg 12801e04c3fSmrg c->prog_data.urb_read_length = c->nr_regs; /* ? */ 12901e04c3fSmrg c->prog_data.total_grf = i; 13001e04c3fSmrg} 13101e04c3fSmrg 13201e04c3fSmrg 13301e04c3fSmrg 13401e04c3fSmrgvoid brw_clip_tri_init_vertices( struct brw_clip_compile *c ) 13501e04c3fSmrg{ 13601e04c3fSmrg struct brw_codegen *p = &c->func; 13701e04c3fSmrg struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ 13801e04c3fSmrg 13901e04c3fSmrg /* Initial list of indices for incoming vertexes: 14001e04c3fSmrg */ 14101e04c3fSmrg brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 14201e04c3fSmrg brw_CMP(p, 14301e04c3fSmrg vec1(brw_null_reg()), 14401e04c3fSmrg BRW_CONDITIONAL_EQ, 14501e04c3fSmrg tmp0, 14601e04c3fSmrg brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE)); 14701e04c3fSmrg 14801e04c3fSmrg /* XXX: Is there an easier way to do this? Need to reverse every 14901e04c3fSmrg * second tristrip element: Can ignore sometimes? 15001e04c3fSmrg */ 15101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 15201e04c3fSmrg { 15301e04c3fSmrg brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) ); 15401e04c3fSmrg brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) ); 15501e04c3fSmrg if (c->need_direction) 15601e04c3fSmrg brw_MOV(p, c->reg.dir, brw_imm_f(-1)); 15701e04c3fSmrg } 15801e04c3fSmrg brw_ELSE(p); 15901e04c3fSmrg { 16001e04c3fSmrg brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) ); 16101e04c3fSmrg brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) ); 16201e04c3fSmrg if (c->need_direction) 16301e04c3fSmrg brw_MOV(p, c->reg.dir, brw_imm_f(1)); 16401e04c3fSmrg } 16501e04c3fSmrg brw_ENDIF(p); 16601e04c3fSmrg 16701e04c3fSmrg brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) ); 16801e04c3fSmrg brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0)); 16901e04c3fSmrg brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3)); 17001e04c3fSmrg} 17101e04c3fSmrg 17201e04c3fSmrg 17301e04c3fSmrg 17401e04c3fSmrgvoid brw_clip_tri_flat_shade( struct brw_clip_compile *c ) 17501e04c3fSmrg{ 17601e04c3fSmrg struct brw_codegen *p = &c->func; 17701e04c3fSmrg struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ 17801e04c3fSmrg 17901e04c3fSmrg brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 18001e04c3fSmrg brw_CMP(p, 18101e04c3fSmrg vec1(brw_null_reg()), 18201e04c3fSmrg BRW_CONDITIONAL_EQ, 18301e04c3fSmrg tmp0, 18401e04c3fSmrg brw_imm_ud(_3DPRIM_POLYGON)); 18501e04c3fSmrg 18601e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 18701e04c3fSmrg { 18801e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 1, 0); 18901e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 2, 0); 19001e04c3fSmrg } 19101e04c3fSmrg brw_ELSE(p); 19201e04c3fSmrg { 19301e04c3fSmrg if (c->key.pv_first) { 19401e04c3fSmrg brw_CMP(p, 19501e04c3fSmrg vec1(brw_null_reg()), 19601e04c3fSmrg BRW_CONDITIONAL_EQ, 19701e04c3fSmrg tmp0, 19801e04c3fSmrg brw_imm_ud(_3DPRIM_TRIFAN)); 19901e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 20001e04c3fSmrg { 20101e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 0, 1); 20201e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 2, 1); 20301e04c3fSmrg } 20401e04c3fSmrg brw_ELSE(p); 20501e04c3fSmrg { 20601e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 1, 0); 20701e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 2, 0); 20801e04c3fSmrg } 20901e04c3fSmrg brw_ENDIF(p); 21001e04c3fSmrg } 21101e04c3fSmrg else { 21201e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 0, 2); 21301e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 1, 2); 21401e04c3fSmrg } 21501e04c3fSmrg } 21601e04c3fSmrg brw_ENDIF(p); 21701e04c3fSmrg} 21801e04c3fSmrg 21901e04c3fSmrg 22001e04c3fSmrg/** 22101e04c3fSmrg * Loads the clip distance for a vertex into `dst`, and ends with 22201e04c3fSmrg * a comparison of it to zero with the condition `cond`. 22301e04c3fSmrg * 22401e04c3fSmrg * - If using a fixed plane, the distance is dot(hpos, plane). 22501e04c3fSmrg * - If using a user clip plane, the distance is directly available in the vertex. 22601e04c3fSmrg */ 22701e04c3fSmrgstatic inline void 22801e04c3fSmrgload_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx, 22901e04c3fSmrg struct brw_reg dst, GLuint hpos_offset, int cond) 23001e04c3fSmrg{ 23101e04c3fSmrg struct brw_codegen *p = &c->func; 23201e04c3fSmrg 23301e04c3fSmrg dst = vec4(dst); 23401e04c3fSmrg brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1)); 23501e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 23601e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 23701e04c3fSmrg { 23801e04c3fSmrg struct brw_indirect temp_ptr = brw_indirect(7, 0); 23901e04c3fSmrg brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset); 24001e04c3fSmrg brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0)); 24101e04c3fSmrg } 24201e04c3fSmrg brw_ELSE(p); 24301e04c3fSmrg { 24401e04c3fSmrg brw_MOV(p, dst, deref_4f(vtx, hpos_offset)); 24501e04c3fSmrg brw_DP4(p, dst, dst, c->reg.plane_equation); 24601e04c3fSmrg } 24701e04c3fSmrg brw_ENDIF(p); 24801e04c3fSmrg 24901e04c3fSmrg brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f)); 25001e04c3fSmrg} 25101e04c3fSmrg 25201e04c3fSmrg 2537ec681f3Smrg/* Use mesa's clipping algorithms, translated to GFX4 assembly. 25401e04c3fSmrg */ 25501e04c3fSmrgvoid brw_clip_tri( struct brw_clip_compile *c ) 25601e04c3fSmrg{ 25701e04c3fSmrg struct brw_codegen *p = &c->func; 25801e04c3fSmrg struct brw_indirect vtx = brw_indirect(0, 0); 25901e04c3fSmrg struct brw_indirect vtxPrev = brw_indirect(1, 0); 26001e04c3fSmrg struct brw_indirect vtxOut = brw_indirect(2, 0); 26101e04c3fSmrg struct brw_indirect plane_ptr = brw_indirect(3, 0); 26201e04c3fSmrg struct brw_indirect inlist_ptr = brw_indirect(4, 0); 26301e04c3fSmrg struct brw_indirect outlist_ptr = brw_indirect(5, 0); 26401e04c3fSmrg struct brw_indirect freelist_ptr = brw_indirect(6, 0); 26501e04c3fSmrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 26601e04c3fSmrg GLint clipdist0_offset = c->key.nr_userclip 26701e04c3fSmrg ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0) 26801e04c3fSmrg : 0; 26901e04c3fSmrg 27001e04c3fSmrg brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) ); 27101e04c3fSmrg brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c)); 27201e04c3fSmrg brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist)); 27301e04c3fSmrg brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist)); 27401e04c3fSmrg 27501e04c3fSmrg brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) ); 27601e04c3fSmrg 27701e04c3fSmrg /* Set the initial vertex source mask: The first 6 planes are the bounds 27801e04c3fSmrg * of the view volume; the next 8 planes are the user clipping planes. 27901e04c3fSmrg */ 28001e04c3fSmrg brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0)); 28101e04c3fSmrg 28201e04c3fSmrg /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0]. 28301e04c3fSmrg * We'll increment 6 times before we start hitting actual user clipping. */ 28401e04c3fSmrg brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float))); 28501e04c3fSmrg 28601e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 28701e04c3fSmrg { 28801e04c3fSmrg /* if (planemask & 1) 28901e04c3fSmrg */ 29001e04c3fSmrg brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1)); 29101e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 29201e04c3fSmrg 29301e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 29401e04c3fSmrg { 29501e04c3fSmrg /* vtxOut = freelist_ptr++ 29601e04c3fSmrg */ 29701e04c3fSmrg brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) ); 29801e04c3fSmrg brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE)); 29901e04c3fSmrg 30001e04c3fSmrg if (c->key.nr_userclip) 30101e04c3fSmrg brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0)); 30201e04c3fSmrg else 30301e04c3fSmrg brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0)); 30401e04c3fSmrg 30501e04c3fSmrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 30601e04c3fSmrg brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0)); 30701e04c3fSmrg 30801e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 30901e04c3fSmrg { 31001e04c3fSmrg /* vtx = *input_ptr; 31101e04c3fSmrg */ 31201e04c3fSmrg brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0)); 31301e04c3fSmrg 31401e04c3fSmrg load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L); 31501e04c3fSmrg /* (prev < 0.0f) */ 31601e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 31701e04c3fSmrg { 31801e04c3fSmrg load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE); 31901e04c3fSmrg /* IS_POSITIVE(next) 32001e04c3fSmrg */ 32101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 32201e04c3fSmrg { 32301e04c3fSmrg 32401e04c3fSmrg /* Coming back in. 32501e04c3fSmrg */ 32601e04c3fSmrg brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp)); 32701e04c3fSmrg brw_math_invert(p, c->reg.t, c->reg.t); 32801e04c3fSmrg brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev); 32901e04c3fSmrg 33001e04c3fSmrg /* If (vtxOut == 0) vtxOut = vtxPrev 33101e04c3fSmrg */ 33201e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) ); 33301e04c3fSmrg brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev)); 33401e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, 33501e04c3fSmrg BRW_PREDICATE_NORMAL); 33601e04c3fSmrg 33701e04c3fSmrg brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false); 33801e04c3fSmrg 33901e04c3fSmrg /* *outlist_ptr++ = vtxOut; 34001e04c3fSmrg * nr_verts++; 34101e04c3fSmrg * vtxOut = 0; 34201e04c3fSmrg */ 34301e04c3fSmrg brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut)); 34401e04c3fSmrg brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); 34501e04c3fSmrg brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); 34601e04c3fSmrg brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) ); 34701e04c3fSmrg } 34801e04c3fSmrg brw_ENDIF(p); 34901e04c3fSmrg 35001e04c3fSmrg } 35101e04c3fSmrg brw_ELSE(p); 35201e04c3fSmrg { 35301e04c3fSmrg /* *outlist_ptr++ = vtxPrev; 35401e04c3fSmrg * nr_verts++; 35501e04c3fSmrg */ 35601e04c3fSmrg brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev)); 35701e04c3fSmrg brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); 35801e04c3fSmrg brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); 35901e04c3fSmrg 36001e04c3fSmrg load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_L); 36101e04c3fSmrg /* (next < 0.0f) 36201e04c3fSmrg */ 36301e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 36401e04c3fSmrg { 36501e04c3fSmrg /* Going out of bounds. Avoid division by zero as we 36601e04c3fSmrg * know dp != dpPrev from DIFFERENT_SIGNS, above. 36701e04c3fSmrg */ 36801e04c3fSmrg brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev)); 36901e04c3fSmrg brw_math_invert(p, c->reg.t, c->reg.t); 37001e04c3fSmrg brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp); 37101e04c3fSmrg 37201e04c3fSmrg /* If (vtxOut == 0) vtxOut = vtx 37301e04c3fSmrg */ 37401e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) ); 37501e04c3fSmrg brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx)); 37601e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, 37701e04c3fSmrg BRW_PREDICATE_NORMAL); 37801e04c3fSmrg 37901e04c3fSmrg brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true); 38001e04c3fSmrg 38101e04c3fSmrg /* *outlist_ptr++ = vtxOut; 38201e04c3fSmrg * nr_verts++; 38301e04c3fSmrg * vtxOut = 0; 38401e04c3fSmrg */ 38501e04c3fSmrg brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut)); 38601e04c3fSmrg brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); 38701e04c3fSmrg brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); 38801e04c3fSmrg brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) ); 38901e04c3fSmrg } 39001e04c3fSmrg brw_ENDIF(p); 39101e04c3fSmrg } 39201e04c3fSmrg brw_ENDIF(p); 39301e04c3fSmrg 39401e04c3fSmrg /* vtxPrev = vtx; 39501e04c3fSmrg * inlist_ptr++; 39601e04c3fSmrg */ 39701e04c3fSmrg brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx)); 39801e04c3fSmrg brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short))); 39901e04c3fSmrg 40001e04c3fSmrg /* while (--loopcount != 0) 40101e04c3fSmrg */ 40201e04c3fSmrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 40301e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 40401e04c3fSmrg } 40501e04c3fSmrg brw_WHILE(p); 40601e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 40701e04c3fSmrg 40801e04c3fSmrg /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1] 40901e04c3fSmrg * inlist = outlist 41001e04c3fSmrg * inlist_ptr = &inlist[0] 41101e04c3fSmrg * outlist_ptr = &outlist[0] 41201e04c3fSmrg */ 41301e04c3fSmrg brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2)); 41401e04c3fSmrg brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0)); 41501e04c3fSmrg brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0)); 41601e04c3fSmrg brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist)); 41701e04c3fSmrg brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist)); 41801e04c3fSmrg } 41901e04c3fSmrg brw_ENDIF(p); 42001e04c3fSmrg 42101e04c3fSmrg /* plane_ptr++; 42201e04c3fSmrg */ 42301e04c3fSmrg brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c)); 42401e04c3fSmrg 42501e04c3fSmrg /* nr_verts >= 3 42601e04c3fSmrg */ 42701e04c3fSmrg brw_CMP(p, 42801e04c3fSmrg vec1(brw_null_reg()), 42901e04c3fSmrg BRW_CONDITIONAL_GE, 43001e04c3fSmrg c->reg.nr_verts, 43101e04c3fSmrg brw_imm_ud(3)); 43201e04c3fSmrg brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL); 43301e04c3fSmrg 43401e04c3fSmrg /* && (planemask>>=1) != 0 43501e04c3fSmrg */ 43601e04c3fSmrg brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1)); 43701e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 43801e04c3fSmrg brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1)); 43901e04c3fSmrg brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float))); 44001e04c3fSmrg } 44101e04c3fSmrg brw_WHILE(p); 44201e04c3fSmrg brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 44301e04c3fSmrg} 44401e04c3fSmrg 44501e04c3fSmrg 44601e04c3fSmrg 44701e04c3fSmrgvoid brw_clip_tri_emit_polygon(struct brw_clip_compile *c) 44801e04c3fSmrg{ 44901e04c3fSmrg struct brw_codegen *p = &c->func; 45001e04c3fSmrg 45101e04c3fSmrg /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--) 45201e04c3fSmrg */ 45301e04c3fSmrg brw_ADD(p, 45401e04c3fSmrg c->reg.loopcount, 45501e04c3fSmrg c->reg.nr_verts, 45601e04c3fSmrg brw_imm_d(-2)); 45701e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G); 45801e04c3fSmrg 45901e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 46001e04c3fSmrg { 46101e04c3fSmrg struct brw_indirect v0 = brw_indirect(0, 0); 46201e04c3fSmrg struct brw_indirect vptr = brw_indirect(1, 0); 46301e04c3fSmrg 46401e04c3fSmrg brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist)); 46501e04c3fSmrg brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); 46601e04c3fSmrg 46701e04c3fSmrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 46801e04c3fSmrg ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT) 46901e04c3fSmrg | URB_WRITE_PRIM_START)); 47001e04c3fSmrg 47101e04c3fSmrg brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2)); 47201e04c3fSmrg brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); 47301e04c3fSmrg 47401e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 47501e04c3fSmrg { 47601e04c3fSmrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 47701e04c3fSmrg (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)); 47801e04c3fSmrg 47901e04c3fSmrg brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2)); 48001e04c3fSmrg brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); 48101e04c3fSmrg 48201e04c3fSmrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 48301e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 48401e04c3fSmrg } 48501e04c3fSmrg brw_WHILE(p); 48601e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 48701e04c3fSmrg 48801e04c3fSmrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_EOT_COMPLETE, 48901e04c3fSmrg ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT) 49001e04c3fSmrg | URB_WRITE_PRIM_END)); 49101e04c3fSmrg } 49201e04c3fSmrg brw_ENDIF(p); 49301e04c3fSmrg} 49401e04c3fSmrg 49501e04c3fSmrgstatic void do_clip_tri( struct brw_clip_compile *c ) 49601e04c3fSmrg{ 49701e04c3fSmrg brw_clip_init_planes(c); 49801e04c3fSmrg 49901e04c3fSmrg brw_clip_tri(c); 50001e04c3fSmrg} 50101e04c3fSmrg 50201e04c3fSmrg 50301e04c3fSmrgstatic void maybe_do_clip_tri( struct brw_clip_compile *c ) 50401e04c3fSmrg{ 50501e04c3fSmrg struct brw_codegen *p = &c->func; 50601e04c3fSmrg 50701e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0)); 50801e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 50901e04c3fSmrg { 51001e04c3fSmrg do_clip_tri(c); 51101e04c3fSmrg } 51201e04c3fSmrg brw_ENDIF(p); 51301e04c3fSmrg} 51401e04c3fSmrg 51501e04c3fSmrgstatic void brw_clip_test( struct brw_clip_compile *c ) 51601e04c3fSmrg{ 51701e04c3fSmrg struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 51801e04c3fSmrg struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 51901e04c3fSmrg struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 52001e04c3fSmrg struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 52101e04c3fSmrg 52201e04c3fSmrg struct brw_reg v0 = get_tmp(c); 52301e04c3fSmrg struct brw_reg v1 = get_tmp(c); 52401e04c3fSmrg struct brw_reg v2 = get_tmp(c); 52501e04c3fSmrg 52601e04c3fSmrg struct brw_indirect vt0 = brw_indirect(0, 0); 52701e04c3fSmrg struct brw_indirect vt1 = brw_indirect(1, 0); 52801e04c3fSmrg struct brw_indirect vt2 = brw_indirect(2, 0); 52901e04c3fSmrg 53001e04c3fSmrg struct brw_codegen *p = &c->func; 53101e04c3fSmrg struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ 53201e04c3fSmrg 53301e04c3fSmrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, 53401e04c3fSmrg VARYING_SLOT_POS); 53501e04c3fSmrg 53601e04c3fSmrg brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0])); 53701e04c3fSmrg brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1])); 53801e04c3fSmrg brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2])); 53901e04c3fSmrg brw_MOV(p, v0, deref_4f(vt0, hpos_offset)); 54001e04c3fSmrg brw_MOV(p, v1, deref_4f(vt1, hpos_offset)); 54101e04c3fSmrg brw_MOV(p, v2, deref_4f(vt2, hpos_offset)); 54201e04c3fSmrg brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f)); 54301e04c3fSmrg 54401e04c3fSmrg /* test nearz, xmin, ymin plane */ 54501e04c3fSmrg /* clip.xyz < -clip.w */ 54601e04c3fSmrg brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3))); 54701e04c3fSmrg brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3))); 54801e04c3fSmrg brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3))); 54901e04c3fSmrg 55001e04c3fSmrg /* All vertices are outside of a plane, rejected */ 55101e04c3fSmrg brw_AND(p, t, t1, t2); 55201e04c3fSmrg brw_AND(p, t, t, t3); 55301e04c3fSmrg brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1)); 55401e04c3fSmrg brw_OR(p, tmp0, tmp0, get_element(t, 2)); 55501e04c3fSmrg brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1)); 55601e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 55701e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 55801e04c3fSmrg { 55901e04c3fSmrg brw_clip_kill_thread(c); 56001e04c3fSmrg } 56101e04c3fSmrg brw_ENDIF(p); 56201e04c3fSmrg brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 56301e04c3fSmrg 56401e04c3fSmrg /* some vertices are inside a plane, some are outside,need to clip */ 56501e04c3fSmrg brw_XOR(p, t, t1, t2); 56601e04c3fSmrg brw_XOR(p, t1, t2, t3); 56701e04c3fSmrg brw_OR(p, t, t, t1); 56801e04c3fSmrg brw_AND(p, t, t, brw_imm_ud(0x1)); 56901e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 57001e04c3fSmrg get_element(t, 0), brw_imm_ud(0)); 57101e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5))); 57201e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 57301e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 57401e04c3fSmrg get_element(t, 1), brw_imm_ud(0)); 57501e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3))); 57601e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 57701e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 57801e04c3fSmrg get_element(t, 2), brw_imm_ud(0)); 57901e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1))); 58001e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 58101e04c3fSmrg 58201e04c3fSmrg /* test farz, xmax, ymax plane */ 58301e04c3fSmrg /* clip.xyz > clip.w */ 58401e04c3fSmrg brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3)); 58501e04c3fSmrg brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3)); 58601e04c3fSmrg brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3)); 58701e04c3fSmrg 58801e04c3fSmrg /* All vertices are outside of a plane, rejected */ 58901e04c3fSmrg brw_AND(p, t, t1, t2); 59001e04c3fSmrg brw_AND(p, t, t, t3); 59101e04c3fSmrg brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1)); 59201e04c3fSmrg brw_OR(p, tmp0, tmp0, get_element(t, 2)); 59301e04c3fSmrg brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1)); 59401e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 59501e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 59601e04c3fSmrg { 59701e04c3fSmrg brw_clip_kill_thread(c); 59801e04c3fSmrg } 59901e04c3fSmrg brw_ENDIF(p); 60001e04c3fSmrg brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 60101e04c3fSmrg 60201e04c3fSmrg /* some vertices are inside a plane, some are outside,need to clip */ 60301e04c3fSmrg brw_XOR(p, t, t1, t2); 60401e04c3fSmrg brw_XOR(p, t1, t2, t3); 60501e04c3fSmrg brw_OR(p, t, t, t1); 60601e04c3fSmrg brw_AND(p, t, t, brw_imm_ud(0x1)); 60701e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 60801e04c3fSmrg get_element(t, 0), brw_imm_ud(0)); 60901e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4))); 61001e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 61101e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 61201e04c3fSmrg get_element(t, 1), brw_imm_ud(0)); 61301e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2))); 61401e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 61501e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 61601e04c3fSmrg get_element(t, 2), brw_imm_ud(0)); 61701e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0))); 61801e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 61901e04c3fSmrg 62001e04c3fSmrg release_tmps(c); 62101e04c3fSmrg} 62201e04c3fSmrg 62301e04c3fSmrg 62401e04c3fSmrgvoid brw_emit_tri_clip( struct brw_clip_compile *c ) 62501e04c3fSmrg{ 62601e04c3fSmrg struct brw_codegen *p = &c->func; 62701e04c3fSmrg brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); 62801e04c3fSmrg brw_clip_tri_init_vertices(c); 62901e04c3fSmrg brw_clip_init_clipmask(c); 63001e04c3fSmrg brw_clip_init_ff_sync(c); 63101e04c3fSmrg 63201e04c3fSmrg /* if -ve rhw workaround bit is set, 63301e04c3fSmrg do cliptest */ 63401e04c3fSmrg if (p->devinfo->has_negative_rhw_bug) { 63501e04c3fSmrg brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2), 63601e04c3fSmrg brw_imm_ud(1<<20)); 63701e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 63801e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 63901e04c3fSmrg { 64001e04c3fSmrg brw_clip_test(c); 64101e04c3fSmrg } 64201e04c3fSmrg brw_ENDIF(p); 64301e04c3fSmrg } 64401e04c3fSmrg /* Can't push into do_clip_tri because with polygon (or quad) 64501e04c3fSmrg * flatshading, need to apply the flatshade here because we don't 64601e04c3fSmrg * respect the PV when converting to trifan for emit: 64701e04c3fSmrg */ 64801e04c3fSmrg if (c->key.contains_flat_varying) 64901e04c3fSmrg brw_clip_tri_flat_shade(c); 65001e04c3fSmrg 65101e04c3fSmrg if ((c->key.clip_mode == BRW_CLIP_MODE_NORMAL) || 65201e04c3fSmrg (c->key.clip_mode == BRW_CLIP_MODE_KERNEL_CLIP)) 65301e04c3fSmrg do_clip_tri(c); 65401e04c3fSmrg else 65501e04c3fSmrg maybe_do_clip_tri(c); 65601e04c3fSmrg 65701e04c3fSmrg brw_clip_tri_emit_polygon(c); 65801e04c3fSmrg 65901e04c3fSmrg /* Send an empty message to kill the thread: 66001e04c3fSmrg */ 66101e04c3fSmrg brw_clip_kill_thread(c); 66201e04c3fSmrg} 663