From 78d73fa98e4dc553d9aa2233f68cafcb632335de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 6 Apr 2016 16:32:49 +0200 Subject: [PATCH] DebugTools: utility to get texture image on OpenGL ES. --- src/Magnum/DebugTools/CMakeLists.txt | 4 +- src/Magnum/DebugTools/Test/CMakeLists.txt | 1 + .../DebugTools/Test/TextureImageGLTest.cpp | 147 ++++++++++++++++++ src/Magnum/DebugTools/TextureImage.cpp | 83 ++++++++++ src/Magnum/DebugTools/TextureImage.h | 95 +++++++++++ 5 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 src/Magnum/DebugTools/Test/TextureImageGLTest.cpp create mode 100644 src/Magnum/DebugTools/TextureImage.cpp create mode 100644 src/Magnum/DebugTools/TextureImage.h diff --git a/src/Magnum/DebugTools/CMakeLists.txt b/src/Magnum/DebugTools/CMakeLists.txt index 978e68a26..1eaf37f50 100644 --- a/src/Magnum/DebugTools/CMakeLists.txt +++ b/src/Magnum/DebugTools/CMakeLists.txt @@ -25,12 +25,14 @@ set(MagnumDebugTools_SRCS Profiler.cpp - ResourceManager.cpp) + ResourceManager.cpp + TextureImage.cpp) set(MagnumDebugTools_HEADERS DebugTools.h Profiler.h ResourceManager.h + TextureImage.h visibility.h) # Header files to display in project view of IDEs only diff --git a/src/Magnum/DebugTools/Test/CMakeLists.txt b/src/Magnum/DebugTools/Test/CMakeLists.txt index d1b2654a2..e46197d97 100644 --- a/src/Magnum/DebugTools/Test/CMakeLists.txt +++ b/src/Magnum/DebugTools/Test/CMakeLists.txt @@ -30,4 +30,5 @@ corrade_add_test(DebugToolsLineSegmentRendererTest LineSegmentRendererTest.cpp L if(BUILD_GL_TESTS) corrade_add_test(DebugToolsBufferDataGLTest BufferDataGLTest.cpp LIBRARIES MagnumDebugTools ${GL_TEST_LIBRARIES}) + corrade_add_test(DebugToolsTextureImageGLTest TextureImageGLTest.cpp LIBRARIES MagnumDebugTools ${GL_TEST_LIBRARIES}) endif() diff --git a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp new file mode 100644 index 000000000..a948ed968 --- /dev/null +++ b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp @@ -0,0 +1,147 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/BufferImage.h" +#include "Magnum/CubeMapTexture.h" +#include "Magnum/Image.h" +#include "Magnum/PixelFormat.h" +#include "Magnum/Texture.h" +#include "Magnum/TextureFormat.h" +#include "Magnum/DebugTools/BufferData.h" +#include "Magnum/DebugTools/TextureImage.h" +#include "Magnum/Math/Range.h" +#include "Magnum/Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace DebugTools { namespace Test { + +struct TextureImageGLTest: Magnum::Test::AbstractOpenGLTester { + explicit TextureImageGLTest(); + + void subImage2D(); + #ifndef MAGNUM_TARGET_GLES2 + void subImage2DBuffer(); + #endif + + void subImageCube(); + #ifndef MAGNUM_TARGET_GLES2 + void subImageCubeBuffer(); + #endif +}; + +TextureImageGLTest::TextureImageGLTest() { + addTests({&TextureImageGLTest::subImage2D, + #ifndef MAGNUM_TARGET_GLES2 + &TextureImageGLTest::subImage2DBuffer, + #endif + + &TextureImageGLTest::subImageCube, + #ifndef MAGNUM_TARGET_GLES2 + &TextureImageGLTest::subImageCubeBuffer + #endif + }); +} + +namespace { + constexpr UnsignedByte Data2D[] = { 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }; +} + +void TextureImageGLTest::subImage2D() { + Texture2D texture; + texture.setImage(0, TextureFormat::RGBA8, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, Data2D}); + + Image2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {PixelFormat::RGBA, PixelType::UnsignedByte}); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS( + (Containers::ArrayView{image.data(), image.data().size()}), + Containers::ArrayView{Data2D}, + TestSuite::Compare::Container); +} + +#ifndef MAGNUM_TARGET_GLES2 +void TextureImageGLTest::subImage2DBuffer() { + Texture2D texture; + texture.setImage(0, TextureFormat::RGBA8, ImageView2D{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, Data2D}); + + BufferImage2D image = textureSubImage(texture, 0, {{}, Vector2i{2}}, {PixelFormat::RGBA, PixelType::UnsignedByte}, BufferUsage::StaticRead); + Containers::Array data = bufferData(image.buffer()); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS(data, + Containers::ArrayView{Data2D}, + TestSuite::Compare::Container); +} +#endif + +void TextureImageGLTest::subImageCube() { + ImageView2D view{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, Data2D}; + + CubeMapTexture texture; + texture.setImage(CubeMapCoordinate::PositiveX, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::NegativeX, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::PositiveY, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::NegativeY, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::PositiveZ, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::NegativeZ, 0, TextureFormat::RGBA8, view); + + Image2D image = textureSubImage(texture, CubeMapCoordinate::PositiveX, 0, {{}, Vector2i{2}}, {PixelFormat::RGBA, PixelType::UnsignedByte}); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS( + (Containers::ArrayView{image.data(), image.data().size()}), + Containers::ArrayView{Data2D}, + TestSuite::Compare::Container); +} + +#ifndef MAGNUM_TARGET_GLES2 +void TextureImageGLTest::subImageCubeBuffer() { + ImageView2D view{PixelFormat::RGBA, PixelType::UnsignedByte, Vector2i{2}, Data2D}; + + CubeMapTexture texture; + texture.setImage(CubeMapCoordinate::PositiveX, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::NegativeX, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::PositiveY, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::NegativeY, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::PositiveZ, 0, TextureFormat::RGBA8, view) + .setImage(CubeMapCoordinate::NegativeZ, 0, TextureFormat::RGBA8, view); + + BufferImage2D image = textureSubImage(texture, CubeMapCoordinate::PositiveX, 0, {{}, Vector2i{2}}, {PixelFormat::RGBA, PixelType::UnsignedByte}, BufferUsage::StaticRead); + Containers::Array data = bufferData(image.buffer()); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(image.size(), Vector2i{2}); + CORRADE_COMPARE_AS(data, + Containers::ArrayView{Data2D}, + TestSuite::Compare::Container); +} +#endif + +}}} + +MAGNUM_GL_TEST_MAIN(Magnum::DebugTools::Test::TextureImageGLTest) diff --git a/src/Magnum/DebugTools/TextureImage.cpp b/src/Magnum/DebugTools/TextureImage.cpp new file mode 100644 index 000000000..22725bf2e --- /dev/null +++ b/src/Magnum/DebugTools/TextureImage.cpp @@ -0,0 +1,83 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "TextureImage.h" + +#include "Magnum/BufferImage.h" +#include "Magnum/Framebuffer.h" +#include "Magnum/Texture.h" +#include "Magnum/Image.h" + +namespace Magnum { namespace DebugTools { + +void textureSubImage(Texture2D& texture, const Int level, const Range2Di& range, Image2D& image) { + Framebuffer fb{range}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, texture, level) + .read(range, image); +} + +void textureSubImage(CubeMapTexture& texture, const CubeMapCoordinate coordinate, const Int level, const Range2Di& range, Image2D& image) { + Framebuffer fb{range}; + fb.attachCubeMapTexture(Framebuffer::ColorAttachment{0}, texture, coordinate, level) + .read(range, image); +} + +#ifndef MAGNUM_TARGET_GLES2 +void textureSubImage(Texture2D& texture, const Int level, const Range2Di& range, BufferImage2D& image, const BufferUsage usage) { + Framebuffer fb{range}; + fb.attachTexture(Framebuffer::ColorAttachment{0}, texture, level) + .read(range, image, usage); +} + +void textureSubImage(CubeMapTexture& texture, const CubeMapCoordinate coordinate, const Int level, const Range2Di& range, BufferImage2D& image, const BufferUsage usage) { + Framebuffer fb{range}; + fb.attachCubeMapTexture(Framebuffer::ColorAttachment{0}, texture, coordinate, level) + .read(range, image, usage); +} +#endif + +Image2D textureSubImage(Texture2D& texture, const Int level, const Range2Di& range, Image2D&& image) { + textureSubImage(texture, level, range, image); + return std::move(image); +} + +Image2D textureSubImage(CubeMapTexture& texture, const CubeMapCoordinate coordinate, const Int level, const Range2Di& range, Image2D&& image) { + textureSubImage(texture, coordinate, level, range, image); + return std::move(image); +} + +#ifndef MAGNUM_TARGET_GLES2 +BufferImage2D textureSubImage(Texture2D& texture, const Int level, const Range2Di& range, BufferImage2D&& image, const BufferUsage usage) { + textureSubImage(texture, level, range, image, usage); + return std::move(image); +} + +BufferImage2D textureSubImage(CubeMapTexture& texture, const CubeMapCoordinate coordinate, const Int level, const Range2Di& range, BufferImage2D&& image, const BufferUsage usage) { + textureSubImage(texture, coordinate, level, range, image, usage); + return std::move(image); +} +#endif + +}} diff --git a/src/Magnum/DebugTools/TextureImage.h b/src/Magnum/DebugTools/TextureImage.h new file mode 100644 index 000000000..c6d67fa01 --- /dev/null +++ b/src/Magnum/DebugTools/TextureImage.h @@ -0,0 +1,95 @@ +#ifndef Magnum_DebugTools_TextureImage_h +#define Magnum_DebugTools_TextureImage_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Function @ref Magnum::DebugTools::textureSubImage() + */ + +#include "Magnum/Magnum.h" +#include "Magnum/DebugTools/visibility.h" + +namespace Magnum { namespace DebugTools { + +/** +@brief Read range of given texture mip level to image + +Emulates @ref Texture::subImage() "*Texture::subImage()" call on platforms that +don't support it (such as OpenGL ES) by creating a framebuffer object and using +@ref Framebuffer::read(). Note that only @ref PixelFormat and @ref PixelType +values that are marked as framebuffer readable are supported. +*/ +MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(Texture2D& texture, Int level, const Range2Di& range, Image2D& image); + +/** @overload */ +MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(CubeMapTexture& texture, CubeMapCoordinate coordinate, Int level, const Range2Di& range, Image2D& image); + +/** +@brief Read range of given texture mip level to image + +Convenience alternative to the above, example usage: +@code +Image2D image = DebugTools::textureSubImage(texture, 0, rect, {PixelFormat::RGBA, PixelType::UnsignedByte}); +@endcode +*/ +MAGNUM_DEBUGTOOLS_EXPORT Image2D textureSubImage(Texture2D& texture, Int level, const Range2Di& range, Image2D&& image); + +/** @overload */ +MAGNUM_DEBUGTOOLS_EXPORT Image2D textureSubImage(CubeMapTexture& texture, CubeMapCoordinate coordinate, Int level, const Range2Di& range, Image2D&& image); + +#ifndef MAGNUM_TARGET_GLES2 +/** +@brief Read range of given texture mip level to buffer image + +Emulates @ref Texture::subImage() "*Texture::subImage()" call on platforms that +don't support it (such as OpenGL ES) by creating a framebuffer object and using +@ref Framebuffer::read(). Note that only @ref PixelFormat and @ref PixelType +values that are marked as framebuffer readable are supported. +@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. +*/ +MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(Texture2D& texture, Int level, const Range2Di& range, BufferImage2D& image, BufferUsage usage); + +/** @overload */ +MAGNUM_DEBUGTOOLS_EXPORT void textureSubImage(CubeMapTexture& texture, CubeMapCoordinate coordinate, Int level, const Range2Di& range, BufferImage2D& image, BufferUsage usage); + +/** +@brief Read range of given texture mip level to buffer image + +Convenience alternative to the above, example usage: +@code +BufferImage2D image = DebugTools::textureSubImage(texture, 0, rect, {PixelFormat::RGBA, PixelType::UnsignedByte}, BufferUsage::StaticRead); +@endcode +*/ +MAGNUM_DEBUGTOOLS_EXPORT BufferImage2D textureSubImage(Texture2D& texture, Int level, const Range2Di& range, BufferImage2D&& image, BufferUsage usage); + +/** @overload */ +MAGNUM_DEBUGTOOLS_EXPORT BufferImage2D textureSubImage(CubeMapTexture& texture, CubeMapCoordinate coordinate, Int level, const Range2Di& range, BufferImage2D&& image, BufferUsage usage); +#endif + +}} + +#endif