i965: Gen4-5: Include alpha func/ref in program key
[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 brw_context *brw = c->func.brw;
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 c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);
124 i++;
125
126 if (brw->gen == 5) {
127 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
128 i++;
129 }
130
131 c->first_tmp = i;
132 c->last_tmp = i;
133
134 c->prog_data.urb_read_length = c->nr_regs; /* ? */
135 c->prog_data.total_grf = i;
136 }
137
138
139
140 void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
141 {
142 struct brw_compile *p = &c->func;
143 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
144
145 /* Initial list of indices for incoming vertexes:
146 */
147 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
148 brw_CMP(p,
149 vec1(brw_null_reg()),
150 BRW_CONDITIONAL_EQ,
151 tmp0,
152 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
153
154 /* XXX: Is there an easier way to do this? Need to reverse every
155 * second tristrip element: Can ignore sometimes?
156 */
157 brw_IF(p, BRW_EXECUTE_1);
158 {
159 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
160 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
161 if (c->need_direction)
162 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
163 }
164 brw_ELSE(p);
165 {
166 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
167 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
168 if (c->need_direction)
169 brw_MOV(p, c->reg.dir, brw_imm_f(1));
170 }
171 brw_ENDIF(p);
172
173 brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
174 brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
175 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
176 }
177
178
179
180 void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
181 {
182 struct brw_compile *p = &c->func;
183 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
184
185 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
186 brw_CMP(p,
187 vec1(brw_null_reg()),
188 BRW_CONDITIONAL_EQ,
189 tmp0,
190 brw_imm_ud(_3DPRIM_POLYGON));
191
192 brw_IF(p, BRW_EXECUTE_1);
193 {
194 brw_clip_copy_flatshaded_attributes(c, 1, 0);
195 brw_clip_copy_flatshaded_attributes(c, 2, 0);
196 }
197 brw_ELSE(p);
198 {
199 if (c->key.pv_first) {
200 brw_CMP(p,
201 vec1(brw_null_reg()),
202 BRW_CONDITIONAL_EQ,
203 tmp0,
204 brw_imm_ud(_3DPRIM_TRIFAN));
205 brw_IF(p, BRW_EXECUTE_1);
206 {
207 brw_clip_copy_flatshaded_attributes(c, 0, 1);
208 brw_clip_copy_flatshaded_attributes(c, 2, 1);
209 }
210 brw_ELSE(p);
211 {
212 brw_clip_copy_flatshaded_attributes(c, 1, 0);
213 brw_clip_copy_flatshaded_attributes(c, 2, 0);
214 }
215 brw_ENDIF(p);
216 }
217 else {
218 brw_clip_copy_flatshaded_attributes(c, 0, 2);
219 brw_clip_copy_flatshaded_attributes(c, 1, 2);
220 }
221 }
222 brw_ENDIF(p);
223 }
224
225
226 /**
227 * Loads the clip distance for a vertex into `dst`, and ends with
228 * a comparison of it to zero with the condition `cond`.
229 *
230 * - If using a fixed plane, the distance is dot(hpos, plane).
231 * - If using a user clip plane, the distance is directly available in the vertex.
232 */
233 static inline void
234 load_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx,
235 struct brw_reg dst, GLuint hpos_offset, int cond)
236 {
237 struct brw_compile *p = &c->func;
238
239 dst = vec4(dst);
240 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
241 brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
242 brw_IF(p, BRW_EXECUTE_1);
243 {
244 struct brw_indirect temp_ptr = brw_indirect(7, 0);
245 brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset);
246 brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0));
247 }
248 brw_ELSE(p);
249 {
250 brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
251 brw_DP4(p, dst, dst, c->reg.plane_equation);
252 }
253 brw_ENDIF(p);
254
255 brw_set_conditionalmod(p, cond);
256 brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f));
257 }
258
259
260 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
261 */
262 void brw_clip_tri( struct brw_clip_compile *c )
263 {
264 struct brw_compile *p = &c->func;
265 struct brw_indirect vtx = brw_indirect(0, 0);
266 struct brw_indirect vtxPrev = brw_indirect(1, 0);
267 struct brw_indirect vtxOut = brw_indirect(2, 0);
268 struct brw_indirect plane_ptr = brw_indirect(3, 0);
269 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
270 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
271 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
272 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
273 GLint clipdist0_offset = c->key.nr_userclip
274 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
275 : 0;
276
277 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
278 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
279 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
280 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
281
282 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
283
284 /* Set the initial vertex source mask: The first 6 planes are the bounds
285 * of the view volume; the next 8 planes are the user clipping planes.
286 */
287 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
288
289 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
290 * We'll increment 6 times before we start hitting actual user clipping. */
291 brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
292
293 brw_DO(p, BRW_EXECUTE_1);
294 {
295 /* if (planemask & 1)
296 */
297 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
298 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
299
300 brw_IF(p, BRW_EXECUTE_1);
301 {
302 /* vtxOut = freelist_ptr++
303 */
304 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
305 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
306
307 if (c->key.nr_userclip)
308 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
309 else
310 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
311
312 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
313 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
314
315 brw_DO(p, BRW_EXECUTE_1);
316 {
317 /* vtx = *input_ptr;
318 */
319 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
320
321 load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L);
322 /* IS_NEGATIVE(prev) */
323 brw_IF(p, BRW_EXECUTE_1);
324 {
325 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE);
326 /* IS_POSITIVE(next)
327 */
328 brw_IF(p, BRW_EXECUTE_1);
329 {
330
331 /* Coming back in.
332 */
333 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
334 brw_math_invert(p, c->reg.t, c->reg.t);
335 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
336
337 /* If (vtxOut == 0) vtxOut = vtxPrev
338 */
339 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
340 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
341 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
342
343 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false);
344
345 /* *outlist_ptr++ = vtxOut;
346 * nr_verts++;
347 * vtxOut = 0;
348 */
349 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
350 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
351 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
352 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
353 }
354 brw_ENDIF(p);
355
356 }
357 brw_ELSE(p);
358 {
359 /* *outlist_ptr++ = vtxPrev;
360 * nr_verts++;
361 */
362 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
363 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
364 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
365
366 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_L);
367 /* IS_NEGATIVE(next)
368 */
369 brw_IF(p, BRW_EXECUTE_1);
370 {
371 /* Going out of bounds. Avoid division by zero as we
372 * know dp != dpPrev from DIFFERENT_SIGNS, above.
373 */
374 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
375 brw_math_invert(p, c->reg.t, c->reg.t);
376 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
377
378 /* If (vtxOut == 0) vtxOut = vtx
379 */
380 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
381 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
382 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
383
384 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true);
385
386 /* *outlist_ptr++ = vtxOut;
387 * nr_verts++;
388 * vtxOut = 0;
389 */
390 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
391 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
392 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
393 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
394 }
395 brw_ENDIF(p);
396 }
397 brw_ENDIF(p);
398
399 /* vtxPrev = vtx;
400 * inlist_ptr++;
401 */
402 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
403 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
404
405 /* while (--loopcount != 0)
406 */
407 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
408 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
409 }
410 brw_WHILE(p);
411
412 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
413 * inlist = outlist
414 * inlist_ptr = &inlist[0]
415 * outlist_ptr = &outlist[0]
416 */
417 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
418 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
419 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
420 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
421 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
422 }
423 brw_ENDIF(p);
424
425 /* plane_ptr++;
426 */
427 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
428
429 /* nr_verts >= 3
430 */
431 brw_CMP(p,
432 vec1(brw_null_reg()),
433 BRW_CONDITIONAL_GE,
434 c->reg.nr_verts,
435 brw_imm_ud(3));
436
437 /* && (planemask>>=1) != 0
438 */
439 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
440 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
441 brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
442 brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
443 }
444 brw_WHILE(p);
445 }
446
447
448
449 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
450 {
451 struct brw_compile *p = &c->func;
452
453 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
454 */
455 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
456 brw_ADD(p,
457 c->reg.loopcount,
458 c->reg.nr_verts,
459 brw_imm_d(-2));
460
461 brw_IF(p, BRW_EXECUTE_1);
462 {
463 struct brw_indirect v0 = brw_indirect(0, 0);
464 struct brw_indirect vptr = brw_indirect(1, 0);
465
466 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
467 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
468
469 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
470 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
471 | URB_WRITE_PRIM_START));
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_DO(p, BRW_EXECUTE_1);
477 {
478 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
479 (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
480
481 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
482 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
483
484 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
485 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
486 }
487 brw_WHILE(p);
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
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
504 static void maybe_do_clip_tri( struct brw_clip_compile *c )
505 {
506 struct brw_compile *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
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_compile *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_set_predicate_control(p, BRW_PREDICATE_NONE);
549 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
550 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
551 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
552 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
553
554 /* All vertices are outside of a plane, rejected */
555 brw_AND(p, t, t1, t2);
556 brw_AND(p, t, t, t3);
557 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
558 brw_OR(p, tmp0, tmp0, get_element(t, 2));
559 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
560 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
561 brw_IF(p, BRW_EXECUTE_1);
562 {
563 brw_clip_kill_thread(c);
564 }
565 brw_ENDIF(p);
566 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
567
568 /* some vertices are inside a plane, some are outside,need to clip */
569 brw_XOR(p, t, t1, t2);
570 brw_XOR(p, t1, t2, t3);
571 brw_OR(p, t, t, t1);
572 brw_AND(p, t, t, brw_imm_ud(0x1));
573 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
574 get_element(t, 0), brw_imm_ud(0));
575 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
576 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
577 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
578 get_element(t, 1), brw_imm_ud(0));
579 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
580 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
581 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
582 get_element(t, 2), brw_imm_ud(0));
583 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
584 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
585
586 /* test farz, xmax, ymax plane */
587 /* clip.xyz > clip.w */
588 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
589 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
590 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
591 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
592 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
593 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
594
595 /* All vertices are outside of a plane, rejected */
596 brw_AND(p, t, t1, t2);
597 brw_AND(p, t, t, t3);
598 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
599 brw_OR(p, tmp0, tmp0, get_element(t, 2));
600 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
601 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
602 brw_IF(p, BRW_EXECUTE_1);
603 {
604 brw_clip_kill_thread(c);
605 }
606 brw_ENDIF(p);
607 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
608
609 /* some vertices are inside a plane, some are outside,need to clip */
610 brw_XOR(p, t, t1, t2);
611 brw_XOR(p, t1, t2, t3);
612 brw_OR(p, t, t, t1);
613 brw_AND(p, t, t, brw_imm_ud(0x1));
614 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
615 get_element(t, 0), brw_imm_ud(0));
616 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
617 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
618 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
619 get_element(t, 1), brw_imm_ud(0));
620 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
621 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
622 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
623 get_element(t, 2), brw_imm_ud(0));
624 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
625 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
626
627 release_tmps(c);
628 }
629
630
631 void brw_emit_tri_clip( struct brw_clip_compile *c )
632 {
633 struct brw_compile *p = &c->func;
634 struct brw_context *brw = p->brw;
635 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
636 brw_clip_tri_init_vertices(c);
637 brw_clip_init_clipmask(c);
638 brw_clip_init_ff_sync(c);
639
640 /* if -ve rhw workaround bit is set,
641 do cliptest */
642 if (brw->has_negative_rhw_bug) {
643 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
644 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
645 brw_imm_ud(1<<20));
646 brw_IF(p, BRW_EXECUTE_1);
647 {
648 brw_clip_test(c);
649 }
650 brw_ENDIF(p);
651 }
652 /* Can't push into do_clip_tri because with polygon (or quad)
653 * flatshading, need to apply the flatshade here because we don't
654 * respect the PV when converting to trifan for emit:
655 */
656 if (c->has_flat_shading)
657 brw_clip_tri_flat_shade(c);
658
659 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
660 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
661 do_clip_tri(c);
662 else
663 maybe_do_clip_tri(c);
664
665 brw_clip_tri_emit_polygon(c);
666
667 /* Send an empty message to kill the thread:
668 */
669 brw_clip_kill_thread(c);
670 }