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
[] = {
66 static const char *wm_file_strings
[] = {
72 /***********************************************************************
76 static struct prog_src_register
src_reg(GLuint file
, GLuint idx
)
78 struct prog_src_register reg
;
81 reg
.Swizzle
= SWIZZLE_NOOP
;
83 reg
.Negate
= NEGATE_NONE
;
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
;
132 reg
.CondMask
= COND_TR
;
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
);
317 /* Need to use PINTERP on attributes which have been
318 * multiplied by 1/W in the SF program, and LINTERP on those
322 case FRAG_ATTRIB_WPOS
:
323 /* Have to treat wpos.xy specially:
327 dst_mask(dst
, WRITEMASK_XY
),
333 dst
= dst_mask(dst
, WRITEMASK_ZW
);
335 /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
345 case FRAG_ATTRIB_COL0
:
346 case FRAG_ATTRIB_COL1
:
347 if (c
->key
.flat_shade
) {
366 case FRAG_ATTRIB_FOGC
:
367 /* The FOGC input is really special. When a program uses glFogFragCoord,
368 * the results returned are supposed to be (f,0,0,1). But for Mesa GLSL,
369 * the glFrontFacing and glPointCoord values are also stashed in FOGC.
370 * So, write the interpolated fog value to X, then either 0, 1, or the
371 * stashed values to Y, Z, W. Note that this means that
372 * glFogFragCoord.yzw can be wrong in those cases!
375 /* Interpolate the fog coordinate */
378 dst_mask(dst
, WRITEMASK_X
),
384 /* Move the front facing value into FOGC.y if it's needed. */
385 if (c
->fp
->program
.UsesFrontFacing
) {
388 dst_mask(dst
, WRITEMASK_Y
),
396 dst_mask(dst
, WRITEMASK_Y
),
398 src_swizzle1(interp
, SWIZZLE_ZERO
),
403 /* Should do the PointCoord thing here. */
406 dst_mask(dst
, WRITEMASK_ZW
),
427 c
->fp_interp_emitted
|= 1<<idx
;
430 static void emit_ddx( struct brw_wm_compile
*c
,
431 const struct prog_instruction
*inst
)
433 GLuint idx
= inst
->SrcReg
[0].Index
;
434 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
436 c
->fp_deriv_emitted
|= 1<<idx
;
446 static void emit_ddy( struct brw_wm_compile
*c
,
447 const struct prog_instruction
*inst
)
449 GLuint idx
= inst
->SrcReg
[0].Index
;
450 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
452 c
->fp_deriv_emitted
|= 1<<idx
;
462 /***********************************************************************
463 * Hacks to extend the program parameter and constant lists.
466 /* Add the fog parameters to the parameter list of the original
467 * program, rather than creating a new list. Doesn't really do any
468 * harm and it's not as if the parameter handling isn't a big hack
471 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
478 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
479 gl_state_index tokens
[STATE_LENGTH
];
487 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
488 if (paramList
->Parameters
[idx
].Type
== PROGRAM_STATE_VAR
&&
489 memcmp(paramList
->Parameters
[idx
].StateIndexes
, tokens
, sizeof(tokens
)) == 0)
490 return src_reg(PROGRAM_STATE_VAR
, idx
);
493 idx
= _mesa_add_state_reference( paramList
, tokens
);
495 return src_reg(PROGRAM_STATE_VAR
, idx
);
499 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
505 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
515 /* Have to search, otherwise multiple compilations will each grow
516 * the parameter list.
518 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
519 if (paramList
->Parameters
[idx
].Type
== PROGRAM_CONSTANT
&&
520 memcmp(paramList
->ParameterValues
[idx
], values
, sizeof(values
)) == 0)
522 /* XXX: this mimics the mesa bug which puts all constants and
523 * parameters into the "PROGRAM_STATE_VAR" category:
525 return src_reg(PROGRAM_STATE_VAR
, idx
);
528 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
529 assert(swizzle
== SWIZZLE_NOOP
); /* Need to handle swizzle in reg setup */
530 return src_reg(PROGRAM_STATE_VAR
, idx
);
535 /***********************************************************************
536 * Expand various instructions here to simpler forms.
538 static void precalc_dst( struct brw_wm_compile
*c
,
539 const struct prog_instruction
*inst
)
541 struct prog_src_register src0
= inst
->SrcReg
[0];
542 struct prog_src_register src1
= inst
->SrcReg
[1];
543 struct prog_dst_register dst
= inst
->DstReg
;
545 if (dst
.WriteMask
& WRITEMASK_Y
) {
546 /* dst.y = mul src0.y, src1.y
550 dst_mask(dst
, WRITEMASK_Y
),
557 if (dst
.WriteMask
& WRITEMASK_XZ
) {
558 struct prog_instruction
*swz
;
559 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
561 /* dst.xz = swz src0.1zzz
565 dst_mask(dst
, WRITEMASK_XZ
),
567 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
570 /* Avoid letting negation flag of src0 affect our 1 constant. */
571 swz
->SrcReg
[0].Negate
&= ~NEGATE_X
;
573 if (dst
.WriteMask
& WRITEMASK_W
) {
574 /* dst.w = mov src1.w
578 dst_mask(dst
, WRITEMASK_W
),
587 static void precalc_lit( struct brw_wm_compile
*c
,
588 const struct prog_instruction
*inst
)
590 struct prog_src_register src0
= inst
->SrcReg
[0];
591 struct prog_dst_register dst
= inst
->DstReg
;
593 if (dst
.WriteMask
& WRITEMASK_XW
) {
594 struct prog_instruction
*swz
;
596 /* dst.xw = swz src0.1111
600 dst_mask(dst
, WRITEMASK_XW
),
602 src_swizzle1(src0
, SWIZZLE_ONE
),
605 /* Avoid letting the negation flag of src0 affect our 1 constant. */
606 swz
->SrcReg
[0].Negate
= NEGATE_NONE
;
609 if (dst
.WriteMask
& WRITEMASK_YZ
) {
612 dst_mask(dst
, WRITEMASK_YZ
),
622 * Some TEX instructions require extra code, cube map coordinate
623 * normalization, or coordinate scaling for RECT textures, etc.
624 * This function emits those extra instructions and the TEX
625 * instruction itself.
627 static void precalc_tex( struct brw_wm_compile
*c
,
628 const struct prog_instruction
*inst
)
630 struct prog_src_register coord
;
631 struct prog_dst_register tmpcoord
;
632 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
634 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
635 struct prog_instruction
*out
;
636 struct prog_dst_register tmp0
= get_temp(c
);
637 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
638 struct prog_dst_register tmp1
= get_temp(c
);
639 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
640 struct prog_src_register src0
= inst
->SrcReg
[0];
642 /* find longest component of coord vector and normalize it */
643 tmpcoord
= get_temp(c
);
644 coord
= src_reg_from_dst(tmpcoord
);
646 /* tmpcoord = src0 (i.e.: coord = src0) */
647 out
= emit_op(c
, OPCODE_MOV
,
653 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
654 out
->SrcReg
[0].Abs
= 1;
656 /* tmp0 = MAX(coord.X, coord.Y) */
657 emit_op(c
, OPCODE_MAX
,
660 src_swizzle1(coord
, X
),
661 src_swizzle1(coord
, Y
),
664 /* tmp1 = MAX(tmp0, coord.Z) */
665 emit_op(c
, OPCODE_MAX
,
669 src_swizzle1(coord
, Z
),
672 /* tmp0 = 1 / tmp1 */
673 emit_op(c
, OPCODE_RCP
,
680 /* tmpCoord = src0 * tmp0 */
681 emit_op(c
, OPCODE_MUL
,
688 release_temp(c
, tmp0
);
689 release_temp(c
, tmp1
);
691 else if (inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
692 struct prog_src_register scale
=
693 search_or_add_param5( c
,
699 tmpcoord
= get_temp(c
);
701 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
711 coord
= src_reg_from_dst(tmpcoord
);
714 coord
= inst
->SrcReg
[0];
717 /* Need to emit YUV texture conversions by hand. Probably need to
718 * do this here - the alternative is in brw_wm_emit.c, but the
719 * conversion requires allocating a temporary variable which we
720 * don't have the facility to do that late in the compilation.
722 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
723 /* convert ycbcr to RGBA */
724 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
727 CONST C0 = { -.5, -.0625, -.5, 1.164 }
728 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
730 UYV.xyz = ADD UYV, C0
731 UYV.y = MUL UYV.y, C0.w
733 RGB.xyz = MAD UYV.zzx, C1, UYV.y
735 RGB.xyz = MAD UYV.xxz, C1, UYV.y
736 RGB.y = MAD UYV.z, C1.w, RGB.y
738 struct prog_dst_register dst
= inst
->DstReg
;
739 struct prog_dst_register tmp
= get_temp(c
);
740 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
741 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
742 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
757 /* tmp.xyz = ADD TMP, C0
761 dst_mask(tmp
, WRITEMASK_XYZ
),
767 /* YUV.y = MUL YUV.y, C0.w
772 dst_mask(tmp
, WRITEMASK_Y
),
780 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
782 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
787 dst_mask(dst
, WRITEMASK_XYZ
),
789 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
791 src_swizzle1(tmpsrc
, Y
));
793 /* RGB.y = MAD YUV.z, C1.w, RGB.y
797 dst_mask(dst
, WRITEMASK_Y
),
799 src_swizzle1(tmpsrc
, Z
),
801 src_swizzle1(src_reg_from_dst(dst
), Y
));
803 release_temp(c
, tmp
);
806 /* ordinary RGBA tex instruction */
819 /* For GL_EXT_texture_swizzle: */
820 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
821 /* swizzle the result of the TEX instruction */
822 struct prog_src_register tmpsrc
= src_reg_from_dst(inst
->DstReg
);
823 emit_op(c
, OPCODE_SWZ
,
825 SATURATE_OFF
, /* saturate already done above */
826 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
831 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
832 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
833 release_temp(c
, tmpcoord
);
837 static GLboolean
projtex( struct brw_wm_compile
*c
,
838 const struct prog_instruction
*inst
)
840 struct prog_src_register src
= inst
->SrcReg
[0];
842 /* Only try to detect the simplest cases. Could detect (later)
843 * cases where we are trying to emit code like RCP {1.0}, MUL x,
846 * More complex cases than this typically only arise from
847 * user-provided fragment programs anyway:
849 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
850 return 0; /* ut2004 gun rendering !?! */
851 else if (src
.File
== PROGRAM_INPUT
&&
852 GET_SWZ(src
.Swizzle
, W
) == W
&&
853 (c
->key
.projtex_mask
& (1<<(src
.Index
+ FRAG_ATTRIB_WPOS
- FRAG_ATTRIB_TEX0
))) == 0)
860 static void precalc_txp( struct brw_wm_compile
*c
,
861 const struct prog_instruction
*inst
)
863 struct prog_src_register src0
= inst
->SrcReg
[0];
865 if (projtex(c
, inst
)) {
866 struct prog_dst_register tmp
= get_temp(c
);
867 struct prog_instruction tmp_inst
;
869 /* tmp0.w = RCP inst.arg[0][3]
873 dst_mask(tmp
, WRITEMASK_W
),
875 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
879 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
883 dst_mask(tmp
, WRITEMASK_XYZ
),
886 src_swizzle1(src_reg_from_dst(tmp
), W
),
889 /* dst = precalc(TEX tmp0)
892 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
893 precalc_tex(c
, &tmp_inst
);
895 release_temp(c
, tmp
);
899 /* dst = precalc(TEX src0)
901 precalc_tex(c
, inst
);
907 static void emit_fb_write( struct brw_wm_compile
*c
)
909 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
910 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPTH
);
911 struct prog_src_register outcolor
;
914 struct prog_instruction
*inst
, *last_inst
;
915 struct brw_context
*brw
= c
->func
.brw
;
917 /* The inst->Aux field is used for FB write target and the EOT marker */
919 if (brw
->state
.nr_color_regions
> 1) {
920 for (i
= 0 ; i
< brw
->state
.nr_color_regions
; i
++) {
921 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
922 last_inst
= inst
= emit_op(c
,
923 WM_FB_WRITE
, dst_mask(dst_undef(),0), 0,
924 outcolor
, payload_r0_depth
, outdepth
);
926 if (c
->fp_fragcolor_emitted
) {
927 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
928 last_inst
= inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
929 0, outcolor
, payload_r0_depth
, outdepth
);
933 last_inst
->Aux
|= 1; //eot
936 /* if gl_FragData[0] is written, use it, else use gl_FragColor */
937 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_DATA0
))
938 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
);
940 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
942 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
943 0, outcolor
, payload_r0_depth
, outdepth
);
944 inst
->Aux
= 1|(0<<1);
951 /***********************************************************************
952 * Emit INTERP instructions ahead of first use of each attrib.
955 static void validate_src_regs( struct brw_wm_compile
*c
,
956 const struct prog_instruction
*inst
)
958 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
961 for (i
= 0; i
< nr_args
; i
++) {
962 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
963 GLuint idx
= inst
->SrcReg
[i
].Index
;
964 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
971 static void validate_dst_regs( struct brw_wm_compile
*c
,
972 const struct prog_instruction
*inst
)
974 if (inst
->DstReg
.File
== PROGRAM_OUTPUT
) {
975 GLuint idx
= inst
->DstReg
.Index
;
976 if (idx
== FRAG_RESULT_COLOR
)
977 c
->fp_fragcolor_emitted
= 1;
981 static void print_insns( const struct prog_instruction
*insn
,
985 for (i
= 0; i
< nr
; i
++, insn
++) {
986 _mesa_printf("%3d: ", i
);
987 if (insn
->Opcode
< MAX_OPCODE
)
988 _mesa_print_instruction(insn
);
989 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
990 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
992 _mesa_print_alu_instruction(insn
,
993 wm_opcode_strings
[idx
],
997 _mesa_printf("965 Opcode %d\n", insn
->Opcode
);
1003 * Initial pass for fragment program code generation.
1004 * This function is used by both the GLSL and non-GLSL paths.
1006 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
1008 struct brw_fragment_program
*fp
= c
->fp
;
1011 if (INTEL_DEBUG
& DEBUG_WM
) {
1012 _mesa_printf("pre-fp:\n");
1013 _mesa_print_program(&fp
->program
.Base
);
1017 c
->pixel_xy
= src_undef();
1018 c
->delta_xy
= src_undef();
1019 c
->pixel_w
= src_undef();
1022 /* Emit preamble instructions. This is where special instructions such as
1023 * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
1024 * compute shader inputs from varying vars.
1026 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1027 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1028 validate_src_regs(c
, inst
);
1029 validate_dst_regs(c
, inst
);
1032 /* Loop over all instructions doing assorted simplifications and
1035 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1036 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1037 struct prog_instruction
*out
;
1039 /* Check for INPUT values, emit INTERP instructions where
1043 switch (inst
->Opcode
) {
1045 out
= emit_insn(c
, inst
);
1046 out
->Opcode
= OPCODE_MOV
;
1050 out
= emit_insn(c
, inst
);
1051 out
->Opcode
= OPCODE_MOV
;
1052 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
1053 out
->SrcReg
[0].Abs
= 1;
1057 out
= emit_insn(c
, inst
);
1058 out
->Opcode
= OPCODE_ADD
;
1059 out
->SrcReg
[1].Negate
^= NEGATE_XYZW
;
1063 out
= emit_insn(c
, inst
);
1064 /* This should probably be done in the parser.
1066 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1070 precalc_dst(c
, inst
);
1074 precalc_lit(c
, inst
);
1078 precalc_tex(c
, inst
);
1082 precalc_txp(c
, inst
);
1086 out
= emit_insn(c
, inst
);
1087 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1091 out
= emit_insn(c
, inst
);
1092 /* This should probably be done in the parser.
1094 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1098 out
= emit_insn(c
, inst
);
1099 /* This should probably be done in the parser.
1101 out
->DstReg
.WriteMask
= 0;
1121 if (INTEL_DEBUG
& DEBUG_WM
) {
1122 _mesa_printf("pass_fp:\n");
1123 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);