dd750f5f90d7a33ed9d8301a9fd3b02b7a883176
[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 static inline void
227 load_vertex_pos(struct brw_clip_compile *c, struct brw_indirect vtx,
228 struct brw_reg dst,
229 GLuint hpos_offset, GLuint clip_offset)
230 {
231 struct brw_compile *p = &c->func;
232
233 /*
234 * Roughly:
235 * dst = (vertex_src_mask & 1) ? src.hpos : src.clipvertex;
236 */
237
238 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
239 brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
240 brw_IF(p, BRW_EXECUTE_1);
241 {
242 brw_MOV(p, dst, deref_4f(vtx, clip_offset));
243 }
244 brw_ELSE(p);
245 {
246 brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
247 }
248 brw_ENDIF(p);
249 }
250
251
252 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
253 */
254 void brw_clip_tri( struct brw_clip_compile *c )
255 {
256 struct brw_compile *p = &c->func;
257 struct brw_indirect vtx = brw_indirect(0, 0);
258 struct brw_indirect vtxPrev = brw_indirect(1, 0);
259 struct brw_indirect vtxOut = brw_indirect(2, 0);
260 struct brw_indirect plane_ptr = brw_indirect(3, 0);
261 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
262 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
263 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
264 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
265 GLuint clipvert_offset = brw_clip_have_varying(c, VARYING_SLOT_CLIP_VERTEX)
266 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_VERTEX)
267 : hpos_offset;
268 GLint clipdist0_offset = c->key.nr_userclip
269 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
270 : 0;
271
272 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
273 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
274 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
275 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
276
277 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
278
279 /* Set the initial vertex source mask: The first 6 planes are the bounds
280 * of the view volume; the next 6 planes are the user clipping planes.
281 */
282 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0xfc0));
283
284 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
285 * We'll increment 6 times before we start hitting actual user clipping. */
286 brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
287
288 brw_DO(p, BRW_EXECUTE_1);
289 {
290 /* if (planemask & 1)
291 */
292 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
293 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
294
295 brw_IF(p, BRW_EXECUTE_1);
296 {
297 /* vtxOut = freelist_ptr++
298 */
299 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
300 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
301
302 if (c->key.nr_userclip)
303 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
304 else
305 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
306
307 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
308 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
309
310 brw_DO(p, BRW_EXECUTE_1);
311 {
312 /* vtx = *input_ptr;
313 */
314 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
315
316 load_vertex_pos(c, vtxPrev, vec4(c->reg.dpPrev), hpos_offset, clipvert_offset);
317 /* IS_NEGATIVE(prev) */
318 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
319 brw_DP4(p, vec4(c->reg.dpPrev), vec4(c->reg.dpPrev), c->reg.plane_equation);
320 brw_IF(p, BRW_EXECUTE_1);
321 {
322 load_vertex_pos(c, vtx, vec4(c->reg.dp), hpos_offset, clipvert_offset);
323 /* IS_POSITIVE(next)
324 */
325 brw_set_conditionalmod(p, BRW_CONDITIONAL_GE);
326 brw_DP4(p, vec4(c->reg.dp), vec4(c->reg.dp), c->reg.plane_equation);
327 brw_IF(p, BRW_EXECUTE_1);
328 {
329
330 /* Coming back in.
331 */
332 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
333 brw_math_invert(p, c->reg.t, c->reg.t);
334 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
335
336 /* If (vtxOut == 0) vtxOut = vtxPrev
337 */
338 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
339 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) );
340 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
341
342 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false);
343
344 /* *outlist_ptr++ = vtxOut;
345 * nr_verts++;
346 * vtxOut = 0;
347 */
348 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
349 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
350 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
351 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
352 }
353 brw_ENDIF(p);
354
355 }
356 brw_ELSE(p);
357 {
358 /* *outlist_ptr++ = vtxPrev;
359 * nr_verts++;
360 */
361 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
362 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
363 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
364
365 load_vertex_pos(c, vtx, vec4(c->reg.dp), hpos_offset, clipvert_offset);
366 /* IS_NEGATIVE(next)
367 */
368 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
369 brw_DP4(p, vec4(c->reg.dp), vec4(c->reg.dp), c->reg.plane_equation);
370 brw_IF(p, BRW_EXECUTE_1);
371 {
372 /* Going out of bounds. Avoid division by zero as we
373 * know dp != dpPrev from DIFFERENT_SIGNS, above.
374 */
375 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
376 brw_math_invert(p, c->reg.t, c->reg.t);
377 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
378
379 /* If (vtxOut == 0) vtxOut = vtx
380 */
381 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
382 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) );
383 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
384
385 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true);
386
387 /* *outlist_ptr++ = vtxOut;
388 * nr_verts++;
389 * vtxOut = 0;
390 */
391 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
392 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
393 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
394 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
395 }
396 brw_ENDIF(p);
397 }
398 brw_ENDIF(p);
399
400 /* vtxPrev = vtx;
401 * inlist_ptr++;
402 */
403 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
404 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
405
406 /* while (--loopcount != 0)
407 */
408 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
409 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
410 }
411 brw_WHILE(p);
412
413 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
414 * inlist = outlist
415 * inlist_ptr = &inlist[0]
416 * outlist_ptr = &outlist[0]
417 */
418 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
419 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
420 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
421 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
422 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
423 }
424 brw_ENDIF(p);
425
426 /* plane_ptr++;
427 */
428 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
429
430 /* nr_verts >= 3
431 */
432 brw_CMP(p,
433 vec1(brw_null_reg()),
434 BRW_CONDITIONAL_GE,
435 c->reg.nr_verts,
436 brw_imm_ud(3));
437
438 /* && (planemask>>=1) != 0
439 */
440 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
441 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
442 brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
443 brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
444 }
445 brw_WHILE(p);
446 }
447
448
449
450 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
451 {
452 struct brw_compile *p = &c->func;
453
454 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
455 */
456 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
457 brw_ADD(p,
458 c->reg.loopcount,
459 c->reg.nr_verts,
460 brw_imm_d(-2));
461
462 brw_IF(p, BRW_EXECUTE_1);
463 {
464 struct brw_indirect v0 = brw_indirect(0, 0);
465 struct brw_indirect vptr = brw_indirect(1, 0);
466
467 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
468 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
469
470 brw_clip_emit_vue(c, v0, 1, 0,
471 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
472 | URB_WRITE_PRIM_START));
473
474 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
475 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
476
477 brw_DO(p, BRW_EXECUTE_1);
478 {
479 brw_clip_emit_vue(c, v0, 1, 0,
480 (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
481
482 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
483 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
484
485 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
486 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
487 }
488 brw_WHILE(p);
489
490 brw_clip_emit_vue(c, v0, 0, 1,
491 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
492 | URB_WRITE_PRIM_END));
493 }
494 brw_ENDIF(p);
495 }
496
497 static void do_clip_tri( struct brw_clip_compile *c )
498 {
499 brw_clip_init_planes(c);
500
501 brw_clip_tri(c);
502 }
503
504
505 static void maybe_do_clip_tri( struct brw_clip_compile *c )
506 {
507 struct brw_compile *p = &c->func;
508
509 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
510 brw_IF(p, BRW_EXECUTE_1);
511 {
512 do_clip_tri(c);
513 }
514 brw_ENDIF(p);
515 }
516
517 static void brw_clip_test( struct brw_clip_compile *c )
518 {
519 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
520 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
521 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
522 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
523
524 struct brw_reg v0 = get_tmp(c);
525 struct brw_reg v1 = get_tmp(c);
526 struct brw_reg v2 = get_tmp(c);
527
528 struct brw_indirect vt0 = brw_indirect(0, 0);
529 struct brw_indirect vt1 = brw_indirect(1, 0);
530 struct brw_indirect vt2 = brw_indirect(2, 0);
531
532 struct brw_compile *p = &c->func;
533 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
534
535 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map,
536 VARYING_SLOT_POS);
537
538 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
539 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
540 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
541 brw_MOV(p, v0, deref_4f(vt0, hpos_offset));
542 brw_MOV(p, v1, deref_4f(vt1, hpos_offset));
543 brw_MOV(p, v2, deref_4f(vt2, hpos_offset));
544 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
545
546 /* test nearz, xmin, ymin plane */
547 /* clip.xyz < -clip.w */
548 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
549 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
550 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
551 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
552 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
553 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
554
555 /* All vertices are outside of a plane, rejected */
556 brw_AND(p, t, t1, t2);
557 brw_AND(p, t, t, t3);
558 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
559 brw_OR(p, tmp0, tmp0, get_element(t, 2));
560 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
561 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
562 brw_IF(p, BRW_EXECUTE_1);
563 {
564 brw_clip_kill_thread(c);
565 }
566 brw_ENDIF(p);
567 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
568
569 /* some vertices are inside a plane, some are outside,need to clip */
570 brw_XOR(p, t, t1, t2);
571 brw_XOR(p, t1, t2, t3);
572 brw_OR(p, t, t, t1);
573 brw_AND(p, t, t, brw_imm_ud(0x1));
574 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
575 get_element(t, 0), brw_imm_ud(0));
576 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
577 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
578 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
579 get_element(t, 1), brw_imm_ud(0));
580 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
581 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
582 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
583 get_element(t, 2), brw_imm_ud(0));
584 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
585 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
586
587 /* test farz, xmax, ymax plane */
588 /* clip.xyz > clip.w */
589 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
590 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
591 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
592 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
593 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
594 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
595
596 /* All vertices are outside of a plane, rejected */
597 brw_AND(p, t, t1, t2);
598 brw_AND(p, t, t, t3);
599 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
600 brw_OR(p, tmp0, tmp0, get_element(t, 2));
601 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
602 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
603 brw_IF(p, BRW_EXECUTE_1);
604 {
605 brw_clip_kill_thread(c);
606 }
607 brw_ENDIF(p);
608 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
609
610 /* some vertices are inside a plane, some are outside,need to clip */
611 brw_XOR(p, t, t1, t2);
612 brw_XOR(p, t1, t2, t3);
613 brw_OR(p, t, t, t1);
614 brw_AND(p, t, t, brw_imm_ud(0x1));
615 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
616 get_element(t, 0), brw_imm_ud(0));
617 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
618 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
619 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
620 get_element(t, 1), brw_imm_ud(0));
621 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
622 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
623 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
624 get_element(t, 2), brw_imm_ud(0));
625 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
626 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
627
628 release_tmps(c);
629 }
630
631
632 void brw_emit_tri_clip( struct brw_clip_compile *c )
633 {
634 struct brw_compile *p = &c->func;
635 struct brw_context *brw = p->brw;
636 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
637 brw_clip_tri_init_vertices(c);
638 brw_clip_init_clipmask(c);
639 brw_clip_init_ff_sync(c);
640
641 /* if -ve rhw workaround bit is set,
642 do cliptest */
643 if (brw->has_negative_rhw_bug) {
644 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
645 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
646 brw_imm_ud(1<<20));
647 brw_IF(p, BRW_EXECUTE_1);
648 {
649 brw_clip_test(c);
650 }
651 brw_ENDIF(p);
652 }
653 /* Can't push into do_clip_tri because with polygon (or quad)
654 * flatshading, need to apply the flatshade here because we don't
655 * respect the PV when converting to trifan for emit:
656 */
657 if (c->has_flat_shading)
658 brw_clip_tri_flat_shade(c);
659
660 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
661 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
662 do_clip_tri(c);
663 else
664 maybe_do_clip_tri(c);
665
666 brw_clip_tri_emit_polygon(c);
667
668 /* Send an empty message to kill the thread:
669 */
670 brw_clip_kill_thread(c);
671 }