From c983068fcc505d59e4dc595fa86baafbf44399ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 20 Jul 2018 18:56:18 +0200 Subject: [PATCH] TextureTools: initial test for distanceField(). Fully passes only on desktop and ES3 (Mesa), expecting minor differences onother GPUs. ES2 is slightly broken and needs fixing; doesn't even compile on WebGL 1 and causes a serious GPU stall on WebGL 2 -- in both causes caused by the unbounded nested loops. Rendering doesn't work on WebGL 1 at the moment, since luminance formats are not renderable. And for a RGBA output format I would need some utility to get rid of the extra channels in order to pass the comparison. Lots of work to do here. --- src/Magnum/TextureTools/Test/CMakeLists.txt | 52 ++++++ .../TextureTools/Test/DistanceFieldGLTest.cpp | 159 ++++++++++++++++++ .../Test/DistanceFieldGLTestFiles/input.tga | Bin 0 -> 65554 bytes .../Test/DistanceFieldGLTestFiles/output.tga | Bin 0 -> 4114 bytes .../TextureTools/Test/configure.h.cmake | 28 +++ 5 files changed, 239 insertions(+) create mode 100644 src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp create mode 100644 src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/input.tga create mode 100644 src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/output.tga create mode 100644 src/Magnum/TextureTools/Test/configure.h.cmake diff --git a/src/Magnum/TextureTools/Test/CMakeLists.txt b/src/Magnum/TextureTools/Test/CMakeLists.txt index dffd1b322..3aabdefb3 100644 --- a/src/Magnum/TextureTools/Test/CMakeLists.txt +++ b/src/Magnum/TextureTools/Test/CMakeLists.txt @@ -25,3 +25,55 @@ corrade_add_test(TextureToolsAtlasTest AtlasTest.cpp LIBRARIES MagnumTextureTools) set_target_properties(TextureToolsAtlasTest PROPERTIES FOLDER "Magnum/TextureTools/Test") + +if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) + set(DISTANCEFIELDGLTEST_FILES_DIR "DistanceFieldGLTestFiles") +else() + set(DISTANCEFIELDGLTEST_FILES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/DistanceFieldGLTestFiles) +endif() + +if(BUILD_GL_TESTS) + # Otherwise CMake complains that Corrade::PluginManager is not found, wtf + find_package(Corrade REQUIRED PluginManager) + + # CMake before 3.8 has broken $ expressions for iOS (see + # https://gitlab.kitware.com/cmake/cmake/merge_requests/404) and since + # Corrade doesn't support dynamic plugins on iOS, this sorta works around + # that. Should be revisited when updating Travis to newer Xcode (current + # has CMake 3.6). + if(NOT BUILD_PLUGINS_STATIC) + if(WITH_ANYIMAGEIMPORTER) + set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $) + endif() + if(WITH_TGAIMPORTER) + set(TGAIMPORTER_PLUGIN_FILENAME $) + endif() + + # First replace ${} variables, then $<> generator expressions + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) + file(GENERATE OUTPUT $/configure.h + INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) + else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + endif() + + corrade_add_test(TextureToolsDistanceFieldGLTest DistanceFieldGLTest.cpp + LIBRARIES MagnumTextureTools MagnumGL MagnumTrade MagnumDebugTools MagnumOpenGLTester + FILES + DistanceFieldGLTestFiles/input.tga + DistanceFieldGLTestFiles/output.tga) + set_target_properties(TextureToolsDistanceFieldGLTest PROPERTIES FOLDER "Magnum/TextureTools/Test") + if(NOT BUILD_PLUGINS_STATIC) + target_include_directories(TextureToolsDistanceFieldGLTest PRIVATE $) + else() + target_include_directories(TextureToolsDistanceFieldGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + if(WITH_ANYIMAGEIMPORTER) + target_link_libraries(TextureToolsDistanceFieldGLTest PRIVATE AnyImageImporter) + endif() + if(WITH_TGAIMPORTER) + target_link_libraries(TextureToolsDistanceFieldGLTest PRIVATE TgaImporter) + endif() + endif() +endif() diff --git a/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp b/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp new file mode 100644 index 000000000..e1d2439ea --- /dev/null +++ b/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp @@ -0,0 +1,159 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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 "Magnum/Image.h" +#include "Magnum/PixelFormat.h" +#include "Magnum/Math/Range.h" +#include "Magnum/DebugTools/CompareImage.h" +#include "Magnum/DebugTools/TextureImage.h" +#include "Magnum/GL/Context.h" +#include "Magnum/GL/Extensions.h" +#include "Magnum/GL/OpenGLTester.h" +#include "Magnum/GL/PixelFormat.h" +#include "Magnum/GL/Texture.h" +#include "Magnum/GL/TextureFormat.h" +#include "Magnum/TextureTools/DistanceField.h" +#include "Magnum/Trade/AbstractImporter.h" +#include "Magnum/Trade/ImageData.h" + +#include "configure.h" + +namespace Magnum { namespace TextureTools { namespace Test { + +struct DistanceFieldGLTest: GL::OpenGLTester { + explicit DistanceFieldGLTest(); + + void test(); + + private: + PluginManager::Manager _manager; +}; + +DistanceFieldGLTest::DistanceFieldGLTest() { + addTests({&DistanceFieldGLTest::test}); + + /* Load the plugin directly from the build tree. Otherwise it's either + static and already loaded or not present in the build tree */ + #if defined(ANYIMAGEIMPORTER_PLUGIN_FILENAME) && defined(TGAIMPORTER_PLUGIN_FILENAME) + CORRADE_INTERNAL_ASSERT(_manager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + CORRADE_INTERNAL_ASSERT(_manager.load(TGAIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif +} + +void DistanceFieldGLTest::test() { + std::unique_ptr importer; + if(!(importer = _manager.loadAndInstantiate("TgaImporter"))) + CORRADE_SKIP("TgaImporter plugin not found."); + + CORRADE_VERIFY(importer->openFile(Utility::Directory::join(DISTANCEFIELDGLTEST_FILES_DIR, "input.tga"))); + CORRADE_COMPARE(importer->image2DCount(), 1); + Containers::Optional inputImage = importer->image2D(0); + CORRADE_VERIFY(inputImage); + CORRADE_COMPARE(inputImage->format(), PixelFormat::R8Unorm); + + #ifndef MAGNUM_TARGET_GLES2 + const GL::TextureFormat inputFormat = GL::TextureFormat::R8; + #elif !defined(MAGNUM_TARGET_WEBGL) + GL::TextureFormat inputFormat; + if(GL::Context::current().isExtensionSupported()) + inputFormat = GL::TextureFormat::R8; + else + inputFormat = GL::TextureFormat::Luminance; /** @todo Luminance8 */ + #else + const GL::TextureFormat inputFormat = GL::TextureFormat::Luminance; + #endif + + GL::Texture2D input; + input.setMinificationFilter(GL::SamplerFilter::Nearest, GL::SamplerMipmap::Base) + .setMagnificationFilter(GL::SamplerFilter::Nearest) + .setStorage(1, inputFormat, inputImage->size()); + + #if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_TARGET_WEBGL) + input.setSubImage(0, {}, *inputImage); + #else + if(GL::Context::current().isExtensionSupported()) + input.setSubImage(0, {}, ImageView2D{inputImage->storage(), GL::PixelFormat::Red, GL::PixelType::UnsignedByte, inputImage->size(), inputImage->data()}); + else + input.setSubImage(0, {}, *inputImage); + #endif + + #ifndef MAGNUM_TARGET_GLES2 + const GL::TextureFormat outputFormat = GL::TextureFormat::R8; + #elif !defined(MAGNUM_TARGET_WEBGL) + GL::TextureFormat outputFormat; + if(GL::Context::current().isExtensionSupported()) + outputFormat = GL::TextureFormat::R8; + else + outputFormat = GL::TextureFormat::Luminance; /** @todo Luminance8 */ + #else + const GL::TextureFormat outputFormat = GL::TextureFormat::Luminance; + #endif + + /** @todo luminance is usually not renderable, but with RGBA i would need + some TextureTools::swizzle() to get rid of the extra channels for an + image compare ... so at the moment, the test just blows up on WebGL 1 */ + + GL::Texture2D output; + output.setMinificationFilter(GL::SamplerFilter::Nearest, GL::SamplerMipmap::Base) + .setMagnificationFilter(GL::SamplerFilter::Nearest) + .setStorage(1, outputFormat, Vector2i{64}); + + TextureTools::distanceField(input, output, {{}, Vector2i{64}}, 32 + #ifdef MAGNUM_TARGET_GLES + , inputImage->size() + #endif + ); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Containers::Optional actualOutputImage; + #if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_TARGET_WEBGL) + actualOutputImage = Image2D{PixelFormat::R8Unorm}; + #else + if(GL::Context::current().isExtensionSupported()) + actualOutputImage = Image2D{GL::PixelFormat::Red, GL::PixelType::UnsignedByte}; + else + actualOutputImage = Image2D{PixelFormat::R8Unorm}; + #endif + + DebugTools::textureSubImage(output, 0, {{}, Vector2i{64}}, *actualOutputImage); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + if(_manager.loadState("AnyImageImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("AnyImageImporter plugin not found."); + + /* In some cases actualOutputImage might have GL-specific format, + reinterpret as R8Unorm for the comparison to work */ + CORRADE_COMPARE_WITH((ImageView2D{actualOutputImage->storage(), PixelFormat::R8Unorm, actualOutputImage->size(), actualOutputImage->data()}), Utility::Directory::join(DISTANCEFIELDGLTEST_FILES_DIR, "output.tga"), + DebugTools::CompareImageToFile{_manager}); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::TextureTools::Test::DistanceFieldGLTest) diff --git a/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/input.tga b/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/input.tga new file mode 100644 index 0000000000000000000000000000000000000000..5ccb2afc106b97250a59c5867981e5b292c5a0f5 GIT binary patch literal 65554 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 literal 0 HcmV?d00001 diff --git a/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/output.tga b/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/output.tga new file mode 100644 index 0000000000000000000000000000000000000000..278ec6a320b32770d42009f0934995a90c13835a GIT binary patch literal 4114 zcmeH~|4-9+7{})+g5LsR;+GgiAjlbv5dy|2!p0#YFkv9`790$0WP@fb`;s+Fe`}UC zc1u~R+eld_+tN8EbxsCM1&<(S;^lJTxBGMM)53E{j9I2PoK~8rIX1H z%W_i46ta@s$^YN7qT&*%Dn9ZpOvgL@>55@v+&c&iptu{^-@(=eL;TwTLUN0 z)igA=+>ol~>sKyS9NRZgQc-j5rlPY;syf?R8mh{R@&-yP8*cuh8XA_W!Cqx^{rM9) zzUXvqqe7*ffTT*V>1n-IRd#64K=IkjEuBLXGd8J$M+cORHS%07l$@=<(KQU&+!BSE z$JHH8wenmRP!w|$zTnG5l4V~dxzxLr_v@d;`1QB3pcg|d@U#Jj&2}gDjG~!9 zU~Zm?#NvxwN`(KMiPI!zpN2*sYjvX&ldu(a&r-OX@RF22NHdXWVgEN$5z6J59@7k{ z9%v_k3x*ko%Y)j5hk529spm|=_^l;qFKQmw+*kH#p&18?IxMgQvrigfv&F_6!2<>P zWj5e;7)Ml!u7~3$r`zLkgIJhh{fJKg?b8Aar!K5EhcBu7cl%(lU;rQ?IZ9+XgkEXMWG~omW+XRDDWbw5mzFpu0?8*uo zz!8JC=k`4fC{SQfB!70FfAH>o5I#5H-^KiH8>G2+yGLt4aIhf4^XX%s)IR8b^wb9U zcl>@>o;2YEKMYwhieZ!a{m`3Gl3Ds7!hhrzC>$|CI*s1s z#C?Hz+OxkO)WVw$5q>L^2+g{j7EnOYj1$AXzGonOy{)ICK8x|7{}6~7Bg5SK)+ZrZKsUIX z58oFtKEwAP7-Slk{q*}f7bb;bSM-D8=fn3^j0frAvhkfGnoO^*CWP$kS9GXB_;{cG z6yv$D4>KDOm)9SPy;_XCa69(04^%@W{o7w+{Ob_tKak0R;iP|#_IpuKd|mB*yVbnB zwIjxZc7vFV(3AxMvx~qnyYX>p-)${ZV?!#nW^4-d z;stK~4^ci94N_iydV=IP7z~hZ1ay7~wqss8p4r+F<+B{SFdq<1IQasCjYimHMKEtL znp*$*w4eSaeOuy<+9s5;`iU&+}z0WCWPeokzRtIynztQWx-EC zh5JW3uhbGKpfEE})AP&%o6N5l7eIxbbZhuycXUM$VMKg&*CxYDBR8Bj}Ae|K9`-MRgL5J%;g8k$>` z9a5#Z)%0^^S;y?7srnKA_F4W@$NvBqIO*a5 literal 0 HcmV?d00001 diff --git a/src/Magnum/TextureTools/Test/configure.h.cmake b/src/Magnum/TextureTools/Test/configure.h.cmake new file mode 100644 index 000000000..bb4fbf1c2 --- /dev/null +++ b/src/Magnum/TextureTools/Test/configure.h.cmake @@ -0,0 +1,28 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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. +*/ + +#cmakedefine ANYIMAGEIMPORTER_PLUGIN_FILENAME "${ANYIMAGEIMPORTER_PLUGIN_FILENAME}" +#cmakedefine TGAIMPORTER_PLUGIN_FILENAME "${TGAIMPORTER_PLUGIN_FILENAME}" +#define DISTANCEFIELDGLTEST_FILES_DIR "${DISTANCEFIELDGLTEST_FILES_DIR}"