From 7d0a5d904782091bbd2e4d001c15e731305f535f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 2 Jan 2016 00:05:21 +0100 Subject: [PATCH] Make it possible to get predictable compressed cubemap image sizes. I expect the drivers to return size of *one* face when I'm querying that particular face using the pre-DSA or EXT_DSA API and size of *all* six faces when I'm querying whole texture using DSA API. One can dream, eh? It appears that, at least on my NVidia, the returned value does not depend on whether I'm querying all faces or a single one, but RATHER is based on whether the texture is immutable or not. How's that predictable at all?! Workaround in the next commit. --- src/Magnum/CubeMapTexture.cpp | 48 ++++++++++++++++++---- src/Magnum/CubeMapTexture.h | 8 ++++ src/Magnum/Implementation/TextureState.cpp | 3 ++ src/Magnum/Implementation/TextureState.h | 1 + 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/Magnum/CubeMapTexture.cpp b/src/Magnum/CubeMapTexture.cpp index 2e5e917c9..569a3dbd9 100644 --- a/src/Magnum/CubeMapTexture.cpp +++ b/src/Magnum/CubeMapTexture.cpp @@ -109,8 +109,7 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image) createIfNotAlready(); const Vector3i size{imageSize(level), 6}; - GLint textureDataSize; - (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + const GLint textureDataSize = (this->*Context::current()->state().texture->getCubeLevelCompressedImageSizeImplementation)(level); const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize); GLint format; (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); @@ -135,8 +134,7 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i createIfNotAlready(); const Vector3i size{imageSize(level), 6}; - GLint textureDataSize; - (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + const GLint textureDataSize = (this->*Context::current()->state().texture->getCubeLevelCompressedImageSizeImplementation)(level); const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize); GLint format; (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); @@ -199,8 +197,9 @@ BufferImage2D CubeMapTexture::image(const Coordinate coordinate, const Int level void CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedImage2D& image) { const Vector2i size = imageSize(level); - GLint textureDataSize; - (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + /* The function returns size of all six faces, divide the result to get size + of one face */ + const GLint textureDataSize = (this->*Context::current()->state().texture->getCubeLevelCompressedImageSizeImplementation)(level)/6; const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize); GLint format; (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); @@ -223,8 +222,9 @@ CompressedImage2D CubeMapTexture::compressedImage(const Coordinate coordinate, c void CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) { const Vector2i size = imageSize(level); - GLint textureDataSize; - (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + /* The function returns size of all six faces, divide the result to get size + of one face */ + const GLint textureDataSize = (this->*Context::current()->state().texture->getCubeLevelCompressedImageSizeImplementation)(level)/6; const std::size_t dataSize = Implementation::compressedImageDataSizeFor(image, size, textureDataSize); GLint format; (this->*Context::current()->state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); @@ -362,6 +362,38 @@ void CubeMapTexture::getLevelParameterImplementationDSAEXT(const GLint level, co #endif #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +GLint CubeMapTexture::getLevelCompressedImageSizeImplementationDefault(const GLint level) { + bindInternal(); + /* Using only parameters of +X in pre-DSA code path and assuming that all + other faces are the same */ + GLint value; + glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &value); + + /* Size of all six faces */ + return value*6; +} + +#ifndef MAGNUM_TARGET_GLES +GLint CubeMapTexture::getLevelCompressedImageSizeImplementationDSA(const GLint level) { + GLint value; + glGetTextureLevelParameteriv(_id, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &value); + return value; +} + +GLint CubeMapTexture::getLevelCompressedImageSizeImplementationDSAEXT(const GLint level) { + _flags |= ObjectFlag::Created; + /* Using only parameters of +X in pre-DSA code path and assuming that all + other faces are the same */ + GLint value; + glGetTextureLevelParameterivEXT(_id, GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &value); + + /* Size of all six faces */ + return value*6; +} +#endif +#endif + #ifndef MAGNUM_TARGET_GLES void CubeMapTexture::getImageImplementationDefault(const Coordinate coordinate, const GLint level, const Vector2i&, const PixelFormat format, const PixelType type, std::size_t, GLvoid* const data) { bindInternal(); diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 9f0a4ffc8..4e4b0c4d9 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -952,6 +952,14 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { #endif #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + GLint MAGNUM_LOCAL getLevelCompressedImageSizeImplementationDefault(GLint level); + #ifndef MAGNUM_TARGET_GLES + GLint MAGNUM_LOCAL getLevelCompressedImageSizeImplementationDSA(GLint level); + GLint MAGNUM_LOCAL getLevelCompressedImageSizeImplementationDSAEXT(GLint level); + #endif + #endif + #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL getImageImplementationDefault(Coordinate coordinate, GLint level, const Vector2i& size, PixelFormat format, PixelType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDSA(Coordinate coordinate, GLint level, const Vector2i& size, PixelFormat format, PixelType type, std::size_t dataSize, GLvoid* data); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 0ece7be34..ec127405e 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -136,6 +136,7 @@ TextureState::TextureState(Context& context, std::vector& extension setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA; getCubeLevelParameterivImplementation = &CubeMapTexture::getLevelParameterImplementationDSA; + getCubeLevelCompressedImageSizeImplementation = &CubeMapTexture::getLevelCompressedImageSizeImplementationDSA; cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDSA; cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDSA; @@ -161,6 +162,7 @@ TextureState::TextureState(Context& context, std::vector& extension setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSAEXT; getCubeLevelParameterivImplementation = &CubeMapTexture::getLevelParameterImplementationDSAEXT; + getCubeLevelCompressedImageSizeImplementation = &CubeMapTexture::getLevelCompressedImageSizeImplementationDSAEXT; cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDSAEXT; cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDSAEXT; @@ -199,6 +201,7 @@ TextureState::TextureState(Context& context, std::vector& extension #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) getCubeLevelParameterivImplementation = &CubeMapTexture::getLevelParameterImplementationDefault; + getCubeLevelCompressedImageSizeImplementation = &CubeMapTexture::getLevelCompressedImageSizeImplementationDefault; #endif cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDefault; cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDefault; diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 81ab20a42..85ceb0b7b 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -99,6 +99,7 @@ struct TextureState { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void(CubeMapTexture::*getCubeLevelParameterivImplementation)(GLint, GLenum, GLint*); + GLint(CubeMapTexture::*getCubeLevelCompressedImageSizeImplementation)(GLint); #endif #ifndef MAGNUM_TARGET_GLES void(CubeMapTexture::*getCubeImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, PixelFormat, PixelType, std::size_t, GLvoid*);