Merge remote branch 'origin/7.8'
[mesa.git] / src / mesa / drivers / dri / i965 / brw_clip_tri.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) 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 <keith@tungstengraphics.com>
30 */
31
32 #include "main/glheader.h"
33 #include "main/macros.h"
34 #include "main/enums.h"
35 #include "shader/program.h"
36
37 #include "intel_batchbuffer.h"
38
39 #include "brw_defines.h"
40 #include "brw_context.h"
41 #include "brw_eu.h"
42 #include "brw_clip.h"
43
44 static void release_tmps( struct brw_clip_compile *c )
45 {
46 c->last_tmp = c->first_tmp;
47 }
48
49
50 void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
51 GLuint nr_verts )
52 {
53 struct intel_context *intel = &c->func.brw->intel;
54 GLuint i = 0,j;
55
56 /* Register usage is static, precompute here:
57 */
58 c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
59
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;
63
64 c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
65 }
66 else
67 c->prog_data.curb_read_length = 0;
68
69
70 /* Payload vertices plus space for more generated vertices:
71 */
72 for (j = 0; j < nr_verts; j++) {
73 c->reg.vertex[j] = brw_vec4_grf(i, 0);
74 i += c->nr_regs;
75 }
76
77 if (c->nr_attrs & 1) {
78 for (j = 0; j < 3; j++) {
79 GLuint delta = c->nr_attrs*16 + 32;
80
81 if (intel->gen == 5)
82 delta = c->nr_attrs * 16 + 32 * 3;
83
84 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
85 }
86 }
87
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);
93 i++;
94
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);
97 i++;
98
99 c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
100 i++;
101
102 c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
103 i++;
104
105 c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
106 i++;
107
108 if (!c->key.nr_userclip) {
109 c->reg.fixed_planes = brw_vec8_grf(i, 0);
110 i++;
111 }
112
113 if (c->key.do_unfilled) {
114 c->reg.dir = brw_vec4_grf(i, 0);
115 c->reg.offset = brw_vec4_grf(i, 4);
116 i++;
117 c->reg.tmp0 = brw_vec4_grf(i, 0);
118 c->reg.tmp1 = brw_vec4_grf(i, 4);
119 i++;
120 }
121
122 if (intel->needs_ff_sync) {
123 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
124 i++;
125 }
126
127 c->first_tmp = i;
128 c->last_tmp = i;
129
130 c->prog_data.urb_read_length = c->nr_regs; /* ? */
131 c->prog_data.total_grf = i;
132 }
133
134
135
136 void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
137 {
138 struct brw_compile *p = &c->func;
139 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
140 struct brw_instruction *is_rev;
141
142 /* Initial list of indices for incoming vertexes:
143 */
144 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
145 brw_CMP(p,
146 vec1(brw_null_reg()),
147 BRW_CONDITIONAL_EQ,
148 tmp0,
149 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
150
151 /* XXX: Is there an easier way to do this? Need to reverse every
152 * second tristrip element: Can ignore sometimes?
153 */
154 is_rev = brw_IF(p, BRW_EXECUTE_1);
155 {
156 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
157 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
158 if (c->need_direction)
159 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
160 }
161 is_rev = brw_ELSE(p, is_rev);
162 {
163 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
164 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
165 if (c->need_direction)
166 brw_MOV(p, c->reg.dir, brw_imm_f(1));
167 }
168 brw_ENDIF(p, is_rev);
169
170 brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
171 brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
172 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
173 }
174
175
176
177 void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
178 {
179 struct brw_compile *p = &c->func;
180 struct brw_instruction *is_poly;
181 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
182
183 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
184 brw_CMP(p,
185 vec1(brw_null_reg()),
186 BRW_CONDITIONAL_EQ,
187 tmp0,
188 brw_imm_ud(_3DPRIM_POLYGON));
189
190 is_poly = brw_IF(p, BRW_EXECUTE_1);
191 {
192 brw_clip_copy_colors(c, 1, 0);
193 brw_clip_copy_colors(c, 2, 0);
194 }
195 is_poly = brw_ELSE(p, is_poly);
196 {
197 if (c->key.pv_first) {
198 brw_clip_copy_colors(c, 1, 0);
199 brw_clip_copy_colors(c, 2, 0);
200 }
201 else {
202 brw_clip_copy_colors(c, 0, 2);
203 brw_clip_copy_colors(c, 1, 2);
204 }
205 }
206 brw_ENDIF(p, is_poly);
207 }
208
209
210
211 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
212 */
213 void brw_clip_tri( struct brw_clip_compile *c )
214 {
215 struct brw_compile *p = &c->func;
216 struct brw_indirect vtx = brw_indirect(0, 0);
217 struct brw_indirect vtxPrev = brw_indirect(1, 0);
218 struct brw_indirect vtxOut = brw_indirect(2, 0);
219 struct brw_indirect plane_ptr = brw_indirect(3, 0);
220 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
221 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
222 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
223 struct brw_instruction *plane_loop;
224 struct brw_instruction *plane_active;
225 struct brw_instruction *vertex_loop;
226 struct brw_instruction *next_test;
227 struct brw_instruction *prev_test;
228
229 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
230 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
231 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
232 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
233
234 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
235
236 plane_loop = brw_DO(p, BRW_EXECUTE_1);
237 {
238 /* if (planemask & 1)
239 */
240 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
241 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
242
243 plane_active = brw_IF(p, BRW_EXECUTE_1);
244 {
245 /* vtxOut = freelist_ptr++
246 */
247 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
248 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
249
250 if (c->key.nr_userclip)
251 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
252 else
253 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
254
255 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
256 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
257
258 vertex_loop = brw_DO(p, BRW_EXECUTE_1);
259 {
260 /* vtx = *input_ptr;
261 */
262 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
263
264 /* IS_NEGATIVE(prev) */
265 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
266 brw_DP4(p, vec4(c->reg.dpPrev), deref_4f(vtxPrev, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
267 prev_test = brw_IF(p, BRW_EXECUTE_1);
268 {
269 /* IS_POSITIVE(next)
270 */
271 brw_set_conditionalmod(p, BRW_CONDITIONAL_GE);
272 brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
273 next_test = brw_IF(p, BRW_EXECUTE_1);
274 {
275
276 /* Coming back in.
277 */
278 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
279 brw_math_invert(p, c->reg.t, c->reg.t);
280 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
281
282 /* If (vtxOut == 0) vtxOut = vtxPrev
283 */
284 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
285 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
286 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
287
288 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, GL_FALSE);
289
290 /* *outlist_ptr++ = vtxOut;
291 * nr_verts++;
292 * vtxOut = 0;
293 */
294 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
295 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
296 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
297 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
298 }
299 brw_ENDIF(p, next_test);
300
301 }
302 prev_test = brw_ELSE(p, prev_test);
303 {
304 /* *outlist_ptr++ = vtxPrev;
305 * nr_verts++;
306 */
307 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
308 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
309 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
310
311 /* IS_NEGATIVE(next)
312 */
313 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
314 brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
315 next_test = brw_IF(p, BRW_EXECUTE_1);
316 {
317 /* Going out of bounds. Avoid division by zero as we
318 * know dp != dpPrev from DIFFERENT_SIGNS, above.
319 */
320 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
321 brw_math_invert(p, c->reg.t, c->reg.t);
322 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
323
324 /* If (vtxOut == 0) vtxOut = vtx
325 */
326 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
327 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
328 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
329
330 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, GL_TRUE);
331
332 /* *outlist_ptr++ = vtxOut;
333 * nr_verts++;
334 * vtxOut = 0;
335 */
336 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
337 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
338 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
339 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
340 }
341 brw_ENDIF(p, next_test);
342 }
343 brw_ENDIF(p, prev_test);
344
345 /* vtxPrev = vtx;
346 * inlist_ptr++;
347 */
348 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
349 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
350
351 /* while (--loopcount != 0)
352 */
353 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
354 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
355 }
356 brw_WHILE(p, vertex_loop);
357
358 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
359 * inlist = outlist
360 * inlist_ptr = &inlist[0]
361 * outlist_ptr = &outlist[0]
362 */
363 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
364 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
365 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
366 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
367 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
368 }
369 brw_ENDIF(p, plane_active);
370
371 /* plane_ptr++;
372 */
373 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
374
375 /* nr_verts >= 3
376 */
377 brw_CMP(p,
378 vec1(brw_null_reg()),
379 BRW_CONDITIONAL_GE,
380 c->reg.nr_verts,
381 brw_imm_ud(3));
382
383 /* && (planemask>>=1) != 0
384 */
385 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
386 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
387 }
388 brw_WHILE(p, plane_loop);
389 }
390
391
392
393 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
394 {
395 struct brw_compile *p = &c->func;
396 struct brw_instruction *loop, *if_insn;
397
398 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
399 */
400 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
401 brw_ADD(p,
402 c->reg.loopcount,
403 c->reg.nr_verts,
404 brw_imm_d(-2));
405
406 if_insn = brw_IF(p, BRW_EXECUTE_1);
407 {
408 struct brw_indirect v0 = brw_indirect(0, 0);
409 struct brw_indirect vptr = brw_indirect(1, 0);
410
411 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
412 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
413
414 brw_clip_emit_vue(c, v0, 1, 0, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_START));
415
416 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
417 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
418
419 loop = brw_DO(p, BRW_EXECUTE_1);
420 {
421 brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_TRIFAN << 2));
422
423 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
424 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
425
426 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
427 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
428 }
429 brw_WHILE(p, loop);
430
431 brw_clip_emit_vue(c, v0, 0, 1, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_END));
432 }
433 brw_ENDIF(p, if_insn);
434 }
435
436 static void do_clip_tri( struct brw_clip_compile *c )
437 {
438 brw_clip_init_planes(c);
439
440 brw_clip_tri(c);
441 }
442
443
444 static void maybe_do_clip_tri( struct brw_clip_compile *c )
445 {
446 struct brw_compile *p = &c->func;
447 struct brw_instruction *do_clip;
448
449 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
450 do_clip = brw_IF(p, BRW_EXECUTE_1);
451 {
452 do_clip_tri(c);
453 }
454 brw_ENDIF(p, do_clip);
455 }
456
457 static void brw_clip_test( struct brw_clip_compile *c )
458 {
459 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
460 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
461 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
462 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
463
464 struct brw_reg v0 = get_tmp(c);
465 struct brw_reg v1 = get_tmp(c);
466 struct brw_reg v2 = get_tmp(c);
467
468 struct brw_indirect vt0 = brw_indirect(0, 0);
469 struct brw_indirect vt1 = brw_indirect(1, 0);
470 struct brw_indirect vt2 = brw_indirect(2, 0);
471
472 struct brw_compile *p = &c->func;
473 struct brw_instruction *is_outside;
474 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
475
476 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
477 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
478 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
479 brw_MOV(p, v0, deref_4f(vt0, c->offset[VERT_RESULT_HPOS]));
480 brw_MOV(p, v1, deref_4f(vt1, c->offset[VERT_RESULT_HPOS]));
481 brw_MOV(p, v2, deref_4f(vt2, c->offset[VERT_RESULT_HPOS]));
482 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
483
484 /* test nearz, xmin, ymin plane */
485 /* clip.xyz < -clip.w */
486 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
487 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
488 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
489 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
490 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
491 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
492
493 /* All vertices are outside of a plane, rejected */
494 brw_AND(p, t, t1, t2);
495 brw_AND(p, t, t, t3);
496 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
497 brw_OR(p, tmp0, tmp0, get_element(t, 2));
498 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
499 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
500 is_outside = brw_IF(p, BRW_EXECUTE_1);
501 {
502 brw_clip_kill_thread(c);
503 }
504 brw_ENDIF(p, is_outside);
505 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
506
507 /* some vertices are inside a plane, some are outside,need to clip */
508 brw_XOR(p, t, t1, t2);
509 brw_XOR(p, t1, t2, t3);
510 brw_OR(p, t, t, t1);
511 brw_AND(p, t, t, brw_imm_ud(0x1));
512 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
513 get_element(t, 0), brw_imm_ud(0));
514 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
515 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
516 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
517 get_element(t, 1), brw_imm_ud(0));
518 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
519 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
520 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
521 get_element(t, 2), brw_imm_ud(0));
522 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
523 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
524
525 /* test farz, xmax, ymax plane */
526 /* clip.xyz > clip.w */
527 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
528 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
529 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
530 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
531 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
532 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
533
534 /* All vertices are outside of a plane, rejected */
535 brw_AND(p, t, t1, t2);
536 brw_AND(p, t, t, t3);
537 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
538 brw_OR(p, tmp0, tmp0, get_element(t, 2));
539 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
540 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
541 is_outside = brw_IF(p, BRW_EXECUTE_1);
542 {
543 brw_clip_kill_thread(c);
544 }
545 brw_ENDIF(p, is_outside);
546 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
547
548 /* some vertices are inside a plane, some are outside,need to clip */
549 brw_XOR(p, t, t1, t2);
550 brw_XOR(p, t1, t2, t3);
551 brw_OR(p, t, t, t1);
552 brw_AND(p, t, t, brw_imm_ud(0x1));
553 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
554 get_element(t, 0), brw_imm_ud(0));
555 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
556 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
557 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
558 get_element(t, 1), brw_imm_ud(0));
559 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
560 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
561 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
562 get_element(t, 2), brw_imm_ud(0));
563 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
564 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
565
566 release_tmps(c);
567 }
568
569
570 void brw_emit_tri_clip( struct brw_clip_compile *c )
571 {
572 struct brw_instruction *neg_rhw;
573 struct brw_compile *p = &c->func;
574 struct brw_context *brw = p->brw;
575 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
576 brw_clip_tri_init_vertices(c);
577 brw_clip_init_clipmask(c);
578 brw_clip_init_ff_sync(c);
579
580 /* if -ve rhw workaround bit is set,
581 do cliptest */
582 if (brw->has_negative_rhw_bug) {
583 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
584 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
585 brw_imm_ud(1<<20));
586 neg_rhw = brw_IF(p, BRW_EXECUTE_1);
587 {
588 brw_clip_test(c);
589 }
590 brw_ENDIF(p, neg_rhw);
591 }
592 /* Can't push into do_clip_tri because with polygon (or quad)
593 * flatshading, need to apply the flatshade here because we don't
594 * respect the PV when converting to trifan for emit:
595 */
596 if (c->key.do_flat_shading)
597 brw_clip_tri_flat_shade(c);
598
599 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
600 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
601 do_clip_tri(c);
602 else
603 maybe_do_clip_tri(c);
604
605 brw_clip_tri_emit_polygon(c);
606
607 /* Send an empty message to kill the thread:
608 */
609 brw_clip_kill_thread(c);
610 }