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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev