[Mesa-dev] [PATCH 11/17] st/mesa: implement DrawPixels shader transformation using tgsi_transform_shader

Marek Olšák maraeo at gmail.com
Mon Oct 5 18:26:24 PDT 2015


From: Marek Olšák <marek.olsak at amd.com>

---
 src/mesa/Makefile.sources                        |   1 +
 src/mesa/state_tracker/st_atom_pixeltransfer.c   | 225 +-------------------
 src/mesa/state_tracker/st_cb_drawpixels.c        | 118 +----------
 src/mesa/state_tracker/st_cb_drawpixels.h        |   9 +-
 src/mesa/state_tracker/st_cb_drawpixels_shader.c | 255 +++++++++++++++++++++++
 src/mesa/state_tracker/st_context.c              |   6 +-
 src/mesa/state_tracker/st_context.h              |   7 -
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp       | 132 ------------
 src/mesa/state_tracker/st_glsl_to_tgsi.h         |   3 -
 src/mesa/state_tracker/st_program.c              |  51 +++--
 10 files changed, 303 insertions(+), 504 deletions(-)
 create mode 100644 src/mesa/state_tracker/st_cb_drawpixels_shader.c

diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources
index 8eb43ce..36a0d33 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 a04163c..f94c358 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 0ef0e69..a08c0b2 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).
@@ -1111,7 +998,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++;
@@ -1449,7 +1336,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++;
@@ -1620,7 +1507,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 c6649cb..b8a3495 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 0000000..01db0b6
--- /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 a9ab5ed..bef7307 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 262581e..f187d82 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 a54ee17..cdd80f1 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 dcdfbeb..729295b 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 d900ede..01e33d0 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;
 }
 
-- 
2.1.4



More information about the mesa-dev mailing list