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