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_op(struct brw_wm_compile
*c
,
191 struct prog_dst_register dest
,
194 GLuint tex_src_target
,
195 struct prog_src_register src0
,
196 struct prog_src_register src1
,
197 struct prog_src_register src2
)
199 struct prog_instruction
*inst
= get_fp_inst(c
);
201 memset(inst
, 0, sizeof(*inst
));
205 inst
->SaturateMode
= saturate
;
206 inst
->TexSrcUnit
= tex_src_unit
;
207 inst
->TexSrcTarget
= tex_src_target
;
208 inst
->SrcReg
[0] = src0
;
209 inst
->SrcReg
[1] = src1
;
210 inst
->SrcReg
[2] = src2
;
217 /***********************************************************************
218 * Special instructions for interpolation and other tasks
221 static struct prog_src_register
get_pixel_xy( struct brw_wm_compile
*c
)
223 if (src_is_undef(c
->pixel_xy
)) {
224 struct prog_dst_register pixel_xy
= get_temp(c
);
225 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
228 /* Emit the out calculations, and hold onto the results. Use
229 * two instructions as a temporary is required.
231 /* pixel_xy.xy = PIXELXY payload[0];
235 dst_mask(pixel_xy
, WRITEMASK_XY
),
241 c
->pixel_xy
= src_reg_from_dst(pixel_xy
);
247 static struct prog_src_register
get_delta_xy( struct brw_wm_compile
*c
)
249 if (src_is_undef(c
->delta_xy
)) {
250 struct prog_dst_register delta_xy
= get_temp(c
);
251 struct prog_src_register pixel_xy
= get_pixel_xy(c
);
252 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
254 /* deltas.xy = DELTAXY pixel_xy, payload[0]
258 dst_mask(delta_xy
, WRITEMASK_XY
),
264 c
->delta_xy
= src_reg_from_dst(delta_xy
);
270 static struct prog_src_register
get_pixel_w( struct brw_wm_compile
*c
)
272 if (src_is_undef(c
->pixel_w
)) {
273 struct prog_dst_register pixel_w
= get_temp(c
);
274 struct prog_src_register deltas
= get_delta_xy(c
);
275 struct prog_src_register interp_wpos
= src_reg(PROGRAM_PAYLOAD
, FRAG_ATTRIB_WPOS
);
278 /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
282 dst_mask(pixel_w
, WRITEMASK_W
),
289 c
->pixel_w
= src_reg_from_dst(pixel_w
);
295 static void emit_interp( struct brw_wm_compile
*c
,
298 struct prog_dst_register dst
= dst_reg(PROGRAM_INPUT
, idx
);
299 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
300 struct prog_src_register deltas
= get_delta_xy(c
);
301 struct prog_src_register arg2
;
304 /* Need to use PINTERP on attributes which have been
305 * multiplied by 1/W in the SF program, and LINTERP on those
309 case FRAG_ATTRIB_WPOS
:
313 /* Have to treat wpos.xy specially:
317 dst_mask(dst
, WRITEMASK_XY
),
323 dst
= dst_mask(dst
, WRITEMASK_ZW
);
325 /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
335 case FRAG_ATTRIB_COL0
:
336 case FRAG_ATTRIB_COL1
:
337 if (c
->key
.flat_shade
) {
367 c
->fp_interp_emitted
|= 1<<idx
;
370 static void emit_ddx( struct brw_wm_compile
*c
,
371 const struct prog_instruction
*inst
)
373 GLuint idx
= inst
->SrcReg
[0].Index
;
374 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
376 c
->fp_deriv_emitted
|= 1<<idx
;
386 static void emit_ddy( struct brw_wm_compile
*c
,
387 const struct prog_instruction
*inst
)
389 GLuint idx
= inst
->SrcReg
[0].Index
;
390 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
392 c
->fp_deriv_emitted
|= 1<<idx
;
402 /***********************************************************************
403 * Hacks to extend the program parameter and constant lists.
406 /* Add the fog parameters to the parameter list of the original
407 * program, rather than creating a new list. Doesn't really do any
408 * harm and it's not as if the parameter handling isn't a big hack
411 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
418 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
419 gl_state_index tokens
[STATE_LENGTH
];
427 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
428 if (paramList
->Parameters
[idx
].Type
== PROGRAM_STATE_VAR
&&
429 memcmp(paramList
->Parameters
[idx
].StateIndexes
, tokens
, sizeof(tokens
)) == 0)
430 return src_reg(PROGRAM_STATE_VAR
, idx
);
433 idx
= _mesa_add_state_reference( paramList
, tokens
);
435 return src_reg(PROGRAM_STATE_VAR
, idx
);
439 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
445 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
455 /* Have to search, otherwise multiple compilations will each grow
456 * the parameter list.
458 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
459 if (paramList
->Parameters
[idx
].Type
== PROGRAM_CONSTANT
&&
460 memcmp(paramList
->ParameterValues
[idx
], values
, sizeof(values
)) == 0)
462 /* XXX: this mimics the mesa bug which puts all constants and
463 * parameters into the "PROGRAM_STATE_VAR" category:
465 return src_reg(PROGRAM_STATE_VAR
, idx
);
468 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
469 assert(swizzle
== SWIZZLE_NOOP
); /* Need to handle swizzle in reg setup */
470 return src_reg(PROGRAM_STATE_VAR
, idx
);
475 /***********************************************************************
476 * Expand various instructions here to simpler forms.
478 static void precalc_dst( struct brw_wm_compile
*c
,
479 const struct prog_instruction
*inst
)
481 struct prog_src_register src0
= inst
->SrcReg
[0];
482 struct prog_src_register src1
= inst
->SrcReg
[1];
483 struct prog_dst_register dst
= inst
->DstReg
;
485 if (dst
.WriteMask
& WRITEMASK_Y
) {
486 /* dst.y = mul src0.y, src1.y
490 dst_mask(dst
, WRITEMASK_Y
),
491 inst
->SaturateMode
, 0, 0,
498 if (dst
.WriteMask
& WRITEMASK_XZ
) {
499 struct prog_instruction
*swz
;
500 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
502 /* dst.xz = swz src0.1zzz
506 dst_mask(dst
, WRITEMASK_XZ
),
507 inst
->SaturateMode
, 0, 0,
508 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
511 /* Avoid letting negation flag of src0 affect our 1 constant. */
512 swz
->SrcReg
[0].NegateBase
&= ~NEGATE_X
;
514 if (dst
.WriteMask
& WRITEMASK_W
) {
515 /* dst.w = mov src1.w
519 dst_mask(dst
, WRITEMASK_W
),
520 inst
->SaturateMode
, 0, 0,
528 static void precalc_lit( struct brw_wm_compile
*c
,
529 const struct prog_instruction
*inst
)
531 struct prog_src_register src0
= inst
->SrcReg
[0];
532 struct prog_dst_register dst
= inst
->DstReg
;
534 if (dst
.WriteMask
& WRITEMASK_XW
) {
535 struct prog_instruction
*swz
;
537 /* dst.xw = swz src0.1111
541 dst_mask(dst
, WRITEMASK_XW
),
543 src_swizzle1(src0
, SWIZZLE_ONE
),
546 /* Avoid letting the negation flag of src0 affect our 1 constant. */
547 swz
->SrcReg
[0].NegateBase
= 0;
551 if (dst
.WriteMask
& WRITEMASK_YZ
) {
554 dst_mask(dst
, WRITEMASK_YZ
),
555 inst
->SaturateMode
, 0, 0,
564 * Some TEX instructions require extra code, cube map coordinate
565 * normalization, or coordinate scaling for RECT textures, etc.
566 * This function emits those extra instructions and the TEX
567 * instruction itself.
569 static void precalc_tex( struct brw_wm_compile
*c
,
570 const struct prog_instruction
*inst
)
572 struct prog_src_register coord
;
573 struct prog_dst_register tmpcoord
;
574 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
576 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
577 struct prog_instruction
*out
;
578 struct prog_dst_register tmp0
= get_temp(c
);
579 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
580 struct prog_dst_register tmp1
= get_temp(c
);
581 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
582 struct prog_src_register src0
= inst
->SrcReg
[0];
584 /* find longest component of coord vector and normalize it */
585 tmpcoord
= get_temp(c
);
586 coord
= src_reg_from_dst(tmpcoord
);
588 /* tmpcoord = src0 (i.e.: coord = src0) */
589 out
= emit_op(c
, OPCODE_MOV
,
595 out
->SrcReg
[0].NegateBase
= 0;
596 out
->SrcReg
[0].Abs
= 1;
598 /* tmp0 = MAX(coord.X, coord.Y) */
599 emit_op(c
, OPCODE_MAX
,
602 src_swizzle1(coord
, X
),
603 src_swizzle1(coord
, Y
),
606 /* tmp1 = MAX(tmp0, coord.Z) */
607 emit_op(c
, OPCODE_MAX
,
611 src_swizzle1(coord
, Z
),
614 /* tmp0 = 1 / tmp1 */
615 emit_op(c
, OPCODE_RCP
,
622 /* tmpCoord = src0 * tmp0 */
623 emit_op(c
, OPCODE_MUL
,
630 release_temp(c
, tmp0
);
631 release_temp(c
, tmp1
);
633 else if (inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
634 struct prog_src_register scale
=
635 search_or_add_param5( c
,
641 tmpcoord
= get_temp(c
);
643 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
653 coord
= src_reg_from_dst(tmpcoord
);
656 coord
= inst
->SrcReg
[0];
659 /* Need to emit YUV texture conversions by hand. Probably need to
660 * do this here - the alternative is in brw_wm_emit.c, but the
661 * conversion requires allocating a temporary variable which we
662 * don't have the facility to do that late in the compilation.
664 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
665 /* convert ycbcr to RGBA */
666 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
669 CONST C0 = { -.5, -.0625, -.5, 1.164 }
670 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
672 UYV.xyz = ADD UYV, C0
673 UYV.y = MUL UYV.y, C0.w
675 RGB.xyz = MAD UYV.zzx, C1, UYV.y
677 RGB.xyz = MAD UYV.xxz, C1, UYV.y
678 RGB.y = MAD UYV.z, C1.w, RGB.y
680 struct prog_dst_register dst
= inst
->DstReg
;
681 struct prog_dst_register tmp
= get_temp(c
);
682 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
683 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
684 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
698 /* tmp.xyz = ADD TMP, C0
702 dst_mask(tmp
, WRITEMASK_XYZ
),
708 /* YUV.y = MUL YUV.y, C0.w
713 dst_mask(tmp
, WRITEMASK_Y
),
721 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
723 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
728 dst_mask(dst
, WRITEMASK_XYZ
),
730 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
732 src_swizzle1(tmpsrc
, Y
));
734 /* RGB.y = MAD YUV.z, C1.w, RGB.y
738 dst_mask(dst
, WRITEMASK_Y
),
740 src_swizzle1(tmpsrc
, Z
),
742 src_swizzle1(src_reg_from_dst(dst
), Y
));
744 release_temp(c
, tmp
);
747 /* ordinary RGBA tex instruction */
759 /* For GL_EXT_texture_swizzle: */
760 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
761 /* swizzle the result of the TEX instruction */
762 struct prog_src_register tmpsrc
= src_reg_from_dst(inst
->DstReg
);
763 emit_op(c
, OPCODE_SWZ
,
765 SATURATE_OFF
, /* saturate already done above */
766 0, 0, /* tex unit, target N/A */
767 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
772 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
773 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
774 release_temp(c
, tmpcoord
);
778 static GLboolean
projtex( struct brw_wm_compile
*c
,
779 const struct prog_instruction
*inst
)
781 struct prog_src_register src
= inst
->SrcReg
[0];
783 /* Only try to detect the simplest cases. Could detect (later)
784 * cases where we are trying to emit code like RCP {1.0}, MUL x,
787 * More complex cases than this typically only arise from
788 * user-provided fragment programs anyway:
790 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
791 return 0; /* ut2004 gun rendering !?! */
792 else if (src
.File
== PROGRAM_INPUT
&&
793 GET_SWZ(src
.Swizzle
, W
) == W
&&
794 (c
->key
.projtex_mask
& (1<<(src
.Index
+ FRAG_ATTRIB_WPOS
- FRAG_ATTRIB_TEX0
))) == 0)
801 static void precalc_txp( struct brw_wm_compile
*c
,
802 const struct prog_instruction
*inst
)
804 struct prog_src_register src0
= inst
->SrcReg
[0];
806 if (projtex(c
, inst
)) {
807 struct prog_dst_register tmp
= get_temp(c
);
808 struct prog_instruction tmp_inst
;
810 /* tmp0.w = RCP inst.arg[0][3]
814 dst_mask(tmp
, WRITEMASK_W
),
816 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
820 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
824 dst_mask(tmp
, WRITEMASK_XYZ
),
827 src_swizzle1(src_reg_from_dst(tmp
), W
),
830 /* dst = precalc(TEX tmp0)
833 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
834 precalc_tex(c
, &tmp_inst
);
836 release_temp(c
, tmp
);
840 /* dst = precalc(TEX src0)
842 precalc_tex(c
, inst
);
848 static void emit_fb_write( struct brw_wm_compile
*c
)
850 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
851 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPR
);
852 struct prog_src_register outcolor
;
855 struct prog_instruction
*inst
, *last_inst
;
856 struct brw_context
*brw
= c
->func
.brw
;
858 /* inst->Sampler is not used by backend,
859 use it for fb write target and eot */
861 if (brw
->state
.nr_draw_regions
> 1) {
862 for (i
= 0 ; i
< brw
->state
.nr_draw_regions
; i
++) {
863 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
864 last_inst
= inst
= emit_op(c
,
865 WM_FB_WRITE
, dst_mask(dst_undef(),0), 0, 0, 0,
866 outcolor
, payload_r0_depth
, outdepth
);
867 inst
->Sampler
= (i
<<1);
868 if (c
->fp_fragcolor_emitted
) {
869 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLR
);
870 last_inst
= inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
871 0, 0, 0, outcolor
, payload_r0_depth
, outdepth
);
872 inst
->Sampler
= (i
<<1);
875 last_inst
->Sampler
|= 1; //eot
878 /* if gl_FragData[0] is written, use it, else use gl_FragColor */
879 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_DATA0
))
880 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
);
882 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLR
);
884 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
885 0, 0, 0, outcolor
, payload_r0_depth
, outdepth
);
886 inst
->Sampler
= 1|(0<<1);
893 /***********************************************************************
894 * Emit INTERP instructions ahead of first use of each attrib.
897 static void validate_src_regs( struct brw_wm_compile
*c
,
898 const struct prog_instruction
*inst
)
900 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
903 for (i
= 0; i
< nr_args
; i
++) {
904 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
905 GLuint idx
= inst
->SrcReg
[i
].Index
;
906 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
913 static void validate_dst_regs( struct brw_wm_compile
*c
,
914 const struct prog_instruction
*inst
)
916 if (inst
->DstReg
.File
== PROGRAM_OUTPUT
) {
917 GLuint idx
= inst
->DstReg
.Index
;
918 if (idx
== FRAG_RESULT_COLR
)
919 c
->fp_fragcolor_emitted
= 1;
923 static void print_insns( const struct prog_instruction
*insn
,
927 for (i
= 0; i
< nr
; i
++, insn
++) {
928 _mesa_printf("%3d: ", i
);
929 if (insn
->Opcode
< MAX_OPCODE
)
930 _mesa_print_instruction(insn
);
931 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
932 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
934 _mesa_print_alu_instruction(insn
,
935 wm_opcode_strings
[idx
],
939 _mesa_printf("UNKNOWN\n");
946 * Initial pass for fragment program code generation.
947 * This function is used by both the GLSL and non-GLSL paths.
949 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
951 struct brw_fragment_program
*fp
= c
->fp
;
954 if (INTEL_DEBUG
& DEBUG_WM
) {
955 _mesa_printf("pre-fp:\n");
956 _mesa_print_program(&fp
->program
.Base
);
960 c
->pixel_xy
= src_undef();
961 c
->delta_xy
= src_undef();
962 c
->pixel_w
= src_undef();
965 /* Emit preamble instructions. This is where special instructions such as
966 * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
967 * compute shader inputs from varying vars.
969 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
970 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
971 validate_src_regs(c
, inst
);
972 validate_dst_regs(c
, inst
);
975 /* Loop over all instructions doing assorted simplifications and
978 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
979 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
980 struct prog_instruction
*out
;
982 /* Check for INPUT values, emit INTERP instructions where
986 switch (inst
->Opcode
) {
988 out
= emit_insn(c
, inst
);
989 out
->Opcode
= OPCODE_MOV
;
993 out
= emit_insn(c
, inst
);
994 out
->Opcode
= OPCODE_MOV
;
995 out
->SrcReg
[0].NegateBase
= 0;
996 out
->SrcReg
[0].Abs
= 1;
1000 out
= emit_insn(c
, inst
);
1001 out
->Opcode
= OPCODE_ADD
;
1002 out
->SrcReg
[1].NegateBase
^= 0xf;
1006 out
= emit_insn(c
, inst
);
1007 /* This should probably be done in the parser.
1009 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1013 precalc_dst(c
, inst
);
1017 precalc_lit(c
, inst
);
1021 precalc_tex(c
, inst
);
1025 precalc_txp(c
, inst
);
1029 out
= emit_insn(c
, inst
);
1030 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1034 out
= emit_insn(c
, inst
);
1035 /* This should probably be done in the parser.
1037 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1041 out
= emit_insn(c
, inst
);
1042 /* This should probably be done in the parser.
1044 out
->DstReg
.WriteMask
= 0;
1064 if (INTEL_DEBUG
& DEBUG_WM
) {
1065 _mesa_printf("pass_fp:\n");
1066 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);