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"
36 #include "brw_context.h"
40 #include "shader/prog_parameter.h"
41 #include "shader/prog_print.h"
42 #include "shader/prog_statevars.h"
45 #define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS
53 static const char *wm_opcode_strings
[] = {
65 static const char *wm_file_strings
[] = {
71 /***********************************************************************
75 static struct prog_src_register
src_reg(GLuint file
, GLuint idx
)
77 struct prog_src_register reg
;
80 reg
.Swizzle
= SWIZZLE_NOOP
;
88 static struct prog_src_register
src_reg_from_dst(struct prog_dst_register dst
)
90 return src_reg(dst
.File
, dst
.Index
);
93 static struct prog_src_register
src_undef( void )
95 return src_reg(PROGRAM_UNDEFINED
, 0);
98 static GLboolean
src_is_undef(struct prog_src_register src
)
100 return src
.File
== PROGRAM_UNDEFINED
;
103 static struct prog_src_register
src_swizzle( struct prog_src_register reg
, int x
, int y
, int z
, int w
)
105 reg
.Swizzle
= MAKE_SWIZZLE4(x
,y
,z
,w
);
109 static struct prog_src_register
src_swizzle1( struct prog_src_register reg
, int x
)
111 return src_swizzle(reg
, x
, x
, x
, x
);
114 static struct prog_src_register
src_swizzle4( struct prog_src_register reg
, uint swizzle
)
116 reg
.Swizzle
= swizzle
;
121 /***********************************************************************
125 static struct prog_dst_register
dst_reg(GLuint file
, GLuint idx
)
127 struct prog_dst_register reg
;
130 reg
.WriteMask
= WRITEMASK_XYZW
;
139 static struct prog_dst_register
dst_mask( struct prog_dst_register reg
, int mask
)
141 reg
.WriteMask
&= mask
;
145 static struct prog_dst_register
dst_undef( void )
147 return dst_reg(PROGRAM_UNDEFINED
, 0);
152 static struct prog_dst_register
get_temp( struct brw_wm_compile
*c
)
154 int bit
= _mesa_ffs( ~c
->fp_temp
);
157 _mesa_printf("%s: out of temporaries\n", __FILE__
);
161 c
->fp_temp
|= 1<<(bit
-1);
162 return dst_reg(PROGRAM_TEMPORARY
, FIRST_INTERNAL_TEMP
+(bit
-1));
166 static void release_temp( struct brw_wm_compile
*c
, struct prog_dst_register temp
)
168 c
->fp_temp
&= ~(1 << (temp
.Index
- FIRST_INTERNAL_TEMP
));
172 /***********************************************************************
176 static struct prog_instruction
*get_fp_inst(struct brw_wm_compile
*c
)
178 return &c
->prog_instructions
[c
->nr_fp_insns
++];
181 static struct prog_instruction
*emit_insn(struct brw_wm_compile
*c
,
182 const struct prog_instruction
*inst0
)
184 struct prog_instruction
*inst
= get_fp_inst(c
);
189 static struct prog_instruction
* emit_tex_op(struct brw_wm_compile
*c
,
191 struct prog_dst_register dest
,
194 GLuint tex_src_target
,
196 struct prog_src_register src0
,
197 struct prog_src_register src1
,
198 struct prog_src_register src2
)
200 struct prog_instruction
*inst
= get_fp_inst(c
);
202 memset(inst
, 0, sizeof(*inst
));
206 inst
->SaturateMode
= saturate
;
207 inst
->TexSrcUnit
= tex_src_unit
;
208 inst
->TexSrcTarget
= tex_src_target
;
209 inst
->TexShadow
= tex_shadow
;
210 inst
->SrcReg
[0] = src0
;
211 inst
->SrcReg
[1] = src1
;
212 inst
->SrcReg
[2] = src2
;
217 static struct prog_instruction
* emit_op(struct brw_wm_compile
*c
,
219 struct prog_dst_register dest
,
221 struct prog_src_register src0
,
222 struct prog_src_register src1
,
223 struct prog_src_register src2
)
225 return emit_tex_op(c
, op
, dest
, saturate
,
226 0, 0, 0, /* tex unit, target, shadow */
233 /***********************************************************************
234 * Special instructions for interpolation and other tasks
237 static struct prog_src_register
get_pixel_xy( struct brw_wm_compile
*c
)
239 if (src_is_undef(c
->pixel_xy
)) {
240 struct prog_dst_register pixel_xy
= get_temp(c
);
241 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
244 /* Emit the out calculations, and hold onto the results. Use
245 * two instructions as a temporary is required.
247 /* pixel_xy.xy = PIXELXY payload[0];
251 dst_mask(pixel_xy
, WRITEMASK_XY
),
257 c
->pixel_xy
= src_reg_from_dst(pixel_xy
);
263 static struct prog_src_register
get_delta_xy( struct brw_wm_compile
*c
)
265 if (src_is_undef(c
->delta_xy
)) {
266 struct prog_dst_register delta_xy
= get_temp(c
);
267 struct prog_src_register pixel_xy
= get_pixel_xy(c
);
268 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
270 /* deltas.xy = DELTAXY pixel_xy, payload[0]
274 dst_mask(delta_xy
, WRITEMASK_XY
),
280 c
->delta_xy
= src_reg_from_dst(delta_xy
);
286 static struct prog_src_register
get_pixel_w( struct brw_wm_compile
*c
)
288 if (src_is_undef(c
->pixel_w
)) {
289 struct prog_dst_register pixel_w
= get_temp(c
);
290 struct prog_src_register deltas
= get_delta_xy(c
);
291 struct prog_src_register interp_wpos
= src_reg(PROGRAM_PAYLOAD
, FRAG_ATTRIB_WPOS
);
293 /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
297 dst_mask(pixel_w
, WRITEMASK_W
),
304 c
->pixel_w
= src_reg_from_dst(pixel_w
);
310 static void emit_interp( struct brw_wm_compile
*c
,
313 struct prog_dst_register dst
= dst_reg(PROGRAM_INPUT
, idx
);
314 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
315 struct prog_src_register deltas
= get_delta_xy(c
);
316 struct prog_src_register arg2
;
319 /* Need to use PINTERP on attributes which have been
320 * multiplied by 1/W in the SF program, and LINTERP on those
324 case FRAG_ATTRIB_WPOS
:
328 /* Have to treat wpos.xy specially:
332 dst_mask(dst
, WRITEMASK_XY
),
338 dst
= dst_mask(dst
, WRITEMASK_ZW
);
340 /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
350 case FRAG_ATTRIB_COL0
:
351 case FRAG_ATTRIB_COL1
:
352 if (c
->key
.flat_shade
) {
382 c
->fp_interp_emitted
|= 1<<idx
;
385 static void emit_ddx( struct brw_wm_compile
*c
,
386 const struct prog_instruction
*inst
)
388 GLuint idx
= inst
->SrcReg
[0].Index
;
389 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
391 c
->fp_deriv_emitted
|= 1<<idx
;
401 static void emit_ddy( struct brw_wm_compile
*c
,
402 const struct prog_instruction
*inst
)
404 GLuint idx
= inst
->SrcReg
[0].Index
;
405 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
407 c
->fp_deriv_emitted
|= 1<<idx
;
417 /***********************************************************************
418 * Hacks to extend the program parameter and constant lists.
421 /* Add the fog parameters to the parameter list of the original
422 * program, rather than creating a new list. Doesn't really do any
423 * harm and it's not as if the parameter handling isn't a big hack
426 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
433 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
434 gl_state_index tokens
[STATE_LENGTH
];
442 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
443 if (paramList
->Parameters
[idx
].Type
== PROGRAM_STATE_VAR
&&
444 memcmp(paramList
->Parameters
[idx
].StateIndexes
, tokens
, sizeof(tokens
)) == 0)
445 return src_reg(PROGRAM_STATE_VAR
, idx
);
448 idx
= _mesa_add_state_reference( paramList
, tokens
);
450 return src_reg(PROGRAM_STATE_VAR
, idx
);
454 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
460 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
470 /* Have to search, otherwise multiple compilations will each grow
471 * the parameter list.
473 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
474 if (paramList
->Parameters
[idx
].Type
== PROGRAM_CONSTANT
&&
475 memcmp(paramList
->ParameterValues
[idx
], values
, sizeof(values
)) == 0)
477 /* XXX: this mimics the mesa bug which puts all constants and
478 * parameters into the "PROGRAM_STATE_VAR" category:
480 return src_reg(PROGRAM_STATE_VAR
, idx
);
483 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
484 assert(swizzle
== SWIZZLE_NOOP
); /* Need to handle swizzle in reg setup */
485 return src_reg(PROGRAM_STATE_VAR
, idx
);
490 /***********************************************************************
491 * Expand various instructions here to simpler forms.
493 static void precalc_dst( struct brw_wm_compile
*c
,
494 const struct prog_instruction
*inst
)
496 struct prog_src_register src0
= inst
->SrcReg
[0];
497 struct prog_src_register src1
= inst
->SrcReg
[1];
498 struct prog_dst_register dst
= inst
->DstReg
;
500 if (dst
.WriteMask
& WRITEMASK_Y
) {
501 /* dst.y = mul src0.y, src1.y
505 dst_mask(dst
, WRITEMASK_Y
),
512 if (dst
.WriteMask
& WRITEMASK_XZ
) {
513 struct prog_instruction
*swz
;
514 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
516 /* dst.xz = swz src0.1zzz
520 dst_mask(dst
, WRITEMASK_XZ
),
522 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
525 /* Avoid letting negation flag of src0 affect our 1 constant. */
526 swz
->SrcReg
[0].NegateBase
&= ~NEGATE_X
;
528 if (dst
.WriteMask
& WRITEMASK_W
) {
529 /* dst.w = mov src1.w
533 dst_mask(dst
, WRITEMASK_W
),
542 static void precalc_lit( struct brw_wm_compile
*c
,
543 const struct prog_instruction
*inst
)
545 struct prog_src_register src0
= inst
->SrcReg
[0];
546 struct prog_dst_register dst
= inst
->DstReg
;
548 if (dst
.WriteMask
& WRITEMASK_XW
) {
549 struct prog_instruction
*swz
;
551 /* dst.xw = swz src0.1111
555 dst_mask(dst
, WRITEMASK_XW
),
557 src_swizzle1(src0
, SWIZZLE_ONE
),
560 /* Avoid letting the negation flag of src0 affect our 1 constant. */
561 swz
->SrcReg
[0].NegateBase
= 0;
564 if (dst
.WriteMask
& WRITEMASK_YZ
) {
567 dst_mask(dst
, WRITEMASK_YZ
),
577 * Some TEX instructions require extra code, cube map coordinate
578 * normalization, or coordinate scaling for RECT textures, etc.
579 * This function emits those extra instructions and the TEX
580 * instruction itself.
582 static void precalc_tex( struct brw_wm_compile
*c
,
583 const struct prog_instruction
*inst
)
585 struct prog_src_register coord
;
586 struct prog_dst_register tmpcoord
;
587 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
589 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
590 struct prog_instruction
*out
;
591 struct prog_dst_register tmp0
= get_temp(c
);
592 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
593 struct prog_dst_register tmp1
= get_temp(c
);
594 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
595 struct prog_src_register src0
= inst
->SrcReg
[0];
597 /* find longest component of coord vector and normalize it */
598 tmpcoord
= get_temp(c
);
599 coord
= src_reg_from_dst(tmpcoord
);
601 /* tmpcoord = src0 (i.e.: coord = src0) */
602 out
= emit_op(c
, OPCODE_MOV
,
608 out
->SrcReg
[0].NegateBase
= 0;
609 out
->SrcReg
[0].Abs
= 1;
611 /* tmp0 = MAX(coord.X, coord.Y) */
612 emit_op(c
, OPCODE_MAX
,
615 src_swizzle1(coord
, X
),
616 src_swizzle1(coord
, Y
),
619 /* tmp1 = MAX(tmp0, coord.Z) */
620 emit_op(c
, OPCODE_MAX
,
624 src_swizzle1(coord
, Z
),
627 /* tmp0 = 1 / tmp1 */
628 emit_op(c
, OPCODE_RCP
,
635 /* tmpCoord = src0 * tmp0 */
636 emit_op(c
, OPCODE_MUL
,
643 release_temp(c
, tmp0
);
644 release_temp(c
, tmp1
);
646 else if (inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
647 struct prog_src_register scale
=
648 search_or_add_param5( c
,
654 tmpcoord
= get_temp(c
);
656 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
666 coord
= src_reg_from_dst(tmpcoord
);
669 coord
= inst
->SrcReg
[0];
672 /* Need to emit YUV texture conversions by hand. Probably need to
673 * do this here - the alternative is in brw_wm_emit.c, but the
674 * conversion requires allocating a temporary variable which we
675 * don't have the facility to do that late in the compilation.
677 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
678 /* convert ycbcr to RGBA */
679 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
682 CONST C0 = { -.5, -.0625, -.5, 1.164 }
683 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
685 UYV.xyz = ADD UYV, C0
686 UYV.y = MUL UYV.y, C0.w
688 RGB.xyz = MAD UYV.zzx, C1, UYV.y
690 RGB.xyz = MAD UYV.xxz, C1, UYV.y
691 RGB.y = MAD UYV.z, C1.w, RGB.y
693 struct prog_dst_register dst
= inst
->DstReg
;
694 struct prog_dst_register tmp
= get_temp(c
);
695 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
696 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
697 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
712 /* tmp.xyz = ADD TMP, C0
716 dst_mask(tmp
, WRITEMASK_XYZ
),
722 /* YUV.y = MUL YUV.y, C0.w
727 dst_mask(tmp
, WRITEMASK_Y
),
735 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
737 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
742 dst_mask(dst
, WRITEMASK_XYZ
),
744 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
746 src_swizzle1(tmpsrc
, Y
));
748 /* RGB.y = MAD YUV.z, C1.w, RGB.y
752 dst_mask(dst
, WRITEMASK_Y
),
754 src_swizzle1(tmpsrc
, Z
),
756 src_swizzle1(src_reg_from_dst(dst
), Y
));
758 release_temp(c
, tmp
);
761 /* ordinary RGBA tex instruction */
774 /* For GL_EXT_texture_swizzle: */
775 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
776 /* swizzle the result of the TEX instruction */
777 struct prog_src_register tmpsrc
= src_reg_from_dst(inst
->DstReg
);
778 emit_op(c
, OPCODE_SWZ
,
780 SATURATE_OFF
, /* saturate already done above */
781 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
786 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
787 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
788 release_temp(c
, tmpcoord
);
792 static GLboolean
projtex( struct brw_wm_compile
*c
,
793 const struct prog_instruction
*inst
)
795 struct prog_src_register src
= inst
->SrcReg
[0];
797 /* Only try to detect the simplest cases. Could detect (later)
798 * cases where we are trying to emit code like RCP {1.0}, MUL x,
801 * More complex cases than this typically only arise from
802 * user-provided fragment programs anyway:
804 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
805 return 0; /* ut2004 gun rendering !?! */
806 else if (src
.File
== PROGRAM_INPUT
&&
807 GET_SWZ(src
.Swizzle
, W
) == W
&&
808 (c
->key
.projtex_mask
& (1<<(src
.Index
+ FRAG_ATTRIB_WPOS
- FRAG_ATTRIB_TEX0
))) == 0)
815 static void precalc_txp( struct brw_wm_compile
*c
,
816 const struct prog_instruction
*inst
)
818 struct prog_src_register src0
= inst
->SrcReg
[0];
820 if (projtex(c
, inst
)) {
821 struct prog_dst_register tmp
= get_temp(c
);
822 struct prog_instruction tmp_inst
;
824 /* tmp0.w = RCP inst.arg[0][3]
828 dst_mask(tmp
, WRITEMASK_W
),
830 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
834 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
838 dst_mask(tmp
, WRITEMASK_XYZ
),
841 src_swizzle1(src_reg_from_dst(tmp
), W
),
844 /* dst = precalc(TEX tmp0)
847 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
848 precalc_tex(c
, &tmp_inst
);
850 release_temp(c
, tmp
);
854 /* dst = precalc(TEX src0)
856 precalc_tex(c
, inst
);
862 static void emit_fb_write( struct brw_wm_compile
*c
)
864 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
865 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPTH
);
866 struct prog_src_register outcolor
;
869 struct prog_instruction
*inst
, *last_inst
;
870 struct brw_context
*brw
= c
->func
.brw
;
872 /* The inst->Aux field is used for FB write target and the EOT marker */
874 if (brw
->state
.nr_color_regions
> 1) {
875 for (i
= 0 ; i
< brw
->state
.nr_color_regions
; i
++) {
876 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
877 last_inst
= inst
= emit_op(c
,
878 WM_FB_WRITE
, dst_mask(dst_undef(),0), 0,
879 outcolor
, payload_r0_depth
, outdepth
);
881 if (c
->fp_fragcolor_emitted
) {
882 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
883 last_inst
= inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
884 0, outcolor
, payload_r0_depth
, outdepth
);
888 last_inst
->Aux
|= 1; //eot
891 /* if gl_FragData[0] is written, use it, else use gl_FragColor */
892 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_DATA0
))
893 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
);
895 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
897 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
898 0, outcolor
, payload_r0_depth
, outdepth
);
899 inst
->Aux
= 1|(0<<1);
906 /***********************************************************************
907 * Emit INTERP instructions ahead of first use of each attrib.
910 static void validate_src_regs( struct brw_wm_compile
*c
,
911 const struct prog_instruction
*inst
)
913 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
916 for (i
= 0; i
< nr_args
; i
++) {
917 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
918 GLuint idx
= inst
->SrcReg
[i
].Index
;
919 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
926 static void validate_dst_regs( struct brw_wm_compile
*c
,
927 const struct prog_instruction
*inst
)
929 if (inst
->DstReg
.File
== PROGRAM_OUTPUT
) {
930 GLuint idx
= inst
->DstReg
.Index
;
931 if (idx
== FRAG_RESULT_COLOR
)
932 c
->fp_fragcolor_emitted
= 1;
936 static void print_insns( const struct prog_instruction
*insn
,
940 for (i
= 0; i
< nr
; i
++, insn
++) {
941 _mesa_printf("%3d: ", i
);
942 if (insn
->Opcode
< MAX_OPCODE
)
943 _mesa_print_instruction(insn
);
944 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
945 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
947 _mesa_print_alu_instruction(insn
,
948 wm_opcode_strings
[idx
],
952 _mesa_printf("UNKNOWN\n");
958 * Initial pass for fragment program code generation.
959 * This function is used by both the GLSL and non-GLSL paths.
961 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
963 struct brw_fragment_program
*fp
= c
->fp
;
966 if (INTEL_DEBUG
& DEBUG_WM
) {
967 _mesa_printf("pre-fp:\n");
968 _mesa_print_program(&fp
->program
.Base
);
972 c
->pixel_xy
= src_undef();
973 c
->delta_xy
= src_undef();
974 c
->pixel_w
= src_undef();
977 /* Emit preamble instructions. This is where special instructions such as
978 * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
979 * compute shader inputs from varying vars.
981 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
982 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
983 validate_src_regs(c
, inst
);
984 validate_dst_regs(c
, inst
);
987 /* Loop over all instructions doing assorted simplifications and
990 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
991 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
992 struct prog_instruction
*out
;
994 /* Check for INPUT values, emit INTERP instructions where
998 switch (inst
->Opcode
) {
1000 out
= emit_insn(c
, inst
);
1001 out
->Opcode
= OPCODE_MOV
;
1005 out
= emit_insn(c
, inst
);
1006 out
->Opcode
= OPCODE_MOV
;
1007 out
->SrcReg
[0].NegateBase
= 0;
1008 out
->SrcReg
[0].Abs
= 1;
1012 out
= emit_insn(c
, inst
);
1013 out
->Opcode
= OPCODE_ADD
;
1014 out
->SrcReg
[1].NegateBase
^= 0xf;
1018 out
= emit_insn(c
, inst
);
1019 /* This should probably be done in the parser.
1021 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1025 precalc_dst(c
, inst
);
1029 precalc_lit(c
, inst
);
1033 precalc_tex(c
, inst
);
1037 precalc_txp(c
, inst
);
1041 out
= emit_insn(c
, inst
);
1042 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1046 out
= emit_insn(c
, inst
);
1047 /* This should probably be done in the parser.
1049 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1053 out
= emit_insn(c
, inst
);
1054 /* This should probably be done in the parser.
1056 out
->DstReg
.WriteMask
= 0;
1076 if (INTEL_DEBUG
& DEBUG_WM
) {
1077 _mesa_printf("pass_fp:\n");
1078 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);