Mesa (st-mesa-per-context-shaders): st/mesa: restore glDraw/ CopyPixels using new fragment program variants

Brian Paul brianp at kemper.freedesktop.org
Mon Dec 13 00:10:20 UTC 2010


Module: Mesa
Branch: st-mesa-per-context-shaders
Commit: c5751c673644808ab069259a852f24c4c0e92b9d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c5751c673644808ab069259a852f24c4c0e92b9d

Author: Brian Paul <brianp at vmware.com>
Date:   Sun Dec 12 15:28:57 2010 -0700

st/mesa: restore glDraw/CopyPixels using new fragment program variants

Clean up the logic for fragment programs for glDraw/CopyPixels.  We now
generate fragment program variants for glDraw/CopyPixels as needed which
do texture sampling, pixel scale/bias, pixelmap lookups, etc.

---

 src/mesa/state_tracker/st_cb_bitmap.c     |    8 +-
 src/mesa/state_tracker/st_cb_bitmap.h     |    8 +-
 src/mesa/state_tracker/st_cb_drawpixels.c |  213 +++++++++++++++++------------
 src/mesa/state_tracker/st_cb_drawpixels.h |   10 ++
 src/mesa/state_tracker/st_cb_program.c    |   10 --
 src/mesa/state_tracker/st_context.h       |    2 +-
 src/mesa/state_tracker/st_program.c       |   28 ++++-
 src/mesa/state_tracker/st_program.h       |   23 ++--
 8 files changed, 182 insertions(+), 120 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index a2ab743..320b73f 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -191,10 +191,10 @@ find_free_bit(uint bitfield)
  * \param bitmap_sampler  sampler number for the bitmap texture
  */
 void
-st_make_combined_bitmap_fragment_program(struct st_context *st,
-                                         struct gl_fragment_program *fpIn,
-                                         struct gl_fragment_program **fpOut,
-                                         GLuint *bitmap_sampler)
+st_make_bitmap_fragment_program(struct st_context *st,
+                                struct gl_fragment_program *fpIn,
+                                struct gl_fragment_program **fpOut,
+                                GLuint *bitmap_sampler)
 {
    struct st_fragment_program *bitmap_prog;
    struct gl_program *newProg;
diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h
index 041dda7..2bd63b9 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.h
+++ b/src/mesa/state_tracker/st_cb_bitmap.h
@@ -49,10 +49,10 @@ extern void
 st_destroy_bitmap(struct st_context *st);
 
 extern void
-st_make_combined_bitmap_fragment_program(struct st_context *st,
-                                         struct gl_fragment_program *fpIn,
-                                         struct gl_fragment_program **fpOut,
-                                         GLuint *bitmap_sampler);
+st_make_bitmap_fragment_program(struct st_context *st,
+                                struct gl_fragment_program *fpIn,
+                                struct gl_fragment_program **fpOut,
+                                GLuint *bitmap_sampler);
 
 extern void
 st_flush_bitmap_cache(struct st_context *st);
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index e2b1946..323e7e3 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -94,94 +94,61 @@ is_passthrough_program(const struct gl_fragment_program *prog)
 /**
  * Make fragment shader for glDraw/CopyPixels.  This shader is made
  * by combining the pixel transfer shader with the user-defined shader.
- * \return pointer to Gallium driver fragment shader
+ * \param fpIn  the current/incoming fragment program
+ * \param fpOut  returns the combined fragment program
  */
-static void *
-combined_drawpix_fragment_program(struct gl_context *ctx)
+void
+st_make_drawpix_fragment_program(struct st_context *st,
+                                 struct gl_fragment_program *fpIn,
+                                 struct gl_fragment_program **fpOut)
 {
-   struct st_context *st = st_context(ctx);
-   struct st_fragment_program *stfp;
+   struct gl_program *newProg;
 
-   if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
-       && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
-      /* the pixel tranfer program has not changed and the user-defined
-       * program has not changed, so re-use the combined program.
-       */
-      stfp = st->pixel_xfer.combined_prog;
+   if (is_passthrough_program(fpIn)) {
+      newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx,
+                                             &st->pixel_xfer.program->Base);
    }
    else {
-      /* Concatenate the pixel transfer program with the current user-
-       * defined program.
-       */
-      if (is_passthrough_program(&st->fp->Base)) {
-         stfp = (struct st_fragment_program *)
-            _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base);
-      }
-      else {
 #if 0
-         printf("Base program:\n");
-         _mesa_print_program(&st->fp->Base.Base);
-         printf("DrawPix program:\n");
-         _mesa_print_program(&st->pixel_xfer.program->Base.Base);
+      /* debug */
+      printf("Base program:\n");
+      _mesa_print_program(&fpIn->Base);
+      printf("DrawPix program:\n");
+      _mesa_print_program(&st->pixel_xfer.program->Base.Base);
 #endif
-         stfp = (struct st_fragment_program *)
-            _mesa_combine_programs(ctx,
-                                   &st->pixel_xfer.program->Base.Base,
-                                   &st->fp->Base.Base);
-      }
+      newProg = _mesa_combine_programs(st->ctx,
+                                       &st->pixel_xfer.program->Base.Base,
+                                       &fpIn->Base);
+   }
 
 #if 0
-      {
-         struct gl_program *p = &stfp->Base.Base;
-         printf("Combined DrawPixels program:\n");
-         _mesa_print_program(p);
-         printf("InputsRead: 0x%x\n", p->InputsRead);
-         printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
-         _mesa_print_parameter_list(p->Parameters);
-      }
-#endif
-
-      /* translate to TGSI tokens */
-#if 0000000000000
-      st_translate_fragment_program(st, stfp);
+   /* 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
 
-      /* save new program, update serial numbers */
-      st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
-      st->pixel_xfer.user_prog_sn = st->fp->serialNo;
-      st->pixel_xfer.combined_prog_sn = stfp->serialNo;
-      /* can't reference new program directly, already have a reference on it */
-      st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
-      st->pixel_xfer.combined_prog = stfp;
-   }
-
-   /* Ideally we'd have updated the pipe constants during the normal
-    * st/atom mechanism.  But we can't since this is specific to glDrawPixels.
-    */
-   st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
-
-#if 00000000000
-   return stfp->driver_shader;
-#else
-   return 0;
-#endif
+   *fpOut = (struct gl_fragment_program *) newProg;
 }
 
 
 /**
- * Create fragment shader that does a TEX() instruction to get a Z and/or
+ * 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).
  * Pass fragment color through as-is.
- * \return pointer to the Gallium driver fragment shader
+ * \return pointer to the gl_fragment program
  */
-static void *
-make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
-                               GLboolean write_stencil)
+struct gl_fragment_program *
+st_make_drawpix_z_stencil_program(struct st_context *st,
+                                  GLboolean write_depth,
+                                  GLboolean write_stencil)
 {
    struct gl_context *ctx = st->ctx;
    struct gl_program *p;
-   struct st_fragment_program *stp;
+   struct gl_fragment_program *fp;
    GLuint ic = 0;
    const GLuint shaderIndex = write_depth * 2 + write_stencil;
 
@@ -189,11 +156,7 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
 
    if (st->drawpix.shaders[shaderIndex]) {
       /* already have the proper shader */
-#if 00000
-      return st->drawpix.shaders[shaderIndex]->driver_shader;
-#else
-      return 0;
-#endif
+      return st->drawpix.shaders[shaderIndex];
    }
 
    /*
@@ -255,22 +218,15 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
    if (write_stencil)
       p->SamplersUsed |= 1 << 1;
 
-   stp = st_fragment_program((struct gl_fragment_program *) p);
+   fp = (struct gl_fragment_program *) p;
 
-#if 0000
    /* save the new shader */
-   st->drawpix.shaders[shaderIndex] = stp;
+   st->drawpix.shaders[shaderIndex] = fp;
 
-   st_translate_fragment_program(st, stp);
-
-   return stp->driver_shader;
-#else
-   return 000;
-#endif
+   return fp;
 }
 
 
-
 /**
  * Create a simple vertex shader that just passes through the
  * vertex position and texcoord (and optionally, color).
@@ -887,6 +843,61 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
 
 
 /**
+ * Get fragment program variant for a glDrawPixels or glCopyPixels
+ * command for RGBA data.
+ */
+static struct st_fp_varient *
+get_color_fp_varient(struct st_context *st)
+{
+   struct gl_context *ctx = st->ctx;
+   struct st_fp_varient_key key;
+   struct st_fp_varient *fpv;
+
+   memset(&key, 0, sizeof(key));
+
+   key.st = st;
+   key.drawpixels = 1;
+   key.scaleAndBias = (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.pixelMaps = ctx->Pixel.MapColorFlag;
+
+   fpv = st_get_fp_varient(st, st->fp, &key);
+
+   return fpv;
+}
+
+
+/**
+ * Get fragment program variant for a glDrawPixels or glCopyPixels
+ * command for depth/stencil data.
+ */
+static struct st_fp_varient *
+get_depth_stencil_fp_varient(struct st_context *st, GLboolean write_depth,
+                             GLboolean write_stencil)
+{
+   struct st_fp_varient_key key;
+   struct st_fp_varient *fpv;
+
+   memset(&key, 0, sizeof(key));
+
+   key.st = st;
+   key.drawpixels = 1;
+   key.drawpixels_z = write_depth;
+   key.drawpixels_stencil = write_stencil;
+
+   fpv = st_get_fp_varient(st, st->fp, &key);
+
+   return fpv;
+}
+
+
+/**
  * Called via ctx->Driver.DrawPixels()
  */
 static void
@@ -903,6 +914,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
    struct pipe_sampler_view *sv[2];
    int num_sampler_view = 1;
    enum pipe_format stencil_format = PIPE_FORMAT_NONE;
+   struct st_fp_varient *fpv;
 
    if (format == GL_DEPTH_STENCIL)
       write_stencil = write_depth = GL_TRUE;
@@ -935,14 +947,25 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
 
    st_validate_state(st);
 
+   /*
+    * Get vertex/fragment shaders
+    */
    if (write_depth || write_stencil) {
-      driver_fp = make_fragment_shader_z_stencil(st, write_depth, write_stencil);
+      fpv = get_depth_stencil_fp_varient(st, write_depth, write_stencil);
+
+      driver_fp = fpv->driver_shader;
+
       driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
+
       color = ctx->Current.RasterColor;
    }
    else {
-      driver_fp = combined_drawpix_fragment_program(ctx);
+      fpv = get_color_fp_varient(st);
+
+      driver_fp = fpv->driver_shader;
+
       driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
+
       color = NULL;
       if (st->pixel_xfer.pixelmap_enabled) {
 	  sv[1] = st->pixel_xfer.pixelmap_sampler_view;
@@ -950,6 +973,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
       }
    }
 
+   /* update fragment program constants */
+   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+
    /* draw with textured quad */
    {
       struct pipe_resource *pt
@@ -1130,6 +1156,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    GLint readX, readY, readW, readH;
    GLuint sample_count;
    struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
+   struct st_fp_varient *fpv;
 
    st_validate_state(st);
 
@@ -1139,11 +1166,18 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       return;
    }
 
+   /*
+    * Get vertex/fragment shaders
+    */
    if (type == GL_COLOR) {
       rbRead = st_get_color_read_renderbuffer(ctx);
       color = NULL;
-      driver_fp = combined_drawpix_fragment_program(ctx);
+
+      fpv = get_color_fp_varient(st);
+      driver_fp = fpv->driver_shader;
+
       driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
+
       if (st->pixel_xfer.pixelmap_enabled) {
 	  sv[1] = st->pixel_xfer.pixelmap_sampler_view;
 	  num_sampler_view++;
@@ -1153,10 +1187,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       assert(type == GL_DEPTH);
       rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
       color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
-      driver_fp = make_fragment_shader_z_stencil(st, GL_TRUE, GL_FALSE);
+
+      fpv = get_depth_stencil_fp_varient(st, GL_TRUE, GL_FALSE);
+      driver_fp = fpv->driver_shader;
+
       driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
    }
 
+   /* update fragment program constants */
+   st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
+
+
    if (rbRead->Base.Wrapped)
       rbRead = st_renderbuffer(rbRead->Base.Wrapped);
 
@@ -1308,7 +1349,7 @@ st_destroy_drawpix(struct st_context *st)
 
    for (i = 0; i < Elements(st->drawpix.shaders); i++) {
       if (st->drawpix.shaders[i])
-         st_reference_fragprog(st, &st->drawpix.shaders[i], NULL);
+         _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL);
    }
 
    st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h
index 575f169..8f73e62 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.h
+++ b/src/mesa/state_tracker/st_cb_drawpixels.h
@@ -42,6 +42,16 @@ 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 struct gl_fragment_program *
+st_make_drawpix_z_stencil_program(struct st_context *st,
+                                  GLboolean write_depth,
+                                  GLboolean write_stencil);
+
 #else
 
 static INLINE void
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index c803f84..25a135a 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -112,8 +112,6 @@ static struct gl_program *st_new_program( struct gl_context *ctx,
    case GL_FRAGMENT_PROGRAM_NV: {
       struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program);
 
-      prog->serialNo = SerialNo++;
-
       return _mesa_init_fragment_program( ctx, 
 					  &prog->Base,
 					  target, 
@@ -217,20 +215,12 @@ static GLboolean st_program_string_notify( struct gl_context *ctx,
    if (target == GL_FRAGMENT_PROGRAM_ARB) {
       struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
 
-      stfp->serialNo++;
-
       st_fp_release_varients(st, stfp);
-#if 00000
-      if (stfp->driver_shader) {
-         cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
-         stfp->driver_shader = NULL;
-      }
 
       if (stfp->tgsi.tokens) {
          st_free_tokens(stfp->tgsi.tokens);
          stfp->tgsi.tokens = NULL;
       }
-#endif
 
       if (st->fp == stfp)
 	 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index dbc6744..4559769 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -161,7 +161,7 @@ struct st_context
 
    /** for glDraw/CopyPixels */
    struct {
-      struct st_fragment_program *shaders[4];
+      struct gl_fragment_program *shaders[4];
       void *vert_shaders[2];   /**< ureg shaders */
    } drawpix;
 
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 322eec8..795d875 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -47,6 +47,7 @@
 
 #include "st_debug.h"
 #include "st_cb_bitmap.h"
+#include "st_cb_drawpixels.h"
 #include "st_context.h"
 #include "st_program.h"
 #include "st_mesa_to_tgsi.h"
@@ -327,7 +328,7 @@ fail:
 /**
  * Translate a Mesa fragment shader into a TGSI shader using extra info in
  * the key.
- * \return  pointer to cached pipe_shader object.
+ * \return  new fragment program variant
  */
 struct st_fp_varient *
 st_translate_fragment_program(struct st_context *st,
@@ -335,19 +336,38 @@ st_translate_fragment_program(struct st_context *st,
                               const struct st_fp_varient_key *key)
 {
    struct pipe_context *pipe = st->pipe;
-   struct st_fp_varient *varient = MALLOC_STRUCT(st_fp_varient);
+   struct st_fp_varient *varient = CALLOC_STRUCT(st_fp_varient);
 
    if (!varient)
       return NULL;
 
+   assert(!(key->bitmap && key->drawpixels));
+
    if (key->bitmap) {
+      /* glBitmap drawing */
       struct gl_fragment_program *fp;
-      st_make_combined_bitmap_fragment_program(st, &stfp->Base,
-                                               &fp, &varient->bitmap_sampler);
+
+      st_make_bitmap_fragment_program(st, &stfp->Base,
+                                      &fp, &varient->bitmap_sampler);
 
       varient->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
       stfp = (struct st_fragment_program *) fp;
    }
+   else if (key->drawpixels) {
+      /* glDrawPixels drawing */
+      struct gl_fragment_program *fp;
+
+      if (key->drawpixels_z || key->drawpixels_stencil) {
+         fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
+                                                key->drawpixels_stencil);
+      }
+      else {
+         /* RGBA */
+         st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
+         varient->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
+      }
+      stfp = (struct st_fragment_program *) fp;
+   }
 
    if (!stfp->tgsi.tokens) {
       /* need to translate Mesa instructions to TGSI now */
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 642a256..acbecc9 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -43,8 +43,17 @@
 /** Fragment program variant key */
 struct st_fp_varient_key
 {
-   struct st_context *st;          /**< variants are per-context */
-   GLboolean bitmap;               /**< glBitmap varient? */
+   struct st_context *st;         /**< variants are per-context */
+
+   /** for glBitmap */
+   GLuint bitmap:1;               /**< glBitmap varient? */
+
+   /** for glDrawPixels */
+   GLuint drawpixels:1;           /**< glDrawPixels varient */
+   GLuint scaleAndBias:1;         /**< glDrawPixels w/ scale and/or bias? */
+   GLuint pixelMaps:1;            /**< glDrawPixels w/ pixel lookup map? */
+   GLuint drawpixels_z:1;         /**< glDrawPixels(GL_DEPTH) */
+   GLuint drawpixels_stencil:1;   /**< glDrawPixels(GL_STENCIL) */
 };
 
 
@@ -74,18 +83,10 @@ struct st_fp_varient
 struct st_fragment_program
 {
    struct gl_fragment_program Base;
-   GLuint serialNo;
 
    struct pipe_shader_state tgsi;
-#if 0
-   void *driver_shader;
-#else
-   struct st_fp_varient *varients;
-#endif
 
-   /** Program prefixed with glBitmap prologue */
-   struct st_fragment_program *bitmap_program;
-   uint bitmap_sampler;
+   struct st_fp_varient *varients;
 };
 
 




More information about the mesa-commit mailing list