st_atom_pixeltransfer.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 /*
00029  * Generate fragment programs to implement pixel transfer ops, such as
00030  * scale/bias, colormatrix, colortable, convolution...
00031  *
00032  * Authors:
00033  *   Brian Paul
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; /* simple, and usually perfect */
00123 
00124    /* find an RGBA texture format */
00125    format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER);
00126 
00127    /* create texture for color map/table */
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    /* Pack four 1D maps into a 2D texture:
00158     * R map is placed horizontally, indexed by S, in channel 0
00159     * G map is placed vertically, indexed by T, in channel 1
00160     * B map is placed horizontally, indexed by S, in channel 2
00161     * A map is placed vertically, indexed by T, in channel 3
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     * Get initial pixel color from the texture.
00204     * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
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;  /* sampler 0 (bit 0) is used */
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       /* MAD colorTemp, colorTemp, scale, bias; */
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       /* create the colormap/texture now if not already done */
00257       if (!st->pixel_xfer.pixelmap_texture) {
00258          st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
00259       }
00260 
00261       /* with a little effort, we can do four pixel map look-ups with
00262        * two TEX instructions:
00263        */
00264 
00265       /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
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; /* write R,G */
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       /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
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; /* write B,A */
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       /* MOV colorTemp, temp; */
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);  /* sampler 1 is used */
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       /* DP4 temp.x, colorTemp, matrow0; */
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       /* DP4 temp.y, colorTemp, matrow1; */
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       /* DP4 temp.z, colorTemp, matrow2; */
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       /* DP4 temp.w, colorTemp, matrow3; */
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       /* MOV colorTemp, temp; */
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    /* Modify last instruction's dst reg to write to result.color */
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    /* END; */
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",                          /* name */
00469    {                                                    /* dirty */
00470       _NEW_PIXEL | _NEW_COLOR_MATRIX,                   /* mesa */
00471       0,                                                /* st */
00472    },
00473    update_pixel_transfer                                /* update */
00474 };

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4