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 "main/glheader.h"
34 #include "main/macros.h"
35 #include "main/enums.h"
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;
62 /***********************************************************************
65 static void copy_bfc( struct brw_sf_compile
*c
,
68 struct brw_compile
*p
= &c
->func
;
71 for (i
= 0; i
< 2; i
++) {
72 if (have_attr(c
, VERT_RESULT_COL0
+i
) &&
73 have_attr(c
, VERT_RESULT_BFC0
+i
))
75 get_vert_attr(c
, vert
, VERT_RESULT_COL0
+i
),
76 get_vert_attr(c
, vert
, VERT_RESULT_BFC0
+i
));
81 static void do_twoside_color( struct brw_sf_compile
*c
)
83 struct brw_compile
*p
= &c
->func
;
84 struct brw_instruction
*if_insn
;
85 GLuint backface_conditional
= c
->key
.frontface_ccw
? BRW_CONDITIONAL_G
: BRW_CONDITIONAL_L
;
87 /* Already done in clip program:
89 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
92 /* XXX: What happens if BFC isn't present? This could only happen
93 * for user-supplied vertex programs, as t_vp_build.c always does
96 if (!(have_attr(c
, VERT_RESULT_COL0
) && have_attr(c
, VERT_RESULT_BFC0
)) &&
97 !(have_attr(c
, VERT_RESULT_COL1
) && have_attr(c
, VERT_RESULT_BFC1
)))
100 /* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
101 * to get all channels active inside the IF. In the clipping code
102 * we run with NoMask, so it's not an option and we can use
103 * BRW_EXECUTE_1 for all comparisions.
105 brw_push_insn_state(p
);
106 brw_CMP(p
, vec4(brw_null_reg()), backface_conditional
, c
->det
, brw_imm_f(0));
107 if_insn
= brw_IF(p
, BRW_EXECUTE_4
);
109 switch (c
->nr_verts
) {
110 case 3: copy_bfc(c
, c
->vert
[2]);
111 case 2: copy_bfc(c
, c
->vert
[1]);
112 case 1: copy_bfc(c
, c
->vert
[0]);
115 brw_ENDIF(p
, if_insn
);
116 brw_pop_insn_state(p
);
121 /***********************************************************************
125 #define VERT_RESULT_COLOR_BITS ((1<<VERT_RESULT_COL0) | \
126 (1<<VERT_RESULT_COL1))
128 static void copy_colors( struct brw_sf_compile
*c
,
132 struct brw_compile
*p
= &c
->func
;
135 for (i
= VERT_RESULT_COL0
; i
<= VERT_RESULT_COL1
; i
++) {
138 get_vert_attr(c
, dst
, i
),
139 get_vert_attr(c
, src
, i
));
145 /* Need to use a computed jump to copy flatshaded attributes as the
146 * vertices are ordered according to y-coordinate before reaching this
147 * point, so the PV could be anywhere.
149 static void do_flatshade_triangle( struct brw_sf_compile
*c
)
151 struct brw_compile
*p
= &c
->func
;
152 struct brw_reg ip
= brw_ip_reg();
153 GLuint nr
= brw_count_bits(c
->key
.attrs
& VERT_RESULT_COLOR_BITS
);
157 /* Already done in clip program:
159 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
162 brw_push_insn_state(p
);
164 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_ud(nr
*2+1));
165 brw_JMPI(p
, ip
, ip
, c
->pv
);
167 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
168 copy_colors(c
, c
->vert
[2], c
->vert
[0]);
169 brw_JMPI(p
, ip
, ip
, brw_imm_ud(nr
*4+1));
171 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
172 copy_colors(c
, c
->vert
[2], c
->vert
[1]);
173 brw_JMPI(p
, ip
, ip
, brw_imm_ud(nr
*2));
175 copy_colors(c
, c
->vert
[0], c
->vert
[2]);
176 copy_colors(c
, c
->vert
[1], c
->vert
[2]);
178 brw_pop_insn_state(p
);
182 static void do_flatshade_line( struct brw_sf_compile
*c
)
184 struct brw_compile
*p
= &c
->func
;
185 struct brw_reg ip
= brw_ip_reg();
186 GLuint nr
= brw_count_bits(c
->key
.attrs
& VERT_RESULT_COLOR_BITS
);
191 /* Already done in clip program:
193 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
196 brw_push_insn_state(p
);
198 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_ud(nr
+1));
199 brw_JMPI(p
, ip
, ip
, c
->pv
);
200 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
202 brw_JMPI(p
, ip
, ip
, brw_imm_ud(nr
));
203 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
205 brw_pop_insn_state(p
);
210 /***********************************************************************
215 static void alloc_regs( struct brw_sf_compile
*c
)
219 /* Values computed by fixed function unit:
221 c
->pv
= retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_UD
);
222 c
->det
= brw_vec1_grf(1, 2);
223 c
->dx0
= brw_vec1_grf(1, 3);
224 c
->dx2
= brw_vec1_grf(1, 4);
225 c
->dy0
= brw_vec1_grf(1, 5);
226 c
->dy2
= brw_vec1_grf(1, 6);
228 /* z and 1/w passed in seperately:
230 c
->z
[0] = brw_vec1_grf(2, 0);
231 c
->inv_w
[0] = brw_vec1_grf(2, 1);
232 c
->z
[1] = brw_vec1_grf(2, 2);
233 c
->inv_w
[1] = brw_vec1_grf(2, 3);
234 c
->z
[2] = brw_vec1_grf(2, 4);
235 c
->inv_w
[2] = brw_vec1_grf(2, 5);
240 for (i
= 0; i
< c
->nr_verts
; i
++) {
241 c
->vert
[i
] = brw_vec8_grf(reg
, 0);
242 reg
+= c
->nr_attr_regs
;
245 /* Temporaries, allocated after last vertex reg.
247 c
->inv_det
= brw_vec1_grf(reg
, 0); reg
++;
248 c
->a1_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
249 c
->a2_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
250 c
->tmp
= brw_vec8_grf(reg
, 0); reg
++;
252 /* Note grf allocation:
254 c
->prog_data
.total_grf
= reg
;
257 /* Outputs of this program - interpolation coefficients for
260 c
->m1Cx
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 1, 0);
261 c
->m2Cy
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 2, 0);
262 c
->m3C0
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 3, 0);
266 static void copy_z_inv_w( struct brw_sf_compile
*c
)
268 struct brw_compile
*p
= &c
->func
;
271 brw_push_insn_state(p
);
273 /* Copy both scalars with a single MOV:
275 for (i
= 0; i
< c
->nr_verts
; i
++)
276 brw_MOV(p
, vec2(suboffset(c
->vert
[i
], 2)), vec2(c
->z
[i
]));
278 brw_pop_insn_state(p
);
282 static void invert_det( struct brw_sf_compile
*c
)
284 /* Looks like we invert all 8 elements just to get 1/det in
289 BRW_MATH_FUNCTION_INV
,
290 BRW_MATH_SATURATE_NONE
,
293 BRW_MATH_DATA_SCALAR
,
294 BRW_MATH_PRECISION_FULL
);
299 static GLboolean
calculate_masks( struct brw_sf_compile
*c
,
305 GLboolean is_last_attr
= (reg
== c
->nr_setup_regs
- 1);
309 if (c
->key
.do_flat_shading
|| c
->key
.linear_color
)
310 persp_mask
= c
->key
.attrs
& ~(FRAG_BIT_WPOS
|
314 persp_mask
= c
->key
.attrs
& ~(FRAG_BIT_WPOS
);
316 if (c
->key
.do_flat_shading
)
317 linear_mask
= c
->key
.attrs
& ~(FRAG_BIT_COL0
|FRAG_BIT_COL1
);
319 linear_mask
= c
->key
.attrs
;
325 if (persp_mask
& (1 << c
->idx_to_attr
[reg
*2]))
328 if (linear_mask
& (1 << c
->idx_to_attr
[reg
*2]))
331 /* Maybe only processs one attribute on the final round:
333 if (reg
*2+1 < c
->nr_setup_attrs
) {
336 if (persp_mask
& (1 << c
->idx_to_attr
[reg
*2+1]))
339 if (linear_mask
& (1 << c
->idx_to_attr
[reg
*2+1]))
348 void brw_emit_tri_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
350 struct brw_compile
*p
= &c
->func
;
361 if (c
->key
.do_twoside_color
)
364 if (c
->key
.do_flat_shading
)
365 do_flatshade_triangle(c
);
368 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
370 /* Pair of incoming attributes:
372 struct brw_reg a0
= offset(c
->vert
[0], i
);
373 struct brw_reg a1
= offset(c
->vert
[1], i
);
374 struct brw_reg a2
= offset(c
->vert
[2], i
);
375 GLushort pc
, pc_persp
, pc_linear
;
376 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
380 brw_set_predicate_control_flag_value(p
, pc_persp
);
381 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
382 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
383 brw_MUL(p
, a2
, a2
, c
->inv_w
[2]);
387 /* Calculate coefficients for interpolated values:
391 brw_set_predicate_control_flag_value(p
, pc_linear
);
393 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
394 brw_ADD(p
, c
->a2_sub_a0
, a2
, negate(a0
));
398 brw_MUL(p
, brw_null_reg(), c
->a1_sub_a0
, c
->dy2
);
399 brw_MAC(p
, c
->tmp
, c
->a2_sub_a0
, negate(c
->dy0
));
400 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
404 brw_MUL(p
, brw_null_reg(), c
->a2_sub_a0
, c
->dx0
);
405 brw_MAC(p
, c
->tmp
, c
->a1_sub_a0
, negate(c
->dx2
));
406 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
410 brw_set_predicate_control_flag_value(p
, pc
);
411 /* start point for interpolation
413 brw_MOV(p
, c
->m3C0
, a0
);
415 /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
416 * the send instruction:
421 brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
425 0, /* response len */
427 last
, /* writes complete */
429 BRW_URB_SWIZZLE_TRANSPOSE
); /* XXX: Swizzle control "SF to windower" */
436 void brw_emit_line_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
438 struct brw_compile
*p
= &c
->func
;
450 if (c
->key
.do_flat_shading
)
451 do_flatshade_line(c
);
453 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
455 /* Pair of incoming attributes:
457 struct brw_reg a0
= offset(c
->vert
[0], i
);
458 struct brw_reg a1
= offset(c
->vert
[1], i
);
459 GLushort pc
, pc_persp
, pc_linear
;
460 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
464 brw_set_predicate_control_flag_value(p
, pc_persp
);
465 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
466 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
469 /* Calculate coefficients for position, color:
472 brw_set_predicate_control_flag_value(p
, pc_linear
);
474 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
476 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dx0
);
477 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
479 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dy0
);
480 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
484 brw_set_predicate_control_flag_value(p
, pc
);
486 /* start point for interpolation
488 brw_MOV(p
, c
->m3C0
, a0
);
490 /* Copy m0..m3 to URB.
499 0, /* response len */
501 last
, /* writes complete */
502 i
*4, /* urb destination offset */
503 BRW_URB_SWIZZLE_TRANSPOSE
);
508 void brw_emit_point_sprite_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
510 struct brw_compile
*p
= &c
->func
;
519 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
521 struct brw_sf_point_tex
*tex
= &c
->point_attrs
[c
->idx_to_attr
[2*i
]];
522 struct brw_reg a0
= offset(c
->vert
[0], i
);
523 GLushort pc
, pc_persp
, pc_linear
;
524 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
528 if (!tex
->CoordReplace
) {
529 brw_set_predicate_control_flag_value(p
, pc_persp
);
530 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
534 if (tex
->CoordReplace
) {
535 /* Caculate 1.0/PointWidth */
538 BRW_MATH_FUNCTION_INV
,
539 BRW_MATH_SATURATE_NONE
,
542 BRW_MATH_DATA_SCALAR
,
543 BRW_MATH_PRECISION_FULL
);
545 if (c
->key
.SpriteOrigin
== GL_LOWER_LEFT
) {
546 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
547 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
548 brw_MUL(p
, c
->m2Cy
, c
->tmp
, negate(c
->inv_w
[0]));
549 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
551 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
552 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
553 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_w
[0]);
554 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
557 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0));
558 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0));
562 brw_set_predicate_control_flag_value(p
, pc
);
563 if (tex
->CoordReplace
) {
564 if (c
->key
.SpriteOrigin
== GL_LOWER_LEFT
) {
565 brw_MUL(p
, c
->m3C0
, c
->inv_w
[0], brw_imm_f(1.0));
566 brw_MOV(p
, vec1(suboffset(c
->m3C0
, 0)), brw_imm_f(0.0));
569 brw_MOV(p
, c
->m3C0
, brw_imm_f(0.0));
571 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
574 /* Copy m0..m3 to URB.
583 0, /* response len */
585 last
, /* writes complete */
586 i
*4, /* urb destination offset */
587 BRW_URB_SWIZZLE_TRANSPOSE
);
592 /* Points setup - several simplifications as all attributes are
593 * constant across the face of the point (point sprites excluded!)
595 void brw_emit_point_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
597 struct brw_compile
*p
= &c
->func
;
607 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0)); /* zero - move out of loop */
608 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0)); /* zero - move out of loop */
610 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
612 struct brw_reg a0
= offset(c
->vert
[0], i
);
613 GLushort pc
, pc_persp
, pc_linear
;
614 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
618 /* This seems odd as the values are all constant, but the
619 * fragment shader will be expecting it:
621 brw_set_predicate_control_flag_value(p
, pc_persp
);
622 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
626 /* The delta values are always zero, just send the starting
627 * coordinate. Again, this is to fit in with the interpolation
628 * code in the fragment shader.
631 brw_set_predicate_control_flag_value(p
, pc
);
633 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
635 /* Copy m0..m3 to URB.
644 0, /* response len */
646 last
, /* writes complete */
647 i
*4, /* urb destination offset */
648 BRW_URB_SWIZZLE_TRANSPOSE
);
653 void brw_emit_anyprim_setup( struct brw_sf_compile
*c
)
655 struct brw_compile
*p
= &c
->func
;
656 struct brw_reg ip
= brw_ip_reg();
657 struct brw_reg payload_prim
= brw_uw1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0);
658 struct brw_reg payload_attr
= get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0), 0);
659 struct brw_reg primmask
;
660 struct brw_instruction
*jmp
;
661 struct brw_reg v1_null_ud
= vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD
));
668 primmask
= retype(get_element(c
->tmp
, 0), BRW_REGISTER_TYPE_UD
);
670 brw_MOV(p
, primmask
, brw_imm_ud(1));
671 brw_SHL(p
, primmask
, primmask
, payload_prim
);
673 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
674 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_TRILIST
) |
675 (1<<_3DPRIM_TRISTRIP
) |
676 (1<<_3DPRIM_TRIFAN
) |
677 (1<<_3DPRIM_TRISTRIP_REVERSE
) |
678 (1<<_3DPRIM_POLYGON
) |
679 (1<<_3DPRIM_RECTLIST
) |
680 (1<<_3DPRIM_TRIFAN_NOSTIPPLE
)));
681 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_w(0));
683 saveflag
= p
->flag_value
;
684 brw_push_insn_state(p
);
685 brw_emit_tri_setup( c
, GL_FALSE
);
686 brw_pop_insn_state(p
);
687 p
->flag_value
= saveflag
;
688 /* note - thread killed in subroutine, so must
689 * restore the flag which is changed when building
690 * the subroutine. fix #13240
693 brw_land_fwd_jump(p
, jmp
);
695 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
696 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_LINELIST
) |
697 (1<<_3DPRIM_LINESTRIP
) |
698 (1<<_3DPRIM_LINELOOP
) |
699 (1<<_3DPRIM_LINESTRIP_CONT
) |
700 (1<<_3DPRIM_LINESTRIP_BF
) |
701 (1<<_3DPRIM_LINESTRIP_CONT_BF
)));
702 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_w(0));
704 saveflag
= p
->flag_value
;
705 brw_push_insn_state(p
);
706 brw_emit_line_setup( c
, GL_FALSE
);
707 brw_pop_insn_state(p
);
708 p
->flag_value
= saveflag
;
709 /* note - thread killed in subroutine */
711 brw_land_fwd_jump(p
, jmp
);
713 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
714 brw_AND(p
, v1_null_ud
, payload_attr
, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE
));
715 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_w(0));
717 saveflag
= p
->flag_value
;
718 brw_push_insn_state(p
);
719 brw_emit_point_sprite_setup( c
, GL_FALSE
);
720 brw_pop_insn_state(p
);
721 p
->flag_value
= saveflag
;
723 brw_land_fwd_jump(p
, jmp
);
725 brw_emit_point_setup( c
, GL_FALSE
);