[Mesa-dev] [PATCH 12/17] st/mesa: fix glDrawPixels with a texture

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


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

The samplers for DrawPixels data and the pixel map are assigned to slots
which don't overlap with the existing sampler slots.

The texture coordinates for the user texture are uploaded as a constant.
---
 src/mesa/state_tracker/st_cb_drawpixels.c        | 52 +++++++++++++++++-----
 src/mesa/state_tracker/st_cb_drawpixels.h        |  4 +-
 src/mesa/state_tracker/st_cb_drawpixels_shader.c | 55 +++++++++++++++++-------
 src/mesa/state_tracker/st_program.c              | 25 ++++++++++-
 src/mesa/state_tracker/st_program.h              |  4 ++
 5 files changed, 111 insertions(+), 29 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index a08c0b2..cc2c885 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -535,6 +535,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                    int num_sampler_view,
                    void *driver_vp,
                    void *driver_fp,
+                   struct st_fp_variant *fpv,
                    const GLfloat *color,
                    GLboolean invertTex,
                    GLboolean write_depth, GLboolean write_stencil)
@@ -622,10 +623,9 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_set_tesseval_shader_handle(cso, NULL);
    cso_set_geometry_shader_handle(cso, NULL);
 
-   /* texture sampling state: */
+   /* user samplers, plus the drawpix samplers */
    {
       struct pipe_sampler_state sampler;
-      const struct pipe_sampler_state *states[2] = {&sampler, &sampler};
 
       memset(&sampler, 0, sizeof(sampler));
       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
@@ -636,8 +636,25 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
       sampler.normalized_coords = normalized;
 
-      cso_set_samplers(cso, PIPE_SHADER_FRAGMENT,
-                       num_sampler_view > 1 ? 2 : 1, states);
+      if (fpv) {
+         const struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+         uint num = MAX2(MAX2(fpv->drawpix_sampler, fpv->pixelmap_sampler) + 1,
+                         st->state.num_samplers[PIPE_SHADER_FRAGMENT]);
+         uint i;
+
+         for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++)
+            samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i];
+
+         samplers[fpv->drawpix_sampler] = &sampler;
+         if (sv[1])
+            samplers[fpv->pixelmap_sampler] = &sampler;
+
+         cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, samplers);
+      } else {
+         const struct pipe_sampler_state *samplers[2] = {&sampler, &sampler};
+
+         cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, samplers);
+      }
    }
 
    /* viewport state: viewport matching window dims */
@@ -657,8 +674,21 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_set_vertex_elements(cso, 3, st->velems_util_draw);
    cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 
-   /* texture state: */
-   cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
+   /* user textures, plus the drawpix textures */
+   if (fpv) {
+      struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
+      uint num = MAX2(MAX2(fpv->drawpix_sampler, fpv->pixelmap_sampler) + 1,
+                      st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
+
+      memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT],
+             sizeof(sampler_views));
+
+      sampler_views[fpv->drawpix_sampler] = sv[0];
+      if (sv[1])
+         sampler_views[fpv->pixelmap_sampler] = sv[1];
+      cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num, sampler_views);
+   } else
+      cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
 
    /* Compute Gallium window coords (y=0=top) with pixel zoom.
     * Recall that these coords are transformed by the current
@@ -953,6 +983,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
    struct pipe_sampler_view *sv[2] = { NULL };
    int num_sampler_view = 1;
    struct gl_pixelstore_attrib clippedUnpack;
+   struct st_fp_variant *fpv = NULL;
 
    /* Mesa state should be up to date by now */
    assert(ctx->NewState == 0x0);
@@ -992,7 +1023,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
       color = ctx->Current.RasterColor;
    }
    else {
-      struct st_fp_variant *fpv = get_color_fp_variant(st);
+      fpv = get_color_fp_variant(st);
 
       driver_fp = fpv->driver_shader;
       driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
@@ -1035,7 +1066,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
                                sv,
                                num_sampler_view,
                                driver_vp,
-                               driver_fp,
+                               driver_fp, fpv,
                                color, GL_FALSE, write_depth, write_stencil);
             pipe_sampler_view_reference(&sv[0], NULL);
             if (num_sampler_view > 1)
@@ -1290,6 +1321,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    void *driver_vp, *driver_fp;
    struct pipe_resource *pt;
    struct pipe_sampler_view *sv[2] = { NULL };
+   struct st_fp_variant *fpv = NULL;
    int num_sampler_view = 1;
    GLfloat *color;
    enum pipe_format srcFormat;
@@ -1328,7 +1360,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
     * Get vertex/fragment shaders
     */
    if (type == GL_COLOR) {
-      struct st_fp_variant *fpv = get_color_fp_variant(st);
+      fpv = get_color_fp_variant(st);
 
       rbRead = st_get_color_read_renderbuffer(ctx);
       color = NULL;
@@ -1480,7 +1512,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
                       sv,
                       num_sampler_view,
                       driver_vp, 
-                      driver_fp,
+                      driver_fp, fpv,
                       color, invertTex, GL_FALSE, GL_FALSE);
 
    pipe_resource_reference(&pt, NULL);
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h
index b8a3495..f1fb32d 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.h
+++ b/src/mesa/state_tracker/st_cb_drawpixels.h
@@ -44,6 +44,8 @@ st_destroy_drawpix(struct st_context *st);
 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);
+                      unsigned bias_const, bool pixel_maps,
+                      unsigned drawpix_sampler, unsigned pixelmap_sampler,
+                      unsigned texcoord_const);
 
 #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
index 01db0b6..749b46c 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels_shader.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels_shader.c
@@ -40,6 +40,9 @@ struct tgsi_drawpix_transform {
    unsigned scale_const;
    unsigned bias_const;
    unsigned color_temp;
+   unsigned drawpix_sampler;
+   unsigned pixelmap_sampler;
+   unsigned texcoord_const;
 };
 
 static inline struct tgsi_drawpix_transform *
@@ -71,7 +74,8 @@ transform_instr(struct tgsi_transform_context *tctx,
    struct tgsi_drawpix_transform *ctx = tgsi_drawpix_transform(tctx);
    struct tgsi_full_declaration decl;
    struct tgsi_full_instruction inst;
-   unsigned i, semantic;
+   unsigned i, sem_texcoord = ctx->use_texcoord ? TGSI_SEMANTIC_TEXCOORD :
+                                                  TGSI_SEMANTIC_GENERIC;
    int texcoord_index = -1;
 
    if (ctx->first_instruction_emitted)
@@ -96,6 +100,13 @@ transform_instr(struct tgsi_transform_context *tctx,
       }
    }
 
+   if (ctx->info.const_file_max[0] < (int)ctx->texcoord_const) {
+      decl = tgsi_default_full_declaration();
+      decl.Declaration.File = TGSI_FILE_CONSTANT;
+      decl.Range.First = decl.Range.Last = ctx->texcoord_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();
@@ -103,11 +114,9 @@ transform_instr(struct tgsi_transform_context *tctx,
    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;
+   /* Add TEXCOORD[texcoord_slot] if it's missing. */
    for (i = 0; i < ctx->info.num_inputs; i++) {
-      if (ctx->info.input_semantic_name[i] == semantic &&
+      if (ctx->info.input_semantic_name[i] == sem_texcoord &&
           ctx->info.input_semantic_index[i] == 0) {
          texcoord_index = i;
          break;
@@ -118,7 +127,7 @@ transform_instr(struct tgsi_transform_context *tctx,
       decl = tgsi_default_full_declaration();
       decl.Declaration.File = TGSI_FILE_INPUT;
       decl.Declaration.Semantic = 1;
-      decl.Semantic.Name = semantic;
+      decl.Semantic.Name = sem_texcoord;
       decl.Declaration.Interpolate = 1;
       decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
       decl.Range.First = decl.Range.Last = ctx->info.num_inputs;
@@ -127,17 +136,19 @@ transform_instr(struct tgsi_transform_context *tctx,
    }
 
    /* Declare the drawpix sampler if it's missing. */
-   if (ctx->info.file_max[TGSI_FILE_SAMPLER] == -1) {
+   if (!(ctx->info.samplers_declared & (1 << ctx->drawpix_sampler))) {
       decl = tgsi_default_full_declaration();
       decl.Declaration.File = TGSI_FILE_SAMPLER;
+      decl.Range.First = decl.Range.Last = ctx->drawpix_sampler;
       tctx->emit_declaration(tctx, &decl);
    }
 
    /* Declare the pixel map sampler if it's missing. */
-   if (ctx->info.file_max[TGSI_FILE_SAMPLER] <= 0) {
+   if (ctx->pixel_maps &&
+       !(ctx->info.samplers_declared & (1 << ctx->pixelmap_sampler))) {
       decl = tgsi_default_full_declaration();
       decl.Declaration.File = TGSI_FILE_SAMPLER;
-      decl.Range.First = decl.Range.Last = 1;
+      decl.Range.First = decl.Range.Last = ctx->pixelmap_sampler;
       tctx->emit_declaration(tctx, &decl);
    }
 
@@ -157,7 +168,7 @@ transform_instr(struct tgsi_transform_context *tctx,
    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;
+   inst.Src[1].Register.Index = ctx->drawpix_sampler;
 
    tctx->emit_instruction(tctx, &inst);
 
@@ -197,7 +208,7 @@ transform_instr(struct tgsi_transform_context *tctx,
       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;
+      inst.Src[1].Register.Index = ctx->pixelmap_sampler;
 
       tctx->emit_instruction(tctx, &inst);
 
@@ -207,7 +218,9 @@ transform_instr(struct tgsi_transform_context *tctx,
       tctx->emit_instruction(tctx, &inst);
    }
 
-   /* Now, "color_temp" should be used in place of IN:COLOR0 */
+   /* Now, "color_temp" should be used in place of IN:COLOR0,
+    * and CONST[texcoord_slot] should be used in place of IN:TEXCOORD0.
+    */
 
 transform_inst:
 
@@ -215,12 +228,17 @@ transform_inst:
       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 &&
+      if (src->Register.File != TGSI_FILE_INPUT || src->Register.Indirect)
+         continue;
+
+      if (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;
+      } else if (ctx->info.input_semantic_name[reg] == sem_texcoord &&
+                 ctx->info.input_semantic_index[reg] == 0) {
+         src->Register.File = TGSI_FILE_CONSTANT;
+         src->Register.Index = ctx->texcoord_const;
       }
    }
 
@@ -230,7 +248,9 @@ transform_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)
+                      unsigned bias_const, bool pixel_maps,
+                      unsigned drawpix_sampler, unsigned pixelmap_sampler,
+                      unsigned texcoord_const)
 {
    struct tgsi_drawpix_transform ctx;
    struct tgsi_token *newtoks;
@@ -243,6 +263,9 @@ st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
    ctx.scale_const = scale_const;
    ctx.bias_const = bias_const;
    ctx.pixel_maps = pixel_maps;
+   ctx.drawpix_sampler = drawpix_sampler;
+   ctx.pixelmap_sampler = pixelmap_sampler;
+   ctx.texcoord_const = texcoord_const;
    tgsi_scan_shader(tokens, &ctx.info);
 
    newlen = tgsi_num_tokens(tokens) + 30;
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 01e33d0..95ad2f4 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -886,7 +886,17 @@ st_translate_fragment_program(struct st_context *st,
    /* glDrawPixels (color only) */
    if (key->drawpixels) {
       const struct tgsi_token *tokens;
-      unsigned scale_const = 0, bias_const = 0;
+      unsigned scale_const = 0, bias_const = 0, texcoord_const = 0;
+
+      /* Find the first unused slot. */
+      variant->drawpix_sampler = ffs(~stfp->Base.Base.SamplersUsed) - 1;
+
+      if (key->pixelMaps) {
+         unsigned samplers_used = stfp->Base.Base.SamplersUsed |
+                                  (1 << variant->drawpix_sampler);
+
+         variant->pixelmap_sampler = ffs(~samplers_used) - 1;
+      }
 
       variant->parameters =
          _mesa_clone_parameter_list(stfp->Base.Base.Parameters);
@@ -903,10 +913,21 @@ st_translate_fragment_program(struct st_context *st,
                                                 bias_state);
       }
 
+      {
+         static const gl_state_index state[STATE_LENGTH] =
+            { STATE_INTERNAL, STATE_CURRENT_ATTRIB, VERT_ATTRIB_TEX0 };
+
+         texcoord_const = _mesa_add_state_reference(variant->parameters,
+                                                    state);
+      }
+
       tokens = st_get_drawpix_shader(variant->tgsi.tokens,
                                      st->needs_texcoord_semantic,
                                      key->scaleAndBias, scale_const,
-                                     bias_const, key->pixelMaps);
+                                     bias_const, key->pixelMaps,
+                                     variant->drawpix_sampler,
+                                     variant->pixelmap_sampler,
+                                     texcoord_const);
 
       if (tokens) {
          tgsi_free_tokens(variant->tgsi.tokens);
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 2927d54..33d39f0 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -85,6 +85,10 @@ struct st_fp_variant
    struct gl_program_parameter_list *parameters;
    uint bitmap_sampler;
 
+   /** For glDrawPixels variants */
+   unsigned drawpix_sampler;
+   unsigned pixelmap_sampler;
+
    /** next in linked list */
    struct st_fp_variant *next;
 };
-- 
2.1.4



More information about the mesa-dev mailing list