gallium/u_blitter: add a query for checking whether copying is supported
authorMarek Olšák <maraeo@gmail.com>
Fri, 27 Jul 2012 23:19:18 +0000 (01:19 +0200)
committerMarek Olšák <maraeo@gmail.com>
Sat, 4 Aug 2012 12:05:37 +0000 (14:05 +0200)
v2: add comments

src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h
src/gallium/drivers/i915/i915_resource_texture.c
src/gallium/drivers/i915/i915_surface.c

index 21dc19fa107f72eb867be4114c0929d2ca960c8b..fa71f25ea753c918788bbec7890c437a9f8e3472 100644 (file)
@@ -932,6 +932,61 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
     src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA;
 }
 
+boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
+                                       const struct pipe_resource *dst,
+                                       const struct pipe_resource *src,
+                                       unsigned mask)
+{
+   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+   struct pipe_screen *screen = ctx->base.pipe->screen;
+
+   if (dst) {
+      unsigned bind;
+      boolean is_stencil;
+      const struct util_format_description *desc =
+            util_format_description(dst->format);
+
+      is_stencil = util_format_has_stencil(desc);
+
+      /* Stencil export must be supported for stencil copy. */
+      if ((mask & PIPE_MASK_S) && is_stencil && !ctx->has_stencil_export) {
+         return FALSE;
+      }
+
+      if (is_stencil || util_format_has_depth(desc))
+         bind = PIPE_BIND_DEPTH_STENCIL;
+      else
+         bind = PIPE_BIND_RENDER_TARGET;
+
+      if (!screen->is_format_supported(screen, dst->format, dst->target,
+                                       dst->nr_samples, bind)) {
+         return FALSE;
+      }
+   }
+
+   if (src) {
+      if (!screen->is_format_supported(screen, src->format, src->target,
+                                 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
+         return FALSE;
+      }
+
+      /* Check stencil sampler support for stencil copy. */
+      if (util_format_has_stencil(util_format_description(src->format))) {
+         enum pipe_format stencil_format =
+               util_format_stencil_only(src->format);
+         assert(stencil_format != PIPE_FORMAT_NONE);
+
+         if (stencil_format != src->format &&
+             !screen->is_format_supported(screen, stencil_format, src->target,
+                                 src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
+            return FALSE;
+         }
+      }
+   }
+
+   return TRUE;
+}
+
 void util_blitter_copy_texture(struct blitter_context *blitter,
                                struct pipe_resource *dst,
                                unsigned dst_level,
@@ -942,44 +997,12 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    struct pipe_context *pipe = ctx->base.pipe;
-   struct pipe_screen *screen = pipe->screen;
    struct pipe_surface *dst_view, dst_templ;
    struct pipe_sampler_view src_templ, *src_view;
-   unsigned bind;
-   boolean is_stencil, is_depth;
-   const struct util_format_description *src_desc;
 
-   /* Give up if textures are not set. */
    assert(dst && src);
-   if (!dst || !src)
-      return;
-
-   src_desc = util_format_description(src->format);
-
    assert(src->target < PIPE_MAX_TEXTURE_TYPES);
 
-   /* Is this a ZS format? */
-   is_depth = util_format_has_depth(src_desc);
-   is_stencil = util_format_has_stencil(src_desc);
-
-   if (is_depth || is_stencil)
-      bind = PIPE_BIND_DEPTH_STENCIL;
-   else
-      bind = PIPE_BIND_RENDER_TARGET;
-
-   /* Check if we can sample from and render to the surfaces. */
-   /* (assuming copying a stencil buffer is not possible) */
-   if (!screen->is_format_supported(screen, dst->format, dst->target,
-                                    dst->nr_samples, bind) ||
-       !screen->is_format_supported(screen, src->format, src->target,
-                                    src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
-      blitter_set_running_flag(ctx);
-      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
-                                src, src_level, srcbox);
-      blitter_unset_running_flag(ctx);
-      return;
-   }
-
    /* Initialize the surface. */
    util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, srcbox);
    dst_view = pipe->create_surface(pipe, dst, &dst_templ);
index 80a11526e77fa10f1d7deabc8192ad2b1235c55d..7600391c511ea8a6a17645ab285b00d1cff393f5 100644 (file)
@@ -160,6 +160,16 @@ void util_blitter_clear_depth_custom(struct blitter_context *blitter,
                                      unsigned width, unsigned height,
                                      double depth, void *custom_dsa);
 
+/**
+ * Check if the blitter (with the help of the driver) can blit between
+ * the two resources.
+ * The mask is a combination of the PIPE_MASK_* flags.
+ * Set to PIPE_MASK_RGBAZS if unsure.
+ */
+boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
+                                       const struct pipe_resource *dst,
+                                       const struct pipe_resource *src,
+                                       unsigned mask);
 /**
  * Copy a block of pixels from one surface to another.
  *
@@ -201,6 +211,9 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
  * coordinates. The dst dimensions are supplied through pipe_surface::width
  * and height.
  *
+ * The mask is a combination of the PIPE_MASK_* flags.
+ * Set to PIPE_MASK_RGBAZS if unsure.
+ *
  * NOTE: There are no checks whether the blit is actually supported.
  */
 void util_blitter_copy_texture_view(struct blitter_context *blitter,
index 8ff733a7be530f261d8fe3e54084fe1192a51449..e60b5b435cc2b7170835d556d2bb5dc2f8e8b464 100644 (file)
@@ -739,11 +739,8 @@ i915_texture_get_transfer(struct pipe_context *pipe,
    /* if we use staging transfers, only support textures we can render to,
     * because we need that for u_blitter */
    if (i915->blitter &&
-       i915_is_format_supported(NULL, /* screen */
-                                transfer->b.resource->format,
-                                0, /* target */
-                                1, /* sample count */
-                                PIPE_BIND_RENDER_TARGET) &&
+       util_blitter_is_copy_supported(i915->blitter, resource, resource,
+                                     PIPE_MASK_RGBAZS) &&
        (usage & PIPE_TRANSFER_WRITE) &&
        !(usage & (PIPE_TRANSFER_READ | PIPE_TRANSFER_DONTBLOCK | PIPE_TRANSFER_UNSYNCHRONIZED)))
       use_staging_texture = TRUE;
index c51689dcb4c993d32b1c9cc9609d1fbc4f2d8072..a25676efeca318215f7eca17a679e5cb8f67665f 100644 (file)
@@ -59,6 +59,13 @@ i915_surface_copy_render(struct pipe_context *pipe,
       return;
    }
 
+   if (!util_blitter_is_copy_supported(i915->blitter, dst, src,
+                                       PIPE_MASK_RGBAZS)) {
+      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
+                                src, src_level, src_box);
+      return;
+   }
+
    util_blitter_save_blend(i915->blitter, (void *)i915->blend);
    util_blitter_save_depth_stencil_alpha(i915->blitter, (void *)i915->depth_stencil);
    util_blitter_save_stencil_ref(i915->blitter, &i915->stencil_ref);