i915: Remove most of the code under gen >= 4 checks.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_clip_tri.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) 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 <keith@tungstengraphics.com>
30 */
31
32 #include "main/glheader.h"
33 #include "main/macros.h"
34 #include "main/enums.h"
35 #include "program/program.h"
36
37 #include "intel_batchbuffer.h"
38
39 #include "brw_defines.h"
40 #include "brw_context.h"
41 #include "brw_eu.h"
42 #include "brw_clip.h"
43
44 static void release_tmps( struct brw_clip_compile *c )
45 {
46 c->last_tmp = c->first_tmp;
47 }
48
49
50 void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
51 GLuint nr_verts )
52 {
53 struct intel_context *intel = &c->func.brw->intel;
54 GLuint i = 0,j;
55
56 /* Register usage is static, precompute here:
57 */
58 c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
59
60 if (c->key.nr_userclip) {
61 c->reg.fixed_planes = brw_vec4_grf(i, 0);
62 i += (6 + c->key.nr_userclip + 1) / 2;
63
64 c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
65 }
66 else
67 c->prog_data.curb_read_length = 0;
68
69
70 /* Payload vertices plus space for more generated vertices:
71 */
72 for (j = 0; j < nr_verts; j++) {
73 c->reg.vertex[j] = brw_vec4_grf(i, 0);
74 i += c->nr_regs;
75 }
76
77 if (c->vue_map.num_slots % 2) {
78 /* The VUE has an odd number of slots so the last register is only half
79 * used. Fill the second half with zero.
80 */
81 for (j = 0; j < 3; j++) {
82 GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);
83
84 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
85 }
86 }
87
88 c->reg.t = brw_vec1_grf(i, 0);
89 c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
90 c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
91 c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
92 c->reg.plane_equation = brw_vec4_grf(i, 4);
93 i++;
94
95 c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
96 c->reg.dp = brw_vec1_grf(i, 4);
97 i++;
98
99 c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
100 i++;
101
102 c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
103 i++;
104
105 c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
106 i++;
107
108 if (!c->key.nr_userclip) {
109 c->reg.fixed_planes = brw_vec8_grf(i, 0);
110 i++;
111 }
112
113 if (c->key.do_unfilled) {
114 c->reg.dir = brw_vec4_grf(i, 0);
115 c->reg.offset = brw_vec4_grf(i, 4);
116 i++;
117 c->reg.tmp0 = brw_vec4_grf(i, 0);
118 c->reg.tmp1 = brw_vec4_grf(i, 4);
119 i++;
120 }
121
122 c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
123 i++;
124
125 if (intel->needs_ff_sync) {
126 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
127 i++;
128 }
129
130 c->first_tmp = i;
131 c->last_tmp = i;
132
133 c->prog_data.urb_read_length = c->nr_regs; /* ? */
134 c->prog_data.total_grf = i;
135 }
136
137
138
139 void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
140 {
141 struct brw_compile *p = &c->func;
142 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
143
144 /* Initial list of indices for incoming vertexes:
145 */
146 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
147 brw_CMP(p,
148 vec1(brw_null_reg()),
149 BRW_CONDITIONAL_EQ,
150 tmp0,
151 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
152
153 /* XXX: Is there an easier way to do this? Need to reverse every
154 * second tristrip element: Can ignore sometimes?
155 */
156 brw_IF(p, BRW_EXECUTE_1);
157 {
158 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
159 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
160 if (c->need_direction)
161 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
162 }
163 brw_ELSE(p);
164 {
165 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
166 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
167 if (c->need_direction)
168 brw_MOV(p, c->reg.dir, brw_imm_f(1));
169 }
170 brw_ENDIF(p);
171
172 brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
173 brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
174 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
175 }
176
177
178
179 void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
180 {
181 struct brw_compile *p = &c->func;
182 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
183
184 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
185 brw_CMP(p,
186 vec1(brw_null_reg()),
187 BRW_CONDITIONAL_EQ,
188 tmp0,
189 brw_imm_ud(_3DPRIM_POLYGON));
190
191 brw_IF(p, BRW_EXECUTE_1);
192 {
193 brw_clip_copy_colors(c, 1, 0);
194 brw_clip_copy_colors(c, 2, 0);
195 }
196 brw_ELSE(p);
197 {
198 if (c->key.pv_first) {
199 brw_CMP(p,
200 vec1(brw_null_reg()),
201 BRW_CONDITIONAL_EQ,
202 tmp0,
203 brw_imm_ud(_3DPRIM_TRIFAN));
204 brw_IF(p, BRW_EXECUTE_1);
205 {
206 brw_clip_copy_colors(c, 0, 1);
207 brw_clip_copy_colors(c, 2, 1);
208 }
209 brw_ELSE(p);
210 {
211 brw_clip_copy_colors(c, 1, 0);
212 brw_clip_copy_colors(c, 2, 0);
213 }
214 brw_ENDIF(p);
215 }
216 else {
217 brw_clip_copy_colors(c, 0, 2);
218 brw_clip_copy_colors(c, 1, 2);
219 }
220 }
221 brw_ENDIF(p);
222 }
223
224
225 static inline void
226 load_vertex_pos(struct brw_clip_compile *c, struct brw_indirect vtx,
227 struct brw_reg dst,
228 GLuint hpos_offset, GLuint clip_offset)
229 {
230 struct brw_compile *p = &c->func;
231
232 /*
233 * Roughly:
234 * dst = (vertex_src_mask & 1) ? src.hpos : src.clipvertex;
235 */
236
237 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
238 brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
239 brw_IF(p, BRW_EXECUTE_1);
240 {
241 brw_MOV(p, dst, deref_4f(vtx, clip_offset));
242 }
243 brw_ELSE(p);
244 {
245 brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
246 }
247 brw_ENDIF(p);
248 }
249
250
251 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
252 */
253 void brw_clip_tri( struct brw_clip_compile *c )
254 {
255 struct brw_compile *p = &c->func;
256 struct brw_indirect vtx = brw_indirect(0, 0);
257 struct brw_indirect vtxPrev = brw_indirect(1, 0);
258 struct brw_indirect vtxOut = brw_indirect(2, 0);
259 struct brw_indirect plane_ptr = brw_indirect(3, 0);
260 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
261 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
262 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
263 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
264 GLuint clipvert_offset = brw_clip_have_varying(c, VARYING_SLOT_CLIP_VERTEX)
265 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_VERTEX)
266 : hpos_offset;
267
268 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
269 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
270 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
271 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
272
273 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
274
275 /* Set the initial vertex source mask: The first 6 planes are the bounds
276 * of the view volume; the next 6 planes are the user clipping planes.
277 */
278 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0xfc0));
279
280 brw_DO(p, BRW_EXECUTE_1);
281 {
282 /* if (planemask & 1)
283 */
284 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
285 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
286
287 brw_IF(p, BRW_EXECUTE_1);
288 {
289 /* vtxOut = freelist_ptr++
290 */
291 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
292 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
293
294 if (c->key.nr_userclip)
295 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
296 else
297 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
298
299 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
300 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
301
302 brw_DO(p, BRW_EXECUTE_1);
303 {
304 /* vtx = *input_ptr;
305 */
306 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
307
308 load_vertex_pos(c, vtxPrev, vec4(c->reg.dpPrev), hpos_offset, clipvert_offset);
309 /* IS_NEGATIVE(prev) */
310 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
311 brw_DP4(p, vec4(c->reg.dpPrev), vec4(c->reg.dpPrev), c->reg.plane_equation);
312 brw_IF(p, BRW_EXECUTE_1);
313 {
314 load_vertex_pos(c, vtx, vec4(c->reg.dp), hpos_offset, clipvert_offset);
315 /* IS_POSITIVE(next)
316 */
317 brw_set_conditionalmod(p, BRW_CONDITIONAL_GE);
318 brw_DP4(p, vec4(c->reg.dp), vec4(c->reg.dp), c->reg.plane_equation);
319 brw_IF(p, BRW_EXECUTE_1);
320 {
321
322 /* Coming back in.
323 */
324 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
325 brw_math_invert(p, c->reg.t, c->reg.t);
326 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
327
328 /* If (vtxOut == 0) vtxOut = vtxPrev
329 */
330 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
331 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
332 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
333
334 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false);
335
336 /* *outlist_ptr++ = vtxOut;
337 * nr_verts++;
338 * vtxOut = 0;
339 */
340 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
341 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
342 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
343 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
344 }
345 brw_ENDIF(p);
346
347 }
348 brw_ELSE(p);
349 {
350 /* *outlist_ptr++ = vtxPrev;
351 * nr_verts++;
352 */
353 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
354 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
355 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
356
357 load_vertex_pos(c, vtx, vec4(c->reg.dp), hpos_offset, clipvert_offset);
358 /* IS_NEGATIVE(next)
359 */
360 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
361 brw_DP4(p, vec4(c->reg.dp), vec4(c->reg.dp), c->reg.plane_equation);
362 brw_IF(p, BRW_EXECUTE_1);
363 {
364 /* Going out of bounds. Avoid division by zero as we
365 * know dp != dpPrev from DIFFERENT_SIGNS, above.
366 */
367 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
368 brw_math_invert(p, c->reg.t, c->reg.t);
369 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
370
371 /* If (vtxOut == 0) vtxOut = vtx
372 */
373 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
374 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
375 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
376
377 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true);
378
379 /* *outlist_ptr++ = vtxOut;
380 * nr_verts++;
381 * vtxOut = 0;
382 */
383 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
384 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
385 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
386 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
387 }
388 brw_ENDIF(p);
389 }
390 brw_ENDIF(p);
391
392 /* vtxPrev = vtx;
393 * inlist_ptr++;
394 */
395 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
396 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
397
398 /* while (--loopcount != 0)
399 */
400 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
401 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
402 }
403 brw_WHILE(p);
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 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
411 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
412 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
413 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
414 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
415 }
416 brw_ENDIF(p);
417
418 /* plane_ptr++;
419 */
420 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
421
422 /* nr_verts >= 3
423 */
424 brw_CMP(p,
425 vec1(brw_null_reg()),
426 BRW_CONDITIONAL_GE,
427 c->reg.nr_verts,
428 brw_imm_ud(3));
429
430 /* && (planemask>>=1) != 0
431 */
432 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
433 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
434 brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
435 }
436 brw_WHILE(p);
437 }
438
439
440
441 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
442 {
443 struct brw_compile *p = &c->func;
444
445 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
446 */
447 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
448 brw_ADD(p,
449 c->reg.loopcount,
450 c->reg.nr_verts,
451 brw_imm_d(-2));
452
453 brw_IF(p, BRW_EXECUTE_1);
454 {
455 struct brw_indirect v0 = brw_indirect(0, 0);
456 struct brw_indirect vptr = brw_indirect(1, 0);
457
458 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
459 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
460
461 brw_clip_emit_vue(c, v0, 1, 0,
462 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
463 | URB_WRITE_PRIM_START));
464
465 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
466 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
467
468 brw_DO(p, BRW_EXECUTE_1);
469 {
470 brw_clip_emit_vue(c, v0, 1, 0,
471 (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
472
473 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
474 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
475
476 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
477 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
478 }
479 brw_WHILE(p);
480
481 brw_clip_emit_vue(c, v0, 0, 1,
482 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
483 | URB_WRITE_PRIM_END));
484 }
485 brw_ENDIF(p);
486 }
487
488 static void do_clip_tri( struct brw_clip_compile *c )
489 {
490 brw_clip_init_planes(c);
491
492 brw_clip_tri(c);
493 }
494
495
496 static void maybe_do_clip_tri( struct brw_clip_compile *c )
497 {
498 struct brw_compile *p = &c->func;
499
500 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
501 brw_IF(p, BRW_EXECUTE_1);
502 {
503 do_clip_tri(c);
504 }
505 brw_ENDIF(p);
506 }
507
508 static void brw_clip_test( struct brw_clip_compile *c )
509 {
510 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
511 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
512 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
513 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
514
515 struct brw_reg v0 = get_tmp(c);
516 struct brw_reg v1 = get_tmp(c);
517 struct brw_reg v2 = get_tmp(c);
518
519 struct brw_indirect vt0 = brw_indirect(0, 0);
520 struct brw_indirect vt1 = brw_indirect(1, 0);
521 struct brw_indirect vt2 = brw_indirect(2, 0);
522
523 struct brw_compile *p = &c->func;
524 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
525
526 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map,
527 VARYING_SLOT_POS);
528
529 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
530 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
531 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
532 brw_MOV(p, v0, deref_4f(vt0, hpos_offset));
533 brw_MOV(p, v1, deref_4f(vt1, hpos_offset));
534 brw_MOV(p, v2, deref_4f(vt2, hpos_offset));
535 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
536
537 /* test nearz, xmin, ymin plane */
538 /* clip.xyz < -clip.w */
539 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
540 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
541 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
542 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
543 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
544 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
545
546 /* All vertices are outside of a plane, rejected */
547 brw_AND(p, t, t1, t2);
548 brw_AND(p, t, t, t3);
549 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
550 brw_OR(p, tmp0, tmp0, get_element(t, 2));
551 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
552 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
553 brw_IF(p, BRW_EXECUTE_1);
554 {
555 brw_clip_kill_thread(c);
556 }
557 brw_ENDIF(p);
558 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
559
560 /* some vertices are inside a plane, some are outside,need to clip */
561 brw_XOR(p, t, t1, t2);
562 brw_XOR(p, t1, t2, t3);
563 brw_OR(p, t, t, t1);
564 brw_AND(p, t, t, brw_imm_ud(0x1));
565 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
566 get_element(t, 0), brw_imm_ud(0));
567 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
568 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
569 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
570 get_element(t, 1), brw_imm_ud(0));
571 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
572 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
573 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
574 get_element(t, 2), brw_imm_ud(0));
575 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
576 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
577
578 /* test farz, xmax, ymax plane */
579 /* clip.xyz > clip.w */
580 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
581 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
582 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
583 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
584 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
585 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
586
587 /* All vertices are outside of a plane, rejected */
588 brw_AND(p, t, t1, t2);
589 brw_AND(p, t, t, t3);
590 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
591 brw_OR(p, tmp0, tmp0, get_element(t, 2));
592 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
593 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
594 brw_IF(p, BRW_EXECUTE_1);
595 {
596 brw_clip_kill_thread(c);
597 }
598 brw_ENDIF(p);
599 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
600
601 /* some vertices are inside a plane, some are outside,need to clip */
602 brw_XOR(p, t, t1, t2);
603 brw_XOR(p, t1, t2, t3);
604 brw_OR(p, t, t, t1);
605 brw_AND(p, t, t, brw_imm_ud(0x1));
606 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
607 get_element(t, 0), brw_imm_ud(0));
608 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
609 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
610 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
611 get_element(t, 1), brw_imm_ud(0));
612 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
613 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
614 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
615 get_element(t, 2), brw_imm_ud(0));
616 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
617 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
618
619 release_tmps(c);
620 }
621
622
623 void brw_emit_tri_clip( struct brw_clip_compile *c )
624 {
625 struct brw_compile *p = &c->func;
626 struct brw_context *brw = p->brw;
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 (brw->has_negative_rhw_bug) {
635 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
636 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
637 brw_imm_ud(1<<20));
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.do_flat_shading)
649 brw_clip_tri_flat_shade(c);
650
651 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
652 (c->key.clip_mode == BRW_CLIPMODE_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 }