[Mesa-dev] [PATCH 06/22] gallium/u_blitter: accelerate stencil-only copying

Marek Olšák maraeo at gmail.com
Mon Jul 9 12:15:39 PDT 2012


This doesn't seem to be used by anything yet, but better safe than sorry.
---
 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(-)

diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 31f3139..b8bf322 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 545b607..3476b6c 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -265,6 +265,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.
  */
 void *
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index 54d0efe..0764998 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -81,6 +81,12 @@ util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
 
 
 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);
 
 
-- 
1.7.9.5



More information about the mesa-dev mailing list