2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
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:
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.
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.
26 **********************************************************************/
29 * Keith Whitwell <keithw@vmware.com>
32 #include "main/macros.h"
33 #include "main/enums.h"
34 #include "program/program.h"
36 #include "intel_batchbuffer.h"
38 #include "brw_defines.h"
39 #include "brw_context.h"
42 static void release_tmps( struct brw_clip_compile
*c
)
44 c
->last_tmp
= c
->first_tmp
;
48 void brw_clip_tri_alloc_regs( struct brw_clip_compile
*c
,
51 const struct gen_device_info
*devinfo
= c
->func
.devinfo
;
54 /* Register usage is static, precompute here:
56 c
->reg
.R0
= retype(brw_vec8_grf(i
, 0), BRW_REGISTER_TYPE_UD
); i
++;
58 if (c
->key
.nr_userclip
) {
59 c
->reg
.fixed_planes
= brw_vec4_grf(i
, 0);
60 i
+= (6 + c
->key
.nr_userclip
+ 1) / 2;
62 c
->prog_data
.curb_read_length
= (6 + c
->key
.nr_userclip
+ 1) / 2;
65 c
->prog_data
.curb_read_length
= 0;
68 /* Payload vertices plus space for more generated vertices:
70 for (j
= 0; j
< nr_verts
; j
++) {
71 c
->reg
.vertex
[j
] = brw_vec4_grf(i
, 0);
75 if (c
->vue_map
.num_slots
% 2) {
76 /* The VUE has an odd number of slots so the last register is only half
77 * used. Fill the second half with zero.
79 for (j
= 0; j
< 3; j
++) {
80 GLuint delta
= brw_vue_slot_to_offset(c
->vue_map
.num_slots
);
82 brw_MOV(&c
->func
, byte_offset(c
->reg
.vertex
[j
], delta
), brw_imm_f(0));
86 c
->reg
.t
= brw_vec1_grf(i
, 0);
87 c
->reg
.loopcount
= retype(brw_vec1_grf(i
, 1), BRW_REGISTER_TYPE_D
);
88 c
->reg
.nr_verts
= retype(brw_vec1_grf(i
, 2), BRW_REGISTER_TYPE_UD
);
89 c
->reg
.planemask
= retype(brw_vec1_grf(i
, 3), BRW_REGISTER_TYPE_UD
);
90 c
->reg
.plane_equation
= brw_vec4_grf(i
, 4);
93 c
->reg
.dpPrev
= brw_vec1_grf(i
, 0); /* fixme - dp4 will clobber r.1,2,3 */
94 c
->reg
.dp
= brw_vec1_grf(i
, 4);
97 c
->reg
.inlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
100 c
->reg
.outlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
103 c
->reg
.freelist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
106 if (!c
->key
.nr_userclip
) {
107 c
->reg
.fixed_planes
= brw_vec8_grf(i
, 0);
111 if (c
->key
.do_unfilled
) {
112 c
->reg
.dir
= brw_vec4_grf(i
, 0);
113 c
->reg
.offset
= brw_vec4_grf(i
, 4);
115 c
->reg
.tmp0
= brw_vec4_grf(i
, 0);
116 c
->reg
.tmp1
= brw_vec4_grf(i
, 4);
120 c
->reg
.vertex_src_mask
= retype(brw_vec1_grf(i
, 0), BRW_REGISTER_TYPE_UD
);
121 c
->reg
.clipdistance_offset
= retype(brw_vec1_grf(i
, 1), BRW_REGISTER_TYPE_W
);
124 if (devinfo
->gen
== 5) {
125 c
->reg
.ff_sync
= retype(brw_vec1_grf(i
, 0), BRW_REGISTER_TYPE_UD
);
132 c
->prog_data
.urb_read_length
= c
->nr_regs
; /* ? */
133 c
->prog_data
.total_grf
= i
;
138 void brw_clip_tri_init_vertices( struct brw_clip_compile
*c
)
140 struct brw_codegen
*p
= &c
->func
;
141 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
143 /* Initial list of indices for incoming vertexes:
145 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
147 vec1(brw_null_reg()),
150 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE
));
152 /* XXX: Is there an easier way to do this? Need to reverse every
153 * second tristrip element: Can ignore sometimes?
155 brw_IF(p
, BRW_EXECUTE_1
);
157 brw_MOV(p
, get_element(c
->reg
.inlist
, 0), brw_address(c
->reg
.vertex
[1]) );
158 brw_MOV(p
, get_element(c
->reg
.inlist
, 1), brw_address(c
->reg
.vertex
[0]) );
159 if (c
->need_direction
)
160 brw_MOV(p
, c
->reg
.dir
, brw_imm_f(-1));
164 brw_MOV(p
, get_element(c
->reg
.inlist
, 0), brw_address(c
->reg
.vertex
[0]) );
165 brw_MOV(p
, get_element(c
->reg
.inlist
, 1), brw_address(c
->reg
.vertex
[1]) );
166 if (c
->need_direction
)
167 brw_MOV(p
, c
->reg
.dir
, brw_imm_f(1));
171 brw_MOV(p
, get_element(c
->reg
.inlist
, 2), brw_address(c
->reg
.vertex
[2]) );
172 brw_MOV(p
, brw_vec8_grf(c
->reg
.outlist
.nr
, 0), brw_imm_f(0));
173 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(3));
178 void brw_clip_tri_flat_shade( struct brw_clip_compile
*c
)
180 struct brw_codegen
*p
= &c
->func
;
181 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
183 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
185 vec1(brw_null_reg()),
188 brw_imm_ud(_3DPRIM_POLYGON
));
190 brw_IF(p
, BRW_EXECUTE_1
);
192 brw_clip_copy_flatshaded_attributes(c
, 1, 0);
193 brw_clip_copy_flatshaded_attributes(c
, 2, 0);
197 if (c
->key
.pv_first
) {
199 vec1(brw_null_reg()),
202 brw_imm_ud(_3DPRIM_TRIFAN
));
203 brw_IF(p
, BRW_EXECUTE_1
);
205 brw_clip_copy_flatshaded_attributes(c
, 0, 1);
206 brw_clip_copy_flatshaded_attributes(c
, 2, 1);
210 brw_clip_copy_flatshaded_attributes(c
, 1, 0);
211 brw_clip_copy_flatshaded_attributes(c
, 2, 0);
216 brw_clip_copy_flatshaded_attributes(c
, 0, 2);
217 brw_clip_copy_flatshaded_attributes(c
, 1, 2);
225 * Loads the clip distance for a vertex into `dst`, and ends with
226 * a comparison of it to zero with the condition `cond`.
228 * - If using a fixed plane, the distance is dot(hpos, plane).
229 * - If using a user clip plane, the distance is directly available in the vertex.
232 load_clip_distance(struct brw_clip_compile
*c
, struct brw_indirect vtx
,
233 struct brw_reg dst
, GLuint hpos_offset
, int cond
)
235 struct brw_codegen
*p
= &c
->func
;
238 brw_AND(p
, vec1(brw_null_reg()), c
->reg
.vertex_src_mask
, brw_imm_ud(1));
239 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
240 brw_IF(p
, BRW_EXECUTE_1
);
242 struct brw_indirect temp_ptr
= brw_indirect(7, 0);
243 brw_ADD(p
, get_addr_reg(temp_ptr
), get_addr_reg(vtx
), c
->reg
.clipdistance_offset
);
244 brw_MOV(p
, vec1(dst
), deref_1f(temp_ptr
, 0));
248 brw_MOV(p
, dst
, deref_4f(vtx
, hpos_offset
));
249 brw_DP4(p
, dst
, dst
, c
->reg
.plane_equation
);
253 brw_CMP(p
, brw_null_reg(), cond
, vec1(dst
), brw_imm_f(0.0f
));
257 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
259 void brw_clip_tri( struct brw_clip_compile
*c
)
261 struct brw_codegen
*p
= &c
->func
;
262 struct brw_indirect vtx
= brw_indirect(0, 0);
263 struct brw_indirect vtxPrev
= brw_indirect(1, 0);
264 struct brw_indirect vtxOut
= brw_indirect(2, 0);
265 struct brw_indirect plane_ptr
= brw_indirect(3, 0);
266 struct brw_indirect inlist_ptr
= brw_indirect(4, 0);
267 struct brw_indirect outlist_ptr
= brw_indirect(5, 0);
268 struct brw_indirect freelist_ptr
= brw_indirect(6, 0);
269 GLuint hpos_offset
= brw_varying_to_offset(&c
->vue_map
, VARYING_SLOT_POS
);
270 GLint clipdist0_offset
= c
->key
.nr_userclip
271 ? brw_varying_to_offset(&c
->vue_map
, VARYING_SLOT_CLIP_DIST0
)
274 brw_MOV(p
, get_addr_reg(vtxPrev
), brw_address(c
->reg
.vertex
[2]) );
275 brw_MOV(p
, get_addr_reg(plane_ptr
), brw_clip_plane0_address(c
));
276 brw_MOV(p
, get_addr_reg(inlist_ptr
), brw_address(c
->reg
.inlist
));
277 brw_MOV(p
, get_addr_reg(outlist_ptr
), brw_address(c
->reg
.outlist
));
279 brw_MOV(p
, get_addr_reg(freelist_ptr
), brw_address(c
->reg
.vertex
[3]) );
281 /* Set the initial vertex source mask: The first 6 planes are the bounds
282 * of the view volume; the next 8 planes are the user clipping planes.
284 brw_MOV(p
, c
->reg
.vertex_src_mask
, brw_imm_ud(0x3fc0));
286 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
287 * We'll increment 6 times before we start hitting actual user clipping. */
288 brw_MOV(p
, c
->reg
.clipdistance_offset
, brw_imm_d(clipdist0_offset
- 6*sizeof(float)));
290 brw_DO(p
, BRW_EXECUTE_1
);
292 /* if (planemask & 1)
294 brw_AND(p
, vec1(brw_null_reg()), c
->reg
.planemask
, brw_imm_ud(1));
295 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
297 brw_IF(p
, BRW_EXECUTE_1
);
299 /* vtxOut = freelist_ptr++
301 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(freelist_ptr
) );
302 brw_ADD(p
, get_addr_reg(freelist_ptr
), get_addr_reg(freelist_ptr
), brw_imm_uw(c
->nr_regs
* REG_SIZE
));
304 if (c
->key
.nr_userclip
)
305 brw_MOV(p
, c
->reg
.plane_equation
, deref_4f(plane_ptr
, 0));
307 brw_MOV(p
, c
->reg
.plane_equation
, deref_4b(plane_ptr
, 0));
309 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
310 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(0));
312 brw_DO(p
, BRW_EXECUTE_1
);
316 brw_MOV(p
, get_addr_reg(vtx
), deref_1uw(inlist_ptr
, 0));
318 load_clip_distance(c
, vtxPrev
, c
->reg
.dpPrev
, hpos_offset
, BRW_CONDITIONAL_L
);
320 brw_IF(p
, BRW_EXECUTE_1
);
322 load_clip_distance(c
, vtx
, c
->reg
.dp
, hpos_offset
, BRW_CONDITIONAL_GE
);
325 brw_IF(p
, BRW_EXECUTE_1
);
330 brw_ADD(p
, c
->reg
.t
, c
->reg
.dpPrev
, negate(c
->reg
.dp
));
331 brw_math_invert(p
, c
->reg
.t
, c
->reg
.t
);
332 brw_MUL(p
, c
->reg
.t
, c
->reg
.t
, c
->reg
.dpPrev
);
334 /* If (vtxOut == 0) vtxOut = vtxPrev
336 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
337 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(vtxPrev
));
338 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
,
339 BRW_PREDICATE_NORMAL
);
341 brw_clip_interp_vertex(c
, vtxOut
, vtxPrev
, vtx
, c
->reg
.t
, false);
343 /* *outlist_ptr++ = vtxOut;
347 brw_MOV(p
, deref_1uw(outlist_ptr
, 0), get_addr_reg(vtxOut
));
348 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_uw(sizeof(short)));
349 brw_ADD(p
, c
->reg
.nr_verts
, c
->reg
.nr_verts
, brw_imm_ud(1));
350 brw_MOV(p
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
357 /* *outlist_ptr++ = vtxPrev;
360 brw_MOV(p
, deref_1uw(outlist_ptr
, 0), get_addr_reg(vtxPrev
));
361 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_uw(sizeof(short)));
362 brw_ADD(p
, c
->reg
.nr_verts
, c
->reg
.nr_verts
, brw_imm_ud(1));
364 load_clip_distance(c
, vtx
, c
->reg
.dp
, hpos_offset
, BRW_CONDITIONAL_L
);
367 brw_IF(p
, BRW_EXECUTE_1
);
369 /* Going out of bounds. Avoid division by zero as we
370 * know dp != dpPrev from DIFFERENT_SIGNS, above.
372 brw_ADD(p
, c
->reg
.t
, c
->reg
.dp
, negate(c
->reg
.dpPrev
));
373 brw_math_invert(p
, c
->reg
.t
, c
->reg
.t
);
374 brw_MUL(p
, c
->reg
.t
, c
->reg
.t
, c
->reg
.dp
);
376 /* If (vtxOut == 0) vtxOut = vtx
378 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
379 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(vtx
));
380 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
,
381 BRW_PREDICATE_NORMAL
);
383 brw_clip_interp_vertex(c
, vtxOut
, vtx
, vtxPrev
, c
->reg
.t
, true);
385 /* *outlist_ptr++ = vtxOut;
389 brw_MOV(p
, deref_1uw(outlist_ptr
, 0), get_addr_reg(vtxOut
));
390 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_uw(sizeof(short)));
391 brw_ADD(p
, c
->reg
.nr_verts
, c
->reg
.nr_verts
, brw_imm_ud(1));
392 brw_MOV(p
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
401 brw_MOV(p
, get_addr_reg(vtxPrev
), get_addr_reg(vtx
));
402 brw_ADD(p
, get_addr_reg(inlist_ptr
), get_addr_reg(inlist_ptr
), brw_imm_uw(sizeof(short)));
404 /* while (--loopcount != 0)
406 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
407 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
410 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
412 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
414 * inlist_ptr = &inlist[0]
415 * outlist_ptr = &outlist[0]
417 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_w(-2));
418 brw_MOV(p
, get_addr_reg(vtxPrev
), deref_1uw(outlist_ptr
, 0));
419 brw_MOV(p
, brw_vec8_grf(c
->reg
.inlist
.nr
, 0), brw_vec8_grf(c
->reg
.outlist
.nr
, 0));
420 brw_MOV(p
, get_addr_reg(inlist_ptr
), brw_address(c
->reg
.inlist
));
421 brw_MOV(p
, get_addr_reg(outlist_ptr
), brw_address(c
->reg
.outlist
));
427 brw_ADD(p
, get_addr_reg(plane_ptr
), get_addr_reg(plane_ptr
), brw_clip_plane_stride(c
));
432 vec1(brw_null_reg()),
436 brw_set_default_predicate_control(p
, BRW_PREDICATE_NORMAL
);
438 /* && (planemask>>=1) != 0
440 brw_SHR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud(1));
441 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
442 brw_SHR(p
, c
->reg
.vertex_src_mask
, c
->reg
.vertex_src_mask
, brw_imm_ud(1));
443 brw_ADD(p
, c
->reg
.clipdistance_offset
, c
->reg
.clipdistance_offset
, brw_imm_w(sizeof(float)));
446 brw_set_default_predicate_control(p
, BRW_PREDICATE_NONE
);
451 void brw_clip_tri_emit_polygon(struct brw_clip_compile
*c
)
453 struct brw_codegen
*p
= &c
->func
;
455 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
461 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_G
);
463 brw_IF(p
, BRW_EXECUTE_1
);
465 struct brw_indirect v0
= brw_indirect(0, 0);
466 struct brw_indirect vptr
= brw_indirect(1, 0);
468 brw_MOV(p
, get_addr_reg(vptr
), brw_address(c
->reg
.inlist
));
469 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
471 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_ALLOCATE_COMPLETE
,
472 ((_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
)
473 | URB_WRITE_PRIM_START
));
475 brw_ADD(p
, get_addr_reg(vptr
), get_addr_reg(vptr
), brw_imm_uw(2));
476 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
478 brw_DO(p
, BRW_EXECUTE_1
);
480 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_ALLOCATE_COMPLETE
,
481 (_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
));
483 brw_ADD(p
, get_addr_reg(vptr
), get_addr_reg(vptr
), brw_imm_uw(2));
484 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
486 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
487 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
490 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
492 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_EOT_COMPLETE
,
493 ((_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
)
494 | URB_WRITE_PRIM_END
));
499 static void do_clip_tri( struct brw_clip_compile
*c
)
501 brw_clip_init_planes(c
);
507 static void maybe_do_clip_tri( struct brw_clip_compile
*c
)
509 struct brw_codegen
*p
= &c
->func
;
511 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ
, c
->reg
.planemask
, brw_imm_ud(0));
512 brw_IF(p
, BRW_EXECUTE_1
);
519 static void brw_clip_test( struct brw_clip_compile
*c
)
521 struct brw_reg t
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
522 struct brw_reg t1
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
523 struct brw_reg t2
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
524 struct brw_reg t3
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
526 struct brw_reg v0
= get_tmp(c
);
527 struct brw_reg v1
= get_tmp(c
);
528 struct brw_reg v2
= get_tmp(c
);
530 struct brw_indirect vt0
= brw_indirect(0, 0);
531 struct brw_indirect vt1
= brw_indirect(1, 0);
532 struct brw_indirect vt2
= brw_indirect(2, 0);
534 struct brw_codegen
*p
= &c
->func
;
535 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
537 GLuint hpos_offset
= brw_varying_to_offset(&c
->vue_map
,
540 brw_MOV(p
, get_addr_reg(vt0
), brw_address(c
->reg
.vertex
[0]));
541 brw_MOV(p
, get_addr_reg(vt1
), brw_address(c
->reg
.vertex
[1]));
542 brw_MOV(p
, get_addr_reg(vt2
), brw_address(c
->reg
.vertex
[2]));
543 brw_MOV(p
, v0
, deref_4f(vt0
, hpos_offset
));
544 brw_MOV(p
, v1
, deref_4f(vt1
, hpos_offset
));
545 brw_MOV(p
, v2
, deref_4f(vt2
, hpos_offset
));
546 brw_AND(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud(~0x3f));
548 /* test nearz, xmin, ymin plane */
549 /* clip.xyz < -clip.w */
550 brw_CMP(p
, t1
, BRW_CONDITIONAL_L
, v0
, negate(get_element(v0
, 3)));
551 brw_CMP(p
, t2
, BRW_CONDITIONAL_L
, v1
, negate(get_element(v1
, 3)));
552 brw_CMP(p
, t3
, BRW_CONDITIONAL_L
, v2
, negate(get_element(v2
, 3)));
554 /* All vertices are outside of a plane, rejected */
555 brw_AND(p
, t
, t1
, t2
);
556 brw_AND(p
, t
, t
, t3
);
557 brw_OR(p
, tmp0
, get_element(t
, 0), get_element(t
, 1));
558 brw_OR(p
, tmp0
, tmp0
, get_element(t
, 2));
559 brw_AND(p
, brw_null_reg(), tmp0
, brw_imm_ud(0x1));
560 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
561 brw_IF(p
, BRW_EXECUTE_1
);
563 brw_clip_kill_thread(c
);
566 brw_set_default_predicate_control(p
, BRW_PREDICATE_NONE
);
568 /* some vertices are inside a plane, some are outside,need to clip */
569 brw_XOR(p
, t
, t1
, t2
);
570 brw_XOR(p
, t1
, t2
, t3
);
572 brw_AND(p
, t
, t
, brw_imm_ud(0x1));
573 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
574 get_element(t
, 0), brw_imm_ud(0));
575 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<5)));
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
, 1), brw_imm_ud(0));
579 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<3)));
580 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
581 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
582 get_element(t
, 2), brw_imm_ud(0));
583 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<1)));
584 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
586 /* test farz, xmax, ymax plane */
587 /* clip.xyz > clip.w */
588 brw_CMP(p
, t1
, BRW_CONDITIONAL_G
, v0
, get_element(v0
, 3));
589 brw_CMP(p
, t2
, BRW_CONDITIONAL_G
, v1
, get_element(v1
, 3));
590 brw_CMP(p
, t3
, BRW_CONDITIONAL_G
, v2
, get_element(v2
, 3));
592 /* All vertices are outside of a plane, rejected */
593 brw_AND(p
, t
, t1
, t2
);
594 brw_AND(p
, t
, t
, t3
);
595 brw_OR(p
, tmp0
, get_element(t
, 0), get_element(t
, 1));
596 brw_OR(p
, tmp0
, tmp0
, get_element(t
, 2));
597 brw_AND(p
, brw_null_reg(), tmp0
, brw_imm_ud(0x1));
598 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
599 brw_IF(p
, BRW_EXECUTE_1
);
601 brw_clip_kill_thread(c
);
604 brw_set_default_predicate_control(p
, BRW_PREDICATE_NONE
);
606 /* some vertices are inside a plane, some are outside,need to clip */
607 brw_XOR(p
, t
, t1
, t2
);
608 brw_XOR(p
, t1
, t2
, t3
);
610 brw_AND(p
, t
, t
, brw_imm_ud(0x1));
611 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
612 get_element(t
, 0), brw_imm_ud(0));
613 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<4)));
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
, 1), brw_imm_ud(0));
617 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<2)));
618 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
619 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
620 get_element(t
, 2), brw_imm_ud(0));
621 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<0)));
622 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
628 void brw_emit_tri_clip( struct brw_clip_compile
*c
)
630 struct brw_codegen
*p
= &c
->func
;
631 brw_clip_tri_alloc_regs(c
, 3 + c
->key
.nr_userclip
+ 6);
632 brw_clip_tri_init_vertices(c
);
633 brw_clip_init_clipmask(c
);
634 brw_clip_init_ff_sync(c
);
636 /* if -ve rhw workaround bit is set,
638 if (p
->devinfo
->has_negative_rhw_bug
) {
639 brw_AND(p
, brw_null_reg(), get_element_ud(c
->reg
.R0
, 2),
641 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
642 brw_IF(p
, BRW_EXECUTE_1
);
648 /* Can't push into do_clip_tri because with polygon (or quad)
649 * flatshading, need to apply the flatshade here because we don't
650 * respect the PV when converting to trifan for emit:
652 if (c
->key
.contains_flat_varying
)
653 brw_clip_tri_flat_shade(c
);
655 if ((c
->key
.clip_mode
== BRW_CLIPMODE_NORMAL
) ||
656 (c
->key
.clip_mode
== BRW_CLIPMODE_KERNEL_CLIP
))
659 maybe_do_clip_tri(c
);
661 brw_clip_tri_emit_polygon(c
);
663 /* Send an empty message to kill the thread:
665 brw_clip_kill_thread(c
);