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