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>
37 #include "intel_batchbuffer.h"
39 #include "brw_defines.h"
40 #include "brw_context.h"
46 static struct brw_reg
get_vert_attr(struct brw_sf_compile
*c
,
50 GLuint off
= c
->attr_to_idx
[attr
] / 2;
51 GLuint sub
= c
->attr_to_idx
[attr
] % 2;
53 return brw_vec4_grf(vert
.nr
+ off
, sub
* 4);
56 static GLboolean
have_attr(struct brw_sf_compile
*c
,
59 return (c
->key
.attrs
& (1<<attr
)) ? 1 : 0;
64 /***********************************************************************
67 static void copy_bfc( struct brw_sf_compile
*c
,
70 struct brw_compile
*p
= &c
->func
;
73 for (i
= 0; i
< 2; i
++) {
74 if (have_attr(c
, VERT_RESULT_COL0
+i
) &&
75 have_attr(c
, VERT_RESULT_BFC0
+i
))
77 get_vert_attr(c
, vert
, VERT_RESULT_COL0
+i
),
78 get_vert_attr(c
, vert
, VERT_RESULT_BFC0
+i
));
83 static void do_twoside_color( struct brw_sf_compile
*c
)
85 struct brw_compile
*p
= &c
->func
;
86 struct brw_instruction
*if_insn
;
87 GLuint backface_conditional
= c
->key
.frontface_ccw
? BRW_CONDITIONAL_G
: BRW_CONDITIONAL_L
;
89 /* Already done in clip program:
91 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
94 /* XXX: What happens if BFC isn't present? This could only happen
95 * for user-supplied vertex programs, as t_vp_build.c always does
98 if (!(have_attr(c
, VERT_RESULT_COL0
) && have_attr(c
, VERT_RESULT_BFC0
)) &&
99 !(have_attr(c
, VERT_RESULT_COL1
) && have_attr(c
, VERT_RESULT_BFC1
)))
102 /* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
103 * to get all channels active inside the IF. In the clipping code
104 * we run with NoMask, so it's not an option and we can use
105 * BRW_EXECUTE_1 for all comparisions.
107 brw_push_insn_state(p
);
108 brw_CMP(p
, vec4(brw_null_reg()), backface_conditional
, c
->det
, brw_imm_f(0));
109 if_insn
= brw_IF(p
, BRW_EXECUTE_4
);
111 switch (c
->nr_verts
) {
112 case 3: copy_bfc(c
, c
->vert
[2]);
113 case 2: copy_bfc(c
, c
->vert
[1]);
114 case 1: copy_bfc(c
, c
->vert
[0]);
117 brw_ENDIF(p
, if_insn
);
118 brw_pop_insn_state(p
);
123 /***********************************************************************
127 #define VERT_RESULT_COLOR_BITS ((1<<VERT_RESULT_COL0) | \
128 (1<<VERT_RESULT_COL1))
130 static void copy_colors( struct brw_sf_compile
*c
,
134 struct brw_compile
*p
= &c
->func
;
137 for (i
= VERT_RESULT_COL0
; i
<= VERT_RESULT_COL1
; i
++) {
140 get_vert_attr(c
, dst
, i
),
141 get_vert_attr(c
, src
, i
));
147 /* Need to use a computed jump to copy flatshaded attributes as the
148 * vertices are ordered according to y-coordinate before reaching this
149 * point, so the PV could be anywhere.
151 static void do_flatshade_triangle( struct brw_sf_compile
*c
)
153 struct brw_compile
*p
= &c
->func
;
154 struct brw_reg ip
= brw_ip_reg();
155 GLuint nr
= brw_count_bits(c
->key
.attrs
& VERT_RESULT_COLOR_BITS
);
159 /* Already done in clip program:
161 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
164 brw_push_insn_state(p
);
166 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_ud(nr
*2+1));
167 brw_JMPI(p
, ip
, ip
, c
->pv
);
169 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
170 copy_colors(c
, c
->vert
[2], c
->vert
[0]);
171 brw_JMPI(p
, ip
, ip
, brw_imm_ud(nr
*4+1));
173 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
174 copy_colors(c
, c
->vert
[2], c
->vert
[1]);
175 brw_JMPI(p
, ip
, ip
, brw_imm_ud(nr
*2));
177 copy_colors(c
, c
->vert
[0], c
->vert
[2]);
178 copy_colors(c
, c
->vert
[1], c
->vert
[2]);
180 brw_pop_insn_state(p
);
184 static void do_flatshade_line( struct brw_sf_compile
*c
)
186 struct brw_compile
*p
= &c
->func
;
187 struct brw_reg ip
= brw_ip_reg();
188 GLuint nr
= brw_count_bits(c
->key
.attrs
& VERT_RESULT_COLOR_BITS
);
193 /* Already done in clip program:
195 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
198 brw_push_insn_state(p
);
200 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_ud(nr
+1));
201 brw_JMPI(p
, ip
, ip
, c
->pv
);
202 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
204 brw_JMPI(p
, ip
, ip
, brw_imm_ud(nr
));
205 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
207 brw_pop_insn_state(p
);
212 /***********************************************************************
217 static void alloc_regs( struct brw_sf_compile
*c
)
221 /* Values computed by fixed function unit:
223 c
->pv
= retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_UD
);
224 c
->det
= brw_vec1_grf(1, 2);
225 c
->dx0
= brw_vec1_grf(1, 3);
226 c
->dx2
= brw_vec1_grf(1, 4);
227 c
->dy0
= brw_vec1_grf(1, 5);
228 c
->dy2
= brw_vec1_grf(1, 6);
230 /* z and 1/w passed in seperately:
232 c
->z
[0] = brw_vec1_grf(2, 0);
233 c
->inv_w
[0] = brw_vec1_grf(2, 1);
234 c
->z
[1] = brw_vec1_grf(2, 2);
235 c
->inv_w
[1] = brw_vec1_grf(2, 3);
236 c
->z
[2] = brw_vec1_grf(2, 4);
237 c
->inv_w
[2] = brw_vec1_grf(2, 5);
242 for (i
= 0; i
< c
->nr_verts
; i
++) {
243 c
->vert
[i
] = brw_vec8_grf(reg
, 0);
244 reg
+= c
->nr_attr_regs
;
247 /* Temporaries, allocated after last vertex reg.
249 c
->inv_det
= brw_vec1_grf(reg
, 0); reg
++;
250 c
->a1_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
251 c
->a2_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
252 c
->tmp
= brw_vec8_grf(reg
, 0); reg
++;
254 /* Note grf allocation:
256 c
->prog_data
.total_grf
= reg
;
259 /* Outputs of this program - interpolation coefficients for
262 c
->m1Cx
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 1, 0);
263 c
->m2Cy
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 2, 0);
264 c
->m3C0
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 3, 0);
268 static void copy_z_inv_w( struct brw_sf_compile
*c
)
270 struct brw_compile
*p
= &c
->func
;
273 brw_push_insn_state(p
);
275 /* Copy both scalars with a single MOV:
277 for (i
= 0; i
< c
->nr_verts
; i
++)
278 brw_MOV(p
, vec2(suboffset(c
->vert
[i
], 2)), vec2(c
->z
[i
]));
280 brw_pop_insn_state(p
);
284 static void invert_det( struct brw_sf_compile
*c
)
286 /* Looks like we invert all 8 elements just to get 1/det in
291 BRW_MATH_FUNCTION_INV
,
292 BRW_MATH_SATURATE_NONE
,
295 BRW_MATH_DATA_SCALAR
,
296 BRW_MATH_PRECISION_FULL
);
300 #define NON_PERPECTIVE_ATTRS (FRAG_BIT_WPOS | \
304 static GLboolean
calculate_masks( struct brw_sf_compile
*c
,
310 GLboolean is_last_attr
= (reg
== c
->nr_setup_regs
- 1);
311 GLuint persp_mask
= c
->key
.attrs
& ~NON_PERPECTIVE_ATTRS
;
314 if (c
->key
.do_flat_shading
)
315 linear_mask
= c
->key
.attrs
& ~(FRAG_BIT_COL0
|FRAG_BIT_COL1
);
317 linear_mask
= c
->key
.attrs
;
323 if (persp_mask
& (1 << c
->idx_to_attr
[reg
*2]))
326 if (linear_mask
& (1 << c
->idx_to_attr
[reg
*2]))
329 /* Maybe only processs one attribute on the final round:
331 if (reg
*2+1 < c
->nr_setup_attrs
) {
334 if (persp_mask
& (1 << c
->idx_to_attr
[reg
*2+1]))
337 if (linear_mask
& (1 << c
->idx_to_attr
[reg
*2+1]))
346 void brw_emit_tri_setup( struct brw_sf_compile
*c
)
348 struct brw_compile
*p
= &c
->func
;
356 if (c
->key
.do_twoside_color
)
359 if (c
->key
.do_flat_shading
)
360 do_flatshade_triangle(c
);
363 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
365 /* Pair of incoming attributes:
367 struct brw_reg a0
= offset(c
->vert
[0], i
);
368 struct brw_reg a1
= offset(c
->vert
[1], i
);
369 struct brw_reg a2
= offset(c
->vert
[2], i
);
370 GLushort pc
, pc_persp
, pc_linear
;
371 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
375 brw_set_predicate_control_flag_value(p
, pc_persp
);
376 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
377 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
378 brw_MUL(p
, a2
, a2
, c
->inv_w
[2]);
382 /* Calculate coefficients for interpolated values:
386 brw_set_predicate_control_flag_value(p
, pc_linear
);
388 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
389 brw_ADD(p
, c
->a2_sub_a0
, a2
, negate(a0
));
393 brw_MUL(p
, brw_null_reg(), c
->a1_sub_a0
, c
->dy2
);
394 brw_MAC(p
, c
->tmp
, c
->a2_sub_a0
, negate(c
->dy0
));
395 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
399 brw_MUL(p
, brw_null_reg(), c
->a2_sub_a0
, c
->dx0
);
400 brw_MAC(p
, c
->tmp
, c
->a1_sub_a0
, negate(c
->dx2
));
401 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
405 brw_set_predicate_control_flag_value(p
, pc
);
406 /* start point for interpolation
408 brw_MOV(p
, c
->m3C0
, a0
);
410 /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
411 * the send instruction:
416 brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
420 0, /* response len */
422 last
, /* writes complete */
424 BRW_URB_SWIZZLE_TRANSPOSE
); /* XXX: Swizzle control "SF to windower" */
431 void brw_emit_line_setup( struct brw_sf_compile
*c
)
433 struct brw_compile
*p
= &c
->func
;
442 if (c
->key
.do_flat_shading
)
443 do_flatshade_line(c
);
445 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
447 /* Pair of incoming attributes:
449 struct brw_reg a0
= offset(c
->vert
[0], i
);
450 struct brw_reg a1
= offset(c
->vert
[1], i
);
451 GLushort pc
, pc_persp
, pc_linear
;
452 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
456 brw_set_predicate_control_flag_value(p
, pc_persp
);
457 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
458 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
461 /* Calculate coefficients for position, color:
464 brw_set_predicate_control_flag_value(p
, pc_linear
);
466 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
468 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dx0
);
469 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
471 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dy0
);
472 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
476 brw_set_predicate_control_flag_value(p
, pc
);
478 /* start point for interpolation
480 brw_MOV(p
, c
->m3C0
, a0
);
482 /* Copy m0..m3 to URB.
491 0, /* response len */
493 last
, /* writes complete */
494 i
*4, /* urb destination offset */
495 BRW_URB_SWIZZLE_TRANSPOSE
);
500 void brw_emit_point_sprite_setup( struct brw_sf_compile
*c
)
502 struct brw_compile
*p
= &c
->func
;
508 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
510 struct brw_sf_point_tex
*tex
= &c
->point_attrs
[c
->idx_to_attr
[2*i
]];
511 struct brw_reg a0
= offset(c
->vert
[0], i
);
512 GLushort pc
, pc_persp
, pc_linear
;
513 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
517 if (!tex
->CoordReplace
) {
518 brw_set_predicate_control_flag_value(p
, pc_persp
);
519 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
523 if (tex
->CoordReplace
) {
524 /* Caculate 1.0/PointWidth */
527 BRW_MATH_FUNCTION_INV
,
528 BRW_MATH_SATURATE_NONE
,
531 BRW_MATH_DATA_SCALAR
,
532 BRW_MATH_PRECISION_FULL
);
534 if (c
->key
.SpriteOrigin
== GL_UPPER_LEFT
) {
535 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
536 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
537 brw_MUL(p
, c
->m2Cy
, c
->tmp
, negate(c
->inv_w
[0]));
538 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
540 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
541 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
542 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_w
[0]);
543 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
546 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0));
547 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0));
551 brw_set_predicate_control_flag_value(p
, pc
);
552 if (tex
->CoordReplace
) {
553 if (c
->key
.SpriteOrigin
== GL_UPPER_LEFT
) {
554 brw_MUL(p
, c
->m3C0
, c
->inv_w
[0], brw_imm_f(1.0));
555 brw_MOV(p
, vec1(suboffset(c
->m3C0
, 0)), brw_imm_f(0.0));
558 brw_MOV(p
, c
->m3C0
, brw_imm_f(0.0));
560 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
563 /* Copy m0..m3 to URB.
572 0, /* response len */
574 last
, /* writes complete */
575 i
*4, /* urb destination offset */
576 BRW_URB_SWIZZLE_TRANSPOSE
);
581 /* Points setup - several simplifications as all attributes are
582 * constant across the face of the point (point sprites excluded!)
584 void brw_emit_point_setup( struct brw_sf_compile
*c
)
586 struct brw_compile
*p
= &c
->func
;
593 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0)); /* zero - move out of loop */
594 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0)); /* zero - move out of loop */
596 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
598 struct brw_reg a0
= offset(c
->vert
[0], i
);
599 GLushort pc
, pc_persp
, pc_linear
;
600 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
604 /* This seems odd as the values are all constant, but the
605 * fragment shader will be expecting it:
607 brw_set_predicate_control_flag_value(p
, pc_persp
);
608 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
612 /* The delta values are always zero, just send the starting
613 * coordinate. Again, this is to fit in with the interpolation
614 * code in the fragment shader.
617 brw_set_predicate_control_flag_value(p
, pc
);
619 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
621 /* Copy m0..m3 to URB.
630 0, /* response len */
632 last
, /* writes complete */
633 i
*4, /* urb destination offset */
634 BRW_URB_SWIZZLE_TRANSPOSE
);
639 void brw_emit_anyprim_setup( struct brw_sf_compile
*c
)
641 struct brw_compile
*p
= &c
->func
;
642 struct brw_reg ip
= brw_ip_reg();
643 struct brw_reg payload_prim
= brw_uw1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0);
644 struct brw_reg payload_attr
= get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0), 0);
645 struct brw_reg primmask
;
646 struct brw_instruction
*jmp
;
647 struct brw_reg v1_null_ud
= vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD
));
651 primmask
= retype(get_element(c
->tmp
, 0), BRW_REGISTER_TYPE_UD
);
653 brw_MOV(p
, primmask
, brw_imm_ud(1));
654 brw_SHL(p
, primmask
, primmask
, payload_prim
);
656 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
657 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_TRILIST
) |
658 (1<<_3DPRIM_TRISTRIP
) |
659 (1<<_3DPRIM_TRIFAN
) |
660 (1<<_3DPRIM_TRISTRIP_REVERSE
) |
661 (1<<_3DPRIM_POLYGON
) |
662 (1<<_3DPRIM_RECTLIST
) |
663 (1<<_3DPRIM_TRIFAN_NOSTIPPLE
)));
664 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_w(0));
666 brw_push_insn_state(p
);
667 brw_emit_tri_setup( c
);
668 brw_pop_insn_state(p
);
669 /* note - thread killed in subroutine */
671 brw_land_fwd_jump(p
, jmp
);
673 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
674 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_LINELIST
) |
675 (1<<_3DPRIM_LINESTRIP
) |
676 (1<<_3DPRIM_LINELOOP
) |
677 (1<<_3DPRIM_LINESTRIP_CONT
) |
678 (1<<_3DPRIM_LINESTRIP_BF
) |
679 (1<<_3DPRIM_LINESTRIP_CONT_BF
)));
680 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_w(0));
682 brw_push_insn_state(p
);
683 brw_emit_line_setup( c
);
684 brw_pop_insn_state(p
);
685 /* note - thread killed in subroutine */
687 brw_land_fwd_jump(p
, jmp
);
689 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
690 brw_AND(p
, v1_null_ud
, payload_attr
, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE
));
691 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_w(0));
693 brw_push_insn_state(p
);
694 brw_emit_point_sprite_setup( c
);
695 brw_pop_insn_state(p
);
697 brw_land_fwd_jump(p
, jmp
);
699 brw_emit_point_setup( c
);