00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "main/imports.h"
00037 #include "main/image.h"
00038 #include "main/macros.h"
00039 #include "shader/program.h"
00040 #include "shader/prog_instruction.h"
00041 #include "shader/prog_parameter.h"
00042 #include "shader/prog_print.h"
00043
00044 #include "st_context.h"
00045 #include "st_format.h"
00046 #include "st_program.h"
00047 #include "st_texture.h"
00048
00049 #include "pipe/p_screen.h"
00050 #include "pipe/p_context.h"
00051 #include "pipe/p_inlines.h"
00052 #include "util/u_pack_color.h"
00053
00054
00055 struct state_key
00056 {
00057 GLuint scaleAndBias:1;
00058 GLuint colorMatrix:1;
00059 GLuint colorMatrixPostScaleBias:1;
00060 GLuint pixelMaps:1;
00061
00062 #if 0
00063 GLfloat Maps[3][256][4];
00064 int NumMaps;
00065 GLint NumStages;
00066 pipeline_stage Stages[STAGE_MAX];
00067 GLboolean StagesUsed[STAGE_MAX];
00068 GLfloat Scale1[4], Bias1[4];
00069 GLfloat Scale2[4], Bias2[4];
00070 #endif
00071 };
00072
00073
00074 static GLboolean
00075 is_identity(const GLfloat m[16])
00076 {
00077 GLuint i;
00078 for (i = 0; i < 16; i++) {
00079 const int row = i % 4, col = i / 4;
00080 const float val = (GLfloat)(row == col);
00081 if (m[i] != val)
00082 return GL_FALSE;
00083 }
00084 return GL_TRUE;
00085 }
00086
00087
00088 static void
00089 make_state_key(GLcontext *ctx, struct state_key *key)
00090 {
00091 static const GLfloat zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
00092 static const GLfloat one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
00093
00094 memset(key, 0, sizeof(*key));
00095
00096 if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
00097 ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
00098 ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
00099 ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
00100 key->scaleAndBias = 1;
00101 }
00102
00103 if (!is_identity(ctx->ColorMatrixStack.Top->m)) {
00104 key->colorMatrix = 1;
00105 }
00106
00107 if (!TEST_EQ_4V(ctx->Pixel.PostColorMatrixScale, one) ||
00108 !TEST_EQ_4V(ctx->Pixel.PostColorMatrixBias, zero)) {
00109 key->colorMatrixPostScaleBias = 1;
00110 }
00111
00112 key->pixelMaps = ctx->Pixel.MapColorFlag;
00113 }
00114
00115
00116 static struct pipe_texture *
00117 create_color_map_texture(GLcontext *ctx)
00118 {
00119 struct pipe_context *pipe = ctx->st->pipe;
00120 struct pipe_texture *pt;
00121 enum pipe_format format;
00122 const uint texSize = 256;
00123
00124
00125 format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER);
00126
00127
00128 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0,
00129 texSize, texSize, 1, 0,
00130 PIPE_TEXTURE_USAGE_SAMPLER);
00131 return pt;
00132 }
00133
00134
00138 static void
00139 load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)
00140 {
00141 struct pipe_context *pipe = ctx->st->pipe;
00142 struct pipe_screen *screen = pipe->screen;
00143 struct pipe_surface *surface;
00144 const GLuint rSize = ctx->PixelMaps.RtoR.Size;
00145 const GLuint gSize = ctx->PixelMaps.GtoG.Size;
00146 const GLuint bSize = ctx->PixelMaps.BtoB.Size;
00147 const GLuint aSize = ctx->PixelMaps.AtoA.Size;
00148 const uint texSize = pt->width[0];
00149 uint *dest;
00150 uint i, j;
00151
00152 surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
00153 PIPE_BUFFER_USAGE_CPU_WRITE);
00154 dest = (uint *) screen->surface_map(screen, surface,
00155 PIPE_BUFFER_USAGE_CPU_WRITE);
00156
00157
00158
00159
00160
00161
00162
00163 for (i = 0; i < texSize; i++) {
00164 for (j = 0; j < texSize; j++) {
00165 int k = (i * texSize + j);
00166 ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize];
00167 ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize];
00168 ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize];
00169 ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize];
00170 util_pack_color_ub(r, g, b, a, pt->format, dest + k);
00171 }
00172 }
00173
00174 screen->surface_unmap(screen, surface);
00175 pipe_surface_reference(&surface, NULL);
00176 }
00177
00178
00179
00180 #define MAX_INST 100
00181
00185 static struct gl_fragment_program *
00186 get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
00187 {
00188 struct st_context *st = ctx->st;
00189 struct prog_instruction inst[MAX_INST];
00190 struct gl_program_parameter_list *params;
00191 struct gl_fragment_program *fp;
00192 GLuint ic = 0;
00193 const GLuint colorTemp = 0;
00194
00195 fp = (struct gl_fragment_program *)
00196 ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
00197 if (!fp)
00198 return NULL;
00199
00200 params = _mesa_new_parameter_list();
00201
00202
00203
00204
00205
00206 _mesa_init_instructions(inst + ic, 1);
00207 inst[ic].Opcode = OPCODE_TEX;
00208 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00209 inst[ic].DstReg.Index = colorTemp;
00210 inst[ic].SrcReg[0].File = PROGRAM_INPUT;
00211 inst[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
00212 inst[ic].TexSrcUnit = 0;
00213 inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
00214 ic++;
00215 fp->Base.InputsRead = (1 << FRAG_ATTRIB_TEX0);
00216 fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLR);
00217 fp->Base.SamplersUsed = 0x1;
00218
00219 if (key->scaleAndBias) {
00220 static const gl_state_index scale_state[STATE_LENGTH] =
00221 { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
00222 static const gl_state_index bias_state[STATE_LENGTH] =
00223 { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
00224 GLfloat scale[4], bias[4];
00225 GLint scale_p, bias_p;
00226
00227 scale[0] = ctx->Pixel.RedScale;
00228 scale[1] = ctx->Pixel.GreenScale;
00229 scale[2] = ctx->Pixel.BlueScale;
00230 scale[3] = ctx->Pixel.AlphaScale;
00231 bias[0] = ctx->Pixel.RedBias;
00232 bias[1] = ctx->Pixel.GreenBias;
00233 bias[2] = ctx->Pixel.BlueBias;
00234 bias[3] = ctx->Pixel.AlphaBias;
00235
00236 scale_p = _mesa_add_state_reference(params, scale_state);
00237 bias_p = _mesa_add_state_reference(params, bias_state);
00238
00239
00240 _mesa_init_instructions(inst + ic, 1);
00241 inst[ic].Opcode = OPCODE_MAD;
00242 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00243 inst[ic].DstReg.Index = colorTemp;
00244 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00245 inst[ic].SrcReg[0].Index = colorTemp;
00246 inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
00247 inst[ic].SrcReg[1].Index = scale_p;
00248 inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
00249 inst[ic].SrcReg[2].Index = bias_p;
00250 ic++;
00251 }
00252
00253 if (key->pixelMaps) {
00254 const GLuint temp = 1;
00255
00256
00257 if (!st->pixel_xfer.pixelmap_texture) {
00258 st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
00259 }
00260
00261
00262
00263
00264
00265
00266 _mesa_init_instructions(inst + ic, 1);
00267 inst[ic].Opcode = OPCODE_TEX;
00268 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00269 inst[ic].DstReg.Index = temp;
00270 inst[ic].DstReg.WriteMask = WRITEMASK_XY;
00271 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00272 inst[ic].SrcReg[0].Index = colorTemp;
00273 inst[ic].TexSrcUnit = 1;
00274 inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
00275 ic++;
00276
00277
00278 _mesa_init_instructions(inst + ic, 1);
00279 inst[ic].Opcode = OPCODE_TEX;
00280 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00281 inst[ic].DstReg.Index = temp;
00282 inst[ic].DstReg.WriteMask = WRITEMASK_ZW;
00283 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00284 inst[ic].SrcReg[0].Index = colorTemp;
00285 inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
00286 SWIZZLE_Z, SWIZZLE_W);
00287 inst[ic].TexSrcUnit = 1;
00288 inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
00289 ic++;
00290
00291
00292 _mesa_init_instructions(inst + ic, 1);
00293 inst[ic].Opcode = OPCODE_MOV;
00294 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00295 inst[ic].DstReg.Index = colorTemp;
00296 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00297 inst[ic].SrcReg[0].Index = temp;
00298 ic++;
00299
00300 fp->Base.SamplersUsed |= (1 << 1);
00301 }
00302
00303 if (key->colorMatrix) {
00304 static const gl_state_index row0_state[STATE_LENGTH] =
00305 { STATE_COLOR_MATRIX, 0, 0, 0, 0 };
00306 static const gl_state_index row1_state[STATE_LENGTH] =
00307 { STATE_COLOR_MATRIX, 0, 1, 1, 0 };
00308 static const gl_state_index row2_state[STATE_LENGTH] =
00309 { STATE_COLOR_MATRIX, 0, 2, 2, 0 };
00310 static const gl_state_index row3_state[STATE_LENGTH] =
00311 { STATE_COLOR_MATRIX, 0, 3, 3, 0 };
00312
00313 GLint row0_p = _mesa_add_state_reference(params, row0_state);
00314 GLint row1_p = _mesa_add_state_reference(params, row1_state);
00315 GLint row2_p = _mesa_add_state_reference(params, row2_state);
00316 GLint row3_p = _mesa_add_state_reference(params, row3_state);
00317 const GLuint temp = 1;
00318
00319
00320 _mesa_init_instructions(inst + ic, 1);
00321 inst[ic].Opcode = OPCODE_DP4;
00322 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00323 inst[ic].DstReg.Index = temp;
00324 inst[ic].DstReg.WriteMask = WRITEMASK_X;
00325 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00326 inst[ic].SrcReg[0].Index = colorTemp;
00327 inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
00328 inst[ic].SrcReg[1].Index = row0_p;
00329 ic++;
00330
00331
00332 _mesa_init_instructions(inst + ic, 1);
00333 inst[ic].Opcode = OPCODE_DP4;
00334 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00335 inst[ic].DstReg.Index = temp;
00336 inst[ic].DstReg.WriteMask = WRITEMASK_Y;
00337 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00338 inst[ic].SrcReg[0].Index = colorTemp;
00339 inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
00340 inst[ic].SrcReg[1].Index = row1_p;
00341 ic++;
00342
00343
00344 _mesa_init_instructions(inst + ic, 1);
00345 inst[ic].Opcode = OPCODE_DP4;
00346 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00347 inst[ic].DstReg.Index = temp;
00348 inst[ic].DstReg.WriteMask = WRITEMASK_Z;
00349 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00350 inst[ic].SrcReg[0].Index = colorTemp;
00351 inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
00352 inst[ic].SrcReg[1].Index = row2_p;
00353 ic++;
00354
00355
00356 _mesa_init_instructions(inst + ic, 1);
00357 inst[ic].Opcode = OPCODE_DP4;
00358 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00359 inst[ic].DstReg.Index = temp;
00360 inst[ic].DstReg.WriteMask = WRITEMASK_W;
00361 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00362 inst[ic].SrcReg[0].Index = colorTemp;
00363 inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
00364 inst[ic].SrcReg[1].Index = row3_p;
00365 ic++;
00366
00367
00368 _mesa_init_instructions(inst + ic, 1);
00369 inst[ic].Opcode = OPCODE_MOV;
00370 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00371 inst[ic].DstReg.Index = colorTemp;
00372 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00373 inst[ic].SrcReg[0].Index = temp;
00374 ic++;
00375 }
00376
00377 if (key->colorMatrixPostScaleBias) {
00378 static const gl_state_index scale_state[STATE_LENGTH] =
00379 { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
00380 static const gl_state_index bias_state[STATE_LENGTH] =
00381 { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
00382 GLint scale_param, bias_param;
00383
00384 scale_param = _mesa_add_state_reference(params, scale_state);
00385 bias_param = _mesa_add_state_reference(params, bias_state);
00386
00387 _mesa_init_instructions(inst + ic, 1);
00388 inst[ic].Opcode = OPCODE_MAD;
00389 inst[ic].DstReg.File = PROGRAM_TEMPORARY;
00390 inst[ic].DstReg.Index = colorTemp;
00391 inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00392 inst[ic].SrcReg[0].Index = colorTemp;
00393 inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
00394 inst[ic].SrcReg[1].Index = scale_param;
00395 inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
00396 inst[ic].SrcReg[2].Index = bias_param;
00397 ic++;
00398 }
00399
00400
00401 {
00402 struct prog_instruction *last = &inst[ic - 1];
00403 last->DstReg.File = PROGRAM_OUTPUT;
00404 last->DstReg.Index = FRAG_RESULT_COLR;
00405 }
00406
00407
00408 _mesa_init_instructions(inst + ic, 1);
00409 inst[ic].Opcode = OPCODE_END;
00410 ic++;
00411
00412 assert(ic <= MAX_INST);
00413
00414
00415 fp->Base.Instructions = _mesa_alloc_instructions(ic);
00416 if (!fp->Base.Instructions) {
00417 _mesa_error(ctx, GL_OUT_OF_MEMORY,
00418 "generating pixel transfer program");
00419 return NULL;
00420 }
00421
00422 _mesa_copy_instructions(fp->Base.Instructions, inst, ic);
00423 fp->Base.NumInstructions = ic;
00424 fp->Base.Parameters = params;
00425
00426 #if 0
00427 printf("========= pixel transfer prog\n");
00428 _mesa_print_program(&fp->Base);
00429 _mesa_print_parameter_list(fp->Base.Parameters);
00430 #endif
00431
00432 return fp;
00433 }
00434
00435
00436
00440 static void
00441 update_pixel_transfer(struct st_context *st)
00442 {
00443 GLcontext *ctx = st->ctx;
00444 struct state_key key;
00445 struct gl_fragment_program *fp;
00446
00447 make_state_key(st->ctx, &key);
00448
00449 fp = (struct gl_fragment_program *)
00450 _mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
00451 if (!fp) {
00452 fp = get_pixel_transfer_program(st->ctx, &key);
00453 _mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
00454 &key, sizeof(key), &fp->Base);
00455 }
00456
00457 if (ctx->Pixel.MapColorFlag) {
00458 load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture);
00459 }
00460 st->pixel_xfer.pixelmap_enabled = ctx->Pixel.MapColorFlag;
00461
00462 st->pixel_xfer.program = (struct st_fragment_program *) fp;
00463 }
00464
00465
00466
00467 const struct st_tracked_state st_update_pixel_transfer = {
00468 "st_update_pixel_transfer",
00469 {
00470 _NEW_PIXEL | _NEW_COLOR_MATRIX,
00471 0,
00472 },
00473 update_pixel_transfer
00474 };