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/glheader.h"
33 #include "main/macros.h"
34 #include "main/enums.h"
35 #include "program/program.h"
37 #include "intel_batchbuffer.h"
39 #include "brw_defines.h"
40 #include "brw_context.h"
44 static void release_tmps( struct brw_clip_compile
*c
)
46 c
->last_tmp
= c
->first_tmp
;
50 void brw_clip_tri_alloc_regs( struct brw_clip_compile
*c
,
53 struct brw_context
*brw
= c
->func
.brw
;
56 /* Register usage is static, precompute here:
58 c
->reg
.R0
= retype(brw_vec8_grf(i
, 0), BRW_REGISTER_TYPE_UD
); i
++;
60 if (c
->key
.nr_userclip
) {
61 c
->reg
.fixed_planes
= brw_vec4_grf(i
, 0);
62 i
+= (6 + c
->key
.nr_userclip
+ 1) / 2;
64 c
->prog_data
.curb_read_length
= (6 + c
->key
.nr_userclip
+ 1) / 2;
67 c
->prog_data
.curb_read_length
= 0;
70 /* Payload vertices plus space for more generated vertices:
72 for (j
= 0; j
< nr_verts
; j
++) {
73 c
->reg
.vertex
[j
] = brw_vec4_grf(i
, 0);
77 if (c
->vue_map
.num_slots
% 2) {
78 /* The VUE has an odd number of slots so the last register is only half
79 * used. Fill the second half with zero.
81 for (j
= 0; j
< 3; j
++) {
82 GLuint delta
= brw_vue_slot_to_offset(c
->vue_map
.num_slots
);
84 brw_MOV(&c
->func
, byte_offset(c
->reg
.vertex
[j
], delta
), brw_imm_f(0));
88 c
->reg
.t
= brw_vec1_grf(i
, 0);
89 c
->reg
.loopcount
= retype(brw_vec1_grf(i
, 1), BRW_REGISTER_TYPE_D
);
90 c
->reg
.nr_verts
= retype(brw_vec1_grf(i
, 2), BRW_REGISTER_TYPE_UD
);
91 c
->reg
.planemask
= retype(brw_vec1_grf(i
, 3), BRW_REGISTER_TYPE_UD
);
92 c
->reg
.plane_equation
= brw_vec4_grf(i
, 4);
95 c
->reg
.dpPrev
= brw_vec1_grf(i
, 0); /* fixme - dp4 will clobber r.1,2,3 */
96 c
->reg
.dp
= brw_vec1_grf(i
, 4);
99 c
->reg
.inlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
102 c
->reg
.outlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
105 c
->reg
.freelist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
108 if (!c
->key
.nr_userclip
) {
109 c
->reg
.fixed_planes
= brw_vec8_grf(i
, 0);
113 if (c
->key
.do_unfilled
) {
114 c
->reg
.dir
= brw_vec4_grf(i
, 0);
115 c
->reg
.offset
= brw_vec4_grf(i
, 4);
117 c
->reg
.tmp0
= brw_vec4_grf(i
, 0);
118 c
->reg
.tmp1
= brw_vec4_grf(i
, 4);
122 c
->reg
.vertex_src_mask
= retype(brw_vec1_grf(i
, 0), BRW_REGISTER_TYPE_UD
);
123 c
->reg
.clipdistance_offset
= retype(brw_vec1_grf(i
, 1), BRW_REGISTER_TYPE_W
);
127 c
->reg
.ff_sync
= retype(brw_vec1_grf(i
, 0), BRW_REGISTER_TYPE_UD
);
134 c
->prog_data
.urb_read_length
= c
->nr_regs
; /* ? */
135 c
->prog_data
.total_grf
= i
;
140 void brw_clip_tri_init_vertices( struct brw_clip_compile
*c
)
142 struct brw_compile
*p
= &c
->func
;
143 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
145 /* Initial list of indices for incoming vertexes:
147 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
149 vec1(brw_null_reg()),
152 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE
));
154 /* XXX: Is there an easier way to do this? Need to reverse every
155 * second tristrip element: Can ignore sometimes?
157 brw_IF(p
, BRW_EXECUTE_1
);
159 brw_MOV(p
, get_element(c
->reg
.inlist
, 0), brw_address(c
->reg
.vertex
[1]) );
160 brw_MOV(p
, get_element(c
->reg
.inlist
, 1), brw_address(c
->reg
.vertex
[0]) );
161 if (c
->need_direction
)
162 brw_MOV(p
, c
->reg
.dir
, brw_imm_f(-1));
166 brw_MOV(p
, get_element(c
->reg
.inlist
, 0), brw_address(c
->reg
.vertex
[0]) );
167 brw_MOV(p
, get_element(c
->reg
.inlist
, 1), brw_address(c
->reg
.vertex
[1]) );
168 if (c
->need_direction
)
169 brw_MOV(p
, c
->reg
.dir
, brw_imm_f(1));
173 brw_MOV(p
, get_element(c
->reg
.inlist
, 2), brw_address(c
->reg
.vertex
[2]) );
174 brw_MOV(p
, brw_vec8_grf(c
->reg
.outlist
.nr
, 0), brw_imm_f(0));
175 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(3));
180 void brw_clip_tri_flat_shade( struct brw_clip_compile
*c
)
182 struct brw_compile
*p
= &c
->func
;
183 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
185 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
187 vec1(brw_null_reg()),
190 brw_imm_ud(_3DPRIM_POLYGON
));
192 brw_IF(p
, BRW_EXECUTE_1
);
194 brw_clip_copy_flatshaded_attributes(c
, 1, 0);
195 brw_clip_copy_flatshaded_attributes(c
, 2, 0);
199 if (c
->key
.pv_first
) {
201 vec1(brw_null_reg()),
204 brw_imm_ud(_3DPRIM_TRIFAN
));
205 brw_IF(p
, BRW_EXECUTE_1
);
207 brw_clip_copy_flatshaded_attributes(c
, 0, 1);
208 brw_clip_copy_flatshaded_attributes(c
, 2, 1);
212 brw_clip_copy_flatshaded_attributes(c
, 1, 0);
213 brw_clip_copy_flatshaded_attributes(c
, 2, 0);
218 brw_clip_copy_flatshaded_attributes(c
, 0, 2);
219 brw_clip_copy_flatshaded_attributes(c
, 1, 2);
227 * Loads the clip distance for a vertex into `dst`, and ends with
228 * a comparison of it to zero with the condition `cond`.
230 * - If using a fixed plane, the distance is dot(hpos, plane).
231 * - If using a user clip plane, the distance is directly available in the vertex.
234 load_clip_distance(struct brw_clip_compile
*c
, struct brw_indirect vtx
,
235 struct brw_reg dst
, GLuint hpos_offset
, int cond
)
237 struct brw_compile
*p
= &c
->func
;
240 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
241 brw_AND(p
, vec1(brw_null_reg()), c
->reg
.vertex_src_mask
, brw_imm_ud(1));
242 brw_IF(p
, BRW_EXECUTE_1
);
244 struct brw_indirect temp_ptr
= brw_indirect(7, 0);
245 brw_ADD(p
, get_addr_reg(temp_ptr
), get_addr_reg(vtx
), c
->reg
.clipdistance_offset
);
246 brw_MOV(p
, vec1(dst
), deref_1f(temp_ptr
, 0));
250 brw_MOV(p
, dst
, deref_4f(vtx
, hpos_offset
));
251 brw_DP4(p
, dst
, dst
, c
->reg
.plane_equation
);
255 brw_CMP(p
, brw_null_reg(), cond
, vec1(dst
), brw_imm_f(0.0f
));
259 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
261 void brw_clip_tri( struct brw_clip_compile
*c
)
263 struct brw_compile
*p
= &c
->func
;
264 struct brw_indirect vtx
= brw_indirect(0, 0);
265 struct brw_indirect vtxPrev
= brw_indirect(1, 0);
266 struct brw_indirect vtxOut
= brw_indirect(2, 0);
267 struct brw_indirect plane_ptr
= brw_indirect(3, 0);
268 struct brw_indirect inlist_ptr
= brw_indirect(4, 0);
269 struct brw_indirect outlist_ptr
= brw_indirect(5, 0);
270 struct brw_indirect freelist_ptr
= brw_indirect(6, 0);
271 GLuint hpos_offset
= brw_varying_to_offset(&c
->vue_map
, VARYING_SLOT_POS
);
272 GLint clipdist0_offset
= c
->key
.nr_userclip
273 ? brw_varying_to_offset(&c
->vue_map
, VARYING_SLOT_CLIP_DIST0
)
276 brw_MOV(p
, get_addr_reg(vtxPrev
), brw_address(c
->reg
.vertex
[2]) );
277 brw_MOV(p
, get_addr_reg(plane_ptr
), brw_clip_plane0_address(c
));
278 brw_MOV(p
, get_addr_reg(inlist_ptr
), brw_address(c
->reg
.inlist
));
279 brw_MOV(p
, get_addr_reg(outlist_ptr
), brw_address(c
->reg
.outlist
));
281 brw_MOV(p
, get_addr_reg(freelist_ptr
), brw_address(c
->reg
.vertex
[3]) );
283 /* Set the initial vertex source mask: The first 6 planes are the bounds
284 * of the view volume; the next 8 planes are the user clipping planes.
286 brw_MOV(p
, c
->reg
.vertex_src_mask
, brw_imm_ud(0x3fc0));
288 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
289 * We'll increment 6 times before we start hitting actual user clipping. */
290 brw_MOV(p
, c
->reg
.clipdistance_offset
, brw_imm_d(clipdist0_offset
- 6*sizeof(float)));
292 brw_DO(p
, BRW_EXECUTE_1
);
294 /* if (planemask & 1)
296 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
297 brw_AND(p
, vec1(brw_null_reg()), c
->reg
.planemask
, brw_imm_ud(1));
299 brw_IF(p
, BRW_EXECUTE_1
);
301 /* vtxOut = freelist_ptr++
303 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(freelist_ptr
) );
304 brw_ADD(p
, get_addr_reg(freelist_ptr
), get_addr_reg(freelist_ptr
), brw_imm_uw(c
->nr_regs
* REG_SIZE
));
306 if (c
->key
.nr_userclip
)
307 brw_MOV(p
, c
->reg
.plane_equation
, deref_4f(plane_ptr
, 0));
309 brw_MOV(p
, c
->reg
.plane_equation
, deref_4b(plane_ptr
, 0));
311 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
312 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(0));
314 brw_DO(p
, BRW_EXECUTE_1
);
318 brw_MOV(p
, get_addr_reg(vtx
), deref_1uw(inlist_ptr
, 0));
320 load_clip_distance(c
, vtxPrev
, c
->reg
.dpPrev
, hpos_offset
, BRW_CONDITIONAL_L
);
321 /* IS_NEGATIVE(prev) */
322 brw_IF(p
, BRW_EXECUTE_1
);
324 load_clip_distance(c
, vtx
, c
->reg
.dp
, hpos_offset
, BRW_CONDITIONAL_GE
);
327 brw_IF(p
, BRW_EXECUTE_1
);
332 brw_ADD(p
, c
->reg
.t
, c
->reg
.dpPrev
, negate(c
->reg
.dp
));
333 brw_math_invert(p
, c
->reg
.t
, c
->reg
.t
);
334 brw_MUL(p
, c
->reg
.t
, c
->reg
.t
, c
->reg
.dpPrev
);
336 /* If (vtxOut == 0) vtxOut = vtxPrev
338 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
339 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(vtxPrev
));
340 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
342 brw_clip_interp_vertex(c
, vtxOut
, vtxPrev
, vtx
, c
->reg
.t
, false);
344 /* *outlist_ptr++ = vtxOut;
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) );
358 /* *outlist_ptr++ = vtxPrev;
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));
365 load_clip_distance(c
, vtx
, c
->reg
.dp
, hpos_offset
, BRW_CONDITIONAL_L
);
368 brw_IF(p
, BRW_EXECUTE_1
);
370 /* Going out of bounds. Avoid division by zero as we
371 * know dp != dpPrev from DIFFERENT_SIGNS, above.
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
);
377 /* If (vtxOut == 0) vtxOut = vtx
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_last_inst
->header
.predicate_control
= 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_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
407 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
411 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
413 * inlist_ptr = &inlist[0]
414 * outlist_ptr = &outlist[0]
416 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_w(-2));
417 brw_MOV(p
, get_addr_reg(vtxPrev
), deref_1uw(outlist_ptr
, 0));
418 brw_MOV(p
, brw_vec8_grf(c
->reg
.inlist
.nr
, 0), brw_vec8_grf(c
->reg
.outlist
.nr
, 0));
419 brw_MOV(p
, get_addr_reg(inlist_ptr
), brw_address(c
->reg
.inlist
));
420 brw_MOV(p
, get_addr_reg(outlist_ptr
), brw_address(c
->reg
.outlist
));
426 brw_ADD(p
, get_addr_reg(plane_ptr
), get_addr_reg(plane_ptr
), brw_clip_plane_stride(c
));
431 vec1(brw_null_reg()),
435 brw_set_predicate_control(p
, BRW_PREDICATE_NORMAL
);
437 /* && (planemask>>=1) != 0
439 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
440 brw_SHR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud(1));
441 brw_SHR(p
, c
->reg
.vertex_src_mask
, c
->reg
.vertex_src_mask
, brw_imm_ud(1));
442 brw_ADD(p
, c
->reg
.clipdistance_offset
, c
->reg
.clipdistance_offset
, brw_imm_w(sizeof(float)));
449 void brw_clip_tri_emit_polygon(struct brw_clip_compile
*c
)
451 struct brw_compile
*p
= &c
->func
;
453 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
455 brw_set_conditionalmod(p
, BRW_CONDITIONAL_G
);
461 brw_IF(p
, BRW_EXECUTE_1
);
463 struct brw_indirect v0
= brw_indirect(0, 0);
464 struct brw_indirect vptr
= brw_indirect(1, 0);
466 brw_MOV(p
, get_addr_reg(vptr
), brw_address(c
->reg
.inlist
));
467 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
469 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_ALLOCATE_COMPLETE
,
470 ((_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
)
471 | URB_WRITE_PRIM_START
));
473 brw_ADD(p
, get_addr_reg(vptr
), get_addr_reg(vptr
), brw_imm_uw(2));
474 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
476 brw_DO(p
, BRW_EXECUTE_1
);
478 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_ALLOCATE_COMPLETE
,
479 (_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
));
481 brw_ADD(p
, get_addr_reg(vptr
), get_addr_reg(vptr
), brw_imm_uw(2));
482 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
484 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
485 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
489 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_EOT_COMPLETE
,
490 ((_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
)
491 | URB_WRITE_PRIM_END
));
496 static void do_clip_tri( struct brw_clip_compile
*c
)
498 brw_clip_init_planes(c
);
504 static void maybe_do_clip_tri( struct brw_clip_compile
*c
)
506 struct brw_compile
*p
= &c
->func
;
508 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ
, c
->reg
.planemask
, brw_imm_ud(0));
509 brw_IF(p
, BRW_EXECUTE_1
);
516 static void brw_clip_test( struct brw_clip_compile
*c
)
518 struct brw_reg t
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
519 struct brw_reg t1
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
520 struct brw_reg t2
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
521 struct brw_reg t3
= retype(get_tmp(c
), BRW_REGISTER_TYPE_UD
);
523 struct brw_reg v0
= get_tmp(c
);
524 struct brw_reg v1
= get_tmp(c
);
525 struct brw_reg v2
= get_tmp(c
);
527 struct brw_indirect vt0
= brw_indirect(0, 0);
528 struct brw_indirect vt1
= brw_indirect(1, 0);
529 struct brw_indirect vt2
= brw_indirect(2, 0);
531 struct brw_compile
*p
= &c
->func
;
532 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
534 GLuint hpos_offset
= brw_varying_to_offset(&c
->vue_map
,
537 brw_MOV(p
, get_addr_reg(vt0
), brw_address(c
->reg
.vertex
[0]));
538 brw_MOV(p
, get_addr_reg(vt1
), brw_address(c
->reg
.vertex
[1]));
539 brw_MOV(p
, get_addr_reg(vt2
), brw_address(c
->reg
.vertex
[2]));
540 brw_MOV(p
, v0
, deref_4f(vt0
, hpos_offset
));
541 brw_MOV(p
, v1
, deref_4f(vt1
, hpos_offset
));
542 brw_MOV(p
, v2
, deref_4f(vt2
, hpos_offset
));
543 brw_AND(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud(~0x3f));
545 /* test nearz, xmin, ymin plane */
546 /* clip.xyz < -clip.w */
547 brw_CMP(p
, t1
, BRW_CONDITIONAL_L
, v0
, negate(get_element(v0
, 3)));
548 brw_CMP(p
, t2
, BRW_CONDITIONAL_L
, v1
, negate(get_element(v1
, 3)));
549 brw_CMP(p
, t3
, BRW_CONDITIONAL_L
, v2
, negate(get_element(v2
, 3)));
551 /* All vertices are outside of a plane, rejected */
552 brw_AND(p
, t
, t1
, t2
);
553 brw_AND(p
, t
, t
, t3
);
554 brw_OR(p
, tmp0
, get_element(t
, 0), get_element(t
, 1));
555 brw_OR(p
, tmp0
, tmp0
, get_element(t
, 2));
556 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
557 brw_AND(p
, brw_null_reg(), tmp0
, brw_imm_ud(0x1));
558 brw_IF(p
, BRW_EXECUTE_1
);
560 brw_clip_kill_thread(c
);
563 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
565 /* some vertices are inside a plane, some are outside,need to clip */
566 brw_XOR(p
, t
, t1
, t2
);
567 brw_XOR(p
, t1
, t2
, t3
);
569 brw_AND(p
, t
, t
, brw_imm_ud(0x1));
570 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
571 get_element(t
, 0), brw_imm_ud(0));
572 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<5)));
573 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
574 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
575 get_element(t
, 1), brw_imm_ud(0));
576 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<3)));
577 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
578 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
579 get_element(t
, 2), brw_imm_ud(0));
580 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<1)));
581 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
583 /* test farz, xmax, ymax plane */
584 /* clip.xyz > clip.w */
585 brw_CMP(p
, t1
, BRW_CONDITIONAL_G
, v0
, get_element(v0
, 3));
586 brw_CMP(p
, t2
, BRW_CONDITIONAL_G
, v1
, get_element(v1
, 3));
587 brw_CMP(p
, t3
, BRW_CONDITIONAL_G
, v2
, get_element(v2
, 3));
589 /* All vertices are outside of a plane, rejected */
590 brw_AND(p
, t
, t1
, t2
);
591 brw_AND(p
, t
, t
, t3
);
592 brw_OR(p
, tmp0
, get_element(t
, 0), get_element(t
, 1));
593 brw_OR(p
, tmp0
, tmp0
, get_element(t
, 2));
594 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
595 brw_AND(p
, brw_null_reg(), tmp0
, brw_imm_ud(0x1));
596 brw_IF(p
, BRW_EXECUTE_1
);
598 brw_clip_kill_thread(c
);
601 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
603 /* some vertices are inside a plane, some are outside,need to clip */
604 brw_XOR(p
, t
, t1
, t2
);
605 brw_XOR(p
, t1
, t2
, t3
);
607 brw_AND(p
, t
, t
, brw_imm_ud(0x1));
608 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
609 get_element(t
, 0), brw_imm_ud(0));
610 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<4)));
611 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
612 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
613 get_element(t
, 1), brw_imm_ud(0));
614 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<2)));
615 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
616 brw_CMP(p
, brw_null_reg(), BRW_CONDITIONAL_NZ
,
617 get_element(t
, 2), brw_imm_ud(0));
618 brw_OR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud((1<<0)));
619 brw_last_inst
->header
.predicate_control
= BRW_PREDICATE_NORMAL
;
625 void brw_emit_tri_clip( struct brw_clip_compile
*c
)
627 struct brw_compile
*p
= &c
->func
;
628 struct brw_context
*brw
= p
->brw
;
629 brw_clip_tri_alloc_regs(c
, 3 + c
->key
.nr_userclip
+ 6);
630 brw_clip_tri_init_vertices(c
);
631 brw_clip_init_clipmask(c
);
632 brw_clip_init_ff_sync(c
);
634 /* if -ve rhw workaround bit is set,
636 if (brw
->has_negative_rhw_bug
) {
637 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
638 brw_AND(p
, brw_null_reg(), get_element_ud(c
->reg
.R0
, 2),
640 brw_IF(p
, BRW_EXECUTE_1
);
646 /* Can't push into do_clip_tri because with polygon (or quad)
647 * flatshading, need to apply the flatshade here because we don't
648 * respect the PV when converting to trifan for emit:
650 if (c
->has_flat_shading
)
651 brw_clip_tri_flat_shade(c
);
653 if ((c
->key
.clip_mode
== BRW_CLIPMODE_NORMAL
) ||
654 (c
->key
.clip_mode
== BRW_CLIPMODE_KERNEL_CLIP
))
657 maybe_do_clip_tri(c
);
659 brw_clip_tri_emit_polygon(c
);
661 /* Send an empty message to kill the thread:
663 brw_clip_kill_thread(c
);