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, colortable, convolution...
36 #include "main/imports.h"
37 #include "main/image.h"
38 #include "main/macros.h"
39 #include "program/program.h"
40 #include "program/prog_cache.h"
41 #include "program/prog_instruction.h"
42 #include "program/prog_parameter.h"
43 #include "program/prog_print.h"
45 #include "st_context.h"
46 #include "st_format.h"
47 #include "st_texture.h"
49 #include "pipe/p_screen.h"
50 #include "pipe/p_context.h"
51 #include "util/u_inlines.h"
52 #include "util/u_pack_color.h"
57 GLuint scaleAndBias
:1;
61 GLfloat Maps
[3][256][4];
64 pipeline_stage Stages
[STAGE_MAX
];
65 GLboolean StagesUsed
[STAGE_MAX
];
66 GLfloat Scale1
[4], Bias1
[4];
67 GLfloat Scale2
[4], Bias2
[4];
72 make_state_key(struct gl_context
*ctx
, struct state_key
*key
)
74 memset(key
, 0, sizeof(*key
));
76 if (ctx
->Pixel
.RedBias
!= 0.0 || ctx
->Pixel
.RedScale
!= 1.0 ||
77 ctx
->Pixel
.GreenBias
!= 0.0 || ctx
->Pixel
.GreenScale
!= 1.0 ||
78 ctx
->Pixel
.BlueBias
!= 0.0 || ctx
->Pixel
.BlueScale
!= 1.0 ||
79 ctx
->Pixel
.AlphaBias
!= 0.0 || ctx
->Pixel
.AlphaScale
!= 1.0) {
80 key
->scaleAndBias
= 1;
83 key
->pixelMaps
= ctx
->Pixel
.MapColorFlag
;
88 * Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
91 load_color_map_texture(struct gl_context
*ctx
, struct pipe_resource
*pt
)
93 struct st_context
*st
= st_context(ctx
);
94 struct pipe_context
*pipe
= st
->pipe
;
95 struct pipe_transfer
*transfer
;
96 const GLuint rSize
= ctx
->PixelMaps
.RtoR
.Size
;
97 const GLuint gSize
= ctx
->PixelMaps
.GtoG
.Size
;
98 const GLuint bSize
= ctx
->PixelMaps
.BtoB
.Size
;
99 const GLuint aSize
= ctx
->PixelMaps
.AtoA
.Size
;
100 const uint texSize
= pt
->width0
;
104 transfer
= pipe_get_transfer(pipe
,
105 pt
, 0, 0, PIPE_TRANSFER_WRITE
,
106 0, 0, texSize
, texSize
);
107 dest
= (uint
*) pipe_transfer_map(pipe
, transfer
);
109 /* Pack four 1D maps into a 2D texture:
110 * R map is placed horizontally, indexed by S, in channel 0
111 * G map is placed vertically, indexed by T, in channel 1
112 * B map is placed horizontally, indexed by S, in channel 2
113 * A map is placed vertically, indexed by T, in channel 3
115 for (i
= 0; i
< texSize
; i
++) {
116 for (j
= 0; j
< texSize
; j
++) {
118 int k
= (i
* texSize
+ j
);
119 ubyte r
= ctx
->PixelMaps
.RtoR
.Map8
[j
* rSize
/ texSize
];
120 ubyte g
= ctx
->PixelMaps
.GtoG
.Map8
[i
* gSize
/ texSize
];
121 ubyte b
= ctx
->PixelMaps
.BtoB
.Map8
[j
* bSize
/ texSize
];
122 ubyte a
= ctx
->PixelMaps
.AtoA
.Map8
[i
* aSize
/ texSize
];
123 util_pack_color_ub(r
, g
, b
, a
, pt
->format
, &uc
);
128 pipe_transfer_unmap(pipe
, transfer
);
129 pipe
->transfer_destroy(pipe
, transfer
);
137 * Returns a fragment program which implements the current pixel transfer ops.
139 static struct gl_fragment_program
*
140 get_pixel_transfer_program(struct gl_context
*ctx
, const struct state_key
*key
)
142 struct st_context
*st
= st_context(ctx
);
143 struct prog_instruction inst
[MAX_INST
];
144 struct gl_program_parameter_list
*params
;
145 struct gl_fragment_program
*fp
;
147 const GLuint colorTemp
= 0;
149 fp
= (struct gl_fragment_program
*)
150 ctx
->Driver
.NewProgram(ctx
, GL_FRAGMENT_PROGRAM_ARB
, 0);
154 params
= _mesa_new_parameter_list();
157 * Get initial pixel color from the texture.
158 * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
160 _mesa_init_instructions(inst
+ ic
, 1);
161 inst
[ic
].Opcode
= OPCODE_TEX
;
162 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
163 inst
[ic
].DstReg
.Index
= colorTemp
;
164 inst
[ic
].SrcReg
[0].File
= PROGRAM_INPUT
;
165 inst
[ic
].SrcReg
[0].Index
= FRAG_ATTRIB_TEX0
;
166 inst
[ic
].TexSrcUnit
= 0;
167 inst
[ic
].TexSrcTarget
= TEXTURE_2D_INDEX
;
169 fp
->Base
.InputsRead
= BITFIELD64_BIT(FRAG_ATTRIB_TEX0
);
170 fp
->Base
.OutputsWritten
= BITFIELD64_BIT(FRAG_RESULT_COLOR
);
171 fp
->Base
.SamplersUsed
= 0x1; /* sampler 0 (bit 0) is used */
173 if (key
->scaleAndBias
) {
174 static const gl_state_index scale_state
[STATE_LENGTH
] =
175 { STATE_INTERNAL
, STATE_PT_SCALE
, 0, 0, 0 };
176 static const gl_state_index bias_state
[STATE_LENGTH
] =
177 { STATE_INTERNAL
, STATE_PT_BIAS
, 0, 0, 0 };
178 GLint scale_p
, bias_p
;
180 scale_p
= _mesa_add_state_reference(params
, scale_state
);
181 bias_p
= _mesa_add_state_reference(params
, bias_state
);
183 /* MAD colorTemp, colorTemp, scale, bias; */
184 _mesa_init_instructions(inst
+ ic
, 1);
185 inst
[ic
].Opcode
= OPCODE_MAD
;
186 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
187 inst
[ic
].DstReg
.Index
= colorTemp
;
188 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
189 inst
[ic
].SrcReg
[0].Index
= colorTemp
;
190 inst
[ic
].SrcReg
[1].File
= PROGRAM_STATE_VAR
;
191 inst
[ic
].SrcReg
[1].Index
= scale_p
;
192 inst
[ic
].SrcReg
[2].File
= PROGRAM_STATE_VAR
;
193 inst
[ic
].SrcReg
[2].Index
= bias_p
;
197 if (key
->pixelMaps
) {
198 const GLuint temp
= 1;
200 /* create the colormap/texture now if not already done */
201 if (!st
->pixel_xfer
.pixelmap_texture
) {
202 st
->pixel_xfer
.pixelmap_texture
= st_create_color_map_texture(ctx
);
203 st
->pixel_xfer
.pixelmap_sampler_view
=
204 st_create_texture_sampler_view(st
->pipe
,
205 st
->pixel_xfer
.pixelmap_texture
);
208 /* with a little effort, we can do four pixel map look-ups with
209 * two TEX instructions:
212 /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
213 _mesa_init_instructions(inst
+ ic
, 1);
214 inst
[ic
].Opcode
= OPCODE_TEX
;
215 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
216 inst
[ic
].DstReg
.Index
= temp
;
217 inst
[ic
].DstReg
.WriteMask
= WRITEMASK_XY
; /* write R,G */
218 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
219 inst
[ic
].SrcReg
[0].Index
= colorTemp
;
220 inst
[ic
].TexSrcUnit
= 1;
221 inst
[ic
].TexSrcTarget
= TEXTURE_2D_INDEX
;
224 /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
225 _mesa_init_instructions(inst
+ ic
, 1);
226 inst
[ic
].Opcode
= OPCODE_TEX
;
227 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
228 inst
[ic
].DstReg
.Index
= temp
;
229 inst
[ic
].DstReg
.WriteMask
= WRITEMASK_ZW
; /* write B,A */
230 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
231 inst
[ic
].SrcReg
[0].Index
= colorTemp
;
232 inst
[ic
].SrcReg
[0].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_Z
, SWIZZLE_W
,
233 SWIZZLE_Z
, SWIZZLE_W
);
234 inst
[ic
].TexSrcUnit
= 1;
235 inst
[ic
].TexSrcTarget
= TEXTURE_2D_INDEX
;
238 /* MOV colorTemp, temp; */
239 _mesa_init_instructions(inst
+ ic
, 1);
240 inst
[ic
].Opcode
= OPCODE_MOV
;
241 inst
[ic
].DstReg
.File
= PROGRAM_TEMPORARY
;
242 inst
[ic
].DstReg
.Index
= colorTemp
;
243 inst
[ic
].SrcReg
[0].File
= PROGRAM_TEMPORARY
;
244 inst
[ic
].SrcReg
[0].Index
= temp
;
247 fp
->Base
.SamplersUsed
|= (1 << 1); /* sampler 1 is used */
250 /* Modify last instruction's dst reg to write to result.color */
252 struct prog_instruction
*last
= &inst
[ic
- 1];
253 last
->DstReg
.File
= PROGRAM_OUTPUT
;
254 last
->DstReg
.Index
= FRAG_RESULT_COLOR
;
258 _mesa_init_instructions(inst
+ ic
, 1);
259 inst
[ic
].Opcode
= OPCODE_END
;
262 assert(ic
<= MAX_INST
);
265 fp
->Base
.Instructions
= _mesa_alloc_instructions(ic
);
266 if (!fp
->Base
.Instructions
) {
267 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
268 "generating pixel transfer program");
269 _mesa_free_parameter_list(params
);
273 _mesa_copy_instructions(fp
->Base
.Instructions
, inst
, ic
);
274 fp
->Base
.NumInstructions
= ic
;
275 fp
->Base
.Parameters
= params
;
278 printf("========= pixel transfer prog\n");
279 _mesa_print_program(&fp
->Base
);
280 _mesa_print_parameter_list(fp
->Base
.Parameters
);
289 * Update st->pixel_xfer.program in response to new pixel-transfer state.
292 update_pixel_transfer(struct st_context
*st
)
294 struct gl_context
*ctx
= st
->ctx
;
295 struct state_key key
;
296 struct gl_fragment_program
*fp
;
298 make_state_key(st
->ctx
, &key
);
300 fp
= (struct gl_fragment_program
*)
301 _mesa_search_program_cache(st
->pixel_xfer
.cache
, &key
, sizeof(key
));
303 fp
= get_pixel_transfer_program(st
->ctx
, &key
);
304 _mesa_program_cache_insert(st
->ctx
, st
->pixel_xfer
.cache
,
305 &key
, sizeof(key
), &fp
->Base
);
308 if (ctx
->Pixel
.MapColorFlag
) {
309 load_color_map_texture(ctx
, st
->pixel_xfer
.pixelmap_texture
);
311 st
->pixel_xfer
.pixelmap_enabled
= ctx
->Pixel
.MapColorFlag
;
313 st
->pixel_xfer
.program
= (struct st_fragment_program
*) fp
;
318 const struct st_tracked_state st_update_pixel_transfer
= {
319 "st_update_pixel_transfer", /* name */
321 _NEW_PIXEL
, /* mesa */
324 update_pixel_transfer
/* update */