[Mesa-dev] [PATCH] mesa/state_tracker: Fix draw-pixel-with-texture piglit test.

Matthew Dawson matthew at mjdsystems.ca
Mon Mar 23 22:38:26 PDT 2015


When glDrawPixels was used with an external texture, the pixels passed in
were sampled instead of the texture.  Change gallium to instead move the user
texture to a new sampler below the glDrawPixels samplers and use the texture
coordinates from the raster position.

This uses a uniform for the texture coordinates instead passing it through
the vertex shader as the texture coordinates are constant for the entire
operation.  While working the vertex shader would be possible, implementing
that solution would break several assumptions throughout the glDrawPixels
implementation as well as helper functions used by other code paths, increasing
the chance for breakage.

Tested on llvmpipe, r600, and radeonsi.

V2: Complete everything missing from V1.
---
Thanks for all the help I've gotten getting this patch into shape, especially considering what functionality it covers.
I know it probably won't directly help anyone, but it was a decent introduction to some mesa concepts, and
I  hope I can apply the knowledge in the future.

 src/mesa/state_tracker/st_cb_drawpixels.c  | 25 ++++++++++++++++++++++---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 25 +++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 3edf31b..8847b1f1 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -44,6 +44,7 @@
 #include "main/texstore.h"
 #include "main/glformats.h"
 #include "program/program.h"
+#include "program/prog_parameter.h"
 #include "program/prog_print.h"
 #include "program/prog_instruction.h"
 
@@ -676,6 +677,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    GLfloat x0, y0, x1, y1;
    GLsizei maxSize;
    boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT;
+   int num_user_sampers = st->state.num_samplers[PIPE_SHADER_FRAGMENT];
 
    /* limit checks */
    /* XXX if DrawPixels image is larger than max texture size, break
@@ -765,6 +767,9 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
       if (num_sampler_view > 1) {
          cso_single_sampler(cso, PIPE_SHADER_FRAGMENT, 1, &sampler);
       }
+      for(int i = 0; i < num_user_sampers; ++i) {
+         cso_single_sampler(cso, PIPE_SHADER_FRAGMENT, i+num_sampler_view, &st->state.samplers[PIPE_SHADER_FRAGMENT][i]);
+      }
       cso_single_sampler_done(cso, PIPE_SHADER_FRAGMENT);
    }
 
@@ -786,7 +791,12 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
 
    /* texture state: */
-   cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
+   {
+      struct pipe_sampler_view *lsv[PIPE_MAX_SAMPLERS];
+      memcpy(lsv, sv, num_sampler_view*sizeof(struct pipe_sampler_view*));
+      memcpy(lsv+num_sampler_view, st->state.sampler_views[PIPE_SHADER_FRAGMENT], num_user_sampers*sizeof(struct pipe_sampler_view*));
+      cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view+num_user_sampers, lsv);
+   }
 
    /* Compute Gallium window coords (y=0=top) with pixel zoom.
     * Recall that these coords are transformed by the current
@@ -1160,8 +1170,17 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
       }
    }
 
-   /* update fragment program constants */
-   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+   /* updated texture coordinates and fragment program constants. */
+   {
+      struct gl_program_parameter_list *parameters = fpv->parameters;
+      for(int i = 0; i < parameters->NumParameters; ++i) {
+         const char *name = parameters->Parameters[i].Name;
+         if (strncmp("texcoord", name, 8) == 0 && strlen(name) == 9) {
+            memcpy(parameters->ParameterValues[i], st->ctx->Current.RasterTexCoords[name[8] - 'A'], sizeof(GL_FLOAT) * 4);
+         }
+      }
+      st_upload_constants(st, parameters, PIPE_SHADER_FRAGMENT);
+   }
 
    /* draw with textured quad */
    {
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index efee4b2..2613112 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -4254,6 +4254,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
    st_src_reg coord, src0;
    st_dst_reg dst0;
    glsl_to_tgsi_instruction *inst;
+   unsigned int count_samplers_used = 0;
 
    /* Copy attributes of the glsl_to_tgsi_visitor in the original shader. */
    v->ctx = original->ctx;
@@ -4284,6 +4285,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
    prog->InputsRead |= VARYING_BIT_TEX0;
    prog->SamplersUsed |= (1 << 0); /* mark sampler 0 as used */
    v->samplers_used |= (1 << 0);
+   count_samplers_used++;
 
    if (scale_and_bias) {
       static const gl_state_index scale_state[STATE_LENGTH] =
@@ -4331,6 +4333,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
 
       prog->SamplersUsed |= (1 << 1); /* mark sampler 1 as used */
       v->samplers_used |= (1 << 1);
+      count_samplers_used++;
 
       /* MOV colorTemp, temp; */
       inst = v->emit(NULL, TGSI_OPCODE_MOV, dst0, temp);
@@ -4359,6 +4362,28 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,
       newinst = v->emit(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]);
       newinst->tex_target = inst->tex_target;
       newinst->sampler_array_size = inst->sampler_array_size;
+
+      if (newinst->tex_target != 0) {
+         newinst->sampler = inst->sampler;
+         int new_sampler_index = newinst->sampler.index + count_samplers_used;
+
+         // This name records what texture coordinates are need for this parameter.  This is used later to update the texture coordinates as appropriate.
+         char name[10];
+         memcpy(name, "texcoord_", 10);
+         name[8] = 'A' + newinst->sampler.index; // Replaces the underscore from above, while keeping the null byte.
+
+         GLint param;
+         if ((prog->SamplersUsed & (1 << new_sampler_index)) == 0) {
+            param = _mesa_add_parameter(params, PROGRAM_UNIFORM, name, 4, GL_FLOAT, (const gl_constant_value*)st->ctx->Current.RasterTexCoords[newinst->sampler.index], 0);
+         } else {
+            param = _mesa_lookup_parameter_index(params, -1, name);
+         }
+         newinst->src[0] = st_src_reg(PROGRAM_UNIFORM, param, GLSL_TYPE_FLOAT);
+         newinst->sampler.index = new_sampler_index;
+
+         prog->SamplersUsed |= (1 << new_sampler_index);
+         v->samplers_used |= (1 << new_sampler_index);
+      }
    }
 
    /* Make modifications to fragment program info. */
-- 
2.0.5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5584 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150324/a76bcc09/attachment-0001.bin>


More information about the mesa-dev mailing list