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