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