From bdaf0a085ba7b8af4cf858b31f701caf571b7c4f Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sun, 8 Jul 2012 00:06:27 +0200 Subject: gallium/u_blitter: accelerate stencil-only copying This doesn't seem to be used by anything yet, but better safe than sorry. Reviewed-by: Alex Deucher --- src/gallium/auxiliary/util/u_blitter.c | 28 +++++++++++++++- src/gallium/auxiliary/util/u_simple_shaders.c | 46 +++++++++++++++++++++++++++ src/gallium/auxiliary/util/u_simple_shaders.h | 6 ++++ 3 files changed, 79 insertions(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index b422ff8faed..590a6aad817 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -79,6 +79,7 @@ struct blitter_context_priv where the index is PIPE_TEXTURE_* to be sampled. */ void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES]; void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES]; + void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES]; /* Blend state. */ void *blend_write_color; /**< blend state with writemask of RGBA */ @@ -322,6 +323,8 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); if (ctx->fs_texfetch_depthstencil[i]) pipe->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); + if (ctx->fs_texfetch_stencil[i]) + pipe->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); } for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) { @@ -746,6 +749,26 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, return ctx->fs_texfetch_depthstencil[tex_target]; } +static INLINE +void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, + unsigned tex_target) +{ + struct pipe_context *pipe = ctx->base.pipe; + + assert(tex_target < PIPE_MAX_TEXTURE_TYPES); + + /* Create the fragment shader on-demand. */ + if (!ctx->fs_texfetch_stencil[tex_target]) { + unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target); + + ctx->fs_texfetch_stencil[tex_target] = + util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex, + TGSI_INTERPOLATE_LINEAR); + } + + return ctx->fs_texfetch_stencil[tex_target]; +} + static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx) { struct pipe_context *pipe = ctx->base.pipe; @@ -1056,7 +1079,10 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, pipe->bind_fs_state(pipe, blitter_get_fs_texfetch_depth(ctx, src_target)); } else { /* is_stencil */ - assert(0); + pipe->bind_depth_stencil_alpha_state(pipe, + ctx->dsa_keep_depth_write_stencil); + pipe->bind_fs_state(pipe, + blitter_get_fs_texfetch_stencil(ctx, src_target)); } fb_state.nr_cbufs = 0; diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 545b6078667..3476b6ce0ca 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -264,6 +264,52 @@ util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe, } +/** + * Make a simple fragment texture shader which reads a texture and writes it + * as stencil. + */ +void * +util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode) +{ + struct ureg_program *ureg; + struct ureg_src stencil_sampler; + struct ureg_src tex; + struct ureg_dst out, stencil; + struct ureg_src imm; + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + stencil_sampler = ureg_DECL_sampler( ureg, 0 ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + interp_mode ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + stencil = ureg_DECL_output( ureg, + TGSI_SEMANTIC_STENCIL, + 0 ); + + imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); + + ureg_MOV( ureg, out, imm ); + + ureg_TEX( ureg, + ureg_writemask(stencil, TGSI_WRITEMASK_Y), + tex_target, tex, stencil_sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); +} + + /** * Make simple fragment color pass-through shader. */ diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h index 54d0efe63d7..0764998a338 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/src/gallium/auxiliary/util/u_simple_shaders.h @@ -80,6 +80,12 @@ util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe, unsigned interp_mode); +extern void * +util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, + unsigned tex_target, + unsigned interp_mode); + + extern void * util_make_fragment_passthrough_shader(struct pipe_context *pipe); -- cgit v1.2.3