diff --git a/doc/changelog.dox b/doc/changelog.dox index 83b36c041..a648eafc0 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -97,6 +97,10 @@ See also: - Implemented the GL 4.3 @gl_extension{ARB,framebuffer_no_attachments} extension and matching GLES 3.1 functionality, exposed as @ref GL::Framebuffer::setDefaultSize() and related APIs +- Implemented the GL 4.3 @gl_extension{ARB,texture_view} extension and + matching @gl_extension{OES,texture_view} and @gl_extension{EXT,texture_view} + extensions on GLES 3.1+, exposed as @ref GL::Texture::view() and similar + APIs on other texture types - Implemented @gl_extension{EXT,texture_norm16} and @webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making normalized 16-bit texture and renderbuffer formats available on all diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index da929b376..c657960af 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -381,7 +381,7 @@ OpenGL function | Matching API @fn_gl{TexStorage2DMultisample}, \n `glTextureStorage2DMultisample()`, \n @fn_gl{TexStorage3DMultisample}, \n `glTextureStorage3DMultisample()` | @ref GL::MultisampleTexture::setStorage() @fn_gl{TexSubImage1D}, \n `glTextureSubImage1D()`, \n @fn_gl{TexSubImage2D}, \n `glTextureSubImage2D()`, \n @fn_gl{TexSubImage3D}, \n `glTextureSubImage3D()` | @ref GL::Texture::setSubImage(), \n @ref GL::TextureArray::setSubImage(), \n @ref GL::CubeMapTexture::setSubImage(), \n @ref GL::CubeMapTextureArray::setSubImage(), \n @ref GL::RectangleTexture::setSubImage() @fn_gl{TextureBarrier} | @ref GL::Renderer::setTextureBarrier() -@fn_gl{TextureView} | | +@fn_gl{TextureView} | @ref GL::Texture::view(), \n @ref GL::TextureArray::view(), \n @ref GL::CubeMapTexture::view(), \n @ref GL::CubeMapTextureArray::view(), @ref GL::MultisampleTexture::view(), \n @ref GL::RectangleTexture::view() @fn_gl{TransformFeedbackBufferBase}, \n @fn_gl{TransformFeedbackBufferRange} | @ref GL::TransformFeedback::attachBuffer(), \n @ref GL::TransformFeedback::attachBuffers() @fn_gl{TransformFeedbackVaryings} | @ref GL::AbstractShaderProgram::setTransformFeedbackOutputs() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index cd308c6c5..f829c49bc 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -215,7 +215,7 @@ GLSL 4.30 | done @gl_extension{ARB,texture_buffer_range} | done @gl_extension{ARB,texture_query_levels} | done (shading language only) @gl_extension{ARB,texture_storage_multisample} | done -@gl_extension{ARB,texture_view} | | +@gl_extension{ARB,texture_view} | done @gl_extension{ARB,vertex_attrib_binding} | | @subsection opengl-support-44 OpenGL 4.4 @@ -475,7 +475,7 @@ Extension | Status @gl_extension{EXT,texture_compression_s3tc} | done @gl_extension{EXT,pvrtc_sRGB} | done @gl_extension{EXT,shader_integer_mix} | done (shading language only) -@gl_extension{EXT,texture_view} | | +@gl_extension{EXT,texture_view} | done @gl_extension{EXT,draw_elements_base_vertex} | done @gl_extension{EXT,texture_norm16} | done @gl_extension{EXT,texture_sRGB_R8} | done @@ -505,7 +505,7 @@ Extension | Status @gl_extension{OES,stencil1} | done @gl_extension{OES,stencil4} | done @gl_extension{OES,texture_float_linear} | done -@gl_extension{OES,texture_view} | | +@gl_extension{OES,texture_view} | done @gl_extension{OES,draw_elements_base_vertex} | done @gl_extension{OVR,multiview} | | @gl_extension{OVR,multiview2} | | diff --git a/src/Magnum/GL/AbstractTexture.cpp b/src/Magnum/GL/AbstractTexture.cpp index e770f1f6c..0dcabcf81 100644 --- a/src/Magnum/GL/AbstractTexture.cpp +++ b/src/Magnum/GL/AbstractTexture.cpp @@ -504,6 +504,12 @@ void AbstractTexture::setDepthStencilMode(const SamplerDepthStencilMode mode) { } #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +void AbstractTexture::viewInternal(AbstractTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + Context::current().state().texture.viewImplementation(_id, _target, original._id, GLenum(internalFormat), levelOffset, levelCount, layerOffset, layerCount); +} +#endif + void AbstractTexture::invalidateImage(const Int level) { Context::current().state().texture.invalidateImageImplementation(*this, level); } diff --git a/src/Magnum/GL/AbstractTexture.h b/src/Magnum/GL/AbstractTexture.h index 809035f9d..79a24856a 100644 --- a/src/Magnum/GL/AbstractTexture.h +++ b/src/Magnum/GL/AbstractTexture.h @@ -490,6 +490,9 @@ class MAGNUM_GL_EXPORT AbstractTexture: public AbstractObject { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void setDepthStencilMode(SamplerDepthStencilMode mode); #endif + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + void viewInternal(AbstractTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount); + #endif void invalidateImage(Int level); void generateMipmap(); diff --git a/src/Magnum/GL/CubeMapTexture.cpp b/src/Magnum/GL/CubeMapTexture.cpp index 938a03eeb..a03bac727 100644 --- a/src/Magnum/GL/CubeMapTexture.cpp +++ b/src/Magnum/GL/CubeMapTexture.cpp @@ -41,6 +41,10 @@ #include "Magnum/GL/Implementation/State.h" #include "Magnum/GL/Implementation/TextureState.h" +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +#include "Magnum/GL/CubeMapTextureArray.h" +#endif + namespace Magnum { namespace GL { static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 0 && @@ -55,6 +59,30 @@ Vector2i CubeMapTexture::maxSize() { return Vector2i{Implementation::maxCubeMapTextureSideSize()}; } +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +CubeMapTexture CubeMapTexture::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + CubeMapTexture out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, 0, 6); + return out; +} + +CubeMapTexture CubeMapTexture::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + CubeMapTexture out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 6); + return out; +} +#endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Vector2i CubeMapTexture::imageSize(const Int level) { const Implementation::TextureState& state = Context::current().state().texture; diff --git a/src/Magnum/GL/CubeMapTexture.h b/src/Magnum/GL/CubeMapTexture.h index c316aab29..118897341 100644 --- a/src/Magnum/GL/CubeMapTexture.h +++ b/src/Magnum/GL/CubeMapTexture.h @@ -132,6 +132,42 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { } #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * @brief Create a view on another cube map texture + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_CUBE_MAP} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + static CubeMapTexture view(CubeMapTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount); + + /** + * @brief Create a view on a cube map texture array + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_CUBE_MAP} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + static CubeMapTexture view(CubeMapTextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset); + #endif + /** * @brief Wrap existing OpenGL cube map texture object * @param id OpenGL cube map texture ID diff --git a/src/Magnum/GL/CubeMapTextureArray.cpp b/src/Magnum/GL/CubeMapTextureArray.cpp index 17415414a..bc6961cd6 100644 --- a/src/Magnum/GL/CubeMapTextureArray.cpp +++ b/src/Magnum/GL/CubeMapTextureArray.cpp @@ -31,6 +31,7 @@ #include "Magnum/Image.h" #include "Magnum/GL/BufferImage.h" #include "Magnum/GL/Context.h" +#include "Magnum/GL/CubeMapTexture.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/Implementation/maxTextureSize.h" @@ -49,6 +50,28 @@ Vector3i CubeMapTextureArray::maxSize() { Implementation::maxTextureArrayLayers()}; } +CubeMapTextureArray CubeMapTextureArray::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + CubeMapTextureArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); + return out; +} + +CubeMapTextureArray CubeMapTextureArray::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + CubeMapTextureArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, 0, 6); + return out; +} + #ifndef MAGNUM_TARGET_GLES Image3D CubeMapTextureArray::image(const Int level, Image3D&& image) { this->image(level, image); diff --git a/src/Magnum/GL/CubeMapTextureArray.h b/src/Magnum/GL/CubeMapTextureArray.h index 684496411..26b282cd8 100644 --- a/src/Magnum/GL/CubeMapTextureArray.h +++ b/src/Magnum/GL/CubeMapTextureArray.h @@ -119,6 +119,40 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { } #endif + /** + * @brief Create a view on another cube map texture array + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with + * @def_gl{TEXTURE_CUBE_MAP_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + */ + static CubeMapTextureArray view(CubeMapTextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount); + + /** + * @brief Create a view on a cube map texture + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with + * @def_gl{TEXTURE_CUBE_MAP_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + */ + static CubeMapTextureArray view(CubeMapTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount); + /** * @brief Wrap existing OpenGL cube map array texture object * @param id OpenGL cube map array texture ID @@ -461,7 +495,7 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * Z coordinate of @p size must be multiple of 6. * * See @ref Texture::setStorage() for more information. - * @see @ref maxSize() + * @see @ref view(), @ref maxSize() */ CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& size) { DataHelper<3>::setStorage(*this, levels, internalFormat, size); diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index c6a0b97c4..fc3191ef0 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -255,6 +255,30 @@ TextureState::TextureState(Context& context, } #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /* Texture view implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions[Extensions::ARB::texture_view::Index] = + Extensions::ARB::texture_view::string(); + viewImplementation = glTextureView; + } + #else + if(context.isExtensionSupported()) { + extensions[Extensions::EXT::texture_view::Index] = + Extensions::EXT::texture_view::string(); + viewImplementation = glTextureViewEXT; + } else if(context.isExtensionSupported()) { + extensions[Extensions::OES::texture_view::Index] = + Extensions::OES::texture_view::string(); + viewImplementation = glTextureViewOES; + } + #endif + else { + viewImplementation = nullptr; + } + #endif + /* Data invalidation implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { diff --git a/src/Magnum/GL/Implementation/TextureState.h b/src/Magnum/GL/Implementation/TextureState.h index e9ac573ac..68dc330fd 100644 --- a/src/Magnum/GL/Implementation/TextureState.h +++ b/src/Magnum/GL/Implementation/TextureState.h @@ -118,6 +118,9 @@ struct TextureState { void(*subImage3DImplementation)(AbstractTexture&, GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&); void(*compressedSubImage3DImplementation)(AbstractTexture&, GLint, const Vector3i&, const Vector3i&, CompressedPixelFormat, const GLvoid*, GLsizei); #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + void(APIENTRY *viewImplementation)(GLuint, GLenum, GLuint, GLenum, GLuint, GLuint, GLuint, GLuint); + #endif void(*invalidateImageImplementation)(AbstractTexture&, GLint); void(*invalidateSubImageImplementation)(AbstractTexture&, GLint, const Vector3i&, const Vector3i&); diff --git a/src/Magnum/GL/MultisampleTexture.cpp b/src/Magnum/GL/MultisampleTexture.cpp index 92ff9d7a1..d91305b17 100644 --- a/src/Magnum/GL/MultisampleTexture.cpp +++ b/src/Magnum/GL/MultisampleTexture.cpp @@ -64,6 +64,19 @@ template<> Vector3i MAGNUM_GL_EXPORT maxMultisampleTextureSize<3>() { } +template MultisampleTexture MultisampleTexture::view(MultisampleTexture2D& original, const TextureFormat internalFormat) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + MultisampleTexture out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, 0, 1, 0, 1); + return out; +} + +/* Other view() overloads at the end */ + template MultisampleTexture& MultisampleTexture::setLabel(Containers::StringView label) { AbstractTexture::setLabel(label); return *this; @@ -72,5 +85,32 @@ template MultisampleTexture& MultisampleText template class MAGNUM_GL_EXPORT MultisampleTexture<2>; template class MAGNUM_GL_EXPORT MultisampleTexture<3>; +/* Because these refer to concrete types different than the class itself, they + have to be after the explicit type instantiations. Additionally, on Windows (MSVC, clang-cl and MinGw) these need an explicit export otherwise the + symbol doesn't get exported. + + Other view() overloads above. */ +template<> template<> MAGNUM_GL_EXPORT MultisampleTexture2D MultisampleTexture2D::view(MultisampleTexture2DArray& original, const TextureFormat internalFormat, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + MultisampleTexture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, 0, 1, layer, 1); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT MultisampleTexture2DArray MultisampleTexture2DArray::view(MultisampleTexture2DArray& original, const TextureFormat internalFormat, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + MultisampleTexture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, 0, 1, layerOffset, layerCount); + return out; +} + }} #endif diff --git a/src/Magnum/GL/MultisampleTexture.h b/src/Magnum/GL/MultisampleTexture.h index e9d68c25a..c95e212b6 100644 --- a/src/Magnum/GL/MultisampleTexture.h +++ b/src/Magnum/GL/MultisampleTexture.h @@ -121,6 +121,66 @@ template class MAGNUM_GL_EXPORT MultisampleTexture: publ return Implementation::maxMultisampleTextureSize(); } + /** + * @brief Create a view on a multisample texture + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with + * @def_gl{TEXTURE_2D_MULTISAMPLE} or + * @def_gl{TEXTURE_2D_MULTISAMPLE_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + */ + static MultisampleTexture view(MultisampleTexture2D& original, TextureFormat internalFormat); + + /** + * @brief Create a view on a layer of a multisample texture array + * @m_since_latest + * + * Enabled only on a @ref MultisampleTexture2D. The @p internalFormat + * has to either match the format of @p original, or be compatible with + * it, such as having the same pixel size and other restrictions + * described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with + * @def_gl{TEXTURE_2D_MULTISAMPLE} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static MultisampleTexture view(MultisampleTexture2DArray& original, TextureFormat internalFormat, Int layer); + + /** + * @brief Create a view on a multisample texture array + * @m_since_latest + * + * Enabled only on a @ref MultisampleTexture2DArray. The + * @p internalFormat has to either match the format of @p original, or + * be compatible with it, such as having the same pixel size and other + * restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with + * @def_gl{TEXTURE_2D_MULTISAMPLE_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static MultisampleTexture view(MultisampleTexture2DArray& original, TextureFormat internalFormat, Int layerOffset, Int layerCount); + /** * @brief Wrap existing OpenGL multisample texture object * @param id OpenGL multisample texture ID @@ -259,8 +319,8 @@ template class MAGNUM_GL_EXPORT MultisampleTexture: publ * OpenGL 4.3) is not available, the texture is bound and the feature * is emulated using plain @gl_extension{ARB,texture_multisample} * functionality. - * @see @ref maxSize(), @ref maxColorSamples(), @ref maxDepthSamples(), - * @ref maxIntegerSamples(), @fn_gl2_keyword{TextureStorage2DMultisample,TexStorage2DMultisample} / + * @see @ref view(), @ref maxSize(), @ref maxColorSamples(), + * @ref maxDepthSamples(), @ref maxIntegerSamples(), @fn_gl2_keyword{TextureStorage2DMultisample,TexStorage2DMultisample} / * @fn_gl2_keyword{TextureStorage3DMultisample,TexStorage3DMultisample}, * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} * and @fn_gl_keyword{TexStorage2DMultisample} / @fn_gl_keyword{TexStorage3DMultisample} diff --git a/src/Magnum/GL/RectangleTexture.cpp b/src/Magnum/GL/RectangleTexture.cpp index 8fa827514..4f762e9da 100644 --- a/src/Magnum/GL/RectangleTexture.cpp +++ b/src/Magnum/GL/RectangleTexture.cpp @@ -52,6 +52,17 @@ Vector2i RectangleTexture::maxSize() { return Vector2i{value}; } +RectangleTexture RectangleTexture::view(RectangleTexture& original, const TextureFormat internalFormat) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + RectangleTexture out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, 0, 1, 0, 1); + return out; +} + Image2D RectangleTexture::image(Image2D&& image) { this->image(image); return std::move(image); diff --git a/src/Magnum/GL/RectangleTexture.h b/src/Magnum/GL/RectangleTexture.h index 1ff0e396a..e58ad721c 100644 --- a/src/Magnum/GL/RectangleTexture.h +++ b/src/Magnum/GL/RectangleTexture.h @@ -101,6 +101,20 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { return AbstractTexture::compressedBlockDataSize(GL_TEXTURE_RECTANGLE, format); } + /** + * @brief Create a view on another rectangle texture + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with + * @def_gl{TEXTURE_RECTANGLE} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + */ + static RectangleTexture view(RectangleTexture& original, TextureFormat internalFormat); + /** * @brief Wrap existing OpenGL rectangle texture object * @param id OpenGL rectangle texture ID diff --git a/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp index 635faa07a..050cbf7c9 100644 --- a/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp @@ -29,6 +29,7 @@ #include "Magnum/Image.h" #include "Magnum/ImageView.h" #include "Magnum/GL/BufferImage.h" +#include "Magnum/GL/CubeMapTexture.h" #include "Magnum/GL/CubeMapTextureArray.h" #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" @@ -64,6 +65,9 @@ struct CubeMapTextureArrayGLTest: OpenGLTester { void storage(); + void view(); + void viewOnNonArray(); + void image(); void imageBuffer(); #ifndef MAGNUM_TARGET_GLES @@ -287,7 +291,10 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { &CubeMapTextureArrayGLTest::samplingBorder, #endif - &CubeMapTextureArrayGLTest::storage}); + &CubeMapTextureArrayGLTest::storage, + + &CubeMapTextureArrayGLTest::view, + &CubeMapTextureArrayGLTest::viewOnNonArray}); addInstancedTests({ &CubeMapTextureArrayGLTest::image, @@ -615,6 +622,54 @@ void CubeMapTextureArrayGLTest::storage() { MAGNUM_VERIFY_NO_GL_ERROR(); } +void CubeMapTextureArrayGLTest::view() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTextureArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32, 12}); + + auto view = CubeMapTextureArray::view(texture, TextureFormat::RGBA8, 2, 3, 6, 6); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{8, 8, 6})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{4, 4, 6})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{2, 2, 6})); +} + +void CubeMapTextureArrayGLTest::viewOnNonArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTexture texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32}); + + auto view = CubeMapTextureArray::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{8, 8, 6})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{4, 4, 6})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{2, 2, 6})); +} + void CubeMapTextureArrayGLTest::image() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); diff --git a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp index 8a6ca729d..cdbcbf2b2 100644 --- a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp @@ -48,6 +48,10 @@ #include #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +#include "Magnum/GL/CubeMapTextureArray.h" +#endif + namespace Magnum { namespace GL { namespace Test { namespace { struct CubeMapTextureGLTest: OpenGLTester { @@ -86,6 +90,11 @@ struct CubeMapTextureGLTest: OpenGLTester { void storageImageSize(); + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + void view(); + void viewOnArray(); + #endif + void storage(); void image(); #ifndef MAGNUM_TARGET_GLES2 @@ -348,7 +357,13 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { &CubeMapTextureGLTest::samplingBorder, #endif - &CubeMapTextureGLTest::storageImageSize}); + &CubeMapTextureGLTest::storageImageSize, + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + &CubeMapTextureGLTest::view, + &CubeMapTextureGLTest::viewOnArray + #endif + }); addInstancedTests({ &CubeMapTextureGLTest::storage, @@ -736,6 +751,52 @@ void CubeMapTextureGLTest::storageImageSize() { #endif } +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +void CubeMapTextureGLTest::view() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTexture texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32}); + + auto view = CubeMapTexture::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{8, 8})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{4, 4})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{2, 2})); +} + +void CubeMapTextureGLTest::viewOnArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTextureArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32, 12}); + + auto view = CubeMapTexture::view(texture, TextureFormat::RGBA8, 2, 3, 6); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{8, 8})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{4, 4})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{2, 2})); +} +#endif + void CubeMapTextureGLTest::storage() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); diff --git a/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp b/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp index 2fb20b56e..7cd6e6bfc 100644 --- a/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp @@ -59,6 +59,11 @@ struct MultisampleTextureGLTest: OpenGLTester { void storage2D(); void storage2DArray(); + void view2D(); + void view2DOnArray(); + void view2DArray(); + void view2DArrayOnNonArray(); + void invalidateImage2D(); void invalidateImage2DArray(); @@ -87,6 +92,11 @@ MultisampleTextureGLTest::MultisampleTextureGLTest() { &MultisampleTextureGLTest::storage2D, &MultisampleTextureGLTest::storage2DArray, + &MultisampleTextureGLTest::view2D, + &MultisampleTextureGLTest::view2DOnArray, + &MultisampleTextureGLTest::view2DArray, + &MultisampleTextureGLTest::view2DArrayOnNonArray, + &MultisampleTextureGLTest::invalidateImage2D, &MultisampleTextureGLTest::invalidateImage2DArray, @@ -399,6 +409,100 @@ void MultisampleTextureGLTest::storage2DArray() { MAGNUM_VERIFY_NO_GL_ERROR(); } +void MultisampleTextureGLTest::view2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + MultisampleTexture2D texture; + /* Mesa software implementation supports only 1 sample so we have to clamp */ + texture.setStorage(Math::min(4, MultisampleTexture2D::maxColorSamples()), + TextureFormat::RGBA8, {32, 8}); + + auto view = MultisampleTexture2D::view(texture, TextureFormat::RGBA8); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(), (Vector2i{32, 8})); +} + +void MultisampleTextureGLTest::view2DOnArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + MultisampleTexture2DArray texture; + /* Mesa software implementation supports only 1 sample so we have to clamp */ + texture.setStorage(Math::min(4, MultisampleTexture2D::maxColorSamples()), + TextureFormat::RGBA8, {32, 8, 7}); + + auto view = MultisampleTexture2D::view(texture, TextureFormat::RGBA8, 4); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(), (Vector2i{32, 8})); +} + +void MultisampleTextureGLTest::view2DArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + MultisampleTexture2DArray texture; + /* Mesa software implementation supports only 1 sample so we have to clamp */ + texture.setStorage(Math::min(4, MultisampleTexture2D::maxColorSamples()), + TextureFormat::RGBA8, {32, 8, 7}); + + auto view = MultisampleTexture2DArray::view(texture, TextureFormat::RGBA8, 4, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(), (Vector3i{32, 8, 3})); +} + +void MultisampleTextureGLTest::view2DArrayOnNonArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + MultisampleTexture2D texture; + /* Mesa software implementation supports only 1 sample so we have to clamp */ + texture.setStorage(Math::min(4, MultisampleTexture2D::maxColorSamples()), + TextureFormat::RGBA8, {32, 8}); + + auto view = MultisampleTexture2DArray::view(texture, TextureFormat::RGBA8); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(), (Vector3i{32, 8, 1})); +} + void MultisampleTextureGLTest::invalidateImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) diff --git a/src/Magnum/GL/Test/RectangleTextureGLTest.cpp b/src/Magnum/GL/Test/RectangleTextureGLTest.cpp index 29ecc5525..6bf9c68cb 100644 --- a/src/Magnum/GL/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/GL/Test/RectangleTextureGLTest.cpp @@ -62,6 +62,8 @@ struct RectangleTextureGLTest: OpenGLTester { void storage(); + void view(); + void image(); void imageBuffer(); void imageQueryView(); @@ -134,7 +136,9 @@ RectangleTextureGLTest::RectangleTextureGLTest() { &RectangleTextureGLTest::samplingSwizzle, &RectangleTextureGLTest::samplingDepthStencilMode, - &RectangleTextureGLTest::storage}); + &RectangleTextureGLTest::storage, + + &RectangleTextureGLTest::view}); addInstancedTests({ &RectangleTextureGLTest::image, @@ -354,6 +358,18 @@ void RectangleTextureGLTest::storage() { MAGNUM_VERIFY_NO_GL_ERROR(); } +void RectangleTextureGLTest::view() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, {32, 8}); + + auto view = RectangleTexture::view(texture, TextureFormat::RGBA8); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(), (Vector2i{32, 8})); +} + void RectangleTextureGLTest::image() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); diff --git a/src/Magnum/GL/Test/TextureArrayGLTest.cpp b/src/Magnum/GL/Test/TextureArrayGLTest.cpp index e7f558b82..ec139230a 100644 --- a/src/Magnum/GL/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/GL/Test/TextureArrayGLTest.cpp @@ -43,6 +43,9 @@ #ifndef MAGNUM_TARGET_WEBGL #include "Magnum/GL/ImageFormat.h" +#include "Magnum/GL/CubeMapTexture.h" +#include "Magnum/GL/CubeMapTextureArray.h" +#include "Magnum/GL/Texture.h" #endif namespace Magnum { namespace GL { namespace Test { namespace { @@ -121,6 +124,17 @@ struct TextureArrayGLTest: OpenGLTester { #endif void storage2D(); + #ifndef MAGNUM_TARGET_WEBGL + #ifndef MAGNUM_TARGET_GLES + void view1D(); + void view1DOnNonArray(); + #endif + void view2D(); + void view2DOnNonArray(); + void view2DOnCubeMap(); + void view2DOnCubeMapArray(); + #endif + #ifndef MAGNUM_TARGET_GLES void image1D(); void image1DBuffer(); @@ -352,7 +366,19 @@ TextureArrayGLTest::TextureArrayGLTest() { #ifndef MAGNUM_TARGET_GLES &TextureArrayGLTest::storage1D, #endif - &TextureArrayGLTest::storage2D}); + &TextureArrayGLTest::storage2D, + + #ifndef MAGNUM_TARGET_WEBGL + #ifndef MAGNUM_TARGET_GLES + &TextureArrayGLTest::view1D, + &TextureArrayGLTest::view1DOnNonArray, + #endif + &TextureArrayGLTest::view2D, + &TextureArrayGLTest::view2DOnNonArray, + &TextureArrayGLTest::view2DOnCubeMap, + &TextureArrayGLTest::view2DOnCubeMapArray, + #endif + }); #ifndef MAGNUM_TARGET_GLES addInstancedTests({ @@ -935,6 +961,122 @@ void TextureArrayGLTest::storage2D() { #endif } +#ifndef MAGNUM_TARGET_WEBGL +#ifndef MAGNUM_TARGET_GLES +void TextureArrayGLTest::view1D() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + + Texture1DArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {128, 7}); + + auto view = Texture1DArray::view(texture, TextureFormat::RGBA8, 2, 3, 4, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{32, 3})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{16, 3})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{8, 3})); +} + +void TextureArrayGLTest::view1DOnNonArray() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + + Texture1D texture; + texture.setStorage(5, TextureFormat::RGBA8, 128); + + auto view = Texture1DArray::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{32, 1})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{16, 1})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{8, 1})); +} +#endif + +void TextureArrayGLTest::view2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + Texture2DArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {128, 32, 7}); + + auto view = Texture2DArray::view(texture, TextureFormat::RGBA8, 2, 3, 4, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{32, 8, 3})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{16, 4, 3})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{8, 2, 3})); +} + +void TextureArrayGLTest::view2DOnNonArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + Texture2D texture; + texture.setStorage(5, TextureFormat::RGBA8, {128, 32}); + + auto view = Texture2DArray::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{32, 8, 1})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{16, 4, 1})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{8, 2, 1})); +} + +void TextureArrayGLTest::view2DOnCubeMap() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTexture texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32}); + + auto view = Texture2DArray::view(texture, TextureFormat::RGBA8, 2, 3, 4, 2); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{8, 8, 2})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{4, 4, 2})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{2, 2, 2})); +} + +void TextureArrayGLTest::view2DOnCubeMapArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTextureArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32, 12}); + + auto view = Texture2DArray::view(texture, TextureFormat::RGBA8, 2, 3, 9, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{8, 8, 3})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{4, 4, 3})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{2, 2, 3})); +} +#endif + #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::image1D() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); diff --git a/src/Magnum/GL/Test/TextureGLTest.cpp b/src/Magnum/GL/Test/TextureGLTest.cpp index cdb29b054..4713822c9 100644 --- a/src/Magnum/GL/Test/TextureGLTest.cpp +++ b/src/Magnum/GL/Test/TextureGLTest.cpp @@ -46,6 +46,12 @@ #include #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +#include "Magnum/GL/TextureArray.h" +#include "Magnum/GL/CubeMapTexture.h" +#include "Magnum/GL/CubeMapTextureArray.h" +#endif + namespace Magnum { namespace GL { namespace Test { namespace { struct TextureGLTest: OpenGLTester { @@ -151,6 +157,17 @@ struct TextureGLTest: OpenGLTester { void storage3D(); #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES + void view1D(); + #endif + void view2D(); + void view2DOnArray(); + void view2DOnCubeMap(); + void view2DOnCubeMapArray(); + void view3D(); + #endif + #ifndef MAGNUM_TARGET_GLES void image1D(); void image1DBuffer(); @@ -539,7 +556,18 @@ TextureGLTest::TextureGLTest() { #endif &TextureGLTest::storage2D, #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) - &TextureGLTest::storage3D + &TextureGLTest::storage3D, + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::view1D, + #endif + &TextureGLTest::view2D, + &TextureGLTest::view2DOnArray, + &TextureGLTest::view2DOnCubeMap, + &TextureGLTest::view2DOnCubeMapArray, + &TextureGLTest::view3D #endif }); @@ -1412,6 +1440,128 @@ void TextureGLTest::storage3D() { } #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::view1D() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + + Texture1D texture; + texture.setStorage(5, TextureFormat::RGBA8, 128); + + auto view = Texture1D::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), 32); + CORRADE_COMPARE(view.imageSize(1), 16); + CORRADE_COMPARE(view.imageSize(2), 8); +} +#endif + +void TextureGLTest::view2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + Texture2D texture; + texture.setStorage(5, TextureFormat::RGBA8, {128, 32}); + + auto view = Texture2D::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{32, 8})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{16, 4})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{8, 2})); +} + +void TextureGLTest::view2DOnArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + Texture2DArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {128, 32, 7}); + + auto view = Texture2D::view(texture, TextureFormat::RGBA8, 2, 3, 4); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{32, 8})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{16, 4})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{8, 2})); +} + +void TextureGLTest::view2DOnCubeMap() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTexture texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32}); + + auto view = Texture2D::view(texture, TextureFormat::RGBA8, 2, 3, 4); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{8, 8})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{4, 4})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{2, 2})); +} + +void TextureGLTest::view2DOnCubeMapArray() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + CubeMapTextureArray texture; + texture.setStorage(5, TextureFormat::RGBA8, {32, 32, 12}); + + auto view = Texture2D::view(texture, TextureFormat::RGBA8, 2, 3, 11); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector2i{8, 8})); + CORRADE_COMPARE(view.imageSize(1), (Vector2i{4, 4})); + CORRADE_COMPARE(view.imageSize(2), (Vector2i{2, 2})); +} + +void TextureGLTest::view3D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported."); + #else + if(!Context::current().isExtensionSupported() && + !Context::current().isExtensionSupported()) + CORRADE_SKIP("Neither" << Extensions::EXT::texture_view::string() << "nor" << Extensions::OES::texture_view::string() << "is supported."); + #endif + + Texture3D texture; + texture.setStorage(5, TextureFormat::RGBA8, {128, 32, 64}); + + auto view = Texture3D::view(texture, TextureFormat::RGBA8, 2, 3); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(view.imageSize(0), (Vector3i{32, 8, 16})); + CORRADE_COMPARE(view.imageSize(1), (Vector3i{16, 4, 8})); + CORRADE_COMPARE(view.imageSize(2), (Vector3i{8, 2, 4})); +} +#endif + #ifndef MAGNUM_TARGET_GLES void TextureGLTest::image1D() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); diff --git a/src/Magnum/GL/Texture.cpp b/src/Magnum/GL/Texture.cpp index 813d25368..3a1166bda 100644 --- a/src/Magnum/GL/Texture.cpp +++ b/src/Magnum/GL/Texture.cpp @@ -40,6 +40,12 @@ #include "Magnum/GL/BufferImage.h" #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +#include "Magnum/GL/TextureArray.h" +#include "Magnum/GL/CubeMapTexture.h" +#include "Magnum/GL/CubeMapTextureArray.h" +#endif + namespace Magnum { namespace GL { namespace Implementation { @@ -65,6 +71,21 @@ template<> MAGNUM_GL_EXPORT Vector3i maxTextureSize<3>() { } +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +template Texture Texture::view(Texture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, 0, 1); + return out; +} + +/* Other view() overloads at the end */ +#endif + #ifndef MAGNUM_TARGET_GLES template Image Texture::image(const Int level, Image&& image) { this->image(level, image); @@ -122,4 +143,58 @@ template class MAGNUM_GL_EXPORT Texture<2>; template class MAGNUM_GL_EXPORT Texture<3>; #endif +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +/* Because these refer to concrete types different than the class itself, they + have to be after the explicit type instantiations. Additionally, on Windows + (MSVC, clang-cl and MinGw) these need an explicit export otherwise the + symbol doesn't get exported. + + Other view() overloads at the top. */ +#ifndef MAGNUM_TARGET_GLES +template<> template<> MAGNUM_GL_EXPORT Texture1D Texture1D::view(Texture1DArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture1D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} +#endif + +template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(Texture2DArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} +#endif + }} diff --git a/src/Magnum/GL/Texture.h b/src/Magnum/GL/Texture.h index db31a9c93..267e173ff 100644 --- a/src/Magnum/GL/Texture.h +++ b/src/Magnum/GL/Texture.h @@ -151,6 +151,90 @@ template class Texture: public AbstractTexture { } #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * @brief Create a view on another texture + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_1D}, + * @def_gl{TEXTURE_2D} or @def_gl{TEXTURE_3D} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + static Texture view(Texture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount); + + /** + * @brief Create a view on a layer of an array texture + * @m_since_latest + * + * Enabled only on a @ref Texture1D and @ref Texture2D. The + * @p internalFormat has to either match the format of @p original, or + * be compatible with it, such as having the same pixel size and other + * restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_1D} or + * @def_gl{TEXTURE_2D} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static Texture view(TextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layer); + + /** + * @brief Create a view on a layer of a cube map texture + * @m_since_latest + * + * Enabled only on a @ref Texture2D. The @p internalFormat has to + * either match the format of @p original, or be compatible with it, + * such as having the same pixel size and other restrictions described + * in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_2D} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static Texture view(CubeMapTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layer); + + /** + * @brief Create a view on a layer of a cube map texture array + * @m_since_latest + * + * Enabled only on a @ref Texture2D. The @p internalFormat has to + * either match the format of @p original, or be compatible with it, + * such as having the same pixel size and other restrictions described + * in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_2D} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static Texture view(CubeMapTextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layer); + #endif + /** * @brief Wrap existing OpenGL texture object * @param id OpenGL texture ID @@ -721,7 +805,7 @@ template class Texture: public AbstractTexture { * 4.2), OpenGL ES 3.0 nor @gl_extension{EXT,texture_storage} in OpenGL * ES 2.0 is available, the feature is emulated with sequence of * @ref setImage() calls. - * @see @ref maxSize(), @ref setMaxLevel(), + * @see @ref view(), @ref maxSize(), @ref setMaxLevel(), * @fn_gl2_keyword{TextureStorage1D,TexStorage1D} / * @fn_gl2_keyword{TextureStorage2D,TexStorage2D} / * @fn_gl2_keyword{TextureStorage3D,TexStorage3D}, diff --git a/src/Magnum/GL/TextureArray.cpp b/src/Magnum/GL/TextureArray.cpp index 83d22992c..990a7d864 100644 --- a/src/Magnum/GL/TextureArray.cpp +++ b/src/Magnum/GL/TextureArray.cpp @@ -39,6 +39,12 @@ #include "Magnum/GL/BufferImage.h" #endif +#ifndef MAGNUM_TARGET_WEBGL +#include "Magnum/GL/Texture.h" +#include "Magnum/GL/CubeMapTexture.h" +#include "Magnum/GL/CubeMapTextureArray.h" +#endif + namespace Magnum { namespace GL { namespace { @@ -57,6 +63,32 @@ template VectorTypeFor TextureArray TextureArray TextureArray::view(TextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + TextureArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); + return out; +} + +template TextureArray TextureArray::view(Texture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + TextureArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, 0, 1); + return out; +} + +/* Other view() overloads at the end */ +#endif + #ifndef MAGNUM_TARGET_GLES template Image TextureArray::image(const Int level, Image&& image) { this->image(level, image); @@ -111,5 +143,35 @@ template class MAGNUM_GL_EXPORT TextureArray<1>; #endif template class MAGNUM_GL_EXPORT TextureArray<2>; +#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +/* Because these refer to concrete types different than the class itself, they + have to be after the explicit type instantiations. Additionally, on Windows + (MSVC, clang-cl and MinGw) these need an explicit export otherwise the + symbol doesn't get exported. + + Other view() overloads at the top. */ +template<> template<> MAGNUM_GL_EXPORT Texture2DArray Texture2DArray::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT Texture2DArray Texture2DArray::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); + return out; +} +#endif + }} #endif diff --git a/src/Magnum/GL/TextureArray.h b/src/Magnum/GL/TextureArray.h index 5cbf345e8..4b633132f 100644 --- a/src/Magnum/GL/TextureArray.h +++ b/src/Magnum/GL/TextureArray.h @@ -136,6 +136,86 @@ template class TextureArray: public AbstractTexture { } #endif + #ifndef MAGNUM_TARGET_WEBGL + /** + * @brief Create a view on another texture array + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_1D_ARRAY} or + * @def_gl{TEXTURE_2D_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + static TextureArray view(TextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount); + + /** + * @brief Create a view on a texture + * @m_since_latest + * + * The @p internalFormat has to either match the format of @p original, + * or be compatible with it, such as having the same pixel size and + * other restrictions described in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_1D_ARRAY} or + * @def_gl{TEXTURE_2D_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + static TextureArray view(Texture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount); + + /** + * @brief Create a view on a cube map texture + * @m_since_latest + * + * Enabled only on a @ref Texture2DArray. The @p internalFormat has to + * either match the format of @p original, or be compatible with it, + * such as having the same pixel size and other restrictions described + * in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_2D_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static TextureArray view(CubeMapTexture& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount); + + /** + * @brief Create a view on a cube map texture array + * @m_since_latest + * + * Enabled only on a @ref Texture2DArray. The @p internalFormat has to + * either match the format of @p original, or be compatible with it, + * such as having the same pixel size and other restrictions described + * in the OpenGL specification. + * @see @ref setStorage(), @fn_gl_keyword{GenTextures}, + * @fn_gl_keyword{TextureView} with @def_gl{TEXTURE_2D_ARRAY} + * @requires_gl43 Extension @gl_extension{ARB,texture_view} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{OES,texture_view} or + * @gl_extension{EXT,texture_view} + * @requires_gles Texture views are not available in WebGL. + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + static TextureArray view(CubeMapTextureArray& original, TextureFormat internalFormat, Int levelOffset, Int levelCount, Int layerOffset, Int layerCount); + #endif + /** * @brief Wrap existing OpenGL texture array object * @param id OpenGL texture array ID @@ -492,7 +572,7 @@ template class TextureArray: public AbstractTexture { * @return Reference to self (for method chaining) * * See @ref Texture::setStorage() for more information. - * @see @ref maxSize() + * @see @ref view(), @ref maxSize() */ TextureArray& setStorage(Int levels, TextureFormat internalFormat, const VectorTypeFor& size) { DataHelper::setStorage(*this, levels, internalFormat, size);