i965: add support for new chipsets
[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 "shader/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_util.h"
43 #include "brw_clip.h"
44
45 static void release_tmps( struct brw_clip_compile *c )
46 {
47 c->last_tmp = c->first_tmp;
48 }
49
50
51 void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
52 GLuint nr_verts )
53 {
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->nr_attrs & 1) {
78 for (j = 0; j < 3; j++) {
79 GLuint delta = c->nr_attrs*16 + 32;
80
81 if (BRW_IS_IGDNG(c->func.brw))
82 delta = c->nr_attrs * 16 + 32 * 3;
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->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
131 void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
132 {
133 struct brw_compile *p = &c->func;
134 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
135 struct brw_instruction *is_rev;
136
137 /* Initial list of indices for incoming vertexes:
138 */
139 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
140 brw_CMP(p,
141 vec1(brw_null_reg()),
142 BRW_CONDITIONAL_EQ,
143 tmp0,
144 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
145
146 /* XXX: Is there an easier way to do this? Need to reverse every
147 * second tristrip element: Can ignore sometimes?
148 */
149 is_rev = brw_IF(p, BRW_EXECUTE_1);
150 {
151 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
152 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
153 if (c->need_direction)
154 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
155 }
156 is_rev = brw_ELSE(p, is_rev);
157 {
158 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
159 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
160 if (c->need_direction)
161 brw_MOV(p, c->reg.dir, brw_imm_f(1));
162 }
163 brw_ENDIF(p, is_rev);
164
165 brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
166 brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
167 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
168 }
169
170
171
172 void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
173 {
174 struct brw_compile *p = &c->func;
175 struct brw_instruction *is_poly;
176 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
177
178 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
179 brw_CMP(p,
180 vec1(brw_null_reg()),
181 BRW_CONDITIONAL_EQ,
182 tmp0,
183 brw_imm_ud(_3DPRIM_POLYGON));
184
185 is_poly = brw_IF(p, BRW_EXECUTE_1);
186 {
187 brw_clip_copy_colors(c, 1, 0);
188 brw_clip_copy_colors(c, 2, 0);
189 }
190 is_poly = brw_ELSE(p, is_poly);
191 {
192 brw_clip_copy_colors(c, 0, 2);
193 brw_clip_copy_colors(c, 1, 2);
194 }
195 brw_ENDIF(p, is_poly);
196 }
197
198
199
200 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
201 */
202 void brw_clip_tri( struct brw_clip_compile *c )
203 {
204 struct brw_compile *p = &c->func;
205 struct brw_indirect vtx = brw_indirect(0, 0);
206 struct brw_indirect vtxPrev = brw_indirect(1, 0);
207 struct brw_indirect vtxOut = brw_indirect(2, 0);
208 struct brw_indirect plane_ptr = brw_indirect(3, 0);
209 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
210 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
211 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
212 struct brw_instruction *plane_loop;
213 struct brw_instruction *plane_active;
214 struct brw_instruction *vertex_loop;
215 struct brw_instruction *next_test;
216 struct brw_instruction *prev_test;
217
218 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
219 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
220 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
221 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
222
223 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
224
225 plane_loop = brw_DO(p, BRW_EXECUTE_1);
226 {
227 /* if (planemask & 1)
228 */
229 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
230 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
231
232 plane_active = brw_IF(p, BRW_EXECUTE_1);
233 {
234 /* vtxOut = freelist_ptr++
235 */
236 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
237 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
238
239 if (c->key.nr_userclip)
240 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
241 else
242 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
243
244 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
245 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
246
247 vertex_loop = brw_DO(p, BRW_EXECUTE_1);
248 {
249 /* vtx = *input_ptr;
250 */
251 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
252
253 /* IS_NEGATIVE(prev) */
254 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
255 brw_DP4(p, vec4(c->reg.dpPrev), deref_4f(vtxPrev, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
256 prev_test = brw_IF(p, BRW_EXECUTE_1);
257 {
258 /* IS_POSITIVE(next)
259 */
260 brw_set_conditionalmod(p, BRW_CONDITIONAL_GE);
261 brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
262 next_test = brw_IF(p, BRW_EXECUTE_1);
263 {
264
265 /* Coming back in.
266 */
267 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
268 brw_math_invert(p, c->reg.t, c->reg.t);
269 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
270
271 /* If (vtxOut == 0) vtxOut = vtxPrev
272 */
273 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
274 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
275 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
276
277 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, GL_FALSE);
278
279 /* *outlist_ptr++ = vtxOut;
280 * nr_verts++;
281 * vtxOut = 0;
282 */
283 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
284 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
285 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
286 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
287 }
288 brw_ENDIF(p, next_test);
289
290 }
291 prev_test = brw_ELSE(p, prev_test);
292 {
293 /* *outlist_ptr++ = vtxPrev;
294 * nr_verts++;
295 */
296 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
297 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
298 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
299
300 /* IS_NEGATIVE(next)
301 */
302 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
303 brw_DP4(p, vec4(c->reg.dp), deref_4f(vtx, c->offset[VERT_RESULT_HPOS]), c->reg.plane_equation);
304 next_test = brw_IF(p, BRW_EXECUTE_1);
305 {
306 /* Going out of bounds. Avoid division by zero as we
307 * know dp != dpPrev from DIFFERENT_SIGNS, above.
308 */
309 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
310 brw_math_invert(p, c->reg.t, c->reg.t);
311 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
312
313 /* If (vtxOut == 0) vtxOut = vtx
314 */
315 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
316 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
317 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
318
319 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, GL_TRUE);
320
321 /* *outlist_ptr++ = vtxOut;
322 * nr_verts++;
323 * vtxOut = 0;
324 */
325 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
326 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
327 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
328 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
329 }
330 brw_ENDIF(p, next_test);
331 }
332 brw_ENDIF(p, prev_test);
333
334 /* vtxPrev = vtx;
335 * inlist_ptr++;
336 */
337 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
338 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
339
340 /* while (--loopcount != 0)
341 */
342 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
343 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
344 }
345 brw_WHILE(p, vertex_loop);
346
347 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
348 * inlist = outlist
349 * inlist_ptr = &inlist[0]
350 * outlist_ptr = &outlist[0]
351 */
352 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
353 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
354 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
355 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
356 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
357 }
358 brw_ENDIF(p, plane_active);
359
360 /* plane_ptr++;
361 */
362 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
363
364 /* nr_verts >= 3
365 */
366 brw_CMP(p,
367 vec1(brw_null_reg()),
368 BRW_CONDITIONAL_GE,
369 c->reg.nr_verts,
370 brw_imm_ud(3));
371
372 /* && (planemask>>=1) != 0
373 */
374 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
375 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
376 }
377 brw_WHILE(p, plane_loop);
378 }
379
380
381
382 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
383 {
384 struct brw_compile *p = &c->func;
385 struct brw_instruction *loop, *if_insn;
386
387 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
388 */
389 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
390 brw_ADD(p,
391 c->reg.loopcount,
392 c->reg.nr_verts,
393 brw_imm_d(-2));
394
395 if_insn = brw_IF(p, BRW_EXECUTE_1);
396 {
397 struct brw_indirect v0 = brw_indirect(0, 0);
398 struct brw_indirect vptr = brw_indirect(1, 0);
399
400 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
401 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
402
403 brw_clip_emit_vue(c, v0, 1, 0, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_START));
404
405 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
406 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
407
408 loop = brw_DO(p, BRW_EXECUTE_1);
409 {
410 brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_TRIFAN << 2));
411
412 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
413 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
414
415 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
416 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
417 }
418 brw_WHILE(p, loop);
419
420 brw_clip_emit_vue(c, v0, 0, 1, ((_3DPRIM_TRIFAN << 2) | R02_PRIM_END));
421 }
422 brw_ENDIF(p, if_insn);
423 }
424
425 static void do_clip_tri( struct brw_clip_compile *c )
426 {
427 brw_clip_init_planes(c);
428
429 brw_clip_tri(c);
430 }
431
432
433 static void maybe_do_clip_tri( struct brw_clip_compile *c )
434 {
435 struct brw_compile *p = &c->func;
436 struct brw_instruction *do_clip;
437
438 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
439 do_clip = brw_IF(p, BRW_EXECUTE_1);
440 {
441 do_clip_tri(c);
442 }
443 brw_ENDIF(p, do_clip);
444 }
445
446 static void brw_clip_test( struct brw_clip_compile *c )
447 {
448 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
449 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
450 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
451 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
452
453 struct brw_reg v0 = get_tmp(c);
454 struct brw_reg v1 = get_tmp(c);
455 struct brw_reg v2 = get_tmp(c);
456
457 struct brw_indirect vt0 = brw_indirect(0, 0);
458 struct brw_indirect vt1 = brw_indirect(1, 0);
459 struct brw_indirect vt2 = brw_indirect(2, 0);
460
461 struct brw_compile *p = &c->func;
462 struct brw_instruction *is_outside;
463 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
464
465 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
466 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
467 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
468 brw_MOV(p, v0, deref_4f(vt0, c->offset[VERT_RESULT_HPOS]));
469 brw_MOV(p, v1, deref_4f(vt1, c->offset[VERT_RESULT_HPOS]));
470 brw_MOV(p, v2, deref_4f(vt2, c->offset[VERT_RESULT_HPOS]));
471 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
472
473 /* test nearz, xmin, ymin plane */
474 /* clip.xyz < -clip.w */
475 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
476 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
477 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
478 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
479 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
480 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
481
482 /* All vertices are outside of a plane, rejected */
483 brw_AND(p, t, t1, t2);
484 brw_AND(p, t, t, t3);
485 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
486 brw_OR(p, tmp0, tmp0, get_element(t, 2));
487 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
488 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
489 is_outside = brw_IF(p, BRW_EXECUTE_1);
490 {
491 brw_clip_kill_thread(c);
492 }
493 brw_ENDIF(p, is_outside);
494 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
495
496 /* some vertices are inside a plane, some are outside,need to clip */
497 brw_XOR(p, t, t1, t2);
498 brw_XOR(p, t1, t2, t3);
499 brw_OR(p, t, t, t1);
500 brw_AND(p, t, t, brw_imm_ud(0x1));
501 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
502 get_element(t, 0), brw_imm_ud(0));
503 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
504 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
505 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
506 get_element(t, 1), brw_imm_ud(0));
507 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
508 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
509 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
510 get_element(t, 2), brw_imm_ud(0));
511 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
512 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
513
514 /* test farz, xmax, ymax plane */
515 /* clip.xyz > clip.w */
516 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
517 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
518 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
519 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
520 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
521 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
522
523 /* All vertices are outside of a plane, rejected */
524 brw_AND(p, t, t1, t2);
525 brw_AND(p, t, t, t3);
526 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
527 brw_OR(p, tmp0, tmp0, get_element(t, 2));
528 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
529 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
530 is_outside = brw_IF(p, BRW_EXECUTE_1);
531 {
532 brw_clip_kill_thread(c);
533 }
534 brw_ENDIF(p, is_outside);
535 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
536
537 /* some vertices are inside a plane, some are outside,need to clip */
538 brw_XOR(p, t, t1, t2);
539 brw_XOR(p, t1, t2, t3);
540 brw_OR(p, t, t, t1);
541 brw_AND(p, t, t, brw_imm_ud(0x1));
542 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
543 get_element(t, 0), brw_imm_ud(0));
544 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
545 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
546 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
547 get_element(t, 1), brw_imm_ud(0));
548 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
549 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
550 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
551 get_element(t, 2), brw_imm_ud(0));
552 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
553 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
554
555 release_tmps(c);
556 }
557
558
559 void brw_emit_tri_clip( struct brw_clip_compile *c )
560 {
561 struct brw_instruction *neg_rhw;
562 struct brw_compile *p = &c->func;
563 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
564 brw_clip_tri_init_vertices(c);
565 brw_clip_init_clipmask(c);
566
567 /* if -ve rhw workaround bit is set,
568 do cliptest */
569 if (BRW_IS_965(p->brw)) {
570 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
571 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
572 brw_imm_ud(1<<20));
573 neg_rhw = brw_IF(p, BRW_EXECUTE_1);
574 {
575 brw_clip_test(c);
576 }
577 brw_ENDIF(p, neg_rhw);
578 }
579 /* Can't push into do_clip_tri because with polygon (or quad)
580 * flatshading, need to apply the flatshade here because we don't
581 * respect the PV when converting to trifan for emit:
582 */
583 if (c->key.do_flat_shading)
584 brw_clip_tri_flat_shade(c);
585
586 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
587 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
588 do_clip_tri(c);
589 else
590 maybe_do_clip_tri(c);
591
592 if (c->need_ff_sync)
593 brw_clip_ff_sync(c);
594 brw_clip_tri_emit_polygon(c);
595
596 /* Send an empty message to kill the thread:
597 */
598 brw_clip_kill_thread(c);
599 }