[Mesa-dev] [PATCH 7/9] meta: Add an accelerated glCopyTexSubImage using glBlitFramebuffer.
Eric Anholt
eric at anholt.net
Tue Apr 8 14:03:18 PDT 2014
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.
*/
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);
+ }
+
+ 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) !=
--
1.9.1
More information about the mesa-dev
mailing list