st/mesa: implement CopyTexSubImage for MSAA framebuffers
authorMarek Olšák <maraeo@gmail.com>
Mon, 3 Dec 2012 16:34:58 +0000 (17:34 +0100)
committerMarek Olšák <maraeo@gmail.com>
Fri, 7 Dec 2012 13:19:28 +0000 (14:19 +0100)
Reviewed-by: Brian Paul <brianp@vmware.com>
Just use pipe->blit, which can do resolve, flipping, and format conversions.
The util_blit_pixels codepath is still there for the cases where we have to
force alpha to 1.

This also turns on acceleration for copying GL_DEPTH_STENCIL.

src/mesa/state_tracker/st_cb_texture.c

index f06814f9cd326db7abb1af2f46877f5c39492eb9..10db5bcb51af237184e58c006ca54304f83d60a3 100644 (file)
@@ -59,6 +59,7 @@
 #include "pipe/p_shader_tokens.h"
 #include "util/u_tile.h"
 #include "util/u_blit.h"
+#include "util/u_blitter.h"
 #include "util/u_format.h"
 #include "util/u_surface.h"
 #include "util/u_sampler.h"
@@ -922,12 +923,12 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    struct pipe_context *pipe = st->pipe;
    struct pipe_screen *screen = pipe->screen;
    enum pipe_format dest_format, src_format;
-   GLboolean matching_base_formats;
-   GLuint color_writemask, zs_writemask, sample_count;
+   GLuint color_writemask;
    struct pipe_surface *dest_surface = NULL;
    GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
    struct pipe_surface surf_tmpl;
-   unsigned int dst_usage;
+   unsigned dst_usage;
+   unsigned blit_mask;
    GLint srcY0, srcY1;
 
    /* make sure finalize_textures has been called? 
@@ -939,12 +940,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
       return;
    }
 
-   sample_count = strb->surface->texture->nr_samples;
-   /* I believe this would be legal, presumably would need to do a resolve
-      for color, and for depth/stencil spec says to just use one of the
-      depth/stencil samples per pixel? Need some transfer clarifications. */
-   assert(sample_count < 2);
-
    assert(strb);
    assert(strb->surface);
    assert(stImage->pt);
@@ -952,22 +947,24 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
    src_format = strb->surface->format;
    dest_format = stImage->pt->format;
 
-   /*
-    * Determine if the src framebuffer and dest texture have the same
-    * base format.  We need this to detect a case such as the framebuffer
-    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
-    * texture format stores RGBA we need to set A=1 (overriding the
-    * framebuffer's alpha values).  We can't do that with the blit or
-    * textured-quad paths.
-    */
-   matching_base_formats =
-      (_mesa_get_format_base_format(strb->Base.Format) ==
-       _mesa_get_format_base_format(texImage->TexFormat));
+   if (do_flip) {
+      srcY1 = strb->Base.Height - srcY - height;
+      srcY0 = srcY1 + height;
+   }
+   else {
+      srcY0 = srcY;
+      srcY1 = srcY0 + height;
+   }
 
    if (ctx->_ImageTransferState) {
       goto fallback;
    }
 
+   /* Compressed and subsampled textures aren't supported for blitting. */
+   if (!util_format_is_plain(dest_format)) {
+      goto fallback;
+   }
+
    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
       /* 1D arrays might be thought of as 2D images but the actual layout
        * might not be that way.  At some points, we convert OpenGL's 1D
@@ -978,53 +975,112 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
       goto fallback;
    }
 
-   if (matching_base_formats &&
-       src_format == dest_format &&
-       !do_flip) {
-      /* use surface_copy() / blit */
-      struct pipe_box src_box;
-      unsigned dstLevel;
+   /* Set the blit writemask. */
+   switch (texBaseFormat) {
+   case GL_DEPTH_STENCIL:
+      switch (strb->Base._BaseFormat) {
+      case GL_DEPTH_STENCIL:
+         blit_mask = PIPE_MASK_ZS;
+         break;
+      case GL_DEPTH_COMPONENT:
+         blit_mask = PIPE_MASK_Z;
+         break;
+      case GL_STENCIL_INDEX:
+         blit_mask = PIPE_MASK_S;
+         break;
+      default:
+         assert(0);
+         return;
+      }
+      dst_usage = PIPE_BIND_DEPTH_STENCIL;
+      break;
 
-      u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
-                      width, height, &src_box);
+   case GL_DEPTH_COMPONENT:
+      blit_mask = PIPE_MASK_Z;
+      dst_usage = PIPE_BIND_DEPTH_STENCIL;
+      break;
+
+   default:
+      /* Colorbuffers.
+       *
+       * Determine if the src framebuffer and dest texture have the same
+       * base format.  We need this to detect a case such as the framebuffer
+       * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
+       * texture format stores RGBA we need to set A=1 (overriding the
+       * framebuffer's alpha values).
+       *
+       * XXX util_blit_pixels doesn't support MSAA resolve, so always use
+       *     pipe->blit
+       */
+      if (texBaseFormat == strb->Base._BaseFormat ||
+          strb->texture->nr_samples > 1) {
+         blit_mask = PIPE_MASK_RGBA;
+      }
+      else {
+         blit_mask = 0;
+      }
+      dst_usage = PIPE_BIND_RENDER_TARGET;
+   }
 
+   /* Blit the texture.
+    * This supports flipping, format conversions, and downsampling.
+    */
+   if (blit_mask) {
       /* If stImage->pt is an independent image (not a pointer into a full
        * mipmap) stImage->pt.last_level will be zero and we need to use that
        * as the dest level.
        */
-      dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level);
-
-      /* for resource_copy_region(), y=0=top, always */
-      pipe->resource_copy_region(pipe,
-                                 /* dest */
-                                 stImage->pt,
-                                 dstLevel,
-                                 destX, destY, destZ + stImage->base.Face,
-                                 /* src */
-                                 strb->texture,
-                                 strb->surface->u.tex.level,
-                                 &src_box);
-      return;
-   }
+      unsigned dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level);
+      struct pipe_blit_info blit;
+
+      memset(&blit, 0, sizeof(blit));
+      blit.src.resource = strb->texture;
+      blit.src.format = src_format;
+      blit.src.level = strb->surface->u.tex.level;
+      blit.src.box.x = srcX;
+      blit.src.box.y = srcY0;
+      blit.src.box.z = strb->surface->u.tex.first_layer;
+      blit.src.box.width = width;
+      blit.src.box.height = srcY1 - srcY0;
+      blit.src.box.depth = 1;
+      blit.dst.resource = stImage->pt;
+      blit.dst.format = dest_format;
+      blit.dst.level = dstLevel;
+      blit.dst.box.x = destX;
+      blit.dst.box.y = destY;
+      blit.dst.box.z = stImage->base.Face + destZ;
+      blit.dst.box.width = width;
+      blit.dst.box.height = height;
+      blit.dst.box.depth = 1;
+      blit.mask = blit_mask;
+      blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+      /* try resource_copy_region in case the format is not supported
+       * for rendering */
+      if (util_try_blit_via_copy_region(pipe, &blit)) {
+         return; /* done */
+      }
 
-   if (texBaseFormat == GL_DEPTH_STENCIL) {
-      goto fallback;
-   }
+      /* check the format support */
+      if (!screen->is_format_supported(screen, src_format,
+                                       PIPE_TEXTURE_2D, 0,
+                                       PIPE_BIND_SAMPLER_VIEW) ||
+          !screen->is_format_supported(screen, dest_format,
+                                       PIPE_TEXTURE_2D, 0,
+                                       dst_usage)) {
+         goto fallback;
+      }
 
-   if (texBaseFormat == GL_DEPTH_COMPONENT) {
-      color_writemask = 0;
-      zs_writemask = BLIT_WRITEMASK_Z;
-      dst_usage = PIPE_BIND_DEPTH_STENCIL;
-   }
-   else {
-      color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
-      zs_writemask = 0;
-      dst_usage = PIPE_BIND_RENDER_TARGET;
+      pipe->blit(pipe, &blit);
+      return;
    }
 
-   if ((!color_writemask && !zs_writemask) ||
+   /* try u_blit */
+   color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
+
+   if (!color_writemask ||
        !screen->is_format_supported(screen, src_format,
-                                    PIPE_TEXTURE_2D, sample_count,
+                                    PIPE_TEXTURE_2D, 0,
                                     PIPE_BIND_SAMPLER_VIEW) ||
        !screen->is_format_supported(screen, dest_format,
                                     PIPE_TEXTURE_2D, 0,
@@ -1032,15 +1088,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
       goto fallback;
    }
 
-   if (do_flip) {
-      srcY1 = strb->Base.Height - srcY - height;
-      srcY0 = srcY1 + height;
-   }
-   else {
-      srcY0 = srcY;
-      srcY1 = srcY0 + height;
-   }
-
    /* Disable conditional rendering. */
    if (st->render_condition) {
       pipe->render_condition(pipe, NULL, 0);
@@ -1065,7 +1112,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                     destX, destY,
                     destX + width, destY + height,
                     0.0, PIPE_TEX_MIPFILTER_NEAREST,
-                    color_writemask, zs_writemask);
+                    color_writemask, 0);
    pipe_surface_reference(&dest_surface, NULL);
 
    /* Restore conditional rendering state. */