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 3801e04c3fSmrg 3901e04c3fSmrg/* This is performed against the original triangles, so no indirection 4001e04c3fSmrg * required: 4101e04c3fSmrgBZZZT! 4201e04c3fSmrg */ 4301e04c3fSmrgstatic void compute_tri_direction( struct brw_clip_compile *c ) 4401e04c3fSmrg{ 4501e04c3fSmrg struct brw_codegen *p = &c->func; 4601e04c3fSmrg struct brw_reg e = c->reg.tmp0; 4701e04c3fSmrg struct brw_reg f = c->reg.tmp1; 4801e04c3fSmrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 4901e04c3fSmrg struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset); 5001e04c3fSmrg struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset); 5101e04c3fSmrg struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset); 5201e04c3fSmrg 5301e04c3fSmrg 5401e04c3fSmrg struct brw_reg v0n = get_tmp(c); 5501e04c3fSmrg struct brw_reg v1n = get_tmp(c); 5601e04c3fSmrg struct brw_reg v2n = get_tmp(c); 5701e04c3fSmrg 5801e04c3fSmrg /* Convert to NDC. 5901e04c3fSmrg * NOTE: We can't modify the original vertex coordinates, 6001e04c3fSmrg * as it may impact further operations. 6101e04c3fSmrg * So, we have to keep normalized coordinates in temp registers. 6201e04c3fSmrg * 6301e04c3fSmrg * TBD-KC 6401e04c3fSmrg * Try to optimize unnecessary MOV's. 6501e04c3fSmrg */ 6601e04c3fSmrg brw_MOV(p, v0n, v0); 6701e04c3fSmrg brw_MOV(p, v1n, v1); 6801e04c3fSmrg brw_MOV(p, v2n, v2); 6901e04c3fSmrg 7001e04c3fSmrg brw_clip_project_position(c, v0n); 7101e04c3fSmrg brw_clip_project_position(c, v1n); 7201e04c3fSmrg brw_clip_project_position(c, v2n); 7301e04c3fSmrg 7401e04c3fSmrg /* Calculate the vectors of two edges of the triangle: 7501e04c3fSmrg */ 7601e04c3fSmrg brw_ADD(p, e, v0n, negate(v2n)); 7701e04c3fSmrg brw_ADD(p, f, v1n, negate(v2n)); 7801e04c3fSmrg 7901e04c3fSmrg /* Take their crossproduct: 8001e04c3fSmrg */ 8101e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_16); 8201e04c3fSmrg brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW), 8301e04c3fSmrg brw_swizzle(f, BRW_SWIZZLE_ZXYW)); 8401e04c3fSmrg brw_MAC(p, vec4(e), negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)), 8501e04c3fSmrg brw_swizzle(f, BRW_SWIZZLE_YZXW)); 8601e04c3fSmrg brw_set_default_access_mode(p, BRW_ALIGN_1); 8701e04c3fSmrg 8801e04c3fSmrg brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e)); 8901e04c3fSmrg} 9001e04c3fSmrg 9101e04c3fSmrg 9201e04c3fSmrgstatic void cull_direction( struct brw_clip_compile *c ) 9301e04c3fSmrg{ 9401e04c3fSmrg struct brw_codegen *p = &c->func; 9501e04c3fSmrg GLuint conditional; 9601e04c3fSmrg 9701e04c3fSmrg assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL && 9801e04c3fSmrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)); 9901e04c3fSmrg 10001e04c3fSmrg if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL) 10101e04c3fSmrg conditional = BRW_CONDITIONAL_GE; 10201e04c3fSmrg else 10301e04c3fSmrg conditional = BRW_CONDITIONAL_L; 10401e04c3fSmrg 10501e04c3fSmrg brw_CMP(p, 10601e04c3fSmrg vec1(brw_null_reg()), 10701e04c3fSmrg conditional, 10801e04c3fSmrg get_element(c->reg.dir, 2), 10901e04c3fSmrg brw_imm_f(0)); 11001e04c3fSmrg 11101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 11201e04c3fSmrg { 11301e04c3fSmrg brw_clip_kill_thread(c); 11401e04c3fSmrg } 11501e04c3fSmrg brw_ENDIF(p); 11601e04c3fSmrg} 11701e04c3fSmrg 11801e04c3fSmrg 11901e04c3fSmrg 12001e04c3fSmrgstatic void copy_bfc( struct brw_clip_compile *c ) 12101e04c3fSmrg{ 12201e04c3fSmrg struct brw_codegen *p = &c->func; 12301e04c3fSmrg GLuint conditional; 12401e04c3fSmrg 12501e04c3fSmrg /* Do we have any colors to copy? 12601e04c3fSmrg */ 12701e04c3fSmrg if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) && 12801e04c3fSmrg brw_clip_have_varying(c, VARYING_SLOT_BFC0)) && 12901e04c3fSmrg !(brw_clip_have_varying(c, VARYING_SLOT_COL1) && 13001e04c3fSmrg brw_clip_have_varying(c, VARYING_SLOT_BFC1))) 13101e04c3fSmrg return; 13201e04c3fSmrg 13301e04c3fSmrg /* In some weird degenerate cases we can end up testing the 13401e04c3fSmrg * direction twice, once for culling and once for bfc copying. Oh 13501e04c3fSmrg * well, that's what you get for setting weird GL state. 13601e04c3fSmrg */ 13701e04c3fSmrg if (c->key.copy_bfc_ccw) 13801e04c3fSmrg conditional = BRW_CONDITIONAL_GE; 13901e04c3fSmrg else 14001e04c3fSmrg conditional = BRW_CONDITIONAL_L; 14101e04c3fSmrg 14201e04c3fSmrg brw_CMP(p, 14301e04c3fSmrg vec1(brw_null_reg()), 14401e04c3fSmrg conditional, 14501e04c3fSmrg get_element(c->reg.dir, 2), 14601e04c3fSmrg brw_imm_f(0)); 14701e04c3fSmrg 14801e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 14901e04c3fSmrg { 15001e04c3fSmrg GLuint i; 15101e04c3fSmrg 15201e04c3fSmrg for (i = 0; i < 3; i++) { 15301e04c3fSmrg if (brw_clip_have_varying(c, VARYING_SLOT_COL0) && 15401e04c3fSmrg brw_clip_have_varying(c, VARYING_SLOT_BFC0)) 15501e04c3fSmrg brw_MOV(p, 15601e04c3fSmrg byte_offset(c->reg.vertex[i], 15701e04c3fSmrg brw_varying_to_offset(&c->vue_map, 15801e04c3fSmrg VARYING_SLOT_COL0)), 15901e04c3fSmrg byte_offset(c->reg.vertex[i], 16001e04c3fSmrg brw_varying_to_offset(&c->vue_map, 16101e04c3fSmrg VARYING_SLOT_BFC0))); 16201e04c3fSmrg 16301e04c3fSmrg if (brw_clip_have_varying(c, VARYING_SLOT_COL1) && 16401e04c3fSmrg brw_clip_have_varying(c, VARYING_SLOT_BFC1)) 16501e04c3fSmrg brw_MOV(p, 16601e04c3fSmrg byte_offset(c->reg.vertex[i], 16701e04c3fSmrg brw_varying_to_offset(&c->vue_map, 16801e04c3fSmrg VARYING_SLOT_COL1)), 16901e04c3fSmrg byte_offset(c->reg.vertex[i], 17001e04c3fSmrg brw_varying_to_offset(&c->vue_map, 17101e04c3fSmrg VARYING_SLOT_BFC1))); 17201e04c3fSmrg } 17301e04c3fSmrg } 17401e04c3fSmrg brw_ENDIF(p); 17501e04c3fSmrg} 17601e04c3fSmrg 17701e04c3fSmrg 17801e04c3fSmrg 17901e04c3fSmrg 18001e04c3fSmrg/* 18101e04c3fSmrg GLfloat iz = 1.0 / dir.z; 18201e04c3fSmrg GLfloat ac = dir.x * iz; 18301e04c3fSmrg GLfloat bc = dir.y * iz; 18401e04c3fSmrg offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; 18501e04c3fSmrg offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor; 18601e04c3fSmrg if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) { 18701e04c3fSmrg if (ctx->Polygon.OffsetClamp < 0) 18801e04c3fSmrg offset = MAX2( offset, ctx->Polygon.OffsetClamp ); 18901e04c3fSmrg else 19001e04c3fSmrg offset = MIN2( offset, ctx->Polygon.OffsetClamp ); 19101e04c3fSmrg } 19201e04c3fSmrg offset *= MRD; 19301e04c3fSmrg*/ 19401e04c3fSmrgstatic void compute_offset( struct brw_clip_compile *c ) 19501e04c3fSmrg{ 19601e04c3fSmrg struct brw_codegen *p = &c->func; 19701e04c3fSmrg struct brw_reg off = c->reg.offset; 19801e04c3fSmrg struct brw_reg dir = c->reg.dir; 19901e04c3fSmrg 20001e04c3fSmrg brw_math_invert(p, get_element(off, 2), get_element(dir, 2)); 20101e04c3fSmrg brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2)); 20201e04c3fSmrg 20301e04c3fSmrg brw_CMP(p, 20401e04c3fSmrg vec1(brw_null_reg()), 20501e04c3fSmrg BRW_CONDITIONAL_GE, 20601e04c3fSmrg brw_abs(get_element(off, 0)), 20701e04c3fSmrg brw_abs(get_element(off, 1))); 20801e04c3fSmrg 20901e04c3fSmrg brw_SEL(p, vec1(off), 21001e04c3fSmrg brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1))); 21101e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 21201e04c3fSmrg 21301e04c3fSmrg brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor)); 21401e04c3fSmrg brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units)); 21501e04c3fSmrg if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) { 21601e04c3fSmrg brw_CMP(p, 21701e04c3fSmrg vec1(brw_null_reg()), 21801e04c3fSmrg c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L, 21901e04c3fSmrg vec1(off), 22001e04c3fSmrg brw_imm_f(c->key.offset_clamp)); 22101e04c3fSmrg brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp)); 22201e04c3fSmrg } 22301e04c3fSmrg} 22401e04c3fSmrg 22501e04c3fSmrg 22601e04c3fSmrgstatic void merge_edgeflags( struct brw_clip_compile *c ) 22701e04c3fSmrg{ 22801e04c3fSmrg struct brw_codegen *p = &c->func; 22901e04c3fSmrg struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0); 23001e04c3fSmrg 23101e04c3fSmrg brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 23201e04c3fSmrg brw_CMP(p, 23301e04c3fSmrg vec1(brw_null_reg()), 23401e04c3fSmrg BRW_CONDITIONAL_EQ, 23501e04c3fSmrg tmp0, 23601e04c3fSmrg brw_imm_ud(_3DPRIM_POLYGON)); 23701e04c3fSmrg 23801e04c3fSmrg /* Get away with using reg.vertex because we know that this is not 23901e04c3fSmrg * a _3DPRIM_TRISTRIP_REVERSE: 24001e04c3fSmrg */ 24101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 24201e04c3fSmrg { 24301e04c3fSmrg brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8)); 24401e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ); 24501e04c3fSmrg brw_MOV(p, byte_offset(c->reg.vertex[0], 24601e04c3fSmrg brw_varying_to_offset(&c->vue_map, 24701e04c3fSmrg VARYING_SLOT_EDGE)), 24801e04c3fSmrg brw_imm_f(0)); 24901e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 25001e04c3fSmrg 25101e04c3fSmrg brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9)); 25201e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ); 25301e04c3fSmrg brw_MOV(p, byte_offset(c->reg.vertex[2], 25401e04c3fSmrg brw_varying_to_offset(&c->vue_map, 25501e04c3fSmrg VARYING_SLOT_EDGE)), 25601e04c3fSmrg brw_imm_f(0)); 25701e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 25801e04c3fSmrg } 25901e04c3fSmrg brw_ENDIF(p); 26001e04c3fSmrg} 26101e04c3fSmrg 26201e04c3fSmrg 26301e04c3fSmrg 26401e04c3fSmrgstatic void apply_one_offset( struct brw_clip_compile *c, 26501e04c3fSmrg struct brw_indirect vert ) 26601e04c3fSmrg{ 26701e04c3fSmrg struct brw_codegen *p = &c->func; 26801e04c3fSmrg GLuint ndc_offset = brw_varying_to_offset(&c->vue_map, 26901e04c3fSmrg BRW_VARYING_SLOT_NDC); 27001e04c3fSmrg struct brw_reg z = deref_1f(vert, ndc_offset + 27101e04c3fSmrg 2 * type_sz(BRW_REGISTER_TYPE_F)); 27201e04c3fSmrg 27301e04c3fSmrg brw_ADD(p, z, z, vec1(c->reg.offset)); 27401e04c3fSmrg} 27501e04c3fSmrg 27601e04c3fSmrg 27701e04c3fSmrg 27801e04c3fSmrg/*********************************************************************** 27901e04c3fSmrg * Output clipped polygon as an unfilled primitive: 28001e04c3fSmrg */ 28101e04c3fSmrgstatic void emit_lines(struct brw_clip_compile *c, 28201e04c3fSmrg bool do_offset) 28301e04c3fSmrg{ 28401e04c3fSmrg struct brw_codegen *p = &c->func; 28501e04c3fSmrg struct brw_indirect v0 = brw_indirect(0, 0); 28601e04c3fSmrg struct brw_indirect v1 = brw_indirect(1, 0); 28701e04c3fSmrg struct brw_indirect v0ptr = brw_indirect(2, 0); 28801e04c3fSmrg struct brw_indirect v1ptr = brw_indirect(3, 0); 28901e04c3fSmrg 29001e04c3fSmrg /* Need a separate loop for offset: 29101e04c3fSmrg */ 29201e04c3fSmrg if (do_offset) { 29301e04c3fSmrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 29401e04c3fSmrg brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); 29501e04c3fSmrg 29601e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 29701e04c3fSmrg { 29801e04c3fSmrg brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); 29901e04c3fSmrg brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); 30001e04c3fSmrg 30101e04c3fSmrg apply_one_offset(c, v0); 30201e04c3fSmrg 30301e04c3fSmrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 30401e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G); 30501e04c3fSmrg } 30601e04c3fSmrg brw_WHILE(p); 30701e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 30801e04c3fSmrg } 30901e04c3fSmrg 31001e04c3fSmrg /* v1ptr = &inlist[nr_verts] 31101e04c3fSmrg * *v1ptr = v0 31201e04c3fSmrg */ 31301e04c3fSmrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 31401e04c3fSmrg brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); 31501e04c3fSmrg brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW)); 31601e04c3fSmrg brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW)); 31701e04c3fSmrg brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0)); 31801e04c3fSmrg 31901e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 32001e04c3fSmrg { 32101e04c3fSmrg brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); 32201e04c3fSmrg brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2)); 32301e04c3fSmrg brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); 32401e04c3fSmrg 32501e04c3fSmrg /* draw edge if edgeflag != 0 */ 32601e04c3fSmrg brw_CMP(p, 32701e04c3fSmrg vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 32801e04c3fSmrg deref_1f(v0, brw_varying_to_offset(&c->vue_map, 32901e04c3fSmrg VARYING_SLOT_EDGE)), 33001e04c3fSmrg brw_imm_f(0)); 33101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 33201e04c3fSmrg { 33301e04c3fSmrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 33401e04c3fSmrg (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) 33501e04c3fSmrg | URB_WRITE_PRIM_START); 33601e04c3fSmrg brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE, 33701e04c3fSmrg (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) 33801e04c3fSmrg | URB_WRITE_PRIM_END); 33901e04c3fSmrg } 34001e04c3fSmrg brw_ENDIF(p); 34101e04c3fSmrg 34201e04c3fSmrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 34301e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 34401e04c3fSmrg } 34501e04c3fSmrg brw_WHILE(p); 34601e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 34701e04c3fSmrg} 34801e04c3fSmrg 34901e04c3fSmrg 35001e04c3fSmrg 35101e04c3fSmrgstatic void emit_points(struct brw_clip_compile *c, 35201e04c3fSmrg bool do_offset ) 35301e04c3fSmrg{ 35401e04c3fSmrg struct brw_codegen *p = &c->func; 35501e04c3fSmrg 35601e04c3fSmrg struct brw_indirect v0 = brw_indirect(0, 0); 35701e04c3fSmrg struct brw_indirect v0ptr = brw_indirect(2, 0); 35801e04c3fSmrg 35901e04c3fSmrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 36001e04c3fSmrg brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); 36101e04c3fSmrg 36201e04c3fSmrg brw_DO(p, BRW_EXECUTE_1); 36301e04c3fSmrg { 36401e04c3fSmrg brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); 36501e04c3fSmrg brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); 36601e04c3fSmrg 36701e04c3fSmrg /* draw if edgeflag != 0 36801e04c3fSmrg */ 36901e04c3fSmrg brw_CMP(p, 37001e04c3fSmrg vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 37101e04c3fSmrg deref_1f(v0, brw_varying_to_offset(&c->vue_map, 37201e04c3fSmrg VARYING_SLOT_EDGE)), 37301e04c3fSmrg brw_imm_f(0)); 37401e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 37501e04c3fSmrg { 37601e04c3fSmrg if (do_offset) 37701e04c3fSmrg apply_one_offset(c, v0); 37801e04c3fSmrg 37901e04c3fSmrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 38001e04c3fSmrg (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT) 38101e04c3fSmrg | URB_WRITE_PRIM_START | URB_WRITE_PRIM_END); 38201e04c3fSmrg } 38301e04c3fSmrg brw_ENDIF(p); 38401e04c3fSmrg 38501e04c3fSmrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 38601e04c3fSmrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 38701e04c3fSmrg } 38801e04c3fSmrg brw_WHILE(p); 38901e04c3fSmrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 39001e04c3fSmrg} 39101e04c3fSmrg 39201e04c3fSmrg 39301e04c3fSmrg 39401e04c3fSmrg 39501e04c3fSmrg 39601e04c3fSmrg 39701e04c3fSmrg 39801e04c3fSmrgstatic void emit_primitives( struct brw_clip_compile *c, 39901e04c3fSmrg GLuint mode, 40001e04c3fSmrg bool do_offset ) 40101e04c3fSmrg{ 40201e04c3fSmrg switch (mode) { 40301e04c3fSmrg case BRW_CLIP_FILL_MODE_FILL: 40401e04c3fSmrg brw_clip_tri_emit_polygon(c); 40501e04c3fSmrg break; 40601e04c3fSmrg 40701e04c3fSmrg case BRW_CLIP_FILL_MODE_LINE: 40801e04c3fSmrg emit_lines(c, do_offset); 40901e04c3fSmrg break; 41001e04c3fSmrg 41101e04c3fSmrg case BRW_CLIP_FILL_MODE_POINT: 41201e04c3fSmrg emit_points(c, do_offset); 41301e04c3fSmrg break; 41401e04c3fSmrg 41501e04c3fSmrg case BRW_CLIP_FILL_MODE_CULL: 41601e04c3fSmrg unreachable("not reached"); 41701e04c3fSmrg } 41801e04c3fSmrg} 41901e04c3fSmrg 42001e04c3fSmrg 42101e04c3fSmrg 42201e04c3fSmrgstatic void emit_unfilled_primitives( struct brw_clip_compile *c ) 42301e04c3fSmrg{ 42401e04c3fSmrg struct brw_codegen *p = &c->func; 42501e04c3fSmrg 42601e04c3fSmrg /* Direction culling has already been done. 42701e04c3fSmrg */ 42801e04c3fSmrg if (c->key.fill_ccw != c->key.fill_cw && 42901e04c3fSmrg c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL && 43001e04c3fSmrg c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) 43101e04c3fSmrg { 43201e04c3fSmrg brw_CMP(p, 43301e04c3fSmrg vec1(brw_null_reg()), 43401e04c3fSmrg BRW_CONDITIONAL_GE, 43501e04c3fSmrg get_element(c->reg.dir, 2), 43601e04c3fSmrg brw_imm_f(0)); 43701e04c3fSmrg 43801e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 43901e04c3fSmrg { 44001e04c3fSmrg emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw); 44101e04c3fSmrg } 44201e04c3fSmrg brw_ELSE(p); 44301e04c3fSmrg { 44401e04c3fSmrg emit_primitives(c, c->key.fill_cw, c->key.offset_cw); 44501e04c3fSmrg } 44601e04c3fSmrg brw_ENDIF(p); 44701e04c3fSmrg } 44801e04c3fSmrg else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) { 44901e04c3fSmrg emit_primitives(c, c->key.fill_cw, c->key.offset_cw); 45001e04c3fSmrg } 45101e04c3fSmrg else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) { 45201e04c3fSmrg emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw); 45301e04c3fSmrg } 45401e04c3fSmrg} 45501e04c3fSmrg 45601e04c3fSmrg 45701e04c3fSmrg 45801e04c3fSmrg 45901e04c3fSmrgstatic void check_nr_verts( struct brw_clip_compile *c ) 46001e04c3fSmrg{ 46101e04c3fSmrg struct brw_codegen *p = &c->func; 46201e04c3fSmrg 46301e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3)); 46401e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 46501e04c3fSmrg { 46601e04c3fSmrg brw_clip_kill_thread(c); 46701e04c3fSmrg } 46801e04c3fSmrg brw_ENDIF(p); 46901e04c3fSmrg} 47001e04c3fSmrg 47101e04c3fSmrg 47201e04c3fSmrgvoid brw_emit_unfilled_clip( struct brw_clip_compile *c ) 47301e04c3fSmrg{ 47401e04c3fSmrg struct brw_codegen *p = &c->func; 47501e04c3fSmrg 47601e04c3fSmrg c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) || 47701e04c3fSmrg (c->key.fill_ccw != c->key.fill_cw) || 47801e04c3fSmrg c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL || 47901e04c3fSmrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL || 48001e04c3fSmrg c->key.copy_bfc_cw || 48101e04c3fSmrg c->key.copy_bfc_ccw); 48201e04c3fSmrg 48301e04c3fSmrg brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); 48401e04c3fSmrg brw_clip_tri_init_vertices(c); 48501e04c3fSmrg brw_clip_init_ff_sync(c); 48601e04c3fSmrg 48701e04c3fSmrg assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE)); 48801e04c3fSmrg 48901e04c3fSmrg if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL && 49001e04c3fSmrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) { 49101e04c3fSmrg brw_clip_kill_thread(c); 49201e04c3fSmrg return; 49301e04c3fSmrg } 49401e04c3fSmrg 49501e04c3fSmrg merge_edgeflags(c); 49601e04c3fSmrg 49701e04c3fSmrg /* Need to use the inlist indirection here: 49801e04c3fSmrg */ 49901e04c3fSmrg if (c->need_direction) 50001e04c3fSmrg compute_tri_direction(c); 50101e04c3fSmrg 50201e04c3fSmrg if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL || 50301e04c3fSmrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) 50401e04c3fSmrg cull_direction(c); 50501e04c3fSmrg 50601e04c3fSmrg if (c->key.offset_ccw || 50701e04c3fSmrg c->key.offset_cw) 50801e04c3fSmrg compute_offset(c); 50901e04c3fSmrg 51001e04c3fSmrg if (c->key.copy_bfc_ccw || 51101e04c3fSmrg c->key.copy_bfc_cw) 51201e04c3fSmrg copy_bfc(c); 51301e04c3fSmrg 51401e04c3fSmrg /* Need to do this whether we clip or not: 51501e04c3fSmrg */ 51601e04c3fSmrg if (c->key.contains_flat_varying) 51701e04c3fSmrg brw_clip_tri_flat_shade(c); 51801e04c3fSmrg 51901e04c3fSmrg brw_clip_init_clipmask(c); 52001e04c3fSmrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0)); 52101e04c3fSmrg brw_IF(p, BRW_EXECUTE_1); 52201e04c3fSmrg { 52301e04c3fSmrg brw_clip_init_planes(c); 52401e04c3fSmrg brw_clip_tri(c); 52501e04c3fSmrg check_nr_verts(c); 52601e04c3fSmrg } 52701e04c3fSmrg brw_ENDIF(p); 52801e04c3fSmrg 52901e04c3fSmrg emit_unfilled_primitives(c); 53001e04c3fSmrg brw_clip_kill_thread(c); 53101e04c3fSmrg} 532