1b8e80941Smrg/*
2b8e80941Smrg Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3b8e80941Smrg Intel funded Tungsten Graphics to
4b8e80941Smrg develop this 3D driver.
5b8e80941Smrg
6b8e80941Smrg Permission is hereby granted, free of charge, to any person obtaining
7b8e80941Smrg a copy of this software and associated documentation files (the
8b8e80941Smrg "Software"), to deal in the Software without restriction, including
9b8e80941Smrg without limitation the rights to use, copy, modify, merge, publish,
10b8e80941Smrg distribute, sublicense, and/or sell copies of the Software, and to
11b8e80941Smrg permit persons to whom the Software is furnished to do so, subject to
12b8e80941Smrg the following conditions:
13b8e80941Smrg
14b8e80941Smrg The above copyright notice and this permission notice (including the
15b8e80941Smrg next paragraph) shall be included in all copies or substantial
16b8e80941Smrg portions of the Software.
17b8e80941Smrg
18b8e80941Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19b8e80941Smrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20b8e80941Smrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21b8e80941Smrg IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22b8e80941Smrg LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23b8e80941Smrg OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24b8e80941Smrg WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25b8e80941Smrg
26b8e80941Smrg **********************************************************************/
27b8e80941Smrg /*
28b8e80941Smrg  * Authors:
29b8e80941Smrg  *   Keith Whitwell <keithw@vmware.com>
30b8e80941Smrg  */
31b8e80941Smrg
32b8e80941Smrg#include "main/macros.h"
33b8e80941Smrg#include "main/enums.h"
34b8e80941Smrg#include "program/program.h"
35b8e80941Smrg
36b8e80941Smrg#include "brw_clip.h"
37b8e80941Smrg
38b8e80941Smrg
39b8e80941Smrg/* This is performed against the original triangles, so no indirection
40b8e80941Smrg * required:
41b8e80941SmrgBZZZT!
42b8e80941Smrg */
43b8e80941Smrgstatic void compute_tri_direction( struct brw_clip_compile *c )
44b8e80941Smrg{
45b8e80941Smrg   struct brw_codegen *p = &c->func;
46b8e80941Smrg   struct brw_reg e = c->reg.tmp0;
47b8e80941Smrg   struct brw_reg f = c->reg.tmp1;
48b8e80941Smrg   GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
49b8e80941Smrg   struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset);
50b8e80941Smrg   struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset);
51b8e80941Smrg   struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset);
52b8e80941Smrg
53b8e80941Smrg
54b8e80941Smrg   struct brw_reg v0n = get_tmp(c);
55b8e80941Smrg   struct brw_reg v1n = get_tmp(c);
56b8e80941Smrg   struct brw_reg v2n = get_tmp(c);
57b8e80941Smrg
58b8e80941Smrg   /* Convert to NDC.
59b8e80941Smrg    * NOTE: We can't modify the original vertex coordinates,
60b8e80941Smrg    * as it may impact further operations.
61b8e80941Smrg    * So, we have to keep normalized coordinates in temp registers.
62b8e80941Smrg    *
63b8e80941Smrg    * TBD-KC
64b8e80941Smrg    * Try to optimize unnecessary MOV's.
65b8e80941Smrg    */
66b8e80941Smrg   brw_MOV(p, v0n, v0);
67b8e80941Smrg   brw_MOV(p, v1n, v1);
68b8e80941Smrg   brw_MOV(p, v2n, v2);
69b8e80941Smrg
70b8e80941Smrg   brw_clip_project_position(c, v0n);
71b8e80941Smrg   brw_clip_project_position(c, v1n);
72b8e80941Smrg   brw_clip_project_position(c, v2n);
73b8e80941Smrg
74b8e80941Smrg   /* Calculate the vectors of two edges of the triangle:
75b8e80941Smrg    */
76b8e80941Smrg   brw_ADD(p, e, v0n, negate(v2n));
77b8e80941Smrg   brw_ADD(p, f, v1n, negate(v2n));
78b8e80941Smrg
79b8e80941Smrg   /* Take their crossproduct:
80b8e80941Smrg    */
81b8e80941Smrg   brw_set_default_access_mode(p, BRW_ALIGN_16);
82b8e80941Smrg   brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW),
83b8e80941Smrg           brw_swizzle(f, BRW_SWIZZLE_ZXYW));
84b8e80941Smrg   brw_MAC(p, vec4(e),  negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)),
85b8e80941Smrg           brw_swizzle(f, BRW_SWIZZLE_YZXW));
86b8e80941Smrg   brw_set_default_access_mode(p, BRW_ALIGN_1);
87b8e80941Smrg
88b8e80941Smrg   brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
89b8e80941Smrg}
90b8e80941Smrg
91b8e80941Smrg
92b8e80941Smrgstatic void cull_direction( struct brw_clip_compile *c )
93b8e80941Smrg{
94b8e80941Smrg   struct brw_codegen *p = &c->func;
95b8e80941Smrg   GLuint conditional;
96b8e80941Smrg
97b8e80941Smrg   assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
98b8e80941Smrg	     c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL));
99b8e80941Smrg
100b8e80941Smrg   if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL)
101b8e80941Smrg      conditional = BRW_CONDITIONAL_GE;
102b8e80941Smrg   else
103b8e80941Smrg      conditional = BRW_CONDITIONAL_L;
104b8e80941Smrg
105b8e80941Smrg   brw_CMP(p,
106b8e80941Smrg	   vec1(brw_null_reg()),
107b8e80941Smrg	   conditional,
108b8e80941Smrg	   get_element(c->reg.dir, 2),
109b8e80941Smrg	   brw_imm_f(0));
110b8e80941Smrg
111b8e80941Smrg   brw_IF(p, BRW_EXECUTE_1);
112b8e80941Smrg   {
113b8e80941Smrg      brw_clip_kill_thread(c);
114b8e80941Smrg   }
115b8e80941Smrg   brw_ENDIF(p);
116b8e80941Smrg}
117b8e80941Smrg
118b8e80941Smrg
119b8e80941Smrg
120b8e80941Smrgstatic void copy_bfc( struct brw_clip_compile *c )
121b8e80941Smrg{
122b8e80941Smrg   struct brw_codegen *p = &c->func;
123b8e80941Smrg   GLuint conditional;
124b8e80941Smrg
125b8e80941Smrg   /* Do we have any colors to copy?
126b8e80941Smrg    */
127b8e80941Smrg   if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
128b8e80941Smrg         brw_clip_have_varying(c, VARYING_SLOT_BFC0)) &&
129b8e80941Smrg       !(brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
130b8e80941Smrg         brw_clip_have_varying(c, VARYING_SLOT_BFC1)))
131b8e80941Smrg      return;
132b8e80941Smrg
133b8e80941Smrg   /* In some weird degenerate cases we can end up testing the
134b8e80941Smrg    * direction twice, once for culling and once for bfc copying.  Oh
135b8e80941Smrg    * well, that's what you get for setting weird GL state.
136b8e80941Smrg    */
137b8e80941Smrg   if (c->key.copy_bfc_ccw)
138b8e80941Smrg      conditional = BRW_CONDITIONAL_GE;
139b8e80941Smrg   else
140b8e80941Smrg      conditional = BRW_CONDITIONAL_L;
141b8e80941Smrg
142b8e80941Smrg   brw_CMP(p,
143b8e80941Smrg	   vec1(brw_null_reg()),
144b8e80941Smrg	   conditional,
145b8e80941Smrg	   get_element(c->reg.dir, 2),
146b8e80941Smrg	   brw_imm_f(0));
147b8e80941Smrg
148b8e80941Smrg   brw_IF(p, BRW_EXECUTE_1);
149b8e80941Smrg   {
150b8e80941Smrg      GLuint i;
151b8e80941Smrg
152b8e80941Smrg      for (i = 0; i < 3; i++) {
153b8e80941Smrg	 if (brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
154b8e80941Smrg             brw_clip_have_varying(c, VARYING_SLOT_BFC0))
155b8e80941Smrg	    brw_MOV(p,
156b8e80941Smrg		    byte_offset(c->reg.vertex[i],
157b8e80941Smrg                                brw_varying_to_offset(&c->vue_map,
158b8e80941Smrg                                                      VARYING_SLOT_COL0)),
159b8e80941Smrg		    byte_offset(c->reg.vertex[i],
160b8e80941Smrg                                brw_varying_to_offset(&c->vue_map,
161b8e80941Smrg                                                      VARYING_SLOT_BFC0)));
162b8e80941Smrg
163b8e80941Smrg	 if (brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
164b8e80941Smrg             brw_clip_have_varying(c, VARYING_SLOT_BFC1))
165b8e80941Smrg	    brw_MOV(p,
166b8e80941Smrg		    byte_offset(c->reg.vertex[i],
167b8e80941Smrg                                brw_varying_to_offset(&c->vue_map,
168b8e80941Smrg                                                      VARYING_SLOT_COL1)),
169b8e80941Smrg		    byte_offset(c->reg.vertex[i],
170b8e80941Smrg                                brw_varying_to_offset(&c->vue_map,
171b8e80941Smrg                                                      VARYING_SLOT_BFC1)));
172b8e80941Smrg      }
173b8e80941Smrg   }
174b8e80941Smrg   brw_ENDIF(p);
175b8e80941Smrg}
176b8e80941Smrg
177b8e80941Smrg
178b8e80941Smrg
179b8e80941Smrg
180b8e80941Smrg/*
181b8e80941Smrg  GLfloat iz	= 1.0 / dir.z;
182b8e80941Smrg  GLfloat ac	= dir.x * iz;
183b8e80941Smrg  GLfloat bc	= dir.y * iz;
184b8e80941Smrg  offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
185b8e80941Smrg  offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
186b8e80941Smrg  if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) {
187b8e80941Smrg    if (ctx->Polygon.OffsetClamp < 0)
188b8e80941Smrg      offset = MAX2( offset, ctx->Polygon.OffsetClamp );
189b8e80941Smrg    else
190b8e80941Smrg      offset = MIN2( offset, ctx->Polygon.OffsetClamp );
191b8e80941Smrg  }
192b8e80941Smrg  offset *= MRD;
193b8e80941Smrg*/
194b8e80941Smrgstatic void compute_offset( struct brw_clip_compile *c )
195b8e80941Smrg{
196b8e80941Smrg   struct brw_codegen *p = &c->func;
197b8e80941Smrg   struct brw_reg off = c->reg.offset;
198b8e80941Smrg   struct brw_reg dir = c->reg.dir;
199b8e80941Smrg
200b8e80941Smrg   brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
201b8e80941Smrg   brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2));
202b8e80941Smrg
203b8e80941Smrg   brw_CMP(p,
204b8e80941Smrg	   vec1(brw_null_reg()),
205b8e80941Smrg	   BRW_CONDITIONAL_GE,
206b8e80941Smrg	   brw_abs(get_element(off, 0)),
207b8e80941Smrg	   brw_abs(get_element(off, 1)));
208b8e80941Smrg
209b8e80941Smrg   brw_SEL(p, vec1(off),
210b8e80941Smrg           brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
211b8e80941Smrg   brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
212b8e80941Smrg
213b8e80941Smrg   brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor));
214b8e80941Smrg   brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units));
215b8e80941Smrg   if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) {
216b8e80941Smrg      brw_CMP(p,
217b8e80941Smrg              vec1(brw_null_reg()),
218b8e80941Smrg              c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L,
219b8e80941Smrg              vec1(off),
220b8e80941Smrg              brw_imm_f(c->key.offset_clamp));
221b8e80941Smrg      brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp));
222b8e80941Smrg   }
223b8e80941Smrg}
224b8e80941Smrg
225b8e80941Smrg
226b8e80941Smrgstatic void merge_edgeflags( struct brw_clip_compile *c )
227b8e80941Smrg{
228b8e80941Smrg   struct brw_codegen *p = &c->func;
229b8e80941Smrg   struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
230b8e80941Smrg
231b8e80941Smrg   brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
232b8e80941Smrg   brw_CMP(p,
233b8e80941Smrg	   vec1(brw_null_reg()),
234b8e80941Smrg	   BRW_CONDITIONAL_EQ,
235b8e80941Smrg	   tmp0,
236b8e80941Smrg	   brw_imm_ud(_3DPRIM_POLYGON));
237b8e80941Smrg
238b8e80941Smrg   /* Get away with using reg.vertex because we know that this is not
239b8e80941Smrg    * a _3DPRIM_TRISTRIP_REVERSE:
240b8e80941Smrg    */
241b8e80941Smrg   brw_IF(p, BRW_EXECUTE_1);
242b8e80941Smrg   {
243b8e80941Smrg      brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
244b8e80941Smrg      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
245b8e80941Smrg      brw_MOV(p, byte_offset(c->reg.vertex[0],
246b8e80941Smrg                             brw_varying_to_offset(&c->vue_map,
247b8e80941Smrg                                                   VARYING_SLOT_EDGE)),
248b8e80941Smrg              brw_imm_f(0));
249b8e80941Smrg      brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
250b8e80941Smrg
251b8e80941Smrg      brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
252b8e80941Smrg      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
253b8e80941Smrg      brw_MOV(p, byte_offset(c->reg.vertex[2],
254b8e80941Smrg                             brw_varying_to_offset(&c->vue_map,
255b8e80941Smrg                                                   VARYING_SLOT_EDGE)),
256b8e80941Smrg              brw_imm_f(0));
257b8e80941Smrg      brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
258b8e80941Smrg   }
259b8e80941Smrg   brw_ENDIF(p);
260b8e80941Smrg}
261b8e80941Smrg
262b8e80941Smrg
263b8e80941Smrg
264b8e80941Smrgstatic void apply_one_offset( struct brw_clip_compile *c,
265b8e80941Smrg			  struct brw_indirect vert )
266b8e80941Smrg{
267b8e80941Smrg   struct brw_codegen *p = &c->func;
268b8e80941Smrg   GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,
269b8e80941Smrg                                             BRW_VARYING_SLOT_NDC);
270b8e80941Smrg   struct brw_reg z = deref_1f(vert, ndc_offset +
271b8e80941Smrg			       2 * type_sz(BRW_REGISTER_TYPE_F));
272b8e80941Smrg
273b8e80941Smrg   brw_ADD(p, z, z, vec1(c->reg.offset));
274b8e80941Smrg}
275b8e80941Smrg
276b8e80941Smrg
277b8e80941Smrg
278b8e80941Smrg/***********************************************************************
279b8e80941Smrg * Output clipped polygon as an unfilled primitive:
280b8e80941Smrg */
281b8e80941Smrgstatic void emit_lines(struct brw_clip_compile *c,
282b8e80941Smrg		       bool do_offset)
283b8e80941Smrg{
284b8e80941Smrg   struct brw_codegen *p = &c->func;
285b8e80941Smrg   struct brw_indirect v0 = brw_indirect(0, 0);
286b8e80941Smrg   struct brw_indirect v1 = brw_indirect(1, 0);
287b8e80941Smrg   struct brw_indirect v0ptr = brw_indirect(2, 0);
288b8e80941Smrg   struct brw_indirect v1ptr = brw_indirect(3, 0);
289b8e80941Smrg
290b8e80941Smrg   /* Need a separate loop for offset:
291b8e80941Smrg    */
292b8e80941Smrg   if (do_offset) {
293b8e80941Smrg      brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
294b8e80941Smrg      brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
295b8e80941Smrg
296b8e80941Smrg      brw_DO(p, BRW_EXECUTE_1);
297b8e80941Smrg      {
298b8e80941Smrg	 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
299b8e80941Smrg	 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
300b8e80941Smrg
301b8e80941Smrg	 apply_one_offset(c, v0);
302b8e80941Smrg
303b8e80941Smrg	 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
304b8e80941Smrg         brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
305b8e80941Smrg      }
306b8e80941Smrg      brw_WHILE(p);
307b8e80941Smrg      brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
308b8e80941Smrg   }
309b8e80941Smrg
310b8e80941Smrg   /* v1ptr = &inlist[nr_verts]
311b8e80941Smrg    * *v1ptr = v0
312b8e80941Smrg    */
313b8e80941Smrg   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
314b8e80941Smrg   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
315b8e80941Smrg   brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
316b8e80941Smrg   brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
317b8e80941Smrg   brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
318b8e80941Smrg
319b8e80941Smrg   brw_DO(p, BRW_EXECUTE_1);
320b8e80941Smrg   {
321b8e80941Smrg      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
322b8e80941Smrg      brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
323b8e80941Smrg      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
324b8e80941Smrg
325b8e80941Smrg      /* draw edge if edgeflag != 0 */
326b8e80941Smrg      brw_CMP(p,
327b8e80941Smrg	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
328b8e80941Smrg	      deref_1f(v0, brw_varying_to_offset(&c->vue_map,
329b8e80941Smrg                                                 VARYING_SLOT_EDGE)),
330b8e80941Smrg	      brw_imm_f(0));
331b8e80941Smrg      brw_IF(p, BRW_EXECUTE_1);
332b8e80941Smrg      {
333b8e80941Smrg	 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
334b8e80941Smrg                           (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
335b8e80941Smrg                           | URB_WRITE_PRIM_START);
336b8e80941Smrg	 brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE,
337b8e80941Smrg                           (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
338b8e80941Smrg                           | URB_WRITE_PRIM_END);
339b8e80941Smrg      }
340b8e80941Smrg      brw_ENDIF(p);
341b8e80941Smrg
342b8e80941Smrg      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
343b8e80941Smrg      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
344b8e80941Smrg   }
345b8e80941Smrg   brw_WHILE(p);
346b8e80941Smrg   brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
347b8e80941Smrg}
348b8e80941Smrg
349b8e80941Smrg
350b8e80941Smrg
351b8e80941Smrgstatic void emit_points(struct brw_clip_compile *c,
352b8e80941Smrg			bool do_offset )
353b8e80941Smrg{
354b8e80941Smrg   struct brw_codegen *p = &c->func;
355b8e80941Smrg
356b8e80941Smrg   struct brw_indirect v0 = brw_indirect(0, 0);
357b8e80941Smrg   struct brw_indirect v0ptr = brw_indirect(2, 0);
358b8e80941Smrg
359b8e80941Smrg   brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
360b8e80941Smrg   brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
361b8e80941Smrg
362b8e80941Smrg   brw_DO(p, BRW_EXECUTE_1);
363b8e80941Smrg   {
364b8e80941Smrg      brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
365b8e80941Smrg      brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
366b8e80941Smrg
367b8e80941Smrg      /* draw if edgeflag != 0
368b8e80941Smrg       */
369b8e80941Smrg      brw_CMP(p,
370b8e80941Smrg	      vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
371b8e80941Smrg	      deref_1f(v0, brw_varying_to_offset(&c->vue_map,
372b8e80941Smrg                                                 VARYING_SLOT_EDGE)),
373b8e80941Smrg	      brw_imm_f(0));
374b8e80941Smrg      brw_IF(p, BRW_EXECUTE_1);
375b8e80941Smrg      {
376b8e80941Smrg	 if (do_offset)
377b8e80941Smrg	    apply_one_offset(c, v0);
378b8e80941Smrg
379b8e80941Smrg	 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
380b8e80941Smrg                           (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)
381b8e80941Smrg                           | URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
382b8e80941Smrg      }
383b8e80941Smrg      brw_ENDIF(p);
384b8e80941Smrg
385b8e80941Smrg      brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
386b8e80941Smrg      brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
387b8e80941Smrg   }
388b8e80941Smrg   brw_WHILE(p);
389b8e80941Smrg   brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
390b8e80941Smrg}
391b8e80941Smrg
392b8e80941Smrg
393b8e80941Smrg
394b8e80941Smrg
395b8e80941Smrg
396b8e80941Smrg
397b8e80941Smrg
398b8e80941Smrgstatic void emit_primitives( struct brw_clip_compile *c,
399b8e80941Smrg			     GLuint mode,
400b8e80941Smrg			     bool do_offset )
401b8e80941Smrg{
402b8e80941Smrg   switch (mode) {
403b8e80941Smrg   case BRW_CLIP_FILL_MODE_FILL:
404b8e80941Smrg      brw_clip_tri_emit_polygon(c);
405b8e80941Smrg      break;
406b8e80941Smrg
407b8e80941Smrg   case BRW_CLIP_FILL_MODE_LINE:
408b8e80941Smrg      emit_lines(c, do_offset);
409b8e80941Smrg      break;
410b8e80941Smrg
411b8e80941Smrg   case BRW_CLIP_FILL_MODE_POINT:
412b8e80941Smrg      emit_points(c, do_offset);
413b8e80941Smrg      break;
414b8e80941Smrg
415b8e80941Smrg   case BRW_CLIP_FILL_MODE_CULL:
416b8e80941Smrg      unreachable("not reached");
417b8e80941Smrg   }
418b8e80941Smrg}
419b8e80941Smrg
420b8e80941Smrg
421b8e80941Smrg
422b8e80941Smrgstatic void emit_unfilled_primitives( struct brw_clip_compile *c )
423b8e80941Smrg{
424b8e80941Smrg   struct brw_codegen *p = &c->func;
425b8e80941Smrg
426b8e80941Smrg   /* Direction culling has already been done.
427b8e80941Smrg    */
428b8e80941Smrg   if (c->key.fill_ccw != c->key.fill_cw &&
429b8e80941Smrg       c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL &&
430b8e80941Smrg       c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL)
431b8e80941Smrg   {
432b8e80941Smrg      brw_CMP(p,
433b8e80941Smrg	      vec1(brw_null_reg()),
434b8e80941Smrg	      BRW_CONDITIONAL_GE,
435b8e80941Smrg	      get_element(c->reg.dir, 2),
436b8e80941Smrg	      brw_imm_f(0));
437b8e80941Smrg
438b8e80941Smrg      brw_IF(p, BRW_EXECUTE_1);
439b8e80941Smrg      {
440b8e80941Smrg	 emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
441b8e80941Smrg      }
442b8e80941Smrg      brw_ELSE(p);
443b8e80941Smrg      {
444b8e80941Smrg	 emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
445b8e80941Smrg      }
446b8e80941Smrg      brw_ENDIF(p);
447b8e80941Smrg   }
448b8e80941Smrg   else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) {
449b8e80941Smrg      emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
450b8e80941Smrg   }
451b8e80941Smrg   else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) {
452b8e80941Smrg      emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
453b8e80941Smrg   }
454b8e80941Smrg}
455b8e80941Smrg
456b8e80941Smrg
457b8e80941Smrg
458b8e80941Smrg
459b8e80941Smrgstatic void check_nr_verts( struct brw_clip_compile *c )
460b8e80941Smrg{
461b8e80941Smrg   struct brw_codegen *p = &c->func;
462b8e80941Smrg
463b8e80941Smrg   brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
464b8e80941Smrg   brw_IF(p, BRW_EXECUTE_1);
465b8e80941Smrg   {
466b8e80941Smrg      brw_clip_kill_thread(c);
467b8e80941Smrg   }
468b8e80941Smrg   brw_ENDIF(p);
469b8e80941Smrg}
470b8e80941Smrg
471b8e80941Smrg
472b8e80941Smrgvoid brw_emit_unfilled_clip( struct brw_clip_compile *c )
473b8e80941Smrg{
474b8e80941Smrg   struct brw_codegen *p = &c->func;
475b8e80941Smrg
476b8e80941Smrg   c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
477b8e80941Smrg			(c->key.fill_ccw != c->key.fill_cw) ||
478b8e80941Smrg			c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
479b8e80941Smrg			c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL ||
480b8e80941Smrg			c->key.copy_bfc_cw ||
481b8e80941Smrg			c->key.copy_bfc_ccw);
482b8e80941Smrg
483b8e80941Smrg   brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
484b8e80941Smrg   brw_clip_tri_init_vertices(c);
485b8e80941Smrg   brw_clip_init_ff_sync(c);
486b8e80941Smrg
487b8e80941Smrg   assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE));
488b8e80941Smrg
489b8e80941Smrg   if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
490b8e80941Smrg       c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) {
491b8e80941Smrg      brw_clip_kill_thread(c);
492b8e80941Smrg      return;
493b8e80941Smrg   }
494b8e80941Smrg
495b8e80941Smrg   merge_edgeflags(c);
496b8e80941Smrg
497b8e80941Smrg   /* Need to use the inlist indirection here:
498b8e80941Smrg    */
499b8e80941Smrg   if (c->need_direction)
500b8e80941Smrg      compute_tri_direction(c);
501b8e80941Smrg
502b8e80941Smrg   if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
503b8e80941Smrg       c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)
504b8e80941Smrg      cull_direction(c);
505b8e80941Smrg
506b8e80941Smrg   if (c->key.offset_ccw ||
507b8e80941Smrg       c->key.offset_cw)
508b8e80941Smrg      compute_offset(c);
509b8e80941Smrg
510b8e80941Smrg   if (c->key.copy_bfc_ccw ||
511b8e80941Smrg       c->key.copy_bfc_cw)
512b8e80941Smrg      copy_bfc(c);
513b8e80941Smrg
514b8e80941Smrg   /* Need to do this whether we clip or not:
515b8e80941Smrg    */
516b8e80941Smrg   if (c->key.contains_flat_varying)
517b8e80941Smrg      brw_clip_tri_flat_shade(c);
518b8e80941Smrg
519b8e80941Smrg   brw_clip_init_clipmask(c);
520b8e80941Smrg   brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
521b8e80941Smrg   brw_IF(p, BRW_EXECUTE_1);
522b8e80941Smrg   {
523b8e80941Smrg      brw_clip_init_planes(c);
524b8e80941Smrg      brw_clip_tri(c);
525b8e80941Smrg      check_nr_verts(c);
526b8e80941Smrg   }
527b8e80941Smrg   brw_ENDIF(p);
528b8e80941Smrg
529b8e80941Smrg   emit_unfilled_primitives(c);
530b8e80941Smrg   brw_clip_kill_thread(c);
531b8e80941Smrg}
532