Browse Source

GL: implement {ARB,OES,EXT}_texture_view.

"Funny" how this is the only API where I can't use glCreateTextures().
Like, it would have been so easy to just stop teaching glGen*() and
all their quirks and "this ID exists but it's not an object until you
bind it somewhere actually" to people altogether, BUT NO! FFS.
pull/601/head
Vladimír Vondruš 3 years ago
parent
commit
3227766aca
  1. 4
      doc/changelog.dox
  2. 2
      doc/opengl-mapping.dox
  3. 6
      doc/opengl-support.dox
  4. 6
      src/Magnum/GL/AbstractTexture.cpp
  5. 3
      src/Magnum/GL/AbstractTexture.h
  6. 28
      src/Magnum/GL/CubeMapTexture.cpp
  7. 36
      src/Magnum/GL/CubeMapTexture.h
  8. 23
      src/Magnum/GL/CubeMapTextureArray.cpp
  9. 36
      src/Magnum/GL/CubeMapTextureArray.h
  10. 24
      src/Magnum/GL/Implementation/TextureState.cpp
  11. 3
      src/Magnum/GL/Implementation/TextureState.h
  12. 40
      src/Magnum/GL/MultisampleTexture.cpp
  13. 64
      src/Magnum/GL/MultisampleTexture.h
  14. 11
      src/Magnum/GL/RectangleTexture.cpp
  15. 14
      src/Magnum/GL/RectangleTexture.h
  16. 57
      src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp
  17. 63
      src/Magnum/GL/Test/CubeMapTextureGLTest.cpp
  18. 104
      src/Magnum/GL/Test/MultisampleTextureGLTest.cpp
  19. 18
      src/Magnum/GL/Test/RectangleTextureGLTest.cpp
  20. 144
      src/Magnum/GL/Test/TextureArrayGLTest.cpp
  21. 152
      src/Magnum/GL/Test/TextureGLTest.cpp
  22. 75
      src/Magnum/GL/Texture.cpp
  23. 86
      src/Magnum/GL/Texture.h
  24. 62
      src/Magnum/GL/TextureArray.cpp
  25. 82
      src/Magnum/GL/TextureArray.h

4
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

2
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()

6
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} | |

6
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);
}

3
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();

28
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;

36
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

23
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);

36
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);

24
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::ARB::texture_view>()) {
extensions[Extensions::ARB::texture_view::Index] =
Extensions::ARB::texture_view::string();
viewImplementation = glTextureView;
}
#else
if(context.isExtensionSupported<Extensions::EXT::texture_view>()) {
extensions[Extensions::EXT::texture_view::Index] =
Extensions::EXT::texture_view::string();
viewImplementation = glTextureViewEXT;
} else if(context.isExtensionSupported<Extensions::OES::texture_view>()) {
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<Extensions::ARB::invalidate_subdata>()) {

3
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&);

40
src/Magnum/GL/MultisampleTexture.cpp

@ -64,6 +64,19 @@ template<> Vector3i MAGNUM_GL_EXPORT maxMultisampleTextureSize<3>() {
}
template<UnsignedInt dimensions> MultisampleTexture<dimensions> MultisampleTexture<dimensions>::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<dimensions> out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction};
out.viewInternal(original, internalFormat, 0, 1, 0, 1);
return out;
}
/* Other view() overloads at the end */
template<UnsignedInt dimensions> MultisampleTexture<dimensions>& MultisampleTexture<dimensions>::setLabel(Containers::StringView label) {
AbstractTexture::setLabel(label);
return *this;
@ -72,5 +85,32 @@ template<UnsignedInt dimensions> MultisampleTexture<dimensions>& 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

64
src/Magnum/GL/MultisampleTexture.h

@ -121,6 +121,66 @@ template<UnsignedInt dimensions> class MAGNUM_GL_EXPORT MultisampleTexture: publ
return Implementation::maxMultisampleTextureSize<dimensions>();
}
/**
* @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<dimensions> 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<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
#endif
static MultisampleTexture<dimensions> 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<UnsignedInt d = dimensions, class = typename std::enable_if<d == 3>::type>
#endif
static MultisampleTexture<dimensions> 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<UnsignedInt dimensions> 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}

11
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);

14
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

57
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<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_cube_map_array>())
CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_cube_map_array>())
CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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);

63
src/Magnum/GL/Test/CubeMapTextureGLTest.cpp

@ -48,6 +48,10 @@
#include <Corrade/Containers/String.h>
#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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_cube_map_array>())
CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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);

104
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<Extensions::ARB::texture_multisample>())
CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_multisample>())
CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::OES::texture_storage_multisample_2d_array>())
CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_multisample>())
CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::OES::texture_storage_multisample_2d_array>())
CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_multisample>())
CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::OES::texture_storage_multisample_2d_array>())
CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_multisample>())

18
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<Extensions::ARB::texture_view>())
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);

144
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<Extensions::ARB::texture_view>())
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<Extensions::ARB::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_cube_map_array>())
CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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);

152
src/Magnum/GL/Test/TextureGLTest.cpp

@ -46,6 +46,12 @@
#include <Corrade/Containers/String.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 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<Extensions::ARB::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_cube_map_array>())
CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_cube_map_array>())
CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported.");
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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<Extensions::ARB::texture_view>())
CORRADE_SKIP(Extensions::ARB::texture_view::string() << "is not supported.");
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::texture_view>() &&
!Context::current().isExtensionSupported<Extensions::OES::texture_view>())
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);

75
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<UnsignedInt dimensions> Texture<dimensions> Texture<dimensions>::view(Texture<dimensions>& 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<dimensions> 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<UnsignedInt dimensions> Image<dimensions> Texture<dimensions>::image(const Int level, Image<dimensions>&& 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
}}

86
src/Magnum/GL/Texture.h

@ -151,6 +151,90 @@ template<UnsignedInt dimensions> 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<dimensions> view(Texture<dimensions>& 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<UnsignedInt d = dimensions, class = typename std::enable_if<d <= 2>::type>
#endif
static Texture<dimensions> view(TextureArray<dimensions>& 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<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
#endif
static Texture<dimensions> 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<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
#endif
static Texture<dimensions> 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<UnsignedInt dimensions> 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},

62
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<UnsignedInt dimensions> VectorTypeFor<dimensions+1, Int> TextureArray<d
Implementation::maxTextureArrayLayers()};
}
#ifndef MAGNUM_TARGET_WEBGL
template<UnsignedInt dimensions> TextureArray<dimensions> TextureArray<dimensions>::view(TextureArray<dimensions>& 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<dimensions> out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction};
out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount);
return out;
}
template<UnsignedInt dimensions> TextureArray<dimensions> TextureArray<dimensions>::view(Texture<dimensions>& 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<dimensions> 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<UnsignedInt dimensions> Image<dimensions+1> TextureArray<dimensions>::image(const Int level, Image<dimensions+1>&& 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

82
src/Magnum/GL/TextureArray.h

@ -136,6 +136,86 @@ template<UnsignedInt dimensions> 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<dimensions> view(TextureArray<dimensions>& 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<dimensions> view(Texture<dimensions>& 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<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
#endif
static TextureArray<dimensions> 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<UnsignedInt d = dimensions, class = typename std::enable_if<d == 2>::type>
#endif
static TextureArray<dimensions> 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<UnsignedInt dimensions> 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<dimensions>& setStorage(Int levels, TextureFormat internalFormat, const VectorTypeFor<dimensions+1, Int>& size) {
DataHelper<dimensions+1>::setStorage(*this, levels, internalFormat, size);

Loading…
Cancel
Save