summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2014-02-28 13:23:25 -0800
committerEric Anholt <eric@anholt.net>2014-04-15 14:34:22 -0700
commit234db609544ee521458ce8b648e70cffe2fda6f9 (patch)
treed5cb5d5bde7e5661a7880fba80d184cfea579315
parent70961c032fab53ae30a25b95445eae5aaf8c2068 (diff)
meta: Add an accelerated glCopyTexSubImage using glBlitFramebuffer.
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. v3: Drop an _EXT suffix I copy-and-pasted. Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> (v2) Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
-rw-r--r--src/mesa/drivers/common/meta.c95
-rw-r--r--src/mesa/drivers/common/meta.h4
-rw-r--r--src/mesa/drivers/common/meta_blit.c3
-rw-r--r--src/mesa/drivers/common/meta_generate_mipmap.c4
4 files changed, 94 insertions, 12 deletions
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 12d6f65d206..ddd0b1ad19a 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"
@@ -94,7 +95,8 @@ static void meta_decompress_cleanup(struct decompress_state *decompress);
static void meta_drawpix_cleanup(struct drawpix_state *drawpix);
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;
@@ -103,17 +105,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);
@@ -123,7 +126,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);
@@ -2729,6 +2732,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);
+ }
+
+ 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.
*/
@@ -2745,11 +2819,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 ad3da9cd8d4..fd8a385b644 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 d1c40f50c52..526295bacbd 100644
--- a/src/mesa/drivers/common/meta_blit.c
+++ b/src/mesa/drivers/common/meta_blit.c
@@ -419,6 +419,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 db469745d12..3c9ac89afba 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) !=