summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian <brian.paul@tungstengraphics.com>2007-10-30 16:13:37 -0600
committerBrian <brian.paul@tungstengraphics.com>2007-10-30 16:13:37 -0600
commitd6a739f6b0658414a81715bf690159f7cfdb4961 (patch)
tree018a879a8a638972bf660d660a1762bd7f885bfb
parentee70c02b62f7692de6293045928c47168652bd1c (diff)
Use program serial numbers to avoid re-generating fragment programs for glDrawPixels.
-rw-r--r--src/mesa/state_tracker/st_atom_pixeltransfer.c14
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c52
-rw-r--r--src/mesa/state_tracker/st_cb_program.c6
-rw-r--r--src/mesa/state_tracker/st_context.c4
-rw-r--r--src/mesa/state_tracker/st_context.h10
5 files changed, 58 insertions, 28 deletions
diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c
index b190c39343..8cf340e685 100644
--- a/src/mesa/state_tracker/st_atom_pixeltransfer.c
+++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c
@@ -42,6 +42,7 @@
#include "shader/prog_print.h"
#include "st_context.h"
+#include "st_program.h"
@@ -79,8 +80,6 @@ is_identity(const GLfloat m[16])
static void
make_state_key(GLcontext *ctx, struct state_key *key)
{
- /*GLuint i, j;*/
-
memset(key, 0, sizeof(*key));
if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
@@ -189,6 +188,8 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
inst[ic].SrcReg[0].Index = FRAG_RESULT_COLR;
ic++;
+ /* XXX reimplement in terms of MUL/MAD (see t_vp_build.c) */
+
/* DP4 result.color.x, tmp0, matrow0; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_DP4;
@@ -268,6 +269,9 @@ get_pixel_transfer_program(GLcontext *ctx, const struct state_key *key)
+/**
+ * Update st->pixel_xfer.program in response to new pixel-transfer state.
+ */
static void
update_pixel_transfer(struct st_context *st)
{
@@ -277,14 +281,14 @@ update_pixel_transfer(struct st_context *st)
make_state_key(st->ctx, &key);
fp = (struct gl_fragment_program *)
- _mesa_search_program_cache(st->pixel_transfer_cache, &key, sizeof(key));
+ _mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
if (!fp) {
fp = get_pixel_transfer_program(st->ctx, &key);
- _mesa_program_cache_insert(st->ctx, st->pixel_transfer_cache,
+ _mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
&key, sizeof(key), &fp->Base);
}
- st->pixel_transfer_program = fp;
+ st->pixel_xfer.program = (struct st_fragment_program *) fp;
}
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 3359338385..c74c8fa641 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -182,30 +182,48 @@ make_drawpix_fragment_shader(struct st_context *st)
{
GLcontext *ctx = st->ctx;
struct st_fragment_program *stfp;
- struct gl_program *p;
- /*
- * XXX Use st_program's serial numbers to determine when the
- * user-provided program and pixel-transfer program to avoid
- * needless combining/translation here.
- */
+ 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
+ * shader has not changed, so re-use the combined program.
+ */
+ stfp = st->pixel_xfer.combined_prog;
+ }
+ else {
+ /* Concatenate the pixel transfer program with the current user-
+ * defined shader.
+ */
+ stfp = (struct st_fragment_program *)
+ _mesa_combine_programs(ctx,
+ &st->pixel_xfer.program->Base.Base,
+ &st->fp->Base.Base);
- p = _mesa_combine_programs(ctx,
- &st->pixel_transfer_program->Base,
- &ctx->FragmentProgram._Current->Base);
#if 0
- _mesa_print_program(p);
- printf("InputsRead: 0x%x\n", p->InputsRead);
- printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
- _mesa_print_parameter_list(p->Parameters);
+ {
+ struct gl_program *p = &stfp->Base.Base;
+ _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
- stfp = (struct st_fragment_program *) p;
- st_translate_fragment_program(st, stfp, NULL,
- stfp->tokens, ST_MAX_SHADER_TOKENS);
+ /* translate to TGSI tokens */
+ st_translate_fragment_program(st, stfp, NULL,
+ stfp->tokens, ST_MAX_SHADER_TOKENS);
+ /* 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;
+ st->pixel_xfer.combined_prog = stfp;
+ }
- st_upload_constants( st, p->Parameters, PIPE_SHADER_FRAGMENT );
+ /* 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);
return stfp;
}
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index a330c1c922..aed6b1ee97 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -44,6 +44,8 @@
#include "st_atom_shader.h"
+static GLuint SerialNo = 1;
+
/**
* Called via ctx->Driver.BindProgram() to bind an ARB vertex or
@@ -91,7 +93,7 @@ static struct gl_program *st_new_program( GLcontext *ctx,
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program);
- prog->serialNo = 1;
+ prog->serialNo = SerialNo++;
return _mesa_init_vertex_program( ctx,
&prog->Base,
@@ -103,7 +105,7 @@ static struct gl_program *st_new_program( GLcontext *ctx,
case GL_FRAGMENT_PROGRAM_NV: {
struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program);
- prog->serialNo = 1;
+ prog->serialNo = SerialNo++;
return _mesa_init_fragment_program( ctx,
&prog->Base,
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index e872e8b12c..c7398233d8 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -92,7 +92,7 @@ struct st_context *st_create_context( GLcontext *ctx,
st->haveFramebufferRegions = GL_TRUE;
- st->pixel_transfer_cache = _mesa_new_program_cache();
+ st->pixel_xfer.cache = _mesa_new_program_cache();
#if 0
st_init_cb_clear( st );
@@ -126,7 +126,7 @@ void st_destroy_context( struct st_context *st )
#endif
cso_cache_delete( st->cache );
- _mesa_delete_program_cache(st->ctx, st->pixel_transfer_cache);
+ _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
st->pipe->destroy( st->pipe );
FREE( st );
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 4de70a3b2e..8bbfb0d6fe 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -133,8 +133,14 @@ struct st_context
struct st_vertex_program *vp; /**< Currently bound vertex program */
struct st_fragment_program *fp; /**< Currently bound fragment program */
- struct gl_fragment_program *pixel_transfer_program;
- struct gl_program_cache *pixel_transfer_cache;
+ struct {
+ struct gl_program_cache *cache;
+ struct st_fragment_program *program; /**< cur pixel transfer prog */
+ GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
+ GLuint user_prog_sn; /**< user fragment program serial no. */
+ struct st_fragment_program *combined_prog;
+ GLuint combined_prog_sn;
+ } pixel_xfer;
/**
* Buffer object which stores the ctx->Current.Attrib[] values.