b206797f756bff25f1dcdc658a33e8d0d1ddd8af
[mesa.git] / src / mesa / drivers / dri / i965 / brw_sf_emit.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
33 #include "main/glheader.h"
34 #include "main/macros.h"
35 #include "main/enums.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_util.h"
43 #include "brw_sf.h"
44
45
46 /**
47 * Determine the vue slot corresponding to the given half of the given register.
48 */
49 static inline int vert_reg_to_vue_slot(struct brw_sf_compile *c, GLuint reg,
50 int half)
51 {
52 return (reg + c->urb_entry_read_offset) * 2 + half;
53 }
54
55 /**
56 * Determine the varying corresponding to the given half of the given
57 * register. half=0 means the first half of a register, half=1 means the
58 * second half.
59 */
60 static inline int vert_reg_to_varying(struct brw_sf_compile *c, GLuint reg,
61 int half)
62 {
63 int vue_slot = vert_reg_to_vue_slot(c, reg, half);
64 return c->vue_map.slot_to_varying[vue_slot];
65 }
66
67 /**
68 * Determine the register corresponding to the given vue slot
69 */
70 static struct brw_reg get_vue_slot(struct brw_sf_compile *c,
71 struct brw_reg vert,
72 int vue_slot)
73 {
74 GLuint off = vue_slot / 2 - c->urb_entry_read_offset;
75 GLuint sub = vue_slot % 2;
76
77 return brw_vec4_grf(vert.nr + off, sub * 4);
78 }
79
80 /**
81 * Determine the register corresponding to the given varying.
82 */
83 static struct brw_reg get_varying(struct brw_sf_compile *c,
84 struct brw_reg vert,
85 GLuint varying)
86 {
87 int vue_slot = c->vue_map.varying_to_slot[varying];
88 assert (vue_slot >= c->urb_entry_read_offset);
89 return get_vue_slot(c, vert, vue_slot);
90 }
91
92 static bool
93 have_attr(struct brw_sf_compile *c, GLuint attr)
94 {
95 return (c->key.attrs & BITFIELD64_BIT(attr)) ? 1 : 0;
96 }
97
98 /***********************************************************************
99 * Twoside lighting
100 */
101 static void copy_bfc( struct brw_sf_compile *c,
102 struct brw_reg vert )
103 {
104 struct brw_compile *p = &c->func;
105 GLuint i;
106
107 for (i = 0; i < 2; i++) {
108 if (have_attr(c, VARYING_SLOT_COL0+i) &&
109 have_attr(c, VARYING_SLOT_BFC0+i))
110 brw_MOV(p,
111 get_varying(c, vert, VARYING_SLOT_COL0+i),
112 get_varying(c, vert, VARYING_SLOT_BFC0+i));
113 }
114 }
115
116
117 static void do_twoside_color( struct brw_sf_compile *c )
118 {
119 struct brw_compile *p = &c->func;
120 GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L;
121
122 /* Already done in clip program:
123 */
124 if (c->key.primitive == SF_UNFILLED_TRIS)
125 return;
126
127 /* If the vertex shader provides backface color, do the selection. The VS
128 * promises to set up the front color if the backface color is provided, but
129 * it may contain junk if never written to.
130 */
131 if (!(have_attr(c, VARYING_SLOT_COL0) && have_attr(c, VARYING_SLOT_BFC0)) &&
132 !(have_attr(c, VARYING_SLOT_COL1) && have_attr(c, VARYING_SLOT_BFC1)))
133 return;
134
135 /* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
136 * to get all channels active inside the IF. In the clipping code
137 * we run with NoMask, so it's not an option and we can use
138 * BRW_EXECUTE_1 for all comparisions.
139 */
140 brw_push_insn_state(p);
141 brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0));
142 brw_IF(p, BRW_EXECUTE_4);
143 {
144 switch (c->nr_verts) {
145 case 3: copy_bfc(c, c->vert[2]);
146 case 2: copy_bfc(c, c->vert[1]);
147 case 1: copy_bfc(c, c->vert[0]);
148 }
149 }
150 brw_ENDIF(p);
151 brw_pop_insn_state(p);
152 }
153
154
155
156 /***********************************************************************
157 * Flat shading
158 */
159
160 static void copy_flatshaded_attributes(struct brw_sf_compile *c,
161 struct brw_reg dst,
162 struct brw_reg src)
163 {
164 struct brw_compile *p = &c->func;
165 int i;
166
167 for (i = 0; i < c->vue_map.num_slots; i++) {
168 if (c->key.interpolation_mode.mode[i] == INTERP_QUALIFIER_FLAT) {
169 brw_MOV(p,
170 get_vue_slot(c, dst, i),
171 get_vue_slot(c, src, i));
172 }
173 }
174 }
175
176 static int count_flatshaded_attributes(struct brw_sf_compile *c)
177 {
178 int i;
179 int count = 0;
180
181 for (i = 0; i < c->vue_map.num_slots; i++)
182 if (c->key.interpolation_mode.mode[i] == INTERP_QUALIFIER_FLAT)
183 count++;
184
185 return count;
186 }
187
188
189
190 /* Need to use a computed jump to copy flatshaded attributes as the
191 * vertices are ordered according to y-coordinate before reaching this
192 * point, so the PV could be anywhere.
193 */
194 static void do_flatshade_triangle( struct brw_sf_compile *c )
195 {
196 struct brw_compile *p = &c->func;
197 struct brw_context *brw = p->brw;
198 struct brw_reg ip = brw_ip_reg();
199 GLuint nr;
200 GLuint jmpi = 1;
201
202 /* Already done in clip program:
203 */
204 if (c->key.primitive == SF_UNFILLED_TRIS)
205 return;
206
207 if (brw->gen == 5)
208 jmpi = 2;
209
210 nr = count_flatshaded_attributes(c);
211
212 brw_push_insn_state(p);
213
214 brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));
215 brw_JMPI(p, ip, ip, c->pv);
216
217 copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);
218 copy_flatshaded_attributes(c, c->vert[2], c->vert[0]);
219 brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1)));
220
221 copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);
222 copy_flatshaded_attributes(c, c->vert[2], c->vert[1]);
223 brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2));
224
225 copy_flatshaded_attributes(c, c->vert[0], c->vert[2]);
226 copy_flatshaded_attributes(c, c->vert[1], c->vert[2]);
227
228 brw_pop_insn_state(p);
229 }
230
231
232 static void do_flatshade_line( struct brw_sf_compile *c )
233 {
234 struct brw_compile *p = &c->func;
235 struct brw_context *brw = p->brw;
236 struct brw_reg ip = brw_ip_reg();
237 GLuint nr;
238 GLuint jmpi = 1;
239
240 /* Already done in clip program:
241 */
242 if (c->key.primitive == SF_UNFILLED_TRIS)
243 return;
244
245 if (brw->gen == 5)
246 jmpi = 2;
247
248 nr = count_flatshaded_attributes(c);
249
250 brw_push_insn_state(p);
251
252 brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));
253 brw_JMPI(p, ip, ip, c->pv);
254 copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);
255
256 brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr));
257 copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);
258
259 brw_pop_insn_state(p);
260 }
261
262
263
264 /***********************************************************************
265 * Triangle setup.
266 */
267
268
269 static void alloc_regs( struct brw_sf_compile *c )
270 {
271 GLuint reg, i;
272
273 /* Values computed by fixed function unit:
274 */
275 c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D);
276 c->det = brw_vec1_grf(1, 2);
277 c->dx0 = brw_vec1_grf(1, 3);
278 c->dx2 = brw_vec1_grf(1, 4);
279 c->dy0 = brw_vec1_grf(1, 5);
280 c->dy2 = brw_vec1_grf(1, 6);
281
282 /* z and 1/w passed in seperately:
283 */
284 c->z[0] = brw_vec1_grf(2, 0);
285 c->inv_w[0] = brw_vec1_grf(2, 1);
286 c->z[1] = brw_vec1_grf(2, 2);
287 c->inv_w[1] = brw_vec1_grf(2, 3);
288 c->z[2] = brw_vec1_grf(2, 4);
289 c->inv_w[2] = brw_vec1_grf(2, 5);
290
291 /* The vertices:
292 */
293 reg = 3;
294 for (i = 0; i < c->nr_verts; i++) {
295 c->vert[i] = brw_vec8_grf(reg, 0);
296 reg += c->nr_attr_regs;
297 }
298
299 /* Temporaries, allocated after last vertex reg.
300 */
301 c->inv_det = brw_vec1_grf(reg, 0); reg++;
302 c->a1_sub_a0 = brw_vec8_grf(reg, 0); reg++;
303 c->a2_sub_a0 = brw_vec8_grf(reg, 0); reg++;
304 c->tmp = brw_vec8_grf(reg, 0); reg++;
305
306 /* Note grf allocation:
307 */
308 c->prog_data.total_grf = reg;
309
310
311 /* Outputs of this program - interpolation coefficients for
312 * rasterization:
313 */
314 c->m1Cx = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 1, 0);
315 c->m2Cy = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 2, 0);
316 c->m3C0 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 3, 0);
317 }
318
319
320 static void copy_z_inv_w( struct brw_sf_compile *c )
321 {
322 struct brw_compile *p = &c->func;
323 GLuint i;
324
325 brw_push_insn_state(p);
326
327 /* Copy both scalars with a single MOV:
328 */
329 for (i = 0; i < c->nr_verts; i++)
330 brw_MOV(p, vec2(suboffset(c->vert[i], 2)), vec2(c->z[i]));
331
332 brw_pop_insn_state(p);
333 }
334
335
336 static void invert_det( struct brw_sf_compile *c)
337 {
338 /* Looks like we invert all 8 elements just to get 1/det in
339 * position 2 !?!
340 */
341 brw_math(&c->func,
342 c->inv_det,
343 BRW_MATH_FUNCTION_INV,
344 0,
345 c->det,
346 BRW_MATH_DATA_SCALAR,
347 BRW_MATH_PRECISION_FULL);
348
349 }
350
351
352 static bool
353 calculate_masks(struct brw_sf_compile *c,
354 GLuint reg,
355 GLushort *pc,
356 GLushort *pc_persp,
357 GLushort *pc_linear)
358 {
359 bool is_last_attr = (reg == c->nr_setup_regs - 1);
360 enum glsl_interp_qualifier interp;
361
362 *pc_persp = 0;
363 *pc_linear = 0;
364 *pc = 0xf;
365
366 interp = c->key.interpolation_mode.mode[vert_reg_to_vue_slot(c, reg, 0)];
367 if (interp == INTERP_QUALIFIER_SMOOTH) {
368 *pc_linear = 0xf;
369 *pc_persp = 0xf;
370 } else if (interp == INTERP_QUALIFIER_NOPERSPECTIVE)
371 *pc_linear = 0xf;
372
373 /* Maybe only processs one attribute on the final round:
374 */
375 if (vert_reg_to_varying(c, reg, 1) != BRW_VARYING_SLOT_COUNT) {
376 *pc |= 0xf0;
377
378 interp = c->key.interpolation_mode.mode[vert_reg_to_vue_slot(c, reg, 1)];
379 if (interp == INTERP_QUALIFIER_SMOOTH) {
380 *pc_linear |= 0xf0;
381 *pc_persp |= 0xf0;
382 } else if (interp == INTERP_QUALIFIER_NOPERSPECTIVE)
383 *pc_linear |= 0xf0;
384 }
385
386 return is_last_attr;
387 }
388
389 /* Calculates the predicate control for which channels of a reg
390 * (containing 2 attrs) to do point sprite coordinate replacement on.
391 */
392 static uint16_t
393 calculate_point_sprite_mask(struct brw_sf_compile *c, GLuint reg)
394 {
395 int varying1, varying2;
396 uint16_t pc = 0;
397
398 varying1 = vert_reg_to_varying(c, reg, 0);
399 if (varying1 >= VARYING_SLOT_TEX0 && varying1 <= VARYING_SLOT_TEX7) {
400 if (c->key.point_sprite_coord_replace & (1 << (varying1 - VARYING_SLOT_TEX0)))
401 pc |= 0x0f;
402 }
403 if (varying1 == BRW_VARYING_SLOT_PNTC)
404 pc |= 0x0f;
405
406 varying2 = vert_reg_to_varying(c, reg, 1);
407 if (varying2 >= VARYING_SLOT_TEX0 && varying2 <= VARYING_SLOT_TEX7) {
408 if (c->key.point_sprite_coord_replace & (1 << (varying2 -
409 VARYING_SLOT_TEX0)))
410 pc |= 0xf0;
411 }
412 if (varying2 == BRW_VARYING_SLOT_PNTC)
413 pc |= 0xf0;
414
415 return pc;
416 }
417
418
419
420 void brw_emit_tri_setup(struct brw_sf_compile *c, bool allocate)
421 {
422 struct brw_compile *p = &c->func;
423 GLuint i;
424
425 c->nr_verts = 3;
426
427 if (allocate)
428 alloc_regs(c);
429
430 invert_det(c);
431 copy_z_inv_w(c);
432
433 if (c->key.do_twoside_color)
434 do_twoside_color(c);
435
436 if (c->has_flat_shading)
437 do_flatshade_triangle(c);
438
439
440 for (i = 0; i < c->nr_setup_regs; i++)
441 {
442 /* Pair of incoming attributes:
443 */
444 struct brw_reg a0 = offset(c->vert[0], i);
445 struct brw_reg a1 = offset(c->vert[1], i);
446 struct brw_reg a2 = offset(c->vert[2], i);
447 GLushort pc, pc_persp, pc_linear;
448 bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
449
450 if (pc_persp)
451 {
452 brw_set_predicate_control_flag_value(p, pc_persp);
453 brw_MUL(p, a0, a0, c->inv_w[0]);
454 brw_MUL(p, a1, a1, c->inv_w[1]);
455 brw_MUL(p, a2, a2, c->inv_w[2]);
456 }
457
458
459 /* Calculate coefficients for interpolated values:
460 */
461 if (pc_linear)
462 {
463 brw_set_predicate_control_flag_value(p, pc_linear);
464
465 brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
466 brw_ADD(p, c->a2_sub_a0, a2, negate(a0));
467
468 /* calculate dA/dx
469 */
470 brw_MUL(p, brw_null_reg(), c->a1_sub_a0, c->dy2);
471 brw_MAC(p, c->tmp, c->a2_sub_a0, negate(c->dy0));
472 brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
473
474 /* calculate dA/dy
475 */
476 brw_MUL(p, brw_null_reg(), c->a2_sub_a0, c->dx0);
477 brw_MAC(p, c->tmp, c->a1_sub_a0, negate(c->dx2));
478 brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
479 }
480
481 {
482 brw_set_predicate_control_flag_value(p, pc);
483 /* start point for interpolation
484 */
485 brw_MOV(p, c->m3C0, a0);
486
487 /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
488 * the send instruction:
489 */
490 brw_urb_WRITE(p,
491 brw_null_reg(),
492 0,
493 brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
494 last ? BRW_URB_WRITE_EOT_COMPLETE
495 : BRW_URB_WRITE_NO_FLAGS,
496 4, /* msg len */
497 0, /* response len */
498 i*4, /* offset */
499 BRW_URB_SWIZZLE_TRANSPOSE); /* XXX: Swizzle control "SF to windower" */
500 }
501 }
502 }
503
504
505
506 void brw_emit_line_setup(struct brw_sf_compile *c, bool allocate)
507 {
508 struct brw_compile *p = &c->func;
509 GLuint i;
510
511
512 c->nr_verts = 2;
513
514 if (allocate)
515 alloc_regs(c);
516
517 invert_det(c);
518 copy_z_inv_w(c);
519
520 if (c->has_flat_shading)
521 do_flatshade_line(c);
522
523 for (i = 0; i < c->nr_setup_regs; i++)
524 {
525 /* Pair of incoming attributes:
526 */
527 struct brw_reg a0 = offset(c->vert[0], i);
528 struct brw_reg a1 = offset(c->vert[1], i);
529 GLushort pc, pc_persp, pc_linear;
530 bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
531
532 if (pc_persp)
533 {
534 brw_set_predicate_control_flag_value(p, pc_persp);
535 brw_MUL(p, a0, a0, c->inv_w[0]);
536 brw_MUL(p, a1, a1, c->inv_w[1]);
537 }
538
539 /* Calculate coefficients for position, color:
540 */
541 if (pc_linear) {
542 brw_set_predicate_control_flag_value(p, pc_linear);
543
544 brw_ADD(p, c->a1_sub_a0, a1, negate(a0));
545
546 brw_MUL(p, c->tmp, c->a1_sub_a0, c->dx0);
547 brw_MUL(p, c->m1Cx, c->tmp, c->inv_det);
548
549 brw_MUL(p, c->tmp, c->a1_sub_a0, c->dy0);
550 brw_MUL(p, c->m2Cy, c->tmp, c->inv_det);
551 }
552
553 {
554 brw_set_predicate_control_flag_value(p, pc);
555
556 /* start point for interpolation
557 */
558 brw_MOV(p, c->m3C0, a0);
559
560 /* Copy m0..m3 to URB.
561 */
562 brw_urb_WRITE(p,
563 brw_null_reg(),
564 0,
565 brw_vec8_grf(0, 0),
566 last ? BRW_URB_WRITE_EOT_COMPLETE
567 : BRW_URB_WRITE_NO_FLAGS,
568 4, /* msg len */
569 0, /* response len */
570 i*4, /* urb destination offset */
571 BRW_URB_SWIZZLE_TRANSPOSE);
572 }
573 }
574 }
575
576 void brw_emit_point_sprite_setup(struct brw_sf_compile *c, bool allocate)
577 {
578 struct brw_compile *p = &c->func;
579 GLuint i;
580
581 c->nr_verts = 1;
582
583 if (allocate)
584 alloc_regs(c);
585
586 copy_z_inv_w(c);
587 for (i = 0; i < c->nr_setup_regs; i++)
588 {
589 struct brw_reg a0 = offset(c->vert[0], i);
590 GLushort pc, pc_persp, pc_linear, pc_coord_replace;
591 bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
592
593 pc_coord_replace = calculate_point_sprite_mask(c, i);
594 pc_persp &= ~pc_coord_replace;
595
596 if (pc_persp) {
597 brw_set_predicate_control_flag_value(p, pc_persp);
598 brw_MUL(p, a0, a0, c->inv_w[0]);
599 }
600
601 /* Point sprite coordinate replacement: A texcoord with this
602 * enabled gets replaced with the value (x, y, 0, 1) where x and
603 * y vary from 0 to 1 across the horizontal and vertical of the
604 * point.
605 */
606 if (pc_coord_replace) {
607 brw_set_predicate_control_flag_value(p, pc_coord_replace);
608 /* Caculate 1.0/PointWidth */
609 brw_math(&c->func,
610 c->tmp,
611 BRW_MATH_FUNCTION_INV,
612 0,
613 c->dx0,
614 BRW_MATH_DATA_SCALAR,
615 BRW_MATH_PRECISION_FULL);
616
617 brw_set_access_mode(p, BRW_ALIGN_16);
618
619 /* dA/dx, dA/dy */
620 brw_MOV(p, c->m1Cx, brw_imm_f(0.0));
621 brw_MOV(p, c->m2Cy, brw_imm_f(0.0));
622 brw_MOV(p, brw_writemask(c->m1Cx, WRITEMASK_X), c->tmp);
623 if (c->key.sprite_origin_lower_left) {
624 brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), negate(c->tmp));
625 } else {
626 brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), c->tmp);
627 }
628
629 /* attribute constant offset */
630 brw_MOV(p, c->m3C0, brw_imm_f(0.0));
631 if (c->key.sprite_origin_lower_left) {
632 brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_YW), brw_imm_f(1.0));
633 } else {
634 brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_W), brw_imm_f(1.0));
635 }
636
637 brw_set_access_mode(p, BRW_ALIGN_1);
638 }
639
640 if (pc & ~pc_coord_replace) {
641 brw_set_predicate_control_flag_value(p, pc & ~pc_coord_replace);
642 brw_MOV(p, c->m1Cx, brw_imm_ud(0));
643 brw_MOV(p, c->m2Cy, brw_imm_ud(0));
644 brw_MOV(p, c->m3C0, a0); /* constant value */
645 }
646
647
648 brw_set_predicate_control_flag_value(p, pc);
649 /* Copy m0..m3 to URB. */
650 brw_urb_WRITE(p,
651 brw_null_reg(),
652 0,
653 brw_vec8_grf(0, 0),
654 last ? BRW_URB_WRITE_EOT_COMPLETE
655 : BRW_URB_WRITE_NO_FLAGS,
656 4, /* msg len */
657 0, /* response len */
658 i*4, /* urb destination offset */
659 BRW_URB_SWIZZLE_TRANSPOSE);
660 }
661 }
662
663 /* Points setup - several simplifications as all attributes are
664 * constant across the face of the point (point sprites excluded!)
665 */
666 void brw_emit_point_setup(struct brw_sf_compile *c, bool allocate)
667 {
668 struct brw_compile *p = &c->func;
669 GLuint i;
670
671 c->nr_verts = 1;
672
673 if (allocate)
674 alloc_regs(c);
675
676 copy_z_inv_w(c);
677
678 brw_MOV(p, c->m1Cx, brw_imm_ud(0)); /* zero - move out of loop */
679 brw_MOV(p, c->m2Cy, brw_imm_ud(0)); /* zero - move out of loop */
680
681 for (i = 0; i < c->nr_setup_regs; i++)
682 {
683 struct brw_reg a0 = offset(c->vert[0], i);
684 GLushort pc, pc_persp, pc_linear;
685 bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
686
687 if (pc_persp)
688 {
689 /* This seems odd as the values are all constant, but the
690 * fragment shader will be expecting it:
691 */
692 brw_set_predicate_control_flag_value(p, pc_persp);
693 brw_MUL(p, a0, a0, c->inv_w[0]);
694 }
695
696
697 /* The delta values are always zero, just send the starting
698 * coordinate. Again, this is to fit in with the interpolation
699 * code in the fragment shader.
700 */
701 {
702 brw_set_predicate_control_flag_value(p, pc);
703
704 brw_MOV(p, c->m3C0, a0); /* constant value */
705
706 /* Copy m0..m3 to URB.
707 */
708 brw_urb_WRITE(p,
709 brw_null_reg(),
710 0,
711 brw_vec8_grf(0, 0),
712 last ? BRW_URB_WRITE_EOT_COMPLETE
713 : BRW_URB_WRITE_NO_FLAGS,
714 4, /* msg len */
715 0, /* response len */
716 i*4, /* urb destination offset */
717 BRW_URB_SWIZZLE_TRANSPOSE);
718 }
719 }
720 }
721
722 void brw_emit_anyprim_setup( struct brw_sf_compile *c )
723 {
724 struct brw_compile *p = &c->func;
725 struct brw_reg ip = brw_ip_reg();
726 struct brw_reg payload_prim = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0);
727 struct brw_reg payload_attr = get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0), 0);
728 struct brw_reg primmask;
729 int jmp;
730 struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
731
732 GLuint saveflag;
733
734 c->nr_verts = 3;
735 alloc_regs(c);
736
737 primmask = retype(get_element(c->tmp, 0), BRW_REGISTER_TYPE_UD);
738
739 brw_MOV(p, primmask, brw_imm_ud(1));
740 brw_SHL(p, primmask, primmask, payload_prim);
741
742 brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
743 brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_TRILIST) |
744 (1<<_3DPRIM_TRISTRIP) |
745 (1<<_3DPRIM_TRIFAN) |
746 (1<<_3DPRIM_TRISTRIP_REVERSE) |
747 (1<<_3DPRIM_POLYGON) |
748 (1<<_3DPRIM_RECTLIST) |
749 (1<<_3DPRIM_TRIFAN_NOSTIPPLE)));
750 jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store;
751 {
752 saveflag = p->flag_value;
753 brw_push_insn_state(p);
754 brw_emit_tri_setup( c, false );
755 brw_pop_insn_state(p);
756 p->flag_value = saveflag;
757 /* note - thread killed in subroutine, so must
758 * restore the flag which is changed when building
759 * the subroutine. fix #13240
760 */
761 }
762 brw_land_fwd_jump(p, jmp);
763
764 brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
765 brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_LINELIST) |
766 (1<<_3DPRIM_LINESTRIP) |
767 (1<<_3DPRIM_LINELOOP) |
768 (1<<_3DPRIM_LINESTRIP_CONT) |
769 (1<<_3DPRIM_LINESTRIP_BF) |
770 (1<<_3DPRIM_LINESTRIP_CONT_BF)));
771 jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store;
772 {
773 saveflag = p->flag_value;
774 brw_push_insn_state(p);
775 brw_emit_line_setup( c, false );
776 brw_pop_insn_state(p);
777 p->flag_value = saveflag;
778 /* note - thread killed in subroutine */
779 }
780 brw_land_fwd_jump(p, jmp);
781
782 brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
783 brw_AND(p, v1_null_ud, payload_attr, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE));
784 jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store;
785 {
786 saveflag = p->flag_value;
787 brw_push_insn_state(p);
788 brw_emit_point_sprite_setup( c, false );
789 brw_pop_insn_state(p);
790 p->flag_value = saveflag;
791 }
792 brw_land_fwd_jump(p, jmp);
793
794 brw_emit_point_setup( c, false );
795 }
796
797
798
799