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 brw_clip_line_alloc_regs( struct brw_clip_compile *c ) 3901e04c3fSmrg{ 407ec681f3Smrg const struct intel_device_info *devinfo = c->func.devinfo; 4101e04c3fSmrg GLuint i = 0,j; 4201e04c3fSmrg 4301e04c3fSmrg /* Register usage is static, precompute here: 4401e04c3fSmrg */ 4501e04c3fSmrg c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++; 4601e04c3fSmrg 4701e04c3fSmrg if (c->key.nr_userclip) { 4801e04c3fSmrg c->reg.fixed_planes = brw_vec4_grf(i, 0); 4901e04c3fSmrg i += (6 + c->key.nr_userclip + 1) / 2; 5001e04c3fSmrg 5101e04c3fSmrg c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2; 5201e04c3fSmrg } 5301e04c3fSmrg else 5401e04c3fSmrg c->prog_data.curb_read_length = 0; 5501e04c3fSmrg 5601e04c3fSmrg 5701e04c3fSmrg /* Payload vertices plus space for more generated vertices: 5801e04c3fSmrg */ 5901e04c3fSmrg for (j = 0; j < 4; j++) { 6001e04c3fSmrg c->reg.vertex[j] = brw_vec4_grf(i, 0); 6101e04c3fSmrg i += c->nr_regs; 6201e04c3fSmrg } 6301e04c3fSmrg 6401e04c3fSmrg c->reg.t = brw_vec1_grf(i, 0); 6501e04c3fSmrg c->reg.t0 = brw_vec1_grf(i, 1); 6601e04c3fSmrg c->reg.t1 = brw_vec1_grf(i, 2); 6701e04c3fSmrg c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD); 6801e04c3fSmrg c->reg.plane_equation = brw_vec4_grf(i, 4); 6901e04c3fSmrg i++; 7001e04c3fSmrg 7101e04c3fSmrg c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */ 7201e04c3fSmrg c->reg.dp1 = brw_vec1_grf(i, 4); 7301e04c3fSmrg i++; 7401e04c3fSmrg 7501e04c3fSmrg if (!c->key.nr_userclip) { 7601e04c3fSmrg c->reg.fixed_planes = brw_vec8_grf(i, 0); 7701e04c3fSmrg i++; 7801e04c3fSmrg } 7901e04c3fSmrg 8001e04c3fSmrg c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); 8101e04c3fSmrg c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W); 8201e04c3fSmrg i++; 8301e04c3fSmrg 847ec681f3Smrg if (devinfo->ver == 5) { 8501e04c3fSmrg c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); 8601e04c3fSmrg i++; 8701e04c3fSmrg } 8801e04c3fSmrg 8901e04c3fSmrg c->first_tmp = i; 9001e04c3fSmrg c->last_tmp = i; 9101e04c3fSmrg 9201e04c3fSmrg c->prog_data.urb_read_length = c->nr_regs; /* ? */ 9301e04c3fSmrg c->prog_data.total_grf = i; 9401e04c3fSmrg} 9501e04c3fSmrg 9601e04c3fSmrg 9701e04c3fSmrg/* Line clipping, more or less following the following algorithm: 9801e04c3fSmrg * 9901e04c3fSmrg * for (p=0;p<MAX_PLANES;p++) { 10001e04c3fSmrg * if (clipmask & (1 << p)) { 10101e04c3fSmrg * GLfloat dp0 = DOTPROD( vtx0, plane[p] ); 10201e04c3fSmrg * GLfloat dp1 = DOTPROD( vtx1, plane[p] ); 10301e04c3fSmrg * 10401e04c3fSmrg * if (dp1 < 0.0f) { 10501e04c3fSmrg * GLfloat t = dp1 / (dp1 - dp0); 10601e04c3fSmrg * if (t > t1) t1 = t; 10701e04c3fSmrg * } else { 10801e04c3fSmrg * GLfloat t = dp0 / (dp0 - dp1); 10901e04c3fSmrg * if (t > t0) t0 = t; 11001e04c3fSmrg * } 11101e04c3fSmrg * 11201e04c3fSmrg * if (t0 + t1 >= 1.0) 11301e04c3fSmrg * return; 11401e04c3fSmrg * } 11501e04c3fSmrg * } 11601e04c3fSmrg * 11701e04c3fSmrg * interp( ctx, newvtx0, vtx0, vtx1, t0 ); 11801e04c3fSmrg * interp( ctx, newvtx1, vtx1, vtx0, t1 ); 11901e04c3fSmrg * 12001e04c3fSmrg */ 12101e04c3fSmrgstatic void clip_and_emit_line( struct brw_clip_compile *c ) 12201e04c3fSmrg{ 12301e04c3fSmrg struct brw_codegen *p = &c->func; 12401e04c3fSmrg struct brw_indirect vtx0 = brw_indirect(0, 0); 12501e04c3fSmrg struct brw_indirect vtx1 = brw_indirect(1, 0); 12601e04c3fSmrg struct brw_indirect newvtx0 = brw_indirect(2, 0); 12701e04c3fSmrg struct brw_indirect newvtx1 = brw_indirect(3, 0); 12801e04c3fSmrg struct brw_indirect plane_ptr = brw_indirect(4, 0); 12901e04c3fSmrg struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD); 13001e04c3fSmrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 13101e04c3fSmrg GLint clipdist0_offset = c->key.nr_userclip 13201e04c3fSmrg ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0) 13301e04c3fSmrg : 0; 13401e04c3fSmrg 13501e04c3fSmrg brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0])); 13601e04c3fSmrg brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1])); 13701e04c3fSmrg brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2])); 13801e04c3fSmrg brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3])); 13901e04c3fSmrg brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c)); 14001e04c3fSmrg 14101e04c3fSmrg /* Note: init t0, t1 together: 14201e04c3fSmrg */ 14301e04c3fSmrg brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0)); 14401e04c3fSmrg 14501e04c3fSmrg brw_clip_init_planes(c); 14601e04c3fSmrg brw_clip_init_clipmask(c); 14701e04c3fSmrg 14801e04c3fSmrg /* -ve rhw workaround */ 14901e04c3fSmrg if (p->devinfo->has_negative_rhw_bug) { 15001e04c3fSmrg brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2), 15101e04c3fSmrg brw_imm_ud(1<<20)); 15201e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 15301e04c3fSmrg brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f)); 15401e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 15501e04c3fSmrg } 15601e04c3fSmrg 15701e04c3fSmrg /* Set the initial vertex source mask: The first 6 planes are the bounds 15801e04c3fSmrg * of the view volume; the next 8 planes are the user clipping planes. 15901e04c3fSmrg */ 16001e04c3fSmrg brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0)); 16101e04c3fSmrg 16201e04c3fSmrg /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0]. 16301e04c3fSmrg * We'll increment 6 times before we start hitting actual user clipping. */ 16401e04c3fSmrg brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float))); 16501e04c3fSmrg 16601e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 16701e04c3fSmrg { 16801e04c3fSmrg /* if (planemask & 1) 16901e04c3fSmrg */ 17001e04c3fSmrg brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1)); 17101e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 17201e04c3fSmrg 17301e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 17401e04c3fSmrg { 17501e04c3fSmrg brw_AND(p, v1_null_ud, c->reg.vertex_src_mask, brw_imm_ud(1)); 17601e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 17701e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 17801e04c3fSmrg { 17901e04c3fSmrg /* user clip distance: just fetch the correct float from each vertex */ 18001e04c3fSmrg struct brw_indirect temp_ptr = brw_indirect(7, 0); 18101e04c3fSmrg brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx0), c->reg.clipdistance_offset); 18201e04c3fSmrg brw_MOV(p, c->reg.dp0, deref_1f(temp_ptr, 0)); 18301e04c3fSmrg brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx1), c->reg.clipdistance_offset); 18401e04c3fSmrg brw_MOV(p, c->reg.dp1, deref_1f(temp_ptr, 0)); 18501e04c3fSmrg } 18601e04c3fSmrg brw_ELSE(p); 18701e04c3fSmrg { 18801e04c3fSmrg /* fixed plane: fetch the hpos, dp4 against the plane. */ 18901e04c3fSmrg if (c->key.nr_userclip) 19001e04c3fSmrg brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0)); 19101e04c3fSmrg else 19201e04c3fSmrg brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0)); 19301e04c3fSmrg 19401e04c3fSmrg brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, hpos_offset), c->reg.plane_equation); 19501e04c3fSmrg brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, hpos_offset), c->reg.plane_equation); 19601e04c3fSmrg } 19701e04c3fSmrg brw_ENDIF(p); 19801e04c3fSmrg 19901e04c3fSmrg brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, vec1(c->reg.dp1), brw_imm_f(0.0f)); 20001e04c3fSmrg 20101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 20201e04c3fSmrg { 20301e04c3fSmrg /* 20401e04c3fSmrg * Both can be negative on GM965/G965 due to RHW workaround 20501e04c3fSmrg * if so, this object should be rejected. 20601e04c3fSmrg */ 20701e04c3fSmrg if (p->devinfo->has_negative_rhw_bug) { 20801e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0)); 20901e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 21001e04c3fSmrg { 21101e04c3fSmrg brw_clip_kill_thread(c); 21201e04c3fSmrg } 21301e04c3fSmrg brw_ENDIF(p); 21401e04c3fSmrg } 21501e04c3fSmrg 21601e04c3fSmrg brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0)); 21701e04c3fSmrg brw_math_invert(p, c->reg.t, c->reg.t); 21801e04c3fSmrg brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1); 21901e04c3fSmrg 22001e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 ); 22101e04c3fSmrg brw_MOV(p, c->reg.t1, c->reg.t); 22201e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, 22301e04c3fSmrg BRW_PREDICATE_NORMAL); 22401e04c3fSmrg } 22501e04c3fSmrg brw_ELSE(p); 22601e04c3fSmrg { 22701e04c3fSmrg /* Coming back in. We know that both cannot be negative 22801e04c3fSmrg * because the line would have been culled in that case. 22901e04c3fSmrg */ 23001e04c3fSmrg 23101e04c3fSmrg /* If both are positive, do nothing */ 23201e04c3fSmrg /* Only on GM965/G965 */ 23301e04c3fSmrg if (p->devinfo->has_negative_rhw_bug) { 23401e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0)); 23501e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 23601e04c3fSmrg } 23701e04c3fSmrg 23801e04c3fSmrg { 23901e04c3fSmrg brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1)); 24001e04c3fSmrg brw_math_invert(p, c->reg.t, c->reg.t); 24101e04c3fSmrg brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0); 24201e04c3fSmrg 24301e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 ); 24401e04c3fSmrg brw_MOV(p, c->reg.t0, c->reg.t); 24501e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, 24601e04c3fSmrg BRW_PREDICATE_NORMAL); 24701e04c3fSmrg } 24801e04c3fSmrg 24901e04c3fSmrg if (p->devinfo->has_negative_rhw_bug) { 25001e04c3fSmrg brw_ENDIF(p); 25101e04c3fSmrg } 25201e04c3fSmrg } 25301e04c3fSmrg brw_ENDIF(p); 25401e04c3fSmrg } 25501e04c3fSmrg brw_ENDIF(p); 25601e04c3fSmrg 25701e04c3fSmrg /* plane_ptr++; 25801e04c3fSmrg */ 25901e04c3fSmrg brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c)); 26001e04c3fSmrg 26101e04c3fSmrg /* while (planemask>>=1) != 0 26201e04c3fSmrg */ 26301e04c3fSmrg brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1)); 26401e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 26501e04c3fSmrg brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1)); 26601e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 26701e04c3fSmrg brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float))); 26801e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 26901e04c3fSmrg } 27001e04c3fSmrg brw_WHILE(p); 27101e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 27201e04c3fSmrg 27301e04c3fSmrg brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1); 27401e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0)); 27501e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 27601e04c3fSmrg { 27701e04c3fSmrg brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, false); 27801e04c3fSmrg brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, false); 27901e04c3fSmrg 28001e04c3fSmrg brw_clip_emit_vue(c, newvtx0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 28101e04c3fSmrg (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) 28201e04c3fSmrg | URB_WRITE_PRIM_START); 28301e04c3fSmrg brw_clip_emit_vue(c, newvtx1, BRW_URB_WRITE_EOT_COMPLETE, 28401e04c3fSmrg (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) 28501e04c3fSmrg | URB_WRITE_PRIM_END); 28601e04c3fSmrg } 28701e04c3fSmrg brw_ENDIF(p); 28801e04c3fSmrg brw_clip_kill_thread(c); 28901e04c3fSmrg} 29001e04c3fSmrg 29101e04c3fSmrg 29201e04c3fSmrg 29301e04c3fSmrgvoid brw_emit_line_clip( struct brw_clip_compile *c ) 29401e04c3fSmrg{ 29501e04c3fSmrg brw_clip_line_alloc_regs(c); 29601e04c3fSmrg brw_clip_init_ff_sync(c); 29701e04c3fSmrg 29801e04c3fSmrg if (c->key.contains_flat_varying) { 29901e04c3fSmrg if (c->key.pv_first) 30001e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 1, 0); 30101e04c3fSmrg else 30201e04c3fSmrg brw_clip_copy_flatshaded_attributes(c, 0, 1); 30301e04c3fSmrg } 30401e04c3fSmrg 30501e04c3fSmrg clip_and_emit_line(c); 30601e04c3fSmrg} 307