summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker/st_atom_pixeltransfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker/st_atom_pixeltransfer.c')
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c209
1 files changed, 184 insertions, 25 deletions
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index 6410e7cb24..76356bbad7 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -42,14 +42,22 @@
#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];
@@ -80,6 +88,9 @@ is_identity(const GLfloat m[16])
static void
make_state_key(GLcontext *ctx, struct state_key *key)
{
+ static const GLfloat zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ static const GLfloat one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
memset(key, 0, sizeof(*key));
if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
@@ -92,9 +103,76 @@ make_state_key(GLcontext *ctx, struct state_key *key)
if (!is_identity(ctx->ColorMatrixStack.Top->m)) {
key->colorMatrix = 1;
}
+
+ if (!TEST_EQ_4V(ctx->Pixel.PostColorMatrixScale, one) ||
+ !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);
+}
+
#define MAX_INST 100
@@ -105,6 +183,7 @@ make_state_key(GLcontext *ctx, struct state_key *key)
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;
@@ -118,7 +197,10 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
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;
@@ -132,7 +214,6 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
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 };
@@ -153,6 +234,7 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
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;
@@ -166,6 +248,56 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
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 };
@@ -182,64 +314,85 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
GLint row3_p = _mesa_add_state_reference(params, row3_state);
const GLuint temp = 1;
- /* MOV temp, colorTemp; */
- _mesa_init_instructions(inst + ic, 1);
- inst[ic].Opcode = OPCODE_MOV;
- inst[ic].DstReg.File = PROGRAM_TEMPORARY;
- inst[ic].DstReg.Index = temp;
- inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- inst[ic].SrcReg[0].Index = colorTemp;
- ic++;
-
- /* XXX reimplement in terms of MUL/MAD (see t_vp_build.c) */
-
- /* DP4 colorTemp.x, temp, matrow0; */
+ /* DP4 temp.x, colorTemp, matrow0; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
- inst[ic].DstReg.Index = colorTemp;
+ inst[ic].DstReg.Index = temp;
inst[ic].DstReg.WriteMask = WRITEMASK_X;
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- inst[ic].SrcReg[0].Index = temp;
+ inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
inst[ic].SrcReg[1].Index = row0_p;
ic++;
- /* DP4 colorTemp.y, temp, matrow1; */
+ /* DP4 temp.y, colorTemp, matrow1; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
- inst[ic].DstReg.Index = colorTemp;
+ inst[ic].DstReg.Index = temp;
inst[ic].DstReg.WriteMask = WRITEMASK_Y;
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- inst[ic].SrcReg[0].Index = temp;
+ inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
inst[ic].SrcReg[1].Index = row1_p;
ic++;
- /* DP4 colorTemp.z, temp, matrow2; */
+ /* DP4 temp.z, colorTemp, matrow2; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
- inst[ic].DstReg.Index = colorTemp;
+ inst[ic].DstReg.Index = temp;
inst[ic].DstReg.WriteMask = WRITEMASK_Z;
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- inst[ic].SrcReg[0].Index = temp;
+ inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
inst[ic].SrcReg[1].Index = row2_p;
ic++;
- /* DP4 colorTemp.w, temp, matrow3; */
+ /* DP4 temp.w, colorTemp, matrow3; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
- inst[ic].DstReg.Index =colorTemp;
+ inst[ic].DstReg.Index = temp;
inst[ic].DstReg.WriteMask = WRITEMASK_W;
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
- inst[ic].SrcReg[0].Index = temp;
+ inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
inst[ic].SrcReg[1].Index = row3_p;
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++;
+ }
+
+ if (key->colorMatrixPostScaleBias) {
+ static const gl_state_index scale_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
+ static const gl_state_index bias_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
+ GLint scale_param, bias_param;
+
+ scale_param = _mesa_add_state_reference(params, scale_state);
+ bias_param = _mesa_add_state_reference(params, bias_state);
+
+ _mesa_init_instructions(inst + ic, 1);
+ inst[ic].Opcode = OPCODE_MAD;
+ inst[ic].DstReg.File = PROGRAM_TEMPORARY;
+ inst[ic].DstReg.Index = colorTemp;
+ inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst[ic].SrcReg[0].Index = colorTemp;
+ inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[1].Index = scale_param;
+ inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
+ inst[ic].SrcReg[2].Index = bias_param;
+ ic++;
}
/* Modify last instruction's dst reg to write to result.color */
@@ -285,6 +438,7 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
static void
update_pixel_transfer(struct st_context *st)
{
+ GLcontext *ctx = st->ctx;
struct state_key key;
struct gl_fragment_program *fp;
@@ -298,6 +452,11 @@ update_pixel_transfer(struct st_context *st)
&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;
}