From 4a88b4633d22345b0942847cd9c79716c048ea7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 24 Apr 2018 19:39:48 +0200 Subject: [PATCH] DebugTools: support generic pixel formats in textureSubImage(). --- doc/changelog.dox | 6 ++ .../DebugTools/Test/TextureImageGLTest.cpp | 59 ++++++++++++ src/Magnum/DebugTools/TextureImage.cpp | 79 +++++++--------- src/Magnum/DebugTools/TextureImage.h | 93 ++++++++++++++----- 4 files changed, 169 insertions(+), 68 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 1ae8c9039..4140f41e8 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -123,6 +123,12 @@ See also: a compatibility code path is implemented, the @ref GL library expects that all parameters are at their defaults. +@subsubsection changelog-latest-changes-debugtools DebugTools library + +- @ref DebugTools::textureSubImage() now accepts both GL-specific + @ref GL::PixelFormat / @ref GL::PixelType combination and the generic + @ref PixelFormat enum + @subsubsection changelog-latest-changes-gl GL library - The @ref GL::Mesh::indexTypeSize() and @ref GL::MeshView::setIndexRange() diff --git a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp index 9df7075b5..0bb4b7079 100644 --- a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp +++ b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp @@ -26,6 +26,7 @@ #include #include "Magnum/Image.h" +#include "Magnum/PixelFormat.h" #include "Magnum/DebugTools/TextureImage.h" #include "Magnum/GL/CubeMapTexture.h" #include "Magnum/GL/OpenGLTester.h" @@ -48,6 +49,7 @@ struct TextureImageGLTest: GL::OpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void subImage2DBuffer(); #endif + void subImage2DGeneric(); void subImageCube(); #ifndef MAGNUM_TARGET_GLES2 @@ -57,6 +59,7 @@ struct TextureImageGLTest: GL::OpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void subImage2DUInt(); void subImage2DFloat(); + void subImage2DFloatGeneric(); #endif }; @@ -65,6 +68,7 @@ TextureImageGLTest::TextureImageGLTest() { #ifndef MAGNUM_TARGET_GLES2 &TextureImageGLTest::subImage2DBuffer, #endif + &TextureImageGLTest::subImage2DGeneric, &TextureImageGLTest::subImageCube, #ifndef MAGNUM_TARGET_GLES2 @@ -74,6 +78,7 @@ TextureImageGLTest::TextureImageGLTest() { #ifndef MAGNUM_TARGET_GLES2 &TextureImageGLTest::subImage2DUInt, &TextureImageGLTest::subImage2DFloat, + &TextureImageGLTest::subImage2DFloatGeneric, #endif }); } @@ -98,6 +103,9 @@ void TextureImageGLTest::subImage2D() { Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {GL::PixelFormat::RGBA, GL::PixelType::UnsignedByte}); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), pixelFormatWrap(GL::PixelFormat::RGBA)); + CORRADE_COMPARE(GL::PixelType(image.formatExtra()), GL::PixelType::UnsignedByte); + CORRADE_COMPARE(image.pixelSize(), 4); CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), Containers::arrayView(Data2D), TestSuite::Compare::Container); } @@ -111,11 +119,34 @@ void TextureImageGLTest::subImage2DBuffer() { Containers::Array data = bufferData(image.buffer()); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), GL::PixelFormat::RGBA); + CORRADE_COMPARE(image.type(), GL::PixelType::UnsignedByte); + CORRADE_COMPARE(image.pixelSize(), 4); CORRADE_COMPARE_AS(data, Containers::arrayView(Data2D), TestSuite::Compare::Container); } #endif +void TextureImageGLTest::subImage2DGeneric() { + GL::Texture2D texture; + texture.setImage(0, + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + GL::TextureFormat::RGBA8, + #else + GL::TextureFormat::RGBA, + #endif + ImageView2D{PixelFormat::RGBA8Unorm, Vector2i{2}, Data2D}); + + Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {PixelFormat::RGBA8Unorm}); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), PixelFormat::RGBA8Unorm); + CORRADE_COMPARE(image.formatExtra(), 0); + CORRADE_COMPARE(image.pixelSize(), 4); + CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), + Containers::arrayView(Data2D), TestSuite::Compare::Container); +} + void TextureImageGLTest::subImageCube() { ImageView2D view{GL::PixelFormat::RGBA, GL::PixelType::UnsignedByte, Vector2i{2}, Data2D}; @@ -136,6 +167,9 @@ void TextureImageGLTest::subImageCube() { Image2D image = textureSubImage(texture, GL::CubeMapCoordinate::PositiveX, 0, {{}, Vector2i{2}}, {GL::PixelFormat::RGBA, GL::PixelType::UnsignedByte}); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), pixelFormatWrap(GL::PixelFormat::RGBA)); + CORRADE_COMPARE(GL::PixelType(image.formatExtra()), GL::PixelType::UnsignedByte); + CORRADE_COMPARE(image.pixelSize(), 4); CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), Containers::arrayView(Data2D), TestSuite::Compare::Container); } @@ -156,6 +190,9 @@ void TextureImageGLTest::subImageCubeBuffer() { Containers::Array data = bufferData(image.buffer()); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), GL::PixelFormat::RGBA); + CORRADE_COMPARE(image.type(), GL::PixelType::UnsignedByte); + CORRADE_COMPARE(image.pixelSize(), 4); CORRADE_COMPARE_AS(data, Containers::arrayView(Data2D), TestSuite::Compare::Container); } @@ -176,6 +213,9 @@ void TextureImageGLTest::subImage2DUInt() { Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {GL::PixelFormat::RedInteger, GL::PixelType::UnsignedInt}); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), pixelFormatWrap(GL::PixelFormat::RedInteger)); + CORRADE_COMPARE(GL::PixelType(image.formatExtra()), GL::PixelType::UnsignedInt); + CORRADE_COMPARE(image.pixelSize(), 4); CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), Containers::arrayView(Data2DUInt), TestSuite::Compare::Container); @@ -196,6 +236,25 @@ void TextureImageGLTest::subImage2DFloat() { Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {GL::PixelFormat::Red, GL::PixelType::Float}); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), pixelFormatWrap(GL::PixelFormat::Red)); + CORRADE_COMPARE(GL::PixelType(image.formatExtra()), GL::PixelType::Float); + CORRADE_COMPARE(image.pixelSize(), 4); + CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), + Containers::arrayView(Data2DFloat), + TestSuite::Compare::Container); +} + +void TextureImageGLTest::subImage2DFloatGeneric() { + GL::Texture2D texture; + texture.setStorage(1, GL::TextureFormat::R32F, Vector2i{2}) + .setSubImage(0, {}, ImageView2D{GL::PixelFormat::Red, GL::PixelType::Float, Vector2i{2}, Data2DFloat}); + + Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {PixelFormat::R32F}); + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE(image.format(), PixelFormat::R32F); + CORRADE_COMPARE(image.formatExtra(), 0); + CORRADE_COMPARE(image.pixelSize(), 4); CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), Containers::arrayView(Data2DFloat), TestSuite::Compare::Container); diff --git a/src/Magnum/DebugTools/TextureImage.cpp b/src/Magnum/DebugTools/TextureImage.cpp index 8027b5e0e..d88c63745 100644 --- a/src/Magnum/DebugTools/TextureImage.cpp +++ b/src/Magnum/DebugTools/TextureImage.cpp @@ -56,11 +56,11 @@ namespace Magnum { namespace DebugTools { #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) namespace { -class FloatReinterpretShader: public AbstractShaderProgram { +class FloatReinterpretShader: public GL::AbstractShaderProgram { public: explicit FloatReinterpretShader(); - FloatReinterpretShader& setTexture(Texture2D& texture, Int level) { + FloatReinterpretShader& setTexture(GL::Texture2D& texture, Int level) { texture.bind(0); setUniform(levelUniform, level); return *this; @@ -78,12 +78,12 @@ FloatReinterpretShader::FloatReinterpretShader() { #endif Utility::Resource rs{"MagnumDebugTools"}; - Shader vert{Version::GLES300, Shader::Type::Vertex}; - Shader frag{Version::GLES300, Shader::Type::Fragment}; + GL::Shader vert{GL::Version::GLES300, GL::Shader::Type::Vertex}; + GL::Shader frag{GL::Version::GLES300, GL::Shader::Type::Fragment}; vert.addSource(rs.get("TextureImage.vert")); frag.addSource(rs.get("TextureImage.frag")); - CORRADE_INTERNAL_ASSERT(Shader::compile({vert, frag})); + CORRADE_INTERNAL_ASSERT(GL::Shader::compile({vert, frag})); attachShaders({vert, frag}); CORRADE_INTERNAL_ASSERT(link()); @@ -97,68 +97,61 @@ FloatReinterpretShader::FloatReinterpretShader() { void textureSubImage(GL::Texture2D& texture, const Int level, const Range2Di& range, Image2D& image) { #ifndef MAGNUM_TARGET_GLES - if(Context::current().isExtensionSupported()) { + if(GL::Context::current().isExtensionSupported()) { texture.subImage(level, range, image); return; } #endif #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) - if(image.type() == PixelType::Float) { - const PixelFormat imageFormat = image.format(); - TextureFormat textureFormat; - PixelFormat reinterpretFormat; - switch(imageFormat) { - case PixelFormat::Red: - textureFormat = TextureFormat::R32UI; - reinterpretFormat = PixelFormat::RedInteger; + GL::PixelType type = GL::pixelType(image.format(), image.formatExtra()); + if(type == GL::PixelType::Float) { + GL::TextureFormat textureFormat; + GL::PixelFormat reinterpretFormat; + GL::PixelFormat format = GL::pixelFormat(image.format()); + switch(format) { + case GL::PixelFormat::Red: + textureFormat = GL::TextureFormat::R32UI; + reinterpretFormat = GL::PixelFormat::RedInteger; break; - case PixelFormat::RG: - textureFormat = TextureFormat::RG32UI; - reinterpretFormat = PixelFormat::RGInteger; + case GL::PixelFormat::RG: + textureFormat = GL::TextureFormat::RG32UI; + reinterpretFormat = GL::PixelFormat::RGInteger; break; - case PixelFormat::RGB: - textureFormat = TextureFormat::RGB32UI; - reinterpretFormat = PixelFormat::RGBInteger; + case GL::PixelFormat::RGB: + textureFormat = GL::TextureFormat::RGB32UI; + reinterpretFormat = GL::PixelFormat::RGBInteger; break; - case PixelFormat::RGBA: - textureFormat = TextureFormat::RGBA32UI; - reinterpretFormat = PixelFormat::RGBAInteger; + case GL::PixelFormat::RGBA: + textureFormat = GL::TextureFormat::RGBA32UI; + reinterpretFormat = GL::PixelFormat::RGBAInteger; break; default: - CORRADE_ASSERT(false, "DebugTools::textureSubImage(): unsupported pixel format" << image.format(), ); + CORRADE_ASSERT(false, "DebugTools::textureSubImage(): unsupported pixel format" << format, ); } - Texture2D output; + GL::Texture2D output; output.setStorage(1, textureFormat, range.max()); - Framebuffer fb{range}; - fb.attachTexture(Framebuffer::ColorAttachment{0}, output, 0) + GL::Framebuffer fb{range}; + fb.attachTexture(GL::Framebuffer::ColorAttachment{0}, output, 0) .bind(); - CORRADE_INTERNAL_ASSERT(fb.checkStatus(FramebufferTarget::Draw) == Framebuffer::Status::Complete); - CORRADE_INTERNAL_ASSERT(fb.checkStatus(FramebufferTarget::Read) == Framebuffer::Status::Complete); + CORRADE_INTERNAL_ASSERT(fb.checkStatus(GL::FramebufferTarget::Draw) == GL::Framebuffer::Status::Complete); + CORRADE_INTERNAL_ASSERT(fb.checkStatus(GL::FramebufferTarget::Read) == GL::Framebuffer::Status::Complete); FloatReinterpretShader shader; shader.setTexture(texture, level); - Mesh mesh; + GL::Mesh mesh; mesh.setCount(3) .draw(shader); /* release() needs to be called after querying the size to avoid zeroing it out */ - { - Vector2i imageSize = image.size(); - image = Image2D{image.storage(), reinterpretFormat, PixelType::UnsignedInt, imageSize, image.release()}; - } - - fb.read(range, image); - - /* release() needs to be called after querying the size to avoid zeroing it out */ - { - Vector2i imageSize = image.size(); - image = Image2D{image.storage(), imageFormat, PixelType::Float, imageSize, image.release()}; - } + const Vector2i imageSize = image.size(); + Image2D temp{image.storage(), reinterpretFormat, GL::PixelType::UnsignedInt, imageSize, image.release()}; + fb.read(range, temp); + image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), imageSize, temp.release()}; return; } #endif @@ -176,7 +169,7 @@ Image2D textureSubImage(GL::Texture2D& texture, const Int level, const Range2Di& #ifndef MAGNUM_TARGET_GLES2 void textureSubImage(GL::Texture2D& texture, const Int level, const Range2Di& range, GL::BufferImage2D& image, const GL::BufferUsage usage) { #ifndef MAGNUM_TARGET_GLES - if(Context::current().isExtensionSupported()) { + if(GL::Context::current().isExtensionSupported()) { texture.subImage(level, range, image, usage); return; } diff --git a/src/Magnum/DebugTools/TextureImage.h b/src/Magnum/DebugTools/TextureImage.h index a47f44dbc..ae9804e03 100644 --- a/src/Magnum/DebugTools/TextureImage.h +++ b/src/Magnum/DebugTools/TextureImage.h @@ -25,30 +25,38 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_TARGET_GL /** @file * @brief Function @ref Magnum::DebugTools::textureSubImage() */ +#endif #include "Magnum/Magnum.h" #include "Magnum/DebugTools/visibility.h" #include "Magnum/GL/GL.h" +#ifdef MAGNUM_TARGET_GL namespace Magnum { namespace DebugTools { /** @brief Read range of given texture mip level to image -Emulates @ref Texture2D::subImage() call on platforms that don't support it +Emulates @ref GL::Texture2D::subImage() call on platforms that don't support it (such as OpenGL ES) by creating a framebuffer object and using -@ref Framebuffer::read(). On desktop OpenGL, if @extension{ARB,get_texture_sub_image} -is available, it's just an alias to @ref Texture2D::subImage(). - -Note that only @ref Magnum::PixelFormat "PixelFormat" and @ref PixelType values -that are marked as framebuffer readable are supported. In addition, on OpenGL -ES 3.0, images with @ref PixelType::Float are supported --- they are -reinterpreted as @ref PixelType::UnsignedInt using additional shader and -`floatBitsToUint()` GLSL function and then reinterpreted back to -@ref PixelType::Float when read to client memory. +@ref GL::Framebuffer::read(). On desktop OpenGL, if @extension{ARB,get_texture_sub_image} +is available, it's just an alias to @ref GL::Texture2D::subImage(). + +Note that only @ref GL::PixelFormat and @ref GL::PixelType values that are +marked as framebuffer readable are supported; their generic +@ref Magnum::PixelFormat "PixelFormat" counterparts are supported as well. In +addition, on OpenGL ES 3.0, images with @ref GL::PixelType::Float are supported +--- they are reinterpreted as @ref GL::PixelType::UnsignedInt using an +additional shader and the @glsl floatBitsToUint() @ce GLSL function and then +reinterpreted back to @ref GL::PixelType::Float when read to client memory. + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(GL::Texture2D& texture, Int level, const Range2Di& range, Image2D& image); @@ -60,18 +68,27 @@ Convenience alternative to the above, example usage: @code{.cpp} Image2D image = DebugTools::textureSubImage(texture, 0, rect, {PixelFormat::RGBA, PixelType::UnsignedByte}); @endcode + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT Image2D textureSubImage(GL::Texture2D& texture, Int level, const Range2Di& range, Image2D&& image); /** @brief Read range of given cube map texture coordinate mip level to image -Emulates @ref CubeMapTexture::subImage() call on platforms that don't support -it (such as OpenGL ES) by creating a framebuffer object and using -@ref Framebuffer::read(). +Emulates @ref GL::CubeMapTexture::subImage() call on platforms that don't +support it (such as OpenGL ES) by creating a framebuffer object and using +@ref GL::Framebuffer::read(). + +Note that only @ref GL::PixelFormat and @ref GL::PixelType values that are +marked as framebuffer readable are supported; their generic +@ref Magnum::PixelFormat "PixelFormat" counterparts are supported as well. -Note that only @ref Magnum::PixelFormat "PixelFormat" and @ref PixelType values -that are marked as framebuffer readable are supported. +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(GL::CubeMapTexture& texture, GL::CubeMapCoordinate coordinate, Int level, const Range2Di& range, Image2D& image); @@ -83,6 +100,10 @@ Convenience alternative to the above, example usage: @code{.cpp} Image2D image = DebugTools::textureSubImage(texture, CubeMapCoordinate::PositiveX, 0, rect, {PixelFormat::RGBA, PixelType::UnsignedByte}); @endcode + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT Image2D textureSubImage(GL::CubeMapTexture& texture, GL::CubeMapCoordinate coordinate, Int level, const Range2Di& range, Image2D&& image); @@ -90,15 +111,21 @@ MAGNUM_DEBUGTOOLS_EXPORT Image2D textureSubImage(GL::CubeMapTexture& texture, GL /** @brief Read range of given texture mip level to buffer image -Emulates @ref Texture2D::subImage() call on platforms that don't support it +Emulates @ref GL::Texture2D::subImage() call on platforms that don't support it (such as OpenGL ES) by creating a framebuffer object and using -@ref Framebuffer::read(). On desktop OpenGL, if @extension{ARB,get_texture_sub_image} -is available, it's just an alias to @ref Texture2D::subImage(). +@ref GL::Framebuffer::read(). On desktop OpenGL, if +@extension{ARB,get_texture_sub_image} is available, it's just an alias to +@ref GL::Texture2D::subImage(). -Note that only @ref Magnum::PixelFormat "PixelFormat" and @ref PixelType values -that are marked as framebuffer readable are supported. +Note that only @ref GL::PixelFormat and @ref GL::PixelType values that are +marked as framebuffer readable are supported; their generic +@ref Magnum::PixelFormat "PixelFormat" counterparts are supported as well. @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. @requires_webgl20 Pixel buffer objects are not available in WebGL 1.0. + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(GL::Texture2D& texture, Int level, const Range2Di& range, GL::BufferImage2D& image, GL::BufferUsage usage); @@ -110,20 +137,29 @@ Convenience alternative to the above, example usage: @code{.cpp} BufferImage2D image = DebugTools::textureSubImage(texture, 0, rect, {PixelFormat::RGBA, PixelType::UnsignedByte}, BufferUsage::StaticRead); @endcode + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT GL::BufferImage2D textureSubImage(GL::Texture2D& texture, Int level, const Range2Di& range, GL::BufferImage2D&& image, GL::BufferUsage usage); /** @brief Read range of given cube map texture coordinate mip level to buffer image -Emulates @ref CubeMapTexture::subImage() call on platforms that don't support -it (such as OpenGL ES) by creating a framebuffer object and using -@ref Framebuffer::read(). +Emulates @ref GL::CubeMapTexture::subImage() call on platforms that don't +support it (such as OpenGL ES) by creating a framebuffer object and using +@ref GL::Framebuffer::read(). -Note that only @ref Magnum::PixelFormat "PixelFormat" and @ref PixelType values -that are marked as framebuffer readable are supported. +Note that only @ref GL::PixelFormat and @ref GL::PixelType values that are +marked as framebuffer readable are supported; their generic +@ref Magnum::PixelFormat "PixelFormat" counterparts are supported as well. @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. @requires_webgl20 Pixel buffer objects are not available in WebGL 1.0. + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(GL::CubeMapTexture& texture, GL::CubeMapCoordinate coordinate, Int level, const Range2Di& range, GL::BufferImage2D& image, GL::BufferUsage usage); @@ -135,9 +171,16 @@ Convenience alternative to the above, example usage: @code{.cpp} BufferImage2D image = DebugTools::textureSubImage(texture, CubeMapCoordinate::PositiveX, 0, rect, {PixelFormat::RGBA, PixelType::UnsignedByte}, BufferUsage::StaticRead); @endcode + +@note This function is available only if Magnum is compiled with + @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features + for more information. */ MAGNUM_DEBUGTOOLS_EXPORT GL::BufferImage2D textureSubImage(GL::CubeMapTexture& texture, GL::CubeMapCoordinate coordinate, Int level, const Range2Di& range, GL::BufferImage2D&& image, GL::BufferUsage usage); #endif +#else +#error this header is available only in the OpenGL build +#endif }}