st/mesa: fix glDrawPixels with a texture
authorMarek Olšák <marek.olsak@amd.com>
Sun, 4 Oct 2015 23:22:20 +0000 (01:22 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 9 Oct 2015 20:02:18 +0000 (22:02 +0200)
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.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Tested-by: Brian Paul <brianp@vmware.com>
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_drawpixels.h
src/mesa/state_tracker/st_cb_drawpixels_shader.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index 34163ede4a265b314b6ea65df613653299177a31..7e8633edc1a9074b923e5f378bbefdc0669b724c 100644 (file)
@@ -525,6 +525,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)
@@ -612,10 +613,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;
@@ -626,8 +626,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 */
@@ -647,8 +664,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
@@ -943,6 +973,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);
@@ -982,7 +1013,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);
@@ -1025,7 +1056,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)
@@ -1280,6 +1311,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;
@@ -1318,7 +1350,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;
@@ -1470,7 +1502,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);
index b8a34952141b2f455a0dd781c9376cecfee5a573..f1fb32dd6cf6134c1fd63635eb7e34f6fa83ca38 100644 (file)
@@ -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 */
index 01db0b6d73e83296ed23e2c929bbf5b6055a4120..749b46cfbf76945bf41a009070c8517531347548 100644 (file)
@@ -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;
index 01e33d04f74c773fb55286f79578558f4d8799f8..95ad2f4682716c3d9e353657dd2bebf2a4dd0eda 100644 (file)
@@ -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);
index 2927d542dfcffb3ec3b045a6bf069ca302679673..33d39f005b91c7cbc7643c5faf15ff15ff2a7946 100644 (file)
@@ -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;
 };