summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2015-10-04 02:38:55 +0200
committerMarek Olšák <[email protected]>2015-10-09 22:02:18 +0200
commitf15bb3e633d577fe6d8d7bc2c64497c6ac4c2021 (patch)
tree22df135fdeee5a1a504973a5a1fc9473e4de59f9
parentb55b986dc9c89a3a4fb3956dcd269216f59b06ee (diff)
st/mesa: implement DrawPixels shader transformation using tgsi_transform_shader
Reviewed-by: Dave Airlie <[email protected]> Reviewed-by: Brian Paul <[email protected]> Tested-by: Brian Paul <[email protected]>
-rw-r--r--src/mesa/Makefile.sources1
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c225
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c118
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.h9
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels_shader.c255
-rw-r--r--src/mesa/state_tracker/st_context.c6
-rw-r--r--src/mesa/state_tracker/st_context.h7
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp132
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.h3
-rw-r--r--src/mesa/state_tracker/st_program.c51
10 files changed, 303 insertions, 504 deletions
diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 2dabea83075..13208b5e421 100644
--- a/src/mesa/Makefile.sources
+++ b/src/mesa/Makefile.sources
@@ -426,6 +426,7 @@ STATETRACKER_FILES = \
state_tracker/st_cb_condrender.h \
state_tracker/st_cb_drawpixels.c \
state_tracker/st_cb_drawpixels.h \
+ state_tracker/st_cb_drawpixels_shader.c \
state_tracker/st_cb_drawtex.c \
state_tracker/st_cb_drawtex.h \
state_tracker/st_cb_eglimage.c \
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index a04163cc137..f94c358afba 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -25,65 +25,17 @@
*
**************************************************************************/
-/*
- * Generate fragment programs to implement pixel transfer ops, such as
- * scale/bias, colortable, convolution...
- *
- * Authors:
+/* Authors:
* Brian Paul
*/
-#include "main/imports.h"
-#include "main/image.h"
-#include "main/macros.h"
-#include "program/program.h"
-#include "program/prog_cache.h"
-#include "program/prog_instruction.h"
-#include "program/prog_parameter.h"
-#include "program/prog_print.h"
-
#include "st_context.h"
-#include "st_format.h"
#include "st_texture.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "util/u_pack_color.h"
-struct state_key
-{
- GLuint scaleAndBias:1;
- GLuint pixelMaps:1;
-
-#if 0
- GLfloat Maps[3][256][4];
- int NumMaps;
- GLint NumStages;
- pipeline_stage Stages[STAGE_MAX];
- GLboolean StagesUsed[STAGE_MAX];
- GLfloat Scale1[4], Bias1[4];
- GLfloat Scale2[4], Bias2[4];
-#endif
-};
-
-static void
-make_state_key(struct gl_context *ctx, struct state_key *key)
-{
- memset(key, 0, sizeof(*key));
-
- if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
- ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
- ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
- ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
- key->scaleAndBias = 1;
- }
-
- key->pixelMaps = ctx->Pixel.MapColorFlag;
-}
-
-
/**
* Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
*/
@@ -128,74 +80,15 @@ load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt)
pipe_transfer_unmap(pipe, transfer);
}
-
-
-#define MAX_INST 100
-
/**
- * Returns a fragment program which implements the current pixel transfer ops.
+ * Upload the pixel transfer color map texture.
*/
-static struct gl_fragment_program *
-get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key)
+static void
+update_pixel_transfer(struct st_context *st)
{
- struct st_context *st = st_context(ctx);
- struct prog_instruction inst[MAX_INST];
- struct gl_program_parameter_list *params;
- struct gl_fragment_program *fp;
- GLuint ic = 0;
- const GLuint colorTemp = 0;
-
- fp = (struct gl_fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
- if (!fp)
- return NULL;
-
- params = _mesa_new_parameter_list();
-
- /*
- * 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;
- inst[ic].DstReg.Index = colorTemp;
- inst[ic].SrcReg[0].File = PROGRAM_INPUT;
- inst[ic].SrcReg[0].Index = VARYING_SLOT_TEX0;
- inst[ic].TexSrcUnit = 0;
- inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
- ic++;
- fp->Base.InputsRead = BITFIELD64_BIT(VARYING_SLOT_TEX0);
- fp->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR);
- fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
-
- if (key->scaleAndBias) {
- 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_p, bias_p;
-
- 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;
- 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_p;
- inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
- inst[ic].SrcReg[2].Index = bias_p;
- ic++;
- }
-
- if (key->pixelMaps) {
- const GLuint temp = 1;
+ struct gl_context *ctx = st->ctx;
+ if (ctx->Pixel.MapColorFlag) {
/* create the colormap/texture now if not already done */
if (!st->pixel_xfer.pixelmap_texture) {
st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx);
@@ -203,117 +96,11 @@ get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key)
st_create_texture_sampler_view(st->pipe,
st->pixel_xfer.pixelmap_texture);
}
-
- /* 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 */
- }
-
- /* Modify last instruction's dst reg to write to result.color */
- {
- struct prog_instruction *last = &inst[ic - 1];
- last->DstReg.File = PROGRAM_OUTPUT;
- last->DstReg.Index = FRAG_RESULT_COLOR;
- }
-
- /* END; */
- _mesa_init_instructions(inst + ic, 1);
- inst[ic].Opcode = OPCODE_END;
- ic++;
-
- assert(ic <= MAX_INST);
-
-
- fp->Base.Instructions = _mesa_alloc_instructions(ic);
- if (!fp->Base.Instructions) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY,
- "generating pixel transfer program");
- _mesa_free_parameter_list(params);
- return NULL;
- }
-
- _mesa_copy_instructions(fp->Base.Instructions, inst, ic);
- fp->Base.NumInstructions = ic;
- fp->Base.Parameters = params;
-
-#if 0
- printf("========= pixel transfer prog\n");
- _mesa_print_program(&fp->Base);
- _mesa_print_parameter_list(fp->Base.Parameters);
-#endif
-
- return fp;
-}
-
-
-
-/**
- * Update st->pixel_xfer.program in response to new pixel-transfer state.
- */
-static void
-update_pixel_transfer(struct st_context *st)
-{
- struct gl_context *ctx = st->ctx;
- struct state_key key;
- struct gl_fragment_program *fp;
-
- make_state_key(st->ctx, &key);
-
- fp = (struct gl_fragment_program *)
- _mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
- if (!fp) {
- fp = get_pixel_transfer_program(st->ctx, &key);
- _mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
- &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;
}
-
const struct st_tracked_state st_update_pixel_transfer = {
"st_update_pixel_transfer", /* name */
{ /* dirty */
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index f77d3049ae6..34163ede4a2 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -72,119 +72,6 @@
/**
- * Check if the given program is:
- * 0: MOVE result.color, fragment.color;
- * 1: END;
- */
-static GLboolean
-is_passthrough_program(const struct gl_fragment_program *prog)
-{
- if (prog->Base.NumInstructions == 2) {
- const struct prog_instruction *inst = prog->Base.Instructions;
- if (inst[0].Opcode == OPCODE_MOV &&
- inst[1].Opcode == OPCODE_END &&
- inst[0].DstReg.File == PROGRAM_OUTPUT &&
- inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
- inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
- inst[0].SrcReg[0].File == PROGRAM_INPUT &&
- inst[0].SrcReg[0].Index == VARYING_SLOT_COL0 &&
- inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
- return GL_TRUE;
- }
- }
- return GL_FALSE;
-}
-
-
-/**
- * Returns a fragment program which implements the current pixel transfer ops.
- */
-static struct gl_fragment_program *
-get_glsl_pixel_transfer_program(struct st_context *st,
- struct st_fragment_program *orig)
-{
- int pixelMaps = 0, scaleAndBias = 0;
- struct gl_context *ctx = st->ctx;
- struct st_fragment_program *fp = (struct st_fragment_program *)
- ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
-
- if (!fp)
- return NULL;
-
- if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
- ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
- ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
- ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
- scaleAndBias = 1;
- }
-
- pixelMaps = ctx->Pixel.MapColorFlag;
-
- if (pixelMaps) {
- /* create the colormap/texture now if not already done */
- if (!st->pixel_xfer.pixelmap_texture) {
- st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx);
- st->pixel_xfer.pixelmap_sampler_view =
- st_create_texture_sampler_view(st->pipe,
- st->pixel_xfer.pixelmap_texture);
- }
- }
-
- get_pixel_transfer_visitor(fp, orig->glsl_to_tgsi,
- scaleAndBias, pixelMaps);
-
- return &fp->Base;
-}
-
-
-/**
- * Make fragment shader for glDraw/CopyPixels. This shader is made
- * by combining the pixel transfer shader with the user-defined shader.
- * \param fpIn the current/incoming fragment program
- * \param fpOut returns the combined fragment program
- */
-void
-st_make_drawpix_fragment_program(struct st_context *st,
- struct gl_fragment_program *fpIn,
- struct gl_fragment_program **fpOut)
-{
- struct gl_program *newProg;
- struct st_fragment_program *stfp = (struct st_fragment_program *) fpIn;
-
- if (is_passthrough_program(fpIn)) {
- newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx,
- &st->pixel_xfer.program->Base);
- }
- else if (stfp->glsl_to_tgsi != NULL) {
- newProg = (struct gl_program *) get_glsl_pixel_transfer_program(st, stfp);
- }
- else {
-#if 0
- /* debug */
- printf("Base program:\n");
- _mesa_print_program(&fpIn->Base);
- printf("DrawPix program:\n");
- _mesa_print_program(&st->pixel_xfer.program->Base.Base);
-#endif
- newProg = _mesa_combine_programs(st->ctx,
- &st->pixel_xfer.program->Base.Base,
- &fpIn->Base);
- }
-
-#if 0
- /* debug */
- printf("Combined DrawPixels program:\n");
- _mesa_print_program(newProg);
- printf("InputsRead: 0x%x\n", newProg->InputsRead);
- printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
- _mesa_print_parameter_list(newProg->Parameters);
-#endif
-
- *fpOut = (struct gl_fragment_program *) newProg;
-}
-
-
-/**
* Create fragment program that does a TEX() instruction to get a Z and/or
* stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
* Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
@@ -1101,7 +988,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
color = NULL;
- if (st->pixel_xfer.pixelmap_enabled) {
+ if (ctx->Pixel.MapColorFlag) {
pipe_sampler_view_reference(&sv[1],
st->pixel_xfer.pixelmap_sampler_view);
num_sampler_view++;
@@ -1439,7 +1326,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
driver_fp = fpv->driver_shader;
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
- if (st->pixel_xfer.pixelmap_enabled) {
+ if (ctx->Pixel.MapColorFlag) {
pipe_sampler_view_reference(&sv[1],
st->pixel_xfer.pixelmap_sampler_view);
num_sampler_view++;
@@ -1610,7 +1497,6 @@ st_destroy_drawpix(struct st_context *st)
st->drawpix.zs_shaders[i]);
}
- st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
if (st->drawpix.vert_shaders[0])
cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[0]);
if (st->drawpix.vert_shaders[1])
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h
index c6649cbd51c..b8a34952141 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.h
+++ b/src/mesa/state_tracker/st_cb_drawpixels.h
@@ -31,6 +31,7 @@
#include "main/compiler.h"
+#include <stdbool.h>
struct dd_function_table;
struct st_context;
@@ -40,9 +41,9 @@ extern void st_init_drawpixels_functions(struct dd_function_table *functions);
extern void
st_destroy_drawpix(struct st_context *st);
-extern void
-st_make_drawpix_fragment_program(struct st_context *st,
- struct gl_fragment_program *fpIn,
- struct gl_fragment_program **fpOut);
+extern const struct tgsi_token *
+st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
+ bool scale_and_bias, unsigned scale_const,
+ unsigned bias_const, bool pixel_maps);
#endif /* ST_CB_DRAWPIXELS_H */
diff --git a/src/mesa/state_tracker/st_cb_drawpixels_shader.c b/src/mesa/state_tracker/st_cb_drawpixels_shader.c
new file mode 100644
index 00000000000..01db0b6d73e
--- /dev/null
+++ b/src/mesa/state_tracker/st_cb_drawpixels_shader.c
@@ -0,0 +1,255 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2015 Advanced Micro Devices, Inc.
+ * Copyright 2007 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "st_cb_drawpixels.h"
+#include "tgsi/tgsi_transform.h"
+#include "tgsi/tgsi_scan.h"
+
+struct tgsi_drawpix_transform {
+ struct tgsi_transform_context base;
+ struct tgsi_shader_info info;
+ bool use_texcoord;
+ bool scale_and_bias;
+ bool pixel_maps;
+ bool first_instruction_emitted;
+ unsigned scale_const;
+ unsigned bias_const;
+ unsigned color_temp;
+};
+
+static inline struct tgsi_drawpix_transform *
+tgsi_drawpix_transform(struct tgsi_transform_context *tctx)
+{
+ return (struct tgsi_drawpix_transform *)tctx;
+}
+
+static void
+set_src(struct tgsi_full_instruction *inst, unsigned i, unsigned file, unsigned index,
+ unsigned x, unsigned y, unsigned z, unsigned w)
+{
+ inst->Src[i].Register.File = file;
+ inst->Src[i].Register.Index = index;
+ inst->Src[i].Register.SwizzleX = x;
+ inst->Src[i].Register.SwizzleY = y;
+ inst->Src[i].Register.SwizzleZ = z;
+ inst->Src[i].Register.SwizzleW = w;
+}
+
+#define SET_SRC(inst, i, file, index, x, y, z, w) \
+ set_src(inst, i, file, index, TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, \
+ TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w)
+
+static void
+transform_instr(struct tgsi_transform_context *tctx,
+ struct tgsi_full_instruction *current_inst)
+{
+ struct tgsi_drawpix_transform *ctx = tgsi_drawpix_transform(tctx);
+ struct tgsi_full_declaration decl;
+ struct tgsi_full_instruction inst;
+ unsigned i, semantic;
+ int texcoord_index = -1;
+
+ if (ctx->first_instruction_emitted)
+ goto transform_inst;
+
+ ctx->first_instruction_emitted = true;
+
+ /* Add scale and bias constants. */
+ if (ctx->scale_and_bias) {
+ if (ctx->info.const_file_max[0] < (int)ctx->scale_const) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_CONSTANT;
+ decl.Range.First = decl.Range.Last = ctx->scale_const;
+ tctx->emit_declaration(tctx, &decl);
+ }
+
+ if (ctx->info.const_file_max[0] < (int)ctx->bias_const) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_CONSTANT;
+ decl.Range.First = decl.Range.Last = ctx->bias_const;
+ tctx->emit_declaration(tctx, &decl);
+ }
+ }
+
+ /* Add a new temp. */
+ ctx->color_temp = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_TEMPORARY;
+ decl.Range.First = decl.Range.Last = ctx->color_temp;
+ tctx->emit_declaration(tctx, &decl);
+
+ /* Add TEXCOORD[0] if it's missing. */
+ semantic = ctx->use_texcoord ? TGSI_SEMANTIC_TEXCOORD :
+ TGSI_SEMANTIC_GENERIC;
+ for (i = 0; i < ctx->info.num_inputs; i++) {
+ if (ctx->info.input_semantic_name[i] == semantic &&
+ ctx->info.input_semantic_index[i] == 0) {
+ texcoord_index = i;
+ break;
+ }
+ }
+
+ if (texcoord_index == -1) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_INPUT;
+ decl.Declaration.Semantic = 1;
+ decl.Semantic.Name = semantic;
+ decl.Declaration.Interpolate = 1;
+ decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
+ decl.Range.First = decl.Range.Last = ctx->info.num_inputs;
+ texcoord_index = ctx->info.num_inputs;
+ tctx->emit_declaration(tctx, &decl);
+ }
+
+ /* Declare the drawpix sampler if it's missing. */
+ if (ctx->info.file_max[TGSI_FILE_SAMPLER] == -1) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ tctx->emit_declaration(tctx, &decl);
+ }
+
+ /* Declare the pixel map sampler if it's missing. */
+ if (ctx->info.file_max[TGSI_FILE_SAMPLER] <= 0) {
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.Range.First = decl.Range.Last = 1;
+ tctx->emit_declaration(tctx, &decl);
+ }
+
+ /* Get initial pixel color from the texture.
+ * TEX temp, fragment.texcoord[0], texture[0], 2D;
+ */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ inst.Instruction.Texture = 1;
+ inst.Texture.Texture = TGSI_TEXTURE_2D;
+
+ inst.Instruction.NumDstRegs = 1;
+ inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
+ inst.Dst[0].Register.Index = ctx->color_temp;
+ inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
+
+ inst.Instruction.NumSrcRegs = 2;
+ SET_SRC(&inst, 0, TGSI_FILE_INPUT, texcoord_index, X, Y, Z, W);
+ inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
+ inst.Src[1].Register.Index = 0;
+
+ tctx->emit_instruction(tctx, &inst);
+
+ /* Apply the scale and bias. */
+ if (ctx->scale_and_bias) {
+ /* MAD temp, temp, scale, bias; */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_MAD;
+
+ inst.Instruction.NumDstRegs = 1;
+ inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
+ inst.Dst[0].Register.Index = ctx->color_temp;
+ inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW;
+
+ inst.Instruction.NumSrcRegs = 3;
+ SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, X, Y, Z, W);
+ SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, ctx->scale_const, X, Y, Z, W);
+ SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, ctx->bias_const, X, Y, Z, W);
+
+ tctx->emit_instruction(tctx, &inst);
+ }
+
+ if (ctx->pixel_maps) {
+ /* do four pixel map look-ups with two TEX instructions: */
+
+ /* TEX temp.xy, temp.xyyy, texture[1], 2D; */
+ inst = tgsi_default_full_instruction();
+ inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+ inst.Instruction.Texture = 1;
+ inst.Texture.Texture = TGSI_TEXTURE_2D;
+
+ inst.Instruction.NumDstRegs = 1;
+ inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
+ inst.Dst[0].Register.Index = ctx->color_temp;
+ inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XY;
+
+ inst.Instruction.NumSrcRegs = 2;
+ SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, X, Y, Y, Y);
+ inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
+ inst.Src[1].Register.Index = 1;
+
+ tctx->emit_instruction(tctx, &inst);
+
+ /* TEX temp.zw, temp.zwww, texture[1], 2D; */
+ inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_ZW;
+ SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, Z, W, W, W);
+ tctx->emit_instruction(tctx, &inst);
+ }
+
+ /* Now, "color_temp" should be used in place of IN:COLOR0 */
+
+transform_inst:
+
+ for (i = 0; i < current_inst->Instruction.NumSrcRegs; i++) {
+ struct tgsi_full_src_register *src = &current_inst->Src[i];
+ unsigned reg = src->Register.Index;
+
+ if (src->Register.File == TGSI_FILE_INPUT &&
+ !src->Register.Indirect &&
+ ctx->info.input_semantic_name[reg] == TGSI_SEMANTIC_COLOR &&
+ ctx->info.input_semantic_index[reg] == 0) {
+ src->Register.File = TGSI_FILE_TEMPORARY;
+ src->Register.Index = ctx->color_temp;
+ }
+ }
+
+ tctx->emit_instruction(tctx, current_inst);
+}
+
+const struct tgsi_token *
+st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
+ bool scale_and_bias, unsigned scale_const,
+ unsigned bias_const, bool pixel_maps)
+{
+ struct tgsi_drawpix_transform ctx;
+ struct tgsi_token *newtoks;
+ int newlen;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.base.transform_instruction = transform_instr;
+ ctx.use_texcoord = use_texcoord;
+ ctx.scale_and_bias = scale_and_bias;
+ ctx.scale_const = scale_const;
+ ctx.bias_const = bias_const;
+ ctx.pixel_maps = pixel_maps;
+ tgsi_scan_shader(tokens, &ctx.info);
+
+ newlen = tgsi_num_tokens(tokens) + 30;
+ newtoks = tgsi_alloc_tokens(newlen);
+ if (!newtoks)
+ return NULL;
+
+ tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base);
+ return newtoks;
+}
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index a9ab5edcf49..bef7307bb27 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -224,8 +224,6 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
- st->pixel_xfer.cache = _mesa_new_program_cache();
-
st->has_stencil_export =
screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3);
@@ -386,8 +384,8 @@ void st_destroy_context( struct st_context *st )
pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
}
pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
-
- _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
+ pipe_sampler_view_reference(&st->pixel_xfer.pixelmap_sampler_view, NULL);
+ pipe_resource_reference(&st->pixel_xfer.pixelmap_texture, NULL);
_vbo_DestroyContext(st->ctx);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 262581eceeb..f187d82449b 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -162,15 +162,8 @@ struct st_context
struct gl_texture_object *default_texture;
struct {
- struct gl_program_cache *cache;
- struct st_fragment_program *program; /**< cur pixel transfer prog */
- GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
- GLuint user_prog_sn; /**< user fragment program serial no. */
- struct st_fragment_program *combined_prog;
- GLuint combined_prog_sn;
struct pipe_resource *pixelmap_texture;
struct pipe_sampler_view *pixelmap_sampler_view;
- boolean pixelmap_enabled; /**< use the pixelmap texture? */
} pixel_xfer;
/** for glBitmap */
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index a54ee17173a..cdd80f167d0 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -4334,138 +4334,6 @@ glsl_to_tgsi_visitor::renumber_registers(void)
ralloc_free(first_reads);
}
-/**
- * Returns a fragment program which implements the current pixel transfer ops.
- * Based on get_pixel_transfer_program in st_atom_pixeltransfer.c.
- */
-extern "C" void
-get_pixel_transfer_visitor(struct st_fragment_program *fp,
- glsl_to_tgsi_visitor *original,
- int scale_and_bias, int pixel_maps)
-{
- glsl_to_tgsi_visitor *v = new glsl_to_tgsi_visitor();
- struct st_context *st = st_context(original->ctx);
- struct gl_program *prog = &fp->Base.Base;
- struct gl_program_parameter_list *params = _mesa_new_parameter_list();
- st_src_reg coord, src0;
- st_dst_reg dst0;
- glsl_to_tgsi_instruction *inst;
-
- /* Copy attributes of the glsl_to_tgsi_visitor in the original shader. */
- v->ctx = original->ctx;
- v->prog = prog;
- v->shader_program = NULL;
- v->shader = NULL;
- v->glsl_version = original->glsl_version;
- v->native_integers = original->native_integers;
- v->options = original->options;
- v->next_temp = original->next_temp;
- v->num_address_regs = original->num_address_regs;
- v->samplers_used = prog->SamplersUsed = original->samplers_used;
- v->indirect_addr_consts = original->indirect_addr_consts;
- memcpy(&v->immediates, &original->immediates, sizeof(v->immediates));
- v->num_immediates = original->num_immediates;
-
- /*
- * Get initial pixel color from the texture.
- * TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
- */
- coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type);
- src0 = v->get_temp(glsl_type::vec4_type);
- dst0 = st_dst_reg(src0);
- inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, dst0, coord);
- inst->sampler_array_size = 1;
- inst->tex_target = TEXTURE_2D_INDEX;
-
- prog->InputsRead |= VARYING_BIT_TEX0;
- prog->SamplersUsed |= (1 << 0); /* mark sampler 0 as used */
- v->samplers_used |= (1 << 0);
-
- if (scale_and_bias) {
- static const gl_state_index scale_state[STATE_LENGTH] =
- { STATE_INTERNAL, STATE_PT_SCALE,
- (gl_state_index) 0, (gl_state_index) 0, (gl_state_index) 0 };
- static const gl_state_index bias_state[STATE_LENGTH] =
- { STATE_INTERNAL, STATE_PT_BIAS,
- (gl_state_index) 0, (gl_state_index) 0, (gl_state_index) 0 };
- GLint scale_p, bias_p;
- st_src_reg scale, bias;
-
- scale_p = _mesa_add_state_reference(params, scale_state);
- bias_p = _mesa_add_state_reference(params, bias_state);
-
- /* MAD colorTemp, colorTemp, scale, bias; */
- scale = st_src_reg(PROGRAM_STATE_VAR, scale_p, GLSL_TYPE_FLOAT);
- bias = st_src_reg(PROGRAM_STATE_VAR, bias_p, GLSL_TYPE_FLOAT);
- inst = v->emit_asm(NULL, TGSI_OPCODE_MAD, dst0, src0, scale, bias);
- }
-
- if (pixel_maps) {
- st_src_reg temp = v->get_temp(glsl_type::vec4_type);
- st_dst_reg temp_dst = st_dst_reg(temp);
-
- assert(st->pixel_xfer.pixelmap_texture);
- (void) st;
-
- /* With a little effort, we can do four pixel map look-ups with
- * two TEX instructions:
- */
-
- /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
- temp_dst.writemask = WRITEMASK_XY; /* write R,G */
- inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, temp_dst, src0);
- inst->sampler.index = 1;
- inst->sampler_array_size = 1;
- inst->tex_target = TEXTURE_2D_INDEX;
-
- /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
- src0.swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W);
- temp_dst.writemask = WRITEMASK_ZW; /* write B,A */
- inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, temp_dst, src0);
- inst->sampler.index = 1;
- inst->sampler_array_size = 1;
- inst->tex_target = TEXTURE_2D_INDEX;
-
- prog->SamplersUsed |= (1 << 1); /* mark sampler 1 as used */
- v->samplers_used |= (1 << 1);
-
- /* MOV colorTemp, temp; */
- inst = v->emit_asm(NULL, TGSI_OPCODE_MOV, dst0, temp);
- }
-
- /* Now copy the instructions from the original glsl_to_tgsi_visitor into the
- * new visitor. */
- foreach_in_list(glsl_to_tgsi_instruction, inst, &original->instructions) {
- glsl_to_tgsi_instruction *newinst;
- st_src_reg src_regs[4];
-
- if (inst->dst[0].file == PROGRAM_OUTPUT)
- prog->OutputsWritten |= BITFIELD64_BIT(inst->dst[0].index);
-
- for (int i = 0; i < 4; i++) {
- src_regs[i] = inst->src[i];
- if (src_regs[i].file == PROGRAM_INPUT &&
- src_regs[i].index == VARYING_SLOT_COL0) {
- src_regs[i].file = PROGRAM_TEMPORARY;
- src_regs[i].index = src0.index;
- }
- else if (src_regs[i].file == PROGRAM_INPUT)
- prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index);
- }
-
- newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2], src_regs[3]);
- newinst->tex_target = inst->tex_target;
- newinst->sampler_array_size = inst->sampler_array_size;
- }
-
- /* Make modifications to fragment program info. */
- prog->Parameters = _mesa_combine_parameter_lists(params,
- original->prog->Parameters);
- _mesa_free_parameter_list(params);
- count_resources(v, prog);
- fp->glsl_to_tgsi = v;
-}
-
/* ------------------------- TGSI conversion stuff -------------------------- */
struct label {
unsigned branch_target;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.h b/src/mesa/state_tracker/st_glsl_to_tgsi.h
index dcdfbebcbdc..729295bcb52 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.h
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.h
@@ -55,9 +55,6 @@ enum pipe_error st_translate_program(
const ubyte outputSemanticIndex[]);
void free_glsl_to_tgsi_visitor(struct glsl_to_tgsi_visitor *v);
-void get_pixel_transfer_visitor(struct st_fragment_program *fp,
- struct glsl_to_tgsi_visitor *original,
- int scale_and_bias, int pixel_maps);
GLboolean st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index d900ede7265..01e33d04f74 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -540,8 +540,6 @@ st_translate_fragment_program(struct st_context *st,
{
struct pipe_context *pipe = st->pipe;
struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
- GLboolean deleteFP = GL_FALSE;
-
GLuint outputMapping[FRAG_RESULT_MAX];
GLuint inputMapping[VARYING_SLOT_MAX];
GLuint inputSlotToAttr[VARYING_SLOT_MAX];
@@ -567,16 +565,6 @@ st_translate_fragment_program(struct st_context *st,
assert(!(key->bitmap && key->drawpixels));
memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr));
- if (key->drawpixels) {
- /* glDrawPixels color drawing */
- struct gl_fragment_program *fp; /* we free this temp program below */
-
- st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
- variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
- deleteFP = GL_TRUE;
- stfp = st_fragment_program(fp);
- }
-
if (!stfp->glsl_to_tgsi)
_mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
@@ -895,6 +883,38 @@ st_translate_fragment_program(struct st_context *st,
fprintf(stderr, "mesa: cannot create a shader for glBitmap\n");
}
+ /* glDrawPixels (color only) */
+ if (key->drawpixels) {
+ const struct tgsi_token *tokens;
+ unsigned scale_const = 0, bias_const = 0;
+
+ variant->parameters =
+ _mesa_clone_parameter_list(stfp->Base.Base.Parameters);
+
+ if (key->scaleAndBias) {
+ static const gl_state_index scale_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_SCALE };
+ static const gl_state_index bias_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_PT_BIAS };
+
+ scale_const = _mesa_add_state_reference(variant->parameters,
+ scale_state);
+ bias_const = _mesa_add_state_reference(variant->parameters,
+ bias_state);
+ }
+
+ tokens = st_get_drawpix_shader(variant->tgsi.tokens,
+ st->needs_texcoord_semantic,
+ key->scaleAndBias, scale_const,
+ bias_const, key->pixelMaps);
+
+ if (tokens) {
+ tgsi_free_tokens(variant->tgsi.tokens);
+ variant->tgsi.tokens = tokens;
+ } else
+ fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n");
+ }
+
if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/);
debug_printf("\n");
@@ -903,13 +923,6 @@ st_translate_fragment_program(struct st_context *st,
/* fill in variant */
variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi);
variant->key = *key;
-
- if (deleteFP) {
- /* Free the temporary program made above */
- struct gl_fragment_program *fp = &stfp->Base;
- _mesa_reference_fragprog(st->ctx, &fp, NULL);
- }
-
return variant;
}