i965/drm: Rename drm_bacon_bo to brw_bo.
[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/macros.h"
33 #include "main/enums.h"
34 #include "program/program.h"
35
36 #include "intel_batchbuffer.h"
37
38 #include "brw_defines.h"
39 #include "brw_context.h"
40 #include "brw_clip.h"
41
42 static void release_tmps( struct brw_clip_compile *c )
43 {
44 c->last_tmp = c->first_tmp;
45 }
46
47
48 void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
49 GLuint nr_verts )
50 {
51 const struct gen_device_info *devinfo = c->func.devinfo;
52 GLuint i = 0,j;
53
54 /* Register usage is static, precompute here:
55 */
56 c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
57
58 if (c->key.nr_userclip) {
59 c->reg.fixed_planes = brw_vec4_grf(i, 0);
60 i += (6 + c->key.nr_userclip + 1) / 2;
61
62 c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
63 }
64 else
65 c->prog_data.curb_read_length = 0;
66
67
68 /* Payload vertices plus space for more generated vertices:
69 */
70 for (j = 0; j < nr_verts; j++) {
71 c->reg.vertex[j] = brw_vec4_grf(i, 0);
72 i += c->nr_regs;
73 }
74
75 if (c->vue_map.num_slots % 2) {
76 /* The VUE has an odd number of slots so the last register is only half
77 * used. Fill the second half with zero.
78 */
79 for (j = 0; j < 3; j++) {
80 GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);
81
82 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
83 }
84 }
85
86 c->reg.t = brw_vec1_grf(i, 0);
87 c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
88 c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
89 c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
90 c->reg.plane_equation = brw_vec4_grf(i, 4);
91 i++;
92
93 c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
94 c->reg.dp = brw_vec1_grf(i, 4);
95 i++;
96
97 c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
98 i++;
99
100 c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
101 i++;
102
103 c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
104 i++;
105
106 if (!c->key.nr_userclip) {
107 c->reg.fixed_planes = brw_vec8_grf(i, 0);
108 i++;
109 }
110
111 if (c->key.do_unfilled) {
112 c->reg.dir = brw_vec4_grf(i, 0);
113 c->reg.offset = brw_vec4_grf(i, 4);
114 i++;
115 c->reg.tmp0 = brw_vec4_grf(i, 0);
116 c->reg.tmp1 = brw_vec4_grf(i, 4);
117 i++;
118 }
119
120 c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
121 c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);
122 i++;
123
124 if (devinfo->gen == 5) {
125 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
126 i++;
127 }
128
129 c->first_tmp = i;
130 c->last_tmp = i;
131
132 c->prog_data.urb_read_length = c->nr_regs; /* ? */
133 c->prog_data.total_grf = i;
134 }
135
136
137
138 void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
139 {
140 struct brw_codegen *p = &c->func;
141 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
142
143 /* Initial list of indices for incoming vertexes:
144 */
145 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
146 brw_CMP(p,
147 vec1(brw_null_reg()),
148 BRW_CONDITIONAL_EQ,
149 tmp0,
150 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
151
152 /* XXX: Is there an easier way to do this? Need to reverse every
153 * second tristrip element: Can ignore sometimes?
154 */
155 brw_IF(p, BRW_EXECUTE_1);
156 {
157 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) );
158 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) );
159 if (c->need_direction)
160 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
161 }
162 brw_ELSE(p);
163 {
164 brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) );
165 brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) );
166 if (c->need_direction)
167 brw_MOV(p, c->reg.dir, brw_imm_f(1));
168 }
169 brw_ENDIF(p);
170
171 brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) );
172 brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
173 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
174 }
175
176
177
178 void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
179 {
180 struct brw_codegen *p = &c->func;
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 brw_IF(p, BRW_EXECUTE_1);
191 {
192 brw_clip_copy_flatshaded_attributes(c, 1, 0);
193 brw_clip_copy_flatshaded_attributes(c, 2, 0);
194 }
195 brw_ELSE(p);
196 {
197 if (c->key.pv_first) {
198 brw_CMP(p,
199 vec1(brw_null_reg()),
200 BRW_CONDITIONAL_EQ,
201 tmp0,
202 brw_imm_ud(_3DPRIM_TRIFAN));
203 brw_IF(p, BRW_EXECUTE_1);
204 {
205 brw_clip_copy_flatshaded_attributes(c, 0, 1);
206 brw_clip_copy_flatshaded_attributes(c, 2, 1);
207 }
208 brw_ELSE(p);
209 {
210 brw_clip_copy_flatshaded_attributes(c, 1, 0);
211 brw_clip_copy_flatshaded_attributes(c, 2, 0);
212 }
213 brw_ENDIF(p);
214 }
215 else {
216 brw_clip_copy_flatshaded_attributes(c, 0, 2);
217 brw_clip_copy_flatshaded_attributes(c, 1, 2);
218 }
219 }
220 brw_ENDIF(p);
221 }
222
223
224 /**
225 * Loads the clip distance for a vertex into `dst`, and ends with
226 * a comparison of it to zero with the condition `cond`.
227 *
228 * - If using a fixed plane, the distance is dot(hpos, plane).
229 * - If using a user clip plane, the distance is directly available in the vertex.
230 */
231 static inline void
232 load_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx,
233 struct brw_reg dst, GLuint hpos_offset, int cond)
234 {
235 struct brw_codegen *p = &c->func;
236
237 dst = vec4(dst);
238 brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
239 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
240 brw_IF(p, BRW_EXECUTE_1);
241 {
242 struct brw_indirect temp_ptr = brw_indirect(7, 0);
243 brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset);
244 brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0));
245 }
246 brw_ELSE(p);
247 {
248 brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
249 brw_DP4(p, dst, dst, c->reg.plane_equation);
250 }
251 brw_ENDIF(p);
252
253 brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f));
254 }
255
256
257 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
258 */
259 void brw_clip_tri( struct brw_clip_compile *c )
260 {
261 struct brw_codegen *p = &c->func;
262 struct brw_indirect vtx = brw_indirect(0, 0);
263 struct brw_indirect vtxPrev = brw_indirect(1, 0);
264 struct brw_indirect vtxOut = brw_indirect(2, 0);
265 struct brw_indirect plane_ptr = brw_indirect(3, 0);
266 struct brw_indirect inlist_ptr = brw_indirect(4, 0);
267 struct brw_indirect outlist_ptr = brw_indirect(5, 0);
268 struct brw_indirect freelist_ptr = brw_indirect(6, 0);
269 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
270 GLint clipdist0_offset = c->key.nr_userclip
271 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
272 : 0;
273
274 brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) );
275 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
276 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
277 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
278
279 brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
280
281 /* Set the initial vertex source mask: The first 6 planes are the bounds
282 * of the view volume; the next 8 planes are the user clipping planes.
283 */
284 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
285
286 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
287 * We'll increment 6 times before we start hitting actual user clipping. */
288 brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
289
290 brw_DO(p, BRW_EXECUTE_1);
291 {
292 /* if (planemask & 1)
293 */
294 brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
295 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
296
297 brw_IF(p, BRW_EXECUTE_1);
298 {
299 /* vtxOut = freelist_ptr++
300 */
301 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) );
302 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
303
304 if (c->key.nr_userclip)
305 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
306 else
307 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
308
309 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
310 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
311
312 brw_DO(p, BRW_EXECUTE_1);
313 {
314 /* vtx = *input_ptr;
315 */
316 brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
317
318 load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L);
319 /* (prev < 0.0f) */
320 brw_IF(p, BRW_EXECUTE_1);
321 {
322 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE);
323 /* IS_POSITIVE(next)
324 */
325 brw_IF(p, BRW_EXECUTE_1);
326 {
327
328 /* Coming back in.
329 */
330 brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
331 brw_math_invert(p, c->reg.t, c->reg.t);
332 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
333
334 /* If (vtxOut == 0) vtxOut = vtxPrev
335 */
336 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
337 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev));
338 brw_inst_set_pred_control(p->devinfo, brw_last_inst,
339 BRW_PREDICATE_NORMAL);
340
341 brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false);
342
343 /* *outlist_ptr++ = vtxOut;
344 * nr_verts++;
345 * vtxOut = 0;
346 */
347 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
348 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
349 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
350 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
351 }
352 brw_ENDIF(p);
353
354 }
355 brw_ELSE(p);
356 {
357 /* *outlist_ptr++ = vtxPrev;
358 * nr_verts++;
359 */
360 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
361 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
362 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
363
364 load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_L);
365 /* (next < 0.0f)
366 */
367 brw_IF(p, BRW_EXECUTE_1);
368 {
369 /* Going out of bounds. Avoid division by zero as we
370 * know dp != dpPrev from DIFFERENT_SIGNS, above.
371 */
372 brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
373 brw_math_invert(p, c->reg.t, c->reg.t);
374 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
375
376 /* If (vtxOut == 0) vtxOut = vtx
377 */
378 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
379 brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx));
380 brw_inst_set_pred_control(p->devinfo, brw_last_inst,
381 BRW_PREDICATE_NORMAL);
382
383 brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true);
384
385 /* *outlist_ptr++ = vtxOut;
386 * nr_verts++;
387 * vtxOut = 0;
388 */
389 brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
390 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
391 brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
392 brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
393 }
394 brw_ENDIF(p);
395 }
396 brw_ENDIF(p);
397
398 /* vtxPrev = vtx;
399 * inlist_ptr++;
400 */
401 brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
402 brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
403
404 /* while (--loopcount != 0)
405 */
406 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
407 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
408 }
409 brw_WHILE(p);
410 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
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 brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
437
438 /* && (planemask>>=1) != 0
439 */
440 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
441 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
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 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
447 }
448
449
450
451 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
452 {
453 struct brw_codegen *p = &c->func;
454
455 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
456 */
457 brw_ADD(p,
458 c->reg.loopcount,
459 c->reg.nr_verts,
460 brw_imm_d(-2));
461 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
462
463 brw_IF(p, BRW_EXECUTE_1);
464 {
465 struct brw_indirect v0 = brw_indirect(0, 0);
466 struct brw_indirect vptr = brw_indirect(1, 0);
467
468 brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
469 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
470
471 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
472 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
473 | URB_WRITE_PRIM_START));
474
475 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
476 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
477
478 brw_DO(p, BRW_EXECUTE_1);
479 {
480 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
481 (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
482
483 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
484 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
485
486 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
487 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
488 }
489 brw_WHILE(p);
490 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
491
492 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_EOT_COMPLETE,
493 ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
494 | URB_WRITE_PRIM_END));
495 }
496 brw_ENDIF(p);
497 }
498
499 static void do_clip_tri( struct brw_clip_compile *c )
500 {
501 brw_clip_init_planes(c);
502
503 brw_clip_tri(c);
504 }
505
506
507 static void maybe_do_clip_tri( struct brw_clip_compile *c )
508 {
509 struct brw_codegen *p = &c->func;
510
511 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
512 brw_IF(p, BRW_EXECUTE_1);
513 {
514 do_clip_tri(c);
515 }
516 brw_ENDIF(p);
517 }
518
519 static void brw_clip_test( struct brw_clip_compile *c )
520 {
521 struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
522 struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
523 struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
524 struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
525
526 struct brw_reg v0 = get_tmp(c);
527 struct brw_reg v1 = get_tmp(c);
528 struct brw_reg v2 = get_tmp(c);
529
530 struct brw_indirect vt0 = brw_indirect(0, 0);
531 struct brw_indirect vt1 = brw_indirect(1, 0);
532 struct brw_indirect vt2 = brw_indirect(2, 0);
533
534 struct brw_codegen *p = &c->func;
535 struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
536
537 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map,
538 VARYING_SLOT_POS);
539
540 brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
541 brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
542 brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
543 brw_MOV(p, v0, deref_4f(vt0, hpos_offset));
544 brw_MOV(p, v1, deref_4f(vt1, hpos_offset));
545 brw_MOV(p, v2, deref_4f(vt2, hpos_offset));
546 brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
547
548 /* test nearz, xmin, ymin plane */
549 /* clip.xyz < -clip.w */
550 brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
551 brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
552 brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
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_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
560 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
561 brw_IF(p, BRW_EXECUTE_1);
562 {
563 brw_clip_kill_thread(c);
564 }
565 brw_ENDIF(p);
566 brw_set_default_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_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
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_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
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_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
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_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
590 brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
591
592 /* All vertices are outside of a plane, rejected */
593 brw_AND(p, t, t1, t2);
594 brw_AND(p, t, t, t3);
595 brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
596 brw_OR(p, tmp0, tmp0, get_element(t, 2));
597 brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
598 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
599 brw_IF(p, BRW_EXECUTE_1);
600 {
601 brw_clip_kill_thread(c);
602 }
603 brw_ENDIF(p);
604 brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
605
606 /* some vertices are inside a plane, some are outside,need to clip */
607 brw_XOR(p, t, t1, t2);
608 brw_XOR(p, t1, t2, t3);
609 brw_OR(p, t, t, t1);
610 brw_AND(p, t, t, brw_imm_ud(0x1));
611 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
612 get_element(t, 0), brw_imm_ud(0));
613 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
614 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
615 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
616 get_element(t, 1), brw_imm_ud(0));
617 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
618 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
619 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
620 get_element(t, 2), brw_imm_ud(0));
621 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
622 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
623
624 release_tmps(c);
625 }
626
627
628 void brw_emit_tri_clip( struct brw_clip_compile *c )
629 {
630 struct brw_codegen *p = &c->func;
631 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
632 brw_clip_tri_init_vertices(c);
633 brw_clip_init_clipmask(c);
634 brw_clip_init_ff_sync(c);
635
636 /* if -ve rhw workaround bit is set,
637 do cliptest */
638 if (p->devinfo->has_negative_rhw_bug) {
639 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
640 brw_imm_ud(1<<20));
641 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
642 brw_IF(p, BRW_EXECUTE_1);
643 {
644 brw_clip_test(c);
645 }
646 brw_ENDIF(p);
647 }
648 /* Can't push into do_clip_tri because with polygon (or quad)
649 * flatshading, need to apply the flatshade here because we don't
650 * respect the PV when converting to trifan for emit:
651 */
652 if (c->key.contains_flat_varying)
653 brw_clip_tri_flat_shade(c);
654
655 if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
656 (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
657 do_clip_tri(c);
658 else
659 maybe_do_clip_tri(c);
660
661 brw_clip_tri_emit_polygon(c);
662
663 /* Send an empty message to kill the thread:
664 */
665 brw_clip_kill_thread(c);
666 }