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