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