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
);
186 inst
->Data
= (void *)inst0
;
190 static struct prog_instruction
* emit_op(struct brw_wm_compile
*c
,
192 struct prog_dst_register dest
,
195 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
->SrcReg
[0] = src0
;
210 inst
->SrcReg
[1] = src1
;
211 inst
->SrcReg
[2] = src2
;
218 /***********************************************************************
219 * Special instructions for interpolation and other tasks
222 static struct prog_src_register
get_pixel_xy( struct brw_wm_compile
*c
)
224 if (src_is_undef(c
->pixel_xy
)) {
225 struct prog_dst_register pixel_xy
= get_temp(c
);
226 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
229 /* Emit the out calculations, and hold onto the results. Use
230 * two instructions as a temporary is required.
232 /* pixel_xy.xy = PIXELXY payload[0];
236 dst_mask(pixel_xy
, WRITEMASK_XY
),
242 c
->pixel_xy
= src_reg_from_dst(pixel_xy
);
248 static struct prog_src_register
get_delta_xy( struct brw_wm_compile
*c
)
250 if (src_is_undef(c
->delta_xy
)) {
251 struct prog_dst_register delta_xy
= get_temp(c
);
252 struct prog_src_register pixel_xy
= get_pixel_xy(c
);
253 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
255 /* deltas.xy = DELTAXY pixel_xy, payload[0]
259 dst_mask(delta_xy
, WRITEMASK_XY
),
265 c
->delta_xy
= src_reg_from_dst(delta_xy
);
271 static struct prog_src_register
get_pixel_w( struct brw_wm_compile
*c
)
273 if (src_is_undef(c
->pixel_w
)) {
274 struct prog_dst_register pixel_w
= get_temp(c
);
275 struct prog_src_register deltas
= get_delta_xy(c
);
276 struct prog_src_register interp_wpos
= src_reg(PROGRAM_PAYLOAD
, FRAG_ATTRIB_WPOS
);
279 /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
283 dst_mask(pixel_w
, WRITEMASK_W
),
290 c
->pixel_w
= src_reg_from_dst(pixel_w
);
296 static void emit_interp( struct brw_wm_compile
*c
,
299 struct prog_dst_register dst
= dst_reg(PROGRAM_INPUT
, idx
);
300 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
301 struct prog_src_register deltas
= get_delta_xy(c
);
302 struct prog_src_register arg2
;
305 /* Need to use PINTERP on attributes which have been
306 * multiplied by 1/W in the SF program, and LINTERP on those
310 case FRAG_ATTRIB_WPOS
:
314 /* Have to treat wpos.xy specially:
318 dst_mask(dst
, WRITEMASK_XY
),
324 dst
= dst_mask(dst
, WRITEMASK_ZW
);
326 /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
336 case FRAG_ATTRIB_COL0
:
337 case FRAG_ATTRIB_COL1
:
338 if (c
->key
.flat_shade
) {
368 c
->fp_interp_emitted
|= 1<<idx
;
371 static void emit_ddx( struct brw_wm_compile
*c
,
372 const struct prog_instruction
*inst
)
374 GLuint idx
= inst
->SrcReg
[0].Index
;
375 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
377 c
->fp_deriv_emitted
|= 1<<idx
;
387 static void emit_ddy( struct brw_wm_compile
*c
,
388 const struct prog_instruction
*inst
)
390 GLuint idx
= inst
->SrcReg
[0].Index
;
391 struct prog_src_register interp
= src_reg(PROGRAM_PAYLOAD
, idx
);
393 c
->fp_deriv_emitted
|= 1<<idx
;
403 /***********************************************************************
404 * Hacks to extend the program parameter and constant lists.
407 /* Add the fog parameters to the parameter list of the original
408 * program, rather than creating a new list. Doesn't really do any
409 * harm and it's not as if the parameter handling isn't a big hack
412 static struct prog_src_register
search_or_add_param5(struct brw_wm_compile
*c
,
419 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
420 gl_state_index tokens
[STATE_LENGTH
];
428 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
429 if (paramList
->Parameters
[idx
].Type
== PROGRAM_STATE_VAR
&&
430 memcmp(paramList
->Parameters
[idx
].StateIndexes
, tokens
, sizeof(tokens
)) == 0)
431 return src_reg(PROGRAM_STATE_VAR
, idx
);
434 idx
= _mesa_add_state_reference( paramList
, tokens
);
436 return src_reg(PROGRAM_STATE_VAR
, idx
);
440 static struct prog_src_register
search_or_add_const4f( struct brw_wm_compile
*c
,
446 struct gl_program_parameter_list
*paramList
= c
->fp
->program
.Base
.Parameters
;
456 /* Have to search, otherwise multiple compilations will each grow
457 * the parameter list.
459 for (idx
= 0; idx
< paramList
->NumParameters
; idx
++) {
460 if (paramList
->Parameters
[idx
].Type
== PROGRAM_CONSTANT
&&
461 memcmp(paramList
->ParameterValues
[idx
], values
, sizeof(values
)) == 0)
463 /* XXX: this mimics the mesa bug which puts all constants and
464 * parameters into the "PROGRAM_STATE_VAR" category:
466 return src_reg(PROGRAM_STATE_VAR
, idx
);
469 idx
= _mesa_add_unnamed_constant( paramList
, values
, 4, &swizzle
);
470 assert(swizzle
== SWIZZLE_NOOP
); /* Need to handle swizzle in reg setup */
471 return src_reg(PROGRAM_STATE_VAR
, idx
);
476 /***********************************************************************
477 * Expand various instructions here to simpler forms.
479 static void precalc_dst( struct brw_wm_compile
*c
,
480 const struct prog_instruction
*inst
)
482 struct prog_src_register src0
= inst
->SrcReg
[0];
483 struct prog_src_register src1
= inst
->SrcReg
[1];
484 struct prog_dst_register dst
= inst
->DstReg
;
486 if (dst
.WriteMask
& WRITEMASK_Y
) {
487 /* dst.y = mul src0.y, src1.y
491 dst_mask(dst
, WRITEMASK_Y
),
492 inst
->SaturateMode
, 0, 0,
499 if (dst
.WriteMask
& WRITEMASK_XZ
) {
500 struct prog_instruction
*swz
;
501 GLuint z
= GET_SWZ(src0
.Swizzle
, Z
);
503 /* dst.xz = swz src0.1zzz
507 dst_mask(dst
, WRITEMASK_XZ
),
508 inst
->SaturateMode
, 0, 0,
509 src_swizzle(src0
, SWIZZLE_ONE
, z
, z
, z
),
512 /* Avoid letting negation flag of src0 affect our 1 constant. */
513 swz
->SrcReg
[0].NegateBase
&= ~NEGATE_X
;
515 if (dst
.WriteMask
& WRITEMASK_W
) {
516 /* dst.w = mov src1.w
520 dst_mask(dst
, WRITEMASK_W
),
521 inst
->SaturateMode
, 0, 0,
529 static void precalc_lit( struct brw_wm_compile
*c
,
530 const struct prog_instruction
*inst
)
532 struct prog_src_register src0
= inst
->SrcReg
[0];
533 struct prog_dst_register dst
= inst
->DstReg
;
535 if (dst
.WriteMask
& WRITEMASK_XW
) {
536 struct prog_instruction
*swz
;
538 /* dst.xw = swz src0.1111
542 dst_mask(dst
, WRITEMASK_XW
),
544 src_swizzle1(src0
, SWIZZLE_ONE
),
547 /* Avoid letting the negation flag of src0 affect our 1 constant. */
548 swz
->SrcReg
[0].NegateBase
= 0;
552 if (dst
.WriteMask
& WRITEMASK_YZ
) {
555 dst_mask(dst
, WRITEMASK_YZ
),
556 inst
->SaturateMode
, 0, 0,
565 * Some TEX instructions require extra code, cube map coordinate
566 * normalization, or coordinate scaling for RECT textures, etc.
567 * This function emits those extra instructions and the TEX
568 * instruction itself.
570 static void precalc_tex( struct brw_wm_compile
*c
,
571 const struct prog_instruction
*inst
)
573 struct prog_src_register coord
;
574 struct prog_dst_register tmpcoord
;
575 const GLuint unit
= c
->fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
577 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
) {
578 struct prog_instruction
*out
;
579 struct prog_dst_register tmp0
= get_temp(c
);
580 struct prog_src_register tmp0src
= src_reg_from_dst(tmp0
);
581 struct prog_dst_register tmp1
= get_temp(c
);
582 struct prog_src_register tmp1src
= src_reg_from_dst(tmp1
);
583 struct prog_src_register src0
= inst
->SrcReg
[0];
585 /* find longest component of coord vector and normalize it */
586 tmpcoord
= get_temp(c
);
587 coord
= src_reg_from_dst(tmpcoord
);
589 /* tmpcoord = src0 (i.e.: coord = src0) */
590 out
= emit_op(c
, OPCODE_MOV
,
596 out
->SrcReg
[0].NegateBase
= 0;
597 out
->SrcReg
[0].Abs
= 1;
599 /* tmp0 = MAX(coord.X, coord.Y) */
600 emit_op(c
, OPCODE_MAX
,
603 src_swizzle1(coord
, X
),
604 src_swizzle1(coord
, Y
),
607 /* tmp1 = MAX(tmp0, coord.Z) */
608 emit_op(c
, OPCODE_MAX
,
612 src_swizzle1(coord
, Z
),
615 /* tmp0 = 1 / tmp1 */
616 emit_op(c
, OPCODE_RCP
,
623 /* tmpCoord = src0 * tmp0 */
624 emit_op(c
, OPCODE_MUL
,
631 release_temp(c
, tmp0
);
632 release_temp(c
, tmp1
);
634 else if (inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) {
635 struct prog_src_register scale
=
636 search_or_add_param5( c
,
642 tmpcoord
= get_temp(c
);
644 /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
654 coord
= src_reg_from_dst(tmpcoord
);
657 coord
= inst
->SrcReg
[0];
660 /* Need to emit YUV texture conversions by hand. Probably need to
661 * do this here - the alternative is in brw_wm_emit.c, but the
662 * conversion requires allocating a temporary variable which we
663 * don't have the facility to do that late in the compilation.
665 if (c
->key
.yuvtex_mask
& (1 << unit
)) {
666 /* convert ycbcr to RGBA */
667 GLboolean swap_uv
= c
->key
.yuvtex_swap_mask
& (1<<unit
);
670 CONST C0 = { -.5, -.0625, -.5, 1.164 }
671 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
673 UYV.xyz = ADD UYV, C0
674 UYV.y = MUL UYV.y, C0.w
676 RGB.xyz = MAD UYV.zzx, C1, UYV.y
678 RGB.xyz = MAD UYV.xxz, C1, UYV.y
679 RGB.y = MAD UYV.z, C1.w, RGB.y
681 struct prog_dst_register dst
= inst
->DstReg
;
682 struct prog_dst_register tmp
= get_temp(c
);
683 struct prog_src_register tmpsrc
= src_reg_from_dst(tmp
);
684 struct prog_src_register C0
= search_or_add_const4f( c
, -.5, -.0625, -.5, 1.164 );
685 struct prog_src_register C1
= search_or_add_const4f( c
, 1.596, -0.813, 2.018, -.391 );
699 /* tmp.xyz = ADD TMP, C0
703 dst_mask(tmp
, WRITEMASK_XYZ
),
709 /* YUV.y = MUL YUV.y, C0.w
714 dst_mask(tmp
, WRITEMASK_Y
),
722 * RGB.xyz = MAD YUV.zzx, C1, YUV.y
724 * RGB.xyz = MAD YUV.xxz, C1, YUV.y
729 dst_mask(dst
, WRITEMASK_XYZ
),
731 swap_uv
?src_swizzle(tmpsrc
, Z
,Z
,X
,X
):src_swizzle(tmpsrc
, X
,X
,Z
,Z
),
733 src_swizzle1(tmpsrc
, Y
));
735 /* RGB.y = MAD YUV.z, C1.w, RGB.y
739 dst_mask(dst
, WRITEMASK_Y
),
741 src_swizzle1(tmpsrc
, Z
),
743 src_swizzle1(src_reg_from_dst(dst
), Y
));
745 release_temp(c
, tmp
);
748 /* ordinary RGBA tex instruction */
760 /* For GL_EXT_texture_swizzle: */
761 if (c
->key
.tex_swizzles
[unit
] != SWIZZLE_NOOP
) {
762 /* swizzle the result of the TEX instruction */
763 struct prog_src_register tmpsrc
= src_reg_from_dst(inst
->DstReg
);
764 emit_op(c
, OPCODE_SWZ
,
766 SATURATE_OFF
, /* saturate already done above */
767 0, 0, /* tex unit, target N/A */
768 src_swizzle4(tmpsrc
, c
->key
.tex_swizzles
[unit
]),
773 if ((inst
->TexSrcTarget
== TEXTURE_RECT_INDEX
) ||
774 (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
))
775 release_temp(c
, tmpcoord
);
779 static GLboolean
projtex( struct brw_wm_compile
*c
,
780 const struct prog_instruction
*inst
)
782 struct prog_src_register src
= inst
->SrcReg
[0];
784 /* Only try to detect the simplest cases. Could detect (later)
785 * cases where we are trying to emit code like RCP {1.0}, MUL x,
788 * More complex cases than this typically only arise from
789 * user-provided fragment programs anyway:
791 if (inst
->TexSrcTarget
== TEXTURE_CUBE_INDEX
)
792 return 0; /* ut2004 gun rendering !?! */
793 else if (src
.File
== PROGRAM_INPUT
&&
794 GET_SWZ(src
.Swizzle
, W
) == W
&&
795 (c
->key
.projtex_mask
& (1<<(src
.Index
+ FRAG_ATTRIB_WPOS
- FRAG_ATTRIB_TEX0
))) == 0)
802 static void precalc_txp( struct brw_wm_compile
*c
,
803 const struct prog_instruction
*inst
)
805 struct prog_src_register src0
= inst
->SrcReg
[0];
807 if (projtex(c
, inst
)) {
808 struct prog_dst_register tmp
= get_temp(c
);
809 struct prog_instruction tmp_inst
;
811 /* tmp0.w = RCP inst.arg[0][3]
815 dst_mask(tmp
, WRITEMASK_W
),
817 src_swizzle1(src0
, GET_SWZ(src0
.Swizzle
, W
)),
821 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww
825 dst_mask(tmp
, WRITEMASK_XYZ
),
828 src_swizzle1(src_reg_from_dst(tmp
), W
),
831 /* dst = precalc(TEX tmp0)
834 tmp_inst
.SrcReg
[0] = src_reg_from_dst(tmp
);
835 precalc_tex(c
, &tmp_inst
);
837 release_temp(c
, tmp
);
841 /* dst = precalc(TEX src0)
843 precalc_tex(c
, inst
);
849 static void emit_fb_write( struct brw_wm_compile
*c
)
851 struct prog_src_register payload_r0_depth
= src_reg(PROGRAM_PAYLOAD
, PAYLOAD_DEPTH
);
852 struct prog_src_register outdepth
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DEPR
);
853 struct prog_src_register outcolor
;
856 struct prog_instruction
*inst
, *last_inst
;
857 struct brw_context
*brw
= c
->func
.brw
;
859 /* inst->Sampler is not used by backend,
860 use it for fb write target and eot */
862 if (brw
->state
.nr_draw_regions
> 1) {
863 for (i
= 0 ; i
< brw
->state
.nr_draw_regions
; i
++) {
864 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
+ i
);
865 last_inst
= inst
= emit_op(c
,
866 WM_FB_WRITE
, dst_mask(dst_undef(),0), 0, 0, 0,
867 outcolor
, payload_r0_depth
, outdepth
);
868 inst
->Sampler
= (i
<<1);
869 if (c
->fp_fragcolor_emitted
) {
870 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLR
);
871 last_inst
= inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
872 0, 0, 0, outcolor
, payload_r0_depth
, outdepth
);
873 inst
->Sampler
= (i
<<1);
876 last_inst
->Sampler
|= 1; //eot
879 /* if gl_FragData[0] is written, use it, else use gl_FragColor */
880 if (c
->fp
->program
.Base
.OutputsWritten
& (1 << FRAG_RESULT_DATA0
))
881 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_DATA0
);
883 outcolor
= src_reg(PROGRAM_OUTPUT
, FRAG_RESULT_COLR
);
885 inst
= emit_op(c
, WM_FB_WRITE
, dst_mask(dst_undef(),0),
886 0, 0, 0, outcolor
, payload_r0_depth
, outdepth
);
887 inst
->Sampler
= 1|(0<<1);
894 /***********************************************************************
895 * Emit INTERP instructions ahead of first use of each attrib.
898 static void validate_src_regs( struct brw_wm_compile
*c
,
899 const struct prog_instruction
*inst
)
901 GLuint nr_args
= brw_wm_nr_args( inst
->Opcode
);
904 for (i
= 0; i
< nr_args
; i
++) {
905 if (inst
->SrcReg
[i
].File
== PROGRAM_INPUT
) {
906 GLuint idx
= inst
->SrcReg
[i
].Index
;
907 if (!(c
->fp_interp_emitted
& (1<<idx
))) {
914 static void validate_dst_regs( struct brw_wm_compile
*c
,
915 const struct prog_instruction
*inst
)
917 if (inst
->DstReg
.File
== PROGRAM_OUTPUT
) {
918 GLuint idx
= inst
->DstReg
.Index
;
919 if (idx
== FRAG_RESULT_COLR
)
920 c
->fp_fragcolor_emitted
= 1;
924 static void print_insns( const struct prog_instruction
*insn
,
928 for (i
= 0; i
< nr
; i
++, insn
++) {
929 _mesa_printf("%3d: ", i
);
930 if (insn
->Opcode
< MAX_OPCODE
)
931 _mesa_print_instruction(insn
);
932 else if (insn
->Opcode
< MAX_WM_OPCODE
) {
933 GLuint idx
= insn
->Opcode
- MAX_OPCODE
;
935 _mesa_print_alu_instruction(insn
,
936 wm_opcode_strings
[idx
],
940 _mesa_printf("UNKNOWN\n");
945 void brw_wm_pass_fp( struct brw_wm_compile
*c
)
947 struct brw_fragment_program
*fp
= c
->fp
;
950 if (INTEL_DEBUG
& DEBUG_WM
) {
951 _mesa_printf("pre-fp:\n");
952 _mesa_print_program(&fp
->program
.Base
);
956 c
->pixel_xy
= src_undef();
957 c
->delta_xy
= src_undef();
958 c
->pixel_w
= src_undef();
961 /* Emit preamble instructions:
965 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
966 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
967 validate_src_regs(c
, inst
);
968 validate_dst_regs(c
, inst
);
970 for (insn
= 0; insn
< fp
->program
.Base
.NumInstructions
; insn
++) {
971 const struct prog_instruction
*inst
= &fp
->program
.Base
.Instructions
[insn
];
972 struct prog_instruction
*out
;
974 /* Check for INPUT values, emit INTERP instructions where
979 switch (inst
->Opcode
) {
981 out
= emit_insn(c
, inst
);
982 out
->Opcode
= OPCODE_MOV
;
986 out
= emit_insn(c
, inst
);
987 out
->Opcode
= OPCODE_MOV
;
988 out
->SrcReg
[0].NegateBase
= 0;
989 out
->SrcReg
[0].Abs
= 1;
993 out
= emit_insn(c
, inst
);
994 out
->Opcode
= OPCODE_ADD
;
995 out
->SrcReg
[1].NegateBase
^= 0xf;
999 out
= emit_insn(c
, inst
);
1000 /* This should probably be done in the parser.
1002 out
->DstReg
.WriteMask
&= WRITEMASK_XY
;
1006 precalc_dst(c
, inst
);
1010 precalc_lit(c
, inst
);
1014 precalc_tex(c
, inst
);
1018 precalc_txp(c
, inst
);
1022 out
= emit_insn(c
, inst
);
1023 out
->TexSrcUnit
= fp
->program
.Base
.SamplerUnits
[inst
->TexSrcUnit
];
1027 out
= emit_insn(c
, inst
);
1028 /* This should probably be done in the parser.
1030 out
->DstReg
.WriteMask
&= WRITEMASK_XYZ
;
1034 out
= emit_insn(c
, inst
);
1035 /* This should probably be done in the parser.
1037 out
->DstReg
.WriteMask
= 0;
1057 if (INTEL_DEBUG
& DEBUG_WM
) {
1058 _mesa_printf("pass_fp:\n");
1059 print_insns( c
->prog_instructions
, c
->nr_fp_insns
);