Module: Mesa Branch: st-mesa-per-context-shaders Commit: c5751c673644808ab069259a852f24c4c0e92b9d URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=c5751c673644808ab069259a852f24c4c0e92b9d
Author: Brian Paul <bri...@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; }; _______________________________________________ mesa-commit mailing list mesa-commit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-commit