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