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
) {
357 if (c
->key
.linear_color
) {
367 /* perspective-corrected color interpolation */
378 case FRAG_ATTRIB_FOGC
:
379 /* The FOGC input is really special. When a program uses glFogFragCoord,
380 * the results returned are supposed to be (f,0,0,1). But for Mesa GLSL,
381 * the glFrontFacing and glPointCoord values are also stashed in FOGC.
382 * So, write the interpolated fog value to X, then either 0, 1, or the
383 * stashed values to Y, Z, W. Note that this means that
384 * glFogFragCoord.yzw can be wrong in those cases!
387 /* Interpolate the fog coordinate */
390 dst_mask(dst
, WRITEMASK_X
),
396 /* Move the front facing value into FOGC.y if it's needed. */
397 if (c
->fp
->program
.UsesFrontFacing
) {
400 dst_mask(dst
, WRITEMASK_Y
),
408 dst_mask(dst
, WRITEMASK_Y
),
410 src_swizzle1(interp
, SWIZZLE_ZERO
),
415 /* Should do the PointCoord thing here. */
418 dst_mask(dst
, WRITEMASK_ZW
),
439 c
->fp_interp_emitted
|= 1<<idx
;
442 static void emit_ddx( struct brw_wm_compile
*c
,
443 const struct prog_instruction
*inst
)
445 GLuint idx
= inst
->SrcReg
[0].Index
;
446 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
448 c
->fp_deriv_emitted
|= 1<<idx
;
458 static void emit_ddy( struct brw_wm_compile
*c
,
459 const struct prog_instruction
*inst
)
461 GLuint idx
= inst
->SrcReg
[0].Index
;
462 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
464 c
->fp_deriv_emitted
|= 1<<idx
;
474 /***********************************************************************
475 * Hacks to extend the program parameter and constant lists.
478 /* Add the fog parameters to the parameter list of the original
479 * program, rather than creating a new list. Doesn't really do any
480 * harm and it's not as if the parameter handling isn't a big hack
483 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
490 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
491 gl_state_index tokens
[STATE_LENGTH
];
499 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
500 if (paramList
->Parameters
[idx
].Type
== PROGRAM_STATE_VAR
&&
501 memcmp(paramList
->Parameters
[idx
].StateIndexes
, tokens
, sizeof(tokens
)) == 0)
502 return src_reg(PROGRAM_STATE_VAR
, idx
);
505 idx
= _mesa_add_state_reference( paramList
, tokens
);
507 return src_reg(PROGRAM_STATE_VAR
, idx
);
511 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
517 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
527 /* Have to search, otherwise multiple compilations will each grow
528 * the parameter list.
530 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
531 if (paramList
->Parameters
[idx
].Type
== PROGRAM_CONSTANT
&&
532 memcmp(paramList
->ParameterValues
[idx
], values
, sizeof(values
)) == 0)
534 /* XXX: this mimics the mesa bug which puts all constants and
535 * parameters into the "PROGRAM_STATE_VAR" category:
537 return src_reg(PROGRAM_STATE_VAR
, idx
);
540 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
541 assert(swizzle
== SWIZZLE_NOOP
); /* Need to handle swizzle in reg setup */
542 return src_reg(PROGRAM_STATE_VAR
, idx
);
547 /***********************************************************************
548 * Expand various instructions here to simpler forms.
550 static void precalc_dst( struct brw_wm_compile
*c
,
551 const struct prog_instruction
*inst
)
553 struct prog_src_register src0
= inst
->SrcReg
[0];
554 struct prog_src_register src1
= inst
->SrcReg
[1];
555 struct prog_dst_register dst
= inst
->DstReg
;
557 if (dst
.WriteMask
& WRITEMASK_Y
) {
558 /* dst.y = mul src0.y, src1.y
562 dst_mask(dst
, WRITEMASK_Y
),
569 if (dst
.WriteMask
& WRITEMASK_XZ
) {
570 struct prog_instruction
*swz
;
571 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
573 /* dst.xz = swz src0.1zzz
577 dst_mask(dst
, WRITEMASK_XZ
),
579 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
582 /* Avoid letting negation flag of src0 affect our 1 constant. */
583 swz
->SrcReg
[0].Negate
&= ~NEGATE_X
;
585 if (dst
.WriteMask
& WRITEMASK_W
) {
586 /* dst.w = mov src1.w
590 dst_mask(dst
, WRITEMASK_W
),
599 static void precalc_lit( struct brw_wm_compile
*c
,
600 const struct prog_instruction
*inst
)
602 struct prog_src_register src0
= inst
->SrcReg
[0];
603 struct prog_dst_register dst
= inst
->DstReg
;
605 if (dst
.WriteMask
& WRITEMASK_XW
) {
606 struct prog_instruction
*swz
;
608 /* dst.xw = swz src0.1111
612 dst_mask(dst
, WRITEMASK_XW
),
614 src_swizzle1(src0
, SWIZZLE_ONE
),
617 /* Avoid letting the negation flag of src0 affect our 1 constant. */
618 swz
->SrcReg
[0].Negate
= NEGATE_NONE
;
621 if (dst
.WriteMask
& WRITEMASK_YZ
) {
624 dst_mask(dst
, WRITEMASK_YZ
),
634 * Some TEX instructions require extra code, cube map coordinate
635 * normalization, or coordinate scaling for RECT textures, etc.
636 * This function emits those extra instructions and the TEX
637 * instruction itself.
639 static void precalc_tex( struct brw_wm_compile
*c
,
640 const struct prog_instruction
*inst
)
642 struct prog_src_register coord
;
643 struct prog_dst_register tmpcoord
;
644 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
646 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
647 struct prog_instruction
*out
;
648 struct prog_dst_register tmp0
= get_temp(c
);
649 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
650 struct prog_dst_register tmp1
= get_temp(c
);
651 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
652 struct prog_src_register src0
= inst
->SrcReg
[0];
654 /* find longest component of coord vector and normalize it */
655 tmpcoord
= get_temp(c
);
656 coord
= src_reg_from_dst(tmpcoord
);
658 /* tmpcoord = src0 (i.e.: coord = src0) */
659 out
= emit_op(c
, OPCODE_MOV
,
665 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
666 out
->SrcReg
[0].Abs
= 1;
668 /* tmp0 = MAX(coord.X, coord.Y) */
669 emit_op(c
, OPCODE_MAX
,
672 src_swizzle1(coord
, X
),
673 src_swizzle1(coord
, Y
),
676 /* tmp1 = MAX(tmp0, coord.Z) */
677 emit_op(c
, OPCODE_MAX
,
681 src_swizzle1(coord
, Z
),
684 /* tmp0 = 1 / tmp1 */
685 emit_op(c
, OPCODE_RCP
,
692 /* tmpCoord = src0 * tmp0 */
693 emit_op(c
, OPCODE_MUL
,
700 release_temp(c
, tmp0
);
701 release_temp(c
, tmp1
);
703 else if (inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
704 struct prog_src_register scale
=
705 search_or_add_param5( c
,
711 tmpcoord
= get_temp(c
);
713 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
723 coord
= src_reg_from_dst(tmpcoord
);
726 coord
= inst
->SrcReg
[0];
729 /* Need to emit YUV texture conversions by hand. Probably need to
730 * do this here - the alternative is in brw_wm_emit.c, but the
731 * conversion requires allocating a temporary variable which we
732 * don't have the facility to do that late in the compilation.
734 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
735 /* convert ycbcr to RGBA */
736 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
739 CONST C0 = { -.5, -.0625, -.5, 1.164 }
740 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
742 UYV.xyz = ADD UYV, C0
743 UYV.y = MUL UYV.y, C0.w
745 RGB.xyz = MAD UYV.zzx, C1, UYV.y
747 RGB.xyz = MAD UYV.xxz, C1, UYV.y
748 RGB.y = MAD UYV.z, C1.w, RGB.y
750 struct prog_dst_register dst
= inst
->DstReg
;
751 struct prog_dst_register tmp
= get_temp(c
);
752 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
753 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
754 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
769 /* tmp.xyz = ADD TMP, C0
773 dst_mask(tmp
, WRITEMASK_XYZ
),
779 /* YUV.y = MUL YUV.y, C0.w
784 dst_mask(tmp
, WRITEMASK_Y
),
792 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
794 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
799 dst_mask(dst
, WRITEMASK_XYZ
),
801 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
803 src_swizzle1(tmpsrc
, Y
));
805 /* RGB.y = MAD YUV.z, C1.w, RGB.y
809 dst_mask(dst
, WRITEMASK_Y
),
811 src_swizzle1(tmpsrc
, Z
),
813 src_swizzle1(src_reg_from_dst(dst
), Y
));
815 release_temp(c
, tmp
);
818 /* ordinary RGBA tex instruction */
831 /* For GL_EXT_texture_swizzle: */
832 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
833 /* swizzle the result of the TEX instruction */
834 struct prog_src_register tmpsrc
= src_reg_from_dst(inst
->DstReg
);
835 emit_op(c
, OPCODE_SWZ
,
837 SATURATE_OFF
, /* saturate already done above */
838 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
843 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
844 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
845 release_temp(c
, tmpcoord
);
850 * Check if the given TXP instruction really needs the divide-by-W step.
852 static GLboolean
projtex( struct brw_wm_compile
*c
,
853 const struct prog_instruction
*inst
)
855 const struct prog_src_register src
= inst
->SrcReg
[0];
858 assert(inst
->Opcode
== OPCODE_TXP
);
860 /* Only try to detect the simplest cases. Could detect (later)
861 * cases where we are trying to emit code like RCP {1.0}, MUL x,
864 * More complex cases than this typically only arise from
865 * user-provided fragment programs anyway:
867 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
868 retVal
= GL_FALSE
; /* ut2004 gun rendering !?! */
869 else if (src
.File
== PROGRAM_INPUT
&&
870 GET_SWZ(src
.Swizzle
, W
) == W
&&
871 (c
->key
.proj_attrib_mask
& (1 << src
.Index
)) == 0)
883 static void precalc_txp( struct brw_wm_compile
*c
,
884 const struct prog_instruction
*inst
)
886 struct prog_src_register src0
= inst
->SrcReg
[0];
888 if (projtex(c
, inst
)) {
889 struct prog_dst_register tmp
= get_temp(c
);
890 struct prog_instruction tmp_inst
;
892 /* tmp0.w = RCP inst.arg[0][3]
896 dst_mask(tmp
, WRITEMASK_W
),
898 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
902 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
906 dst_mask(tmp
, WRITEMASK_XYZ
),
909 src_swizzle1(src_reg_from_dst(tmp
), W
),
912 /* dst = precalc(TEX tmp0)
915 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
916 precalc_tex(c
, &tmp_inst
);
918 release_temp(c
, tmp
);
922 /* dst = precalc(TEX src0)
924 precalc_tex(c
, inst
);
930 static void emit_fb_write( struct brw_wm_compile
*c
)
932 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
933 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPTH
);
934 struct prog_src_register outcolor
;
937 struct prog_instruction
*inst
, *last_inst
;
938 struct brw_context
*brw
= c
->func
.brw
;
940 /* The inst->Aux field is used for FB write target and the EOT marker */
942 if (brw
->state
.nr_color_regions
> 1) {
943 for (i
= 0 ; i
< brw
->state
.nr_color_regions
; i
++) {
944 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
945 last_inst
= inst
= emit_op(c
,
946 WM_FB_WRITE
, dst_mask(dst_undef(),0), 0,
947 outcolor
, payload_r0_depth
, outdepth
);
949 if (c
->fp_fragcolor_emitted
) {
950 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
951 last_inst
= inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
952 0, outcolor
, payload_r0_depth
, outdepth
);
956 last_inst
->Aux
|= 1; //eot
959 /* if gl_FragData[0] is written, use it, else use gl_FragColor */
960 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_DATA0
))
961 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
);
963 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
965 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
966 0, outcolor
, payload_r0_depth
, outdepth
);
967 inst
->Aux
= 1|(0<<1);
974 /***********************************************************************
975 * Emit INTERP instructions ahead of first use of each attrib.
978 static void validate_src_regs( struct brw_wm_compile
*c
,
979 const struct prog_instruction
*inst
)
981 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
984 for (i
= 0; i
< nr_args
; i
++) {
985 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
986 GLuint idx
= inst
->SrcReg
[i
].Index
;
987 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
994 static void validate_dst_regs( struct brw_wm_compile
*c
,
995 const struct prog_instruction
*inst
)
997 if (inst
->DstReg
.File
== PROGRAM_OUTPUT
) {
998 GLuint idx
= inst
->DstReg
.Index
;
999 if (idx
== FRAG_RESULT_COLOR
)
1000 c
->fp_fragcolor_emitted
= 1;
1004 static void print_insns( const struct prog_instruction
*insn
,
1008 for (i
= 0; i
< nr
; i
++, insn
++) {
1009 _mesa_printf("%3d: ", i
);
1010 if (insn
->Opcode
< MAX_OPCODE
)
1011 _mesa_print_instruction(insn
);
1012 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
1013 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
1015 _mesa_print_alu_instruction(insn
,
1016 wm_opcode_strings
[idx
],
1020 _mesa_printf("965 Opcode %d\n", insn
->Opcode
);
1026 * Initial pass for fragment program code generation.
1027 * This function is used by both the GLSL and non-GLSL paths.
1029 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
1031 struct brw_fragment_program
*fp
= c
->fp
;
1034 if (INTEL_DEBUG
& DEBUG_WM
) {
1035 _mesa_printf("pre-fp:\n");
1036 _mesa_print_program(&fp
->program
.Base
);
1040 c
->pixel_xy
= src_undef();
1041 c
->delta_xy
= src_undef();
1042 c
->pixel_w
= src_undef();
1045 /* Emit preamble instructions. This is where special instructions such as
1046 * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
1047 * compute shader inputs from varying vars.
1049 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1050 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1051 validate_src_regs(c
, inst
);
1052 validate_dst_regs(c
, inst
);
1055 /* Loop over all instructions doing assorted simplifications and
1058 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1059 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1060 struct prog_instruction
*out
;
1062 /* Check for INPUT values, emit INTERP instructions where
1066 switch (inst
->Opcode
) {
1068 out
= emit_insn(c
, inst
);
1069 out
->Opcode
= OPCODE_MOV
;
1073 out
= emit_insn(c
, inst
);
1074 out
->Opcode
= OPCODE_MOV
;
1075 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
1076 out
->SrcReg
[0].Abs
= 1;
1080 out
= emit_insn(c
, inst
);
1081 out
->Opcode
= OPCODE_ADD
;
1082 out
->SrcReg
[1].Negate
^= NEGATE_XYZW
;
1086 out
= emit_insn(c
, inst
);
1087 /* This should probably be done in the parser.
1089 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1093 precalc_dst(c
, inst
);
1097 precalc_lit(c
, inst
);
1101 precalc_tex(c
, inst
);
1105 precalc_txp(c
, inst
);
1109 out
= emit_insn(c
, inst
);
1110 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1114 out
= emit_insn(c
, inst
);
1115 /* This should probably be done in the parser.
1117 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1121 out
= emit_insn(c
, inst
);
1122 /* This should probably be done in the parser.
1124 out
->DstReg
.WriteMask
= 0;
1144 if (INTEL_DEBUG
& DEBUG_WM
) {
1145 _mesa_printf("pass_fp:\n");
1146 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);