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 /* Interpolate the fog coordinate */
382 dst_mask(dst
, WRITEMASK_X
),
390 dst_mask(dst
, WRITEMASK_YZW
),
401 case FRAG_ATTRIB_FACE
:
402 /* XXX review/test this case */
405 dst_mask(dst
, WRITEMASK_X
),
412 case FRAG_ATTRIB_PNTC
:
413 /* XXX review/test this case */
416 dst_mask(dst
, WRITEMASK_XY
),
424 dst_mask(dst
, WRITEMASK_ZW
),
446 c
->fp_interp_emitted
|= 1<<idx
;
449 static void emit_ddx( struct brw_wm_compile
*c
,
450 const struct prog_instruction
*inst
)
452 GLuint idx
= inst
->SrcReg
[0].Index
;
453 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
455 c
->fp_deriv_emitted
|= 1<<idx
;
465 static void emit_ddy( struct brw_wm_compile
*c
,
466 const struct prog_instruction
*inst
)
468 GLuint idx
= inst
->SrcReg
[0].Index
;
469 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
471 c
->fp_deriv_emitted
|= 1<<idx
;
481 /***********************************************************************
482 * Hacks to extend the program parameter and constant lists.
485 /* Add the fog parameters to the parameter list of the original
486 * program, rather than creating a new list. Doesn't really do any
487 * harm and it's not as if the parameter handling isn't a big hack
490 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
497 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
498 gl_state_index tokens
[STATE_LENGTH
];
506 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
507 if (paramList
->Parameters
[idx
].Type
== PROGRAM_STATE_VAR
&&
508 memcmp(paramList
->Parameters
[idx
].StateIndexes
, tokens
, sizeof(tokens
)) == 0)
509 return src_reg(PROGRAM_STATE_VAR
, idx
);
512 idx
= _mesa_add_state_reference( paramList
, tokens
);
514 return src_reg(PROGRAM_STATE_VAR
, idx
);
518 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
524 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
534 /* Have to search, otherwise multiple compilations will each grow
535 * the parameter list.
537 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
538 if (paramList
->Parameters
[idx
].Type
== PROGRAM_CONSTANT
&&
539 memcmp(paramList
->ParameterValues
[idx
], values
, sizeof(values
)) == 0)
541 /* XXX: this mimics the mesa bug which puts all constants and
542 * parameters into the "PROGRAM_STATE_VAR" category:
544 return src_reg(PROGRAM_STATE_VAR
, idx
);
547 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
548 assert(swizzle
== SWIZZLE_NOOP
); /* Need to handle swizzle in reg setup */
549 return src_reg(PROGRAM_STATE_VAR
, idx
);
554 /***********************************************************************
555 * Expand various instructions here to simpler forms.
557 static void precalc_dst( struct brw_wm_compile
*c
,
558 const struct prog_instruction
*inst
)
560 struct prog_src_register src0
= inst
->SrcReg
[0];
561 struct prog_src_register src1
= inst
->SrcReg
[1];
562 struct prog_dst_register dst
= inst
->DstReg
;
564 if (dst
.WriteMask
& WRITEMASK_Y
) {
565 /* dst.y = mul src0.y, src1.y
569 dst_mask(dst
, WRITEMASK_Y
),
576 if (dst
.WriteMask
& WRITEMASK_XZ
) {
577 struct prog_instruction
*swz
;
578 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
580 /* dst.xz = swz src0.1zzz
584 dst_mask(dst
, WRITEMASK_XZ
),
586 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
589 /* Avoid letting negation flag of src0 affect our 1 constant. */
590 swz
->SrcReg
[0].Negate
&= ~NEGATE_X
;
592 if (dst
.WriteMask
& WRITEMASK_W
) {
593 /* dst.w = mov src1.w
597 dst_mask(dst
, WRITEMASK_W
),
606 static void precalc_lit( struct brw_wm_compile
*c
,
607 const struct prog_instruction
*inst
)
609 struct prog_src_register src0
= inst
->SrcReg
[0];
610 struct prog_dst_register dst
= inst
->DstReg
;
612 if (dst
.WriteMask
& WRITEMASK_XW
) {
613 struct prog_instruction
*swz
;
615 /* dst.xw = swz src0.1111
619 dst_mask(dst
, WRITEMASK_XW
),
621 src_swizzle1(src0
, SWIZZLE_ONE
),
624 /* Avoid letting the negation flag of src0 affect our 1 constant. */
625 swz
->SrcReg
[0].Negate
= NEGATE_NONE
;
628 if (dst
.WriteMask
& WRITEMASK_YZ
) {
631 dst_mask(dst
, WRITEMASK_YZ
),
641 * Some TEX instructions require extra code, cube map coordinate
642 * normalization, or coordinate scaling for RECT textures, etc.
643 * This function emits those extra instructions and the TEX
644 * instruction itself.
646 static void precalc_tex( struct brw_wm_compile
*c
,
647 const struct prog_instruction
*inst
)
649 struct prog_src_register coord
;
650 struct prog_dst_register tmpcoord
;
651 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
653 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
654 struct prog_instruction
*out
;
655 struct prog_dst_register tmp0
= get_temp(c
);
656 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
657 struct prog_dst_register tmp1
= get_temp(c
);
658 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
659 struct prog_src_register src0
= inst
->SrcReg
[0];
661 /* find longest component of coord vector and normalize it */
662 tmpcoord
= get_temp(c
);
663 coord
= src_reg_from_dst(tmpcoord
);
665 /* tmpcoord = src0 (i.e.: coord = src0) */
666 out
= emit_op(c
, OPCODE_MOV
,
672 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
673 out
->SrcReg
[0].Abs
= 1;
675 /* tmp0 = MAX(coord.X, coord.Y) */
676 emit_op(c
, OPCODE_MAX
,
679 src_swizzle1(coord
, X
),
680 src_swizzle1(coord
, Y
),
683 /* tmp1 = MAX(tmp0, coord.Z) */
684 emit_op(c
, OPCODE_MAX
,
688 src_swizzle1(coord
, Z
),
691 /* tmp0 = 1 / tmp1 */
692 emit_op(c
, OPCODE_RCP
,
699 /* tmpCoord = src0 * tmp0 */
700 emit_op(c
, OPCODE_MUL
,
707 release_temp(c
, tmp0
);
708 release_temp(c
, tmp1
);
710 else if (inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
711 struct prog_src_register scale
=
712 search_or_add_param5( c
,
718 tmpcoord
= get_temp(c
);
720 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
730 coord
= src_reg_from_dst(tmpcoord
);
733 coord
= inst
->SrcReg
[0];
736 /* Need to emit YUV texture conversions by hand. Probably need to
737 * do this here - the alternative is in brw_wm_emit.c, but the
738 * conversion requires allocating a temporary variable which we
739 * don't have the facility to do that late in the compilation.
741 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
742 /* convert ycbcr to RGBA */
743 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
746 CONST C0 = { -.5, -.0625, -.5, 1.164 }
747 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
749 UYV.xyz = ADD UYV, C0
750 UYV.y = MUL UYV.y, C0.w
752 RGB.xyz = MAD UYV.zzx, C1, UYV.y
754 RGB.xyz = MAD UYV.xxz, C1, UYV.y
755 RGB.y = MAD UYV.z, C1.w, RGB.y
757 struct prog_dst_register dst
= inst
->DstReg
;
758 struct prog_dst_register tmp
= get_temp(c
);
759 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
760 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
761 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
776 /* tmp.xyz = ADD TMP, C0
780 dst_mask(tmp
, WRITEMASK_XYZ
),
786 /* YUV.y = MUL YUV.y, C0.w
791 dst_mask(tmp
, WRITEMASK_Y
),
799 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
801 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
806 dst_mask(dst
, WRITEMASK_XYZ
),
808 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
810 src_swizzle1(tmpsrc
, Y
));
812 /* RGB.y = MAD YUV.z, C1.w, RGB.y
816 dst_mask(dst
, WRITEMASK_Y
),
818 src_swizzle1(tmpsrc
, Z
),
820 src_swizzle1(src_reg_from_dst(dst
), Y
));
822 release_temp(c
, tmp
);
825 /* ordinary RGBA tex instruction */
838 /* For GL_EXT_texture_swizzle: */
839 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
840 /* swizzle the result of the TEX instruction */
841 struct prog_src_register tmpsrc
= src_reg_from_dst(inst
->DstReg
);
842 emit_op(c
, OPCODE_SWZ
,
844 SATURATE_OFF
, /* saturate already done above */
845 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
850 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
851 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
852 release_temp(c
, tmpcoord
);
857 * Check if the given TXP instruction really needs the divide-by-W step.
859 static GLboolean
projtex( struct brw_wm_compile
*c
,
860 const struct prog_instruction
*inst
)
862 const struct prog_src_register src
= inst
->SrcReg
[0];
865 assert(inst
->Opcode
== OPCODE_TXP
);
867 /* Only try to detect the simplest cases. Could detect (later)
868 * cases where we are trying to emit code like RCP {1.0}, MUL x,
871 * More complex cases than this typically only arise from
872 * user-provided fragment programs anyway:
874 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
875 retVal
= GL_FALSE
; /* ut2004 gun rendering !?! */
876 else if (src
.File
== PROGRAM_INPUT
&&
877 GET_SWZ(src
.Swizzle
, W
) == W
&&
878 (c
->key
.proj_attrib_mask
& (1 << src
.Index
)) == 0)
890 static void precalc_txp( struct brw_wm_compile
*c
,
891 const struct prog_instruction
*inst
)
893 struct prog_src_register src0
= inst
->SrcReg
[0];
895 if (projtex(c
, inst
)) {
896 struct prog_dst_register tmp
= get_temp(c
);
897 struct prog_instruction tmp_inst
;
899 /* tmp0.w = RCP inst.arg[0][3]
903 dst_mask(tmp
, WRITEMASK_W
),
905 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
909 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
913 dst_mask(tmp
, WRITEMASK_XYZ
),
916 src_swizzle1(src_reg_from_dst(tmp
), W
),
919 /* dst = precalc(TEX tmp0)
922 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
923 precalc_tex(c
, &tmp_inst
);
925 release_temp(c
, tmp
);
929 /* dst = precalc(TEX src0)
931 precalc_tex(c
, inst
);
937 static void emit_fb_write( struct brw_wm_compile
*c
)
939 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
940 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPTH
);
941 struct prog_src_register outcolor
;
944 struct prog_instruction
*inst
, *last_inst
;
945 struct brw_context
*brw
= c
->func
.brw
;
947 /* The inst->Aux field is used for FB write target and the EOT marker */
949 if (brw
->state
.nr_color_regions
> 1) {
950 for (i
= 0 ; i
< brw
->state
.nr_color_regions
; i
++) {
951 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
952 last_inst
= inst
= emit_op(c
,
953 WM_FB_WRITE
, dst_mask(dst_undef(),0), 0,
954 outcolor
, payload_r0_depth
, outdepth
);
956 if (c
->fp_fragcolor_emitted
) {
957 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
958 last_inst
= inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
959 0, outcolor
, payload_r0_depth
, outdepth
);
963 last_inst
->Aux
|= 1; //eot
966 /* if gl_FragData[0] is written, use it, else use gl_FragColor */
967 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_DATA0
))
968 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
);
970 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLOR
);
972 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
973 0, outcolor
, payload_r0_depth
, outdepth
);
974 inst
->Aux
= 1|(0<<1);
981 /***********************************************************************
982 * Emit INTERP instructions ahead of first use of each attrib.
985 static void validate_src_regs( struct brw_wm_compile
*c
,
986 const struct prog_instruction
*inst
)
988 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
991 for (i
= 0; i
< nr_args
; i
++) {
992 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
993 GLuint idx
= inst
->SrcReg
[i
].Index
;
994 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
1001 static void validate_dst_regs( struct brw_wm_compile
*c
,
1002 const struct prog_instruction
*inst
)
1004 if (inst
->DstReg
.File
== PROGRAM_OUTPUT
) {
1005 GLuint idx
= inst
->DstReg
.Index
;
1006 if (idx
== FRAG_RESULT_COLOR
)
1007 c
->fp_fragcolor_emitted
= 1;
1011 static void print_insns( const struct prog_instruction
*insn
,
1015 for (i
= 0; i
< nr
; i
++, insn
++) {
1016 _mesa_printf("%3d: ", i
);
1017 if (insn
->Opcode
< MAX_OPCODE
)
1018 _mesa_print_instruction(insn
);
1019 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
1020 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
1022 _mesa_print_alu_instruction(insn
,
1023 wm_opcode_strings
[idx
],
1027 _mesa_printf("965 Opcode %d\n", insn
->Opcode
);
1033 * Initial pass for fragment program code generation.
1034 * This function is used by both the GLSL and non-GLSL paths.
1036 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
1038 struct brw_fragment_program
*fp
= c
->fp
;
1041 if (INTEL_DEBUG
& DEBUG_WM
) {
1042 _mesa_printf("pre-fp:\n");
1043 _mesa_print_program(&fp
->program
.Base
);
1047 c
->pixel_xy
= src_undef();
1048 c
->delta_xy
= src_undef();
1049 c
->pixel_w
= src_undef();
1052 /* Emit preamble instructions. This is where special instructions such as
1053 * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
1054 * compute shader inputs from varying vars.
1056 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1057 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1058 validate_src_regs(c
, inst
);
1059 validate_dst_regs(c
, inst
);
1062 /* Loop over all instructions doing assorted simplifications and
1065 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
1066 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
1067 struct prog_instruction
*out
;
1069 /* Check for INPUT values, emit INTERP instructions where
1073 switch (inst
->Opcode
) {
1075 out
= emit_insn(c
, inst
);
1076 out
->Opcode
= OPCODE_MOV
;
1080 out
= emit_insn(c
, inst
);
1081 out
->Opcode
= OPCODE_MOV
;
1082 out
->SrcReg
[0].Negate
= NEGATE_NONE
;
1083 out
->SrcReg
[0].Abs
= 1;
1087 out
= emit_insn(c
, inst
);
1088 out
->Opcode
= OPCODE_ADD
;
1089 out
->SrcReg
[1].Negate
^= NEGATE_XYZW
;
1093 out
= emit_insn(c
, inst
);
1094 /* This should probably be done in the parser.
1096 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1100 precalc_dst(c
, inst
);
1104 precalc_lit(c
, inst
);
1108 precalc_tex(c
, inst
);
1112 precalc_txp(c
, inst
);
1116 out
= emit_insn(c
, inst
);
1117 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1121 out
= emit_insn(c
, inst
);
1122 /* This should probably be done in the parser.
1124 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1128 out
= emit_insn(c
, inst
);
1129 /* This should probably be done in the parser.
1131 out
->DstReg
.WriteMask
= 0;
1151 if (INTEL_DEBUG
& DEBUG_WM
) {
1152 _mesa_printf("pass_fp:\n");
1153 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);