intel/nir: Pass the nir_builder by reference in lower_alpha_to_coverage
[mesa.git] / src / intel / compiler / brw_clip_unfilled.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 "brw_clip.h"
37
38
39 /* This is performed against the original triangles, so no indirection
40 * required:
41 BZZZT!
42 */
43 static void compute_tri_direction( struct brw_clip_compile *c )
44 {
45 struct brw_codegen *p = &c->func;
46 struct brw_reg e = c->reg.tmp0;
47 struct brw_reg f = c->reg.tmp1;
48 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
49 struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset);
50 struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset);
51 struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset);
52
53
54 struct brw_reg v0n = get_tmp(c);
55 struct brw_reg v1n = get_tmp(c);
56 struct brw_reg v2n = get_tmp(c);
57
58 /* Convert to NDC.
59 * NOTE: We can't modify the original vertex coordinates,
60 * as it may impact further operations.
61 * So, we have to keep normalized coordinates in temp registers.
62 *
63 * TBD-KC
64 * Try to optimize unnecessary MOV's.
65 */
66 brw_MOV(p, v0n, v0);
67 brw_MOV(p, v1n, v1);
68 brw_MOV(p, v2n, v2);
69
70 brw_clip_project_position(c, v0n);
71 brw_clip_project_position(c, v1n);
72 brw_clip_project_position(c, v2n);
73
74 /* Calculate the vectors of two edges of the triangle:
75 */
76 brw_ADD(p, e, v0n, negate(v2n));
77 brw_ADD(p, f, v1n, negate(v2n));
78
79 /* Take their crossproduct:
80 */
81 brw_set_default_access_mode(p, BRW_ALIGN_16);
82 brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW),
83 brw_swizzle(f, BRW_SWIZZLE_ZXYW));
84 brw_MAC(p, vec4(e), negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)),
85 brw_swizzle(f, BRW_SWIZZLE_YZXW));
86 brw_set_default_access_mode(p, BRW_ALIGN_1);
87
88 brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
89 }
90
91
92 static void cull_direction( struct brw_clip_compile *c )
93 {
94 struct brw_codegen *p = &c->func;
95 GLuint conditional;
96
97 assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
98 c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL));
99
100 if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL)
101 conditional = BRW_CONDITIONAL_GE;
102 else
103 conditional = BRW_CONDITIONAL_L;
104
105 brw_CMP(p,
106 vec1(brw_null_reg()),
107 conditional,
108 get_element(c->reg.dir, 2),
109 brw_imm_f(0));
110
111 brw_IF(p, BRW_EXECUTE_1);
112 {
113 brw_clip_kill_thread(c);
114 }
115 brw_ENDIF(p);
116 }
117
118
119
120 static void copy_bfc( struct brw_clip_compile *c )
121 {
122 struct brw_codegen *p = &c->func;
123 GLuint conditional;
124
125 /* Do we have any colors to copy?
126 */
127 if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
128 brw_clip_have_varying(c, VARYING_SLOT_BFC0)) &&
129 !(brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
130 brw_clip_have_varying(c, VARYING_SLOT_BFC1)))
131 return;
132
133 /* In some weird degenerate cases we can end up testing the
134 * direction twice, once for culling and once for bfc copying. Oh
135 * well, that's what you get for setting weird GL state.
136 */
137 if (c->key.copy_bfc_ccw)
138 conditional = BRW_CONDITIONAL_GE;
139 else
140 conditional = BRW_CONDITIONAL_L;
141
142 brw_CMP(p,
143 vec1(brw_null_reg()),
144 conditional,
145 get_element(c->reg.dir, 2),
146 brw_imm_f(0));
147
148 brw_IF(p, BRW_EXECUTE_1);
149 {
150 GLuint i;
151
152 for (i = 0; i < 3; i++) {
153 if (brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
154 brw_clip_have_varying(c, VARYING_SLOT_BFC0))
155 brw_MOV(p,
156 byte_offset(c->reg.vertex[i],
157 brw_varying_to_offset(&c->vue_map,
158 VARYING_SLOT_COL0)),
159 byte_offset(c->reg.vertex[i],
160 brw_varying_to_offset(&c->vue_map,
161 VARYING_SLOT_BFC0)));
162
163 if (brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
164 brw_clip_have_varying(c, VARYING_SLOT_BFC1))
165 brw_MOV(p,
166 byte_offset(c->reg.vertex[i],
167 brw_varying_to_offset(&c->vue_map,
168 VARYING_SLOT_COL1)),
169 byte_offset(c->reg.vertex[i],
170 brw_varying_to_offset(&c->vue_map,
171 VARYING_SLOT_BFC1)));
172 }
173 }
174 brw_ENDIF(p);
175 }
176
177
178
179
180 /*
181 GLfloat iz = 1.0 / dir.z;
182 GLfloat ac = dir.x * iz;
183 GLfloat bc = dir.y * iz;
184 offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
185 offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
186 if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) {
187 if (ctx->Polygon.OffsetClamp < 0)
188 offset = MAX2( offset, ctx->Polygon.OffsetClamp );
189 else
190 offset = MIN2( offset, ctx->Polygon.OffsetClamp );
191 }
192 offset *= MRD;
193 */
194 static void compute_offset( struct brw_clip_compile *c )
195 {
196 struct brw_codegen *p = &c->func;
197 struct brw_reg off = c->reg.offset;
198 struct brw_reg dir = c->reg.dir;
199
200 brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
201 brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2));
202
203 brw_CMP(p,
204 vec1(brw_null_reg()),
205 BRW_CONDITIONAL_GE,
206 brw_abs(get_element(off, 0)),
207 brw_abs(get_element(off, 1)));
208
209 brw_SEL(p, vec1(off),
210 brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
211 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
212
213 brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor));
214 brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units));
215 if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) {
216 brw_CMP(p,
217 vec1(brw_null_reg()),
218 c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L,
219 vec1(off),
220 brw_imm_f(c->key.offset_clamp));
221 brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp));
222 }
223 }
224
225
226 static void merge_edgeflags( struct brw_clip_compile *c )
227 {
228 struct brw_codegen *p = &c->func;
229 struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
230
231 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
232 brw_CMP(p,
233 vec1(brw_null_reg()),
234 BRW_CONDITIONAL_EQ,
235 tmp0,
236 brw_imm_ud(_3DPRIM_POLYGON));
237
238 /* Get away with using reg.vertex because we know that this is not
239 * a _3DPRIM_TRISTRIP_REVERSE:
240 */
241 brw_IF(p, BRW_EXECUTE_1);
242 {
243 brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
244 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
245 brw_MOV(p, byte_offset(c->reg.vertex[0],
246 brw_varying_to_offset(&c->vue_map,
247 VARYING_SLOT_EDGE)),
248 brw_imm_f(0));
249 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
250
251 brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
252 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
253 brw_MOV(p, byte_offset(c->reg.vertex[2],
254 brw_varying_to_offset(&c->vue_map,
255 VARYING_SLOT_EDGE)),
256 brw_imm_f(0));
257 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
258 }
259 brw_ENDIF(p);
260 }
261
262
263
264 static void apply_one_offset( struct brw_clip_compile *c,
265 struct brw_indirect vert )
266 {
267 struct brw_codegen *p = &c->func;
268 GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,
269 BRW_VARYING_SLOT_NDC);
270 struct brw_reg z = deref_1f(vert, ndc_offset +
271 2 * type_sz(BRW_REGISTER_TYPE_F));
272
273 brw_ADD(p, z, z, vec1(c->reg.offset));
274 }
275
276
277
278 /***********************************************************************
279 * Output clipped polygon as an unfilled primitive:
280 */
281 static void emit_lines(struct brw_clip_compile *c,
282 bool do_offset)
283 {
284 struct brw_codegen *p = &c->func;
285 struct brw_indirect v0 = brw_indirect(0, 0);
286 struct brw_indirect v1 = brw_indirect(1, 0);
287 struct brw_indirect v0ptr = brw_indirect(2, 0);
288 struct brw_indirect v1ptr = brw_indirect(3, 0);
289
290 /* Need a separate loop for offset:
291 */
292 if (do_offset) {
293 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
294 brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
295
296 brw_DO(p, BRW_EXECUTE_1);
297 {
298 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
299 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
300
301 apply_one_offset(c, v0);
302
303 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
304 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
305 }
306 brw_WHILE(p);
307 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
308 }
309
310 /* v1ptr = &inlist[nr_verts]
311 * *v1ptr = v0
312 */
313 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
314 brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
315 brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
316 brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
317 brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
318
319 brw_DO(p, BRW_EXECUTE_1);
320 {
321 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
322 brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
323 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
324
325 /* draw edge if edgeflag != 0 */
326 brw_CMP(p,
327 vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
328 deref_1f(v0, brw_varying_to_offset(&c->vue_map,
329 VARYING_SLOT_EDGE)),
330 brw_imm_f(0));
331 brw_IF(p, BRW_EXECUTE_1);
332 {
333 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
334 (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
335 | URB_WRITE_PRIM_START);
336 brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE,
337 (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
338 | URB_WRITE_PRIM_END);
339 }
340 brw_ENDIF(p);
341
342 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
343 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
344 }
345 brw_WHILE(p);
346 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
347 }
348
349
350
351 static void emit_points(struct brw_clip_compile *c,
352 bool do_offset )
353 {
354 struct brw_codegen *p = &c->func;
355
356 struct brw_indirect v0 = brw_indirect(0, 0);
357 struct brw_indirect v0ptr = brw_indirect(2, 0);
358
359 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
360 brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
361
362 brw_DO(p, BRW_EXECUTE_1);
363 {
364 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
365 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
366
367 /* draw if edgeflag != 0
368 */
369 brw_CMP(p,
370 vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
371 deref_1f(v0, brw_varying_to_offset(&c->vue_map,
372 VARYING_SLOT_EDGE)),
373 brw_imm_f(0));
374 brw_IF(p, BRW_EXECUTE_1);
375 {
376 if (do_offset)
377 apply_one_offset(c, v0);
378
379 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
380 (_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)
381 | URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
382 }
383 brw_ENDIF(p);
384
385 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
386 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
387 }
388 brw_WHILE(p);
389 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
390 }
391
392
393
394
395
396
397
398 static void emit_primitives( struct brw_clip_compile *c,
399 GLuint mode,
400 bool do_offset )
401 {
402 switch (mode) {
403 case BRW_CLIP_FILL_MODE_FILL:
404 brw_clip_tri_emit_polygon(c);
405 break;
406
407 case BRW_CLIP_FILL_MODE_LINE:
408 emit_lines(c, do_offset);
409 break;
410
411 case BRW_CLIP_FILL_MODE_POINT:
412 emit_points(c, do_offset);
413 break;
414
415 case BRW_CLIP_FILL_MODE_CULL:
416 unreachable("not reached");
417 }
418 }
419
420
421
422 static void emit_unfilled_primitives( struct brw_clip_compile *c )
423 {
424 struct brw_codegen *p = &c->func;
425
426 /* Direction culling has already been done.
427 */
428 if (c->key.fill_ccw != c->key.fill_cw &&
429 c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL &&
430 c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL)
431 {
432 brw_CMP(p,
433 vec1(brw_null_reg()),
434 BRW_CONDITIONAL_GE,
435 get_element(c->reg.dir, 2),
436 brw_imm_f(0));
437
438 brw_IF(p, BRW_EXECUTE_1);
439 {
440 emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
441 }
442 brw_ELSE(p);
443 {
444 emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
445 }
446 brw_ENDIF(p);
447 }
448 else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) {
449 emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
450 }
451 else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) {
452 emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
453 }
454 }
455
456
457
458
459 static void check_nr_verts( struct brw_clip_compile *c )
460 {
461 struct brw_codegen *p = &c->func;
462
463 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
464 brw_IF(p, BRW_EXECUTE_1);
465 {
466 brw_clip_kill_thread(c);
467 }
468 brw_ENDIF(p);
469 }
470
471
472 void brw_emit_unfilled_clip( struct brw_clip_compile *c )
473 {
474 struct brw_codegen *p = &c->func;
475
476 c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
477 (c->key.fill_ccw != c->key.fill_cw) ||
478 c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
479 c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL ||
480 c->key.copy_bfc_cw ||
481 c->key.copy_bfc_ccw);
482
483 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
484 brw_clip_tri_init_vertices(c);
485 brw_clip_init_ff_sync(c);
486
487 assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE));
488
489 if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
490 c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) {
491 brw_clip_kill_thread(c);
492 return;
493 }
494
495 merge_edgeflags(c);
496
497 /* Need to use the inlist indirection here:
498 */
499 if (c->need_direction)
500 compute_tri_direction(c);
501
502 if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
503 c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)
504 cull_direction(c);
505
506 if (c->key.offset_ccw ||
507 c->key.offset_cw)
508 compute_offset(c);
509
510 if (c->key.copy_bfc_ccw ||
511 c->key.copy_bfc_cw)
512 copy_bfc(c);
513
514 /* Need to do this whether we clip or not:
515 */
516 if (c->key.contains_flat_varying)
517 brw_clip_tri_flat_shade(c);
518
519 brw_clip_init_clipmask(c);
520 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
521 brw_IF(p, BRW_EXECUTE_1);
522 {
523 brw_clip_init_planes(c);
524 brw_clip_tri(c);
525 check_nr_verts(c);
526 }
527 brw_ENDIF(p);
528
529 emit_unfilled_primitives(c);
530 brw_clip_kill_thread(c);
531 }