From 3232682d3b04ff16806fd8c5ad36271876a7b419 Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Thu, 13 Feb 2014 16:39:30 +0000 Subject: OpenGL: Fix QOpenGLTexture for cubemaps with mutable storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code was not creating all of the storage necessary for cubemaps as well as attempting to bind to the cubemap face targets which is invalid when using mutable storage - typically on OS X where EXT_direct_state_access is not available and immutable storage is only available at all if using an OpenGL 4.1 context. Change-Id: I4cf84f1b88c90e8359366392b3ccda65669ebfa7 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Pasi Keränen --- src/gui/opengl/qopengltexture.cpp | 24 +++++++++++++- src/gui/opengl/qopengltexturehelper.cpp | 56 ++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 9 deletions(-) (limited to 'src/gui/opengl') diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 43acd0a0c3..8bdbdba6f7 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -347,7 +347,6 @@ void QOpenGLTexturePrivate::allocateMutableStorage() break; case QOpenGLTexture::Target2D: - case QOpenGLTexture::TargetCubeMap: case QOpenGLTexture::TargetRectangle: for (int level = 0; level < mipLevels; ++level) texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format, @@ -357,6 +356,29 @@ void QOpenGLTexturePrivate::allocateMutableStorage() QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0); break; + case QOpenGLTexture::TargetCubeMap: { + // Cubemaps are the odd one out. We have to allocate storage for each + // face and miplevel using the special cubemap face targets rather than + // GL_TARGET_CUBEMAP. + const QOpenGLTexture::CubeMapFace faceTargets[] = { + QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX, + QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY, + QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ + }; + + for (int faceTarget = 0; faceTarget < 6; ++faceTarget) { + for (int level = 0; level < mipLevels; ++level) { + texFuncs->glTextureImage2D(textureId, faceTargets[faceTarget], bindingTarget, + level, format, + mipLevelSize(level, dimensions[0]), + mipLevelSize(level, dimensions[1]), + 0, + QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, 0); + } + } + break; + } + case QOpenGLTexture::Target2DArray: if (features.testFlag(QOpenGLTexture::TextureArrays)) { for (int level = 0; level < mipLevels; ++level) diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp index 69ad498aa7..1f44a81276 100644 --- a/src/gui/opengl/qopengltexturehelper.cpp +++ b/src/gui/opengl/qopengltexturehelper.cpp @@ -478,11 +478,31 @@ void QOpenGLTextureHelper::qt_TextureImage3D(GLuint texture, GLenum target, GLen void QOpenGLTextureHelper::qt_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { + // For cubemaps we can't use the standard DSA emulation as it is illegal to + // try to bind a texture to one of the cubemap face targets. So we force the + // target and binding target to the cubemap values in this case. GLint oldTexture; - glGetIntegerv(bindingTarget, &oldTexture); - glBindTexture(target, texture); - glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); - glBindTexture(target, oldTexture); + + switch (target) { + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &oldTexture); + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); + glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); + glBindTexture(GL_TEXTURE_CUBE_MAP, oldTexture); + break; + + default: + glGetIntegerv(bindingTarget, &oldTexture); + glBindTexture(target, texture); + glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); + glBindTexture(target, oldTexture); + break; + } } void QOpenGLTextureHelper::qt_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) @@ -505,11 +525,31 @@ void QOpenGLTextureHelper::qt_TextureSubImage3D(GLuint texture, GLenum target, G void QOpenGLTextureHelper::qt_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { + // For cubemaps we can't use the standard DSA emulation as it is illegal to + // try to bind a texture to one of the cubemap face targets. So we force the + // target and binding target to the cubemap values in this case. GLint oldTexture; - glGetIntegerv(bindingTarget, &oldTexture); - glBindTexture(target, texture); - glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); - glBindTexture(target, oldTexture); + + switch (target) { + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &oldTexture); + glBindTexture(GL_TEXTURE_CUBE_MAP, texture); + glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + glBindTexture(GL_TEXTURE_CUBE_MAP, oldTexture); + break; + + default: + glGetIntegerv(bindingTarget, &oldTexture); + glBindTexture(target, texture); + glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); + glBindTexture(target, oldTexture); + break; + } } void QOpenGLTextureHelper::qt_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) -- cgit v1.2.3