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"
38 static void release_tmps( struct brw_clip_compile
*c
)
40 c
->last_tmp
= c
->first_tmp
;
44 void brw_clip_tri_alloc_regs( struct brw_clip_compile
*c
,
47 const struct gen_device_info
*devinfo
= c
->func
.devinfo
;
50 /* Register usage is static, precompute here:
52 c
->reg
.R0
= retype(brw_vec8_grf(i
, 0), BRW_REGISTER_TYPE_UD
); i
++;
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;
58 c
->prog_data
.curb_read_length
= (6 + c
->key
.nr_userclip
+ 1) / 2;
61 c
->prog_data
.curb_read_length
= 0;
64 /* Payload vertices plus space for more generated vertices:
66 for (j
= 0; j
< nr_verts
; j
++) {
67 c
->reg
.vertex
[j
] = brw_vec4_grf(i
, 0);
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.
75 for (j
= 0; j
< 3; j
++) {
76 GLuint delta
= brw_vue_slot_to_offset(c
->vue_map
.num_slots
);
78 brw_MOV(&c
->func
, byte_offset(c
->reg
.vertex
[j
], delta
), brw_imm_f(0));
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);
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);
93 c
->reg
.inlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
96 c
->reg
.outlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
99 c
->reg
.freelist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
102 if (!c
->key
.nr_userclip
) {
103 c
->reg
.fixed_planes
= brw_vec8_grf(i
, 0);
107 if (c
->key
.do_unfilled
) {
108 c
->reg
.dir
= brw_vec4_grf(i
, 0);
109 c
->reg
.offset
= brw_vec4_grf(i
, 4);
111 c
->reg
.tmp0
= brw_vec4_grf(i
, 0);
112 c
->reg
.tmp1
= brw_vec4_grf(i
, 4);
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
);
120 if (devinfo
->gen
== 5) {
121 c
->reg
.ff_sync
= retype(brw_vec1_grf(i
, 0), BRW_REGISTER_TYPE_UD
);
128 c
->prog_data
.urb_read_length
= c
->nr_regs
; /* ? */
129 c
->prog_data
.total_grf
= i
;
134 void brw_clip_tri_init_vertices( struct brw_clip_compile
*c
)
136 struct brw_codegen
*p
= &c
->func
;
137 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
139 /* Initial list of indices for incoming vertexes:
141 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
143 vec1(brw_null_reg()),
146 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE
));
148 /* XXX: Is there an easier way to do this? Need to reverse every
149 * second tristrip element: Can ignore sometimes?
151 brw_IF(p
, BRW_EXECUTE_1
);
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));
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));
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));
174 void brw_clip_tri_flat_shade( struct brw_clip_compile
*c
)
176 struct brw_codegen
*p
= &c
->func
;
177 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
179 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
181 vec1(brw_null_reg()),
184 brw_imm_ud(_3DPRIM_POLYGON
));
186 brw_IF(p
, BRW_EXECUTE_1
);
188 brw_clip_copy_flatshaded_attributes(c
, 1, 0);
189 brw_clip_copy_flatshaded_attributes(c
, 2, 0);
193 if (c
->key
.pv_first
) {
195 vec1(brw_null_reg()),
198 brw_imm_ud(_3DPRIM_TRIFAN
));
199 brw_IF(p
, BRW_EXECUTE_1
);
201 brw_clip_copy_flatshaded_attributes(c
, 0, 1);
202 brw_clip_copy_flatshaded_attributes(c
, 2, 1);
206 brw_clip_copy_flatshaded_attributes(c
, 1, 0);
207 brw_clip_copy_flatshaded_attributes(c
, 2, 0);
212 brw_clip_copy_flatshaded_attributes(c
, 0, 2);
213 brw_clip_copy_flatshaded_attributes(c
, 1, 2);
221 * Loads the clip distance for a vertex into `dst`, and ends with
222 * a comparison of it to zero with the condition `cond`.
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.
228 load_clip_distance(struct brw_clip_compile
*c
, struct brw_indirect vtx
,
229 struct brw_reg dst
, GLuint hpos_offset
, int cond
)
231 struct brw_codegen
*p
= &c
->func
;
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
);
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));
244 brw_MOV(p
, dst
, deref_4f(vtx
, hpos_offset
));
245 brw_DP4(p
, dst
, dst
, c
->reg
.plane_equation
);
249 brw_CMP(p
, brw_null_reg(), cond
, vec1(dst
), brw_imm_f(0.0f
));
253 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
255 void brw_clip_tri( struct brw_clip_compile
*c
)
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
)
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
));
275 brw_MOV(p
, get_addr_reg(freelist_ptr
), brw_address(c
->reg
.vertex
[3]) );
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.
280 brw_MOV(p
, c
->reg
.vertex_src_mask
, brw_imm_ud(0x3fc0));
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)));
286 brw_DO(p
, BRW_EXECUTE_1
);
288 /* if (planemask & 1)
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
);
293 brw_IF(p
, BRW_EXECUTE_1
);
295 /* vtxOut = freelist_ptr++
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
));
300 if (c
->key
.nr_userclip
)
301 brw_MOV(p
, c
->reg
.plane_equation
, deref_4f(plane_ptr
, 0));
303 brw_MOV(p
, c
->reg
.plane_equation
, deref_4b(plane_ptr
, 0));
305 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
306 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(0));
308 brw_DO(p
, BRW_EXECUTE_1
);
312 brw_MOV(p
, get_addr_reg(vtx
), deref_1uw(inlist_ptr
, 0));
314 load_clip_distance(c
, vtxPrev
, c
->reg
.dpPrev
, hpos_offset
, BRW_CONDITIONAL_L
);
316 brw_IF(p
, BRW_EXECUTE_1
);
318 load_clip_distance(c
, vtx
, c
->reg
.dp
, hpos_offset
, BRW_CONDITIONAL_GE
);
321 brw_IF(p
, BRW_EXECUTE_1
);
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
);
330 /* If (vtxOut == 0) vtxOut = vtxPrev
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
);
337 brw_clip_interp_vertex(c
, vtxOut
, vtxPrev
, vtx
, c
->reg
.t
, false);
339 /* *outlist_ptr++ = vtxOut;
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) );
353 /* *outlist_ptr++ = vtxPrev;
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));
360 load_clip_distance(c
, vtx
, c
->reg
.dp
, hpos_offset
, BRW_CONDITIONAL_L
);
363 brw_IF(p
, BRW_EXECUTE_1
);
365 /* Going out of bounds. Avoid division by zero as we
366 * know dp != dpPrev from DIFFERENT_SIGNS, above.
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
);
372 /* If (vtxOut == 0) vtxOut = vtx
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
);
379 brw_clip_interp_vertex(c
, vtxOut
, vtx
, vtxPrev
, c
->reg
.t
, true);
381 /* *outlist_ptr++ = vtxOut;
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) );
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)));
400 /* while (--loopcount != 0)
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
);
406 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
408 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
410 * inlist_ptr = &inlist[0]
411 * outlist_ptr = &outlist[0]
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
));
423 brw_ADD(p
, get_addr_reg(plane_ptr
), get_addr_reg(plane_ptr
), brw_clip_plane_stride(c
));
428 vec1(brw_null_reg()),
432 brw_set_default_predicate_control(p
, BRW_PREDICATE_NORMAL
);
434 /* && (planemask>>=1) != 0
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)));
442 brw_set_default_predicate_control(p
, BRW_PREDICATE_NONE
);
447 void brw_clip_tri_emit_polygon(struct brw_clip_compile
*c
)
449 struct brw_codegen
*p
= &c
->func
;
451 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
457 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_G
);
459 brw_IF(p
, BRW_EXECUTE_1
);
461 struct brw_indirect v0
= brw_indirect(0, 0);
462 struct brw_indirect vptr
= brw_indirect(1, 0);
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));
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
));
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));
474 brw_DO(p
, BRW_EXECUTE_1
);
476 brw_clip_emit_vue(c
, v0
, BRW_URB_WRITE_ALLOCATE_COMPLETE
,
477 (_3DPRIM_TRIFAN
<< URB_WRITE_PRIM_TYPE_SHIFT
));
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));
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
);
486 brw_inst_set_pred_control(p
->devinfo
, brw_last_inst
, BRW_PREDICATE_NORMAL
);
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
));
495 static void do_clip_tri( struct brw_clip_compile
*c
)
497 brw_clip_init_planes(c
);
503 static void maybe_do_clip_tri( struct brw_clip_compile
*c
)
505 struct brw_codegen
*p
= &c
->func
;
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
);
515 static void brw_clip_test( struct brw_clip_compile
*c
)
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
);
522 struct brw_reg v0
= get_tmp(c
);
523 struct brw_reg v1
= get_tmp(c
);
524 struct brw_reg v2
= get_tmp(c
);
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);
530 struct brw_codegen
*p
= &c
->func
;
531 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
533 GLuint hpos_offset
= brw_varying_to_offset(&c
->vue_map
,
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));
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)));
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
);
559 brw_clip_kill_thread(c
);
562 brw_set_default_predicate_control(p
, BRW_PREDICATE_NONE
);
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
);
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
);
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));
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
);
597 brw_clip_kill_thread(c
);
600 brw_set_default_predicate_control(p
, BRW_PREDICATE_NONE
);
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
);
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
);
624 void brw_emit_tri_clip( struct brw_clip_compile
*c
)
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
);
632 /* if -ve rhw workaround bit is set,
634 if (p
->devinfo
->has_negative_rhw_bug
) {
635 brw_AND(p
, brw_null_reg(), get_element_ud(c
->reg
.R0
, 2),
637 brw_inst_set_cond_modifier(p
->devinfo
, brw_last_inst
, BRW_CONDITIONAL_NZ
);
638 brw_IF(p
, BRW_EXECUTE_1
);
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:
648 if (c
->key
.contains_flat_varying
)
649 brw_clip_tri_flat_shade(c
);
651 if ((c
->key
.clip_mode
== BRW_CLIP_MODE_NORMAL
) ||
652 (c
->key
.clip_mode
== BRW_CLIP_MODE_KERNEL_CLIP
))
655 maybe_do_clip_tri(c
);
657 brw_clip_tri_emit_polygon(c
);
659 /* Send an empty message to kill the thread:
661 brw_clip_kill_thread(c
);