From 9619bf08b628a37353a4ca1ac9a5bf0c350db28a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 8 Feb 2015 23:16:57 +0100 Subject: [PATCH] Support for ARB_get_texture_sub_image. Only thing missing are compressed texture queries, but that needs a lot more work. --- doc/opengl-mapping.dox | 2 +- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 37 +++++ src/Magnum/AbstractTexture.h | 5 +- src/Magnum/CubeMapTexture.cpp | 10 ++ src/Magnum/CubeMapTexture.h | 42 ++++++ src/Magnum/CubeMapTextureArray.cpp | 10 ++ src/Magnum/CubeMapTextureArray.h | 40 +++++ src/Magnum/RectangleTexture.cpp | 10 ++ src/Magnum/RectangleTexture.h | 40 +++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 48 ++++++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 56 +++++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 48 ++++++ src/Magnum/Test/TextureArrayGLTest.cpp | 97 +++++++++++++ src/Magnum/Test/TextureGLTest.cpp | 137 ++++++++++++++++++ src/Magnum/Texture.cpp | 22 +++ src/Magnum/Texture.h | 50 +++++++ src/Magnum/TextureArray.cpp | 10 ++ src/Magnum/TextureArray.h | 42 ++++++ 19 files changed, 705 insertions(+), 3 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 82c3711fc..8275dd308 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -209,7 +209,7 @@ OpenGL function | Matching API @fn_gl{GetTexImage}, \n `glGetnTexImage()`, \n @fn_gl_extension{GetnTexImage,ARB,robustness}, \n `glGetTextureImage()`, \n @fn_gl_extension{GetTextureImage,EXT,direct_state_access} | @ref Texture::image(), \n @ref TextureArray::image(), \n @ref CubeMapTexture::image(), \n @ref CubeMapTextureArray::image(), \n @ref RectangleTexture::image() @fn_gl{GetTexLevelParameter}, \n `glGetTextureLevelParameter()`, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref TextureArray::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize(), \n @ref RectangleTexture::imageSize() @fn_gl{GetTexParameter}, \n `glGetTextureParameter()`, \n @fn_gl_extension{GetTextureParameter,EXT,direct_state_access} | | -@fn_gl{GetTextureSubImage} | @ref CubeMapTexture::image() +@fn_gl{GetTextureSubImage} | @ref Texture::subImage(), \n @ref TextureArray::subImage(), \n @ref CubeMapTexture::image(), \n @ref CubeMapTexture::subImage(), \n @ref CubeMapTextureArray::subImage(), \n @ref RectangleTexture::subImage() @fn_gl{GetTransformFeedback} | not queryable, @ref TransformFeedback::attachBuffer() and @ref TransformFeedback::attachBuffers() setters only @fn_gl{GetTransformFeedbackVarying} | not queryable, @ref AbstractShaderProgram::setTransformFeedbackOutputs() setter only @fn_gl{GetUniform}, \n `glGetnUniform()`, \n @fn_gl_extension{GetnUniform,ARB,robustness} | not queryable, @ref AbstractShaderProgram::setUniform() setter only diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 1bf2ead5c..550d0866d 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -224,7 +224,7 @@ GLSL 4.50 | done @extension{ARB,cull_distance} | | @extension{ARB,derivative_control} | done (shading language only) @extension{ARB,direct_state_access} | done for implemented functionality (except VAOs) -@extension{ARB,get_texture_sub_image} | | +@extension{ARB,get_texture_sub_image} | missing compressed texture queries @extension{ARB,shader_texture_image_samples} | done (shading language only) @extension{ARB,texture_barrier} | | @extension{KHR,context_flush_control} (also in ES) | | diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index ec883f8c7..523d980b7 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -35,6 +35,7 @@ #include "Magnum/Extensions.h" #include "Magnum/Image.h" #include "Magnum/TextureFormat.h" +#include "Magnum/Math/Range.h" #ifdef MAGNUM_BUILD_DEPRECATED #include "Magnum/Shader.h" @@ -1255,6 +1256,42 @@ template void AbstractTexture::image(GLint level, Buffer template void MAGNUM_EXPORT AbstractTexture::image<1>(GLint, BufferImage<1>&, BufferUsage); template void MAGNUM_EXPORT AbstractTexture::image<2>(GLint, BufferImage<2>&, BufferUsage); template void MAGNUM_EXPORT AbstractTexture::image<3>(GLint, BufferImage<3>&, BufferUsage); + +template void AbstractTexture::subImage(const GLint level, const RangeTypeFor& range, Image& image) { + createIfNotAlready(); + + const Math::Vector size = range.size(); + const Vector3i paddedOffset = Vector3i::pad(range.min()); + const Vector3i paddedSize = Vector3i::pad(size, 1); + const std::size_t dataSize = image.dataSize(size); + char* data = new char[dataSize]; + + Buffer::unbindInternal(Buffer::TargetHint::PixelPack); + glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, data); + image.setData(image.format(), image.type(), size, data); +} + +template void MAGNUM_EXPORT AbstractTexture::subImage<1>(GLint, const Range1Di&, Image<1>&); +template void MAGNUM_EXPORT AbstractTexture::subImage<2>(GLint, const Range2Di&, Image<2>&); +template void MAGNUM_EXPORT AbstractTexture::subImage<3>(GLint, const Range3Di&, Image<3>&); + +template void AbstractTexture::subImage(const GLint level, const RangeTypeFor& range, BufferImage& image, const BufferUsage usage) { + createIfNotAlready(); + + const Math::Vector size = range.size(); + const std::size_t dataSize = image.dataSize(size); + const Vector3i paddedOffset = Vector3i::pad(range.min()); + const Vector3i paddedSize = Vector3i::pad(size, 1); + if(image.size() != size) + image.setData(image.format(), image.type(), size, nullptr, usage); + + image.buffer().bindInternal(Buffer::TargetHint::PixelPack); + glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, nullptr); +} + +template void MAGNUM_EXPORT AbstractTexture::subImage<1>(GLint, const Range1Di&, BufferImage<1>&, BufferUsage); +template void MAGNUM_EXPORT AbstractTexture::subImage<2>(GLint, const Range2Di&, BufferImage<2>&, BufferUsage); +template void MAGNUM_EXPORT AbstractTexture::subImage<3>(GLint, const Range3Di&, BufferImage<3>&, BufferUsage); #endif #endif diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index fd70081c2..0c95f6229 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -31,8 +31,9 @@ #include -#include "Magnum/Sampler.h" #include "Magnum/AbstractObject.h" +#include "Magnum/DimensionTraits.h" +#include "Magnum/Sampler.h" namespace Magnum { @@ -369,6 +370,8 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { #ifndef MAGNUM_TARGET_GLES template void image(GLint level, Image& image); template void image(GLint level, BufferImage& image, BufferUsage usage); + template void subImage(GLint level, const RangeTypeFor& range, Image& image); + template void subImage(GLint level, const RangeTypeFor& range, BufferImage& image, BufferUsage usage); #endif GLenum _target; diff --git a/src/Magnum/CubeMapTexture.cpp b/src/Magnum/CubeMapTexture.cpp index 18f9dd216..ba3f119e3 100644 --- a/src/Magnum/CubeMapTexture.cpp +++ b/src/Magnum/CubeMapTexture.cpp @@ -114,6 +114,16 @@ BufferImage2D CubeMapTexture::image(const Coordinate coordinate, const Int level return std::move(image); } +Image3D CubeMapTexture::subImage(const Int level, const Range3Di& range, Image3D&& image) { + this->subImage(level, range, image); + return std::move(image); +} + +BufferImage3D CubeMapTexture::subImage(const Int level, const Range3Di& range, BufferImage3D&& image, const BufferUsage usage) { + this->subImage(level, range, image, usage); + return std::move(image); +} + CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, const ImageReference3D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); glTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), GLenum(image.type()), image.data()); diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 7fb2bf56c..8d2ac0cb7 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -472,6 +472,48 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { * @endcode */ BufferImage2D image(Coordinate coordinate, Int level, BufferImage2D&& image, BufferUsage usage); + + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, Image&) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl Texture image queries are not available in OpenGL ES. + */ + void subImage(Int level, const Range3Di& range, Image3D& image) { + AbstractTexture::subImage<3>(level, range, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * Image3D image = texture.subImage(0, range, {ColorFormat::RGBA, ColorType::UnsignedByte}); + * @endcode + */ + Image3D subImage(Int level, const Range3Di& range, Image3D&& image); + + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl Texture image queries are not available in OpenGL ES. + */ + void subImage(Int level, const Range3Di& range, BufferImage3D& image, BufferUsage usage) { + AbstractTexture::subImage<3>(level, range, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * BufferImage3D image = texture.subImage(0, range, {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + * @endcode + */ + BufferImage3D subImage(Int level, const Range3Di& range, BufferImage3D&& image, BufferUsage usage); #endif /** diff --git a/src/Magnum/CubeMapTextureArray.cpp b/src/Magnum/CubeMapTextureArray.cpp index 567974fe0..22b5024cb 100644 --- a/src/Magnum/CubeMapTextureArray.cpp +++ b/src/Magnum/CubeMapTextureArray.cpp @@ -53,5 +53,15 @@ BufferImage3D CubeMapTextureArray::image(const Int level, BufferImage3D&& image, return std::move(image); } +Image3D CubeMapTextureArray::subImage(const Int level, const Range3Di& range, Image3D&& image) { + this->subImage(level, range, image); + return std::move(image); +} + +BufferImage3D CubeMapTextureArray::subImage(const Int level, const Range3Di& range, BufferImage3D&& image, const BufferUsage usage) { + this->subImage(level, range, image, usage); + return std::move(image); +} + } #endif diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 065203b5e..ac06c8d23 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -356,6 +356,46 @@ class MAGNUM_EXPORT CubeMapTextureArray: public AbstractTexture { */ BufferImage3D image(Int level, BufferImage3D&& image, BufferUsage usage); + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, Image&) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + */ + void subImage(Int level, const Range3Di& range, Image3D& image) { + AbstractTexture::subImage<3>(level, range, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * Image3D image = texture.subImage(0, range, {ColorFormat::RGBA, ColorType::UnsignedByte}); + * @endcode + */ + Image3D subImage(Int level, const Range3Di& range, Image3D&& image); + + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + */ + void subImage(Int level, const Range3Di& range, BufferImage3D& image, BufferUsage usage) { + AbstractTexture::subImage<3>(level, range, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * BufferImage3D image = texture.subImage(0, range, {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + * @endcode + */ + BufferImage3D subImage(Int level, const Range3Di& range, BufferImage3D&& image, BufferUsage usage); + /** * @copybrief Texture::setImage() * @return Reference to self (for method chaining) diff --git a/src/Magnum/RectangleTexture.cpp b/src/Magnum/RectangleTexture.cpp index 2f2d99fd1..deda0f798 100644 --- a/src/Magnum/RectangleTexture.cpp +++ b/src/Magnum/RectangleTexture.cpp @@ -58,5 +58,15 @@ BufferImage2D RectangleTexture::image(BufferImage2D&& image, const BufferUsage u return std::move(image); } +Image2D RectangleTexture::subImage(const Range2Di& range, Image2D&& image) { + this->subImage(range, image); + return std::move(image); +} + +BufferImage2D RectangleTexture::subImage(const Range2Di& range, BufferImage2D&& image, const BufferUsage usage) { + this->subImage(range, image, usage); + return std::move(image); +} + } #endif diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index a93ba6b4a..193e86e36 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -288,6 +288,46 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { */ BufferImage2D image(BufferImage2D&& image, BufferUsage usage); + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, Image&) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + */ + void subImage(const Range2Di& range, Image2D& image) { + AbstractTexture::subImage<2>(0, range, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * Image2D image = texture.subImage(range, {ColorFormat::RGBA, ColorType::UnsignedByte}); + * @endcode + */ + Image2D subImage(const Range2Di& range, Image2D&& image); + + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + */ + void subImage(const Range2Di& range, BufferImage2D& image, BufferUsage usage) { + AbstractTexture::subImage<2>(0, range, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * BufferImage2D image = texture.subImage(range, {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + * @endcode + */ + BufferImage2D subImage(const Range2Di& range, BufferImage2D&& image, BufferUsage usage); + /** * @copybrief Texture::setImage() * @return Reference to self (for method chaining) diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 4db779ecb..e598d072d 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -31,6 +31,7 @@ #include "Magnum/CubeMapTextureArray.h" #include "Magnum/Image.h" #include "Magnum/TextureFormat.h" +#include "Magnum/Math/Range.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { @@ -53,6 +54,8 @@ struct CubeMapTextureArrayGLTest: AbstractOpenGLTester { void imageBuffer(); void subImage(); void subImageBuffer(); + void subImageQuery(); + void subImageQueryBuffer(); void generateMipmap(); @@ -76,6 +79,8 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { &CubeMapTextureArrayGLTest::imageBuffer, &CubeMapTextureArrayGLTest::subImage, &CubeMapTextureArrayGLTest::subImageBuffer, + &CubeMapTextureArrayGLTest::subImageQuery, + &CubeMapTextureArrayGLTest::subImageQueryBuffer, &CubeMapTextureArrayGLTest::generateMipmap, @@ -365,6 +370,49 @@ void CubeMapTextureArrayGLTest::subImageBuffer() { CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{SubDataComplete}, TestSuite::Compare::Container); } +void CubeMapTextureArrayGLTest::subImageQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + CubeMapTextureArray texture; + texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, {4, 4, 6}, SubDataComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image3D image = texture.subImage(0, Range3Di::fromSize(Vector3i{1}, {2, 2, 4}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2, 2, 4)); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), + Containers::ArrayReference{SubData}, TestSuite::Compare::Container); +} + +void CubeMapTextureArrayGLTest::subImageQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + CubeMapTextureArray texture; + texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, {4, 4, 6}, SubDataComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage3D image = texture.subImage(0, Range3Di::fromSize(Vector3i{1}, {2, 2, 4}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2, 2, 4)); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{SubData}, TestSuite::Compare::Container); +} + void CubeMapTextureArrayGLTest::generateMipmap() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index 976316219..740960a0a 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -34,6 +34,7 @@ #include "Magnum/CubeMapTexture.h" #include "Magnum/Image.h" #include "Magnum/TextureFormat.h" +#include "Magnum/Math/Range.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { @@ -74,6 +75,10 @@ struct CubeMapTextureGLTest: AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES2 void subImageBuffer(); #endif + #ifndef MAGNUM_TARGET_GLES + void subImageQuery(); + void subImageQueryBuffer(); + #endif void generateMipmap(); @@ -110,6 +115,10 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { #ifndef MAGNUM_TARGET_GLES2 &CubeMapTextureGLTest::imageBuffer, #endif + #ifndef MAGNUM_TARGET_GLES + &CubeMapTextureGLTest::subImageQuery, + &CubeMapTextureGLTest::subImageQueryBuffer, + #endif &CubeMapTextureGLTest::subImage, #ifndef MAGNUM_TARGET_GLES2 @@ -460,6 +469,53 @@ void CubeMapTextureGLTest::subImageBuffer() { } #endif +#ifndef MAGNUM_TARGET_GLES +void CubeMapTextureGLTest::subImageQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + /* I'm too lazy to call setSubImage() six times */ + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::direct_state_access::string() + std::string(" is not supported.")); + + CubeMapTexture texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, {4, 4, 1}, SubDataComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image3D image = texture.subImage(0, Range3Di::fromSize({1, 1, 0}, {2, 2, 1}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2, 2, 1)); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), + Containers::ArrayReference{Data}, TestSuite::Compare::Container); +} + +void CubeMapTextureGLTest::subImageQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + /* I'm too lazy to call setSubImage() six times */ + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::direct_state_access::string() + std::string(" is not supported.")); + + CubeMapTexture texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, {4, 4, 1}, SubDataComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage3D image = texture.subImage(0, Range3Di::fromSize({1, 1, 0}, {2, 2, 1}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2, 2, 1)); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data}, TestSuite::Compare::Container); +} +#endif + void CubeMapTextureGLTest::generateMipmap() { CubeMapTexture texture; texture.setImage(CubeMapTexture::Coordinate::PositiveX, 0, TextureFormat::RGBA8, diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index e636fce4b..4c8bc74b9 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -32,6 +32,7 @@ #include "Magnum/Image.h" #include "Magnum/RectangleTexture.h" #include "Magnum/TextureFormat.h" +#include "Magnum/Math/Range.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { @@ -54,6 +55,8 @@ struct RectangleTextureGLTest: AbstractOpenGLTester { void imageBuffer(); void subImage(); void subImageBuffer(); + void subImageQuery(); + void subImageQueryBuffer(); void invalidateImage(); void invalidateSubImage(); @@ -76,6 +79,8 @@ RectangleTextureGLTest::RectangleTextureGLTest() { &RectangleTextureGLTest::subImage, &RectangleTextureGLTest::subImageBuffer, + &RectangleTextureGLTest::subImageQuery, + &RectangleTextureGLTest::subImageQueryBuffer, &RectangleTextureGLTest::invalidateImage, &RectangleTextureGLTest::invalidateSubImage}); @@ -299,6 +304,49 @@ void RectangleTextureGLTest::subImageBuffer() { CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{SubDataComplete}, TestSuite::Compare::Container); } +void RectangleTextureGLTest::subImageQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, Vector2i{4}) + .setSubImage({}, ImageReference2D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i{4}, SubDataComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image = texture.subImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), + Containers::ArrayReference{Data}, TestSuite::Compare::Container); +} + +void RectangleTextureGLTest::subImageQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setStorage(TextureFormat::RGBA8, Vector2i{4}) + .setSubImage({}, ImageReference2D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i{4}, SubDataComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image = texture.subImage(Range2Di::fromSize(Vector2i{1}, Vector2i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data}, TestSuite::Compare::Container); +} + void RectangleTextureGLTest::invalidateImage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index b1cc7566c..0edc55ed9 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -32,6 +32,7 @@ #include "Magnum/Image.h" #include "Magnum/TextureArray.h" #include "Magnum/TextureFormat.h" +#include "Magnum/Math/Range.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { @@ -98,9 +99,15 @@ struct TextureArrayGLTest: AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void subImage1D(); void subImage1DBuffer(); + void subImage1DQuery(); + void subImage1DQueryBuffer(); #endif void subImage2D(); void subImage2DBuffer(); + #ifndef MAGNUM_TARGET_GLES + void subImage2DQuery(); + void subImage2DQueryBuffer(); + #endif #ifndef MAGNUM_TARGET_GLES void generateMipmap1D(); @@ -173,9 +180,15 @@ TextureArrayGLTest::TextureArrayGLTest() { #ifndef MAGNUM_TARGET_GLES &TextureArrayGLTest::subImage1D, &TextureArrayGLTest::subImage1DBuffer, + &TextureArrayGLTest::subImage1DQuery, + &TextureArrayGLTest::subImage1DQueryBuffer, #endif &TextureArrayGLTest::subImage2D, &TextureArrayGLTest::subImage2DBuffer, + #ifndef MAGNUM_TARGET_GLES + &TextureArrayGLTest::subImage2DQuery, + &TextureArrayGLTest::subImage2DQueryBuffer, + #endif #ifndef MAGNUM_TARGET_GLES &TextureArrayGLTest::generateMipmap1D, @@ -699,6 +712,48 @@ void TextureArrayGLTest::subImage1DBuffer() { CORRADE_COMPARE(image.size(), Vector2i(4)); CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{SubData1DComplete}, TestSuite::Compare::Container); } + +void TextureArrayGLTest::subImage1DQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageReference2D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i{4}, SubData1DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image = texture.subImage(0, Range2Di::fromSize(Vector2i{1}, Vector2i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), Containers::ArrayReference{Data1D}, TestSuite::Compare::Container); +} + +void TextureArrayGLTest::subImage1DQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageReference2D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i{4}, SubData1DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image = texture.subImage(0, Range2Di::fromSize(Vector2i{1}, Vector2i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data1D}, TestSuite::Compare::Container); +} #endif namespace { @@ -787,6 +842,48 @@ void TextureArrayGLTest::subImage2DBuffer() { } #ifndef MAGNUM_TARGET_GLES +void TextureArrayGLTest::subImage2DQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture2DArray texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i{4}, SubData2DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image3D image = texture.subImage(0, Range3Di::fromSize(Vector3i{1}, Vector3i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i{2}); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), Containers::ArrayReference{Data2D}, TestSuite::Compare::Container); +} + +void TextureArrayGLTest::subImage2DQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture2DArray texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i{4}, SubData2DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage3D image = texture.subImage(0, Range3Di::fromSize(Vector3i{1}, Vector3i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i{2}); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data2D}, TestSuite::Compare::Container); +} + void TextureArrayGLTest::generateMipmap1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 1a603f8d1..de129e4de 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -34,6 +34,7 @@ #include "Magnum/Image.h" #include "Magnum/Texture.h" #include "Magnum/TextureFormat.h" +#include "Magnum/Math/Range.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { @@ -115,15 +116,25 @@ struct TextureGLTest: AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void subImage1D(); void subImage1DBuffer(); + void subImage1DQuery(); + void subImage1DQueryBuffer(); #endif void subImage2D(); #ifndef MAGNUM_TARGET_GLES2 void subImage2DBuffer(); #endif + #ifndef MAGNUM_TARGET_GLES + void subImage2DQuery(); + void subImage2DQueryBuffer(); + #endif void subImage3D(); #ifndef MAGNUM_TARGET_GLES2 void subImage3DBuffer(); #endif + #ifndef MAGNUM_TARGET_GLES + void subImage3DQuery(); + void subImage3DQueryBuffer(); + #endif #ifndef MAGNUM_TARGET_GLES void generateMipmap1D(); @@ -218,15 +229,25 @@ TextureGLTest::TextureGLTest() { #ifndef MAGNUM_TARGET_GLES &TextureGLTest::subImage1D, &TextureGLTest::subImage1DBuffer, + &TextureGLTest::subImage1DQuery, + &TextureGLTest::subImage1DQueryBuffer, #endif &TextureGLTest::subImage2D, #ifndef MAGNUM_TARGET_GLES2 &TextureGLTest::subImage2DBuffer, #endif + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::subImage2DQuery, + &TextureGLTest::subImage2DQueryBuffer, + #endif &TextureGLTest::subImage3D, #ifndef MAGNUM_TARGET_GLES2 &TextureGLTest::subImage3DBuffer, #endif + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::subImage3DQuery, + &TextureGLTest::subImage3DQueryBuffer, + #endif #ifndef MAGNUM_TARGET_GLES &TextureGLTest::generateMipmap1D, @@ -903,6 +924,44 @@ void TextureGLTest::subImage1DBuffer() { CORRADE_COMPARE(image.size(), 4); CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{SubData1DComplete}, TestSuite::Compare::Container); } + +void TextureGLTest::subImage1DQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture1D texture; + texture.setStorage(1, TextureFormat::RGBA8, 4) + .setSubImage(0, {}, ImageReference1D{ColorFormat::RGBA, ColorType::UnsignedByte, 4, SubData1DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image1D image = texture.subImage(0, Range1Di::fromSize(1, 2), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), 2); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), Containers::ArrayReference{Data1D}, TestSuite::Compare::Container); +} + +void TextureGLTest::subImage1DQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture1D texture; + texture.setStorage(1, TextureFormat::RGBA8, 4) + .setSubImage(0, {}, ImageReference1D{ColorFormat::RGBA, ColorType::UnsignedByte, 4, SubData1DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage1D image = texture.subImage(0, Range1Di::fromSize(1, 2), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), 2); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data1D}, TestSuite::Compare::Container); +} #endif namespace { @@ -960,6 +1019,46 @@ void TextureGLTest::subImage2DBuffer() { } #endif +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::subImage2DQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture2D texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageReference2D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i{4}, SubData2DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image2D image = texture.subImage(0, Range2Di::fromSize(Vector2i{1}, Vector2i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), Containers::ArrayReference{Data2D}, TestSuite::Compare::Container); +} + +void TextureGLTest::subImage2DQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture2D texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) + .setSubImage(0, {}, ImageReference2D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i{4}, SubData2DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage2D image = texture.subImage(0, Range2Di::fromSize(Vector2i{1}, Vector2i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data2D}, TestSuite::Compare::Container); +} +#endif + namespace { constexpr UnsignedByte Zero3D[4*4*4*4] = {}; constexpr UnsignedByte SubData3DComplete[] = { @@ -1036,6 +1135,44 @@ void TextureGLTest::subImage3DBuffer() { #endif #ifndef MAGNUM_TARGET_GLES +void TextureGLTest::subImage3DQuery() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture3D texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i{4}, SubData3DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + Image3D image = texture.subImage(0, Range3Di::fromSize(Vector3i{1}, Vector3i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i{2}); + CORRADE_COMPARE_AS( + Containers::ArrayReference(image.data(), image.pixelSize()*image.size().product()), Containers::ArrayReference{Data3D}, TestSuite::Compare::Container); +} + +void TextureGLTest::subImage3DQueryBuffer() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + + Texture3D texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) + .setSubImage(0, {}, ImageReference3D{ColorFormat::RGBA, ColorType::UnsignedByte, Vector3i{4}, SubData3DComplete}); + + MAGNUM_VERIFY_NO_ERROR(); + + BufferImage3D image = texture.subImage(0, Range3Di::fromSize(Vector3i{1}, Vector3i{2}), {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + const auto imageData = image.buffer().data(); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i{2}); + CORRADE_COMPARE_AS(imageData, Containers::ArrayReference{Data3D}, TestSuite::Compare::Container); +} + void TextureGLTest::generateMipmap1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Texture.cpp b/src/Magnum/Texture.cpp index bfed3d91c..76a305cd8 100644 --- a/src/Magnum/Texture.cpp +++ b/src/Magnum/Texture.cpp @@ -82,6 +82,28 @@ template MAGNUM_EXPORT BufferImage<1> Texture<1>::image(Int, BufferImage<1>&&, B template MAGNUM_EXPORT BufferImage<2> Texture<2>::image(Int, BufferImage<2>&&, BufferUsage); template MAGNUM_EXPORT BufferImage<3> Texture<3>::image(Int, BufferImage<3>&&, BufferUsage); #endif + +template Image Texture::subImage(const Int level, const RangeTypeFor& range, Image&& image) { + this->subImage(level, range, image); + return std::move(image); +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +template MAGNUM_EXPORT Image<1> Texture<1>::subImage(Int, const Range1Di&, Image<1>&&); +template MAGNUM_EXPORT Image<2> Texture<2>::subImage(Int, const Range2Di&, Image<2>&&); +template MAGNUM_EXPORT Image<3> Texture<3>::subImage(Int, const Range3Di&, Image<3>&&); +#endif + +template BufferImage Texture::subImage(const Int level, const RangeTypeFor& range, BufferImage&& image, const BufferUsage usage) { + this->subImage(level, range, image, usage); + return std::move(image); +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +template MAGNUM_EXPORT BufferImage<1> Texture<1>::subImage(Int, const Range1Di&, BufferImage<1>&&, BufferUsage); +template MAGNUM_EXPORT BufferImage<2> Texture<2>::subImage(Int, const Range2Di&, BufferImage<2>&&, BufferUsage); +template MAGNUM_EXPORT BufferImage<3> Texture<3>::subImage(Int, const Range3Di&, BufferImage<3>&&, BufferUsage); +#endif #endif } diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 7f60bc445..031f4d6e2 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -686,6 +686,56 @@ template class Texture: public AbstractTexture { * @endcode */ BufferImage image(Int level, BufferImage&& image, BufferUsage usage); + + /** + * @brief Read range of given texture mip level to image + * @param level Mip level + * @param range Range to read + * @param image Image where to put the data + * + * Image parameters like format and type of pixel data are taken from + * given image. + * @see @fn_gl{GetTextureSubImage} + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl Texture image queries are not available in OpenGL ES. + */ + void subImage(Int level, const RangeTypeFor& range, Image& image) { + AbstractTexture::subImage(level, range, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * Image2D image = texture.subImage(0, rect, {ColorFormat::RGBA, ColorType::UnsignedByte}); + * @endcode + */ + Image subImage(Int level, const RangeTypeFor& range, Image&& image); + + /** + * @brief Read range of given texture mip level to buffer image + * @param level Mip level + * @param range Range to read + * @param image Buffer image where to put the data + * @param usage Buffer usage + * + * See @ref subImage(Int, const RangeTypeFor&, Image&) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl Texture image queries are not available in OpenGL ES. + */ + void subImage(Int level, const RangeTypeFor& range, BufferImage& image, BufferUsage usage) { + AbstractTexture::subImage(level, range, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * BufferImage2D image = texture.subImage(0, rect, {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + * @endcode + */ + BufferImage subImage(Int level, const RangeTypeFor& range, BufferImage&& image, BufferUsage usage); #endif /** diff --git a/src/Magnum/TextureArray.cpp b/src/Magnum/TextureArray.cpp index ef9e14ed9..6da5d90ac 100644 --- a/src/Magnum/TextureArray.cpp +++ b/src/Magnum/TextureArray.cpp @@ -64,6 +64,16 @@ template BufferImage TextureArrayimage(level, image, usage); return std::move(image); } + +template Image TextureArray::subImage(const Int level, const RangeTypeFor& range, Image&& image) { + this->subImage(level, range, image); + return std::move(image); +} + +template BufferImage TextureArray::subImage(const Int level, const RangeTypeFor& range, BufferImage&& image, const BufferUsage usage) { + this->subImage(level, range, image, usage); + return std::move(image); +} #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 5fdc075f6..ea4c4e307 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -386,6 +386,48 @@ template class TextureArray: public AbstractTexture { * @endcode */ BufferImage image(Int level, BufferImage&& image, BufferUsage usage); + + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, Image&) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, Image&) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl Texture image queries are not available in OpenGL ES. + */ + void subImage(Int level, const RangeTypeFor& range, Image& image) { + AbstractTexture::subImage(level, range, image); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * Image3D image = texture.subImage(0, range, {ColorFormat::RGBA, ColorType::UnsignedByte}); + * @endcode + */ + Image subImage(Int level, const RangeTypeFor& range, Image&& image); + + /** + * @copybrief Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * + * See @ref Texture::subImage(Int, const RangeTypeFor&, BufferImage&, BufferUsage) + * for more information. + * @requires_gl45 Extension @extension{ARB,get_texture_sub_image} + * @requires_gl Texture image queries are not available in OpenGL ES. + */ + void subImage(Int level, const RangeTypeFor& range, BufferImage& image, BufferUsage usage) { + AbstractTexture::subImage(level, range, image, usage); + } + + /** @overload + * + * Convenience alternative to the above, example usage: + * @code + * BufferImage3D image = texture.subImage(0, range, {ColorFormat::RGBA, ColorType::UnsignedByte}, BufferUsage::StaticRead); + * @endcode + */ + BufferImage subImage(Int level, const RangeTypeFor& range, BufferImage&& image, BufferUsage usage); #endif /**