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