From c470bc1e858dd46c2e497582f726437238fc509e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 29 Jul 2015 19:15:53 +0200 Subject: [PATCH] Compressed image support, part 7: compressed (sub)image upload. No tests yet. --- doc/opengl-mapping.dox | 4 +- doc/opengl-support.dox | 1 - src/Magnum/AbstractTexture.cpp | 135 +++++++++++++++++++++ src/Magnum/AbstractTexture.h | 28 +++++ src/Magnum/CubeMapTexture.cpp | 42 +++++++ src/Magnum/CubeMapTexture.h | 106 ++++++++++++++++ src/Magnum/CubeMapTextureArray.h | 61 ++++++++++ src/Magnum/Implementation/TextureState.cpp | 12 ++ src/Magnum/Implementation/TextureState.h | 4 + src/Magnum/MultisampleTexture.h | 2 + src/Magnum/RectangleTexture.h | 53 ++++++++ src/Magnum/Texture.h | 101 +++++++++++++++ src/Magnum/TextureArray.h | 66 ++++++++++ 13 files changed, 612 insertions(+), 3 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index c5575b2bc..8d7da9911 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -97,8 +97,8 @@ OpenGL function | Matching API @fn_gl{ClipControl} | | @fn_gl{ColorMask} | @ref Renderer::setColorMask() @fn_gl{CompileShader} | @ref Shader::compile() -@fn_gl{CompressedTexImage1D}, \n @fn_gl_extension{CompressedTextureImage1D,EXT,direct_state_access}, \n @fn_gl{CompressedTexImage2D}, \n @fn_gl_extension{CompressedTextureImage2D,EXT,direct_state_access}, \n @fn_gl{CompressedTexImage3D}, \n @fn_gl_extension{CompressedTextureImage3D,EXT,direct_state_access} | | -@fn_gl{CompressedTexSubImage1D}, \n `glCompressedTextureSubImage1D()`, \n @fn_gl_extension{CompressedTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage2D}, \n `glCompressedTextureSubImage2D()`, \n @fn_gl_extension{CompressedTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage3D}, \n `glCompressedTextureSubImage3D()`, \n @fn_gl_extension{CompressedTextureSubImage3D,EXT,direct_state_access} | | +@fn_gl{CompressedTexImage1D}, \n @fn_gl{CompressedTexImage2D}, \n @fn_gl{CompressedTexImage3D} | @ref Texture::setCompressedImage(), \n @ref TextureArray::setCompressedImage(), \n @ref CubeMapTexture::setCompressedImage(), \n @ref CubeMapTextureArray::setCompressedImage(), \n @ref RectangleTexture::setCompressedImage() +@fn_gl{CompressedTexSubImage1D}, \n `glCompressedTextureSubImage1D()`, \n @fn_gl_extension{CompressedTextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage2D}, \n `glCompressedTextureSubImage2D()`, \n @fn_gl_extension{CompressedTextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{CompressedTexSubImage3D}, \n `glCompressedTextureSubImage3D()`, \n @fn_gl_extension{CompressedTextureSubImage3D,EXT,direct_state_access} | @ref Texture::setCompressedSubImage(), \n @ref TextureArray::setCompressedSubImage(), \n @ref CubeMapTexture::setCompressedSubImage(), \n @ref CubeMapTextureArray::setCompressedSubImage(), \n @ref RectangleTexture::setCompressedSubImage() @fn_gl{CopyBufferSubData}, \n `glCopyNamedBufferSubData()`, \n @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access} | @ref Buffer::copy() @fn_gl{CopyImageSubData} | | @fn_gl{CopyTexImage1D}, \n @fn_gl_extension{CopyTextureImage1D,EXT,direct_state_access}, \n @fn_gl{CopyTexImage2D}, \n @fn_gl_extension{CopyTextureImage2D,EXT,direct_state_access} | | diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 7bcf2d137..c69aeabf6 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -40,7 +40,6 @@ The core subset of OpenGL 2.1 should be fully implemented, except for the following: - Pixel store state (@fn_gl{PixelStore} function) -- Compressed texture upload - Proxy textures - Copying framebuffer to texture (@fn_gl{CopyTexImage2D} etc.) - Some forgotten limit queries diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 7d5b25df6..9e3f7599b 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -1249,14 +1249,28 @@ void AbstractTexture::subImageImplementationDefault(GLint level, const Math::Vec glTexSubImage1D(_target, level, offset[0], size[0], GLenum(format), GLenum(type), data); } +void AbstractTexture::compressedSubImageImplementationDefault(const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, const CompressedColorFormat format, const Containers::ArrayView data) { + bindInternal(); + glCompressedTexSubImage1D(_target, level, offset[0], size[0], GLenum(format), data.size(), data); +} + void AbstractTexture::subImageImplementationDSA(const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, const ColorFormat format, const ColorType type, const GLvoid* const data) { glTextureSubImage1D(_id, level, offset[0], size[0], GLenum(format), GLenum(type), data); } +void AbstractTexture::compressedSubImageImplementationDSA(const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, const CompressedColorFormat format, const Containers::ArrayView data) { + glCompressedTextureSubImage1D(_id, level, offset[0], size[0], GLenum(format), data.size(), data); +} + void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data) { _flags |= ObjectFlag::Created; glTextureSubImage1DEXT(_id, _target, level, offset[0], size[0], GLenum(format), GLenum(type), data); } + +void AbstractTexture::compressedSubImageImplementationDSAEXT(const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, const CompressedColorFormat format, const Containers::ArrayView data) { + _flags |= ObjectFlag::Created; + glCompressedTextureSubImage1DEXT(_id, _target, level, offset[0], size[0], GLenum(format), data.size(), data); +} #endif void AbstractTexture::subImageImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) { @@ -1264,15 +1278,29 @@ void AbstractTexture::subImageImplementationDefault(GLint level, const Vector2i& glTexSubImage2D(_target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data); } +void AbstractTexture::compressedSubImageImplementationDefault(const GLint level, const Vector2i& offset, const Vector2i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + bindInternal(); + glCompressedTexSubImage2D(_target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), data.size(), data); +} + #ifndef MAGNUM_TARGET_GLES void AbstractTexture::subImageImplementationDSA(const GLint level, const Vector2i& offset, const Vector2i& size, const ColorFormat format, const ColorType type, const GLvoid* const data) { glTextureSubImage2D(_id, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data); } +void AbstractTexture::compressedSubImageImplementationDSA(const GLint level, const Vector2i& offset, const Vector2i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + glCompressedTextureSubImage2D(_id, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), data.size(), data); +} + void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data) { _flags |= ObjectFlag::Created; glTextureSubImage2DEXT(_id, _target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data); } + +void AbstractTexture::compressedSubImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Corrade::Containers::ArrayView< const GLvoid > data) { + _flags |= ObjectFlag::Created; + glCompressedTextureSubImage2DEXT(_id, _target, level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), data.size(), data); +} #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) @@ -1292,6 +1320,22 @@ void AbstractTexture::subImageImplementationDefault(GLint level, const Vector3i& CORRADE_ASSERT_UNREACHABLE(); #endif } + +void AbstractTexture::compressedSubImageImplementationDefault(const GLint level, const Vector3i& offset, const Vector3i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + bindInternal(); + #ifndef MAGNUM_TARGET_GLES2 + glCompressedTexSubImage3D(_target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), data.size(), data); + #elif !defined(CORRADE_TARGET_NACL) + glCompressedTexSubImage3DOES(_target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), data.size(), data); + #else + static_cast(level); + static_cast(offset); + static_cast(size); + static_cast(format); + static_cast(data); + CORRADE_ASSERT_UNREACHABLE(); + #endif +} #endif #ifndef MAGNUM_TARGET_GLES @@ -1299,10 +1343,19 @@ void AbstractTexture::subImageImplementationDSA(const GLint level, const Vector3 glTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data); } +void AbstractTexture::compressedSubImageImplementationDSA(const GLint level, const Vector3i& offset, const Vector3i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), data.size(), data); +} + void AbstractTexture::subImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data) { _flags |= ObjectFlag::Created; glTextureSubImage3DEXT(_id, _target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), GLenum(type), data); } + +void AbstractTexture::compressedSubImageImplementationDSAEXT(const GLint level, const Vector3i& offset, const Vector3i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + _flags |= ObjectFlag::Created; + glCompressedTextureSubImage3DEXT(_id, _target, level, offset.x(), offset.y(), offset.z(), size.x(), size.y(), size.z(), GLenum(format), data.size(), data); +} #endif void AbstractTexture::invalidateImageImplementationNoOp(GLint) {} @@ -1453,21 +1506,43 @@ void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GL glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(image.format()), GLenum(image.type()), image.data()); } +void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView1D& image) { + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + texture.bindInternal(); + glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, image.data().size(), image.data()); +} + void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); texture.bindInternal(); glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(image.format()), GLenum(image.type()), nullptr); } +void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage1D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + texture.bindInternal(); + glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, image.dataSize(), nullptr); +} + void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); (texture.*Context::current()->state().texture->subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data()); } +void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) { + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + (texture.*Context::current()->state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), image.data()); +} + void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); (texture.*Context::current()->state().texture->subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr); } + +void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, CompressedBufferImage1D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + (texture.*Context::current()->state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), {nullptr, image.dataSize()}); +} #endif void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageView2D& image) { @@ -1478,12 +1553,26 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), image.data()); } +void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, const CompressedImageView2D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + #endif + texture.bindInternal(); + glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, image.data().size(), image.data()); +} + #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); texture.bindInternal(); glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); } + +void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, CompressedBufferImage2D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + texture.bindInternal(); + glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, image.dataSize(), nullptr); +} #endif void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, const ImageView2D& image) { @@ -1493,11 +1582,23 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const (texture.*Context::current()->state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data()); } +void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, const CompressedImageView2D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + #endif + (texture.*Context::current()->state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), image.data()); +} + #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, BufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); (texture.*Context::current()->state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr); } + +void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + (texture.*Context::current()->state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), {nullptr, image.dataSize()}); +} #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) @@ -1517,6 +1618,22 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL CORRADE_ASSERT_UNREACHABLE(); #endif } + +void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView3D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + #endif + texture.bindInternal(); + #ifndef MAGNUM_TARGET_GLES2 + glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, image.data().size(), image.data()); + #elif !defined(CORRADE_TARGET_NACL) + glCompressedTexImage3DOES(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, image.data().size(), image.data()); + #else + static_cast(level); + static_cast(image); + CORRADE_ASSERT_UNREACHABLE(); + #endif +} #endif #ifndef MAGNUM_TARGET_GLES2 @@ -1525,6 +1642,12 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL texture.bindInternal(); glTexImage3D(texture._target, level, GLint(internalFormat), image.size().x(), image.size().y(), image.size().z(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); } + +void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + texture.bindInternal(); + glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, image.dataSize(), nullptr); +} #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) @@ -1534,6 +1657,13 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const #endif (texture.*Context::current()->state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data()); } + +void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, const CompressedImageView3D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + #endif + (texture.*Context::current()->state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), image.data()); +} #endif #ifndef MAGNUM_TARGET_GLES2 @@ -1541,6 +1671,11 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); (texture.*Context::current()->state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr); } + +void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + (texture.*Context::current()->state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), {nullptr, image.dataSize()}); +} #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 31a401579..c440ecdf5 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -533,20 +533,30 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void MAGNUM_LOCAL subImageImplementationDefault(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSA(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, ColorFormat format, ColorType type, const GLvoid* data); + + void MAGNUM_LOCAL compressedSubImageImplementationDefault(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, CompressedColorFormat format, Containers::ArrayView data); + void MAGNUM_LOCAL compressedSubImageImplementationDSA(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, CompressedColorFormat format, Containers::ArrayView data); + void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLsizei>& size, CompressedColorFormat format, Containers::ArrayView data); #endif void MAGNUM_LOCAL subImageImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); + void MAGNUM_LOCAL compressedSubImageImplementationDefault(GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Containers::ArrayView data); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL subImageImplementationDSA(GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); + void MAGNUM_LOCAL compressedSubImageImplementationDSA(GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Containers::ArrayView data); + void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Containers::ArrayView data); #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void MAGNUM_LOCAL subImageImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); + void MAGNUM_LOCAL compressedSubImageImplementationDefault(GLint level, const Vector3i& offset, const Vector3i& size, CompressedColorFormat format, Containers::ArrayView data); #endif #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL subImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, ColorFormat format, ColorType type, const GLvoid* data); + void MAGNUM_LOCAL compressedSubImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, CompressedColorFormat format, Containers::ArrayView data); + void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(GLint level, const Vector3i& offset, const Vector3i& size, CompressedColorFormat format, Containers::ArrayView data); #endif void MAGNUM_LOCAL invalidateImageImplementationNoOp(GLint level); @@ -577,9 +587,13 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<1> { static void setImage(AbstractTexture& texture, GLint level, TextureFormat internalFormat, const ImageView1D& image); static void setImage(AbstractTexture& texture, GLint level, TextureFormat internalFormat, BufferImage1D& image); + static void setCompressedImage(AbstractTexture& texture, GLint level, const CompressedImageView1D& image); + static void setCompressedImage(AbstractTexture& texture, GLint level, CompressedBufferImage1D& image); static void setSubImage(AbstractTexture& texture, GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image); static void setSubImage(AbstractTexture& texture, GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image); + static void setCompressedSubImage(AbstractTexture& texture, GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image); + static void setCompressedSubImage(AbstractTexture& texture, GLint level, const Math::Vector<1, GLint>& offset, CompressedBufferImage1D& image); static void invalidateSubImage(AbstractTexture& texture, GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size); }; @@ -601,16 +615,26 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { setImage(texture, texture._target, level, internalFormat, image); } static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageView2D& image); + static void setCompressedImage(AbstractTexture& texture, GLint level, const CompressedImageView2D& image) { + setCompressedImage(texture, texture._target, level, image); + } + static void setCompressedImage(AbstractTexture& texture, GLenum target, GLint level, const CompressedImageView2D& image); #ifndef MAGNUM_TARGET_GLES2 static void setImage(AbstractTexture& texture, GLint level, TextureFormat internalFormat, BufferImage2D& image) { setImage(texture, texture._target, level, internalFormat, image); } static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image); + static void setCompressedImage(AbstractTexture& texture, GLint level, CompressedBufferImage2D& image) { + setCompressedImage(texture, texture._target, level, image); + } + static void setCompressedImage(AbstractTexture& texture, GLenum target, GLint level, CompressedBufferImage2D& image); #endif static void setSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, const ImageView2D& image); + static void setCompressedSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, const CompressedImageView2D& image); #ifndef MAGNUM_TARGET_GLES2 static void setSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, BufferImage2D& image); + static void setCompressedSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, CompressedBufferImage2D& image); #endif static void invalidateSubImage(AbstractTexture& texture, GLint level, const Vector2i& offset, const Vector2i& size); @@ -630,13 +654,17 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { #endif static void setImage(AbstractTexture& texture, GLint level, TextureFormat internalFormat, const ImageView3D& image); + static void setCompressedImage(AbstractTexture& texture, GLint level, const CompressedImageView3D& image); #ifndef MAGNUM_TARGET_GLES2 static void setImage(AbstractTexture& texture, GLint level, TextureFormat internalFormat, BufferImage3D& image); + static void setCompressedImage(AbstractTexture& texture, GLint level, CompressedBufferImage3D& image); #endif static void setSubImage(AbstractTexture& texture, GLint level, const Vector3i& offset, const ImageView3D& image); + static void setCompressedSubImage(AbstractTexture& texture, GLint level, const Vector3i& offset, const CompressedImageView3D& image); #ifndef MAGNUM_TARGET_GLES2 static void setSubImage(AbstractTexture& texture, GLint level, const Vector3i& offset, BufferImage3D& image); + static void setCompressedSubImage(AbstractTexture& texture, GLint level, const Vector3i& offset, CompressedBufferImage3D& image); #endif #endif diff --git a/src/Magnum/CubeMapTexture.cpp b/src/Magnum/CubeMapTexture.cpp index 41c7b7bef..36dd58e65 100644 --- a/src/Magnum/CubeMapTexture.cpp +++ b/src/Magnum/CubeMapTexture.cpp @@ -135,6 +135,18 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off glTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), GLenum(image.type()), nullptr); return *this; } + +CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vector3i& offset, const CompressedImageView3D& image) { + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), image.data().size(), image.data()); + return *this; +} + +CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vector3i& offset, CompressedBufferImage3D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), image.dataSize(), nullptr); + return *this; +} #endif CubeMapTexture& CubeMapTexture::setSubImage(const Coordinate coordinate, const Int level, const Vector2i& offset, const ImageView2D& image) { @@ -153,6 +165,22 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Coordinate coordinate, const I } #endif +CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Coordinate coordinate, const Int level, const Vector2i& offset, const CompressedImageView2D& image) { + #ifndef MAGNUM_TARGET_GLES2 + Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + #endif + (this->*Context::current()->state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.data()); + return *this; +} + +#ifndef MAGNUM_TARGET_GLES2 +CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Coordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) { + image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); + (this->*Context::current()->state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), {nullptr, image.dataSize()}); + return *this; +} +#endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Vector2i CubeMapTexture::getImageSizeImplementationDefault(const Int level) { Vector2i size; @@ -206,15 +234,29 @@ void CubeMapTexture::subImageImplementationDefault(const Coordinate coordinate, glTexSubImage2D(GLenum(coordinate), level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data); } +void CubeMapTexture::compressedSubImageImplementationDefault(const Coordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + bindInternal(); + glCompressedTexSubImage2D(GLenum(coordinate), level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), data.size(), data); +} + #ifndef MAGNUM_TARGET_GLES void CubeMapTexture::subImageImplementationDSA(const Coordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const ColorFormat format, const ColorType type, const GLvoid* const data) { glTextureSubImage3D(_id, level, offset.x(), offset.y(), GLenum(coordinate) - GL_TEXTURE_CUBE_MAP_POSITIVE_X, size.x(), size.y(), 1, GLenum(format), GLenum(type), data); } +void CubeMapTexture::compressedSubImageImplementationDSA(const Coordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), GLenum(coordinate) - GL_TEXTURE_CUBE_MAP_POSITIVE_X, size.x(), size.y(), 1, GLenum(format), data.size(), data); +} + void CubeMapTexture::subImageImplementationDSAEXT(const Coordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const ColorFormat format, const ColorType type, const GLvoid* const data) { _flags |= ObjectFlag::Created; glTextureSubImage2DEXT(_id, GLenum(coordinate), level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), GLenum(type), data); } + +void CubeMapTexture::compressedSubImageImplementationDSAEXT(const Coordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const CompressedColorFormat format, const Containers::ArrayView data) { + _flags |= ObjectFlag::Created; + glTextureSubImage2DEXT(_id, GLenum(coordinate), level, offset.x(), offset.y(), size.x(), size.y(), GLenum(format), data.size(), data); +} #endif } diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index e2dee33da..7a330a728 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -620,6 +620,47 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { } #endif + /** + * @copybrief Texture::setCompressedImage() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompressedImage() for more information. + * @see @ref maxSize() + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + CubeMapTexture& setCompressedImage(Coordinate coordinate, Int level, const CompressedImageView2D& image) { + DataHelper<2>::setCompressedImage(*this, GLenum(coordinate), level, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + CubeMapTexture& setCompressedImage(Coordinate coordinate, Int level, CompressedBufferImage2D& image) { + DataHelper<2>::setCompressedImage(*this, GLenum(coordinate), level, image); + return *this; + } + + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + CubeMapTexture& setCompressedImage(Coordinate coordinate, Int level, CompressedBufferImage2D&& image) { + return setCompressedImage(coordinate, level, image); + } + #endif + #ifndef MAGNUM_TARGET_GLES /** * @brief Set image subdata @@ -651,6 +692,37 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D&& image) { return setSubImage(level, offset, image); } + + /** + * @brief Set compressed image subdata + * @param level Mip level + * @param offset Offset where to put data in the texture + * @param image @ref CompressedImage3D, @ref CompressedImageView3D + * or compressed @ref Trade::ImageData3D + * @return Reference to self (for method chaining) + * + * @see @ref setStorage(), @fn_gl2{CompressedTextureSubImage3D,CompressedTexSubImage3D} + * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl In OpenGL ES and WebGL you need to set image for each + * face separately. + */ + CubeMapTexture& setCompressedSubImage(Int level, const Vector3i& offset, const CompressedImageView3D& image); + + /** @overload + * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl In OpenGL ES and WebGL you need to set image for each + * face separately. + */ + CubeMapTexture& setCompressedSubImage(Int level, const Vector3i& offset, CompressedBufferImage3D& image); + + /** @overload + * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl In OpenGL ES and WebGL you need to set image for each + * face separately. + */ + CubeMapTexture& setCompressedSubImage(Int level, const Vector3i& offset, CompressedBufferImage3D&& image) { + return setCompressedSubImage(level, offset, image); + } #endif /** @@ -681,6 +753,34 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { } #endif + /** + * @copybrief Texture::setCompressedSubImage() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompressedSubImage() for more information. + */ + CubeMapTexture& setCompressedSubImage(Coordinate coordinate, Int level, const Vector2i& offset, const CompressedImageView2D& image); + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + */ + CubeMapTexture& setCompressedSubImage(Coordinate coordinate, Int level, const Vector2i& offset, CompressedBufferImage2D& image); + + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + */ + CubeMapTexture& setCompressedSubImage(Coordinate coordinate, Int level, const Vector2i& offset, CompressedBufferImage2D&& image) { + return setCompressedSubImage(coordinate, level, offset, image); + } + #endif + /** * @copybrief Texture::generateMipmap() * @return Reference to self (for method chaining) @@ -748,6 +848,12 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { void MAGNUM_LOCAL subImageImplementationDSA(Coordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); void MAGNUM_LOCAL subImageImplementationDSAEXT(Coordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, const GLvoid* data); #endif + + void MAGNUM_LOCAL compressedSubImageImplementationDefault(Coordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Containers::ArrayView data); + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL compressedSubImageImplementationDSA(Coordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Containers::ArrayView data); + void MAGNUM_LOCAL compressedSubImageImplementationDSAEXT(Coordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, CompressedColorFormat format, Containers::ArrayView data); + #endif }; } diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 58a4d2182..3a2eb2eeb 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -494,6 +494,42 @@ class MAGNUM_EXPORT CubeMapTextureArray: public AbstractTexture { return setImage(level, internalFormat, image); } + /** + * @copybrief Texture::setCompressedImage() + * @return Reference to self (for method chaining) + * + * Sets texture image data from three-dimensional image for all cube + * faces for all layers. Each group of 6 2D images is one cube map + * layer, thus Z coordinate of @p image size must be multiple of 6. The + * images are in order of (+X, -X, +Y, -Y, +Z, -Z). + * + * See @ref Texture::setCompressedImage() for more information. + * @see @ref maxSize() + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + CubeMapTextureArray& setCompressedImage(Int level, const CompressedImageView3D& image) { + DataHelper<3>::setCompressedImage(*this, level, image); + return *this; + } + + /** @overload + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + CubeMapTextureArray& setCompressedImage(Int level, CompressedBufferImage3D& image) { + DataHelper<3>::setCompressedImage(*this, level, image); + return *this; + } + + /** @overload + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + CubeMapTextureArray& setCompressedImage(Int level, CompressedBufferImage3D&& image) { + return setCompressedImage(level, image); + } + /** * @copybrief Texture::setSubImage() * @return Reference to self (for method chaining) @@ -519,6 +555,31 @@ class MAGNUM_EXPORT CubeMapTextureArray: public AbstractTexture { return setSubImage(level, offset, image); } + /** + * @copybrief Texture::setCompressedSubImage() + * @return Reference to self (for method chaining) + * + * Z coordinate is equivalent to layer * 6 + number of texture face, + * i.e. +X is `0` and so on, in order of (+X, -X, +Y, -Y, +Z, -Z). + * + * See @ref Texture::setCompressedSubImage() for more information. + */ + CubeMapTextureArray& setCompressedSubImage(Int level, const Vector3i& offset, const CompressedImageView3D& image) { + DataHelper<3>::setCompressedSubImage(*this, level, offset, image); + return *this; + } + + /** @overload */ + CubeMapTextureArray& setCompressedSubImage(Int level, const Vector3i& offset, CompressedBufferImage3D& image) { + DataHelper<3>::setCompressedSubImage(*this, level, offset, image); + return *this; + } + + /** @overload */ + CubeMapTextureArray& setCompressedSubImage(Int level, const Vector3i& offset, CompressedBufferImage3D&& image) { + return setCompressedSubImage(level, offset, image); + } + /** * @copybrief Texture::generateMipmap() * @return Reference to self (for method chaining) diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index cfaee53d2..84991a591 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -128,12 +128,16 @@ TextureState::TextureState(Context& context, std::vector& extension subImage1DImplementation = &AbstractTexture::subImageImplementationDSA; subImage2DImplementation = &AbstractTexture::subImageImplementationDSA; subImage3DImplementation = &AbstractTexture::subImageImplementationDSA; + compressedSubImage1DImplementation = &AbstractTexture::compressedSubImageImplementationDSA; + compressedSubImage2DImplementation = &AbstractTexture::compressedSubImageImplementationDSA; + compressedSubImage3DImplementation = &AbstractTexture::compressedSubImageImplementationDSA; setBufferImplementation = &BufferTexture::setBufferImplementationDSA; setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSA; getCubeImageSizeImplementation = &CubeMapTexture::getImageSizeImplementationDSA; cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDSA; + cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDSA; } else if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); @@ -149,12 +153,16 @@ TextureState::TextureState(Context& context, std::vector& extension subImage1DImplementation = &AbstractTexture::subImageImplementationDSAEXT; subImage2DImplementation = &AbstractTexture::subImageImplementationDSAEXT; subImage3DImplementation = &AbstractTexture::subImageImplementationDSAEXT; + compressedSubImage1DImplementation = &AbstractTexture::compressedSubImageImplementationDSAEXT; + compressedSubImage2DImplementation = &AbstractTexture::compressedSubImageImplementationDSAEXT; + compressedSubImage3DImplementation = &AbstractTexture::compressedSubImageImplementationDSAEXT; setBufferImplementation = &BufferTexture::setBufferImplementationDSAEXT; setBufferRangeImplementation = &BufferTexture::setBufferRangeImplementationDSAEXT; getCubeImageSizeImplementation = &CubeMapTexture::getImageSizeImplementationDSAEXT; cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDSAEXT; + cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDSAEXT; } else #endif @@ -175,10 +183,13 @@ TextureState::TextureState(Context& context, std::vector& extension mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; #ifndef MAGNUM_TARGET_GLES subImage1DImplementation = &AbstractTexture::subImageImplementationDefault; + compressedSubImage1DImplementation = &AbstractTexture::compressedSubImageImplementationDefault; #endif subImage2DImplementation = &AbstractTexture::subImageImplementationDefault; + compressedSubImage2DImplementation = &AbstractTexture::compressedSubImageImplementationDefault; #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) subImage3DImplementation = &AbstractTexture::subImageImplementationDefault; + compressedSubImage3DImplementation = &AbstractTexture::compressedSubImageImplementationDefault; #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -190,6 +201,7 @@ TextureState::TextureState(Context& context, std::vector& extension getCubeImageSizeImplementation = &CubeMapTexture::getImageSizeImplementationDefault; #endif cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDefault; + cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDefault; } /* Data invalidation implementation */ diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 137435731..9481e6be8 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -73,10 +73,13 @@ struct TextureState { #endif #ifndef MAGNUM_TARGET_GLES void(AbstractTexture::*subImage1DImplementation)(GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); + void(AbstractTexture::*compressedSubImage1DImplementation)(GLint, const Math::Vector<1, GLint>&, const Math::Vector<1, GLsizei>&, CompressedColorFormat, Containers::ArrayView); #endif void(AbstractTexture::*subImage2DImplementation)(GLint, const Vector2i&, const Vector2i&, ColorFormat, ColorType, const GLvoid*); + void(AbstractTexture::*compressedSubImage2DImplementation)(GLint, const Vector2i&, const Vector2i&, CompressedColorFormat, Containers::ArrayView); #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void(AbstractTexture::*subImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, ColorFormat, ColorType, const GLvoid*); + void(AbstractTexture::*compressedSubImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, CompressedColorFormat, Containers::ArrayView); #endif void(AbstractTexture::*invalidateImageImplementation)(GLint); void(AbstractTexture::*invalidateSubImageImplementation)(GLint, const Vector3i&, const Vector3i&); @@ -93,6 +96,7 @@ struct TextureState { void(CubeMapTexture::*getCubeImageImplementation)(CubeMapTexture::Coordinate, GLint, const Vector2i&, ColorFormat, ColorType, 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); GLint maxSize, #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 4407a0e27..d9d42e3d8 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -85,6 +85,8 @@ In shader, the texture is used via `sampler2DMS`/`sampler2DMSArray`, @ref AbstractShaderProgram documentation for more information about usage in shaders. +Note that multisample textures don't support compressed formats. + @see @ref MultisampleTexture2D, @ref MultisampleTexture2DArray, @ref Texture, @ref TextureArray, @ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture, @ref BufferTexture diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 25b74b33c..305aaaf68 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -385,6 +385,37 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { return setImage(internalFormat, image); } + /** + * @copybrief Texture::setCompressedImage() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompressedImage() for more information. + * @see @ref maxSize() + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + RectangleTexture& setCompressedImage(const CompressedImageView2D& image) { + DataHelper<2>::setCompressedImage(*this, 0, image); + return *this; + } + + /** @overload + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + RectangleTexture& setCompressedImage(CompressedBufferImage2D& image) { + DataHelper<2>::setCompressedImage(*this, 0, image); + return *this; + } + + /** @overload + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + RectangleTexture& setCompressedImage(CompressedBufferImage2D&& image) { + return setCompressedImage(image); + } + /** * @copybrief Texture::setSubImage() * @return Reference to self (for method chaining) @@ -407,6 +438,28 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { return setSubImage(offset, image); } + /** + * @copybrief Texture::setCompressedSubImage() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompressedSubImage() for more information. + */ + RectangleTexture& setCompressedSubImage(const Vector2i& offset, const CompressedImageView2D& image) { + DataHelper<2>::setCompressedSubImage(*this, 0, offset, image); + return *this; + } + + /** @overload */ + RectangleTexture& setCompressedSubImage(const Vector2i& offset, CompressedBufferImage2D& image) { + DataHelper<2>::setCompressedSubImage(*this, 0, offset, image); + return *this; + } + + /** @overload */ + RectangleTexture& setCompressedSubImage(const Vector2i& offset, CompressedBufferImage2D&& image) { + return setCompressedSubImage(offset, image); + } + /** * @brief Invalidate texture * diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index e05536faa..6ed8efaec 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -800,6 +800,57 @@ template class Texture: public AbstractTexture { } #endif + /** + * @brief Set compressed image data + * @param level Mip level + * @param image @ref CompressedImage, @ref CompressedImageView + * or compressed @ref Trade::ImageData of the same dimension count + * @return Reference to self (for method chaining) + * + * On platforms that support it prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead, as it avoids unnecessary + * reallocations and has better performance characteristics. This call + * also has no equivalent in @extension{ARB,direct_state_access}, thus + * the texture needs to be bound to some texture unit before the + * operation. + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CompressedTexImage1D} / @fn_gl{CompressedTexImage2D} / + * @fn_gl{CompressedTexImage3D} + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + Texture& setCompressedImage(Int level, const CompressedImageView& image) { + DataHelper::setCompressedImage(*this, level, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + Texture& setCompressedImage(Int level, CompressedBufferImage& image) { + DataHelper::setCompressedImage(*this, level, image); + return *this; + } + + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + Texture& setCompressedImage(Int level, CompressedBufferImage&& image) { + return setCompressedImage(level, image); + } + #endif + /** * @brief Set image subdata * @param level Mip level @@ -853,6 +904,56 @@ template class Texture: public AbstractTexture { } #endif + /** + * @brief Set compressed image subdata + * @param level Mip level + * @param offset Offset where to put data in the texture + * @param image @ref CompressedImage, @ref CompressedImageView + * or compressed @ref Trade::ImageData of the same dimension count + * @return Reference to self (for method chaining) + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref setStorage(), @fn_gl2{CompressedTextureSubImage1D,CompressedTexSubImage1D} / + * @fn_gl2{CompressedTextureSubImage2D,CompressedTexSubImage2D} / + * @fn_gl2{CompressedTextureSubImage3D,CompressedTexSubImage3D}, + * @fn_gl_extension{CompressedTextureSubImage1D,EXT,direct_state_access} / + * @fn_gl_extension{CompressedTextureSubImage2D,EXT,direct_state_access} / + * @fn_gl_extension{CompressedTextureSubImage3D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CompressedTexSubImage1D} / @fn_gl{CompressedTexSubImage2D} / + * @fn_gl{CompressedTexSubImage3D} + */ + Texture& setCompressedSubImage(Int level, const VectorTypeFor& offset, const CompressedImageView& image) { + DataHelper::setCompressedSubImage(*this, level, offset, image); + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + */ + Texture& setCompressedSubImage(Int level, const VectorTypeFor& offset, CompressedBufferImage& image) { + DataHelper::setCompressedSubImage(*this, level, offset, image); + return *this; + } + + /** @overload + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. + */ + Texture& setCompressedSubImage(Int level, const VectorTypeFor& offset, CompressedBufferImage&& image) { + return setCompressedSubImage(level, offset, image); + } + #endif + /** * @brief Generate mipmap * @return Reference to self (for method chaining) diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 74ac5af2b..b51b394b2 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -512,6 +512,37 @@ template class TextureArray: public AbstractTexture { return setImage(level, internalFormat, image); } + /** + * @copybrief Texture::setCompressedImage() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompressedImage() for more information. + * @see @ref maxSize() + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + TextureArray& setCompressedImage(Int level, const CompressedImageView& image) { + DataHelper::setCompressedImage(*this, level, image); + return *this; + } + + /** @overload + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + TextureArray& setCompressedImage(Int level, CompressedBufferImage& image) { + DataHelper::setCompressedImage(*this, level, image); + return *this; + } + + /** @overload + * @deprecated_gl Prefer to use @ref setStorage() and + * @ref setCompressedSubImage() instead. + */ + TextureArray& setCompressedImage(Int level, CompressedBufferImage&& image) { + return setCompressedImage(level, image); + } + /** * @brief Set image subdata * @param level Mip level @@ -547,6 +578,41 @@ template class TextureArray: public AbstractTexture { return setSubImage(level, offset, image); } + /** + * @brief Set compressed image subdata + * @param level Mip level + * @param offset Offset where to put data in the texture + * @param image @ref CompressedImage, @ref CompressedImageView + * or compressed @ref Trade::ImageData of the same dimension count + * @return Reference to self (for method chaining) + * + * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5) + * nor @extension{EXT,direct_state_access} desktop extension is + * available, the texture is bound before the operation (if not + * already). + * @see @ref setStorage(), @fn_gl2{CompressedTextureSubImage2D,CompressedTexSubImage2D}/ + * @fn_gl2{CompressedTextureSubImage3D,CompressedTexSubImage3D}, + * @fn_gl_extension{CompressedTextureSubImage2D,EXT,direct_state_access}/ + * @fn_gl_extension{CompressedTextureSubImage3D,EXT,direct_state_access}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{CompressedTexSubImage2D}/@fn_gl{CompressedTexSubImage3D} + */ + TextureArray& setCompressedSubImage(Int level, const VectorTypeFor& offset, const CompressedImageView& image) { + DataHelper::setCompressedSubImage(*this, level, offset, image); + return *this; + } + + /** @overload */ + TextureArray& setCompressedSubImage(Int level, const VectorTypeFor& offset, CompressedBufferImage& image) { + DataHelper::setCompressedSubImage(*this, level, offset, image); + return *this; + } + + /** @overload */ + TextureArray& setCompressedSubImage(Int level, const VectorTypeFor& offset, CompressedBufferImage&& image) { + return setCompressedSubImage(level, offset, image); + } + /** * @copybrief Texture::generateMipmap() * @return Reference to self (for method chaining)