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
);
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();
191 GLuint nr
= brw_count_bits(c
->key
.attrs
& VERT_RESULT_COLOR_BITS
);
197 /* Already done in clip program:
199 if (c
->key
.primitive
== SF_UNFILLED_TRIS
)
202 if (BRW_IS_IGDNG(p
->brw
))
205 brw_push_insn_state(p
);
207 brw_MUL(p
, c
->pv
, c
->pv
, brw_imm_d(jmpi
*(nr
+1)));
208 brw_JMPI(p
, ip
, ip
, c
->pv
);
209 copy_colors(c
, c
->vert
[1], c
->vert
[0]);
211 brw_JMPI(p
, ip
, ip
, brw_imm_ud(jmpi
*nr
));
212 copy_colors(c
, c
->vert
[0], c
->vert
[1]);
214 brw_pop_insn_state(p
);
219 /***********************************************************************
224 static void alloc_regs( struct brw_sf_compile
*c
)
228 /* Values computed by fixed function unit:
230 c
->pv
= retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D
);
231 c
->det
= brw_vec1_grf(1, 2);
232 c
->dx0
= brw_vec1_grf(1, 3);
233 c
->dx2
= brw_vec1_grf(1, 4);
234 c
->dy0
= brw_vec1_grf(1, 5);
235 c
->dy2
= brw_vec1_grf(1, 6);
237 /* z and 1/w passed in seperately:
239 c
->z
[0] = brw_vec1_grf(2, 0);
240 c
->inv_w
[0] = brw_vec1_grf(2, 1);
241 c
->z
[1] = brw_vec1_grf(2, 2);
242 c
->inv_w
[1] = brw_vec1_grf(2, 3);
243 c
->z
[2] = brw_vec1_grf(2, 4);
244 c
->inv_w
[2] = brw_vec1_grf(2, 5);
249 for (i
= 0; i
< c
->nr_verts
; i
++) {
250 c
->vert
[i
] = brw_vec8_grf(reg
, 0);
251 reg
+= c
->nr_attr_regs
;
254 /* Temporaries, allocated after last vertex reg.
256 c
->inv_det
= brw_vec1_grf(reg
, 0); reg
++;
257 c
->a1_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
258 c
->a2_sub_a0
= brw_vec8_grf(reg
, 0); reg
++;
259 c
->tmp
= brw_vec8_grf(reg
, 0); reg
++;
261 /* Note grf allocation:
263 c
->prog_data
.total_grf
= reg
;
266 /* Outputs of this program - interpolation coefficients for
269 c
->m1Cx
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 1, 0);
270 c
->m2Cy
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 2, 0);
271 c
->m3C0
= brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE
, 3, 0);
275 static void copy_z_inv_w( struct brw_sf_compile
*c
)
277 struct brw_compile
*p
= &c
->func
;
280 brw_push_insn_state(p
);
282 /* Copy both scalars with a single MOV:
284 for (i
= 0; i
< c
->nr_verts
; i
++)
285 brw_MOV(p
, vec2(suboffset(c
->vert
[i
], 2)), vec2(c
->z
[i
]));
287 brw_pop_insn_state(p
);
291 static void invert_det( struct brw_sf_compile
*c
)
293 /* Looks like we invert all 8 elements just to get 1/det in
298 BRW_MATH_FUNCTION_INV
,
299 BRW_MATH_SATURATE_NONE
,
302 BRW_MATH_DATA_SCALAR
,
303 BRW_MATH_PRECISION_FULL
);
308 static GLboolean
calculate_masks( struct brw_sf_compile
*c
,
314 GLboolean is_last_attr
= (reg
== c
->nr_setup_regs
- 1);
318 if (c
->key
.do_flat_shading
|| c
->key
.linear_color
)
319 persp_mask
= c
->key
.attrs
& ~(FRAG_BIT_WPOS
|
323 persp_mask
= c
->key
.attrs
& ~(FRAG_BIT_WPOS
);
325 if (c
->key
.do_flat_shading
)
326 linear_mask
= c
->key
.attrs
& ~(FRAG_BIT_COL0
|FRAG_BIT_COL1
);
328 linear_mask
= c
->key
.attrs
;
334 if (persp_mask
& (1 << c
->idx_to_attr
[reg
*2]))
337 if (linear_mask
& (1 << c
->idx_to_attr
[reg
*2]))
340 /* Maybe only processs one attribute on the final round:
342 if (reg
*2+1 < c
->nr_setup_attrs
) {
345 if (persp_mask
& (1 << c
->idx_to_attr
[reg
*2+1]))
348 if (linear_mask
& (1 << c
->idx_to_attr
[reg
*2+1]))
357 void brw_emit_tri_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
359 struct brw_compile
*p
= &c
->func
;
370 if (c
->key
.do_twoside_color
)
373 if (c
->key
.do_flat_shading
)
374 do_flatshade_triangle(c
);
377 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
379 /* Pair of incoming attributes:
381 struct brw_reg a0
= offset(c
->vert
[0], i
);
382 struct brw_reg a1
= offset(c
->vert
[1], i
);
383 struct brw_reg a2
= offset(c
->vert
[2], i
);
384 GLushort pc
, pc_persp
, pc_linear
;
385 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
389 brw_set_predicate_control_flag_value(p
, pc_persp
);
390 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
391 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
392 brw_MUL(p
, a2
, a2
, c
->inv_w
[2]);
396 /* Calculate coefficients for interpolated values:
400 brw_set_predicate_control_flag_value(p
, pc_linear
);
402 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
403 brw_ADD(p
, c
->a2_sub_a0
, a2
, negate(a0
));
407 brw_MUL(p
, brw_null_reg(), c
->a1_sub_a0
, c
->dy2
);
408 brw_MAC(p
, c
->tmp
, c
->a2_sub_a0
, negate(c
->dy0
));
409 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
413 brw_MUL(p
, brw_null_reg(), c
->a2_sub_a0
, c
->dx0
);
414 brw_MAC(p
, c
->tmp
, c
->a1_sub_a0
, negate(c
->dx2
));
415 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
419 brw_set_predicate_control_flag_value(p
, pc
);
420 /* start point for interpolation
422 brw_MOV(p
, c
->m3C0
, a0
);
424 /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in
425 * the send instruction:
430 brw_vec8_grf(0, 0), /* r0, will be copied to m0 */
434 0, /* response len */
436 last
, /* writes complete */
438 BRW_URB_SWIZZLE_TRANSPOSE
); /* XXX: Swizzle control "SF to windower" */
445 void brw_emit_line_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
447 struct brw_compile
*p
= &c
->func
;
459 if (c
->key
.do_flat_shading
)
460 do_flatshade_line(c
);
462 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
464 /* Pair of incoming attributes:
466 struct brw_reg a0
= offset(c
->vert
[0], i
);
467 struct brw_reg a1
= offset(c
->vert
[1], i
);
468 GLushort pc
, pc_persp
, pc_linear
;
469 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
473 brw_set_predicate_control_flag_value(p
, pc_persp
);
474 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
475 brw_MUL(p
, a1
, a1
, c
->inv_w
[1]);
478 /* Calculate coefficients for position, color:
481 brw_set_predicate_control_flag_value(p
, pc_linear
);
483 brw_ADD(p
, c
->a1_sub_a0
, a1
, negate(a0
));
485 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dx0
);
486 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_det
);
488 brw_MUL(p
, c
->tmp
, c
->a1_sub_a0
, c
->dy0
);
489 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_det
);
493 brw_set_predicate_control_flag_value(p
, pc
);
495 /* start point for interpolation
497 brw_MOV(p
, c
->m3C0
, a0
);
499 /* Copy m0..m3 to URB.
508 0, /* response len */
510 last
, /* writes complete */
511 i
*4, /* urb destination offset */
512 BRW_URB_SWIZZLE_TRANSPOSE
);
517 void brw_emit_point_sprite_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
519 struct brw_compile
*p
= &c
->func
;
528 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
530 struct brw_sf_point_tex
*tex
= &c
->point_attrs
[c
->idx_to_attr
[2*i
]];
531 struct brw_reg a0
= offset(c
->vert
[0], i
);
532 GLushort pc
, pc_persp
, pc_linear
;
533 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
537 if (!tex
->CoordReplace
) {
538 brw_set_predicate_control_flag_value(p
, pc_persp
);
539 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
543 if (tex
->CoordReplace
) {
544 /* Caculate 1.0/PointWidth */
547 BRW_MATH_FUNCTION_INV
,
548 BRW_MATH_SATURATE_NONE
,
551 BRW_MATH_DATA_SCALAR
,
552 BRW_MATH_PRECISION_FULL
);
554 if (c
->key
.sprite_origin_lower_left
) {
555 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
556 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
557 brw_MUL(p
, c
->m2Cy
, c
->tmp
, negate(c
->inv_w
[0]));
558 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
560 brw_MUL(p
, c
->m1Cx
, c
->tmp
, c
->inv_w
[0]);
561 brw_MOV(p
, vec1(suboffset(c
->m1Cx
, 1)), brw_imm_f(0.0));
562 brw_MUL(p
, c
->m2Cy
, c
->tmp
, c
->inv_w
[0]);
563 brw_MOV(p
, vec1(suboffset(c
->m2Cy
, 0)), brw_imm_f(0.0));
566 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0));
567 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0));
571 brw_set_predicate_control_flag_value(p
, pc
);
572 if (tex
->CoordReplace
) {
573 if (c
->key
.sprite_origin_lower_left
) {
574 brw_MUL(p
, c
->m3C0
, c
->inv_w
[0], brw_imm_f(1.0));
575 brw_MOV(p
, vec1(suboffset(c
->m3C0
, 0)), brw_imm_f(0.0));
578 brw_MOV(p
, c
->m3C0
, brw_imm_f(0.0));
580 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
583 /* Copy m0..m3 to URB.
592 0, /* response len */
594 last
, /* writes complete */
595 i
*4, /* urb destination offset */
596 BRW_URB_SWIZZLE_TRANSPOSE
);
601 /* Points setup - several simplifications as all attributes are
602 * constant across the face of the point (point sprites excluded!)
604 void brw_emit_point_setup( struct brw_sf_compile
*c
, GLboolean allocate
)
606 struct brw_compile
*p
= &c
->func
;
616 brw_MOV(p
, c
->m1Cx
, brw_imm_ud(0)); /* zero - move out of loop */
617 brw_MOV(p
, c
->m2Cy
, brw_imm_ud(0)); /* zero - move out of loop */
619 for (i
= 0; i
< c
->nr_setup_regs
; i
++)
621 struct brw_reg a0
= offset(c
->vert
[0], i
);
622 GLushort pc
, pc_persp
, pc_linear
;
623 GLboolean last
= calculate_masks(c
, i
, &pc
, &pc_persp
, &pc_linear
);
627 /* This seems odd as the values are all constant, but the
628 * fragment shader will be expecting it:
630 brw_set_predicate_control_flag_value(p
, pc_persp
);
631 brw_MUL(p
, a0
, a0
, c
->inv_w
[0]);
635 /* The delta values are always zero, just send the starting
636 * coordinate. Again, this is to fit in with the interpolation
637 * code in the fragment shader.
640 brw_set_predicate_control_flag_value(p
, pc
);
642 brw_MOV(p
, c
->m3C0
, a0
); /* constant value */
644 /* Copy m0..m3 to URB.
653 0, /* response len */
655 last
, /* writes complete */
656 i
*4, /* urb destination offset */
657 BRW_URB_SWIZZLE_TRANSPOSE
);
662 void brw_emit_anyprim_setup( struct brw_sf_compile
*c
)
664 struct brw_compile
*p
= &c
->func
;
665 struct brw_reg ip
= brw_ip_reg();
666 struct brw_reg payload_prim
= brw_uw1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0);
667 struct brw_reg payload_attr
= get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE
, 1, 0), 0);
668 struct brw_reg primmask
;
669 struct brw_instruction
*jmp
;
670 struct brw_reg v1_null_ud
= vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD
));
677 primmask
= retype(get_element(c
->tmp
, 0), BRW_REGISTER_TYPE_UD
);
679 brw_MOV(p
, primmask
, brw_imm_ud(1));
680 brw_SHL(p
, primmask
, primmask
, payload_prim
);
682 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
683 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_TRILIST
) |
684 (1<<_3DPRIM_TRISTRIP
) |
685 (1<<_3DPRIM_TRIFAN
) |
686 (1<<_3DPRIM_TRISTRIP_REVERSE
) |
687 (1<<_3DPRIM_POLYGON
) |
688 (1<<_3DPRIM_RECTLIST
) |
689 (1<<_3DPRIM_TRIFAN_NOSTIPPLE
)));
690 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_d(0));
692 saveflag
= p
->flag_value
;
693 brw_push_insn_state(p
);
694 brw_emit_tri_setup( c
, GL_FALSE
);
695 brw_pop_insn_state(p
);
696 p
->flag_value
= saveflag
;
697 /* note - thread killed in subroutine, so must
698 * restore the flag which is changed when building
699 * the subroutine. fix #13240
702 brw_land_fwd_jump(p
, jmp
);
704 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
705 brw_AND(p
, v1_null_ud
, primmask
, brw_imm_ud((1<<_3DPRIM_LINELIST
) |
706 (1<<_3DPRIM_LINESTRIP
) |
707 (1<<_3DPRIM_LINELOOP
) |
708 (1<<_3DPRIM_LINESTRIP_CONT
) |
709 (1<<_3DPRIM_LINESTRIP_BF
) |
710 (1<<_3DPRIM_LINESTRIP_CONT_BF
)));
711 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_d(0));
713 saveflag
= p
->flag_value
;
714 brw_push_insn_state(p
);
715 brw_emit_line_setup( c
, GL_FALSE
);
716 brw_pop_insn_state(p
);
717 p
->flag_value
= saveflag
;
718 /* note - thread killed in subroutine */
720 brw_land_fwd_jump(p
, jmp
);
722 brw_set_conditionalmod(p
, BRW_CONDITIONAL_Z
);
723 brw_AND(p
, v1_null_ud
, payload_attr
, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE
));
724 jmp
= brw_JMPI(p
, ip
, ip
, brw_imm_d(0));
726 saveflag
= p
->flag_value
;
727 brw_push_insn_state(p
);
728 brw_emit_point_sprite_setup( c
, GL_FALSE
);
729 brw_pop_insn_state(p
);
730 p
->flag_value
= saveflag
;
732 brw_land_fwd_jump(p
, jmp
);
734 brw_emit_point_setup( c
, GL_FALSE
);