OpenGL: Fix QOpenGLTexture for cubemaps with mutable storage

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 <giuseppe.dangelo@kdab.com>
Reviewed-by: Pasi Keränen <pasi.keranen@digia.com>
This commit is contained in:
Sean Harmer 2014-02-13 16:39:30 +00:00 committed by The Qt Project
parent 4273c14e57
commit 3232682d3b
2 changed files with 71 additions and 9 deletions

View File

@ -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)

View File

@ -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)