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