i965/fs: Migrate FS gl_SamplePosition/ID computation code to the IR builder.
[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 const struct brw_device_info *devinfo = c->func.devinfo;
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 (devinfo->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_codegen *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_codegen *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_codegen *p = &c->func;
238
239 dst = vec4(dst);
240 brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
241 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
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_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f));
256 }
257
258
259 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
260 */
261 void brw_clip_tri( struct brw_clip_compile *c )
262 {
263 struct brw_codegen *p = &c->func;
264 struct brw_indirect vtx = brw_indirect(0, 0);
265 struct brw_indirect vtxPrev = brw_indirect(1, 0);
266 struct brw_indirect vtxOut = brw_indirect(2, 0);
267 struct brw_indirect plane_ptr = brw_indirect(3, 0);
268 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
269 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
270 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
271 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
272 GLint clipdist0_offset = c->key.nr_userclip
273 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
274 : 0;
275
276 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
277 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
278 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
279 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
280
281 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
282
283 /* Set the initial vertex source mask: The first 6 planes are the bounds
284 * of the view volume; the next 8 planes are the user clipping planes.
285 */
286 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
287
288 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
289 * We'll increment 6 times before we start hitting actual user clipping. */
290 brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
291
292 brw_DO(p, BRW_EXECUTE_1);
293 {
294 /* if (planemask & 1)
295 */
296 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
297 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
298
299 brw_IF(p, BRW_EXECUTE_1);
300 {
301 /* vtxOut = freelist_ptr++
302 */
303 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
304 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
305
306 if (c->key.nr_userclip)
307 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
308 else
309 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
310
311 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
312 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
313
314 brw_DO(p, BRW_EXECUTE_1);
315 {
316 /* vtx = *input_ptr;
317 */
318 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
319
320 load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L);
321 /* (prev < 0.0f) */
322 brw_IF(p, BRW_EXECUTE_1);
323 {
324 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE);
325 /* IS_POSITIVE(next)
326 */
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_inst_set_pred_control(p->devinfo, brw_last_inst,
341 BRW_PREDICATE_NORMAL);
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 /* (next < 0.0f)
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_inst_set_pred_control(p->devinfo, brw_last_inst,
383 BRW_PREDICATE_NORMAL);
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_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
409 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
410 }
411 brw_WHILE(p);
412 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
413
414 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
415 * inlist = outlist
416 * inlist_ptr = &inlist[0]
417 * outlist_ptr = &outlist[0]
418 */
419 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
420 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
421 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
422 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
423 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
424 }
425 brw_ENDIF(p);
426
427 /* plane_ptr++;
428 */
429 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
430
431 /* nr_verts >= 3
432 */
433 brw_CMP(p,
434 vec1(brw_null_reg()),
435 BRW_CONDITIONAL_GE,
436 c->reg.nr_verts,
437 brw_imm_ud(3));
438 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
439
440 /* && (planemask>>=1) != 0
441 */
442 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
443 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
444 brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
445 brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
446 }
447 brw_WHILE(p);
448 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
449 }
450
451
452
453 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
454 {
455 struct brw_codegen *p = &c->func;
456
457 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
458 */
459 brw_ADD(p,
460 c->reg.loopcount,
461 c->reg.nr_verts,
462 brw_imm_d(-2));
463 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
464
465 brw_IF(p, BRW_EXECUTE_1);
466 {
467 struct brw_indirect v0 = brw_indirect(0, 0);
468 struct brw_indirect vptr = brw_indirect(1, 0);
469
470 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
471 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
472
473 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
474 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
475 | URB_WRITE_PRIM_START));
476
477 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
478 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
479
480 brw_DO(p, BRW_EXECUTE_1);
481 {
482 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
483 (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
484
485 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
486 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
487
488 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
489 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
490 }
491 brw_WHILE(p);
492 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
493
494 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_EOT_COMPLETE,
495 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
496 | URB_WRITE_PRIM_END));
497 }
498 brw_ENDIF(p);
499 }
500
501 static void do_clip_tri( struct brw_clip_compile *c )
502 {
503 brw_clip_init_planes(c);
504
505 brw_clip_tri(c);
506 }
507
508
509 static void maybe_do_clip_tri( struct brw_clip_compile *c )
510 {
511 struct brw_codegen *p = &c->func;
512
513 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
514 brw_IF(p, BRW_EXECUTE_1);
515 {
516 do_clip_tri(c);
517 }
518 brw_ENDIF(p);
519 }
520
521 static void brw_clip_test( struct brw_clip_compile *c )
522 {
523 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
524 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
525 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
526 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
527
528 struct brw_reg v0 = get_tmp(c);
529 struct brw_reg v1 = get_tmp(c);
530 struct brw_reg v2 = get_tmp(c);
531
532 struct brw_indirect vt0 = brw_indirect(0, 0);
533 struct brw_indirect vt1 = brw_indirect(1, 0);
534 struct brw_indirect vt2 = brw_indirect(2, 0);
535
536 struct brw_codegen *p = &c->func;
537 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
538
539 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map,
540 VARYING_SLOT_POS);
541
542 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
543 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
544 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
545 brw_MOV(p, v0, deref_4f(vt0, hpos_offset));
546 brw_MOV(p, v1, deref_4f(vt1, hpos_offset));
547 brw_MOV(p, v2, deref_4f(vt2, hpos_offset));
548 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
549
550 /* test nearz, xmin, ymin plane */
551 /* clip.xyz < -clip.w */
552 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
553 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
554 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
555
556 /* All vertices are outside of a plane, rejected */
557 brw_AND(p, t, t1, t2);
558 brw_AND(p, t, t, t3);
559 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
560 brw_OR(p, tmp0, tmp0, get_element(t, 2));
561 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
562 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
563 brw_IF(p, BRW_EXECUTE_1);
564 {
565 brw_clip_kill_thread(c);
566 }
567 brw_ENDIF(p);
568 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
569
570 /* some vertices are inside a plane, some are outside,need to clip */
571 brw_XOR(p, t, t1, t2);
572 brw_XOR(p, t1, t2, t3);
573 brw_OR(p, t, t, t1);
574 brw_AND(p, t, t, brw_imm_ud(0x1));
575 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
576 get_element(t, 0), brw_imm_ud(0));
577 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
578 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
579 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
580 get_element(t, 1), brw_imm_ud(0));
581 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
582 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
583 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
584 get_element(t, 2), brw_imm_ud(0));
585 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
586 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
587
588 /* test farz, xmax, ymax plane */
589 /* clip.xyz > clip.w */
590 brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
591 brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
592 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
593
594 /* All vertices are outside of a plane, rejected */
595 brw_AND(p, t, t1, t2);
596 brw_AND(p, t, t, t3);
597 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
598 brw_OR(p, tmp0, tmp0, get_element(t, 2));
599 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
600 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
601 brw_IF(p, BRW_EXECUTE_1);
602 {
603 brw_clip_kill_thread(c);
604 }
605 brw_ENDIF(p);
606 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
607
608 /* some vertices are inside a plane, some are outside,need to clip */
609 brw_XOR(p, t, t1, t2);
610 brw_XOR(p, t1, t2, t3);
611 brw_OR(p, t, t, t1);
612 brw_AND(p, t, t, brw_imm_ud(0x1));
613 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
614 get_element(t, 0), brw_imm_ud(0));
615 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
616 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
617 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
618 get_element(t, 1), brw_imm_ud(0));
619 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
620 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
621 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
622 get_element(t, 2), brw_imm_ud(0));
623 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
624 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
625
626 release_tmps(c);
627 }
628
629
630 void brw_emit_tri_clip( struct brw_clip_compile *c )
631 {
632 struct brw_codegen *p = &c->func;
633 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
634 brw_clip_tri_init_vertices(c);
635 brw_clip_init_clipmask(c);
636 brw_clip_init_ff_sync(c);
637
638 /* if -ve rhw workaround bit is set,
639 do cliptest */
640 if (p->devinfo->has_negative_rhw_bug) {
641 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
642 brw_imm_ud(1<<20));
643 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
644 brw_IF(p, BRW_EXECUTE_1);
645 {
646 brw_clip_test(c);
647 }
648 brw_ENDIF(p);
649 }
650 /* Can't push into do_clip_tri because with polygon (or quad)
651 * flatshading, need to apply the flatshade here because we don't
652 * respect the PV when converting to trifan for emit:
653 */
654 if (c->has_flat_shading)
655 brw_clip_tri_flat_shade(c);
656
657 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
658 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
659 do_clip_tri(c);
660 else
661 maybe_do_clip_tri(c);
662
663 brw_clip_tri_emit_polygon(c);
664
665 /* Send an empty message to kill the thread:
666 */
667 brw_clip_kill_thread(c);
668 }