#include "shader/prog_print.h"
#include "st_context.h"
+#include "st_format.h"
#include "st_program.h"
+#include "st_texture.h"
+#include "pipe/p_screen.h"
+#include "pipe/p_context.h"
+#include "pipe/p_inlines.h"
+#include "util/u_pack_color.h"
struct state_key
GLuint scaleAndBias:1;
GLuint colorMatrix:1;
GLuint colorMatrixPostScaleBias:1;
+ GLuint pixelMaps:1;
#if 0
GLfloat Maps[3][256][4];
!TEST_EQ_4V(ctx->Pixel.PostColorMatrixBias, zero)) {
key->colorMatrixPostScaleBias = 1;
}
+
+ key->pixelMaps = ctx->Pixel.MapColorFlag;
+}
+
+
+static struct pipe_texture *
+create_color_map_texture(GLcontext *ctx)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_texture *pt;
+ enum pipe_format format;
+ const uint texSize = 256; /* simple, and usually perfect */
+
+ /* find an RGBA texture format */
+ format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE);
+
+ /* create texture for color map/table */
+ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0,
+ texSize, texSize, 1, 0);
+ return pt;
+}
+
+
+/**
+ * Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
+ */
+static void
+load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)
+{
+ struct pipe_context *pipe = ctx->st->pipe;
+ struct pipe_screen *screen = pipe->screen;
+ struct pipe_surface *surface;
+ const GLuint rSize = ctx->PixelMaps.RtoR.Size;
+ const GLuint gSize = ctx->PixelMaps.GtoG.Size;
+ const GLuint bSize = ctx->PixelMaps.BtoB.Size;
+ const GLuint aSize = ctx->PixelMaps.AtoA.Size;
+ const uint texSize = pt->width[0];
+ uint *dest;
+ uint i, j;
+
+ surface = screen->get_tex_surface(screen, pt, 0, 0, 0);
+ dest = (uint *) pipe_surface_map(surface);
+
+ /* Pack four 1D maps into a 2D texture:
+ * R map is placed horizontally, indexed by S, in channel 0
+ * G map is placed vertically, indexed by T, in channel 1
+ * B map is placed horizontally, indexed by S, in channel 2
+ * A map is placed vertically, indexed by T, in channel 3
+ */
+ for (i = 0; i < texSize; i++) {
+ for (j = 0; j < texSize; j++) {
+ int k = (i * texSize + j);
+ ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize];
+ ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize];
+ ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize];
+ ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize];
+ util_pack_color_ub(r, g, b, a, pt->format, dest + k);
+ }
+ }
+
+ pipe_surface_unmap(surface);
+ pipe_surface_reference(&surface, NULL);
+ pipe->texture_update(pipe, pt, 0, 0x1);
}
static struct gl_fragment_program *
get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
{
+ struct st_context *st = ctx->st;
struct prog_instruction inst[MAX_INST];
struct gl_program_parameter_list *params;
struct gl_fragment_program *fp;
params = _mesa_new_parameter_list();
- /* TEX colorTemp, fragment.texcoord[0], texture[0], 2D; */
+ /*
+ * Get initial pixel color from the texture.
+ * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
+ */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_TEX;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLR);
fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
- /* MAD colorTemp, colorTemp, scale, bias; */
if (key->scaleAndBias) {
static const gl_state_index scale_state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
scale_p = _mesa_add_state_reference(params, scale_state);
bias_p = _mesa_add_state_reference(params, bias_state);
+ /* MAD colorTemp, colorTemp, scale, bias; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_MAD;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
ic++;
}
+ if (key->pixelMaps) {
+ const GLuint temp = 1;
+
+ /* create the colormap/texture now if not already done */
+ if (!st->pixel_xfer.pixelmap_texture) {
+ st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
+ }
+
+ /* with a little effort, we can do four pixel map look-ups with
+ * two TEX instructions:
+ */
+
+ /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].TexSrcUnit = 1;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_TEX;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = temp;
+ inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
+ SWIZZLE_Z, SWIZZLE_W);
+ inst[ic].TexSrcUnit = 1;
+ inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
+ ic++;
+
+ /* MOV colorTemp, temp; */
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MOV;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = temp;
+ ic++;
+
+ fp->Base.SamplersUsed |= (1 << 1); /* sampler 1 is used */
+ }
+
if (key->colorMatrix) {
static const gl_state_index row0_state[STATE_LENGTH] =
{ STATE_COLOR_MATRIX, 0, 0, 0, 0 };
GLint row3_p = _mesa_add_state_reference(params, row3_state);
const GLuint temp = 1;
- /* XXX reimplement in terms of MUL/MAD (see t_vp_build.c) */
-
/* DP4 temp.x, colorTemp, matrow0; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
static void
update_pixel_transfer(struct st_context *st)
{
+ GLcontext *ctx = st->ctx;
struct state_key key;
struct gl_fragment_program *fp;
&key, sizeof(key), &fp->Base);
}
+ if (ctx->Pixel.MapColorFlag) {
+ load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture);
+ }
+ st->pixel_xfer.pixelmap_enabled = ctx->Pixel.MapColorFlag;
+
st->pixel_xfer.program = (struct st_fragment_program *) fp;
}