[Mesa-dev] [PATCH 7/9] meta: Add an accelerated glCopyTexSubImage using glBlitFramebuffer.

Kenneth Graunke kenneth at whitecape.org
Sat Apr 12 23:19:15 PDT 2014


On 04/08/2014 02:03 PM, Eric Anholt wrote:
> You'll note from the previous commits that there's something of a loop
> here: You call CTSI, which calls BlitFB, then if things go wrong that
> falls back to CTSI.  As a result, meta CTSI reaches over into blitfb to
> tell it "no, don't try that fallback".
> 
> v2: Drop the _mesa_update_state(), which was only necessary due to use of
>     _mesa_clip_blit() in _mesa_meta_BlitFramebuffer() in another patch
>     series.
> ---
>  src/mesa/drivers/common/meta.c                 | 95 +++++++++++++++++++++++---
>  src/mesa/drivers/common/meta.h                 |  4 +-
>  src/mesa/drivers/common/meta_blit.c            |  3 +
>  src/mesa/drivers/common/meta_generate_mipmap.c |  4 +-
>  4 files changed, 94 insertions(+), 12 deletions(-)
> 
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index 9e832f2..ab79e74 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -37,6 +37,7 @@
>  #include "main/arbprogram.h"
>  #include "main/arrayobj.h"
>  #include "main/blend.h"
> +#include "main/blit.h"
>  #include "main/bufferobj.h"
>  #include "main/buffers.h"
>  #include "main/colortab.h"
> @@ -97,7 +98,8 @@ static void meta_drawpix_cleanup(struct drawpix_state *drawpix);
>   * Bind a particular texture level/layer to mipmap->FBO's GL_COLOR_ATTACHMENT0.
>   */

Comment is really bogus now :)  Maybe:

/**
 * Bind a particular texture level/layer to an FBO attachment.
 */

Or some such?  Feel free to change it however you see fit.

>  void
> -_mesa_meta_bind_fbo_image(struct gl_texture_image *texImage, GLuint layer)
> +_mesa_meta_bind_fbo_image(GLenum attachment,
> +                          struct gl_texture_image *texImage, GLuint layer)
>  {
>     struct gl_texture_object *texObj = texImage->TexObject;
>     int level = texImage->Level;
> @@ -106,17 +108,18 @@ _mesa_meta_bind_fbo_image(struct gl_texture_image *texImage, GLuint layer)
>     switch (target) {
>     case GL_TEXTURE_1D:
>        _mesa_FramebufferTexture1D(GL_FRAMEBUFFER,
> -                                 GL_COLOR_ATTACHMENT0,
> +                                 attachment,
>                                   target,
>                                   texObj->Name,
>                                   level);
>        break;
>     case GL_TEXTURE_1D_ARRAY:
>     case GL_TEXTURE_2D_ARRAY:
> +   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
>     case GL_TEXTURE_CUBE_MAP_ARRAY:
>     case GL_TEXTURE_3D:
>        _mesa_FramebufferTextureLayer(GL_FRAMEBUFFER,
> -                                    GL_COLOR_ATTACHMENT0,
> +                                    attachment,
>                                      texObj->Name,
>                                      level,
>                                      layer);
> @@ -126,7 +129,7 @@ _mesa_meta_bind_fbo_image(struct gl_texture_image *texImage, GLuint layer)
>           target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face;
>  
>        _mesa_FramebufferTexture2D(GL_FRAMEBUFFER,
> -                                 GL_COLOR_ATTACHMENT0,
> +                                 attachment,
>                                   target,
>                                   texObj->Name,
>                                   level);
> @@ -2732,6 +2735,77 @@ get_temp_image_type(struct gl_context *ctx, mesa_format format)
>  }
>  
>  /**
> + * Attempts to wrap the destination texture in an FBO and use
> + * glBlitFramebuffer() to implement glCopyTexSubImage().
> + */
> +static bool
> +copytexsubimage_using_blit_framebuffer(struct gl_context *ctx, GLuint dims,
> +                                       struct gl_texture_image *texImage,
> +                                       GLint xoffset,
> +                                       GLint yoffset,
> +                                       GLint zoffset,
> +                                       struct gl_renderbuffer *rb,
> +                                       GLint x, GLint y,
> +                                       GLsizei width, GLsizei height)
> +{
> +   struct gl_texture_object *texObj = texImage->TexObject;
> +   GLuint fbo;
> +   bool success = false;
> +   GLbitfield mask;
> +   GLenum status;
> +
> +   if (!ctx->Extensions.ARB_framebuffer_object)
> +      return false;
> +
> +   _mesa_unlock_texture(ctx, texObj);
> +
> +   _mesa_meta_begin(ctx, MESA_META_ALL);
> +
> +   _mesa_GenFramebuffers(1, &fbo);
> +   _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
> +
> +   if (rb->_BaseFormat == GL_DEPTH_STENCIL ||
> +       rb->_BaseFormat == GL_DEPTH_COMPONENT) {
> +      _mesa_meta_bind_fbo_image(GL_DEPTH_ATTACHMENT, texImage, zoffset);
> +      mask = GL_DEPTH_BUFFER_BIT;
> +
> +      if (rb->_BaseFormat == GL_DEPTH_STENCIL &&
> +          texImage->_BaseFormat == GL_DEPTH_STENCIL) {
> +         _mesa_meta_bind_fbo_image(GL_STENCIL_ATTACHMENT, texImage, zoffset);
> +         mask |= GL_STENCIL_BUFFER_BIT;
> +      }
> +      _mesa_DrawBuffer(GL_NONE);
> +   } else {
> +      _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, texImage, zoffset);
> +      mask = GL_COLOR_BUFFER_BIT;
> +      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);

Don't need the _EXT here.

> +   }
> +
> +   status = _mesa_CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
> +   if (status != GL_FRAMEBUFFER_COMPLETE)
> +      goto out;
> +
> +   ctx->Meta->Blit.no_ctsi_fallback = true;
> +   /* We skip the core BlitFramebuffer checks for format consistency, which
> +    * are too strict for CopyTexImage.  We know meta will be fine with format
> +    * changes.
> +    */
> +   _mesa_meta_BlitFramebuffer(ctx, x, y,
> +                              x + width, y + height,
> +                              xoffset, yoffset,
> +                              xoffset + width, yoffset + height,
> +                              mask, GL_NEAREST);
> +   ctx->Meta->Blit.no_ctsi_fallback = false;
> +   success = true;
> +
> + out:
> +   _mesa_lock_texture(ctx, texObj);
> +   _mesa_DeleteFramebuffers(1, &fbo);
> +   _mesa_meta_end(ctx);
> +   return success;
> +}
> +
> +/**
>   * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
>   * Have to be careful with locking and meta state for pixel transfer.
>   */
> @@ -2748,11 +2822,14 @@ _mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
>     GLint bpp;
>     void *buf;
>  
> -   /* The gl_renderbuffer is part of the interface for
> -    * dd_function_table::CopyTexSubImage, but this implementation does not use
> -    * it.
> -    */
> -   (void) rb;
> +   if (copytexsubimage_using_blit_framebuffer(ctx, dims,
> +                                              texImage,
> +                                              xoffset, yoffset, zoffset,
> +                                              rb,
> +                                              x, y,
> +                                              width, height)) {
> +      return;
> +   }
>  
>     /* Choose format/type for temporary image buffer */
>     format = _mesa_get_format_base_format(texImage->TexFormat);
> diff --git a/src/mesa/drivers/common/meta.h b/src/mesa/drivers/common/meta.h
> index ad3da9c..fd8a385 100644
> --- a/src/mesa/drivers/common/meta.h
> +++ b/src/mesa/drivers/common/meta.h
> @@ -253,6 +253,7 @@ struct blit_state
>     struct blit_shader_table shaders;
>     GLuint msaa_shaders[BLIT_MSAA_SHADER_COUNT];
>     struct temp_texture depthTex;
> +   bool no_ctsi_fallback;
>  };
>  
>  
> @@ -505,6 +506,7 @@ void
>  _mesa_meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap);
>  
>  void
> -_mesa_meta_bind_fbo_image(struct gl_texture_image *texImage, GLuint layer);
> +_mesa_meta_bind_fbo_image(GLenum attachment,
> +                          struct gl_texture_image *texImage, GLuint layer);
>  
>  #endif /* META_H */
> diff --git a/src/mesa/drivers/common/meta_blit.c b/src/mesa/drivers/common/meta_blit.c
> index d7bb7c8..0bd76a1 100644
> --- a/src/mesa/drivers/common/meta_blit.c
> +++ b/src/mesa/drivers/common/meta_blit.c
> @@ -425,6 +425,9 @@ blitframebuffer_texture(struct gl_context *ctx,
>        /* Fall back to doing a CopyTexSubImage to get the destination
>         * renderbuffer into a texture.
>         */
> +      if (ctx->Meta->Blit.no_ctsi_fallback)
> +         return false;
> +
>        if (rb->NumSamples > 1)
>           return false;
>  
> diff --git a/src/mesa/drivers/common/meta_generate_mipmap.c b/src/mesa/drivers/common/meta_generate_mipmap.c
> index db46974..3c9ac89 100644
> --- a/src/mesa/drivers/common/meta_generate_mipmap.c
> +++ b/src/mesa/drivers/common/meta_generate_mipmap.c
> @@ -103,7 +103,7 @@ fallback_required(struct gl_context *ctx, GLenum target,
>        _mesa_GenFramebuffers(1, &mipmap->FBO);
>     _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO);
>  
> -   _mesa_meta_bind_fbo_image(baseImage, 0);
> +   _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, baseImage, 0);
>  
>     status = _mesa_CheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
>  
> @@ -317,7 +317,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
>           _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts),
>                            verts, GL_DYNAMIC_DRAW_ARB);
>  
> -         _mesa_meta_bind_fbo_image(dstImage, layer);
> +         _mesa_meta_bind_fbo_image(GL_COLOR_ATTACHMENT0, dstImage, layer);
>  
>           /* sanity check */
>           if (_mesa_CheckFramebufferStatus(GL_FRAMEBUFFER) !=
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20140412/ad657ebc/attachment.sig>


More information about the mesa-dev mailing list