diff --git a/doc/changelog.dox b/doc/changelog.dox index e1ba3a647..01613ad7d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -128,6 +128,12 @@ See also: @ref Magnum namespace were moved to @ref Magnum/GL directory and @ref Magnum::GL namespace. See their documentation for information about particular files, classes, enums, typedefs, values and functions. +- @ref PixelStorage::pixelSize() was deprecated, use @ref GL::pixelSize() + instead +- `PixelStorage::dataProperties(GL::PixelFormat, GL::PixelSize, const Vector3i&)` + was deprecated for being too GL-specific, use + @ref PixelStorage::dataProperties(std::size_t, const Vector3i&) const + together with @ref GL::pixelSize() instead - `Audio::Buffer::Format` is deprecated, use `Audio::BufferFormat` instead - `setData()` functions in the @ref Image and @ref CompressedImage classes are deprecated because they don't offer anything extra over simple diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 0699a5b23..c78899486 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -28,6 +28,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake # Files shared between main library and unit test library set(Magnum_SRCS + PixelStorage.cpp Resource.cpp Timeline.cpp) diff --git a/src/Magnum/GL/AbstractFramebuffer.cpp b/src/Magnum/GL/AbstractFramebuffer.cpp index f9b5c3dda..6d8ca6ba9 100644 --- a/src/Magnum/GL/AbstractFramebuffer.cpp +++ b/src/Magnum/GL/AbstractFramebuffer.cpp @@ -43,6 +43,7 @@ #include "Magnum/GL/TextureArray.h" #endif #include "Magnum/GL/Implementation/FramebufferState.h" +#include "Magnum/GL/Implementation/RendererState.h" #include "Magnum/GL/Implementation/State.h" namespace Magnum { namespace GL { @@ -306,10 +307,10 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, Image2D& image) { #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelPack); #endif - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (Context::current().state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), data.size(), data #ifdef MAGNUM_TARGET_GLES2 - + Implementation::pixelStorageSkipOffsetFor(image, rectangle.size()) + + Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size()) #endif ); image = Image2D{image.storage(), image.format(), image.type(), rectangle.size(), std::move(data)}; @@ -332,7 +333,7 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D& image, image.setData(image.storage(), image.format(), image.type(), rectangle.size(), nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (Context::current().state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr); } diff --git a/src/Magnum/GL/AbstractFramebuffer.h b/src/Magnum/GL/AbstractFramebuffer.h index 6398918ee..f9b7b17ec 100644 --- a/src/Magnum/GL/AbstractFramebuffer.h +++ b/src/Magnum/GL/AbstractFramebuffer.h @@ -152,6 +152,12 @@ switching framebuffers. Framebuffer limits and implementation-defined values in repeated @fn_gl{Get} calls. See also @ref Context::resetState() and @ref Context::State::Framebuffers. +Pixel storage mode defined by @ref PixelStorage is applied either right before +doing image download via @ref read() using @fn_gl{PixelStore} with +@def_gl{PACK_*}. The engine tracks currently used pixel pack parameters to +avoid unnecessary calls to @fn_gl{PixelStore}. See also @ref Context::resetState() +and @ref Context::State::PixelStorage. + If extension @extension{ARB,direct_state_access} (part of OpenGL 4.5) is available, @ref blit(), @ref clearDepth(), @ref clearStencil() and @ref clearDepthStencil() functions use DSA to avoid unnecessary call to @@ -342,13 +348,20 @@ class MAGNUM_GL_EXPORT AbstractFramebuffer { * * Image parameters like format and type of pixel data are taken from * given image. The storage is not reallocated if it is large enough to - * contain the new data. + * contain the new data. On OpenGL ES 2.0 and WebGL 1.0, if + * @ref PixelStorage::skip() is set, the functionality is emulated by + * adjusting the data pointer. * * If @extension{ARB,robustness} is available, the operation is * protected from buffer overflow. * @see @fn_gl{BindFramebuffer}, then @fn_gl{PixelStore} and * @fn_gl_keyword{ReadPixels} or * @fn_gl_extension_keyword{ReadnPixels,ARB,robustness} + * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ + * @extension{NV,pack_subimage} in OpenGL ES 2.0 if + * @ref PixelStorage::rowLength() is set to a non-zero value. + * @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not + * supported in WebGL 1.0. */ void read(const Range2Di& rectangle, Image2D& image); diff --git a/src/Magnum/GL/AbstractTexture.cpp b/src/Magnum/GL/AbstractTexture.cpp index 0b298ca49..bd9d18492 100644 --- a/src/Magnum/GL/AbstractTexture.cpp +++ b/src/Magnum/GL/AbstractTexture.cpp @@ -39,6 +39,7 @@ #ifndef MAGNUM_TARGET_WEBGL #include "Magnum/GL/Implementation/DebugState.h" #endif +#include "Magnum/GL/Implementation/RendererState.h" #include "Magnum/GL/Implementation/State.h" #include "Magnum/GL/Implementation/TextureState.h" #include "Magnum/Math/Color.h" @@ -1699,7 +1700,7 @@ template void AbstractTexture::image(GLint level, Image< data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getImageImplementation)(level, image.format(), image.type(), data.size(), data); image = Image{image.storage(), image.format(), image.type(), size, std::move(data)}; } @@ -1719,7 +1720,7 @@ template void AbstractTexture::image(GLint level, Buffer image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr); } @@ -1749,7 +1750,7 @@ template void AbstractTexture::compressedImage(const GLi data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getCompressedImageImplementation)(level, data.size(), data); image = CompressedImage{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -1781,7 +1782,7 @@ template void AbstractTexture::compressedImage(const GLi image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getCompressedImageImplementation)(level, dataSize, nullptr); } @@ -1803,7 +1804,7 @@ template void AbstractTexture::subImage(const GLint leve data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), data.size(), data); image = Image{image.storage(), image.format(), image.type(), size, std::move(data)}; } @@ -1827,7 +1828,7 @@ template void AbstractTexture::subImage(const GLint leve image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, nullptr); } @@ -1868,7 +1869,7 @@ template void AbstractTexture::compressedSubImage(const data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), data.size(), data); image = CompressedImage{CompressedPixelFormat(format), size, std::move(data)}; } @@ -1903,7 +1904,7 @@ template void AbstractTexture::compressedSubImage(const image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), dataSize, nullptr); } @@ -1992,53 +1993,53 @@ void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, const ImageView1D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); texture.bindInternal(); 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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, 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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); 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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, 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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); } void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); } #endif @@ -2047,7 +2048,7 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->image2DImplementation)(target, level, internalFormat, image.size(), image.format(), image.type(), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) @@ -2062,7 +2063,7 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif texture.bindInternal(); glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); @@ -2071,7 +2072,7 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture #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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); } @@ -2081,7 +2082,7 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif texture.bindInternal(); glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); @@ -2092,7 +2093,7 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) @@ -2107,7 +2108,7 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif (texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); } @@ -2115,7 +2116,7 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text #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); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); } @@ -2124,7 +2125,7 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif (texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); } @@ -2135,7 +2136,7 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->image3DImplementation)(level, internalFormat, image.size(), image.format(), image.type(), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) @@ -2150,7 +2151,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif texture.bindInternal(); #ifndef MAGNUM_TARGET_GLES2 @@ -2164,7 +2165,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); 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); } @@ -2174,7 +2175,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif texture.bindInternal(); glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); @@ -2186,7 +2187,7 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) @@ -2201,7 +2202,7 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif (texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); } @@ -2210,7 +2211,7 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, BufferImage3D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); } @@ -2219,7 +2220,7 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif (texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); } diff --git a/src/Magnum/GL/AbstractTexture.h b/src/Magnum/GL/AbstractTexture.h index 57870990b..d8c76ef67 100644 --- a/src/Magnum/GL/AbstractTexture.h +++ b/src/Magnum/GL/AbstractTexture.h @@ -105,6 +105,19 @@ 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 version is preferred over DSA. +Pixel storage mode defined by @ref PixelStorage and @ref CompressedPixelStorage +is applied either right before doing image upload (such as various +@ref Texture::setImage() "setImage()", @ref Texture::setSubImage() "setSubImage()", +@ref Texture::setCompressedImage() "setCompressedImage()" or +@ref Texture::setCompressedSubImage() "setCompressedSubImage()" functions) +using @fn_gl_keyword{PixelStore} with @def_gl{UNPACK_*} parameters or right +before doing image download (such as various @ref Texture::image() "image()", +@ref Texture::subImage() "subImage()", @ref Texture::compressedImage() "compressedImage()", +or @ref Texture::compressedSubImage() "compressedSubImage()" functions) using +@fn_gl{PixelStore} with @def_gl{PACK_*}. The engine tracks currently used pixel +pack/unpack parameters to avoid unnecessary calls to @fn_gl{PixelStore}. See +also @ref Context::resetState() and @ref Context::State::PixelStorage. + To achieve least state changes, fully configure each texture in one run -- method chaining comes in handy --- and try to have often used textures in dedicated units, not occupied by other textures. First configure the texture diff --git a/src/Magnum/GL/BufferImage.h b/src/Magnum/GL/BufferImage.h index c308f319c..0b7bbd442 100644 --- a/src/Magnum/GL/BufferImage.h +++ b/src/Magnum/GL/BufferImage.h @@ -147,7 +147,7 @@ template class BufferImage { /** * @brief Pixel size (in bytes) * - * @see @ref PixelStorage::pixelSize() + * @see @ref Magnum::pixelSize(), @ref GL::pixelSize() */ std::size_t pixelSize() const { return PixelStorage::pixelSize(_format, _type); } diff --git a/src/Magnum/GL/CMakeLists.txt b/src/Magnum/GL/CMakeLists.txt index 1408e5aa7..9e2a9dabd 100644 --- a/src/Magnum/GL/CMakeLists.txt +++ b/src/Magnum/GL/CMakeLists.txt @@ -40,7 +40,6 @@ set(MagnumGL_SRCS MeshView.cpp OpenGL.cpp PixelFormat.cpp - ../PixelStorage.cpp # temporary Renderbuffer.cpp Renderer.cpp Sampler.cpp diff --git a/src/Magnum/GL/CubeMapTexture.cpp b/src/Magnum/GL/CubeMapTexture.cpp index 72bb2afbc..6c9c2e26e 100644 --- a/src/Magnum/GL/CubeMapTexture.cpp +++ b/src/Magnum/GL/CubeMapTexture.cpp @@ -31,6 +31,7 @@ #endif #include "Magnum/GL/Context.h" #include "Magnum/GL/Implementation/maxTextureSize.h" +#include "Magnum/GL/Implementation/RendererState.h" #include "Magnum/GL/Implementation/State.h" #include "Magnum/GL/Implementation/TextureState.h" @@ -72,7 +73,7 @@ void CubeMapTexture::image(const Int level, Image3D& image) { data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); glGetTextureImage(_id, level, GLenum(image.format()), GLenum(image.type()), data.size(), data); image = Image3D{image.storage(), image.format(), image.type(), size, std::move(data)}; } @@ -95,7 +96,7 @@ void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUs image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); glGetTextureImage(_id, level, GLenum(image.format()), GLenum(image.type()), dataSize, nullptr); } @@ -127,7 +128,7 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image) data = Containers::Array{dataOffset + dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffset, dataSize, data); image = CompressedImage3D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -161,7 +162,7 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffset, dataSize, nullptr); } @@ -180,7 +181,7 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), data.size(), data); image = Image2D{image.storage(), image.format(), image.type(), size, std::move(data)}; } @@ -201,7 +202,7 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr); } @@ -231,7 +232,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data); image = CompressedImage2D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -263,7 +264,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - image.storage().applyPack(); + Context::current().state().renderer->applyPixelStoragePack(image.storage()); (this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr); } @@ -296,7 +297,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off createIfNotAlready(); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), image.data(), image.storage()); return *this; } @@ -305,7 +306,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off createIfNotAlready(); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); 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; } @@ -314,7 +315,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec createIfNotAlready(); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); return *this; } @@ -323,7 +324,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec createIfNotAlready(); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); return *this; } @@ -333,7 +334,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) @@ -345,7 +346,7 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, #ifndef MAGNUM_TARGET_GLES2 CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, BufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); (this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr); return *this; } @@ -358,7 +359,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate co #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif (this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); return *this; @@ -370,7 +371,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate co #ifndef MAGNUM_TARGET_GLES /* Pixel storage is completely ignored for compressed images on ES, no need to reset anything */ - image.storage().applyUnpack(); + Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); #endif (this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); return *this; diff --git a/src/Magnum/GL/CubeMapTexture.h b/src/Magnum/GL/CubeMapTexture.h index ce5e73631..80eefc54e 100644 --- a/src/Magnum/GL/CubeMapTexture.h +++ b/src/Magnum/GL/CubeMapTexture.h @@ -567,6 +567,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * @def_gl{TEXTURE_INTERNAL_FORMAT}, @def_gl{TEXTURE_WIDTH}, * @def_gl{TEXTURE_HEIGHT}, then * @fn_gl2_keyword{GetCompressedTextureImage,GetCompressedTexImage} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @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() or @ref DebugTools::textureSubImage() @@ -589,6 +591,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * information. The storage is not reallocated if it is large enough to * contain the new data, which means that @p usage might get ignored. * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -689,6 +693,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * @fn_gl_extension_keyword{GetnCompressedTexImage,ARB,robustness}, * @fn_gl_extension_keyword{GetCompressedTextureImage,EXT,direct_state_access}, * eventually @fn_gl_keyword{GetCompressedTexImage} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -710,6 +716,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * for more information. The storage is not reallocated if it is large * enough to contain the new data, which means that @p usage might get * ignored. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -774,6 +782,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedImage&) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -800,6 +810,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedBufferImage&, BufferUsage) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -827,6 +839,11 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * * See @ref Texture::setImage() for more information. * @see @ref maxSize() + * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ + * @extension{NV,pack_subimage} in OpenGL ES 2.0 if + * @ref PixelStorage::rowLength() is set to a non-zero value. + * @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not + * supported in WebGL 1.0. * @deprecated_gl Prefer to use @ref setStorage() and @ref setSubImage() * instead. */ @@ -868,6 +885,10 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * * See @ref Texture::setCompressedImage() for more information. * @see @ref maxSize() + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -878,6 +899,10 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { #ifndef MAGNUM_TARGET_GLES2 /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL @@ -891,6 +916,10 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { } /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL @@ -945,6 +974,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * * @see @ref setStorage(), @fn_gl2{CompressedTextureSubImage3D,CompressedTexSubImage3D} * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl In OpenGL ES and WebGL you need to set image for each * face separately. */ @@ -952,6 +983,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { /** @overload * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl In OpenGL ES and WebGL you need to set image for each * face separately. */ @@ -959,6 +992,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { /** @overload * @requires_gl45 Extension @extension{ARB,direct_state_access} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl In OpenGL ES and WebGL you need to set image for each * face separately. */ @@ -972,6 +1007,11 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * @return Reference to self (for method chaining) * * See @ref Texture::setSubImage() for more information. + * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ + * @extension{NV,pack_subimage} in OpenGL ES 2.0 if + * @ref PixelStorage::rowLength() is set to a non-zero value. + * @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not + * supported in WebGL 1.0. */ CubeMapTexture& setSubImage(CubeMapCoordinate coordinate, Int level, const Vector2i& offset, const ImageView2D& image); @@ -1000,11 +1040,19 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * @return Reference to self (for method chaining) * * See @ref Texture::setCompressedSubImage() for more information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. */ CubeMapTexture& setCompressedSubImage(CubeMapCoordinate coordinate, Int level, const Vector2i& offset, const CompressedImageView2D& image); #ifndef MAGNUM_TARGET_GLES2 /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL @@ -1013,6 +1061,10 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { CubeMapTexture& setCompressedSubImage(CubeMapCoordinate coordinate, Int level, const Vector2i& offset, CompressedBufferImage2D& image); /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL diff --git a/src/Magnum/GL/CubeMapTextureArray.h b/src/Magnum/GL/CubeMapTextureArray.h index 77396e42e..a442500a1 100644 --- a/src/Magnum/GL/CubeMapTextureArray.h +++ b/src/Magnum/GL/CubeMapTextureArray.h @@ -473,6 +473,8 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * * See @ref Texture::compressedImage(Int, CompressedImage&) for more * information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES. * See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -494,6 +496,8 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) * for more information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES. * See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -560,6 +564,8 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedImage&) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -586,6 +592,8 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedBufferImage&, BufferUsage) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -654,6 +662,10 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * * See @ref Texture::setCompressedImage() for more information. * @see @ref maxSize() + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES. * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -714,19 +726,33 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * -Z). * * See @ref Texture::setCompressedSubImage() for more information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES. */ CubeMapTextureArray& setCompressedSubImage(Int level, const Vector3i& offset, const CompressedImageView3D& image) { DataHelper<3>::setCompressedSubImage(*this, level, offset, image); return *this; } - /** @overload */ + /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES. + */ CubeMapTextureArray& setCompressedSubImage(Int level, const Vector3i& offset, CompressedBufferImage3D& image) { DataHelper<3>::setCompressedSubImage(*this, level, offset, image); return *this; } - /** @overload */ + /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES. + */ CubeMapTextureArray& setCompressedSubImage(Int level, const Vector3i& offset, CompressedBufferImage3D&& image) { return setCompressedSubImage(level, offset, image); } diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index fd934d424..a70d6addb 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -25,6 +25,7 @@ #include "RendererState.h" +#include "Magnum/PixelStorage.h" #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" @@ -118,4 +119,108 @@ void RendererState::PixelStorage::reset() { #endif } + +void RendererState::applyPixelStorageInternal(const Magnum::PixelStorage& storage, const bool isUnpack) { + PixelStorage& state = isUnpack ? unpackPixelStorage : packPixelStorage; + + /* Alignment */ + if(state.alignment == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.alignment != storage.alignment()) + glPixelStorei(isUnpack ? GL_UNPACK_ALIGNMENT : GL_PACK_ALIGNMENT, + state.alignment = storage.alignment()); + + /* Row length */ + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + if(state.rowLength == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.rowLength != storage.rowLength()) + { + /** @todo Use real value for GL_PACK_ROW_LENGTH_NV when it is in headers */ + #ifndef MAGNUM_TARGET_GLES2 + glPixelStorei(isUnpack ? GL_UNPACK_ROW_LENGTH : GL_PACK_ROW_LENGTH, + state.rowLength = storage.rowLength()); + #elif !defined(MAGNUM_TARGET_WEBGL) + glPixelStorei(isUnpack ? GL_UNPACK_ROW_LENGTH_EXT : 0xD02 /*GL_PACK_ROW_LENGTH_NV*/, + state.rowLength = storage.rowLength()); + #endif + } + #else + CORRADE_ASSERT(!storage.rowLength(), + "GL: non-default PixelStorage::rowLength() is not supported in WebGL 1.0", ); + #endif + + #ifndef MAGNUM_TARGET_GLES + /* Image height (on ES for unpack only, taken care of below) */ + if(state.imageHeight == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.imageHeight != storage.imageHeight()) + glPixelStorei(isUnpack ? GL_UNPACK_IMAGE_HEIGHT : GL_PACK_IMAGE_HEIGHT, + state.imageHeight = storage.imageHeight()); + #else + CORRADE_ASSERT(!storage.imageHeight(), + "GL: non-default PixelStorage::imageHeight() is not supported in OpenGL ES", ); + #endif + + /* On ES2 done by modifying data pointer */ + #ifndef MAGNUM_TARGET_GLES2 + /* Skip pixels */ + if(state.skip.x() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.x() != storage.skip().x()) + glPixelStorei(isUnpack ? GL_UNPACK_SKIP_PIXELS : GL_PACK_SKIP_PIXELS, + state.skip.x() = storage.skip().x()); + + /* Skip rows */ + if(state.skip.y() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.y() != storage.skip().y()) + glPixelStorei(isUnpack ? GL_UNPACK_SKIP_ROWS : GL_PACK_SKIP_ROWS, + state.skip.y() = storage.skip().y()); + + #ifndef MAGNUM_TARGET_GLES + /* Skip images (on ES for unpack only, taken care of below) */ + if(state.skip.z() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.z() != storage.skip().z()) + glPixelStorei(isUnpack ? GL_UNPACK_SKIP_IMAGES : GL_PACK_SKIP_IMAGES, + state.skip.z() = storage.skip().z()); + #endif + #endif +} + +void RendererState::applyPixelStorageUnpack(const Magnum::PixelStorage& storage) { + applyPixelStorageInternal(storage, true); + + #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) + PixelStorage& state = unpackPixelStorage; + + /* Image height (on ES for unpack only) */ + if(state.imageHeight == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.imageHeight != storage.imageHeight()) + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, state.imageHeight = storage.imageHeight()); + + /* Skip images (on ES for unpack only) */ + if(state.skip.z() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.z() != storage.skip().z()) + glPixelStorei(GL_UNPACK_SKIP_IMAGES, state.skip.z() = storage.skip().z()); + #endif +} + +void RendererState::applyPixelStorageInternal(const CompressedPixelStorage& storage, const bool isUnpack) { + applyPixelStorageInternal(static_cast(storage), isUnpack); + + PixelStorage& state = isUnpack ? unpackPixelStorage : packPixelStorage; + + /* Compressed block width */ + if(state.compressedBlockSize.x() == PixelStorage::DisengagedValue || + state.compressedBlockSize.x() != storage.compressedBlockSize().x()) + glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_WIDTH : GL_PACK_COMPRESSED_BLOCK_WIDTH, + state.compressedBlockSize.x() = storage.compressedBlockSize().x()); + + /* Compressed block height */ + if(state.compressedBlockSize.y() == PixelStorage::DisengagedValue || + state.compressedBlockSize.y() != storage.compressedBlockSize().y()) + glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_HEIGHT : GL_PACK_COMPRESSED_BLOCK_HEIGHT, + state.compressedBlockSize.y() = storage.compressedBlockSize().y()); + + /* Compressed block depth */ + if(state.compressedBlockSize.z() == PixelStorage::DisengagedValue || + state.compressedBlockSize.z() != storage.compressedBlockSize().z()) + glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_DEPTH : GL_PACK_COMPRESSED_BLOCK_DEPTH, + state.compressedBlockSize.z() = storage.compressedBlockSize().z()); + + /* Compressed block size */ + if(state.compressedBlockDataSize == PixelStorage::DisengagedValue || + state.compressedBlockDataSize != storage.compressedBlockDataSize()) + glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_SIZE : GL_PACK_COMPRESSED_BLOCK_SIZE, + state.compressedBlockDataSize = storage.compressedBlockDataSize()); +} + }}} diff --git a/src/Magnum/GL/Implementation/RendererState.h b/src/Magnum/GL/Implementation/RendererState.h index 1689f4fb9..07ca2df1c 100644 --- a/src/Magnum/GL/Implementation/RendererState.h +++ b/src/Magnum/GL/Implementation/RendererState.h @@ -69,6 +69,28 @@ struct RendererState { }; PixelStorage packPixelStorage, unpackPixelStorage; + + /* Bool parameter is ugly, but this is implementation detail of internal + API so who cares */ + void applyPixelStorageInternal(const Magnum::PixelStorage& storage, bool unpack); + /* Used internally in *Texture::image(), *Texture::subImage(), + *Texture::setImage(), *Texture::setSubImage() and *Framebuffer::read() */ + void applyPixelStoragePack(const Magnum::PixelStorage& storage) { + applyPixelStorageInternal(storage, false); + } + void applyPixelStorageUnpack(const Magnum::PixelStorage& storage); + + /* Bool parameter is ugly, but this is implementation detail of internal + API so who cares */ + void applyPixelStorageInternal(const CompressedPixelStorage& storage, bool unpack); + /* Used internally in *Texture::compressedImage(), *Texture::compressedSubImage(), + *Texture::setCompressedImage() and *Texture::setCompressedSubImage() */ + void applyPixelStoragePack(const CompressedPixelStorage& storage) { + applyPixelStorageInternal(storage, false); + } + void applyPixelStorageUnpack(const CompressedPixelStorage& storage) { + applyPixelStorageInternal(storage, true); + } }; }}} diff --git a/src/Magnum/GL/PixelFormat.cpp b/src/Magnum/GL/PixelFormat.cpp index 0eb8f7621..961197947 100644 --- a/src/Magnum/GL/PixelFormat.cpp +++ b/src/Magnum/GL/PixelFormat.cpp @@ -25,10 +25,136 @@ #include "PixelFormat.h" +#include #include namespace Magnum { namespace GL { +std::size_t pixelSize(const PixelFormat format, const PixelType type) { + std::size_t size = 0; + switch(type) { + case PixelType::UnsignedByte: + #ifndef MAGNUM_TARGET_GLES2 + case PixelType::Byte: + #endif + size = 1; break; + case PixelType::UnsignedShort: + #ifndef MAGNUM_TARGET_GLES2 + case PixelType::Short: + #endif + case PixelType::HalfFloat: + size = 2; break; + case PixelType::UnsignedInt: + #ifndef MAGNUM_TARGET_GLES2 + case PixelType::Int: + #endif + case PixelType::Float: + size = 4; break; + + #ifndef MAGNUM_TARGET_GLES + case PixelType::UnsignedByte332: + case PixelType::UnsignedByte233Rev: + return 1; + #endif + case PixelType::UnsignedShort565: + #ifndef MAGNUM_TARGET_GLES + case PixelType::UnsignedShort565Rev: + #endif + case PixelType::UnsignedShort4444: + #ifndef MAGNUM_TARGET_WEBGL + case PixelType::UnsignedShort4444Rev: + #endif + case PixelType::UnsignedShort5551: + #ifndef MAGNUM_TARGET_WEBGL + case PixelType::UnsignedShort1555Rev: + #endif + return 2; + #ifndef MAGNUM_TARGET_GLES + case PixelType::UnsignedInt8888: + case PixelType::UnsignedInt8888Rev: + case PixelType::UnsignedInt1010102: + #endif + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + case PixelType::UnsignedInt2101010Rev: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case PixelType::UnsignedInt10F11F11FRev: + case PixelType::UnsignedInt5999Rev: + #endif + case PixelType::UnsignedInt248: + return 4; + #ifndef MAGNUM_TARGET_GLES2 + case PixelType::Float32UnsignedInt248Rev: + return 8; + #endif + } + + switch(format) { + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + case PixelFormat::Red: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case PixelFormat::RedInteger: + #endif + #ifndef MAGNUM_TARGET_GLES + case PixelFormat::Green: + case PixelFormat::Blue: + case PixelFormat::GreenInteger: + case PixelFormat::BlueInteger: + #endif + #ifdef MAGNUM_TARGET_GLES2 + case PixelFormat::Luminance: + #endif + case PixelFormat::DepthComponent: + #ifndef MAGNUM_TARGET_WEBGL + case PixelFormat::StencilIndex: + #endif + return 1*size; + #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) + case PixelFormat::RG: + #endif + #ifndef MAGNUM_TARGET_GLES2 + case PixelFormat::RGInteger: + #endif + #ifdef MAGNUM_TARGET_GLES2 + case PixelFormat::LuminanceAlpha: + #endif + return 2*size; + case PixelFormat::RGB: + #ifndef MAGNUM_TARGET_GLES2 + case PixelFormat::RGBInteger: + #endif + #ifndef MAGNUM_TARGET_GLES + case PixelFormat::BGR: + case PixelFormat::BGRInteger: + #endif + #ifdef MAGNUM_TARGET_GLES2 + case PixelFormat::SRGB: + #endif + return 3*size; + case PixelFormat::RGBA: + #ifndef MAGNUM_TARGET_GLES2 + case PixelFormat::RGBAInteger: + #endif + #ifndef MAGNUM_TARGET_WEBGL + case PixelFormat::BGRA: + #endif + #ifdef MAGNUM_TARGET_GLES2 + case PixelFormat::SRGBAlpha: + #endif + #ifndef MAGNUM_TARGET_GLES + case PixelFormat::BGRAInteger: + #endif + return 4*size; + + /* Handled above */ + case PixelFormat::DepthStencil: + CORRADE_ASSERT(false, "GL::pixelSize(): invalid GL::PixelType specified for depth/stencil GL::PixelFormat", 0); + } + + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ +} + #ifndef DOXYGEN_GENERATING_OUTPUT Debug& operator<<(Debug& debug, const PixelFormat value) { switch(value) { diff --git a/src/Magnum/GL/PixelFormat.h b/src/Magnum/GL/PixelFormat.h index f9a4c58df..502ac16ac 100644 --- a/src/Magnum/GL/PixelFormat.h +++ b/src/Magnum/GL/PixelFormat.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Enum @ref Magnum::GL::PixelFormat, @ref Magnum::GL::PixelType, @ref Magnum::GL::CompressedPixelFormat + * @brief Enum @ref Magnum::GL::PixelFormat, @ref Magnum::GL::PixelType, @ref Magnum::GL::CompressedPixelFormat, function @ref Magnum::GL::pixelSize() */ #include "Magnum/Magnum.h" @@ -1234,6 +1234,13 @@ enum class CompressedPixelFormat: GLenum { #endif }; +/** +@brief Pixel size for given format/type combination (in bytes) + +@see @ref PixelStorage::dataProperties() +*/ +MAGNUM_GL_EXPORT std::size_t pixelSize(PixelFormat format, PixelType type); + /** @debugoperatorenum{PixelFormat} */ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, PixelFormat value); diff --git a/src/Magnum/GL/RectangleTexture.h b/src/Magnum/GL/RectangleTexture.h index c9f9b8f14..a36d04646 100644 --- a/src/Magnum/GL/RectangleTexture.h +++ b/src/Magnum/GL/RectangleTexture.h @@ -354,6 +354,8 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * * See @ref Texture::compressedImage(Int, CompressedImage&) for more * information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage */ void compressedImage(CompressedImage2D& image) { AbstractTexture::compressedImage<2>(0, image); @@ -372,6 +374,8 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) * for more information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage */ void compressedImage(CompressedBufferImage2D& image, BufferUsage usage) { AbstractTexture::compressedImage<2>(0, image, usage); @@ -429,6 +433,8 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedImage&) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -452,6 +458,8 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedBufferImage&, BufferUsage) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -506,6 +514,8 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * * See @ref Texture::setCompressedImage() for more information. * @see @ref maxSize() + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -558,6 +568,8 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * @return Reference to self (for method chaining) * * See @ref Texture::setCompressedSubImage() for more information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage */ RectangleTexture& setCompressedSubImage(const Vector2i& offset, const CompressedImageView2D& image) { DataHelper<2>::setCompressedSubImage(*this, 0, offset, image); diff --git a/src/Magnum/GL/Texture.h b/src/Magnum/GL/Texture.h index f02c5bc1b..94f6853ce 100644 --- a/src/Magnum/GL/Texture.h +++ b/src/Magnum/GL/Texture.h @@ -842,6 +842,8 @@ template class Texture: public AbstractTexture { * @fn_gl_extension_keyword{GetnCompressedTexImage,ARB,robustness}, * @fn_gl_extension_keyword{GetCompressedTextureImage,EXT,direct_state_access}, * eventually @fn_gl_keyword{GetCompressedTexImage} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -867,6 +869,8 @@ template class Texture: public AbstractTexture { * See @ref compressedImage(Int, CompressedImage&) for more * information. The storage is not reallocated if it is large enough to * contain the new data, which means that @p usage might get ignored. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -956,6 +960,8 @@ template class Texture: public AbstractTexture { * @def_gl{TEXTURE_COMPRESSED_BLOCK_HEIGHT}, then * @fn_gl_keyword{GetCompressedTextureSubImage} * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -986,6 +992,8 @@ template class Texture: public AbstractTexture { * See @ref compressedSubImage(Int, const RangeTypeFor&, CompressedBufferImage&, BufferUsage) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -1020,10 +1028,20 @@ template class Texture: public AbstractTexture { * 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. + * + * On OpenGL ES 2.0 and WebGL 1.0, if @ref PixelStorage::skip() is set, + * the functionality is emulated by adjusting the data pointer. * @see @ref maxSize(), @ref Framebuffer::copyImage(), @fn_gl{PixelStore}, * then @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl_keyword{TexImage1D} / @fn_gl_keyword{TexImage2D} / * @fn_gl_keyword{TexImage3D} + * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ + * @extension{NV,pack_subimage} in OpenGL ES 2.0 if + * @ref PixelStorage::rowLength() is set to a non-zero value. + * @requires_gles30 Non-zero @ref PixelStorage::imageHeight() for 3D + * images is not available in OpenGL ES 2.0. + * @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not + * supported in WebGL 1.0. * @deprecated_gl Prefer to use @ref setStorage() and @ref setSubImage() * instead. */ @@ -1076,6 +1094,10 @@ template class Texture: public AbstractTexture { * @fn_gl{BindTexture} and @fn_gl_keyword{CompressedTexImage1D} / * @fn_gl_keyword{CompressedTexImage2D} / * @fn_gl_keyword{CompressedTexImage3D} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -1086,6 +1108,10 @@ template class Texture: public AbstractTexture { #ifndef MAGNUM_TARGET_GLES2 /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL @@ -1099,6 +1125,10 @@ template class Texture: public AbstractTexture { } /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL @@ -1123,6 +1153,9 @@ template class Texture: public AbstractTexture { * nor @extension{EXT,direct_state_access} desktop extension is * available, the texture is bound before the operation (if not * already). + * + * On OpenGL ES 2.0 and WebGL 1.0, if @ref PixelStorage::skip() is set, + * the functionality is emulated by adjusting the data pointer. * @see @ref setStorage(), @ref Framebuffer::copySubImage(), * @fn_gl{PixelStore}, @fn_gl2_keyword{TextureSubImage1D,TexSubImage1D} / * @fn_gl2_keyword{TextureSubImage2D,TexSubImage2D} / @@ -1133,6 +1166,13 @@ template class Texture: public AbstractTexture { * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl_keyword{TexSubImage1D} / @fn_gl_keyword{TexSubImage2D} / * @fn_gl_keyword{TexSubImage3D} + * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ + * @extension{NV,pack_subimage} in OpenGL ES 2.0 if + * @ref PixelStorage::rowLength() is set to a non-zero value. + * @requires_gles30 Non-zero @ref PixelStorage::imageHeight() for 3D + * images is not available in OpenGL ES 2.0. + * @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not + * supported in WebGL 1.0. * @requires_gles In @ref MAGNUM_TARGET_WEBGL "WebGL" the @ref PixelType * of data passed in @p image must match the original one * specified in @ref setImage(). It means that you might not be @@ -1190,6 +1230,10 @@ template class Texture: public AbstractTexture { * @fn_gl_keyword{CompressedTexSubImage1D} / * @fn_gl_keyword{CompressedTexSubImage2D} / * @fn_gl_keyword{CompressedTexSubImage3D} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. */ Texture& setCompressedSubImage(Int level, const VectorTypeFor& offset, const CompressedImageView& image) { DataHelper::setCompressedSubImage(*this, level, offset, image); @@ -1198,6 +1242,10 @@ template class Texture: public AbstractTexture { #ifndef MAGNUM_TARGET_GLES2 /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL @@ -1209,6 +1257,10 @@ template class Texture: public AbstractTexture { } /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES * 2.0. * @requires_webgl20 Pixel buffer objects are not available in WebGL diff --git a/src/Magnum/GL/TextureArray.h b/src/Magnum/GL/TextureArray.h index 63debdc6d..4a679c95f 100644 --- a/src/Magnum/GL/TextureArray.h +++ b/src/Magnum/GL/TextureArray.h @@ -510,6 +510,8 @@ template class TextureArray: public AbstractTexture { * * See @ref Texture::compressedImage(Int, CompressedImage&) for more * information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -531,6 +533,8 @@ template class TextureArray: public AbstractTexture { * * See @ref Texture::compressedImage(Int, CompressedBufferImage&, BufferUsage) * for more information. + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() * for possible workarounds. @@ -597,6 +601,8 @@ template class TextureArray: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedImage&) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -623,6 +629,8 @@ template class TextureArray: public AbstractTexture { * See @ref Texture::compressedSubImage(Int, const RangeTypeFor&, CompressedBufferImage&, BufferUsage) * for more information. * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage * @requires_gl43 Extension @extension{ARB,internalformat_query2} if * @ref CompressedPixelStorage::compressedBlockSize() and * @ref CompressedPixelStorage::compressedBlockDataSize() are not @@ -681,6 +689,10 @@ template class TextureArray: public AbstractTexture { * * See @ref Texture::setCompressedImage() for more information. * @see @ref maxSize() + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -690,6 +702,10 @@ template class TextureArray: public AbstractTexture { } /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -699,6 +715,10 @@ template class TextureArray: public AbstractTexture { } /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. * @deprecated_gl Prefer to use @ref setStorage() and * @ref setCompressedSubImage() instead. */ @@ -761,19 +781,33 @@ template class TextureArray: public AbstractTexture { * @fn_gl_extension_keyword{CompressedTextureSubImage3D,EXT,direct_state_access}, * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl_keyword{CompressedTexSubImage2D} / @fn_gl_keyword{CompressedTexSubImage3D} + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. */ TextureArray& setCompressedSubImage(Int level, const VectorTypeFor& offset, const CompressedImageView& image) { DataHelper::setCompressedSubImage(*this, level, offset, image); return *this; } - /** @overload */ + /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. + */ TextureArray& setCompressedSubImage(Int level, const VectorTypeFor& offset, CompressedBufferImage& image) { DataHelper::setCompressedSubImage(*this, level, offset, image); return *this; } - /** @overload */ + /** @overload + * @requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} + * for non-default @ref CompressedPixelStorage + * @requires_gl Non-default @ref CompressedPixelStorage is not + * available in OpenGL ES and WebGL. + */ TextureArray& setCompressedSubImage(Int level, const VectorTypeFor& offset, CompressedBufferImage&& image) { return setCompressedSubImage(level, offset, image); } diff --git a/src/Magnum/PixelStorage.cpp b/src/Magnum/PixelStorage.cpp index 701e5534b..4a14aeb84 100644 --- a/src/Magnum/PixelStorage.cpp +++ b/src/Magnum/PixelStorage.cpp @@ -27,173 +27,29 @@ #include -#include "Magnum/GL/Context.h" -#include "Magnum/GL/Extensions.h" -#include "Magnum/GL/PixelFormat.h" -#include "Magnum/Math/Vector4.h" - -#include "Magnum/GL/Implementation/RendererState.h" -#include "Magnum/GL/Implementation/State.h" +#include "Magnum/Math/Vector3.h" namespace Magnum { -std::size_t PixelStorage::pixelSize(GL::PixelFormat format, GL::PixelType type) { - std::size_t size = 0; - switch(type) { - case GL::PixelType::UnsignedByte: - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelType::Byte: - #endif - size = 1; break; - case GL::PixelType::UnsignedShort: - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelType::Short: - #endif - case GL::PixelType::HalfFloat: - size = 2; break; - case GL::PixelType::UnsignedInt: - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelType::Int: - #endif - case GL::PixelType::Float: - size = 4; break; - - #ifndef MAGNUM_TARGET_GLES - case GL::PixelType::UnsignedByte332: - case GL::PixelType::UnsignedByte233Rev: - return 1; - #endif - case GL::PixelType::UnsignedShort565: - #ifndef MAGNUM_TARGET_GLES - case GL::PixelType::UnsignedShort565Rev: - #endif - case GL::PixelType::UnsignedShort4444: - #ifndef MAGNUM_TARGET_WEBGL - case GL::PixelType::UnsignedShort4444Rev: - #endif - case GL::PixelType::UnsignedShort5551: - #ifndef MAGNUM_TARGET_WEBGL - case GL::PixelType::UnsignedShort1555Rev: - #endif - return 2; - #ifndef MAGNUM_TARGET_GLES - case GL::PixelType::UnsignedInt8888: - case GL::PixelType::UnsignedInt8888Rev: - case GL::PixelType::UnsignedInt1010102: - #endif - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - case GL::PixelType::UnsignedInt2101010Rev: - #endif - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelType::UnsignedInt10F11F11FRev: - case GL::PixelType::UnsignedInt5999Rev: - #endif - case GL::PixelType::UnsignedInt248: - return 4; - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelType::Float32UnsignedInt248Rev: - return 8; - #endif - } - - switch(format) { - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - case GL::PixelFormat::Red: - #endif - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::RedInteger: - #endif - #ifndef MAGNUM_TARGET_GLES - case GL::PixelFormat::Green: - case GL::PixelFormat::Blue: - case GL::PixelFormat::GreenInteger: - case GL::PixelFormat::BlueInteger: - #endif - #ifdef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::Luminance: - #endif - case GL::PixelFormat::DepthComponent: - #ifndef MAGNUM_TARGET_WEBGL - case GL::PixelFormat::StencilIndex: - #endif - return 1*size; - #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - case GL::PixelFormat::RG: - #endif - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::RGInteger: - #endif - #ifdef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::LuminanceAlpha: - #endif - return 2*size; - case GL::PixelFormat::RGB: - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::RGBInteger: - #endif - #ifndef MAGNUM_TARGET_GLES - case GL::PixelFormat::BGR: - case GL::PixelFormat::BGRInteger: - #endif - #ifdef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::SRGB: - #endif - return 3*size; - case GL::PixelFormat::RGBA: - #ifndef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::RGBAInteger: - #endif - #ifndef MAGNUM_TARGET_WEBGL - case GL::PixelFormat::BGRA: - #endif - #ifdef MAGNUM_TARGET_GLES2 - case GL::PixelFormat::SRGBAlpha: - #endif - #ifndef MAGNUM_TARGET_GLES - case GL::PixelFormat::BGRAInteger: - #endif - return 4*size; - - /* Handled above */ - case GL::PixelFormat::DepthStencil: - CORRADE_ASSERT(false, "PixelStorage::pixelSize(): invalid PixelType specified for depth/stencil PixelFormat", 0); - } - - CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ -} - bool PixelStorage::operator==(const PixelStorage& other) const { return - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) _rowLength == other._rowLength && - #endif - #ifndef MAGNUM_TARGET_GLES2 _imageHeight == other._imageHeight && - #endif _skip == other._skip && _alignment == other._alignment; } -std::tuple, Math::Vector3, std::size_t> PixelStorage::dataProperties(const GL::PixelFormat format, const GL::PixelType type, const Vector3i& size) const { - const std::size_t pixelSize = PixelStorage::pixelSize(format, type); +std::pair, Math::Vector3> PixelStorage::dataProperties(const std::size_t pixelSize, const Vector3i& size) const { const Math::Vector3 dataSize{ - std::size_t(((( - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - _rowLength ? _rowLength*pixelSize : - #endif - size[0]*pixelSize) + _alignment - 1)/_alignment)*_alignment), - #ifndef MAGNUM_TARGET_GLES2 + std::size_t((((_rowLength ? _rowLength*pixelSize : size[0]*pixelSize) + + _alignment - 1)/_alignment)*_alignment), std::size_t(_imageHeight ? _imageHeight : size.y()), - #else - std::size_t(size.y()), - #endif std::size_t(size.z())}; - return std::make_tuple(Math::Vector3{pixelSize, dataSize.x(), dataSize.xy().product()}*Math::Vector3{_skip}, - size.product() ? dataSize : Math::Vector3{}, pixelSize); + return {Math::Vector3{pixelSize, dataSize.x(), dataSize.xy().product()}*Math::Vector3{_skip}, + size.product() ? dataSize : Math::Vector3{}}; } -#ifndef MAGNUM_TARGET_GLES std::tuple, Math::Vector3, std::size_t> CompressedPixelStorage::dataProperties(const Vector3i& size) const { CORRADE_ASSERT(_blockDataSize && _blockSize.product(), "CompressedPixelStorage::dataProperties(): expected non-zero storage parameters", {}); @@ -208,111 +64,11 @@ std::tuple, Math::Vector3, std::size_t> return std::make_tuple(offset, size.product() ? dataSize : Math::Vector3{}, _blockDataSize); } -#endif -void PixelStorage::applyInternal(const bool isUnpack) { - GL::Implementation::RendererState::PixelStorage& state = isUnpack ? - Context::current().state().renderer->unpackPixelStorage : - Context::current().state().renderer->packPixelStorage; - - /* Alignment */ - if(state.alignment == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.alignment != _alignment) - glPixelStorei(isUnpack ? GL_UNPACK_ALIGNMENT : GL_PACK_ALIGNMENT, - state.alignment = _alignment); - - /* Row length */ - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - if(state.rowLength == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.rowLength != _rowLength) - { - /** @todo Use real value for GL_PACK_ROW_LENGTH_NV when it is in headers */ - #ifndef MAGNUM_TARGET_GLES2 - glPixelStorei(isUnpack ? GL_UNPACK_ROW_LENGTH : GL_PACK_ROW_LENGTH, - state.rowLength = _rowLength); - #elif !defined(MAGNUM_TARGET_WEBGL) - glPixelStorei(isUnpack ? GL_UNPACK_ROW_LENGTH_EXT : 0xD02 /*GL_PACK_ROW_LENGTH_NV*/, - state.rowLength = _rowLength); - #endif - } - #endif - - #ifndef MAGNUM_TARGET_GLES - /* Image height (on ES for unpack only, taken care of below) */ - if(state.imageHeight == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.imageHeight != _imageHeight) - glPixelStorei(isUnpack ? GL_UNPACK_IMAGE_HEIGHT : GL_PACK_IMAGE_HEIGHT, - state.imageHeight = _imageHeight); - #endif - - /* On ES2 done by modifying data pointer */ - #ifndef MAGNUM_TARGET_GLES2 - /* Skip pixels */ - if(state.skip.x() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.x() != _skip.x()) - glPixelStorei(isUnpack ? GL_UNPACK_SKIP_PIXELS : GL_PACK_SKIP_PIXELS, - state.skip.x() = _skip.x()); - - /* Skip rows */ - if(state.skip.y() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.y() != _skip.y()) - glPixelStorei(isUnpack ? GL_UNPACK_SKIP_ROWS : GL_PACK_SKIP_ROWS, - state.skip.y() = _skip.y()); - - #ifndef MAGNUM_TARGET_GLES - /* Skip images (on ES for unpack only, taken care of below) */ - if(state.skip.z() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.z() != _skip.z()) - glPixelStorei(isUnpack ? GL_UNPACK_SKIP_IMAGES : GL_PACK_SKIP_IMAGES, - state.skip.z() = _skip.z()); - #endif - #endif -} - -void PixelStorage::applyUnpack() { - applyInternal(true); - - #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) - Implementation::RendererState::PixelStorage& state = Context::current().state().renderer->unpackPixelStorage; - - /* Image height (on ES for unpack only) */ - if(state.imageHeight == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.imageHeight != _imageHeight) - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, state.imageHeight = _imageHeight); - - /* Skip images (on ES for unpack only) */ - if(state.skip.z() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.skip.z() != _skip.z()) - glPixelStorei(GL_UNPACK_SKIP_IMAGES, state.skip.z() = _skip.z()); - #endif -} - -#ifndef MAGNUM_TARGET_GLES bool CompressedPixelStorage::operator==(const CompressedPixelStorage& other) const { return PixelStorage::operator==(other) && _blockSize == other._blockSize && _blockDataSize == other._blockDataSize; } -void CompressedPixelStorage::applyInternal(const bool isUnpack) { - PixelStorage::applyInternal(isUnpack); - - GL::Implementation::RendererState::PixelStorage& state = isUnpack ? - Context::current().state().renderer->unpackPixelStorage : - Context::current().state().renderer->packPixelStorage; - - /* Compressed block width */ - if(state.compressedBlockSize.x() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockSize.x() != _blockSize.x()) - glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_WIDTH : GL_PACK_COMPRESSED_BLOCK_WIDTH, - state.compressedBlockSize.x() = _blockSize.x()); - - /* Compressed block height */ - if(state.compressedBlockSize.y() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockSize.y() != _blockSize.y()) - glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_HEIGHT : GL_PACK_COMPRESSED_BLOCK_HEIGHT, - state.compressedBlockSize.y() = _blockSize.y()); - - /* Compressed block depth */ - if(state.compressedBlockSize.z() == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockSize.z() != _blockSize.z()) - glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_DEPTH : GL_PACK_COMPRESSED_BLOCK_DEPTH, - state.compressedBlockSize.z() = _blockSize.z()); - - /* Compressed block size */ - if(state.compressedBlockDataSize == GL::Implementation::RendererState::PixelStorage::DisengagedValue || state.compressedBlockDataSize != _blockDataSize) - glPixelStorei(isUnpack ? GL_UNPACK_COMPRESSED_BLOCK_SIZE : GL_PACK_COMPRESSED_BLOCK_SIZE, - state.compressedBlockDataSize = _blockDataSize); -} -#endif - } diff --git a/src/Magnum/PixelStorage.h b/src/Magnum/PixelStorage.h index 6826ea6b6..6cfab21b1 100644 --- a/src/Magnum/PixelStorage.h +++ b/src/Magnum/PixelStorage.h @@ -33,44 +33,30 @@ #include #include "Magnum/Magnum.h" -#include "Magnum/GL/GL.h" -#include "Magnum/GL/visibility.h" #include "Magnum/Math/Vector3.h" +#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) +#include "Magnum/GL/PixelFormat.h" +#endif + namespace Magnum { /** @brief Pixel storage parameters Descibes how to interpret data which are read from or stored into @ref Image, -@ref ImageView, @ref BufferImage and @ref Trade::ImageData using -@ref Texture::setImage() "*Texture::setImage()", @ref Texture::setSubImage() "*Texture::setSubImage()", -@ref Texture::image() "*Texture::image()", @ref Texture::subImage() "*Texture::subImage()" -and @ref AbstractFramebuffer::read() "*Framebuffer::read()". - -@section PixelFormat-performance-optimizations Performance optimizations - -The storage mode is applied either right before doing image upload using -@fn_gl_keyword{PixelStore} with @def_gl{UNPACK_*} parameters or right before -doing image download using @fn_gl{PixelStore} with @def_gl{PACK_*}. The engine -tracks currently used pixel pack/unpack parameters to avoid unnecessary calls -to @fn_gl{PixelStore}. See also @ref Context::resetState() and -@ref Context::State::PixelStorage. +@ref ImageView, @ref Trade::ImageData or for example @ref GL::BufferImage. @see @ref CompressedPixelStorage */ -class MAGNUM_GL_EXPORT PixelStorage { - friend GL::AbstractFramebuffer; - friend GL::AbstractTexture; - friend GL::CubeMapTexture; - +class MAGNUM_EXPORT PixelStorage { public: - /** - * @brief Pixel size for given format/type combination (in bytes) - * - * @see @ref dataProperties() + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) + /** @brief @copybrief GL::pixelSize() + * @deprecated Use @ref GL::pixelSize() instead. */ - static std::size_t pixelSize(GL::PixelFormat format, GL::PixelType type); + static CORRADE_DEPRECATED("use GL::pixelSize() instead") std::size_t pixelSize(GL::PixelFormat format, GL::PixelType type); + #endif /** * @brief Default constructor @@ -97,73 +83,39 @@ class MAGNUM_GL_EXPORT PixelStorage { * Not applicable for @ref CompressedPixelStorage. Valid values are * @cpp 1 @ce, @cpp 2 @ce, @cpp 4 @ce and @cpp 8 @ce. Default is * @cpp 4 @ce. - * @see @fn_gl{PixelStore} with @def_gl_keyword{PACK_ALIGNMENT}/ - * @def_gl_keyword{UNPACK_ALIGNMENT} */ PixelStorage& setAlignment(Int alignment) { _alignment = alignment; return *this; } - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - /** - * @brief Row length - * - * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ - * @extension{NV,pack_subimage} in OpenGL ES 2.0. - * @requires_webgl20 Row length specification is not available in WebGL - * 1.0. - */ + /** @brief Row length */ constexpr Int rowLength() const { return _rowLength; } /** * @brief Set row length * * Used only on 2D and 3D images. If set to @cpp 0 @ce, size - * information from actual image is used. Default is @cpp 0 @ce. - * @see @fn_gl{PixelStore} with @def_gl_keyword{UNPACK_ROW_LENGTH}/ - * @def_gl_keyword{PACK_ROW_LENGTH} - * @requires_gles30 Extension @extension{EXT,unpack_subimage}/ - * @extension{NV,pack_subimage} in OpenGL ES 2.0. - * @requires_webgl20 Row length specification is not available in WebGL - * 1.0. + * information from the actual image is used. Default is @cpp 0 @ce. */ PixelStorage& setRowLength(Int length) { _rowLength = length; return *this; } - #endif - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief Image height - * - * @requires_gles30 Image height specification is not available in - * OpenGL ES 2.0 - * @requires_webgl20 Image height specification is not available in - * WebGL 1.0. - */ + /** @brief Image height */ constexpr Int imageHeight() const { return _imageHeight; } /** * @brief Set image height * * Used only on 3D images. If set to @cpp 0 @ce, size information from - * actual image is used. Default is @cpp 0 @ce. - * @see @fn_gl{PixelStore} with @def_gl_keyword{UNPACK_IMAGE_HEIGHT}/ - * @def_gl_keyword{PACK_IMAGE_HEIGHT} - * @requires_gles30 Image height specification is not available in - * OpenGL ES 2.0 - * @requires_webgl20 Image height specification is not available in - * WebGL 1.0. - * @requires_gl Image height specification is available only for unpack - * in OpenGL ES and WebGL. + * the actual image is used. Default is @cpp 0 @ce. */ PixelStorage& setImageHeight(Int height) { _imageHeight = height; return *this; } - #endif /** @brief Pixel, row and image skipping */ constexpr Vector3i skip() const { return _skip; } @@ -172,15 +124,7 @@ class MAGNUM_GL_EXPORT PixelStorage { * @brief Set pixel, row and image skipping * * The Y value is used only for 2D and 3D images, the Z value is used - * only for 3D images. Default is @cpp 0 @ce. On OpenGL ES 2.0 and - * WebGL 1.0 the functionality is emulated by increasing the data - * pointer. - * @see @fn_gl{PixelStore} with @def_gl_keyword{UNPACK_SKIP_PIXELS}/ - * @def_gl_keyword{PACK_SKIP_PIXELS}, @def_gl_keyword{UNPACK_SKIP_ROWS}/ - * @def_gl_keyword{PACK_SKIP_ROWS}, @def_gl_keyword{UNPACK_SKIP_IMAGES}/ - * @def_gl_keyword{PACK_SKIP_IMAGES} - * @requires_gl Image skip specification is available only for unpack - * in OpenGL ES and WebGL. + * only for 3D images. Default is @cpp 0 @ce. */ PixelStorage& setSkip(const Vector3i& skip) { _skip = skip; @@ -189,64 +133,52 @@ class MAGNUM_GL_EXPORT PixelStorage { /** * @brief Data properties for given parameters + * + * Returns byte offset in each direction and @cpp {rowLength, rowCount, layerCount} @ce + * for image of given @p size with current pixel storage parameters, + * and given @p pixelSize. The offset reflects the @ref skip() + * parameter. Sum of the byte offset vector gives the byte offset of + * first pixel in the data array. + * @see @ref GL::pixelSize() + */ + std::pair, Math::Vector3> dataProperties(std::size_t pixelSize, const Vector3i& size) const; + + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) + /** @brief @copybrief dataProperties(std::size_t, const Vector3i&) const * * Returns byte offset in each direction, (row length, row count, layer * count) and pixel size for image of given @p size with current pixel - * storage parameters, @p format and @p type. The offset reflects the - * @ref skip() parameter. Sum of the byte offset vector gives the - * byte offset of first pixel in the data array. - * @see @ref pixelSize() + * storage parameters, @p format and @p type. + * @deprecated Use @ref dataProperties(std::size_t, const Vector3i&) const + * instead. */ - std::tuple, Math::Vector3, std::size_t> dataProperties(GL::PixelFormat format, GL::PixelType type, const Vector3i& size) const; + CORRADE_DEPRECATED("use dataProperties(std::size_t, const Vector3i&) instead") std::tuple, Math::Vector3, std::size_t> dataProperties(GL::PixelFormat format, GL::PixelType type, const Vector3i& size) const; + #endif #ifndef DOXYGEN_GENERATING_OUTPUT protected: #else private: #endif - /* Bool parameter is ugly, but this is implementation detail of - internal API so who cares */ - void MAGNUM_GL_LOCAL applyInternal(bool isUnpack); - - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - Int _rowLength; - #endif - #ifndef MAGNUM_TARGET_GLES2 - Int _imageHeight; - #endif + Int _rowLength, + _imageHeight; Vector3i _skip; private: - /* Used internally in *Texture::image(), *Texture::subImage(), - *Texture::setImage(), *Texture::setSubImage() and - *Framebuffer::read() */ - void MAGNUM_GL_LOCAL applyUnpack(); - void MAGNUM_GL_LOCAL applyPack() { applyInternal(false); } - Int _alignment; }; -#ifndef MAGNUM_TARGET_GLES /** @brief Compressed pixel storage parameters Descibes how to interpret data which are read from or stored into -@ref CompressedImage, @ref CompressedImageView, @ref CompressedBufferImage and -@ref Trade::ImageData using @ref Texture::setCompressedImage() "*Texture::setCompressedImage(), -@ref Texture::setCompressedSubImage() "*Texture::setCompressedSubImage()", -@ref Texture::compressedImage() "*Texture::compressedImage()" and -@ref Texture::compressedSubImage() "*Texture::compressedSubImage()". +@ref CompressedImage, @ref CompressedImageView, @ref Trade::ImageData or for +example @ref GL::CompressedBufferImage. Includes all parameters from @ref PixelStorage, except for @ref alignment(), which is ignored for compressed images. - -@requires_gl42 Extension @extension{ARB,compressed_texture_pixel_storage} -@requires_gl Compressed pixel storage is hardcoded in OpenGL ES and WebGL. */ -class MAGNUM_GL_EXPORT CompressedPixelStorage: public PixelStorage { - friend GL::AbstractTexture; - friend GL::CubeMapTexture; - +class MAGNUM_EXPORT CompressedPixelStorage: public PixelStorage { public: /** * @brief Default constructor @@ -330,29 +262,26 @@ class MAGNUM_GL_EXPORT CompressedPixelStorage: public PixelStorage { using PixelStorage::alignment; using PixelStorage::setAlignment; - /* Bool parameter is ugly, but this is implementation detail of - internal API so who cares */ - void MAGNUM_GL_LOCAL applyInternal(bool isUnpack); - - /* Used internally in *Texture::compressedImage(), *Texture::compressedSubImage(), - *Texture::setCompressedImage() and *Texture::setCompressedSubImage() */ - void MAGNUM_GL_LOCAL applyUnpack() { applyInternal(true); } - void MAGNUM_GL_LOCAL applyPack() { applyInternal(false); } - Vector3i _blockSize; Int _blockDataSize; }; -#endif -constexpr PixelStorage::PixelStorage() noexcept: - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - _rowLength{0}, - #endif - #ifndef MAGNUM_TARGET_GLES2 - _imageHeight{0}, - #endif - _skip{0}, - _alignment{4} {} +constexpr PixelStorage::PixelStorage() noexcept: _rowLength{0}, _imageHeight{0}, _skip{0}, _alignment{4} {} + +#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) +/* These have to be in the header because GL::pixelSize() is in Magnum::GL and + putting that in the source would mean undefined reference */ +inline std::size_t PixelStorage::pixelSize(const GL::PixelFormat format, const GL::PixelType type) { + return GL::pixelSize(format, type); +} + +inline std::tuple, Math::Vector3, std::size_t> PixelStorage::dataProperties(const GL::PixelFormat format, const GL::PixelType type, const Vector3i& size) const { + const std::size_t pixelSize = GL::pixelSize(format, type); + Math::Vector3 offset, dataSize; + std::tie(offset, dataSize) = dataProperties(pixelSize, size); + return std::make_tuple(offset, dataSize, pixelSize); +} +#endif namespace Implementation { /* Used in *Image::dataProperties() */ @@ -363,7 +292,6 @@ namespace Implementation { return std::make_tuple(Math::Vector::pad(offset), Math::Vector::pad(dataSize), pixelSize); } - #ifndef MAGNUM_TARGET_GLES2 /* Used in Compressed*Image::dataProperties() */ template std::tuple, Math::Vector, std::size_t> compressedImageDataProperties(const T& image) { Math::Vector3 offset, blockCount; @@ -371,7 +299,6 @@ namespace Implementation { std::tie(offset, blockCount, blockSize) = image.storage().dataProperties(Vector3i::pad(image.size(), 1)); return std::make_tuple(Math::Vector::pad(offset), Math::Vector::pad(blockCount), blockSize); } - #endif /* Used in image query functions */ template std::size_t imageDataSizeFor(const T& image, const Math::Vector& size) { @@ -384,19 +311,11 @@ namespace Implementation { if(offset.z()) dataOffset += offset.z(); else if(offset.y()) { - #ifndef MAGNUM_TARGET_GLES2 if(!image.storage().imageHeight()) - #endif - { dataOffset += offset.y(); - } } else if(offset.x()) { - #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) if(!image.storage().rowLength()) - #endif - { dataOffset += offset.x(); - } } return dataOffset + dataSize.product(); } @@ -406,7 +325,6 @@ namespace Implementation { return imageDataSizeFor(image, image.size()); } - #ifndef MAGNUM_TARGET_GLES template std::pair compressedImageDataOffsetSizeFor(const T& image, const Math::Vector& size) { CORRADE_INTERNAL_ASSERT(image.storage().compressedBlockSize().product() && image.storage().compressedBlockDataSize()); @@ -430,20 +348,13 @@ namespace Implementation { return image.storage().compressedBlockSize().product() && image.storage().compressedBlockDataSize() ? compressedImageDataOffsetSizeFor(image, image.size()).second : dataSize; } - #else - template std::size_t occupiedCompressedImageDataSize(const T&, std::size_t dataSize) { - return dataSize; - } - #endif - #ifdef MAGNUM_TARGET_GLES2 template std::ptrdiff_t pixelStorageSkipOffsetFor(const T& image, const Math::Vector& size) { return std::get<0>(image.storage().dataProperties(image.format(), image.type(), Vector3i::pad(size, 1))).sum(); } template std::ptrdiff_t pixelStorageSkipOffset(const T& image) { return pixelStorageSkipOffsetFor(image, image.size()); } - #endif } } diff --git a/src/Magnum/Trade/ImageData.h b/src/Magnum/Trade/ImageData.h index 8df03bd29..351ce45ec 100644 --- a/src/Magnum/Trade/ImageData.h +++ b/src/Magnum/Trade/ImageData.h @@ -190,7 +190,7 @@ template class ImageData { * @brief Pixel size (in bytes) * * The image is expected to be uncompressed. - * @see @ref isCompressed(), @ref PixelStorage::pixelSize() + * @see @ref isCompressed(), @ref Magnum::pixelSize() */ std::size_t pixelSize() const;