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