From 537177ca26e3386675fc31898a7c68adb48c61f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 16 Feb 2019 22:32:53 +0100 Subject: [PATCH] DebugTools: added screenshot(). --- doc/changelog.dox | 5 + src/Magnum/DebugTools/CMakeLists.txt | 2 + src/Magnum/DebugTools/Screenshot.cpp | 82 ++++++ src/Magnum/DebugTools/Screenshot.h | 101 +++++++ src/Magnum/DebugTools/Test/CMakeLists.txt | 32 ++ .../DebugTools/Test/ScreenshotGLTest.cpp | 274 ++++++++++++++++++ src/Magnum/DebugTools/Test/configure.h.cmake | 3 + .../GL/Implementation/pixelFormatMapping.hpp | 4 +- 8 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 src/Magnum/DebugTools/Screenshot.cpp create mode 100644 src/Magnum/DebugTools/Screenshot.h create mode 100644 src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp diff --git a/doc/changelog.dox b/doc/changelog.dox index 28aecf506..8071a3ee8 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -40,6 +40,11 @@ See also: @subsection changelog-latest-new New features +@subsubsection changelog-latest-new-debugtools DebugTools library + +- New @ref DebugTools::screenshot() function for convenient saving of + screenshots + @subsubsection changelog-latest-new-gl GL library - New @ref GL::AbstractFramebuffer::implementationColorReadFormat() and diff --git a/src/Magnum/DebugTools/CMakeLists.txt b/src/Magnum/DebugTools/CMakeLists.txt index dbfa1e0f5..81af34e80 100644 --- a/src/Magnum/DebugTools/CMakeLists.txt +++ b/src/Magnum/DebugTools/CMakeLists.txt @@ -38,10 +38,12 @@ set(MagnumDebugTools_PRIVATE_HEADERS ) if(TARGET_GL) list(APPEND MagnumDebugTools_SRCS ResourceManager.cpp + Screenshot.cpp TextureImage.cpp) list(APPEND MagnumDebugTools_HEADERS ResourceManager.h + Screenshot.h TextureImage.h visibility.h) diff --git a/src/Magnum/DebugTools/Screenshot.cpp b/src/Magnum/DebugTools/Screenshot.cpp new file mode 100644 index 000000000..4d868094f --- /dev/null +++ b/src/Magnum/DebugTools/Screenshot.cpp @@ -0,0 +1,82 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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 "Screenshot.h" + +#include +#include + +#include "Magnum/PixelFormat.h" +#include "Magnum/Image.h" +#include "Magnum/GL/AbstractFramebuffer.h" +#include "Magnum/GL/PixelFormat.h" +#include "Magnum/Trade/AbstractImageConverter.h" + +namespace Magnum { namespace DebugTools { + +bool screenshot(GL::AbstractFramebuffer& framebuffer, const std::string& filename) { + PluginManager::Manager manager; + return screenshot(manager, framebuffer, filename); +} + +bool screenshot(PluginManager::Manager& manager, GL::AbstractFramebuffer& framebuffer, const std::string& filename) { + /* Get the implementation-specific color read format for given framebuffer */ + const GL::PixelFormat format = framebuffer.implementationColorReadFormat(); + const GL::PixelType type = framebuffer.implementationColorReadType(); + Containers::Optional genericFormat; + #ifndef DOXYGEN_GENERATING_OUTPUT /* It gets *really* confused */ + #define _c(generic, glFormat, glType) if(format == GL::PixelFormat::glFormat && type == GL::PixelType::glType) genericFormat = PixelFormat::generic; + #define _s(generic) + #include "Magnum/GL/Implementation/pixelFormatMapping.hpp" + #undef _c + #undef _s + #endif + if(!genericFormat) { + Error{} << "DebugTools::screenshot(): can't map (" << Debug::nospace << format << Debug::nospace << "," << type << Debug::nospace << ") to a generic pixel format"; + return false; + } + + return screenshot(manager, framebuffer, *genericFormat, filename); +} + +bool screenshot(GL::AbstractFramebuffer& framebuffer, const PixelFormat format, const std::string& filename) { + PluginManager::Manager manager; + return screenshot(manager, framebuffer, format, filename); +} + +bool screenshot(PluginManager::Manager& manager, GL::AbstractFramebuffer& framebuffer, const PixelFormat format, const std::string& filename) { + Containers::Pointer converter; + if(!(converter = manager.loadAndInstantiate("AnyImageConverter"))) + return false; + + Image2D image = framebuffer.read(framebuffer.viewport(), {format}); + if(!converter->exportToFile(image, filename)) + return false; + + Debug{} << "DebugTools::screenshot(): saved a" << format << "image of size" << image.size() << "to" << filename; + return true; +} + +}} diff --git a/src/Magnum/DebugTools/Screenshot.h b/src/Magnum/DebugTools/Screenshot.h new file mode 100644 index 000000000..238153c3f --- /dev/null +++ b/src/Magnum/DebugTools/Screenshot.h @@ -0,0 +1,101 @@ +#ifndef Magnum_DebugTools_Screenshot_h +#define Magnum_DebugTools_Screenshot_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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::screenshot() + */ + +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/DebugTools/visibility.h" +#include "Magnum/GL/GL.h" +#include "Magnum/Trade/Trade.h" + +namespace Magnum { namespace DebugTools { + +/** +@brief Save a screenshot to a file +@param framebuffer Framebuffer which to read +@param filename File where to save + +Reads a rectangle of given @p framebuffer, defined by its +@ref GL::AbstractFramebuffer::viewport() "viewport()". Pixel format is queried +using @ref GL::AbstractFramebuffer::implementationColorReadFormat() and +@ref GL::AbstractFramebuffer::implementationColorReadType() and then mapped +back to the generic @ref Magnum::PixelFormat "PixelFormat". If, for some +reason, the driver-suggested pixel format is not desired, use the +@ref screenshot(GL::AbstractFramebuffer&, PixelFormat, const std::string&) +overload instead. + +The read pixel data are saved using the +@ref Trade::AnyImageConverter "AnyImageConverter" plugin, with format being +detected from @p filename. Note that every file format supports a different set +of pixel formats, it's the user responsibility to choose a file format that +matches the framebuffer pixel format. + +Returns @cpp true @ce on success, @cpp false @ce in case it was not possible to +map the detected pixel format back to a generic format, if either the +@ref Trade::AnyImageConverter "AnyImageConverter" or the corresponding plugin +for given file format could not be loaded, or if the file saving fails (for +example due to unsupported pixel format). A message is printed in each case. +*/ +bool MAGNUM_DEBUGTOOLS_EXPORT screenshot(GL::AbstractFramebuffer& framebuffer, const std::string& filename); + +/** @overload + +Useful in case you already have an instance of the converter plugin manager in +your application or if you intend to save screenshots often, as the operation +doesn't involve costly dynamic library loading and unloading on every call. +*/ +bool MAGNUM_DEBUGTOOLS_EXPORT screenshot(PluginManager::Manager& manager, GL::AbstractFramebuffer& framebuffer, const std::string& filename); + +/** +@brief Save a screenshot in requested pixel format to a file +@param framebuffer Framebuffer which to read +@param format Pixel format to use +@param filename File where to save + +Similar to @ref screenshot(GL::AbstractFramebuffer&, PixelFormat, const std::string&) +but with an explicit pixel format. Useful in cases where the driver-suggested +pixel format is not desired, however note that supplying a format that's +incompatible with the framebuffer may result in GL errors. +*/ +bool MAGNUM_DEBUGTOOLS_EXPORT screenshot(GL::AbstractFramebuffer& framebuffer, PixelFormat format, const std::string& filename); + +/** @overload + +Useful in case you already have an instance of the converter plugin manager in +your application or if you intend to save screenshots often, as the operation +doesn't involve costly dynamic library loading and unloading on every call. +*/ +bool MAGNUM_DEBUGTOOLS_EXPORT screenshot(PluginManager::Manager& manager, GL::AbstractFramebuffer& framebuffer, PixelFormat format, const std::string& filename); + +}} + +#endif diff --git a/src/Magnum/DebugTools/Test/CMakeLists.txt b/src/Magnum/DebugTools/Test/CMakeLists.txt index 5b6eb9a6b..7847ed2be 100644 --- a/src/Magnum/DebugTools/Test/CMakeLists.txt +++ b/src/Magnum/DebugTools/Test/CMakeLists.txt @@ -29,8 +29,10 @@ if(WITH_TRADE) if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) set(DEBUGTOOLS_TEST_DIR ".") + set(SCREENSHOT_TEST_DIR "write") else() set(DEBUGTOOLS_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + set(SCREENSHOT_TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/write) endif() # CMake before 3.8 has broken $ expressions for iOS (see @@ -42,9 +44,15 @@ if(WITH_TRADE) if(WITH_ANYIMAGEIMPORTER) set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $) endif() + if(WITH_ANYIMAGECONVERTER) + set(ANYIMAGECONVERTER_PLUGIN_FILENAME $) + endif() if(WITH_TGAIMPORTER) set(TGAIMPORTER_PLUGIN_FILENAME $) endif() + if(WITH_TGAIMAGECONVERTER) + set(TGAIMAGECONVERTER_PLUGIN_FILENAME $) + endif() # First replace ${} variables, then $<> generator expressions configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake @@ -103,5 +111,29 @@ if(TARGET_GL) set_target_properties(DebugToolsBufferDataGLTest PROPERTIES FOLDER "Magnum/DebugTools/Test") endif() + + if(WITH_TRADE) + corrade_add_test(DebugToolsScreenshotGLTest ScreenshotGLTest.cpp LIBRARIES MagnumDebugTools MagnumOpenGLTester) + set_target_properties(DebugToolsScreenshotGLTest PROPERTIES FOLDER "Magnum/DebugTools/Test") + # The configure.h file is provided for DebugToolsCompareImageTest + # already + if(NOT BUILD_PLUGINS_STATIC) + target_include_directories(DebugToolsScreenshotGLTest PRIVATE $) + else() + target_include_directories(DebugToolsScreenshotGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + if(WITH_ANYIMAGECONVERTER) + target_link_libraries(DebugToolsScreenshotGLTest PRIVATE AnyImageConverter) + endif() + if(WITH_ANYIMAGEIMPORTER) + target_link_libraries(DebugToolsScreenshotGLTest PRIVATE AnyImageImporter) + endif() + if(WITH_TGAIMAGECONVERTER) + target_link_libraries(DebugToolsScreenshotGLTest PRIVATE TgaImageConverter) + endif() + if(WITH_TGAIMPORTER) + target_link_libraries(DebugToolsScreenshotGLTest PRIVATE TgaImporter) + endif() + endif() + endif() endif() endif() diff --git a/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp b/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp new file mode 100644 index 000000000..8ecc7c0d6 --- /dev/null +++ b/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp @@ -0,0 +1,274 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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 +#include +#include +#include + +#include "Magnum/ImageView.h" +#include "Magnum/PixelFormat.h" +#include "Magnum/DebugTools/Screenshot.h" +#include "Magnum/DebugTools/CompareImage.h" +#include "Magnum/GL/Framebuffer.h" +#include "Magnum/GL/OpenGLTester.h" +#include "Magnum/GL/PixelFormat.h" +#include "Magnum/GL/Texture.h" +#include "Magnum/GL/TextureFormat.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Trade/AbstractImageConverter.h" +#include "Magnum/Trade/AbstractImporter.h" + +#ifndef MAGNUM_TARGET_WEBGL +#include "Magnum/GL/DebugOutput.h" +#endif + +#include "configure.h" + +namespace Magnum { namespace DebugTools { namespace Test { namespace { + +struct ScreenshotGLTest: GL::OpenGLTester { + explicit ScreenshotGLTest(); + + void rgba8(); + #if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) + void r8(); + #endif + void unknownFormat(); + void pluginLoadFailed(); + void saveFailed(); + + private: + PluginManager::Manager _converterManager{"nonexistent"}; + PluginManager::Manager _importerManager{"nonexistent"}; +}; + +ScreenshotGLTest::ScreenshotGLTest() { + addTests({&ScreenshotGLTest::rgba8, + #if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) + &ScreenshotGLTest::r8, + #endif + &ScreenshotGLTest::unknownFormat, + &ScreenshotGLTest::pluginLoadFailed, + &ScreenshotGLTest::saveFailed}); + + /* Load the plugins directly from the build tree. Otherwise they're either + static and already loaded or not present in the build tree */ + #ifdef ANYIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_INTERNAL_ASSERT(_converterManager.load(ANYIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + #ifdef TGAIMAGECONVERTER_PLUGIN_FILENAME + CORRADE_INTERNAL_ASSERT(_converterManager.load(TGAIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + #ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME + CORRADE_INTERNAL_ASSERT(_importerManager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + #ifdef TGAIMPORTER_PLUGIN_FILENAME + CORRADE_INTERNAL_ASSERT(_importerManager.load(TGAIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif +} + +using namespace Math::Literals; + +constexpr Color4ub DataRgba8[]{ + 0x11223344_rgba, 0x22334455_rgba, 0x33445566_rgba, 0x44556677_rgba, + 0x55667788_rgba, 0x66778899_rgba, 0x778899aa_rgba, 0x8899aabb_rgba, + 0x99aabbcc_rgba, 0xaabbccdd_rgba, 0xbbccddee_rgba, 0xccddeeff_rgba +}; + +void ScreenshotGLTest::rgba8() { + ImageView2D rgba{PixelFormat::RGBA8Unorm, {4, 3}, DataRgba8}; + + GL::Texture2D texture; + texture.setStorage(1, + #if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) + GL::TextureFormat::RGBA8, + #else + GL::TextureFormat::RGBA, + #endif + {4, 3}) + .setSubImage(0, {}, rgba); + GL::Framebuffer framebuffer{{{}, {4, 3}}}; + framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, texture, 0); + + std::string file = Utility::Directory::join(SCREENSHOT_TEST_DIR, "image.tga"); + if(Utility::Directory::exists(file)) + CORRADE_VERIFY(Utility::Directory::rm(file)); + else + CORRADE_VERIFY(Utility::Directory::mkpath(SCREENSHOT_TEST_DIR)); + + std::ostringstream out; + bool succeeded; + { + #ifndef MAGNUM_TARGET_WEBGL + /* Disable messages from the GL driver so we can verify our message */ + GL::DebugOutput::setCallback(nullptr, nullptr); + Containers::ScopeGuard e{GL::DebugOutput::setDefaultCallback}; + #endif + + Debug redirectOutput{&out}; + succeeded = DebugTools::screenshot(_converterManager, framebuffer, file); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(succeeded); + CORRADE_COMPARE(out.str(), + Utility::formatString("DebugTools::screenshot(): saved a PixelFormat::RGBA8Unorm image of size Vector(4, 3) to {}\n", file)); + CORRADE_COMPARE_WITH(file, rgba, CompareFileToImage{_importerManager}); +} + +#if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) +constexpr unsigned char DataR8[]{ + 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc +}; + +void ScreenshotGLTest::r8() { + ImageView2D r{PixelFormat::R8Unorm, {4, 3}, DataR8}; + + GL::Texture2D texture; + texture.setStorage(1, + #ifndef MAGNUM_TARGET_GLES2 + GL::TextureFormat::R8, + #else + GL::TextureFormat::Luminance, + #endif + {4, 3}) + .setSubImage(0, {}, r); + GL::Framebuffer framebuffer{{{}, {4, 3}}}; + framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, texture, 0); + + std::string file = Utility::Directory::join(SCREENSHOT_TEST_DIR, "image.tga"); + if(Utility::Directory::exists(file)) + CORRADE_VERIFY(Utility::Directory::rm(file)); + else + CORRADE_VERIFY(Utility::Directory::mkpath(SCREENSHOT_TEST_DIR)); + + std::ostringstream out; + bool succeeded; + { + #ifndef MAGNUM_TARGET_WEBGL + /* Disable messages from the GL driver so we can verify our message */ + GL::DebugOutput::setCallback(nullptr, nullptr); + Containers::ScopeGuard e{GL::DebugOutput::setDefaultCallback}; + #endif + + Debug redirectOutput{&out}; + succeeded = DebugTools::screenshot(_converterManager, framebuffer, file); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(succeeded); + CORRADE_COMPARE(out.str(), + Utility::formatString("DebugTools::screenshot(): saved a PixelFormat::R8Unorm image of size Vector(4, 3) to {}\n", file)); + CORRADE_COMPARE_WITH(file, r, CompareFileToImage{_importerManager}); +} +#endif + +void ScreenshotGLTest::unknownFormat() { + ImageView2D rgba{GL::PixelFormat::RGB, GL::PixelType::UnsignedShort565, {4, 3}, DataRgba8}; + + GL::Texture2D texture; + texture.setStorage(1, GL::TextureFormat::RGB565, {4, 3}) + .setSubImage(0, {}, rgba); + GL::Framebuffer framebuffer{{{}, {4, 3}}}; + framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, texture, 0); + + std::ostringstream out; + bool succeeded; + { + Error redirectOutput{&out}; + succeeded = DebugTools::screenshot(_converterManager, framebuffer, Utility::Directory::join(SCREENSHOT_TEST_DIR, "image.tga")); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(!succeeded); + CORRADE_COMPARE(out.str(), "DebugTools::screenshot(): can't map (GL::PixelFormat::RGB, GL::PixelType::UnsignedShort565) to a generic pixel format\n"); +} + +void ScreenshotGLTest::pluginLoadFailed() { + ImageView2D rgba{PixelFormat::RGBA8Unorm, {4, 3}, DataRgba8}; + + GL::Texture2D texture; + texture.setStorage(1, + #if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) + GL::TextureFormat::RGBA8, + #else + GL::TextureFormat::RGBA, + #endif + {4, 3}) + .setSubImage(0, {}, rgba); + GL::Framebuffer framebuffer{{{}, {4, 3}}}; + framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, texture, 0); + + std::ostringstream out; + bool succeeded; + { + Error redirectOutput{&out}; + PluginManager::Manager manager{"nowhere"}; + succeeded = DebugTools::screenshot(manager, framebuffer, Utility::Directory::join(SCREENSHOT_TEST_DIR, "image.poo")); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(!succeeded); + #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT + CORRADE_COMPARE(out.str(), "PluginManager::Manager::load(): plugin AnyImageConverter is not static and was not found in nowhere\n"); + #else + CORRADE_COMPARE(out.str(), "PluginManager::Manager::load(): plugin AnyImageConverter was not found\n"); + #endif +} + +void ScreenshotGLTest::saveFailed() { + ImageView2D rgba{PixelFormat::RGBA8Unorm, {4, 3}, DataRgba8}; + + GL::Texture2D texture; + texture.setStorage(1, + #if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL) + GL::TextureFormat::RGBA8, + #else + GL::TextureFormat::RGBA, + #endif + {4, 3}) + .setSubImage(0, {}, rgba); + GL::Framebuffer framebuffer{{{}, {4, 3}}}; + framebuffer.attachTexture(GL::Framebuffer::ColorAttachment{0}, texture, 0); + + std::ostringstream out; + bool succeeded; + { + Error redirectOutput{&out}; + succeeded = DebugTools::screenshot(_converterManager, framebuffer, "image.poo"); + } + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_VERIFY(!succeeded); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::exportToFile(): cannot determine type of file image.poo\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::DebugTools::Test::ScreenshotGLTest) diff --git a/src/Magnum/DebugTools/Test/configure.h.cmake b/src/Magnum/DebugTools/Test/configure.h.cmake index 116362cf1..780fe5f37 100644 --- a/src/Magnum/DebugTools/Test/configure.h.cmake +++ b/src/Magnum/DebugTools/Test/configure.h.cmake @@ -24,5 +24,8 @@ */ #cmakedefine ANYIMAGEIMPORTER_PLUGIN_FILENAME "${ANYIMAGEIMPORTER_PLUGIN_FILENAME}" +#cmakedefine ANYIMAGECONVERTER_PLUGIN_FILENAME "${ANYIMAGECONVERTER_PLUGIN_FILENAME}" +#cmakedefine TGAIMAGECONVERTER_PLUGIN_FILENAME "${TGAIMAGECONVERTER_PLUGIN_FILENAME}" #cmakedefine TGAIMPORTER_PLUGIN_FILENAME "${TGAIMPORTER_PLUGIN_FILENAME}" #define DEBUGTOOLS_TEST_DIR "${DEBUGTOOLS_TEST_DIR}" +#define SCREENSHOT_TEST_DIR "${SCREENSHOT_TEST_DIR}" diff --git a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp index 0d09553d2..39bc93ce3 100644 --- a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp +++ b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp @@ -23,7 +23,9 @@ DEALINGS IN THE SOFTWARE. */ -/* See Magnum/GL/PixelFormat.cpp and Magnum/GL/Test/PixelFormatTest.cpp */ +/* See Magnum/GL/PixelFormat.cpp, Magnum/GL/Test/PixelFormatTest.cpp and + DebugTools/Screenshot.cpp. _c() is a mapping, _s() denotes a skipped value + (so the enum numbering is preserved) */ #ifdef _c #ifndef MAGNUM_TARGET_GLES2 _c(R8Unorm, Red, UnsignedByte)