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