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 gen_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->gen == 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 GEN4 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