1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 * Generate fragment programs to implement pixel transfer ops, such as
30 * scale/bias, colormatrix, colortable, convolution...
36 #include "main/imports.h"
37 #include "main/image.h"
38 #include "main/macros.h"
39 #include "shader/program.h"
40 #include "shader/prog_instruction.h"
41 #include "shader/prog_parameter.h"
42 #include "shader/prog_print.h"
44 #include "st_context.h"
45 #include "st_program.h"
51 GLuint scaleAndBias
:1;
55 GLfloat Maps
[3][256][4];
58 pipeline_stage Stages
[STAGE_MAX
];
59 GLboolean StagesUsed
[STAGE_MAX
];
60 GLfloat Scale1
[4], Bias1
[4];
61 GLfloat Scale2
[4], Bias2
[4];
67 is_identity(const GLfloat m
[16])
70 for (i
= 0; i
< 16; i
++) {
71 const int row
= i
% 4, col
= i
/ 4;
72 const float val
= (row
== col
);
81 make_state_key(GLcontext
*ctx
, struct state_key
*key
)
83 memset(key
, 0, sizeof(*key
));
85 if (ctx
->Pixel
.RedBias
!= 0.0 || ctx
->Pixel
.RedScale
!= 1.0 ||
86 ctx
->Pixel
.GreenBias
!= 0.0 || ctx
->Pixel
.GreenScale
!= 1.0 ||
87 ctx
->Pixel
.BlueBias
!= 0.0 || ctx
->Pixel
.BlueScale
!= 1.0 ||
88 ctx
->Pixel
.AlphaBias
!= 0.0 || ctx
->Pixel
.AlphaScale
!= 1.0) {
89 key
->scaleAndBias
= 1;
92 if (!is_identity(ctx
->ColorMatrixStack
.Top
->m
)) {
103 * Returns a fragment program which implements the current pixel transfer ops.
105 static struct gl_fragment_program
*
106 get_pixel_transfer_program(GLcontext
*ctx
, const struct state_key
*key
)
108 struct prog_instruction inst
[MAX_INST
];
109 struct gl_program_parameter_list
*params
;
110 struct gl_fragment_program
*fp
;
112 const GLuint colorTemp
= 0;
114 fp
= (struct gl_fragment_program
*)
115 ctx
->Driver
.NewProgram(ctx
, GL_FRAGMENT_PROGRAM_ARB
, 0);
119 params
= _mesa_new_parameter_list();
121 /* TEX colorTemp, fragment.texcoord[0], texture[0], 2D; */
122 _mesa_init_instructions(inst
+ ic
, 1);
123 inst
[ic
].Opcode
= OPCODE_TEX
;
124 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
125 inst
[ic
].DstReg
.Index
= colorTemp
;
126 inst
[ic
].SrcReg
[0].File
= PROGRAM_INPUT
;
127 inst
[ic
].SrcReg
[0].Index
= FRAG_ATTRIB_TEX0
;
128 inst
[ic
].TexSrcUnit
= 0;
129 inst
[ic
].TexSrcTarget
= TEXTURE_2D_INDEX
;
131 fp
->Base
.InputsRead
= (1 << FRAG_ATTRIB_TEX0
);
132 fp
->Base
.OutputsWritten
= (1 << FRAG_RESULT_COLR
);
134 /* MAD colorTemp, colorTemp, scale, bias; */
135 if (key
->scaleAndBias
) {
136 static const gl_state_index scale_state
[STATE_LENGTH
] =
137 { STATE_INTERNAL
, STATE_PT_SCALE
, 0, 0, 0 };
138 static const gl_state_index bias_state
[STATE_LENGTH
] =
139 { STATE_INTERNAL
, STATE_PT_BIAS
, 0, 0, 0 };
140 GLfloat scale
[4], bias
[4];
141 GLint scale_p
, bias_p
;
143 scale
[0] = ctx
->Pixel
.RedScale
;
144 scale
[1] = ctx
->Pixel
.GreenScale
;
145 scale
[2] = ctx
->Pixel
.BlueScale
;
146 scale
[3] = ctx
->Pixel
.AlphaScale
;
147 bias
[0] = ctx
->Pixel
.RedBias
;
148 bias
[1] = ctx
->Pixel
.GreenBias
;
149 bias
[2] = ctx
->Pixel
.BlueBias
;
150 bias
[3] = ctx
->Pixel
.AlphaBias
;
152 scale_p
= _mesa_add_state_reference(params
, scale_state
);
153 bias_p
= _mesa_add_state_reference(params
, bias_state
);
155 _mesa_init_instructions(inst
+ ic
, 1);
156 inst
[ic
].Opcode
= OPCODE_MAD
;
157 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
158 inst
[ic
].DstReg
.Index
= colorTemp
;
159 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
160 inst
[ic
].SrcReg
[0].Index
= colorTemp
;
161 inst
[ic
].SrcReg
[1].File
= PROGRAM_STATE_VAR
;
162 inst
[ic
].SrcReg
[1].Index
= scale_p
;
163 inst
[ic
].SrcReg
[2].File
= PROGRAM_STATE_VAR
;
164 inst
[ic
].SrcReg
[2].Index
= bias_p
;
168 if (key
->colorMatrix
) {
169 static const gl_state_index row0_state
[STATE_LENGTH
] =
170 { STATE_COLOR_MATRIX
, 0, 0, 0, 0 };
171 static const gl_state_index row1_state
[STATE_LENGTH
] =
172 { STATE_COLOR_MATRIX
, 0, 1, 1, 0 };
173 static const gl_state_index row2_state
[STATE_LENGTH
] =
174 { STATE_COLOR_MATRIX
, 0, 2, 2, 0 };
175 static const gl_state_index row3_state
[STATE_LENGTH
] =
176 { STATE_COLOR_MATRIX
, 0, 3, 3, 0 };
178 GLint row0_p
= _mesa_add_state_reference(params
, row0_state
);
179 GLint row1_p
= _mesa_add_state_reference(params
, row1_state
);
180 GLint row2_p
= _mesa_add_state_reference(params
, row2_state
);
181 GLint row3_p
= _mesa_add_state_reference(params
, row3_state
);
182 const GLuint temp
= 1;
184 /* MOV temp, colorTemp; */
185 _mesa_init_instructions(inst
+ ic
, 1);
186 inst
[ic
].Opcode
= OPCODE_MOV
;
187 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
188 inst
[ic
].DstReg
.Index
= temp
;
189 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
190 inst
[ic
].SrcReg
[0].Index
= colorTemp
;
193 /* XXX reimplement in terms of MUL/MAD (see t_vp_build.c) */
195 /* DP4 colorTemp.x, temp, matrow0; */
196 _mesa_init_instructions(inst
+ ic
, 1);
197 inst
[ic
].Opcode
= OPCODE_DP4
;
198 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
199 inst
[ic
].DstReg
.Index
= colorTemp
;
200 inst
[ic
].DstReg
.WriteMask
= WRITEMASK_X
;
201 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
202 inst
[ic
].SrcReg
[0].Index
= temp
;
203 inst
[ic
].SrcReg
[1].File
= PROGRAM_STATE_VAR
;
204 inst
[ic
].SrcReg
[1].Index
= row0_p
;
207 /* DP4 colorTemp.y, temp, matrow1; */
208 _mesa_init_instructions(inst
+ ic
, 1);
209 inst
[ic
].Opcode
= OPCODE_DP4
;
210 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
211 inst
[ic
].DstReg
.Index
= colorTemp
;
212 inst
[ic
].DstReg
.WriteMask
= WRITEMASK_Y
;
213 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
214 inst
[ic
].SrcReg
[0].Index
= temp
;
215 inst
[ic
].SrcReg
[1].File
= PROGRAM_STATE_VAR
;
216 inst
[ic
].SrcReg
[1].Index
= row1_p
;
219 /* DP4 colorTemp.z, temp, matrow2; */
220 _mesa_init_instructions(inst
+ ic
, 1);
221 inst
[ic
].Opcode
= OPCODE_DP4
;
222 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
223 inst
[ic
].DstReg
.Index
= colorTemp
;
224 inst
[ic
].DstReg
.WriteMask
= WRITEMASK_Z
;
225 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
226 inst
[ic
].SrcReg
[0].Index
= temp
;
227 inst
[ic
].SrcReg
[1].File
= PROGRAM_STATE_VAR
;
228 inst
[ic
].SrcReg
[1].Index
= row2_p
;
231 /* DP4 colorTemp.w, temp, matrow3; */
232 _mesa_init_instructions(inst
+ ic
, 1);
233 inst
[ic
].Opcode
= OPCODE_DP4
;
234 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
235 inst
[ic
].DstReg
.Index
=colorTemp
;
236 inst
[ic
].DstReg
.WriteMask
= WRITEMASK_W
;
237 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
238 inst
[ic
].SrcReg
[0].Index
= temp
;
239 inst
[ic
].SrcReg
[1].File
= PROGRAM_STATE_VAR
;
240 inst
[ic
].SrcReg
[1].Index
= row3_p
;
244 /* Modify last instruction's dst reg to write to result.color */
246 struct prog_instruction
*last
= &inst
[ic
- 1];
247 last
->DstReg
.File
= PROGRAM_OUTPUT
;
248 last
->DstReg
.Index
= FRAG_RESULT_COLR
;
252 _mesa_init_instructions(inst
+ ic
, 1);
253 inst
[ic
].Opcode
= OPCODE_END
;
256 assert(ic
<= MAX_INST
);
259 fp
->Base
.Instructions
= _mesa_alloc_instructions(ic
);
260 if (!fp
->Base
.Instructions
) {
261 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
262 "generating pixel transfer program");
266 _mesa_copy_instructions(fp
->Base
.Instructions
, inst
, ic
);
267 fp
->Base
.NumInstructions
= ic
;
268 fp
->Base
.Parameters
= params
;
271 printf("========= pixel transfer prog\n");
272 _mesa_print_program(&fp
->Base
);
273 _mesa_print_parameter_list(fp
->Base
.Parameters
);
282 * Update st->pixel_xfer.program in response to new pixel-transfer state.
285 update_pixel_transfer(struct st_context
*st
)
287 struct state_key key
;
288 struct gl_fragment_program
*fp
;
290 make_state_key(st
->ctx
, &key
);
292 fp
= (struct gl_fragment_program
*)
293 _mesa_search_program_cache(st
->pixel_xfer
.cache
, &key
, sizeof(key
));
295 fp
= get_pixel_transfer_program(st
->ctx
, &key
);
296 _mesa_program_cache_insert(st
->ctx
, st
->pixel_xfer
.cache
,
297 &key
, sizeof(key
), &fp
->Base
);
300 st
->pixel_xfer
.program
= (struct st_fragment_program
*) fp
;
305 const struct st_tracked_state st_update_pixel_transfer
= {
306 .name
= "st_update_pixel_transfer",
308 .mesa
= _NEW_PIXEL
| _NEW_COLOR_MATRIX
,
311 .update
= update_pixel_transfer