1b8e80941Smrg/* 2b8e80941Smrg Copyright (C) Intel Corp. 2006. All Rights Reserved. 3b8e80941Smrg Intel funded Tungsten Graphics to 4b8e80941Smrg develop this 3D driver. 5b8e80941Smrg 6b8e80941Smrg Permission is hereby granted, free of charge, to any person obtaining 7b8e80941Smrg a copy of this software and associated documentation files (the 8b8e80941Smrg "Software"), to deal in the Software without restriction, including 9b8e80941Smrg without limitation the rights to use, copy, modify, merge, publish, 10b8e80941Smrg distribute, sublicense, and/or sell copies of the Software, and to 11b8e80941Smrg permit persons to whom the Software is furnished to do so, subject to 12b8e80941Smrg the following conditions: 13b8e80941Smrg 14b8e80941Smrg The above copyright notice and this permission notice (including the 15b8e80941Smrg next paragraph) shall be included in all copies or substantial 16b8e80941Smrg portions of the Software. 17b8e80941Smrg 18b8e80941Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19b8e80941Smrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20b8e80941Smrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21b8e80941Smrg IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22b8e80941Smrg LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23b8e80941Smrg OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24b8e80941Smrg WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b8e80941Smrg 26b8e80941Smrg **********************************************************************/ 27b8e80941Smrg /* 28b8e80941Smrg * Authors: 29b8e80941Smrg * Keith Whitwell <keithw@vmware.com> 30b8e80941Smrg */ 31b8e80941Smrg 32b8e80941Smrg#include "main/macros.h" 33b8e80941Smrg#include "main/enums.h" 34b8e80941Smrg#include "program/program.h" 35b8e80941Smrg 36b8e80941Smrg#include "brw_clip.h" 37b8e80941Smrg 38b8e80941Smrg 39b8e80941Smrg/* This is performed against the original triangles, so no indirection 40b8e80941Smrg * required: 41b8e80941SmrgBZZZT! 42b8e80941Smrg */ 43b8e80941Smrgstatic void compute_tri_direction( struct brw_clip_compile *c ) 44b8e80941Smrg{ 45b8e80941Smrg struct brw_codegen *p = &c->func; 46b8e80941Smrg struct brw_reg e = c->reg.tmp0; 47b8e80941Smrg struct brw_reg f = c->reg.tmp1; 48b8e80941Smrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 49b8e80941Smrg struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset); 50b8e80941Smrg struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset); 51b8e80941Smrg struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset); 52b8e80941Smrg 53b8e80941Smrg 54b8e80941Smrg struct brw_reg v0n = get_tmp(c); 55b8e80941Smrg struct brw_reg v1n = get_tmp(c); 56b8e80941Smrg struct brw_reg v2n = get_tmp(c); 57b8e80941Smrg 58b8e80941Smrg /* Convert to NDC. 59b8e80941Smrg * NOTE: We can't modify the original vertex coordinates, 60b8e80941Smrg * as it may impact further operations. 61b8e80941Smrg * So, we have to keep normalized coordinates in temp registers. 62b8e80941Smrg * 63b8e80941Smrg * TBD-KC 64b8e80941Smrg * Try to optimize unnecessary MOV's. 65b8e80941Smrg */ 66b8e80941Smrg brw_MOV(p, v0n, v0); 67b8e80941Smrg brw_MOV(p, v1n, v1); 68b8e80941Smrg brw_MOV(p, v2n, v2); 69b8e80941Smrg 70b8e80941Smrg brw_clip_project_position(c, v0n); 71b8e80941Smrg brw_clip_project_position(c, v1n); 72b8e80941Smrg brw_clip_project_position(c, v2n); 73b8e80941Smrg 74b8e80941Smrg /* Calculate the vectors of two edges of the triangle: 75b8e80941Smrg */ 76b8e80941Smrg brw_ADD(p, e, v0n, negate(v2n)); 77b8e80941Smrg brw_ADD(p, f, v1n, negate(v2n)); 78b8e80941Smrg 79b8e80941Smrg /* Take their crossproduct: 80b8e80941Smrg */ 81b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_16); 82b8e80941Smrg brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW), 83b8e80941Smrg brw_swizzle(f, BRW_SWIZZLE_ZXYW)); 84b8e80941Smrg brw_MAC(p, vec4(e), negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)), 85b8e80941Smrg brw_swizzle(f, BRW_SWIZZLE_YZXW)); 86b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_1); 87b8e80941Smrg 88b8e80941Smrg brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e)); 89b8e80941Smrg} 90b8e80941Smrg 91b8e80941Smrg 92b8e80941Smrgstatic void cull_direction( struct brw_clip_compile *c ) 93b8e80941Smrg{ 94b8e80941Smrg struct brw_codegen *p = &c->func; 95b8e80941Smrg GLuint conditional; 96b8e80941Smrg 97b8e80941Smrg assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL && 98b8e80941Smrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)); 99b8e80941Smrg 100b8e80941Smrg if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL) 101b8e80941Smrg conditional = BRW_CONDITIONAL_GE; 102b8e80941Smrg else 103b8e80941Smrg conditional = BRW_CONDITIONAL_L; 104b8e80941Smrg 105b8e80941Smrg brw_CMP(p, 106b8e80941Smrg vec1(brw_null_reg()), 107b8e80941Smrg conditional, 108b8e80941Smrg get_element(c->reg.dir, 2), 109b8e80941Smrg brw_imm_f(0)); 110b8e80941Smrg 111b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 112b8e80941Smrg { 113b8e80941Smrg brw_clip_kill_thread(c); 114b8e80941Smrg } 115b8e80941Smrg brw_ENDIF(p); 116b8e80941Smrg} 117b8e80941Smrg 118b8e80941Smrg 119b8e80941Smrg 120b8e80941Smrgstatic void copy_bfc( struct brw_clip_compile *c ) 121b8e80941Smrg{ 122b8e80941Smrg struct brw_codegen *p = &c->func; 123b8e80941Smrg GLuint conditional; 124b8e80941Smrg 125b8e80941Smrg /* Do we have any colors to copy? 126b8e80941Smrg */ 127b8e80941Smrg if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) && 128b8e80941Smrg brw_clip_have_varying(c, VARYING_SLOT_BFC0)) && 129b8e80941Smrg !(brw_clip_have_varying(c, VARYING_SLOT_COL1) && 130b8e80941Smrg brw_clip_have_varying(c, VARYING_SLOT_BFC1))) 131b8e80941Smrg return; 132b8e80941Smrg 133b8e80941Smrg /* In some weird degenerate cases we can end up testing the 134b8e80941Smrg * direction twice, once for culling and once for bfc copying. Oh 135b8e80941Smrg * well, that's what you get for setting weird GL state. 136b8e80941Smrg */ 137b8e80941Smrg if (c->key.copy_bfc_ccw) 138b8e80941Smrg conditional = BRW_CONDITIONAL_GE; 139b8e80941Smrg else 140b8e80941Smrg conditional = BRW_CONDITIONAL_L; 141b8e80941Smrg 142b8e80941Smrg brw_CMP(p, 143b8e80941Smrg vec1(brw_null_reg()), 144b8e80941Smrg conditional, 145b8e80941Smrg get_element(c->reg.dir, 2), 146b8e80941Smrg brw_imm_f(0)); 147b8e80941Smrg 148b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 149b8e80941Smrg { 150b8e80941Smrg GLuint i; 151b8e80941Smrg 152b8e80941Smrg for (i = 0; i < 3; i++) { 153b8e80941Smrg if (brw_clip_have_varying(c, VARYING_SLOT_COL0) && 154b8e80941Smrg brw_clip_have_varying(c, VARYING_SLOT_BFC0)) 155b8e80941Smrg brw_MOV(p, 156b8e80941Smrg byte_offset(c->reg.vertex[i], 157b8e80941Smrg brw_varying_to_offset(&c->vue_map, 158b8e80941Smrg VARYING_SLOT_COL0)), 159b8e80941Smrg byte_offset(c->reg.vertex[i], 160b8e80941Smrg brw_varying_to_offset(&c->vue_map, 161b8e80941Smrg VARYING_SLOT_BFC0))); 162b8e80941Smrg 163b8e80941Smrg if (brw_clip_have_varying(c, VARYING_SLOT_COL1) && 164b8e80941Smrg brw_clip_have_varying(c, VARYING_SLOT_BFC1)) 165b8e80941Smrg brw_MOV(p, 166b8e80941Smrg byte_offset(c->reg.vertex[i], 167b8e80941Smrg brw_varying_to_offset(&c->vue_map, 168b8e80941Smrg VARYING_SLOT_COL1)), 169b8e80941Smrg byte_offset(c->reg.vertex[i], 170b8e80941Smrg brw_varying_to_offset(&c->vue_map, 171b8e80941Smrg VARYING_SLOT_BFC1))); 172b8e80941Smrg } 173b8e80941Smrg } 174b8e80941Smrg brw_ENDIF(p); 175b8e80941Smrg} 176b8e80941Smrg 177b8e80941Smrg 178b8e80941Smrg 179b8e80941Smrg 180b8e80941Smrg/* 181b8e80941Smrg GLfloat iz = 1.0 / dir.z; 182b8e80941Smrg GLfloat ac = dir.x * iz; 183b8e80941Smrg GLfloat bc = dir.y * iz; 184b8e80941Smrg offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; 185b8e80941Smrg offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor; 186b8e80941Smrg if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) { 187b8e80941Smrg if (ctx->Polygon.OffsetClamp < 0) 188b8e80941Smrg offset = MAX2( offset, ctx->Polygon.OffsetClamp ); 189b8e80941Smrg else 190b8e80941Smrg offset = MIN2( offset, ctx->Polygon.OffsetClamp ); 191b8e80941Smrg } 192b8e80941Smrg offset *= MRD; 193b8e80941Smrg*/ 194b8e80941Smrgstatic void compute_offset( struct brw_clip_compile *c ) 195b8e80941Smrg{ 196b8e80941Smrg struct brw_codegen *p = &c->func; 197b8e80941Smrg struct brw_reg off = c->reg.offset; 198b8e80941Smrg struct brw_reg dir = c->reg.dir; 199b8e80941Smrg 200b8e80941Smrg brw_math_invert(p, get_element(off, 2), get_element(dir, 2)); 201b8e80941Smrg brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2)); 202b8e80941Smrg 203b8e80941Smrg brw_CMP(p, 204b8e80941Smrg vec1(brw_null_reg()), 205b8e80941Smrg BRW_CONDITIONAL_GE, 206b8e80941Smrg brw_abs(get_element(off, 0)), 207b8e80941Smrg brw_abs(get_element(off, 1))); 208b8e80941Smrg 209b8e80941Smrg brw_SEL(p, vec1(off), 210b8e80941Smrg brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1))); 211b8e80941Smrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 212b8e80941Smrg 213b8e80941Smrg brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor)); 214b8e80941Smrg brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units)); 215b8e80941Smrg if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) { 216b8e80941Smrg brw_CMP(p, 217b8e80941Smrg vec1(brw_null_reg()), 218b8e80941Smrg c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L, 219b8e80941Smrg vec1(off), 220b8e80941Smrg brw_imm_f(c->key.offset_clamp)); 221b8e80941Smrg brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp)); 222b8e80941Smrg } 223b8e80941Smrg} 224b8e80941Smrg 225b8e80941Smrg 226b8e80941Smrgstatic void merge_edgeflags( struct brw_clip_compile *c ) 227b8e80941Smrg{ 228b8e80941Smrg struct brw_codegen *p = &c->func; 229b8e80941Smrg struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0); 230b8e80941Smrg 231b8e80941Smrg brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 232b8e80941Smrg brw_CMP(p, 233b8e80941Smrg vec1(brw_null_reg()), 234b8e80941Smrg BRW_CONDITIONAL_EQ, 235b8e80941Smrg tmp0, 236b8e80941Smrg brw_imm_ud(_3DPRIM_POLYGON)); 237b8e80941Smrg 238b8e80941Smrg /* Get away with using reg.vertex because we know that this is not 239b8e80941Smrg * a _3DPRIM_TRISTRIP_REVERSE: 240b8e80941Smrg */ 241b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 242b8e80941Smrg { 243b8e80941Smrg brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8)); 244b8e80941Smrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ); 245b8e80941Smrg brw_MOV(p, byte_offset(c->reg.vertex[0], 246b8e80941Smrg brw_varying_to_offset(&c->vue_map, 247b8e80941Smrg VARYING_SLOT_EDGE)), 248b8e80941Smrg brw_imm_f(0)); 249b8e80941Smrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 250b8e80941Smrg 251b8e80941Smrg brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9)); 252b8e80941Smrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ); 253b8e80941Smrg brw_MOV(p, byte_offset(c->reg.vertex[2], 254b8e80941Smrg brw_varying_to_offset(&c->vue_map, 255b8e80941Smrg VARYING_SLOT_EDGE)), 256b8e80941Smrg brw_imm_f(0)); 257b8e80941Smrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 258b8e80941Smrg } 259b8e80941Smrg brw_ENDIF(p); 260b8e80941Smrg} 261b8e80941Smrg 262b8e80941Smrg 263b8e80941Smrg 264b8e80941Smrgstatic void apply_one_offset( struct brw_clip_compile *c, 265b8e80941Smrg struct brw_indirect vert ) 266b8e80941Smrg{ 267b8e80941Smrg struct brw_codegen *p = &c->func; 268b8e80941Smrg GLuint ndc_offset = brw_varying_to_offset(&c->vue_map, 269b8e80941Smrg BRW_VARYING_SLOT_NDC); 270b8e80941Smrg struct brw_reg z = deref_1f(vert, ndc_offset + 271b8e80941Smrg 2 * type_sz(BRW_REGISTER_TYPE_F)); 272b8e80941Smrg 273b8e80941Smrg brw_ADD(p, z, z, vec1(c->reg.offset)); 274b8e80941Smrg} 275b8e80941Smrg 276b8e80941Smrg 277b8e80941Smrg 278b8e80941Smrg/*********************************************************************** 279b8e80941Smrg * Output clipped polygon as an unfilled primitive: 280b8e80941Smrg */ 281b8e80941Smrgstatic void emit_lines(struct brw_clip_compile *c, 282b8e80941Smrg bool do_offset) 283b8e80941Smrg{ 284b8e80941Smrg struct brw_codegen *p = &c->func; 285b8e80941Smrg struct brw_indirect v0 = brw_indirect(0, 0); 286b8e80941Smrg struct brw_indirect v1 = brw_indirect(1, 0); 287b8e80941Smrg struct brw_indirect v0ptr = brw_indirect(2, 0); 288b8e80941Smrg struct brw_indirect v1ptr = brw_indirect(3, 0); 289b8e80941Smrg 290b8e80941Smrg /* Need a separate loop for offset: 291b8e80941Smrg */ 292b8e80941Smrg if (do_offset) { 293b8e80941Smrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 294b8e80941Smrg brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); 295b8e80941Smrg 296b8e80941Smrg brw_DO(p, BRW_EXECUTE_1); 297b8e80941Smrg { 298b8e80941Smrg brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); 299b8e80941Smrg brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); 300b8e80941Smrg 301b8e80941Smrg apply_one_offset(c, v0); 302b8e80941Smrg 303b8e80941Smrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 304b8e80941Smrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G); 305b8e80941Smrg } 306b8e80941Smrg brw_WHILE(p); 307b8e80941Smrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 308b8e80941Smrg } 309b8e80941Smrg 310b8e80941Smrg /* v1ptr = &inlist[nr_verts] 311b8e80941Smrg * *v1ptr = v0 312b8e80941Smrg */ 313b8e80941Smrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 314b8e80941Smrg brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); 315b8e80941Smrg brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW)); 316b8e80941Smrg brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW)); 317b8e80941Smrg brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0)); 318b8e80941Smrg 319b8e80941Smrg brw_DO(p, BRW_EXECUTE_1); 320b8e80941Smrg { 321b8e80941Smrg brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); 322b8e80941Smrg brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2)); 323b8e80941Smrg brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); 324b8e80941Smrg 325b8e80941Smrg /* draw edge if edgeflag != 0 */ 326b8e80941Smrg brw_CMP(p, 327b8e80941Smrg vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 328b8e80941Smrg deref_1f(v0, brw_varying_to_offset(&c->vue_map, 329b8e80941Smrg VARYING_SLOT_EDGE)), 330b8e80941Smrg brw_imm_f(0)); 331b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 332b8e80941Smrg { 333b8e80941Smrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 334b8e80941Smrg (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) 335b8e80941Smrg | URB_WRITE_PRIM_START); 336b8e80941Smrg brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE, 337b8e80941Smrg (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) 338b8e80941Smrg | URB_WRITE_PRIM_END); 339b8e80941Smrg } 340b8e80941Smrg brw_ENDIF(p); 341b8e80941Smrg 342b8e80941Smrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 343b8e80941Smrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 344b8e80941Smrg } 345b8e80941Smrg brw_WHILE(p); 346b8e80941Smrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 347b8e80941Smrg} 348b8e80941Smrg 349b8e80941Smrg 350b8e80941Smrg 351b8e80941Smrgstatic void emit_points(struct brw_clip_compile *c, 352b8e80941Smrg bool do_offset ) 353b8e80941Smrg{ 354b8e80941Smrg struct brw_codegen *p = &c->func; 355b8e80941Smrg 356b8e80941Smrg struct brw_indirect v0 = brw_indirect(0, 0); 357b8e80941Smrg struct brw_indirect v0ptr = brw_indirect(2, 0); 358b8e80941Smrg 359b8e80941Smrg brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 360b8e80941Smrg brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); 361b8e80941Smrg 362b8e80941Smrg brw_DO(p, BRW_EXECUTE_1); 363b8e80941Smrg { 364b8e80941Smrg brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); 365b8e80941Smrg brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); 366b8e80941Smrg 367b8e80941Smrg /* draw if edgeflag != 0 368b8e80941Smrg */ 369b8e80941Smrg brw_CMP(p, 370b8e80941Smrg vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 371b8e80941Smrg deref_1f(v0, brw_varying_to_offset(&c->vue_map, 372b8e80941Smrg VARYING_SLOT_EDGE)), 373b8e80941Smrg brw_imm_f(0)); 374b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 375b8e80941Smrg { 376b8e80941Smrg if (do_offset) 377b8e80941Smrg apply_one_offset(c, v0); 378b8e80941Smrg 379b8e80941Smrg brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 380b8e80941Smrg (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT) 381b8e80941Smrg | URB_WRITE_PRIM_START | URB_WRITE_PRIM_END); 382b8e80941Smrg } 383b8e80941Smrg brw_ENDIF(p); 384b8e80941Smrg 385b8e80941Smrg brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 386b8e80941Smrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 387b8e80941Smrg } 388b8e80941Smrg brw_WHILE(p); 389b8e80941Smrg brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 390b8e80941Smrg} 391b8e80941Smrg 392b8e80941Smrg 393b8e80941Smrg 394b8e80941Smrg 395b8e80941Smrg 396b8e80941Smrg 397b8e80941Smrg 398b8e80941Smrgstatic void emit_primitives( struct brw_clip_compile *c, 399b8e80941Smrg GLuint mode, 400b8e80941Smrg bool do_offset ) 401b8e80941Smrg{ 402b8e80941Smrg switch (mode) { 403b8e80941Smrg case BRW_CLIP_FILL_MODE_FILL: 404b8e80941Smrg brw_clip_tri_emit_polygon(c); 405b8e80941Smrg break; 406b8e80941Smrg 407b8e80941Smrg case BRW_CLIP_FILL_MODE_LINE: 408b8e80941Smrg emit_lines(c, do_offset); 409b8e80941Smrg break; 410b8e80941Smrg 411b8e80941Smrg case BRW_CLIP_FILL_MODE_POINT: 412b8e80941Smrg emit_points(c, do_offset); 413b8e80941Smrg break; 414b8e80941Smrg 415b8e80941Smrg case BRW_CLIP_FILL_MODE_CULL: 416b8e80941Smrg unreachable("not reached"); 417b8e80941Smrg } 418b8e80941Smrg} 419b8e80941Smrg 420b8e80941Smrg 421b8e80941Smrg 422b8e80941Smrgstatic void emit_unfilled_primitives( struct brw_clip_compile *c ) 423b8e80941Smrg{ 424b8e80941Smrg struct brw_codegen *p = &c->func; 425b8e80941Smrg 426b8e80941Smrg /* Direction culling has already been done. 427b8e80941Smrg */ 428b8e80941Smrg if (c->key.fill_ccw != c->key.fill_cw && 429b8e80941Smrg c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL && 430b8e80941Smrg c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) 431b8e80941Smrg { 432b8e80941Smrg brw_CMP(p, 433b8e80941Smrg vec1(brw_null_reg()), 434b8e80941Smrg BRW_CONDITIONAL_GE, 435b8e80941Smrg get_element(c->reg.dir, 2), 436b8e80941Smrg brw_imm_f(0)); 437b8e80941Smrg 438b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 439b8e80941Smrg { 440b8e80941Smrg emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw); 441b8e80941Smrg } 442b8e80941Smrg brw_ELSE(p); 443b8e80941Smrg { 444b8e80941Smrg emit_primitives(c, c->key.fill_cw, c->key.offset_cw); 445b8e80941Smrg } 446b8e80941Smrg brw_ENDIF(p); 447b8e80941Smrg } 448b8e80941Smrg else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) { 449b8e80941Smrg emit_primitives(c, c->key.fill_cw, c->key.offset_cw); 450b8e80941Smrg } 451b8e80941Smrg else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) { 452b8e80941Smrg emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw); 453b8e80941Smrg } 454b8e80941Smrg} 455b8e80941Smrg 456b8e80941Smrg 457b8e80941Smrg 458b8e80941Smrg 459b8e80941Smrgstatic void check_nr_verts( struct brw_clip_compile *c ) 460b8e80941Smrg{ 461b8e80941Smrg struct brw_codegen *p = &c->func; 462b8e80941Smrg 463b8e80941Smrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3)); 464b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 465b8e80941Smrg { 466b8e80941Smrg brw_clip_kill_thread(c); 467b8e80941Smrg } 468b8e80941Smrg brw_ENDIF(p); 469b8e80941Smrg} 470b8e80941Smrg 471b8e80941Smrg 472b8e80941Smrgvoid brw_emit_unfilled_clip( struct brw_clip_compile *c ) 473b8e80941Smrg{ 474b8e80941Smrg struct brw_codegen *p = &c->func; 475b8e80941Smrg 476b8e80941Smrg c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) || 477b8e80941Smrg (c->key.fill_ccw != c->key.fill_cw) || 478b8e80941Smrg c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL || 479b8e80941Smrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL || 480b8e80941Smrg c->key.copy_bfc_cw || 481b8e80941Smrg c->key.copy_bfc_ccw); 482b8e80941Smrg 483b8e80941Smrg brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); 484b8e80941Smrg brw_clip_tri_init_vertices(c); 485b8e80941Smrg brw_clip_init_ff_sync(c); 486b8e80941Smrg 487b8e80941Smrg assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE)); 488b8e80941Smrg 489b8e80941Smrg if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL && 490b8e80941Smrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) { 491b8e80941Smrg brw_clip_kill_thread(c); 492b8e80941Smrg return; 493b8e80941Smrg } 494b8e80941Smrg 495b8e80941Smrg merge_edgeflags(c); 496b8e80941Smrg 497b8e80941Smrg /* Need to use the inlist indirection here: 498b8e80941Smrg */ 499b8e80941Smrg if (c->need_direction) 500b8e80941Smrg compute_tri_direction(c); 501b8e80941Smrg 502b8e80941Smrg if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL || 503b8e80941Smrg c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) 504b8e80941Smrg cull_direction(c); 505b8e80941Smrg 506b8e80941Smrg if (c->key.offset_ccw || 507b8e80941Smrg c->key.offset_cw) 508b8e80941Smrg compute_offset(c); 509b8e80941Smrg 510b8e80941Smrg if (c->key.copy_bfc_ccw || 511b8e80941Smrg c->key.copy_bfc_cw) 512b8e80941Smrg copy_bfc(c); 513b8e80941Smrg 514b8e80941Smrg /* Need to do this whether we clip or not: 515b8e80941Smrg */ 516b8e80941Smrg if (c->key.contains_flat_varying) 517b8e80941Smrg brw_clip_tri_flat_shade(c); 518b8e80941Smrg 519b8e80941Smrg brw_clip_init_clipmask(c); 520b8e80941Smrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0)); 521b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 522b8e80941Smrg { 523b8e80941Smrg brw_clip_init_planes(c); 524b8e80941Smrg brw_clip_tri(c); 525b8e80941Smrg check_nr_verts(c); 526b8e80941Smrg } 527b8e80941Smrg brw_ENDIF(p); 528b8e80941Smrg 529b8e80941Smrg emit_unfilled_primitives(c); 530b8e80941Smrg brw_clip_kill_thread(c); 531b8e80941Smrg} 532