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