From cb6a1bd7b5f539810d9251ef12280a9ef4a585f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Aug 2015 19:44:58 +0200 Subject: [PATCH] Compressed image support, part 8: compressed image download. Only full images now, no tests yet. --- doc/opengl-mapping.dox | 2 +- src/Magnum/AbstractTexture.cpp | 53 ++++++++++ src/Magnum/AbstractTexture.h | 7 ++ src/Magnum/CubeMapTexture.cpp | 90 +++++++++++++++++ src/Magnum/CubeMapTexture.h | 107 +++++++++++++++++++++ src/Magnum/CubeMapTextureArray.cpp | 10 ++ src/Magnum/CubeMapTextureArray.h | 42 ++++++++ src/Magnum/Implementation/TextureState.cpp | 16 ++- src/Magnum/Implementation/TextureState.h | 2 + src/Magnum/RectangleTexture.cpp | 10 ++ src/Magnum/RectangleTexture.h | 38 ++++++++ src/Magnum/Texture.cpp | 10 ++ src/Magnum/Texture.h | 68 +++++++++++++ src/Magnum/TextureArray.cpp | 10 ++ src/Magnum/TextureArray.h | 44 +++++++++ 15 files changed, 506 insertions(+), 3 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 8d7da9911..3ed606404 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -174,7 +174,7 @@ OpenGL function | Matching API @fn_gl{GetBufferParameter}, \n `glGetNamedBufferParameter()`, \n @fn_gl_extension{GetNamedBufferParameter,EXT,direct_state_access} | @ref Buffer::size() @fn_gl2{GetBufferPointer,GetBufferPointerv}, \n `glGetNamedBufferPointer()`, \n @fn_gl_extension{GetNamedBufferPointer,EXT,direct_state_access} | not queryable, @ref Buffer::map() setter only @fn_gl{GetBufferSubData}, \n `glGetNamedBufferSubData()`, \n @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access} | @ref Buffer::data(), \n @ref Buffer::subData() -@fn_gl{GetCompressedTexImage}, \n `glGetnCompressedTexImage()`, \n @fn_gl_extension{GetnCompressedTexImage,ARB,robustness}, \n `glGetCompressedTextureImage()`, \n @fn_gl_extension{GetCompressedTextureImage,EXT,direct_state_access} | | +@fn_gl{GetCompressedTexImage}, \n `glGetnCompressedTexImage()`, \n @fn_gl_extension{GetnCompressedTexImage,ARB,robustness}, \n `glGetCompressedTextureImage()`, \n @fn_gl_extension{GetCompressedTextureImage,EXT,direct_state_access} | @ref Texture::compressedImage(), \n @ref TextureArray::compressedImage(), \n @ref CubeMapTexture::compressedImage(), \n @ref CubeMapTextureArray::compressedImage(), \n @ref RectangleTexture::compressedImage() @fn_gl{GetCompressedTextureSubImage} | | @fn_gl{GetDebugMessageLog} | | @fn_gl{GetError} | @ref Renderer::error() diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 9e3f7599b..b9ace1eb8 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -1228,19 +1228,38 @@ void AbstractTexture::getImageImplementationDefault(const GLint level, const Col glGetTexImage(_target, level, GLenum(format), GLenum(type), data); } +void AbstractTexture::getCompressedImageImplementationDefault(const GLint level, std::size_t, GLvoid* const data) { + bindInternal(); + glGetCompressedTexImage(_target, level, data); +} + void AbstractTexture::getImageImplementationDSA(const GLint level, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) { glGetTextureImage(_id, level, GLenum(format), GLenum(type), dataSize, data); } +void AbstractTexture::getCompressedImageImplementationDSA(const GLint level, const std::size_t dataSize, GLvoid* const data) { + glGetCompressedTextureImage(_id, level, dataSize, data); +} + void AbstractTexture::getImageImplementationDSAEXT(const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) { _flags |= ObjectFlag::Created; glGetTextureImageEXT(_id, _target, level, GLenum(format), GLenum(type), data); } +void AbstractTexture::getCompressedImageImplementationDSAEXT(const GLint level, std::size_t, GLvoid* const data) { + _flags |= ObjectFlag::Created; + glGetCompressedTextureImageEXT(_id, _target, level, data); +} + void AbstractTexture::getImageImplementationRobustness(const GLint level, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) { bindInternal(); glGetnTexImageARB(_target, level, GLenum(format), GLenum(type), dataSize, data); } + +void AbstractTexture::getCompressedImageImplementationRobustness(const GLint level, const std::size_t dataSize, GLvoid* const data) { + bindInternal(); + glGetnCompressedTexImageARB(_target, level, dataSize, data); +} #endif #ifndef MAGNUM_TARGET_GLES @@ -1382,6 +1401,7 @@ template void AbstractTexture::image(GLint level, Image< const Math::Vector size = DataHelper::imageSize(*this, level); const std::size_t dataSize = image.dataSize(size); char* data = new char[dataSize]; + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); (this->*Context::current()->state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, data); image.setData(image.format(), image.type(), size, data); @@ -1405,6 +1425,39 @@ template void MAGNUM_EXPORT AbstractTexture::image<1>(GLint, BufferImage<1>&, Bu template void MAGNUM_EXPORT AbstractTexture::image<2>(GLint, BufferImage<2>&, BufferUsage); template void MAGNUM_EXPORT AbstractTexture::image<3>(GLint, BufferImage<3>&, BufferUsage); +template void AbstractTexture::compressedImage(const GLint level, CompressedImage& image) { + const Math::Vector size = DataHelper::imageSize(*this, level); + GLint dataSize; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize); + GLint format; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + Containers::Array data{std::size_t(dataSize)}; + + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); + (this->*Context::current()->state().texture->getCompressedImageImplementation)(level, dataSize, data); + image.setData(CompressedColorFormat(format), size, std::move(data)); +} + +template void MAGNUM_EXPORT AbstractTexture::compressedImage<1>(GLint, CompressedImage<1>&); +template void MAGNUM_EXPORT AbstractTexture::compressedImage<2>(GLint, CompressedImage<2>&); +template void MAGNUM_EXPORT AbstractTexture::compressedImage<3>(GLint, CompressedImage<3>&); + +template void AbstractTexture::compressedImage(const GLint level, CompressedBufferImage& image, BufferUsage usage) { + const Math::Vector size = DataHelper::imageSize(*this, level); + GLint dataSize; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize); + GLint format; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + + image.setData(CompressedColorFormat(format), size, {nullptr, std::size_t(dataSize)}, usage); + image.buffer().bindInternal(Buffer::TargetHint::PixelPack); + (this->*Context::current()->state().texture->getCompressedImageImplementation)(level, dataSize, nullptr); +} + +template void MAGNUM_EXPORT AbstractTexture::compressedImage<1>(GLint, CompressedBufferImage<1>&, BufferUsage); +template void MAGNUM_EXPORT AbstractTexture::compressedImage<2>(GLint, CompressedBufferImage<2>&, BufferUsage); +template void MAGNUM_EXPORT AbstractTexture::compressedImage<3>(GLint, CompressedBufferImage<3>&, BufferUsage); + template void AbstractTexture::subImage(const GLint level, const RangeTypeFor& range, Image& image) { createIfNotAlready(); diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index c440ecdf5..d90f8b7a5 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -403,6 +403,8 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { #ifndef MAGNUM_TARGET_GLES template void image(GLint level, Image& image); template void image(GLint level, BufferImage& image, BufferUsage usage); + template void compressedImage(GLint level, CompressedImage& image); + template void compressedImage(GLint level, CompressedBufferImage& image, BufferUsage usage); template void subImage(GLint level, const RangeTypeFor& range, Image& image); template void subImage(GLint level, const RangeTypeFor& range, BufferImage& image, BufferUsage usage); #endif @@ -527,6 +529,11 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void MAGNUM_LOCAL getImageImplementationDSA(GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDSAEXT(GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationRobustness(GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); + + void MAGNUM_LOCAL getCompressedImageImplementationDefault(GLint level, std::size_t dataSize, GLvoid* data); + void MAGNUM_LOCAL getCompressedImageImplementationDSA(GLint level, std::size_t dataSize, GLvoid* data); + void MAGNUM_LOCAL getCompressedImageImplementationDSAEXT(GLint level, std::size_t dataSize, GLvoid* data); + void MAGNUM_LOCAL getCompressedImageImplementationRobustness(GLint level, std::size_t dataSize, GLvoid* data); #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/CubeMapTexture.cpp b/src/Magnum/CubeMapTexture.cpp index 36dd58e65..249771c64 100644 --- a/src/Magnum/CubeMapTexture.cpp +++ b/src/Magnum/CubeMapTexture.cpp @@ -85,10 +85,46 @@ BufferImage3D CubeMapTexture::image(const Int level, BufferImage3D&& image, cons return std::move(image); } +void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image) { + const Vector3i size{imageSize(level), 6}; + GLint dataSize; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize); + GLint format; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + Containers::Array data{std::size_t(dataSize)}; + + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); + glGetCompressedTextureImage(_id, level, dataSize, data); + image.setData(CompressedColorFormat(format), size, std::move(data)); +} + +CompressedImage3D CubeMapTexture::compressedImage(const Int level, CompressedImage3D&& image) { + compressedImage(level, image); + return std::move(image); +} + +void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) { + const Vector3i size{imageSize(level), 6}; + GLint dataSize; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize); + GLint format; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + + image.buffer().bindInternal(Buffer::TargetHint::PixelPack); + image.setData(CompressedColorFormat(format), size, {nullptr, std::size_t(dataSize)}, usage); + glGetCompressedTextureImage(_id, level, dataSize, nullptr); +} + +CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) { + compressedImage(level, image, usage); + return std::move(image); +} + void CubeMapTexture::image(const Coordinate coordinate, const Int level, Image2D& image) { const Vector2i size = imageSize(level); const std::size_t dataSize = image.dataSize(size); char* data = new char[dataSize]; + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); (this->*Context::current()->state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, data); image.setData(image.format(), image.type(), size, data); @@ -114,6 +150,41 @@ BufferImage2D CubeMapTexture::image(const Coordinate coordinate, const Int level return std::move(image); } +void CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedImage2D& image) { + const Vector2i size = imageSize(level); + GLint dataSize; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize); + GLint format; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + Containers::Array data{std::size_t(dataSize)}; + + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); + (this->*Context::current()->state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, data); + image.setData(CompressedColorFormat(format), size, std::move(data)); +} + +CompressedImage2D CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedImage2D&& image) { + compressedImage(coordinate, level, image); + return std::move(image); +} + +void CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) { + const Vector2i size = imageSize(level); + GLint dataSize; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &dataSize); + GLint format; + (this->*Context::current()->state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + + image.setData(CompressedColorFormat(format), size, {nullptr, std::size_t(dataSize)}, usage); + image.buffer().bindInternal(Buffer::TargetHint::PixelPack); + (this->*Context::current()->state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr); +} + +CompressedBufferImage2D CubeMapTexture::compressedImage(const Coordinate coordinate, const Int level, CompressedBufferImage2D&& image, const BufferUsage usage) { + compressedImage(coordinate, level, image, usage); + return std::move(image); +} + Image3D CubeMapTexture::subImage(const Int level, const Range3Di& range, Image3D&& image) { this->subImage(level, range, image); return std::move(image); @@ -214,19 +285,38 @@ void CubeMapTexture::getImageImplementationDefault(const Coordinate coordinate, glGetTexImage(GLenum(coordinate), level, GLenum(format), GLenum(type), data); } +void CubeMapTexture::getCompressedImageImplementationDefault(const Coordinate coordinate, const GLint level, const Vector2i&, std::size_t, GLvoid* const data) { + bindInternal(); + glGetCompressedTexImage(GLenum(coordinate), level, data); +} + void CubeMapTexture::getImageImplementationDSA(const Coordinate coordinate, const GLint level, const Vector2i& size, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) { glGetTextureSubImage(_id, level, 0, 0, GLenum(coordinate) - GL_TEXTURE_CUBE_MAP_POSITIVE_X, size.x(), size.y(), 1, GLenum(format), GLenum(type), dataSize, data); } +void CubeMapTexture::getCompressedImageImplementationDSA(const Coordinate coordinate, const GLint level, const Vector2i& size, const std::size_t dataSize, GLvoid* const data) { + glGetCompressedTextureSubImage(_id, level, 0, 0, GLenum(coordinate) - GL_TEXTURE_CUBE_MAP_POSITIVE_X, size.x(), size.y(), 1, dataSize, data); +} + void CubeMapTexture::getImageImplementationDSAEXT(const Coordinate coordinate, const GLint level, const Vector2i&, const ColorFormat format, const ColorType type, std::size_t, GLvoid* const data) { _flags |= ObjectFlag::Created; glGetTextureImageEXT(_id, GLenum(coordinate), level, GLenum(format), GLenum(type), data); } +void CubeMapTexture::getCompressedImageImplementationDSAEXT(const Coordinate coordinate, const GLint level, const Vector2i&, std::size_t, GLvoid* const data) { + _flags |= ObjectFlag::Created; + glGetCompressedTextureImageEXT(_id, GLenum(coordinate), level, data); +} + void CubeMapTexture::getImageImplementationRobustness(const Coordinate coordinate, const GLint level, const Vector2i&, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) { bindInternal(); glGetnTexImageARB(GLenum(coordinate), level, GLenum(format), GLenum(type), dataSize, data); } + +void CubeMapTexture::getCompressedImageImplementationRobustness(const Coordinate coordinate, const GLint level, const Vector2i&, const std::size_t dataSize, GLvoid* const data) { + bindInternal(); + glGetnCompressedTexImageARB(GLenum(coordinate), level, dataSize, data); +} #endif void CubeMapTexture::subImageImplementationDefault(const Coordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const ColorFormat format, const ColorType type, const GLvoid* const data) { diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 7a330a728..f62af5c30 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -478,6 +478,51 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { */ BufferImage3D image(Int level, BufferImage3D&& image, BufferUsage usage); + /** + * @brief Read given mip level of compressed texture to image + * + * Compression format and data size are taken from the texture, image + * size is taken using @ref imageSize(). + * @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter} with + * @def_gl{TEXTURE_COMPRESSED_IMAGE_SIZE}, + * @def_gl{TEXTURE_INTERNAL_FORMAT}, @def_gl{TEXTURE_WIDTH}, + * @def_gl{TEXTURE_HEIGHT}, then + * @fn_gl2{GetCompressedTextureImage,GetCompressedTexImage} + * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedImage3D& image); + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedImage3D image = texture.compressedImage(0, {}); + * @endcode + */ + CompressedImage3D compressedImage(Int level, CompressedImage3D&& image); + + /** + * @brief Read given mip level of compressed texture to buffer image + * + * See @ref compressedImage(Int, CompressedImage3D&) for more + * information. + * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedBufferImage3D& image, BufferUsage usage); + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedBufferImage3D image = texture.compressedImage(0, {}, BufferUsage::StaticRead); + * @endcode + */ + CompressedBufferImage3D compressedImage(Int level, CompressedBufferImage3D&& image, BufferUsage usage); + /** * @brief Read given mip level and coordinate of texture to image * @@ -534,6 +579,63 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { */ BufferImage2D image(Coordinate coordinate, Int level, BufferImage2D&& image, BufferUsage usage); + /** + * @brief Read given mip level and coordinate of compressed texture to image + * + * Compression format and data size are taken from the texture, image + * size is taken using @ref imageSize(). + * + * If neither @extension{ARB,get_texture_sub_image} (part of OpenGL + * 4.5) nor @extension{EXT,direct_state_access} is available, the + * texture is bound before the operation (if not already). If either + * @extension{ARB,get_texture_sub_image} or @extension{ARB,robustness} + * is available, the operation is protected from buffer overflow. + * However, if @extension{ARB,get_texture_sub_image} is not available + * and both @extension{EXT,direct_state_access} and + * @extension{ARB,robustness} are available, the robust operation is + * preferred over DSA. + * @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter}, + * @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access}, + * eventually @fn_gl{GetTexLevelParameter} with + * @def_gl{TEXTURE_COMPRESSED_IMAGE_SIZE}, + * @def_gl{TEXTURE_INTERNAL_FORMAT}, @def_gl{TEXTURE_WIDTH}, + * @def_gl{TEXTURE_HEIGHT}, then @fn_gl{GetCompressedTextureSubImage}, + * @fn_gl_extension{GetnCompressedTexImage,ARB,robustness}, + * @fn_gl_extension{GetCompressedTextureImage,EXT,direct_state_access}, + * eventually @fn_gl{GetCompressedTexImage} + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Coordinate coordinate, Int level, CompressedImage2D& image); + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedImage2D image = texture.compressedImage(CubeMapTexture::Coordinate::PositiveX, 0, {}); + * @endcode + */ + CompressedImage2D compressedImage(Coordinate coordinate, Int level, CompressedImage2D&& image); + + /** + * @brief Read given mip level and coordinate of compressed texture to buffer image + * + * See @ref compressedImage(Coordinate, Int, CompressedImage2D&) for + * more information. + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Coordinate coordinate, Int level, CompressedBufferImage2D& image, BufferUsage usage); + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedBufferImage2D image = texture.compressedImage(CubeMapTexture::Coordinate::PositiveX, 0, {}, BufferUsage::StaticRead); + * @endcode + */ + CompressedBufferImage2D compressedImage(Coordinate coordinate, Int level, CompressedBufferImage2D&& image, BufferUsage usage); + /** * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) * @@ -841,6 +943,11 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { void MAGNUM_LOCAL getImageImplementationDSA(Coordinate coordinate, GLint level, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDSAEXT(Coordinate coordinate, GLint level, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationRobustness(Coordinate coordinate, GLint level, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); + + void MAGNUM_LOCAL getCompressedImageImplementationDefault(Coordinate coordinate, GLint level, const Vector2i& size, std::size_t dataSize, GLvoid* data); + void MAGNUM_LOCAL getCompressedImageImplementationDSA(Coordinate coordinate, GLint level, const Vector2i& size, std::size_t dataSize, GLvoid* data); + void MAGNUM_LOCAL getCompressedImageImplementationDSAEXT(Coordinate coordinate, GLint level, const Vector2i& size, std::size_t dataSize, GLvoid* data); + void MAGNUM_LOCAL getCompressedImageImplementationRobustness(Coordinate coordinate, GLint level, const Vector2i& size, std::size_t dataSize, GLvoid* data); #endif void MAGNUM_LOCAL subImageImplementationDefault(Coordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); diff --git a/src/Magnum/CubeMapTextureArray.cpp b/src/Magnum/CubeMapTextureArray.cpp index 8ddda9de8..a0a8535a0 100644 --- a/src/Magnum/CubeMapTextureArray.cpp +++ b/src/Magnum/CubeMapTextureArray.cpp @@ -59,6 +59,16 @@ BufferImage3D CubeMapTextureArray::image(const Int level, BufferImage3D&& image, return std::move(image); } +CompressedImage3D CubeMapTextureArray::compressedImage(const Int level, CompressedImage3D&& image) { + compressedImage(level, image); + return std::move(image); +} + +CompressedBufferImage3D CubeMapTextureArray::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) { + compressedImage(level, image, usage); + return std::move(image); +} + Image3D CubeMapTextureArray::subImage(const Int level, const Range3Di& range, Image3D&& image) { this->subImage(level, range, image); return std::move(image); diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 3a2eb2eeb..58a68bbe7 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -413,6 +413,48 @@ class MAGNUM_EXPORT CubeMapTextureArray: public AbstractTexture { */ BufferImage3D image(Int level, BufferImage3D&& image, BufferUsage usage); + /** + * @copybrief Texture::compressedImage(Int, CompressedImage&) + * + * See @ref Texture::compressedImage(Int, CompressedImage&) for more + * information. + * @requires_gl Texture image queries are not available in OpenGL ES. + * See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedImage3D& image) { + AbstractTexture::compressedImage<3>(level, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedImage3D image = texture.compressedImage(0, {}); + * @endcode + */ + CompressedImage3D compressedImage(Int level, CompressedImage3D&& image); + + /** + * @copybrief Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) + * + * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) + * for more information. + * @requires_gl Texture image queries are not available in OpenGL ES. + * See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedBufferImage3D& image, BufferUsage usage) { + AbstractTexture::compressedImage<3>(level, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedBufferImage3D image = texture.compressedImage(0, {}, BufferUsage::StaticRead); + * @endcode + */ + CompressedBufferImage3D compressedImage(Int level, CompressedBufferImage3D&& image, BufferUsage usage); + /** * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) * diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 84991a591..7a41fd8be 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -223,31 +223,43 @@ TextureState::TextureState(Context& context, std::vector& extension if(context.isExtensionSupported()) { /* Extension name added above */ getImageImplementation = &AbstractTexture::getImageImplementationDSA; + getCompressedImageImplementation = &AbstractTexture::getCompressedImageImplementationDSA; } else if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::ARB::robustness::string()); getImageImplementation = &AbstractTexture::getImageImplementationRobustness; + getCompressedImageImplementation = &AbstractTexture::getCompressedImageImplementationRobustness; } else if(context.isExtensionSupported()) { /* Extension name added above */ getImageImplementation = &AbstractTexture::getImageImplementationDSAEXT; + getCompressedImageImplementation = &AbstractTexture::getCompressedImageImplementationDSAEXT; - } else getImageImplementation = &AbstractTexture::getImageImplementationDefault; + } else { + getImageImplementation = &AbstractTexture::getImageImplementationDefault; + getCompressedImageImplementation = &AbstractTexture::getCompressedImageImplementationDefault; + } /* Image retrieval implementation for cube map */ if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::ARB::get_texture_sub_image::string()); getCubeImageImplementation = &CubeMapTexture::getImageImplementationDSA; + getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSA; } else if(context.isExtensionSupported()) { /* Extension name added above */ getCubeImageImplementation = &CubeMapTexture::getImageImplementationRobustness; + getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationRobustness; } else if(context.isExtensionSupported()) { /* Extension name added above */ getCubeImageImplementation = &CubeMapTexture::getImageImplementationDSAEXT; + getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSAEXT; - } else getCubeImageImplementation = &CubeMapTexture::getImageImplementationDefault; + } else { + getCubeImageImplementation = &CubeMapTexture::getImageImplementationDefault; + getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDefault; + } #endif /* Texture storage implementation for desktop and ES */ diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 9481e6be8..3114907af 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -70,6 +70,7 @@ struct TextureState { #endif #ifndef MAGNUM_TARGET_GLES void(AbstractTexture::*getImageImplementation)(GLint, ColorFormat, ColorType, std::size_t, GLvoid*); + void(AbstractTexture::*getCompressedImageImplementation)(GLint, std::size_t, GLvoid*); #endif #ifndef MAGNUM_TARGET_GLES void(AbstractTexture::*subImage1DImplementation)(GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); @@ -94,6 +95,7 @@ struct TextureState { #endif #ifndef MAGNUM_TARGET_GLES void(CubeMapTexture::*getCubeImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*); + void(CubeMapTexture::*getCompressedCubeImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, std::size_t, GLvoid*); #endif void(CubeMapTexture::*cubeSubImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*); void(CubeMapTexture::*cubeCompressedSubImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, const Vector2i&, CompressedColorFormat, Containers::ArrayView); diff --git a/src/Magnum/RectangleTexture.cpp b/src/Magnum/RectangleTexture.cpp index deda0f798..1a7b93a2b 100644 --- a/src/Magnum/RectangleTexture.cpp +++ b/src/Magnum/RectangleTexture.cpp @@ -58,6 +58,16 @@ BufferImage2D RectangleTexture::image(BufferImage2D&& image, const BufferUsage u return std::move(image); } +CompressedImage2D RectangleTexture::compressedImage(CompressedImage2D&& image) { + compressedImage(image); + return std::move(image); +} + +CompressedBufferImage2D RectangleTexture::compressedImage(CompressedBufferImage2D&& image, const BufferUsage usage) { + compressedImage(image, usage); + return std::move(image); +} + Image2D RectangleTexture::subImage(const Range2Di& range, Image2D&& image) { this->subImage(range, image); return std::move(image); diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 305aaaf68..5ddbed1bf 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -314,6 +314,44 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { */ BufferImage2D image(BufferImage2D&& image, BufferUsage usage); + /** + * @brief Read compressed texture to image + * + * See @ref Texture::compressedImage(Int, CompressedImage&) for more + * information. + */ + void compressedImage(CompressedImage2D& image) { + AbstractTexture::compressedImage<2>(0, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedImage2D image = texture.compressedimage({}); + * @endcode + */ + CompressedImage2D compressedImage(CompressedImage2D&& image); + + /** + * @brief Read compressed texture to buffer image + * + * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) + * for more information. + */ + void compressedImage(CompressedBufferImage2D& image, BufferUsage usage) { + AbstractTexture::compressedImage<2>(0, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedBufferImage2D image = texture.compressedImage({}, BufferUsage::StaticRead); + * @endcode + */ + CompressedBufferImage2D compressedImage(CompressedBufferImage2D&& image, BufferUsage usage); + /** * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) * diff --git a/src/Magnum/Texture.cpp b/src/Magnum/Texture.cpp index 0d6438fd1..018d8084b 100644 --- a/src/Magnum/Texture.cpp +++ b/src/Magnum/Texture.cpp @@ -73,6 +73,16 @@ template BufferImage Texture::im return std::move(image); } +template CompressedImage Texture::compressedImage(const Int level, CompressedImage&& image) { + compressedImage(level, image); + return std::move(image); +} + +template CompressedBufferImage Texture::compressedImage(const Int level, CompressedBufferImage&& image, const BufferUsage usage) { + compressedImage(level, image, usage); + return std::move(image); +} + template Image Texture::subImage(const Int level, const RangeTypeFor& range, Image&& image) { this->subImage(level, range, image); return std::move(image); diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 6ed8efaec..06f37c37b 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -697,6 +697,74 @@ template class Texture: public AbstractTexture { */ BufferImage image(Int level, BufferImage&& image, BufferUsage usage); + /** + * @brief Read given mip level of compressed texture to image + * @param level Mip level + * @param image Image where to put the compressed data + * + * Compression format and data size are taken from the texture, image + * size is taken using @ref imageSize(). + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} is available, the texture is + * bound before the operation (if not already). If either + * @extension{ARB,direct_state_access} or @extension{ARB,robustness} + * is available, the operation is protected from buffer overflow. + * However, if @extension{ARB,direct_state_access} is not available and + * both @extension{EXT,direct_state_access} and @extension{ARB,robustness} + * are available, the robust operation is preferred over DSA. + * @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter}, + * @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access}, + * eventually @fn_gl{GetTexLevelParameter} with + * @def_gl{TEXTURE_COMPRESSED_IMAGE_SIZE}, + * @def_gl{TEXTURE_INTERNAL_FORMAT}, @def_gl{TEXTURE_WIDTH}, + * @def_gl{TEXTURE_HEIGHT}, @def_gl{TEXTURE_DEPTH}, then + * @fn_gl2{GetCompressedTextureImage,GetCompressedTexImage}, + * @fn_gl_extension{GetnCompressedTexImage,ARB,robustness}, + * @fn_gl_extension{GetCompressedTextureImage,EXT,direct_state_access}, + * eventually @fn_gl{GetCompressedTexImage} + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedImage& image) { + AbstractTexture::compressedImage(level, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedImage2D image = texture.compressedImage(0, {}); + * @endcode + */ + CompressedImage compressedImage(Int level, CompressedImage&& image); + + /** + * @brief Read given mip level of compressed texture to buffer image + * @param level Mip level + * @param image Buffer image where to put the compressed data + * @param usage Buffer usage + * + * See @ref compressedImage(Int, CompressedImage&) for more + * information. + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + * @todo Make it more flexible (usable with + * @extension{ARB,buffer_storage}, avoiding relocations...) + */ + void compressedImage(Int level, CompressedBufferImage& image, BufferUsage usage) { + AbstractTexture::compressedImage(level, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedBufferImage2D image = texture.compressedImage(0, {}, BufferUsage::StaticRead); + * @endcode + */ + CompressedBufferImage compressedImage(Int level, CompressedBufferImage&& image, BufferUsage usage); + /** * @brief Read range of given texture mip level to image * @param level Mip level diff --git a/src/Magnum/TextureArray.cpp b/src/Magnum/TextureArray.cpp index 6da5d90ac..de611004f 100644 --- a/src/Magnum/TextureArray.cpp +++ b/src/Magnum/TextureArray.cpp @@ -65,6 +65,16 @@ template BufferImage TextureArray CompressedImage TextureArray::compressedImage(const Int level, CompressedImage&& image) { + compressedImage(level, image); + return std::move(image); +} + +template CompressedBufferImage TextureArray::compressedImage(const Int level, CompressedBufferImage&& image, const BufferUsage usage) { + compressedImage(level, image, usage); + return std::move(image); +} + template Image TextureArray::subImage(const Int level, const RangeTypeFor& range, Image&& image) { this->subImage(level, range, image); return std::move(image); diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index b51b394b2..9b95b18a1 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -436,6 +436,50 @@ template class TextureArray: public AbstractTexture { */ BufferImage image(Int level, BufferImage&& image, BufferUsage usage); + /** + * @copybrief Texture::compressedImage(Int, CompressedImage&) + * @return Reference to self (for method chaining) + * + * See @ref Texture::compressedImage(Int, CompressedImage&) for more + * information. + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedImage& image) { + AbstractTexture::compressedImage(level, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedImage3D image = texture.compressedImage(0, {}); + * @endcode + */ + CompressedImage compressedImage(Int level, CompressedImage&& image); + + /** + * @copybrief Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) + * @return Reference to self (for method chaining) + * + * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) + * for more information. + * @requires_gl Texture image queries are not available in OpenGL ES or + * WebGL. See @ref Framebuffer::read() for possible workaround. + */ + void compressedImage(Int level, CompressedBufferImage& image, BufferUsage usage) { + AbstractTexture::compressedImage(level, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * CompressedBufferImage3D image = texture.compressedImage(0, {}, BufferUsage::StaticRead); + * @endcode + */ + CompressedBufferImage compressedImage(Int level, CompressedBufferImage&& image, BufferUsage usage); + /** * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) *