diff --git a/src/Magnum/GL/CubeMapTexture.cpp b/src/Magnum/GL/CubeMapTexture.cpp index 5ec41ace4..cebb0b276 100644 --- a/src/Magnum/GL/CubeMapTexture.cpp +++ b/src/Magnum/GL/CubeMapTexture.cpp @@ -284,11 +284,63 @@ BufferImage3D CubeMapTexture::subImage(const Int level, const Range3Di& range, B return std::move(image); } +void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, CompressedImage3D& image) { + createIfNotAlready(); + + /* Internal texture format */ + GLint format; + (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + + /* Calculate compressed subimage size. If the user-provided pixel storage + doesn't tell us all properties about the compression, we need to ask GL + for it. That requires GL_ARB_internalformat_query2. */ + std::size_t dataSize; + if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) + dataSize = compressedSubImageSize<3>(TextureFormat(format), range.size()); + else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, range.size()); + + /* Reallocate only if needed */ + Containers::Array data{image.release()}; + if(data.size() < dataSize) + data = Containers::Array{dataSize}; + + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); + glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), data.size(), data); + image = CompressedImage3D{CompressedPixelFormat(format), range.size(), std::move(data)}; +} + CompressedImage3D CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, CompressedImage3D&& image) { compressedSubImage(level, range, image); return std::move(image); } +void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, CompressedBufferImage3D& image, const BufferUsage usage) { + createIfNotAlready(); + + /* Internal texture format */ + GLint format; + (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + + /* Calculate compressed subimage size. If the user-provided pixel storage + doesn't tell us all properties about the compression, we need to ask GL + for it. That requires GL_ARB_internalformat_query2. */ + std::size_t dataSize; + if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) + dataSize = compressedSubImageSize<3>(TextureFormat(format), range.size()); + else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, range.size()); + + /* Reallocate only if needed */ + if(image.dataSize() < dataSize) + image.setData(image.storage(), CompressedPixelFormat(format), range.size(), {nullptr, dataSize}, usage); + else + image.setData(image.storage(), CompressedPixelFormat(format), range.size(), nullptr, usage); + + image.buffer().bindInternal(Buffer::TargetHint::PixelPack); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); + glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), dataSize, nullptr); +} + CompressedBufferImage3D CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, CompressedBufferImage3D&& image, const BufferUsage usage) { compressedSubImage(level, range, image, usage); return std::move(image); diff --git a/src/Magnum/GL/CubeMapTexture.h b/src/Magnum/GL/CubeMapTexture.h index 871f19703..6145f5650 100644 --- a/src/Magnum/GL/CubeMapTexture.h +++ b/src/Magnum/GL/CubeMapTexture.h @@ -818,9 +818,7 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. */ - void compressedSubImage(Int level, const Range3Di& range, CompressedImage3D& image) { - AbstractTexture::compressedSubImage<3>(level, range, image); - } + void compressedSubImage(Int level, const Range3Di& range, CompressedImage3D& image); /** @overload * @@ -846,9 +844,7 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. */ - void compressedSubImage(Int level, const Range3Di& range, CompressedBufferImage3D& image, BufferUsage usage) { - AbstractTexture::compressedSubImage<3>(level, range, image, usage); - } + void compressedSubImage(Int level, const Range3Di& range, CompressedBufferImage3D& image, BufferUsage usage); /** @overload *