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