[Mesa-dev] [PATCH 07/10] meta: Add an accelerated glCopyTexSubImage using glBlitFramebuffer.
Eric Anholt
eric at anholt.net
Tue Mar 4 14:17:41 PST 2014
We have to be a little careful here, because BlitFB itself has a fallback
path that calls CopyTexSubImage(), so we reach over into its state to tell
it to skip that case.
---
src/mesa/drivers/common/meta.c | 177 ++++++++++++++++++++++++++----------
src/mesa/drivers/common/meta.h | 1 +
src/mesa/drivers/common/meta_blit.c | 3 +-
3 files changed, 130 insertions(+), 51 deletions(-)
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 24eb0a3..90e49fd 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"
@@ -93,6 +94,41 @@ static void meta_glsl_generate_mipmap_cleanup(struct gen_mipmap_state *mipmap);
static void meta_decompress_cleanup(struct decompress_state *decompress);
static void meta_drawpix_cleanup(struct drawpix_state *drawpix);
+static void
+meta_framebuffer_texture_layer(GLenum fb_target,
+ GLenum attachment,
+ const struct gl_texture_image *texImage,
+ int layer)
+{
+ struct gl_texture_object *texObj = texImage->TexObject;
+ int level = texImage->Level;
+
+ switch (texObj->Target) {
+ case GL_TEXTURE_1D:
+ _mesa_FramebufferTexture1D(fb_target, attachment,
+ texObj->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(fb_target, attachment,
+ texObj->Name, level, layer);
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ _mesa_FramebufferTexture2D(fb_target, attachment,
+ (GL_TEXTURE_CUBE_MAP_POSITIVE_X +
+ texImage->Face),
+ texObj->Name, level);
+ break;
+ default:
+ _mesa_FramebufferTexture2D(fb_target, attachment,
+ texObj->Target, texObj->Name, level);
+ break;
+ }
+}
+
GLuint
_mesa_meta_compile_shader_with_debug(struct gl_context *ctx, GLenum target,
const GLcharARB *source)
@@ -2436,26 +2472,8 @@ _mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target,
_mesa_GenFramebuffers(1, &mipmap->FBO);
_mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, mipmap->FBO);
- if (target == GL_TEXTURE_1D) {
- _mesa_FramebufferTexture1D(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target, texObj->Name, srcLevel);
- }
-#if 0
- /* other work is needed to enable 3D mipmap generation */
- else if (target == GL_TEXTURE_3D) {
- GLint zoffset = 0;
- _mesa_FramebufferTexture3D(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target, texObj->Name, srcLevel, zoffset);
- }
-#endif
- else {
- /* 2D / cube */
- _mesa_FramebufferTexture2D(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target, texObj->Name, srcLevel);
- }
+ meta_framebuffer_texture_layer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ baseImage, 0);
status = _mesa_CheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
@@ -2848,7 +2866,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
_mesa_unlock_texture(ctx, texObj);
for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
- const struct gl_texture_image *srcImage;
+ const struct gl_texture_image *srcImage, *dstImage;
const GLuint srcLevel = dstLevel - 1;
GLsizei srcWidth, srcHeight, srcDepth;
GLsizei dstWidth, dstHeight, dstDepth;
@@ -2889,34 +2907,13 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
*/
break;
}
+ dstImage = _mesa_select_tex_image(ctx, texObj, faceTarget, dstLevel);
/* limit minification to src level */
_mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);
- /* Set to draw into the current dstLevel */
- if (target == GL_TEXTURE_1D) {
- _mesa_FramebufferTexture1D(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texObj->Name,
- dstLevel);
- }
- else if (target == GL_TEXTURE_3D) {
- GLint zoffset = 0; /* XXX unfinished */
- _mesa_FramebufferTexture3D(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texObj->Name,
- dstLevel, zoffset);
- }
- else {
- /* 2D / cube */
- _mesa_FramebufferTexture2D(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- faceTarget,
- texObj->Name,
- dstLevel);
- }
+ meta_framebuffer_texture_layer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ dstImage, 0);
_mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
@@ -3001,6 +2998,83 @@ 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) {
+ meta_framebuffer_texture_layer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ texImage, zoffset);
+ mask = GL_DEPTH_BUFFER_BIT;
+
+ if (rb->_BaseFormat == GL_DEPTH_STENCIL &&
+ texImage->_BaseFormat == GL_DEPTH_STENCIL) {
+ meta_framebuffer_texture_layer(GL_DRAW_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ texImage, zoffset);
+ mask |= GL_STENCIL_BUFFER_BIT;
+ }
+ _mesa_DrawBuffer(GL_NONE);
+ } else {
+ meta_framebuffer_texture_layer(GL_DRAW_FRAMEBUFFER, 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;
+ /* Update clip state. */
+ _mesa_update_state(ctx);
+ /* 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.
*/
@@ -3017,11 +3091,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 104849a..00553e2 100644
--- a/src/mesa/drivers/common/meta.h
+++ b/src/mesa/drivers/common/meta.h
@@ -252,6 +252,7 @@ struct blit_state
struct blit_shader_table shaders;
GLuint msaa_shaders[BLIT_MSAA_SHADER_COUNT];
struct temp_texture depthTex;
+ bool no_ctsi_fallback;
};
diff --git a/src/mesa/drivers/common/meta_blit.c b/src/mesa/drivers/common/meta_blit.c
index 907c2cd..9756d86 100644
--- a/src/mesa/drivers/common/meta_blit.c
+++ b/src/mesa/drivers/common/meta_blit.c
@@ -701,7 +701,8 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx,
if (!use_glsl_version)
_mesa_set_enable(ctx, tex->Target, GL_TRUE);
- if (mask & GL_COLOR_BUFFER_BIT) {
+ if ((mask & GL_COLOR_BUFFER_BIT) &&
+ !ctx->Meta->Blit.no_ctsi_fallback) {
const struct gl_framebuffer *readFb = ctx->ReadBuffer;
const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
const GLenum rb_base_format =
--
1.9.rc1
More information about the mesa-dev
mailing list