gallium/u_blitter: facilitate co-existence with the Draw module
authorMarek Olšák <maraeo@gmail.com>
Wed, 12 Sep 2012 21:14:57 +0000 (23:14 +0200)
committerMarek Olšák <maraeo@gmail.com>
Sun, 30 Sep 2012 16:57:56 +0000 (18:57 +0200)
Tested-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h

index b94366b998d81eb3e1cd8a2708cd23f37e513ae4..3f0d1b17d01633176f795c23e3a45fc93ee29719 100644 (file)
@@ -122,8 +122,12 @@ struct blitter_context_priv
    boolean has_stream_out;
    boolean has_stencil_export;
    boolean has_texture_multisample;
-};
 
+   /* The Draw module overrides these functions.
+    * Always create the blitter before Draw. */
+   void   (*bind_fs_state)(struct pipe_context *, void *);
+   void   (*delete_fs_state)(struct pipe_context *, void *);
+};
 
 struct blitter_context *util_blitter_create(struct pipe_context *pipe)
 {
@@ -142,6 +146,9 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
    ctx->base.pipe = pipe;
    ctx->base.draw_rectangle = util_blitter_draw_rectangle;
 
+   ctx->bind_fs_state = pipe->bind_fs_state;
+   ctx->delete_fs_state = pipe->delete_fs_state;
+
    /* init state objects for them to be considered invalid */
    ctx->base.saved_blend_state = INVALID_PTR;
    ctx->base.saved_dsa_state = INVALID_PTR;
@@ -321,20 +328,20 @@ void util_blitter_destroy(struct blitter_context *blitter)
 
    for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
       if (ctx->fs_texfetch_col[i])
-         pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
+         ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
       if (ctx->fs_texfetch_depth[i])
-         pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
+         ctx->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]);
+         ctx->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]);
+         ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]);
    }
 
    for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) {
       if (ctx->fs_col[i])
-         pipe->delete_fs_state(pipe, ctx->fs_col[i]);
+         ctx->delete_fs_state(pipe, ctx->fs_col[i]);
       if (ctx->fs_col_int[i])
-         pipe->delete_fs_state(pipe, ctx->fs_col_int[i]);
+         ctx->delete_fs_state(pipe, ctx->fs_col_int[i]);
    }
 
    pipe->delete_sampler_state(pipe, ctx->sampler_state);
@@ -431,7 +438,7 @@ static void blitter_restore_fragment_states(struct blitter_context_priv *ctx)
    struct pipe_context *pipe = ctx->base.pipe;
 
    /* Fragment shader. */
-   pipe->bind_fs_state(pipe, ctx->base.saved_fs);
+   ctx->bind_fs_state(pipe, ctx->base.saved_fs);
    ctx->base.saved_fs = INVALID_PTR;
 
    /* Depth, stencil, alpha. */
@@ -657,9 +664,8 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
    ctx->dst_height = height;
 }
 
-static INLINE
-void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
-                         boolean int_format)
+static void *blitter_get_fs_col(struct blitter_context_priv *ctx,
+                                unsigned num_cbufs, boolean int_format)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
@@ -682,32 +688,32 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
    }
 }
 
-static INLINE
-void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
-                                  struct pipe_resource *tex)
+static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
+                                         enum pipe_texture_target target,
+                                         unsigned nr_samples)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
-   assert(tex->target < PIPE_MAX_TEXTURE_TYPES);
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
 
-   if (tex->nr_samples > 1) {
-      void **shader = &ctx->fs_texfetch_col_msaa[tex->target];
+   if (nr_samples > 1) {
+      void **shader = &ctx->fs_texfetch_col_msaa[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target,
-                                                       tex->nr_samples);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
+                                                       nr_samples);
 
          *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex);
       }
 
       return *shader;
    } else {
-      void **shader = &ctx->fs_texfetch_col[tex->target];
+      void **shader = &ctx->fs_texfetch_col[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
          *shader =
             util_make_fragment_tex_shader(pipe, tgsi_tex,
@@ -720,19 +726,20 @@ void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
 
 static INLINE
 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
-                                    struct pipe_resource *tex)
+                                    enum pipe_texture_target target,
+                                    unsigned nr_samples)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
-   assert(tex->target < PIPE_MAX_TEXTURE_TYPES);
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
 
-   if (tex->nr_samples > 1) {
-      void **shader = &ctx->fs_texfetch_depth_msaa[tex->target];
+   if (nr_samples > 1) {
+      void **shader = &ctx->fs_texfetch_depth_msaa[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target,
-                                                       tex->nr_samples);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
+                                                       nr_samples);
 
          *shader =
             util_make_fs_blit_msaa_depth(pipe, tgsi_tex);
@@ -740,11 +747,11 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
 
       return *shader;
    } else {
-      void **shader = &ctx->fs_texfetch_depth[tex->target];
+      void **shader = &ctx->fs_texfetch_depth[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
          *shader =
             util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
@@ -757,19 +764,20 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
 
 static INLINE
 void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
-                                           struct pipe_resource *tex)
+                                           enum pipe_texture_target target,
+                                           unsigned nr_samples)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
-   assert(tex->target < PIPE_MAX_TEXTURE_TYPES);
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
 
-   if (tex->nr_samples > 1) {
-      void **shader = &ctx->fs_texfetch_depthstencil_msaa[tex->target];
+   if (nr_samples > 1) {
+      void **shader = &ctx->fs_texfetch_depthstencil_msaa[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target,
-                                                       tex->nr_samples);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
+                                                       nr_samples);
 
          *shader =
             util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);
@@ -777,11 +785,11 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
 
       return *shader;
    } else {
-      void **shader = &ctx->fs_texfetch_depthstencil[tex->target];
+      void **shader = &ctx->fs_texfetch_depthstencil[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
          *shader =
             util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
@@ -794,19 +802,20 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
 
 static INLINE
 void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
-                                      struct pipe_resource *tex)
+                                      enum pipe_texture_target target,
+                                      unsigned nr_samples)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
-   assert(tex->target < PIPE_MAX_TEXTURE_TYPES);
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
 
-   if (tex->nr_samples > 1) {
-      void **shader = &ctx->fs_texfetch_stencil_msaa[tex->target];
+   if (nr_samples > 1) {
+      void **shader = &ctx->fs_texfetch_stencil_msaa[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target,
-                                                       tex->nr_samples);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
+                                                       nr_samples);
 
          *shader =
             util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);
@@ -814,11 +823,11 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
 
       return *shader;
    } else {
-      void **shader = &ctx->fs_texfetch_stencil[tex->target];
+      void **shader = &ctx->fs_texfetch_stencil[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0);
+         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
          *shader =
             util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
@@ -829,6 +838,43 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
    }
 }
 
+void util_blitter_cache_all_shaders(struct blitter_context *blitter)
+{
+   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+   struct pipe_screen *screen = blitter->pipe->screen;
+   unsigned num_cbufs, i, target, max_samples;
+   boolean has_arraytex;
+
+   num_cbufs = MAX2(screen->get_param(screen,
+                                      PIPE_CAP_MAX_RENDER_TARGETS), 1);
+   max_samples = ctx->has_texture_multisample ? 2 : 1;
+   has_arraytex = screen->get_param(screen,
+                                    PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0;
+
+   for (i = 0; i < num_cbufs; i++) {
+      blitter_get_fs_col(ctx, i, FALSE);
+      blitter_get_fs_col(ctx, i, TRUE);
+   }
+
+   /* It only matters if i <= 1 or > 1. */
+   for (i = 1; i <= max_samples; i++) {
+      for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) {
+         if (!has_arraytex &&
+             (target == PIPE_TEXTURE_1D_ARRAY ||
+              target == PIPE_TEXTURE_2D_ARRAY)) {
+            continue;
+         }
+
+         blitter_get_fs_texfetch_col(ctx, target, i);
+         blitter_get_fs_texfetch_depth(ctx, target, i);
+         if (ctx->has_stencil_export) {
+            blitter_get_fs_texfetch_depthstencil(ctx, target, i);
+            blitter_get_fs_texfetch_stencil(ctx, target, i);
+         }
+      }
+   }
+}
+
 static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx)
 {
    struct pipe_context *pipe = ctx->base.pipe;
@@ -933,7 +979,7 @@ static void util_blitter_clear_custom(struct blitter_context *blitter,
    } else {
       pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
    }
-   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format));
+   ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format));
    pipe->set_sample_mask(pipe, ~0);
 
    blitter_set_common_draw_rect_state(ctx);
@@ -1177,18 +1223,21 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
       if (blit_depth && blit_stencil) {
          pipe->bind_depth_stencil_alpha_state(pipe,
                                               ctx->dsa_write_depth_stencil);
-         pipe->bind_fs_state(pipe,
-               blitter_get_fs_texfetch_depthstencil(ctx, src->texture));
+         ctx->bind_fs_state(pipe,
+               blitter_get_fs_texfetch_depthstencil(ctx, src->texture->target,
+                                                    src->texture->nr_samples));
       } else if (blit_depth) {
          pipe->bind_depth_stencil_alpha_state(pipe,
                                               ctx->dsa_write_depth_keep_stencil);
-         pipe->bind_fs_state(pipe,
-               blitter_get_fs_texfetch_depth(ctx, src->texture));
+         ctx->bind_fs_state(pipe,
+               blitter_get_fs_texfetch_depth(ctx, src->texture->target,
+                                             src->texture->nr_samples));
       } else { /* is_stencil */
          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->texture));
+         ctx->bind_fs_state(pipe,
+               blitter_get_fs_texfetch_stencil(ctx, src->texture->target,
+                                               src->texture->nr_samples));
       }
 
       fb_state.nr_cbufs = 0;
@@ -1196,8 +1245,9 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
    } else {
       pipe->bind_blend_state(pipe, ctx->blend_write_color);
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
-      pipe->bind_fs_state(pipe,
-            blitter_get_fs_texfetch_col(ctx, src->texture));
+      ctx->bind_fs_state(pipe,
+            blitter_get_fs_texfetch_col(ctx, src->texture->target,
+                                        src->texture->nr_samples));
 
       fb_state.nr_cbufs = 1;
       fb_state.cbufs[0] = dst;
@@ -1306,7 +1356,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
    /* bind states */
    pipe->bind_blend_state(pipe, ctx->blend_write_color);
    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
-   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
+   ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
    /* set a framebuffer state */
@@ -1372,7 +1422,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
       /* hmm that should be illegal probably, or make it a no-op somewhere */
       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
 
-   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
+   ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
    /* set a framebuffer state */
@@ -1419,7 +1469,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
    /* bind states */
    pipe->bind_blend_state(pipe, ctx->blend_write_color);
    pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
-   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
+   ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
    /* set a framebuffer state */
@@ -1531,7 +1581,7 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter,
    pipe->bind_blend_state(pipe, custom_blend);
    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
-   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
+   ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
    pipe->set_sample_mask(pipe, sample_mask);
 
    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
@@ -1592,7 +1642,7 @@ void util_blitter_custom_color(struct blitter_context *blitter,
    /* bind states */
    pipe->bind_blend_state(pipe, custom_blend);
    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
-   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
+   ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
    pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1);
 
index 680407381a624f9988de3cc6a5dd24ff2efc5f37..d458f6927023fd236763d7c3c663cdd49671ae47 100644 (file)
@@ -120,6 +120,8 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe);
  */
 void util_blitter_destroy(struct blitter_context *blitter);
 
+void util_blitter_cache_all_shaders(struct blitter_context *blitter);
+
 /**
  * Return the pipe context associated with a blitter context.
  */