#include "shader/prog_print.h"
#include "st_context.h"
+#include "st_program.h"
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 ||
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;
+/**
+ * Update st->pixel_xfer.program in response to new pixel-transfer state.
+ */
static void
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;
}
{
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;
}
#include "st_atom_shader.h"
+static GLuint SerialNo = 1;
+
/**
* Called via ctx->Driver.BindProgram() to bind an ARB vertex or
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,
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,
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 );
#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 );
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.