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 
release_tmps(struct brw_clip_compile * c)38 static void release_tmps( struct brw_clip_compile *c )
39 {
40    c->last_tmp = c->first_tmp;
41 }
42 
43 
brw_clip_tri_alloc_regs(struct brw_clip_compile * c,GLuint nr_verts)44 void 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 
brw_clip_tri_init_vertices(struct brw_clip_compile * c)134 void 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 
brw_clip_tri_flat_shade(struct brw_clip_compile * c)174 void 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  */
227 static inline void
load_clip_distance(struct brw_clip_compile * c,struct brw_indirect vtx,struct brw_reg dst,GLuint hpos_offset,int cond)228 load_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  */
brw_clip_tri(struct brw_clip_compile * c)255 void 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 
brw_clip_tri_emit_polygon(struct brw_clip_compile * c)447 void 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 
do_clip_tri(struct brw_clip_compile * c)495 static 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 
maybe_do_clip_tri(struct brw_clip_compile * c)503 static 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 
brw_clip_test(struct brw_clip_compile * c)515 static 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 
brw_emit_tri_clip(struct brw_clip_compile * c)624 void 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