brw_clip_tri.c revision ecadb51bbcb972a79f3ed79e65a7986b9396e757
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
45static void release_tmps( struct brw_clip_compile *c )
46{
47   c->last_tmp = c->first_tmp;
48}
49
50
51void 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
127void 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
168void 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 */
198void 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
378void 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
421static 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
429static 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
442static 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
459    brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
460    brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
461    brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
462    brw_MOV(p, v0, deref_4f(vt0, c->offset[VERT_RESULT_HPOS]));
463    brw_MOV(p, v1, deref_4f(vt1, c->offset[VERT_RESULT_HPOS]));
464    brw_MOV(p, v2, deref_4f(vt2, c->offset[VERT_RESULT_HPOS]));
465
466    /* test nearz, xmin, ymin plane */
467    brw_CMP(p, t1, BRW_CONDITIONAL_LE, negate(v0), get_element(v0, 3));
468    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
469    brw_CMP(p, t2, BRW_CONDITIONAL_LE, negate(v1), get_element(v1, 3));
470    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
471    brw_CMP(p, t3, BRW_CONDITIONAL_LE, negate(v2), get_element(v2, 3));
472    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
473    brw_XOR(p, t, t1, t2);
474    brw_XOR(p, t1, t2, t3);
475    brw_OR(p, t, t, t1);
476
477    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
478	    get_element(t, 0), brw_imm_ud(0));
479    brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
480    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
481    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
482	    get_element(t, 1), brw_imm_ud(0));
483    brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
484    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
485    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
486	    get_element(t, 2), brw_imm_ud(0));
487    brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
488    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
489
490    /* test farz, xmax, ymax plane */
491    brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, get_element(v0, 3));
492    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
493    brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, get_element(v1, 3));
494    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
495    brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, get_element(v2, 3));
496    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
497
498    brw_XOR(p, t, t1, t2);
499    brw_XOR(p, t1, t2, t3);
500    brw_OR(p, t, t, t1);
501
502    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
503	    get_element(t, 0), brw_imm_ud(0));
504    brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
505    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
506    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
507	    get_element(t, 1), brw_imm_ud(0));
508    brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
509    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
510    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
511	    get_element(t, 2), brw_imm_ud(0));
512    brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
513    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
514
515    release_tmps(c);
516}
517
518
519void brw_emit_tri_clip( struct brw_clip_compile *c )
520{
521   struct brw_instruction *neg_rhw;
522   struct brw_compile *p = &c->func;
523   brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
524   brw_clip_tri_init_vertices(c);
525   brw_clip_init_clipmask(c);
526
527   /* if -ve rhw workaround bit is set,
528      do cliptest */
529   if (!(BRW_IS_GM45(p->brw) || BRW_IS_G4X(p->brw))) {
530      brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
531      brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
532              brw_imm_ud(1<<20));
533      neg_rhw = brw_IF(p, BRW_EXECUTE_1);
534      {
535         brw_clip_test(c);
536      }
537      brw_ENDIF(p, neg_rhw);
538   }
539   /* Can't push into do_clip_tri because with polygon (or quad)
540    * flatshading, need to apply the flatshade here because we don't
541    * respect the PV when converting to trifan for emit:
542    */
543   if (c->key.do_flat_shading)
544      brw_clip_tri_flat_shade(c);
545
546   if (c->key.clip_mode == BRW_CLIPMODE_NORMAL)
547      do_clip_tri(c);
548   else
549      maybe_do_clip_tri(c);
550
551   brw_clip_tri_emit_polygon(c);
552
553   /* Send an empty message to kill the thread:
554    */
555   brw_clip_kill_thread(c);
556}
557