2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
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:
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.
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.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "brw_batchbuffer.h"
35 #include "brw_defines.h"
36 #include "brw_context.h"
41 static struct brw_reg
get_vert_attr(struct brw_sf_compile
*c
,
45 GLuint off
= attr
/ 2;
46 GLuint sub
= attr
% 2;
48 return brw_vec4_grf(vert
.nr
+ off
, sub
* 4);
52 /***********************************************************************
55 static void copy_bfc( struct brw_sf_compile
*c
,
58 struct brw_compile
*p
= &c
->func
;
60 if (c
->key
.attr_col0
&& c
->key
.attr_bfc0
)
62 get_vert_attr(c
, vert
, c
->key
.attr_col0
),
63 get_vert_attr(c
, vert
, c
->key
.attr_bfc0
));
65 if (c
->key
.attr_col1
&& c
->key
.attr_bfc1
)
67 get_vert_attr(c
, vert
, c
->key
.attr_col1
),
68 get_vert_attr(c
, vert
, c
->key
.attr_bfc1
));
72 static void do_twoside_color( struct brw_sf_compile
*c
)
74 struct brw_compile
*p
= &c
->func
;
75 struct brw_instruction
*if_insn
;
76 GLuint backface_conditional
= c
->key
.frontface_ccw
? BRW_CONDITIONAL_G
: BRW_CONDITIONAL_L
;
78 /* Already done in clip program:
80 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
83 /* XXX: What happens if BFC isn't present? This could only happen
84 * for user-supplied vertex programs, as t_vp_build.c always does
87 if (!(c
->key
.attr_col0
&& c
->key
.attr_bfc0
) &&
88 !(c
->key
.attr_col1
&& c
->key
.attr_bfc1
))
91 /* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
92 * to get all channels active inside the IF. In the clipping code
93 * we run with NoMask, so it's not an option and we can use
94 * BRW_EXECUTE_1 for all comparisions.
96 brw_push_insn_state(p
);
97 brw_CMP(p
, vec4(brw_null_reg()), backface_conditional
, c
->det
, brw_imm_f(0));
98 if_insn
= brw_IF(p
, BRW_EXECUTE_4
);
100 switch (c
->nr_verts
) {
101 case 3: copy_bfc(c
, c
->vert
[2]);
102 case 2: copy_bfc(c
, c
->vert
[1]);
103 case 1: copy_bfc(c
, c
->vert
[0]);
106 brw_ENDIF(p
, if_insn
);
107 brw_pop_insn_state(p
);
112 /***********************************************************************
116 #define VERT_RESULT_COLOR_BITS ((1<<VERT_RESULT_COL0) | \
117 (1<<VERT_RESULT_COL1))
119 static void copy_colors( struct brw_sf_compile
*c
,
123 struct brw_compile
*p
= &c
->func
;
125 if (c
->key
.attr_col0
)
127 get_vert_attr(c
, dst
, c
->key
.attr_col0
),
128 get_vert_attr(c
, src
, c
->key
.attr_col0
));
130 if (c
->key
.attr_col1
)
132 get_vert_attr(c
, dst
, c
->key
.attr_col1
),
133 get_vert_attr(c
, src
, c
->key
.attr_col1
));
139 /* Need to use a computed jump to copy flatshaded attributes as the
140 * vertices are ordered according to y-coordinate before reaching this
141 * point, so the PV could be anywhere.
143 static void do_flatshade_triangle( struct brw_sf_compile
*c
)
145 struct brw_compile
*p
= &c
->func
;
146 struct brw_reg ip
= brw_ip_reg();
150 if (c
->key
.attr_col0
)
153 if (c
->key
.attr_col1
)
159 /* Already done in clip program:
161 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
164 if (BRW_IS_IGDNG(p
->brw
))
167 brw_push_insn_state(p
);
169 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_d(jmpi
*(nr
*2+1)));
170 brw_JMPI(p
, ip
, ip
, c
->pv
);
172 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
173 copy_colors(c
, c
->vert
[2], c
->vert
[0]);
174 brw_JMPI(p
, ip
, ip
, brw_imm_d(jmpi
*(nr
*4+1)));
176 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
177 copy_colors(c
, c
->vert
[2], c
->vert
[1]);
178 brw_JMPI(p
, ip
, ip
, brw_imm_d(jmpi
*nr
*2));
180 copy_colors(c
, c
->vert
[0], c
->vert
[2]);
181 copy_colors(c
, c
->vert
[1], c
->vert
[2]);
183 brw_pop_insn_state(p
);
187 static void do_flatshade_line( struct brw_sf_compile
*c
)
189 struct brw_compile
*p
= &c
->func
;
190 struct brw_reg ip
= brw_ip_reg();
194 if (c
->key
.attr_col0
)
197 if (c
->key
.attr_col1
)
203 /* Already done in clip program:
205 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
208 if (BRW_IS_IGDNG(p
->brw
))
211 brw_push_insn_state(p
);
213 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_d(jmpi
*(nr
+1)));
214 brw_JMPI(p
, ip
, ip
, c
->pv
);
215 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
217 brw_JMPI(p
, ip
, ip
, brw_imm_ud(jmpi
*nr
));
218 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
220 brw_pop_insn_state(p
);
225 /***********************************************************************
230 static void alloc_regs( struct brw_sf_compile
*c
)
234 /* Values computed by fixed function unit:
236 c
->pv
= retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D
);
237 c
->det
= brw_vec1_grf(1, 2);
238 c
->dx0
= brw_vec1_grf(1, 3);
239 c
->dx2
= brw_vec1_grf(1, 4);
240 c
->dy0
= brw_vec1_grf(1, 5);
241 c
->dy2
= brw_vec1_grf(1, 6);
243 /* z and 1/w passed in seperately:
245 c
->z
[0] = brw_vec1_grf(2, 0);
246 c
->inv_w
[0] = brw_vec1_grf(2, 1);
247 c
->z
[1] = brw_vec1_grf(2, 2);
248 c
->inv_w
[1] = brw_vec1_grf(2, 3);
249 c
->z
[2] = brw_vec1_grf(2, 4);
250 c
->inv_w
[2] = brw_vec1_grf(2, 5);
255 for (i
= 0; i
< c
->nr_verts
; i
++) {
256 c
->vert
[i
] = brw_vec8_grf(reg
, 0);
257 reg
+= c
->nr_attr_regs
;
260 /* Temporaries, allocated after last vertex reg.
262 c
->inv_det
= brw_vec1_grf(reg
, 0); reg
++;
263 c
->a1_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
264 c
->a2_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
265 c
->tmp
= brw_vec8_grf(reg
, 0); reg
++;
267 /* Note grf allocation:
269 c
->prog_data
.total_grf
= reg
;
272 /* Outputs of this program - interpolation coefficients for
275 c
->m1Cx
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 1, 0);
276 c
->m2Cy
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 2, 0);
277 c
->m3C0
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 3, 0);
281 static void copy_z_inv_w( struct brw_sf_compile
*c
)
283 struct brw_compile
*p
= &c
->func
;
286 brw_push_insn_state(p
);
288 /* Copy both scalars with a single MOV:
290 for (i
= 0; i
< c
->nr_verts
; i
++)
291 brw_MOV(p
, vec2(suboffset(c
->vert
[i
], 2)), vec2(c
->z
[i
]));
293 brw_pop_insn_state(p
);
297 static void invert_det( struct brw_sf_compile
*c
)
299 /* Looks like we invert all 8 elements just to get 1/det in
304 BRW_MATH_FUNCTION_INV
,
305 BRW_MATH_SATURATE_NONE
,
308 BRW_MATH_DATA_SCALAR
,
309 BRW_MATH_PRECISION_FULL
);
314 /* Two attributes packed into a wide register. Figure out if either
315 * or both of them need linear/perspective interpolation. Constant
316 * regs are left as-is.
318 static GLboolean
calculate_masks( struct brw_sf_compile
*c
,
324 GLboolean is_last_attr
= (reg
== c
->nr_setup_regs
- 1);
325 GLuint persp_mask
= c
->key
.persp_attrs
;
326 GLuint linear_mask
= (c
->key
.persp_attrs
| c
->key
.linear_attrs
);
332 if (persp_mask
& (1 << (reg
*2)))
335 if (linear_mask
& (1 << (reg
*2)))
338 /* Maybe only processs one attribute on the final round:
340 if (reg
*2+1 < c
->nr_setup_attrs
) {
343 if (persp_mask
& (1 << (reg
*2+1)))
346 if (linear_mask
& (1 << (reg
*2+1)))
354 void brw_emit_null_setup( struct brw_sf_compile
*c
)
356 struct brw_compile
*p
= &c
->func
;
358 /* m0 is implicitly copied from r0 in the send instruction:
363 brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
367 0, /* response len */
369 1, /* writes complete */
371 BRW_URB_SWIZZLE_TRANSPOSE
);
374 void brw_emit_tri_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
376 struct brw_compile
*p
= &c
->func
;
387 if (c
->key
.do_twoside_color
)
390 if (c
->key
.do_flat_shading
)
391 do_flatshade_triangle(c
);
394 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
396 /* Pair of incoming attributes:
398 struct brw_reg a0
= offset(c
->vert
[0], i
);
399 struct brw_reg a1
= offset(c
->vert
[1], i
);
400 struct brw_reg a2
= offset(c
->vert
[2], i
);
401 GLushort pc
, pc_persp
, pc_linear
;
402 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
406 brw_set_predicate_control_flag_value(p
, pc_persp
);
407 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
408 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
409 brw_MUL(p
, a2
, a2
, c
->inv_w
[2]);
413 /* Calculate coefficients for interpolated values:
417 brw_set_predicate_control_flag_value(p
, pc_linear
);
419 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
420 brw_ADD(p
, c
->a2_sub_a0
, a2
, negate(a0
));
424 brw_MUL(p
, brw_null_reg(), c
->a1_sub_a0
, c
->dy2
);
425 brw_MAC(p
, c
->tmp
, c
->a2_sub_a0
, negate(c
->dy0
));
426 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
430 brw_MUL(p
, brw_null_reg(), c
->a2_sub_a0
, c
->dx0
);
431 brw_MAC(p
, c
->tmp
, c
->a1_sub_a0
, negate(c
->dx2
));
432 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
436 brw_set_predicate_control_flag_value(p
, pc
);
437 /* start point for interpolation
439 brw_MOV(p
, c
->m3C0
, a0
);
441 /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
442 * the send instruction:
447 brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
451 0, /* response len */
453 last
, /* writes complete */
455 BRW_URB_SWIZZLE_TRANSPOSE
); /* XXX: Swizzle control "SF to windower" */
462 void brw_emit_line_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
464 struct brw_compile
*p
= &c
->func
;
476 if (c
->key
.do_flat_shading
)
477 do_flatshade_line(c
);
479 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
481 /* Pair of incoming attributes:
483 struct brw_reg a0
= offset(c
->vert
[0], i
);
484 struct brw_reg a1
= offset(c
->vert
[1], i
);
485 GLushort pc
, pc_persp
, pc_linear
;
486 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
490 brw_set_predicate_control_flag_value(p
, pc_persp
);
491 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
492 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
495 /* Calculate coefficients for position, color:
498 brw_set_predicate_control_flag_value(p
, pc_linear
);
500 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
502 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dx0
);
503 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
505 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dy0
);
506 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
510 brw_set_predicate_control_flag_value(p
, pc
);
512 /* start point for interpolation
514 brw_MOV(p
, c
->m3C0
, a0
);
516 /* Copy m0..m3 to URB.
525 0, /* response len */
527 last
, /* writes complete */
528 i
*4, /* urb destination offset */
529 BRW_URB_SWIZZLE_TRANSPOSE
);
534 void brw_emit_point_sprite_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
536 struct brw_compile
*p
= &c
->func
;
546 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
548 /* XXX: only seems to check point_coord_replace_attrs for every
549 * second attribute?!?
551 boolean coord_replace
= !!(c
->key
.point_coord_replace_attrs
& (1<<(2*i
)));
552 struct brw_reg a0
= offset(c
->vert
[0], i
);
553 GLushort pc
, pc_persp
, pc_linear
;
554 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
559 brw_set_predicate_control_flag_value(p
, pc_persp
);
560 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
565 /* Caculate 1.0/PointWidth */
568 BRW_MATH_FUNCTION_INV
,
569 BRW_MATH_SATURATE_NONE
,
572 BRW_MATH_DATA_SCALAR
,
573 BRW_MATH_PRECISION_FULL
);
575 if (c
->key
.sprite_origin_lower_left
) {
576 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
577 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
578 brw_MUL(p
, c
->m2Cy
, c
->tmp
, negate(c
->inv_w
[0]));
579 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
582 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
583 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
584 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_w
[0]);
585 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
589 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0));
590 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0));
594 brw_set_predicate_control_flag_value(p
, pc
);
596 if (c
->key
.sprite_origin_lower_left
) {
597 brw_MUL(p
, c
->m3C0
, c
->inv_w
[0], brw_imm_f(1.0));
598 brw_MOV(p
, vec1(suboffset(c
->m3C0
, 0)), brw_imm_f(0.0));
601 brw_MOV(p
, c
->m3C0
, brw_imm_f(0.0));
605 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
608 /* Copy m0..m3 to URB.
617 0, /* response len */
619 last
, /* writes complete */
620 i
*4, /* urb destination offset */
621 BRW_URB_SWIZZLE_TRANSPOSE
);
626 /* Points setup - several simplifications as all attributes are
627 * constant across the face of the point (point sprites excluded!)
629 void brw_emit_point_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
631 struct brw_compile
*p
= &c
->func
;
641 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0)); /* zero - move out of loop */
642 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0)); /* zero - move out of loop */
644 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
646 struct brw_reg a0
= offset(c
->vert
[0], i
);
647 GLushort pc
, pc_persp
, pc_linear
;
648 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
652 /* This seems odd as the values are all constant, but the
653 * fragment shader will be expecting it:
655 brw_set_predicate_control_flag_value(p
, pc_persp
);
656 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
660 /* The delta values are always zero, just send the starting
661 * coordinate. Again, this is to fit in with the interpolation
662 * code in the fragment shader.
665 brw_set_predicate_control_flag_value(p
, pc
);
667 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
669 /* Copy m0..m3 to URB.
678 0, /* response len */
680 last
, /* writes complete */
681 i
*4, /* urb destination offset */
682 BRW_URB_SWIZZLE_TRANSPOSE
);
687 void brw_emit_anyprim_setup( struct brw_sf_compile
*c
)
689 struct brw_compile
*p
= &c
->func
;
690 struct brw_reg ip
= brw_ip_reg();
691 struct brw_reg payload_prim
= brw_uw1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0);
692 struct brw_reg payload_attr
= get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0), 0);
693 struct brw_reg primmask
;
694 struct brw_instruction
*jmp
;
695 struct brw_reg v1_null_ud
= vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD
));
702 primmask
= retype(get_element(c
->tmp
, 0), BRW_REGISTER_TYPE_UD
);
704 brw_MOV(p
, primmask
, brw_imm_ud(1));
705 brw_SHL(p
, primmask
, primmask
, payload_prim
);
707 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
708 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_TRILIST
) |
709 (1<<_3DPRIM_TRISTRIP
) |
710 (1<<_3DPRIM_TRIFAN
) |
711 (1<<_3DPRIM_TRISTRIP_REVERSE
) |
712 (1<<_3DPRIM_POLYGON
) |
713 (1<<_3DPRIM_RECTLIST
) |
714 (1<<_3DPRIM_TRIFAN_NOSTIPPLE
)));
715 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_d(0));
717 saveflag
= p
->flag_value
;
718 brw_push_insn_state(p
);
719 brw_emit_tri_setup( c
, GL_FALSE
);
720 brw_pop_insn_state(p
);
721 p
->flag_value
= saveflag
;
722 /* note - thread killed in subroutine, so must
723 * restore the flag which is changed when building
724 * the subroutine. fix #13240
727 brw_land_fwd_jump(p
, jmp
);
729 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
730 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_LINELIST
) |
731 (1<<_3DPRIM_LINESTRIP
) |
732 (1<<_3DPRIM_LINELOOP
) |
733 (1<<_3DPRIM_LINESTRIP_CONT
) |
734 (1<<_3DPRIM_LINESTRIP_BF
) |
735 (1<<_3DPRIM_LINESTRIP_CONT_BF
)));
736 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_d(0));
738 saveflag
= p
->flag_value
;
739 brw_push_insn_state(p
);
740 brw_emit_line_setup( c
, GL_FALSE
);
741 brw_pop_insn_state(p
);
742 p
->flag_value
= saveflag
;
743 /* note - thread killed in subroutine */
745 brw_land_fwd_jump(p
, jmp
);
747 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
748 brw_AND(p
, v1_null_ud
, payload_attr
, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE
));
749 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_d(0));
751 saveflag
= p
->flag_value
;
752 brw_push_insn_state(p
);
753 brw_emit_point_sprite_setup( c
, GL_FALSE
);
754 brw_pop_insn_state(p
);
755 p
->flag_value
= saveflag
;
757 brw_land_fwd_jump(p
, jmp
);
759 brw_emit_point_setup( c
, GL_FALSE
);