1 /* 2 Copyright (C) Intel Corp. 2006. All Rights Reserved. 3 Intel funded Tungsten Graphics to 4 develop this 3D driver. 5 6 Permission is hereby granted, free of charge, to any person obtaining 7 a copy of this software and associated documentation files (the 8 "Software"), to deal in the Software without restriction, including 9 without limitation the rights to use, copy, modify, merge, publish, 10 distribute, sublicense, and/or sell copies of the Software, and to 11 permit persons to whom the Software is furnished to do so, subject to 12 the following conditions: 13 14 The above copyright notice and this permission notice (including the 15 next paragraph) shall be included in all copies or substantial 16 portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 26 **********************************************************************/ 27 /* 28 * Authors: 29 * Keith Whitwell <keithw (at) vmware.com> 30 */ 31 32 #include "main/macros.h" 33 #include "main/enums.h" 34 #include "program/program.h" 35 36 #include "intel_batchbuffer.h" 37 38 #include "brw_defines.h" 39 #include "brw_context.h" 40 #include "brw_eu.h" 41 #include "brw_clip.h" 42 43 static void release_tmps( struct brw_clip_compile *c ) 44 { 45 c->last_tmp = c->first_tmp; 46 } 47 48 49 void brw_clip_tri_alloc_regs( struct brw_clip_compile *c, 50 GLuint nr_verts ) 51 { 52 const struct gen_device_info *devinfo = c->func.devinfo; 53 GLuint i = 0,j; 54 55 /* Register usage is static, precompute here: 56 */ 57 c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++; 58 59 if (c->key.nr_userclip) { 60 c->reg.fixed_planes = brw_vec4_grf(i, 0); 61 i += (6 + c->key.nr_userclip + 1) / 2; 62 63 c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2; 64 } 65 else 66 c->prog_data.curb_read_length = 0; 67 68 69 /* Payload vertices plus space for more generated vertices: 70 */ 71 for (j = 0; j < nr_verts; j++) { 72 c->reg.vertex[j] = brw_vec4_grf(i, 0); 73 i += c->nr_regs; 74 } 75 76 if (c->vue_map.num_slots % 2) { 77 /* The VUE has an odd number of slots so the last register is only half 78 * used. Fill the second half with zero. 79 */ 80 for (j = 0; j < 3; j++) { 81 GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots); 82 83 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0)); 84 } 85 } 86 87 c->reg.t = brw_vec1_grf(i, 0); 88 c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D); 89 c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD); 90 c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD); 91 c->reg.plane_equation = brw_vec4_grf(i, 4); 92 i++; 93 94 c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */ 95 c->reg.dp = brw_vec1_grf(i, 4); 96 i++; 97 98 c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); 99 i++; 100 101 c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); 102 i++; 103 104 c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); 105 i++; 106 107 if (!c->key.nr_userclip) { 108 c->reg.fixed_planes = brw_vec8_grf(i, 0); 109 i++; 110 } 111 112 if (c->key.do_unfilled) { 113 c->reg.dir = brw_vec4_grf(i, 0); 114 c->reg.offset = brw_vec4_grf(i, 4); 115 i++; 116 c->reg.tmp0 = brw_vec4_grf(i, 0); 117 c->reg.tmp1 = brw_vec4_grf(i, 4); 118 i++; 119 } 120 121 c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); 122 c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W); 123 i++; 124 125 if (devinfo->gen == 5) { 126 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); 127 i++; 128 } 129 130 c->first_tmp = i; 131 c->last_tmp = i; 132 133 c->prog_data.urb_read_length = c->nr_regs; /* ? */ 134 c->prog_data.total_grf = i; 135 } 136 137 138 139 void brw_clip_tri_init_vertices( struct brw_clip_compile *c ) 140 { 141 struct brw_codegen *p = &c->func; 142 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ 143 144 /* Initial list of indices for incoming vertexes: 145 */ 146 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 147 brw_CMP(p, 148 vec1(brw_null_reg()), 149 BRW_CONDITIONAL_EQ, 150 tmp0, 151 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE)); 152 153 /* XXX: Is there an easier way to do this? Need to reverse every 154 * second tristrip element: Can ignore sometimes? 155 */ 156 brw_IF(p, BRW_EXECUTE_1); 157 { 158 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) ); 159 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) ); 160 if (c->need_direction) 161 brw_MOV(p, c->reg.dir, brw_imm_f(-1)); 162 } 163 brw_ELSE(p); 164 { 165 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) ); 166 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) ); 167 if (c->need_direction) 168 brw_MOV(p, c->reg.dir, brw_imm_f(1)); 169 } 170 brw_ENDIF(p); 171 172 brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) ); 173 brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0)); 174 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3)); 175 } 176 177 178 179 void brw_clip_tri_flat_shade( struct brw_clip_compile *c ) 180 { 181 struct brw_codegen *p = &c->func; 182 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ 183 184 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 185 brw_CMP(p, 186 vec1(brw_null_reg()), 187 BRW_CONDITIONAL_EQ, 188 tmp0, 189 brw_imm_ud(_3DPRIM_POLYGON)); 190 191 brw_IF(p, BRW_EXECUTE_1); 192 { 193 brw_clip_copy_flatshaded_attributes(c, 1, 0); 194 brw_clip_copy_flatshaded_attributes(c, 2, 0); 195 } 196 brw_ELSE(p); 197 { 198 if (c->key.pv_first) { 199 brw_CMP(p, 200 vec1(brw_null_reg()), 201 BRW_CONDITIONAL_EQ, 202 tmp0, 203 brw_imm_ud(_3DPRIM_TRIFAN)); 204 brw_IF(p, BRW_EXECUTE_1); 205 { 206 brw_clip_copy_flatshaded_attributes(c, 0, 1); 207 brw_clip_copy_flatshaded_attributes(c, 2, 1); 208 } 209 brw_ELSE(p); 210 { 211 brw_clip_copy_flatshaded_attributes(c, 1, 0); 212 brw_clip_copy_flatshaded_attributes(c, 2, 0); 213 } 214 brw_ENDIF(p); 215 } 216 else { 217 brw_clip_copy_flatshaded_attributes(c, 0, 2); 218 brw_clip_copy_flatshaded_attributes(c, 1, 2); 219 } 220 } 221 brw_ENDIF(p); 222 } 223 224 225 /** 226 * Loads the clip distance for a vertex into `dst`, and ends with 227 * a comparison of it to zero with the condition `cond`. 228 * 229 * - If using a fixed plane, the distance is dot(hpos, plane). 230 * - If using a user clip plane, the distance is directly available in the vertex. 231 */ 232 static inline void 233 load_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx, 234 struct brw_reg dst, GLuint hpos_offset, int cond) 235 { 236 struct brw_codegen *p = &c->func; 237 238 dst = vec4(dst); 239 brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1)); 240 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 241 brw_IF(p, BRW_EXECUTE_1); 242 { 243 struct brw_indirect temp_ptr = brw_indirect(7, 0); 244 brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset); 245 brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0)); 246 } 247 brw_ELSE(p); 248 { 249 brw_MOV(p, dst, deref_4f(vtx, hpos_offset)); 250 brw_DP4(p, dst, dst, c->reg.plane_equation); 251 } 252 brw_ENDIF(p); 253 254 brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f)); 255 } 256 257 258 /* Use mesa's clipping algorithms, translated to GEN4 assembly. 259 */ 260 void brw_clip_tri( struct brw_clip_compile *c ) 261 { 262 struct brw_codegen *p = &c->func; 263 struct brw_indirect vtx = brw_indirect(0, 0); 264 struct brw_indirect vtxPrev = brw_indirect(1, 0); 265 struct brw_indirect vtxOut = brw_indirect(2, 0); 266 struct brw_indirect plane_ptr = brw_indirect(3, 0); 267 struct brw_indirect inlist_ptr = brw_indirect(4, 0); 268 struct brw_indirect outlist_ptr = brw_indirect(5, 0); 269 struct brw_indirect freelist_ptr = brw_indirect(6, 0); 270 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 271 GLint clipdist0_offset = c->key.nr_userclip 272 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0) 273 : 0; 274 275 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) ); 276 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c)); 277 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist)); 278 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist)); 279 280 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) ); 281 282 /* Set the initial vertex source mask: The first 6 planes are the bounds 283 * of the view volume; the next 8 planes are the user clipping planes. 284 */ 285 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0)); 286 287 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0]. 288 * We'll increment 6 times before we start hitting actual user clipping. */ 289 brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float))); 290 291 brw_DO(p, BRW_EXECUTE_1); 292 { 293 /* if (planemask & 1) 294 */ 295 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1)); 296 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 297 298 brw_IF(p, BRW_EXECUTE_1); 299 { 300 /* vtxOut = freelist_ptr++ 301 */ 302 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) ); 303 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE)); 304 305 if (c->key.nr_userclip) 306 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0)); 307 else 308 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0)); 309 310 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); 311 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0)); 312 313 brw_DO(p, BRW_EXECUTE_1); 314 { 315 /* vtx = *input_ptr; 316 */ 317 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0)); 318 319 load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L); 320 /* (prev < 0.0f) */ 321 brw_IF(p, BRW_EXECUTE_1); 322 { 323 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE); 324 /* IS_POSITIVE(next) 325 */ 326 brw_IF(p, BRW_EXECUTE_1); 327 { 328 329 /* Coming back in. 330 */ 331 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp)); 332 brw_math_invert(p, c->reg.t, c->reg.t); 333 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev); 334 335 /* If (vtxOut == 0) vtxOut = vtxPrev 336 */ 337 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) ); 338 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev)); 339 brw_inst_set_pred_control(p->devinfo, brw_last_inst, 340 BRW_PREDICATE_NORMAL); 341 342 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false); 343 344 /* *outlist_ptr++ = vtxOut; 345 * nr_verts++; 346 * vtxOut = 0; 347 */ 348 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut)); 349 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); 350 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); 351 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) ); 352 } 353 brw_ENDIF(p); 354 355 } 356 brw_ELSE(p); 357 { 358 /* *outlist_ptr++ = vtxPrev; 359 * nr_verts++; 360 */ 361 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev)); 362 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); 363 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); 364 365 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_L); 366 /* (next < 0.0f) 367 */ 368 brw_IF(p, BRW_EXECUTE_1); 369 { 370 /* Going out of bounds. Avoid division by zero as we 371 * know dp != dpPrev from DIFFERENT_SIGNS, above. 372 */ 373 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev)); 374 brw_math_invert(p, c->reg.t, c->reg.t); 375 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp); 376 377 /* If (vtxOut == 0) vtxOut = vtx 378 */ 379 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) ); 380 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx)); 381 brw_inst_set_pred_control(p->devinfo, brw_last_inst, 382 BRW_PREDICATE_NORMAL); 383 384 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true); 385 386 /* *outlist_ptr++ = vtxOut; 387 * nr_verts++; 388 * vtxOut = 0; 389 */ 390 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut)); 391 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); 392 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); 393 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) ); 394 } 395 brw_ENDIF(p); 396 } 397 brw_ENDIF(p); 398 399 /* vtxPrev = vtx; 400 * inlist_ptr++; 401 */ 402 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx)); 403 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short))); 404 405 /* while (--loopcount != 0) 406 */ 407 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 408 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 409 } 410 brw_WHILE(p); 411 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 412 413 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1] 414 * inlist = outlist 415 * inlist_ptr = &inlist[0] 416 * outlist_ptr = &outlist[0] 417 */ 418 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2)); 419 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0)); 420 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0)); 421 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist)); 422 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist)); 423 } 424 brw_ENDIF(p); 425 426 /* plane_ptr++; 427 */ 428 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c)); 429 430 /* nr_verts >= 3 431 */ 432 brw_CMP(p, 433 vec1(brw_null_reg()), 434 BRW_CONDITIONAL_GE, 435 c->reg.nr_verts, 436 brw_imm_ud(3)); 437 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL); 438 439 /* && (planemask>>=1) != 0 440 */ 441 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1)); 442 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 443 brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1)); 444 brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float))); 445 } 446 brw_WHILE(p); 447 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 448 } 449 450 451 452 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c) 453 { 454 struct brw_codegen *p = &c->func; 455 456 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--) 457 */ 458 brw_ADD(p, 459 c->reg.loopcount, 460 c->reg.nr_verts, 461 brw_imm_d(-2)); 462 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G); 463 464 brw_IF(p, BRW_EXECUTE_1); 465 { 466 struct brw_indirect v0 = brw_indirect(0, 0); 467 struct brw_indirect vptr = brw_indirect(1, 0); 468 469 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist)); 470 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); 471 472 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 473 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT) 474 | URB_WRITE_PRIM_START)); 475 476 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2)); 477 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); 478 479 brw_DO(p, BRW_EXECUTE_1); 480 { 481 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE, 482 (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)); 483 484 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2)); 485 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); 486 487 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); 488 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 489 } 490 brw_WHILE(p); 491 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 492 493 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_EOT_COMPLETE, 494 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT) 495 | URB_WRITE_PRIM_END)); 496 } 497 brw_ENDIF(p); 498 } 499 500 static void do_clip_tri( struct brw_clip_compile *c ) 501 { 502 brw_clip_init_planes(c); 503 504 brw_clip_tri(c); 505 } 506 507 508 static void maybe_do_clip_tri( struct brw_clip_compile *c ) 509 { 510 struct brw_codegen *p = &c->func; 511 512 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0)); 513 brw_IF(p, BRW_EXECUTE_1); 514 { 515 do_clip_tri(c); 516 } 517 brw_ENDIF(p); 518 } 519 520 static void brw_clip_test( struct brw_clip_compile *c ) 521 { 522 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 523 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 524 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 525 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); 526 527 struct brw_reg v0 = get_tmp(c); 528 struct brw_reg v1 = get_tmp(c); 529 struct brw_reg v2 = get_tmp(c); 530 531 struct brw_indirect vt0 = brw_indirect(0, 0); 532 struct brw_indirect vt1 = brw_indirect(1, 0); 533 struct brw_indirect vt2 = brw_indirect(2, 0); 534 535 struct brw_codegen *p = &c->func; 536 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ 537 538 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, 539 VARYING_SLOT_POS); 540 541 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0])); 542 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1])); 543 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2])); 544 brw_MOV(p, v0, deref_4f(vt0, hpos_offset)); 545 brw_MOV(p, v1, deref_4f(vt1, hpos_offset)); 546 brw_MOV(p, v2, deref_4f(vt2, hpos_offset)); 547 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f)); 548 549 /* test nearz, xmin, ymin plane */ 550 /* clip.xyz < -clip.w */ 551 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3))); 552 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3))); 553 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3))); 554 555 /* All vertices are outside of a plane, rejected */ 556 brw_AND(p, t, t1, t2); 557 brw_AND(p, t, t, t3); 558 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1)); 559 brw_OR(p, tmp0, tmp0, get_element(t, 2)); 560 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1)); 561 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 562 brw_IF(p, BRW_EXECUTE_1); 563 { 564 brw_clip_kill_thread(c); 565 } 566 brw_ENDIF(p); 567 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 568 569 /* some vertices are inside a plane, some are outside,need to clip */ 570 brw_XOR(p, t, t1, t2); 571 brw_XOR(p, t1, t2, t3); 572 brw_OR(p, t, t, t1); 573 brw_AND(p, t, t, brw_imm_ud(0x1)); 574 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 575 get_element(t, 0), brw_imm_ud(0)); 576 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5))); 577 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 578 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 579 get_element(t, 1), brw_imm_ud(0)); 580 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3))); 581 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 582 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 583 get_element(t, 2), brw_imm_ud(0)); 584 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1))); 585 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 586 587 /* test farz, xmax, ymax plane */ 588 /* clip.xyz > clip.w */ 589 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3)); 590 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3)); 591 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3)); 592 593 /* All vertices are outside of a plane, rejected */ 594 brw_AND(p, t, t1, t2); 595 brw_AND(p, t, t, t3); 596 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1)); 597 brw_OR(p, tmp0, tmp0, get_element(t, 2)); 598 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1)); 599 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 600 brw_IF(p, BRW_EXECUTE_1); 601 { 602 brw_clip_kill_thread(c); 603 } 604 brw_ENDIF(p); 605 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 606 607 /* some vertices are inside a plane, some are outside,need to clip */ 608 brw_XOR(p, t, t1, t2); 609 brw_XOR(p, t1, t2, t3); 610 brw_OR(p, t, t, t1); 611 brw_AND(p, t, t, brw_imm_ud(0x1)); 612 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 613 get_element(t, 0), brw_imm_ud(0)); 614 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4))); 615 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 616 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 617 get_element(t, 1), brw_imm_ud(0)); 618 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2))); 619 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 620 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, 621 get_element(t, 2), brw_imm_ud(0)); 622 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0))); 623 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL); 624 625 release_tmps(c); 626 } 627 628 629 void brw_emit_tri_clip( struct brw_clip_compile *c ) 630 { 631 struct brw_codegen *p = &c->func; 632 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); 633 brw_clip_tri_init_vertices(c); 634 brw_clip_init_clipmask(c); 635 brw_clip_init_ff_sync(c); 636 637 /* if -ve rhw workaround bit is set, 638 do cliptest */ 639 if (p->devinfo->has_negative_rhw_bug) { 640 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2), 641 brw_imm_ud(1<<20)); 642 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ); 643 brw_IF(p, BRW_EXECUTE_1); 644 { 645 brw_clip_test(c); 646 } 647 brw_ENDIF(p); 648 } 649 /* Can't push into do_clip_tri because with polygon (or quad) 650 * flatshading, need to apply the flatshade here because we don't 651 * respect the PV when converting to trifan for emit: 652 */ 653 if (c->key.contains_flat_varying) 654 brw_clip_tri_flat_shade(c); 655 656 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) || 657 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP)) 658 do_clip_tri(c); 659 else 660 maybe_do_clip_tri(c); 661 662 brw_clip_tri_emit_polygon(c); 663 664 /* Send an empty message to kill the thread: 665 */ 666 brw_clip_kill_thread(c); 667 } 668