Squashed commit of the following (st-mesa-per-context-shaders branch):

commit 4f106f44a32eaddb6cf3fea6ba5ee9787bff609a
Author: Brian Paul <brianp@vmware.com>
Date:   Mon Dec 13 14:06:08 2010 -0700

    st/mesa: reorganize vertex program translation code

    Now it looks like the fragment and geometry program code.
    Also remove the serial number fields from programs.  It was used to
    determine when new translations were needed.  Now the variant key is
    used for that.  And the st_program_string_notify() callback removes all
    variants when the program's code is changed.

commit e12d6791c5e4bff60bb2e6c04414b1b4d1325f3e
Author: Brian Paul <brianp@vmware.com>
Date:   Mon Dec 13 13:38:12 2010 -0700

    st/mesa: implement geometry shader varients

    Only needed in order to support per-context gallium shaders.

commit c5751c673644808ab069259a852f24c4c0e92b9d
Author: Brian Paul <brianp@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.

commit 7b0bb99bab6547f503a0176b5c0aef1482b02c97
Author: Brian Paul <brianp@vmware.com>
Date:   Fri Dec 10 17:03:23 2010 -0700

    st/mesa: checkpoint: implement fragment program variants

    The fragment programs variants are per-context, as the vertex programs.

    NOTE: glDrawPixels is totally broken at this point.

commit 2cc926183f957f8abac18d71276dd5bbd1f27be2
Author: Brian Paul <brianp@vmware.com>
Date:   Fri Dec 10 14:59:32 2010 -0700

    st/mesa: make vertex shader variants per-context

    Gallium shaders are per-context but OpenGL shaders aren't.  So we need
    to make a different variant for each context.

    During context tear-down we need to walk over all shaders/programs and
    free all variants for the context being destroyed.
This commit is contained in:
Brian Paul
2010-12-13 17:20:12 -07:00
parent bb7c2691d2
commit 3d203b6100
10 changed files with 902 additions and 484 deletions

View File

@@ -50,99 +50,6 @@
#include "st_program.h" #include "st_program.h"
/**
* Translate fragment program if needed.
*/
static void
translate_fp(struct st_context *st,
struct st_fragment_program *stfp)
{
if (!stfp->tgsi.tokens) {
assert(stfp->Base.Base.NumInstructions > 0);
st_translate_fragment_program(st, stfp);
}
}
/*
* Translate geometry program if needed.
*/
static void
translate_gp(struct st_context *st,
struct st_geometry_program *stgp)
{
if (!stgp->tgsi.tokens) {
assert(stgp->Base.Base.NumInstructions > 1);
st_translate_geometry_program(st, stgp);
}
}
/**
* Find a translated vertex program that corresponds to stvp and
* has outputs matched to stfp's inputs.
* This performs vertex and fragment translation (to TGSI) when needed.
*/
static struct st_vp_varient *
find_translated_vp(struct st_context *st,
struct st_vertex_program *stvp )
{
struct st_vp_varient *vpv;
struct st_vp_varient_key key;
/* Nothing in our key yet. This will change:
*/
memset(&key, 0, sizeof key);
/* When this is true, we will add an extra input to the vertex
* shader translation (for edgeflags), an extra output with
* edgeflag semantics, and extend the vertex shader to pass through
* the input to the output. We'll need to use similar logic to set
* up the extra vertex_element input for edgeflags.
* _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA
*/
key.passthrough_edgeflags = (st->vertdata_edgeflags && (
st->ctx->Polygon.FrontMode != GL_FILL ||
st->ctx->Polygon.BackMode != GL_FILL));
/* Do we need to throw away old translations after a change in the
* GL program string?
*/
if (stvp->serialNo != stvp->lastSerialNo) {
/* These may have changed if the program string changed.
*/
st_prepare_vertex_program( st, stvp );
/* We are now up-to-date:
*/
stvp->lastSerialNo = stvp->serialNo;
}
/* See if we've got a translated vertex program whose outputs match
* the fragment program's inputs.
*/
for (vpv = stvp->varients; vpv; vpv = vpv->next) {
if (memcmp(&vpv->key, &key, sizeof key) == 0) {
break;
}
}
/* No? Perform new translation here. */
if (!vpv) {
vpv = st_translate_vertex_program(st, stvp, &key);
if (!vpv)
return NULL;
vpv->next = stvp->varients;
stvp->varients = vpv;
}
return vpv;
}
/** /**
* Return pointer to a pass-through fragment shader. * Return pointer to a pass-through fragment shader.
* This shader is used when a texture is missing/incomplete. * This shader is used when a texture is missing/incomplete.
@@ -167,12 +74,16 @@ static void
update_fp( struct st_context *st ) update_fp( struct st_context *st )
{ {
struct st_fragment_program *stfp; struct st_fragment_program *stfp;
struct st_fp_varient_key key;
assert(st->ctx->FragmentProgram._Current); assert(st->ctx->FragmentProgram._Current);
stfp = st_fragment_program(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
translate_fp(st, stfp); memset(&key, 0, sizeof(key));
key.st = st;
st->fp_varient = st_get_fp_varient(st, stfp, &key);
st_reference_fragprog(st, &st->fp, stfp); st_reference_fragprog(st, &st->fp, stfp);
@@ -182,7 +93,8 @@ update_fp( struct st_context *st )
cso_set_fragment_shader_handle(st->cso_context, fs); cso_set_fragment_shader_handle(st->cso_context, fs);
} }
else { else {
cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); cso_set_fragment_shader_handle(st->cso_context,
st->fp_varient->driver_shader);
} }
} }
@@ -206,6 +118,7 @@ static void
update_vp( struct st_context *st ) update_vp( struct st_context *st )
{ {
struct st_vertex_program *stvp; struct st_vertex_program *stvp;
struct st_vp_varient_key key;
/* find active shader and params -- Should be covered by /* find active shader and params -- Should be covered by
* ST_NEW_VERTEX_PROGRAM * ST_NEW_VERTEX_PROGRAM
@@ -214,7 +127,21 @@ update_vp( struct st_context *st )
stvp = st_vertex_program(st->ctx->VertexProgram._Current); stvp = st_vertex_program(st->ctx->VertexProgram._Current);
assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
st->vp_varient = find_translated_vp(st, stvp); memset(&key, 0, sizeof key);
key.st = st; /* variants are per-context */
/* When this is true, we will add an extra input to the vertex
* shader translation (for edgeflags), an extra output with
* edgeflag semantics, and extend the vertex shader to pass through
* the input to the output. We'll need to use similar logic to set
* up the extra vertex_element input for edgeflags.
* _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA
*/
key.passthrough_edgeflags = (st->vertdata_edgeflags && (
st->ctx->Polygon.FrontMode != GL_FILL ||
st->ctx->Polygon.BackMode != GL_FILL));
st->vp_varient = st_get_vp_varient(st, stvp, &key);
st_reference_vertprog(st, &st->vp, stvp); st_reference_vertprog(st, &st->vp, stvp);
@@ -234,11 +161,13 @@ const struct st_tracked_state st_update_vp = {
update_vp /* update */ update_vp /* update */
}; };
static void static void
update_gp( struct st_context *st ) update_gp( struct st_context *st )
{ {
struct st_geometry_program *stgp; struct st_geometry_program *stgp;
struct st_gp_varient_key key;
if (!st->ctx->GeometryProgram._Current) { if (!st->ctx->GeometryProgram._Current) {
cso_set_geometry_shader_handle(st->cso_context, NULL); cso_set_geometry_shader_handle(st->cso_context, NULL);
@@ -248,11 +177,15 @@ update_gp( struct st_context *st )
stgp = st_geometry_program(st->ctx->GeometryProgram._Current); stgp = st_geometry_program(st->ctx->GeometryProgram._Current);
assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM); assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM);
translate_gp(st, stgp); memset(&key, 0, sizeof(key));
key.st = st;
st->gp_varient = st_get_gp_varient(st, stgp, &key);
st_reference_geomprog(st, &st->gp, stgp); st_reference_geomprog(st, &st->gp, stgp);
cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader); cso_set_geometry_shader_handle(st->cso_context,
st->gp_varient->driver_shader);
} }
const struct st_tracked_state st_update_gp = { const struct st_tracked_state st_update_gp = {

View File

@@ -185,48 +185,47 @@ find_free_bit(uint bitfield)
/** /**
* Combine basic bitmap fragment program with the user-defined program. * Combine basic bitmap fragment program with the user-defined program.
* \param st current context
* \param fpIn the incoming fragment program
* \param fpOut the new fragment program which does fragment culling
* \param bitmap_sampler sampler number for the bitmap texture
*/ */
static struct st_fragment_program * void
combined_bitmap_fragment_program(struct gl_context *ctx) st_make_bitmap_fragment_program(struct st_context *st,
struct gl_fragment_program *fpIn,
struct gl_fragment_program **fpOut,
GLuint *bitmap_sampler)
{ {
struct st_context *st = st_context(ctx); struct st_fragment_program *bitmap_prog;
struct st_fragment_program *stfp = st->fp; struct gl_program *newProg;
uint sampler;
if (!stfp->bitmap_program) {
/* /*
* Generate new program which is the user-defined program prefixed * Generate new program which is the user-defined program prefixed
* with the bitmap sampler/kill instructions. * with the bitmap sampler/kill instructions.
*/ */
struct st_fragment_program *bitmap_prog; sampler = find_free_bit(fpIn->Base.SamplersUsed);
uint sampler; bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler);
sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
stfp->bitmap_program = (struct st_fragment_program *)
_mesa_combine_programs(ctx,
&bitmap_prog->Base.Base, &stfp->Base.Base);
stfp->bitmap_program->bitmap_sampler = sampler;
newProg = _mesa_combine_programs(st->ctx,
&bitmap_prog->Base.Base,
&fpIn->Base);
/* done with this after combining */ /* done with this after combining */
st_reference_fragprog(st, &bitmap_prog, NULL); st_reference_fragprog(st, &bitmap_prog, NULL);
#if 0 #if 0
{ {
struct gl_program *p = &stfp->bitmap_program->Base.Base;
printf("Combined bitmap program:\n"); printf("Combined bitmap program:\n");
_mesa_print_program(p); _mesa_print_program(newProg);
printf("InputsRead: 0x%x\n", p->InputsRead); printf("InputsRead: 0x%x\n", newProg->InputsRead);
printf("OutputsWritten: 0x%x\n", p->OutputsWritten); printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
_mesa_print_parameter_list(p->Parameters); _mesa_print_parameter_list(newProg->Parameters);
} }
#endif #endif
/* translate to TGSI tokens */ /* return results */
st_translate_fragment_program(st, stfp->bitmap_program); *fpOut = (struct gl_fragment_program *) newProg;
} *bitmap_sampler = sampler;
return stfp->bitmap_program;
} }
@@ -411,11 +410,16 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe; struct pipe_context *pipe = st->pipe;
struct cso_context *cso = st->cso_context; struct cso_context *cso = st->cso_context;
struct st_fragment_program *stfp; struct st_fp_varient *fpv;
struct st_fp_varient_key key;
GLuint maxSize; GLuint maxSize;
GLuint offset; GLuint offset;
stfp = combined_bitmap_fragment_program(ctx); memset(&key, 0, sizeof(key));
key.st = st;
key.bitmap = GL_TRUE;
fpv = st_get_fp_varient(st, st->fp, &key);
/* As an optimization, Mesa's fragment programs will sometimes get the /* As an optimization, Mesa's fragment programs will sometimes get the
* primary color from a statevar/constant rather than a varying variable. * primary color from a statevar/constant rather than a varying variable.
@@ -428,7 +432,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
GLfloat colorSave[4]; GLfloat colorSave[4];
COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
} }
@@ -454,7 +458,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
cso_set_rasterizer(cso, &st->bitmap.rasterizer); cso_set_rasterizer(cso, &st->bitmap.rasterizer);
/* fragment shader state: TEX lookup program */ /* fragment shader state: TEX lookup program */
cso_set_fragment_shader_handle(cso, stfp->driver_shader); cso_set_fragment_shader_handle(cso, fpv->driver_shader);
/* vertex shader state: position + texcoord pass-through */ /* vertex shader state: position + texcoord pass-through */
cso_set_vertex_shader_handle(cso, st->bitmap.vs); cso_set_vertex_shader_handle(cso, st->bitmap.vs);
@@ -462,21 +466,21 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
/* user samplers, plus our bitmap sampler */ /* user samplers, plus our bitmap sampler */
{ {
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers); uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers);
uint i; uint i;
for (i = 0; i < st->state.num_samplers; i++) { for (i = 0; i < st->state.num_samplers; i++) {
samplers[i] = &st->state.samplers[i]; samplers[i] = &st->state.samplers[i];
} }
samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; samplers[fpv->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers); cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
} }
/* user textures, plus the bitmap texture */ /* user textures, plus the bitmap texture */
{ {
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures);
memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views));
sampler_views[stfp->bitmap_sampler] = sv; sampler_views[fpv->bitmap_sampler] = sv;
cso_set_fragment_sampler_views(cso, num, sampler_views); cso_set_fragment_sampler_views(cso, num, sampler_views);
} }

View File

@@ -34,6 +34,8 @@
struct dd_function_table; struct dd_function_table;
struct st_context; struct st_context;
struct gl_fragment_program;
struct st_fragment_program;
#if FEATURE_drawpix #if FEATURE_drawpix
@@ -46,6 +48,12 @@ st_init_bitmap(struct st_context *st);
extern void extern void
st_destroy_bitmap(struct st_context *st); st_destroy_bitmap(struct st_context *st);
extern void
st_make_bitmap_fragment_program(struct st_context *st,
struct gl_fragment_program *fpIn,
struct gl_fragment_program **fpOut,
GLuint *bitmap_sampler);
extern void extern void
st_flush_bitmap_cache(struct st_context *st); st_flush_bitmap_cache(struct st_context *st);

View File

@@ -94,88 +94,61 @@ is_passthrough_program(const struct gl_fragment_program *prog)
/** /**
* Make fragment shader for glDraw/CopyPixels. This shader is made * Make fragment shader for glDraw/CopyPixels. This shader is made
* by combining the pixel transfer shader with the user-defined shader. * 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 * void
combined_drawpix_fragment_program(struct gl_context *ctx) 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 gl_program *newProg;
struct st_fragment_program *stfp;
if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn if (is_passthrough_program(fpIn)) {
&& st->fp->serialNo == st->pixel_xfer.user_prog_sn) { newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx,
/* the pixel tranfer program has not changed and the user-defined &st->pixel_xfer.program->Base);
* program 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 program.
*/
if (is_passthrough_program(&st->fp->Base)) {
stfp = (struct st_fragment_program *)
_mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base);
} }
else { else {
#if 0 #if 0
/* debug */
printf("Base program:\n"); printf("Base program:\n");
_mesa_print_program(&st->fp->Base.Base); _mesa_print_program(&fpIn->Base);
printf("DrawPix program:\n"); printf("DrawPix program:\n");
_mesa_print_program(&st->pixel_xfer.program->Base.Base); _mesa_print_program(&st->pixel_xfer.program->Base.Base);
#endif #endif
stfp = (struct st_fragment_program *) newProg = _mesa_combine_programs(st->ctx,
_mesa_combine_programs(ctx,
&st->pixel_xfer.program->Base.Base, &st->pixel_xfer.program->Base.Base,
&st->fp->Base.Base); &fpIn->Base);
} }
#if 0 #if 0
{ /* debug */
struct gl_program *p = &stfp->Base.Base;
printf("Combined DrawPixels program:\n"); printf("Combined DrawPixels program:\n");
_mesa_print_program(p); _mesa_print_program(newProg);
printf("InputsRead: 0x%x\n", p->InputsRead); printf("InputsRead: 0x%x\n", newProg->InputsRead);
printf("OutputsWritten: 0x%x\n", p->OutputsWritten); printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
_mesa_print_parameter_list(p->Parameters); _mesa_print_parameter_list(newProg->Parameters);
}
#endif #endif
/* translate to TGSI tokens */ *fpOut = (struct gl_fragment_program *) newProg;
st_translate_fragment_program(st, stfp);
/* 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);
return stfp->driver_shader;
} }
/** /**
* 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. * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
* Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
* Pass fragment color through as-is. * Pass fragment color through as-is.
* \return pointer to the Gallium driver fragment shader * \return pointer to the gl_fragment program
*/ */
static void * struct gl_fragment_program *
make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, st_make_drawpix_z_stencil_program(struct st_context *st,
GLboolean write_depth,
GLboolean write_stencil) GLboolean write_stencil)
{ {
struct gl_context *ctx = st->ctx; struct gl_context *ctx = st->ctx;
struct gl_program *p; struct gl_program *p;
struct st_fragment_program *stp; struct gl_fragment_program *fp;
GLuint ic = 0; GLuint ic = 0;
const GLuint shaderIndex = write_depth * 2 + write_stencil; const GLuint shaderIndex = write_depth * 2 + write_stencil;
@@ -183,7 +156,7 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
if (st->drawpix.shaders[shaderIndex]) { if (st->drawpix.shaders[shaderIndex]) {
/* already have the proper shader */ /* already have the proper shader */
return st->drawpix.shaders[shaderIndex]->driver_shader; return st->drawpix.shaders[shaderIndex];
} }
/* /*
@@ -245,18 +218,15 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
if (write_stencil) if (write_stencil)
p->SamplersUsed |= 1 << 1; p->SamplersUsed |= 1 << 1;
stp = st_fragment_program((struct gl_fragment_program *) p); fp = (struct gl_fragment_program *) p;
/* save the new shader */ /* save the new shader */
st->drawpix.shaders[shaderIndex] = stp; st->drawpix.shaders[shaderIndex] = fp;
st_translate_fragment_program(st, stp); return fp;
return stp->driver_shader;
} }
/** /**
* Create a simple vertex shader that just passes through the * Create a simple vertex shader that just passes through the
* vertex position and texcoord (and optionally, color). * vertex position and texcoord (and optionally, color).
@@ -872,6 +842,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() * Called via ctx->Driver.DrawPixels()
*/ */
@@ -889,6 +914,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
struct pipe_sampler_view *sv[2]; struct pipe_sampler_view *sv[2];
int num_sampler_view = 1; int num_sampler_view = 1;
enum pipe_format stencil_format = PIPE_FORMAT_NONE; enum pipe_format stencil_format = PIPE_FORMAT_NONE;
struct st_fp_varient *fpv;
if (format == GL_DEPTH_STENCIL) if (format == GL_DEPTH_STENCIL)
write_stencil = write_depth = GL_TRUE; write_stencil = write_depth = GL_TRUE;
@@ -921,14 +947,25 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
st_validate_state(st); st_validate_state(st);
/*
* Get vertex/fragment shaders
*/
if (write_depth || write_stencil) { 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); driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
color = ctx->Current.RasterColor; color = ctx->Current.RasterColor;
} }
else { 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); driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
color = NULL; color = NULL;
if (st->pixel_xfer.pixelmap_enabled) { if (st->pixel_xfer.pixelmap_enabled) {
sv[1] = st->pixel_xfer.pixelmap_sampler_view; sv[1] = st->pixel_xfer.pixelmap_sampler_view;
@@ -936,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 */ /* draw with textured quad */
{ {
struct pipe_resource *pt struct pipe_resource *pt
@@ -1116,6 +1156,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GLint readX, readY, readW, readH; GLint readX, readY, readW, readH;
GLuint sample_count; GLuint sample_count;
struct gl_pixelstore_attrib pack = ctx->DefaultPacking; struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
struct st_fp_varient *fpv;
st_validate_state(st); st_validate_state(st);
@@ -1125,11 +1166,18 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
return; return;
} }
/*
* Get vertex/fragment shaders
*/
if (type == GL_COLOR) { if (type == GL_COLOR) {
rbRead = st_get_color_read_renderbuffer(ctx); rbRead = st_get_color_read_renderbuffer(ctx);
color = NULL; 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); driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
if (st->pixel_xfer.pixelmap_enabled) { if (st->pixel_xfer.pixelmap_enabled) {
sv[1] = st->pixel_xfer.pixelmap_sampler_view; sv[1] = st->pixel_xfer.pixelmap_sampler_view;
num_sampler_view++; num_sampler_view++;
@@ -1139,10 +1187,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
assert(type == GL_DEPTH); assert(type == GL_DEPTH);
rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 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); 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) if (rbRead->Base.Wrapped)
rbRead = st_renderbuffer(rbRead->Base.Wrapped); rbRead = st_renderbuffer(rbRead->Base.Wrapped);
@@ -1294,7 +1349,7 @@ st_destroy_drawpix(struct st_context *st)
for (i = 0; i < Elements(st->drawpix.shaders); i++) { for (i = 0; i < Elements(st->drawpix.shaders); i++) {
if (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); st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);

View File

@@ -42,6 +42,16 @@ extern void st_init_drawpixels_functions(struct dd_function_table *functions);
extern void extern void
st_destroy_drawpix(struct st_context *st); 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 #else
static INLINE void static INLINE void

View File

@@ -46,8 +46,6 @@
#include "st_cb_program.h" #include "st_cb_program.h"
static GLuint SerialNo = 1;
/** /**
* Called via ctx->Driver.BindProgram() to bind an ARB vertex or * Called via ctx->Driver.BindProgram() to bind an ARB vertex or
@@ -100,8 +98,6 @@ static struct gl_program *st_new_program( struct gl_context *ctx,
case GL_VERTEX_PROGRAM_ARB: { case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program);
prog->serialNo = SerialNo++;
return _mesa_init_vertex_program( ctx, return _mesa_init_vertex_program( ctx,
&prog->Base, &prog->Base,
target, target,
@@ -112,8 +108,6 @@ static struct gl_program *st_new_program( struct gl_context *ctx,
case GL_FRAGMENT_PROGRAM_NV: { case GL_FRAGMENT_PROGRAM_NV: {
struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program); struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program);
prog->serialNo = SerialNo++;
return _mesa_init_fragment_program( ctx, return _mesa_init_fragment_program( ctx,
&prog->Base, &prog->Base,
target, target,
@@ -123,8 +117,6 @@ static struct gl_program *st_new_program( struct gl_context *ctx,
case MESA_GEOMETRY_PROGRAM: { case MESA_GEOMETRY_PROGRAM: {
struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program);
prog->serialNo = SerialNo++;
return _mesa_init_geometry_program( ctx, return _mesa_init_geometry_program( ctx,
&prog->Base, &prog->Base,
target, target,
@@ -152,12 +144,10 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
break; break;
case MESA_GEOMETRY_PROGRAM: case MESA_GEOMETRY_PROGRAM:
{ {
struct st_geometry_program *stgp = (struct st_geometry_program *) prog; struct st_geometry_program *stgp =
(struct st_geometry_program *) prog;
if (stgp->driver_shader) { st_gp_release_varients(st, stgp);
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
stgp->driver_shader = NULL;
}
if (stgp->tgsi.tokens) { if (stgp->tgsi.tokens) {
st_free_tokens((void *) stgp->tgsi.tokens); st_free_tokens((void *) stgp->tgsi.tokens);
@@ -167,23 +157,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
break; break;
case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_ARB:
{ {
struct st_fragment_program *stfp = (struct st_fragment_program *) prog; struct st_fragment_program *stfp =
(struct st_fragment_program *) prog;
if (stfp->driver_shader) { st_fp_release_varients(st, stfp);
cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
stfp->driver_shader = NULL;
}
if (stfp->tgsi.tokens) { if (stfp->tgsi.tokens) {
st_free_tokens(stfp->tgsi.tokens); st_free_tokens(stfp->tgsi.tokens);
stfp->tgsi.tokens = NULL; stfp->tgsi.tokens = NULL;
} }
if (stfp->bitmap_program) {
struct gl_program *prg = &stfp->bitmap_program->Base.Base;
_mesa_reference_program(ctx, &prg, NULL);
stfp->bitmap_program = NULL;
}
} }
break; break;
default: default:
@@ -212,12 +194,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx,
if (target == GL_FRAGMENT_PROGRAM_ARB) { if (target == GL_FRAGMENT_PROGRAM_ARB) {
struct st_fragment_program *stfp = (struct st_fragment_program *) prog; struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
stfp->serialNo++; st_fp_release_varients(st, stfp);
if (stfp->driver_shader) {
cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
stfp->driver_shader = NULL;
}
if (stfp->tgsi.tokens) { if (stfp->tgsi.tokens) {
st_free_tokens(stfp->tgsi.tokens); st_free_tokens(stfp->tgsi.tokens);
@@ -230,12 +207,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx,
else if (target == MESA_GEOMETRY_PROGRAM) { else if (target == MESA_GEOMETRY_PROGRAM) {
struct st_geometry_program *stgp = (struct st_geometry_program *) prog; struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
stgp->serialNo++; st_gp_release_varients(st, stgp);
if (stgp->driver_shader) {
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
stgp->driver_shader = NULL;
}
if (stgp->tgsi.tokens) { if (stgp->tgsi.tokens) {
st_free_tokens((void *) stgp->tgsi.tokens); st_free_tokens((void *) stgp->tgsi.tokens);
@@ -248,8 +220,6 @@ static GLboolean st_program_string_notify( struct gl_context *ctx,
else if (target == GL_VERTEX_PROGRAM_ARB) { else if (target == GL_VERTEX_PROGRAM_ARB) {
struct st_vertex_program *stvp = (struct st_vertex_program *) prog; struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
stvp->serialNo++;
st_vp_release_varients( st, stvp ); st_vp_release_varients( st, stvp );
if (st->vp == stvp) if (st->vp == stvp)

View File

@@ -252,6 +252,8 @@ void st_destroy_context( struct st_context *st )
_vbo_DestroyContext(st->ctx); _vbo_DestroyContext(st->ctx);
st_destroy_program_variants(st);
_mesa_free_context_data(ctx); _mesa_free_context_data(ctx);
st_destroy_context_priv(st); st_destroy_context_priv(st);

View File

@@ -131,6 +131,8 @@ struct st_context
struct st_geometry_program *gp; /**< Currently bound geometry program */ struct st_geometry_program *gp; /**< Currently bound geometry program */
struct st_vp_varient *vp_varient; struct st_vp_varient *vp_varient;
struct st_fp_varient *fp_varient;
struct st_gp_varient *gp_varient;
struct gl_texture_object *default_texture; struct gl_texture_object *default_texture;
@@ -160,7 +162,7 @@ struct st_context
/** for glDraw/CopyPixels */ /** for glDraw/CopyPixels */
struct { struct {
struct st_fragment_program *shaders[4]; struct gl_fragment_program *shaders[4];
void *vert_shaders[2]; /**< ureg shaders */ void *vert_shaders[2]; /**< ureg shaders */
} drawpix; } drawpix;

View File

@@ -32,7 +32,9 @@
#include "main/imports.h" #include "main/imports.h"
#include "main/hash.h"
#include "main/mtypes.h" #include "main/mtypes.h"
#include "program/prog_parameter.h"
#include "program/prog_print.h" #include "program/prog_print.h"
#include "program/programopt.h" #include "program/programopt.h"
@@ -44,6 +46,8 @@
#include "tgsi/tgsi_ureg.h" #include "tgsi/tgsi_ureg.h"
#include "st_debug.h" #include "st_debug.h"
#include "st_cb_bitmap.h"
#include "st_cb_drawpixels.h"
#include "st_context.h" #include "st_context.h"
#include "st_program.h" #include "st_program.h"
#include "st_mesa_to_tgsi.h" #include "st_mesa_to_tgsi.h"
@@ -51,6 +55,29 @@
/**
* Delete a vertex program varient. Note the caller must unlink
* the varient from the linked list.
*/
static void
delete_vp_varient(struct st_context *st, struct st_vp_varient *vpv)
{
if (vpv->driver_shader)
cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
#if FEATURE_feedback || FEATURE_rastpos
if (vpv->draw_shader)
draw_delete_vertex_shader( st->draw, vpv->draw_shader );
#endif
if (vpv->tgsi.tokens)
st_free_tokens(vpv->tgsi.tokens);
FREE( vpv );
}
/** /**
* Clean out any old compilations: * Clean out any old compilations:
*/ */
@@ -62,20 +89,7 @@ st_vp_release_varients( struct st_context *st,
for (vpv = stvp->varients; vpv; ) { for (vpv = stvp->varients; vpv; ) {
struct st_vp_varient *next = vpv->next; struct st_vp_varient *next = vpv->next;
delete_vp_varient(st, vpv);
if (vpv->driver_shader)
cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
#if FEATURE_feedback || FEATURE_rastpos
if (vpv->draw_shader)
draw_delete_vertex_shader( st->draw, vpv->draw_shader );
#endif
if (vpv->tgsi.tokens)
st_free_tokens(vpv->tgsi.tokens);
FREE( vpv );
vpv = next; vpv = next;
} }
@@ -84,6 +98,71 @@ st_vp_release_varients( struct st_context *st,
/**
* Delete a fragment program varient. Note the caller must unlink
* the varient from the linked list.
*/
static void
delete_fp_varient(struct st_context *st, struct st_fp_varient *fpv)
{
if (fpv->driver_shader)
cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
FREE(fpv);
}
/**
* Free all varients of a fragment program.
*/
void
st_fp_release_varients(struct st_context *st, struct st_fragment_program *stfp)
{
struct st_fp_varient *fpv;
for (fpv = stfp->varients; fpv; ) {
struct st_fp_varient *next = fpv->next;
delete_fp_varient(st, fpv);
fpv = next;
}
stfp->varients = NULL;
}
/**
* Delete a geometry program varient. Note the caller must unlink
* the varient from the linked list.
*/
static void
delete_gp_varient(struct st_context *st, struct st_gp_varient *gpv)
{
if (gpv->driver_shader)
cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
FREE(gpv);
}
/**
* Free all varients of a geometry program.
*/
void
st_gp_release_varients(struct st_context *st, struct st_geometry_program *stgp)
{
struct st_gp_varient *gpv;
for (gpv = stgp->varients; gpv; ) {
struct st_gp_varient *next = gpv->next;
delete_gp_varient(st, gpv);
gpv = next;
}
stgp->varients = NULL;
}
/** /**
* Translate a Mesa vertex shader into a TGSI shader. * Translate a Mesa vertex shader into a TGSI shader.
@@ -92,7 +171,7 @@ st_vp_release_varients( struct st_context *st,
* \param tokensOut destination for TGSI tokens * \param tokensOut destination for TGSI tokens
* \return pointer to cached pipe_shader object. * \return pointer to cached pipe_shader object.
*/ */
void static void
st_prepare_vertex_program(struct st_context *st, st_prepare_vertex_program(struct st_context *st,
struct st_vertex_program *stvp) struct st_vertex_program *stvp)
{ {
@@ -196,7 +275,10 @@ st_prepare_vertex_program(struct st_context *st,
} }
struct st_vp_varient * /**
* Translate a vertex program to create a new varient.
*/
static struct st_vp_varient *
st_translate_vertex_program(struct st_context *st, st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp, struct st_vertex_program *stvp,
const struct st_vp_varient_key *key) const struct st_vp_varient_key *key)
@@ -207,6 +289,8 @@ st_translate_vertex_program(struct st_context *st,
enum pipe_error error; enum pipe_error error;
unsigned num_outputs; unsigned num_outputs;
st_prepare_vertex_program( st, stvp );
_mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
_mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING); _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
@@ -277,16 +361,83 @@ fail:
} }
/**
* Find/create a vertex program varient.
*/
struct st_vp_varient *
st_get_vp_varient(struct st_context *st,
struct st_vertex_program *stvp,
const struct st_vp_varient_key *key)
{
struct st_vp_varient *vpv;
/* Search for existing varient */
for (vpv = stvp->varients; vpv; vpv = vpv->next) {
if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
break;
}
}
if (!vpv) {
/* create now */
vpv = st_translate_vertex_program(st, stvp, key);
if (vpv) {
/* insert into list */
vpv->next = stvp->varients;
stvp->varients = vpv;
}
}
return vpv;
}
/** /**
* Translate a Mesa fragment shader into a TGSI shader. * Translate a Mesa fragment shader into a TGSI shader using extra info in
* \return pointer to cached pipe_shader object. * the key.
* \return new fragment program variant
*/ */
void static struct st_fp_varient *
st_translate_fragment_program(struct st_context *st, st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *stfp ) struct st_fragment_program *stfp,
const struct st_fp_varient_key *key)
{ {
struct pipe_context *pipe = st->pipe; struct pipe_context *pipe = st->pipe;
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_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 */
GLuint outputMapping[FRAG_RESULT_MAX]; GLuint outputMapping[FRAG_RESULT_MAX];
GLuint inputMapping[FRAG_ATTRIB_MAX]; GLuint inputMapping[FRAG_ATTRIB_MAX];
GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
@@ -303,6 +454,7 @@ st_translate_fragment_program(struct st_context *st,
ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
uint fs_num_outputs = 0; uint fs_num_outputs = 0;
_mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
/* /*
@@ -434,7 +586,7 @@ st_translate_fragment_program(struct st_context *st,
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL) if (ureg == NULL)
return; return NULL;
if (ST_DEBUG & DEBUG_MESA) { if (ST_DEBUG & DEBUG_MESA) {
_mesa_print_program(&stfp->Base.Base); _mesa_print_program(&stfp->Base.Base);
@@ -442,8 +594,7 @@ st_translate_fragment_program(struct st_context *st,
debug_printf("\n"); debug_printf("\n");
} }
error = error = st_translate_mesa_program(st->ctx,
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_FRAGMENT, TGSI_PROCESSOR_FRAGMENT,
ureg, ureg,
&stfp->Base.Base, &stfp->Base.Base,
@@ -461,17 +612,59 @@ st_translate_fragment_program(struct st_context *st,
stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
ureg_destroy( ureg ); ureg_destroy( ureg );
stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); }
/* fill in varient */
varient->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
varient->key = *key;
if (ST_DEBUG & DEBUG_TGSI) { if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
debug_printf("\n"); debug_printf("\n");
} }
return varient;
} }
void
/**
* Translate fragment program if needed.
*/
struct st_fp_varient *
st_get_fp_varient(struct st_context *st,
struct st_fragment_program *stfp,
const struct st_fp_varient_key *key)
{
struct st_fp_varient *fpv;
/* Search for existing varient */
for (fpv = stfp->varients; fpv; fpv = fpv->next) {
if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
break;
}
}
if (!fpv) {
/* create new */
fpv = st_translate_fragment_program(st, stfp, key);
if (fpv) {
/* insert into list */
fpv->next = stfp->varients;
stfp->varients = fpv;
}
}
return fpv;
}
/**
* Translate a geometry program to create a new varient.
*/
static struct st_gp_varient *
st_translate_geometry_program(struct st_context *st, st_translate_geometry_program(struct st_context *st,
struct st_geometry_program *stgp) struct st_geometry_program *stgp,
const struct st_gp_varient_key *key)
{ {
GLuint inputMapping[GEOM_ATTRIB_MAX]; GLuint inputMapping[GEOM_ATTRIB_MAX];
GLuint outputMapping[GEOM_RESULT_MAX]; GLuint outputMapping[GEOM_RESULT_MAX];
@@ -494,12 +687,19 @@ st_translate_geometry_program(struct st_context *st,
GLuint maxSlot = 0; GLuint maxSlot = 0;
struct ureg_program *ureg; struct ureg_program *ureg;
struct st_gp_varient *gpv;
gpv = CALLOC_STRUCT(st_gp_varient);
if (!gpv)
return NULL;
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
if (ureg == NULL) { if (ureg == NULL) {
return; FREE(gpv);
return NULL;
} }
/* which vertex output goes to the first geometry input */ /* which vertex output goes to the first geometry input */
@@ -529,7 +729,7 @@ st_translate_geometry_program(struct st_context *st,
} else } else
++gs_builtin_inputs; ++gs_builtin_inputs;
#if 1 #if 0
debug_printf("input map at %d = %d\n", debug_printf("input map at %d = %d\n",
slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
#endif #endif
@@ -671,10 +871,6 @@ st_translate_geometry_program(struct st_context *st,
st_free_tokens(stgp->tgsi.tokens); st_free_tokens(stgp->tgsi.tokens);
stgp->tgsi.tokens = NULL; stgp->tgsi.tokens = NULL;
} }
if (stgp->driver_shader) {
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
stgp->driver_shader = NULL;
}
ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
@@ -697,11 +893,13 @@ st_translate_geometry_program(struct st_context *st,
gs_output_semantic_index, gs_output_semantic_index,
FALSE); FALSE);
stgp->num_inputs = gs_num_inputs; stgp->num_inputs = gs_num_inputs;
stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
ureg_destroy( ureg ); ureg_destroy( ureg );
stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
/* fill in new varient */
gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
gpv->key = *key;
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
_mesa_print_program(&stgp->Base.Base); _mesa_print_program(&stgp->Base.Base);
@@ -712,8 +910,44 @@ st_translate_geometry_program(struct st_context *st,
tgsi_dump(stgp->tgsi.tokens, 0); tgsi_dump(stgp->tgsi.tokens, 0);
debug_printf("\n"); debug_printf("\n");
} }
return gpv;
} }
/**
* Get/create geometry program variant.
*/
struct st_gp_varient *
st_get_gp_varient(struct st_context *st,
struct st_geometry_program *stgp,
const struct st_gp_varient_key *key)
{
struct st_gp_varient *gpv;
/* Search for existing varient */
for (gpv = stgp->varients; gpv; gpv = gpv->next) {
if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
break;
}
}
if (!gpv) {
/* create new */
gpv = st_translate_geometry_program(st, stgp, key);
if (gpv) {
/* insert into list */
gpv->next = stgp->varients;
stgp->varients = gpv;
}
}
return gpv;
}
/** /**
* Debug- print current shader text * Debug- print current shader text
*/ */
@@ -759,3 +993,134 @@ st_print_shaders(struct gl_context *ctx)
} }
} }
} }
/**
* Vert/Geom/Frag programs have per-context variants. Free all the
* variants attached to the given program which match the given context.
*/
static void
destroy_program_variants(struct st_context *st, struct gl_program *program)
{
if (!program)
return;
switch (program->Target) {
case GL_VERTEX_PROGRAM_ARB:
{
struct st_vertex_program *stvp = (struct st_vertex_program *) program;
struct st_vp_varient *vpv, **prev = &stvp->varients;
for (vpv = stvp->varients; vpv; ) {
struct st_vp_varient *next = vpv->next;
if (vpv->key.st == st) {
/* unlink from list */
*prev = next;
/* destroy this variant */
delete_vp_varient(st, vpv);
}
else {
prev = &vpv;
}
vpv = next;
}
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
{
struct st_fragment_program *stfp =
(struct st_fragment_program *) program;
struct st_fp_varient *fpv, **prev = &stfp->varients;
for (fpv = stfp->varients; fpv; ) {
struct st_fp_varient *next = fpv->next;
if (fpv->key.st == st) {
/* unlink from list */
*prev = next;
/* destroy this variant */
delete_fp_varient(st, fpv);
}
else {
prev = &fpv;
}
fpv = next;
}
}
break;
default:
_mesa_problem(NULL, "Unexpected program target in "
"destroy_program_variants_cb()");
}
}
/**
* Callback for _mesa_HashWalk. Free all the shader's program variants
* which match the given context.
*/
static void
destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
{
struct st_context *st = (struct st_context *) userData;
struct gl_shader *shader = (struct gl_shader *) data;
switch (shader->Type) {
case GL_SHADER_PROGRAM_MESA:
{
struct gl_shader_program *shProg = (struct gl_shader_program *) data;
GLuint i;
for (i = 0; i < shProg->NumShaders; i++) {
destroy_program_variants(st, shProg->Shaders[i]->Program);
}
destroy_program_variants(st, (struct gl_program *)
shProg->VertexProgram);
destroy_program_variants(st, (struct gl_program *)
shProg->FragmentProgram);
destroy_program_variants(st, (struct gl_program *)
shProg->GeometryProgram);
}
break;
case GL_VERTEX_SHADER:
case GL_FRAGMENT_SHADER:
case GL_GEOMETRY_SHADER:
{
destroy_program_variants(st, shader->Program);
}
break;
default:
assert(0);
}
}
/**
* Callback for _mesa_HashWalk. Free all the program variants which match
* the given context.
*/
static void
destroy_program_variants_cb(GLuint key, void *data, void *userData)
{
struct st_context *st = (struct st_context *) userData;
struct gl_program *program = (struct gl_program *) data;
destroy_program_variants(st, program);
}
/**
* Walk over all shaders and programs to delete any variants which
* belong to the given context.
* This is called during context tear-down.
*/
void
st_destroy_program_variants(struct st_context *st)
{
/* ARB vert/frag program */
_mesa_HashWalk(st->ctx->Shared->Programs,
destroy_program_variants_cb, st);
/* GLSL vert/frag/geom shaders */
_mesa_HashWalk(st->ctx->Shared->ShaderObjects,
destroy_shader_program_variants_cb, st);
}

View File

@@ -40,26 +40,60 @@
#include "st_context.h" #include "st_context.h"
/** Fragment program variant key */
struct st_fp_varient_key
{
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) */
};
/**
* Variant of a fragment program.
*/
struct st_fp_varient
{
/** Parameters which generated this version of fragment program */
struct st_fp_varient_key key;
/** Driver's compiled shader */
void *driver_shader;
/** For glBitmap variants */
struct gl_program_parameter_list *parameters;
uint bitmap_sampler;
/** next in linked list */
struct st_fp_varient *next;
};
/** /**
* Derived from Mesa gl_fragment_program: * Derived from Mesa gl_fragment_program:
*/ */
struct st_fragment_program struct st_fragment_program
{ {
struct gl_fragment_program Base; struct gl_fragment_program Base;
GLuint serialNo;
struct pipe_shader_state tgsi; struct pipe_shader_state tgsi;
void *driver_shader;
/** Program prefixed with glBitmap prologue */ struct st_fp_varient *varients;
struct st_fragment_program *bitmap_program;
uint bitmap_sampler;
}; };
struct st_vp_varient_key struct st_vp_varient_key
{ {
struct st_context *st; /**< variants are per-context */
boolean passthrough_edgeflags; boolean passthrough_edgeflags;
}; };
@@ -101,7 +135,6 @@ struct st_vp_varient
struct st_vertex_program struct st_vertex_program
{ {
struct gl_vertex_program Base; /**< The Mesa vertex program */ struct gl_vertex_program Base; /**< The Mesa vertex program */
GLuint serialNo, lastSerialNo;
/** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
GLuint input_to_index[VERT_ATTRIB_MAX]; GLuint input_to_index[VERT_ATTRIB_MAX];
@@ -120,13 +153,35 @@ struct st_vertex_program
struct st_vp_varient *varients; struct st_vp_varient *varients;
}; };
struct st_gp_varient_key
{
struct st_context *st; /**< variants are per-context */
/* no other fields yet */
};
/**
* Geometry program variant.
*/
struct st_gp_varient
{
/* Parameters which generated this translated version of a vertex */
struct st_gp_varient_key key;
void *driver_shader;
struct st_gp_varient *next;
};
/** /**
* Derived from Mesa gl_geometry_program: * Derived from Mesa gl_geometry_program:
*/ */
struct st_geometry_program struct st_geometry_program
{ {
struct gl_geometry_program Base; /**< The Mesa geometry program */ struct gl_geometry_program Base; /**< The Mesa geometry program */
GLuint serialNo;
/** map GP input back to VP output */ /** map GP input back to VP output */
GLuint input_map[PIPE_MAX_SHADER_INPUTS]; GLuint input_map[PIPE_MAX_SHADER_INPUTS];
@@ -145,9 +200,12 @@ struct st_geometry_program
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
struct pipe_shader_state tgsi; struct pipe_shader_state tgsi;
void *driver_shader;
struct st_gp_varient *varients;
}; };
static INLINE struct st_fragment_program * static INLINE struct st_fragment_program *
st_fragment_program( struct gl_fragment_program *fp ) st_fragment_program( struct gl_fragment_program *fp )
{ {
@@ -198,32 +256,43 @@ st_reference_fragprog(struct st_context *st,
} }
extern void
st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *fp);
extern void
st_translate_geometry_program(struct st_context *st,
struct st_geometry_program *stgp);
/* Called after program string change, discard all previous
* compilation results.
*/
extern void
st_prepare_vertex_program(struct st_context *st,
struct st_vertex_program *stvp);
extern struct st_vp_varient * extern struct st_vp_varient *
st_translate_vertex_program(struct st_context *st, st_get_vp_varient(struct st_context *st,
struct st_vertex_program *stvp, struct st_vertex_program *stvp,
const struct st_vp_varient_key *key); const struct st_vp_varient_key *key);
void
extern struct st_fp_varient *
st_get_fp_varient(struct st_context *st,
struct st_fragment_program *stfp,
const struct st_fp_varient_key *key);
extern struct st_gp_varient *
st_get_gp_varient(struct st_context *st,
struct st_geometry_program *stgp,
const struct st_gp_varient_key *key);
extern void
st_vp_release_varients( struct st_context *st, st_vp_release_varients( struct st_context *st,
struct st_vertex_program *stvp ); struct st_vertex_program *stvp );
extern void
st_fp_release_varients( struct st_context *st,
struct st_fragment_program *stfp );
extern void
st_gp_release_varients(struct st_context *st,
struct st_geometry_program *stgp);
extern void extern void
st_print_shaders(struct gl_context *ctx); st_print_shaders(struct gl_context *ctx);
extern void
st_destroy_program_variants(struct st_context *st);
#endif #endif