From d89b882ccf4d4af6c4a1f9e9c7ef63ddffaee85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 27 Feb 2021 10:55:18 +0100 Subject: [PATCH] GL: port Debug{Output,Group,Message} away from std::string. Most of these are just inputs, so a compatibility StringStl.h include will do, the only exception is the callback for which there needs to stay a deprecated overload (which is internally delegated from the StringView one). Also explicitly testing with non-null-terminated strings -- the APIs take an explicit size so it shouldn't be a problem, but it's always good to have this verified independently. Drivers are crap, you know. One consequence of no longer using an impossible-to-forward-declare std::string is that I had to deinline the DebugGroup constructor because it no longer worked with just a forward-declared StringView. --- doc/changelog.dox | 4 + src/Magnum/GL/CMakeLists.txt | 3 +- src/Magnum/GL/DebugOutput.cpp | 56 +++++++--- src/Magnum/GL/DebugOutput.h | 82 +++++++------- src/Magnum/GL/Implementation/DebugState.h | 8 +- .../GL/Implementation/defaultDebugCallback.h | 46 ++++++++ src/Magnum/GL/Test/DebugOutputGLTest.cpp | 104 ++++++++++++++++-- 7 files changed, 229 insertions(+), 74 deletions(-) create mode 100644 src/Magnum/GL/Implementation/defaultDebugCallback.h diff --git a/doc/changelog.dox b/doc/changelog.dox index 2402235a1..5a6a92c1c 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -863,6 +863,10 @@ See also: particular, if `BUILD_DEPRECATED` is set but `MAGNUM_BUILD_DEPRECATED` not, the unprefixed options are also recognized. See also [mosra/corrade#139](https://github.com/mosra/corrade/issues/139). +- @ref GL::DebugOutput::setCallback() taking a @ref std::string in the + callback function pointer is deprecated in favor of a version taking a + @ref Containers::StringView. See also [mosra/magnum#499](https://github.com/mosra/magnum/pull/499) + and [mosra/magnum#596](https://github.com/mosra/magnum/pull/596). - The @cpp Array @ce, @cpp Array1D @ce, @cpp Array2D @ce and @cpp Array3D @ce types that were used exclusively for specifying @ref SamplerWrapping in various texture APIs are deprecated in favor of diff --git a/src/Magnum/GL/CMakeLists.txt b/src/Magnum/GL/CMakeLists.txt index 55f82221b..85985d2a1 100644 --- a/src/Magnum/GL/CMakeLists.txt +++ b/src/Magnum/GL/CMakeLists.txt @@ -150,7 +150,8 @@ if(NOT MAGNUM_TARGET_WEBGL) list(APPEND MagnumGL_SRCS DebugOutput.cpp - Implementation/DebugState.cpp) + Implementation/DebugState.cpp + Implementation/defaultDebugCallback.h) list(APPEND MagnumGL_HEADERS DebugOutput.h) diff --git a/src/Magnum/GL/DebugOutput.cpp b/src/Magnum/GL/DebugOutput.cpp index a1df9bce2..65b2d65f4 100644 --- a/src/Magnum/GL/DebugOutput.cpp +++ b/src/Magnum/GL/DebugOutput.cpp @@ -26,20 +26,25 @@ #include "DebugOutput.h" #ifndef MAGNUM_TARGET_WEBGL +#include #include #include -#include #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/Implementation/State.h" #include "Magnum/GL/Implementation/DebugState.h" +#include "Magnum/GL/Implementation/defaultDebugCallback.h" + +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif namespace Magnum { namespace GL { namespace Implementation { -void defaultDebugCallback(const DebugOutput::Source source, const DebugOutput::Type type, const UnsignedInt id, const DebugOutput::Severity severity, const std::string& string, std::ostream* out) { +void defaultDebugCallback(const DebugOutput::Source source, const DebugOutput::Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::StringView string, std::ostream* out) { Debug output{out}; output << "Debug output:"; @@ -105,7 +110,7 @@ APIENTRY #endif callbackWrapper(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { const auto& callback = *static_cast(userParam); - callback.callback(DebugOutput::Source(source), DebugOutput::Type(type), id, DebugOutput::Severity(severity), std::string{message, std::size_t(length)}, callback.userParam); + callback.callback(DebugOutput::Source(source), DebugOutput::Type(type), id, DebugOutput::Severity(severity), {message, std::size_t(length)}, callback.userParam); } } @@ -149,8 +154,25 @@ void DebugOutput::setCallback(const Callback callback, const void* userParam) { Context::current().state().debug.callbackImplementation(callback); } +#ifdef MAGNUM_BUILD_DEPRECATED +void DebugOutput::setCallback(void(*const callback)(Source, Type, UnsignedInt, Severity, const std::string&, const void*), const void* userParam) { + /* This is a second delegation step after the callbackWrapper() which + converts from raw GL types. Alternatively there could be a deprecated + version of all callbackImplementation*() variants, but this is less + code in total -- just two extra members in the MessageCallback + struct. */ + Context::current().state().debug.messageCallback.userParam = &Context::current().state().debug.messageCallback; + Context::current().state().debug.messageCallback.callbackStlString = callback; + Context::current().state().debug.messageCallback.userParamStlString = userParam; + Context::current().state().debug.callbackImplementation([](DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, const Containers::StringView string, const void* userParam) { + const auto& messageCallback = *static_cast(userParam); + messageCallback.callbackStlString(source, type, id, severity, string, messageCallback.userParamStlString); + }); +} +#endif + void DebugOutput::setDefaultCallback() { - setCallback([](DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, const std::string& string, const void*) { + setCallback([](DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, const Containers::StringView string, const void*) { Implementation::defaultDebugCallback(source, type, id, severity, string, Debug::output()); }); } @@ -267,30 +289,30 @@ Debug& operator<<(Debug& debug, const DebugOutput::Severity value) { } #endif -void DebugMessage::insertInternal(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::ArrayView string) { +void DebugMessage::insert(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::StringView string) { Context::current().state().debug.messageInsertImplementation(source, type, id, severity, string); } -void DebugMessage::insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::ArrayView) {} +void DebugMessage::insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::StringView) {} #ifndef MAGNUM_TARGET_GLES2 -void DebugMessage::insertImplementationKhrDesktopES32(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::ArrayView string) { +void DebugMessage::insertImplementationKhrDesktopES32(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::StringView string) { glDebugMessageInsert(GLenum(source), GLenum(type), id, GLenum(severity), string.size(), string.data()); } #endif #ifdef MAGNUM_TARGET_GLES -void DebugMessage::insertImplementationKhrES(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::ArrayView string) { +void DebugMessage::insertImplementationKhrES(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::StringView string) { glDebugMessageInsertKHR(GLenum(source), GLenum(type), id, GLenum(severity), string.size(), string.data()); } #endif -void DebugMessage::insertImplementationExt(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::ArrayView string) { +void DebugMessage::insertImplementationExt(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::StringView string) { glInsertEventMarkerEXT(string.size(), string.data()); } #ifndef MAGNUM_TARGET_GLES -void DebugMessage::insertImplementationGremedy(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::ArrayView string) { +void DebugMessage::insertImplementationGremedy(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::StringView string) { glStringMarkerGREMEDY(string.size(), string.data()); } #endif @@ -347,7 +369,11 @@ Int DebugGroup::maxStackDepth() { return value; } -void DebugGroup::pushInternal(const Source source, const UnsignedInt id, const Containers::ArrayView message) { +DebugGroup::DebugGroup(const Source source, const UnsignedInt id, const Containers::StringView message): DebugGroup{} { + push(source, id, message); +} + +void DebugGroup::push(const Source source, const UnsignedInt id, const Containers::StringView message) { CORRADE_ASSERT(!_active, "GL::DebugGroup::push(): group is already active", ); Context::current().state().debug.pushGroupImplementation(source, id, message); _active = true; @@ -359,21 +385,21 @@ void DebugGroup::pop() { _active = false; } -void DebugGroup::pushImplementationNoOp(Source, UnsignedInt, Containers::ArrayView) {} +void DebugGroup::pushImplementationNoOp(Source, UnsignedInt, Containers::StringView) {} #ifndef MAGNUM_TARGET_GLES2 -void DebugGroup::pushImplementationKhrDesktopES32(const Source source, const UnsignedInt id, const Containers::ArrayView message) { +void DebugGroup::pushImplementationKhrDesktopES32(const Source source, const UnsignedInt id, const Containers::StringView message) { glPushDebugGroup(GLenum(source), id, message.size(), message.data()); } #endif #ifdef MAGNUM_TARGET_GLES -void DebugGroup::pushImplementationKhrES(const Source source, const UnsignedInt id, const Containers::ArrayView message) { +void DebugGroup::pushImplementationKhrES(const Source source, const UnsignedInt id, const Containers::StringView message) { glPushDebugGroupKHR(GLenum(source), id, message.size(), message.data()); } #endif -void DebugGroup::pushImplementationExt(Source, UnsignedInt, const Containers::ArrayView message) { +void DebugGroup::pushImplementationExt(Source, UnsignedInt, const Containers::StringView message) { glPushGroupMarkerEXT(message.size(), message.data()); } diff --git a/src/Magnum/GL/DebugOutput.h b/src/Magnum/GL/DebugOutput.h index f85d13dc1..df3649061 100644 --- a/src/Magnum/GL/DebugOutput.h +++ b/src/Magnum/GL/DebugOutput.h @@ -31,13 +31,20 @@ */ #endif -#include -#include +#include +#include #include "Magnum/Magnum.h" #include "Magnum/GL/OpenGL.h" #include "Magnum/GL/visibility.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For all stuff that took std::string before */ +#include +/* For the deprecated std::string callback */ +#include +#endif + #ifndef MAGNUM_TARGET_WEBGL namespace Magnum { namespace GL { @@ -287,7 +294,7 @@ class MAGNUM_GL_EXPORT DebugOutput { * * @see @ref setCallback() */ - typedef void(*Callback)(Source, Type, UnsignedInt, Severity, const std::string&, const void*); + typedef void(*Callback)(Source, Type, UnsignedInt, Severity, Containers::StringView, const void*); /** * @brief Max count of debug messages in log @@ -394,6 +401,22 @@ class MAGNUM_GL_EXPORT DebugOutput { */ static void setCallback(Callback callback, const void* userParam = nullptr); + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Set debug message callback + * @m_deprecated_since_latest Use a @ref Callback taking a + * @ref Containers::StringView instead. + */ + CORRADE_DEPRECATED("use a callback taking a Containers::StringView instead") static void setCallback(void(*callback)(Source, Type, UnsignedInt, Severity, const std::string&, const void*), const void* userParam = nullptr); + #ifndef DOXYGEN_GENERATING_OUTPUT + /* Because otherwise the call is ambiguous with nullptr due to the + deprecated overload */ + static void setCallback(std::nullptr_t, const void* userParam = nullptr) { + setCallback(static_cast(nullptr), userParam); + } + #endif + #endif + /** * @brief Set default debug message callback * @@ -587,30 +610,22 @@ class MAGNUM_GL_EXPORT DebugMessage { * @fn_gl_extension_keyword{InsertEventMarker,EXT,debug_marker} or * @fn_gl_extension_keyword{StringMarker,GREMEDY,string_marker} */ - static void insert(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, const std::string& string) { - insertInternal(source, type, id, severity, {string.data(), string.size()}); - } - - /** @overload */ - template static void insert(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, const char(&string)[size]) { - insertInternal(source, type, id, severity, {string, size - 1}); - } + static void insert(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::StringView string); /** @brief There's no point in having an instance of this class */ DebugMessage() = delete; private: - static void insertInternal(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::ArrayView string); - static MAGNUM_GL_LOCAL void insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, Containers::ArrayView); + static MAGNUM_GL_LOCAL void insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, Containers::StringView); #ifndef MAGNUM_TARGET_GLES2 - static MAGNUM_GL_LOCAL void insertImplementationKhrDesktopES32(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::ArrayView string); + static MAGNUM_GL_LOCAL void insertImplementationKhrDesktopES32(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::StringView string); #endif #ifdef MAGNUM_TARGET_GLES - static MAGNUM_GL_LOCAL void insertImplementationKhrES(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::ArrayView string); + static MAGNUM_GL_LOCAL void insertImplementationKhrES(Source source, Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::StringView string); #endif - static MAGNUM_GL_LOCAL void insertImplementationExt(Source, Type, UnsignedInt, DebugOutput::Severity, Containers::ArrayView string); + static MAGNUM_GL_LOCAL void insertImplementationExt(Source, Type, UnsignedInt, DebugOutput::Severity, Containers::StringView string); #ifndef MAGNUM_TARGET_GLES - static MAGNUM_GL_LOCAL void insertImplementationGremedy(Source, Type, UnsignedInt, DebugOutput::Severity, Containers::ArrayView string); + static MAGNUM_GL_LOCAL void insertImplementationGremedy(Source, Type, UnsignedInt, DebugOutput::Severity, Containers::StringView string); #endif }; @@ -734,14 +749,7 @@ class MAGNUM_GL_EXPORT DebugGroup { * Calls @ref push(). * @see @link ~DebugGroup() @endlink, @ref pop() */ - explicit DebugGroup(Source source, UnsignedInt id, const std::string& message): DebugGroup{} { - push(source, id, message); - } - - /** @overload */ - template explicit DebugGroup(Source source, UnsignedInt id, const char(&message)[size]): DebugGroup{} { - push(source, id, message); - } + explicit DebugGroup(Source source, UnsignedInt id, Containers::StringView message); /** * @brief Destructor @@ -768,14 +776,7 @@ class MAGNUM_GL_EXPORT DebugGroup { * @ref Renderer::Error::StackOverflow, @fn_gl_keyword{PushDebugGroup} * or @fn_gl_extension_keyword{PushGroupMarker,EXT,debug_marker} */ - void push(Source source, UnsignedInt id, const std::string& message) { - pushInternal(source, id, {message.data(), message.size()}); - } - - /** @overload */ - template void push(Source source, UnsignedInt id, const char(&message)[size]) { - pushInternal(source, id, {message, size - 1}); - } + void push(Source source, UnsignedInt id, Containers::StringView message); /** * @brief Pop debug group from the stack @@ -798,16 +799,14 @@ class MAGNUM_GL_EXPORT DebugGroup { void pop(); private: - void pushInternal(Source source, UnsignedInt id, Containers::ArrayView message); - - static MAGNUM_GL_LOCAL void pushImplementationNoOp(Source source, UnsignedInt id, Containers::ArrayView message); + static MAGNUM_GL_LOCAL void pushImplementationNoOp(Source source, UnsignedInt id, Containers::StringView message); #ifndef MAGNUM_TARGET_GLES2 - static MAGNUM_GL_LOCAL void pushImplementationKhrDesktopES32(Source source, UnsignedInt id, Containers::ArrayView message); + static MAGNUM_GL_LOCAL void pushImplementationKhrDesktopES32(Source source, UnsignedInt id, Containers::StringView message); #endif #ifdef MAGNUM_TARGET_GLES - static MAGNUM_GL_LOCAL void pushImplementationKhrES(Source source, UnsignedInt id, Containers::ArrayView message); + static MAGNUM_GL_LOCAL void pushImplementationKhrES(Source source, UnsignedInt id, Containers::StringView message); #endif - static MAGNUM_GL_LOCAL void pushImplementationExt(Source source, UnsignedInt id, Containers::ArrayView message); + static MAGNUM_GL_LOCAL void pushImplementationExt(Source source, UnsignedInt id, Containers::StringView message); static MAGNUM_GL_LOCAL void popImplementationNoOp(); #ifndef MAGNUM_TARGET_GLES2 @@ -824,11 +823,6 @@ class MAGNUM_GL_EXPORT DebugGroup { /** @debugoperatorclassenum{DebugGroup,DebugGroup::Source} */ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, DebugGroup::Source value); -/* Exposed for testing */ -namespace Implementation { - MAGNUM_GL_EXPORT void defaultDebugCallback(DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, const std::string& string, std::ostream* output); -} - }} #else #error this header is not available in WebGL build diff --git a/src/Magnum/GL/Implementation/DebugState.h b/src/Magnum/GL/Implementation/DebugState.h index 050ff3d9f..939c242af 100644 --- a/src/Magnum/GL/Implementation/DebugState.h +++ b/src/Magnum/GL/Implementation/DebugState.h @@ -40,16 +40,20 @@ struct DebugState { Containers::String(*getLabelImplementation)(GLenum, GLuint); void(*labelImplementation)(GLenum, GLuint, Containers::StringView); - void(*messageInsertImplementation)(DebugMessage::Source, DebugMessage::Type, UnsignedInt, DebugOutput::Severity, Containers::ArrayView); + void(*messageInsertImplementation)(DebugMessage::Source, DebugMessage::Type, UnsignedInt, DebugOutput::Severity, Containers::StringView); void(*controlImplementation)(GLenum, GLenum, GLenum, std::initializer_list, bool); void(*callbackImplementation)(DebugOutput::Callback); - void(*pushGroupImplementation)(DebugGroup::Source, UnsignedInt, Containers::ArrayView); + void(*pushGroupImplementation)(DebugGroup::Source, UnsignedInt, Containers::StringView); void(*popGroupImplementation)(); GLint maxLabelLength, maxLoggedMessages, maxMessageLength, maxStackDepth; struct MessageCallback { DebugOutput::Callback callback{}; const void* userParam{}; + #ifdef MAGNUM_BUILD_DEPRECATED + void(*callbackStlString)(DebugOutput::Source, DebugOutput::Type, UnsignedInt, DebugOutput::Severity, const std::string&, const void*); + const void* userParamStlString{}; + #endif } messageCallback; }; diff --git a/src/Magnum/GL/Implementation/defaultDebugCallback.h b/src/Magnum/GL/Implementation/defaultDebugCallback.h new file mode 100644 index 000000000..ad86a1b8a --- /dev/null +++ b/src/Magnum/GL/Implementation/defaultDebugCallback.h @@ -0,0 +1,46 @@ +#ifndef Magnum_GL_Implementation_defaultDebugCallback_h +#define Magnum_GL_Implementation_defaultDebugCallback_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 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 "Magnum/configure.h" + +#ifndef MAGNUM_TARGET_WEBGL +#include + +#include "Magnum/GL/DebugOutput.h" + +namespace Magnum { namespace GL { namespace Implementation { + +/* Exposed just for testing; not included in DebugOutput.h to avoid having to + include there */ +MAGNUM_GL_EXPORT void defaultDebugCallback(DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::StringView string, std::ostream* output); + +}}} +#else +#error this header is not available in WebGL build +#endif + +#endif diff --git a/src/Magnum/GL/Test/DebugOutputGLTest.cpp b/src/Magnum/GL/Test/DebugOutputGLTest.cpp index 7dafe803b..3a7342ad0 100644 --- a/src/Magnum/GL/Test/DebugOutputGLTest.cpp +++ b/src/Magnum/GL/Test/DebugOutputGLTest.cpp @@ -24,12 +24,15 @@ */ #include -#include +#include +#include +#include /** @todo remove once Debug is stream-free */ #include "Magnum/GL/Context.h" #include "Magnum/GL/DebugOutput.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/OpenGLTester.h" +#include "Magnum/GL/Implementation/defaultDebugCallback.h" namespace Magnum { namespace GL { namespace Test { namespace { @@ -37,6 +40,9 @@ struct DebugOutputGLTest: OpenGLTester { explicit DebugOutputGLTest(); void setCallbackDefault(); + #ifdef MAGNUM_BUILD_DEPRECATED + void setCallbackDeprecated(); + #endif void setup(); void teardown(); @@ -54,18 +60,56 @@ struct DebugOutputGLTest: OpenGLTester { std::ostringstream _out; }; +using namespace Containers::Literals; + +const struct { + const char* name; + Containers::StringView message; +} MessageData[]{ + {"", + "Hello from OpenGL command stream!"}, + {"non-null-terminated string", + "Hello from OpenGL command stream!!"_s.exceptSuffix(1)}, +}; + +const struct { + const char* name; + Containers::StringView automaticGroupName, manualGroupName; +} GroupData[]{ + {"", + "Automatic debug group", + "Manual debug group"}, + {"non-null-terminated string", + "Automatic debug group!"_s.exceptSuffix(1), + "Manual debug group!"_s.exceptSuffix(1)} +}; + DebugOutputGLTest::DebugOutputGLTest() { - addTests({&DebugOutputGLTest::setCallbackDefault}); + addTests({&DebugOutputGLTest::setCallbackDefault, + #ifdef MAGNUM_BUILD_DEPRECATED + &DebugOutputGLTest::setCallbackDeprecated, + #endif + }); addTests({&DebugOutputGLTest::setEnabled, - &DebugOutputGLTest::messageNoOp, - &DebugOutputGLTest::message, - &DebugOutputGLTest::messageFallback, + &DebugOutputGLTest::messageNoOp}, + &DebugOutputGLTest::setup, &DebugOutputGLTest::teardown); + + addInstancedTests({&DebugOutputGLTest::message}, + Containers::arraySize(MessageData), + &DebugOutputGLTest::setup, &DebugOutputGLTest::teardown); + + addTests({&DebugOutputGLTest::messageFallback, - &DebugOutputGLTest::groupNoOp, - &DebugOutputGLTest::group, - &DebugOutputGLTest::groupFallback}, + &DebugOutputGLTest::groupNoOp}, + &DebugOutputGLTest::setup, &DebugOutputGLTest::teardown); + + addInstancedTests({&DebugOutputGLTest::group}, + Containers::arraySize(GroupData), + &DebugOutputGLTest::setup, &DebugOutputGLTest::teardown); + + addTests({&DebugOutputGLTest::groupFallback}, &DebugOutputGLTest::setup, &DebugOutputGLTest::teardown); } @@ -78,6 +122,36 @@ void DebugOutputGLTest::setCallbackDefault() { MAGNUM_VERIFY_NO_GL_ERROR(); } +#ifdef MAGNUM_BUILD_DEPRECATED +void DebugOutputGLTest::setCallbackDeprecated() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); + + Renderer::enable(Renderer::Feature::DebugOutput); + Renderer::enable(Renderer::Feature::DebugOutputSynchronous); + + Containers::ScopeGuard guard{[]() { + Renderer::disable(Renderer::Feature::DebugOutput); + Renderer::disable(Renderer::Feature::DebugOutputSynchronous); + DebugOutput::setDefaultCallback(); + }}; + + std::ostringstream out; + CORRADE_IGNORE_DEPRECATED_PUSH + DebugOutput::setCallback([](DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, const std::string& string, const void* userPtr) { + Implementation::defaultDebugCallback(source, type, id, severity, string, static_cast(const_cast(userPtr))); + }, &out); + CORRADE_IGNORE_DEPRECATED_POP + + DebugMessage::insert(DebugMessage::Source::Application, DebugMessage::Type::Marker, + 1337, DebugOutput::Severity::High, "Hello from OpenGL command stream!"); + + MAGNUM_VERIFY_NO_GL_ERROR(); + CORRADE_COMPARE(out.str(), + "Debug output: high severity application marker (1337): Hello from OpenGL command stream!\n"); +} +#endif + void DebugOutputGLTest::setup() { _out.str({}); @@ -86,7 +160,7 @@ void DebugOutputGLTest::setup() { Renderer::enable(Renderer::Feature::DebugOutput); Renderer::enable(Renderer::Feature::DebugOutputSynchronous); - DebugOutput::setCallback([](DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, const std::string& string, const void* userPtr) { + DebugOutput::setCallback([](DebugOutput::Source source, DebugOutput::Type type, UnsignedInt id, DebugOutput::Severity severity, Containers::StringView string, const void* userPtr) { Implementation::defaultDebugCallback(source, type, id, severity, string, static_cast(const_cast(userPtr))); }, &_out); } @@ -141,12 +215,15 @@ void DebugOutputGLTest::messageNoOp() { } void DebugOutputGLTest::message() { + auto&& data = MessageData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); /* Need to be careful, because the test runner is using debug output too */ DebugMessage::insert(DebugMessage::Source::Application, DebugMessage::Type::Marker, - 1337, DebugOutput::Severity::High, "Hello from OpenGL command stream!"); + 1337, DebugOutput::Severity::High, data.message); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE(_out.str(), @@ -184,14 +261,17 @@ void DebugOutputGLTest::groupNoOp() { } void DebugOutputGLTest::group() { + auto&& data = GroupData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); /* Need to be careful, because the test runner is using debug output too */ { - DebugGroup g1{DebugGroup::Source::Application, 42, "Automatic debug group"}; + DebugGroup g1{DebugGroup::Source::Application, 42, data.automaticGroupName}; DebugGroup g2; - g2.push(DebugGroup::Source::ThirdParty, 1337, "Manual debug group"); + g2.push(DebugGroup::Source::ThirdParty, 1337, data.manualGroupName); g2.pop(); }