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