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