Browse Source

Support for debug message callback from KHR_debug.

pull/38/head
Vladimír Vondruš 13 years ago
parent
commit
7f22b9c214
  1. 59
      src/DebugMessage.cpp
  2. 72
      src/DebugMessage.h
  3. 5
      src/Implementation/DebugState.cpp
  4. 2
      src/Implementation/DebugState.h
  5. 25
      src/Renderer.h
  6. 13
      src/Test/DebugGLTest.cpp

59
src/DebugMessage.cpp

@ -33,6 +33,29 @@
namespace Magnum {
namespace {
void callbackWrapper(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
Context::current()->state().debug->messageCallback(DebugMessage::Source(source), DebugMessage::Type(type), id, DebugMessage::Severity(severity), std::string(message, length), userParam);
}
void defaultCallback(const DebugMessage::Source source, const DebugMessage::Type type, const UnsignedInt id, const DebugMessage::Severity severity, const std::string& string, const void*) {
switch(severity) {
case DebugMessage::Severity::High:
Error() << source << type << id << severity << "\n " << string;
break;
case DebugMessage::Severity::Medium:
case DebugMessage::Severity::Low:
Warning() << source << type << id << severity << "\n " << string;
break;
default: Debug() << source << type << id << severity << "\n " << string;
}
}
}
Int DebugMessage::maxLoggedMessages() {
if(!Context::current()->isExtensionSupported<Extensions::GL::KHR::debug>())
return 0;
@ -71,6 +94,14 @@ void DebugMessage::insert(const Source source, const Type type, const UnsignedIn
Context::current()->state().debug->messageInsertImplementation(source, type, id, severity, string);
}
void DebugMessage::setCallback(const Callback callback, const void* userParam) {
Context::current()->state().debug->messageCallbackImplementation(callback, userParam);
}
void DebugMessage::setDefaultCallback() {
setCallback(defaultCallback, nullptr);
}
void DebugMessage::insertImplementationNoOp(Source, Type, UnsignedInt, Severity, const std::string&) {}
void DebugMessage::insertImplementationKhr(const Source source, const Type type, const UnsignedInt id, const Severity severity, const std::string& string) {
@ -104,6 +135,34 @@ void DebugMessage::insertImplementationGremedy(Source, Type, UnsignedInt, Severi
}
#endif
void DebugMessage::callbackImplementationNoOp(Callback, const void*) {}
void DebugMessage::callbackImplementationKhr(const Callback callback, const void* userParam) {
/* Replace the callback */
const Callback original = Context::current()->state().debug->messageCallback;
Context::current()->state().debug->messageCallback = callback;
/* Adding callback */
if(!original && callback) {
#ifndef MAGNUM_TARGET_GLES
glDebugMessageCallback(callbackWrapper, userParam);
#else
static_cast<void>(userParam);
CORRADE_INTERNAL_ASSERT(false);
//glDebugMessageCallbackEXT(callbackWrapper, userParam);
#endif
/* Deleting callback */
} else if(original && !callback) {
#ifndef MAGNUM_TARGET_GLES
glDebugMessageCallback(nullptr, nullptr);
#else
CORRADE_INTERNAL_ASSERT(false);
//glDebugMessageCallbackEXT(nullptr, nullptr);
#endif
}
}
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, const DebugMessage::Source value) {
switch(value) {

72
src/DebugMessage.h

@ -41,8 +41,32 @@ namespace Implementation { struct DebugState; }
/**
@brief Debug message
Allows inserting debug messages into OpenGL command stream, for example with
conjunction with various debuggers, such as Apitrace or gDEBugger.
Allows retrieving and inserting debug messages from and to OpenGL command
stream, for example with conjunction with various debuggers, such as Apitrace
or gDEBugger.
@section DebugMessage-usage Basic usage
To retrieve debug messages from either the GL or your application you need to
have OpenGL 4.3 or @extension{KHR,debug} desktop/ES extension. You need to
enable @ref Renderer::Feature::DebugOutput and possibly also
@ref Renderer::Feature::DebugOutputSynchronous. Then set up message callback
using @ref setCallback() or use the default one provided in
@ref setDefaultCallback():
@code
Renderer::setFeature(Renderer::Feature::DebugOutput, true);
Renderer::setFeature(Renderer::Feature::DebugOutputSynchronous, true);
DebugMessage::setDefaultCallback();
DebugMessage::insert(DebugMessage::Source::Application, DebugMessage::Type::Marker,
1337, DebugMessage::Severity::Notification, "Hello from OpenGL command stream!");
@endcode
With default callback the messages will be printed on standard output:
DebugMessage::Source::Application DebugMessage::Type::Marker -1 DebugMessage::Severity::Notification
Hello from OpenGL command stream!
*/
class MAGNUM_EXPORT DebugMessage {
friend class Implementation::DebugState;
@ -51,7 +75,7 @@ class MAGNUM_EXPORT DebugMessage {
/**
* @brief Message source
*
* @see @ref insert()
* @see @ref insert(), @ref setCallback()
*/
enum class Source: GLenum {
/** OpenGL */
@ -100,7 +124,7 @@ class MAGNUM_EXPORT DebugMessage {
/**
* @brief Message type
*
* @see @ref insert()
* @see @ref insert(), @ref setCallback()
*/
enum class Type: GLenum {
/** OpenGL error */
@ -156,7 +180,7 @@ class MAGNUM_EXPORT DebugMessage {
/**
* @brief Message severity
*
* @see @ref insert()
* @see @ref insert(), @ref setCallback()
*/
enum class Severity: GLenum {
/**
@ -194,6 +218,13 @@ class MAGNUM_EXPORT DebugMessage {
#endif
};
/**
* @brief Debug callback
*
* @see @ref setCallback()
*/
typedef void(*Callback)(Source, Type, UnsignedInt, Severity, const std::string&, const void*);
/**
* @brief Max count of debug messages in log
*
@ -242,6 +273,34 @@ class MAGNUM_EXPORT DebugMessage {
*/
static void insert(Source source, Type type, UnsignedInt id, Severity severity, const std::string& string);
/**
* @brief Set debug message callback
*
* The messages are sent to the callback only if
* @ref Renderer::Feature::DebugOutput is enabled. If OpenGL 4.3 is not
* supported and @extension{KHR,debug} is not available, this function
* does nothing.
* @see @ref setDefaultCallback(),
* @ref Renderer::Feature::DebugOutputSynchronous
*/
static void setCallback(Callback callback, const void* userParam = nullptr);
/**
* @brief Set default debug message callback
*
* See @ref setCallback() for more information. The message is printed
* to either @ref Corrade::Utility::Error "Error", @ref Corrade::Utility::Warning "Warning"
* or @ref Corrade::Utility::Debug "Debug" in the following format:
* @code
* DebugMessage::insert(DebugMessage::Source::Application,
* DebugMessage::Type::Marker, 1337, DebugMessage::Severity::Notification, "Hello from OpenGL command stream!");
* @endcode
*
* <pre>%DebugMessage::Source::Application %DebugMessage::Type::Marker -1 %DebugMessage::Severity::Notification
* Hello from OpenGL command stream!</pre>
*/
static void setDefaultCallback();
DebugMessage() = delete;
private:
@ -251,6 +310,9 @@ class MAGNUM_EXPORT DebugMessage {
#ifndef MAGNUM_TARGET_GLES
static MAGNUM_LOCAL void insertImplementationGremedy(Source, Type, UnsignedInt, Severity, const std::string& string);
#endif
static MAGNUM_LOCAL void callbackImplementationNoOp(Callback, const void*);
static MAGNUM_LOCAL void callbackImplementationKhr(Callback callback, const void* userParam);
};
/** @debugoperator{Magnum::DebugMessage} */

5
src/Implementation/DebugState.cpp

@ -30,11 +30,12 @@
namespace Magnum { namespace Implementation {
DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0), maxMessageLength(0) {
DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0), maxMessageLength(0), messageCallback(nullptr) {
if(context.isExtensionSupported<Extensions::GL::KHR::debug>()) {
getLabelImplementation = &AbstractObject::getLabelImplementationKhr;
labelImplementation = &AbstractObject::labelImplementationKhr;
messageInsertImplementation = &DebugMessage::insertImplementationKhr;
messageCallbackImplementation = &DebugMessage::callbackImplementationKhr;
} else {
if(context.isExtensionSupported<Extensions::GL::EXT::debug_label>()) {
@ -53,6 +54,8 @@ DebugState::DebugState(Context& context): maxLabelLength(0), maxLoggedMessages(0
#endif
else
messageInsertImplementation = &DebugMessage::insertImplementationNoOp;
messageCallbackImplementation = &DebugMessage::callbackImplementationNoOp;
}
}

2
src/Implementation/DebugState.h

@ -37,8 +37,10 @@ struct DebugState {
void(*labelImplementation)(GLenum, GLuint, const std::string&);
void(*messageInsertImplementation)(DebugMessage::Source, DebugMessage::Type, UnsignedInt, DebugMessage::Severity, const std::string&);
void(*messageCallbackImplementation)(DebugMessage::Callback, const void*);
GLint maxLabelLength, maxLoggedMessages, maxMessageLength;
DebugMessage::Callback messageCallback;
};
}}

25
src/Renderer.h

@ -79,6 +79,31 @@ class MAGNUM_EXPORT Renderer {
*/
Blending = GL_BLEND,
/**
* Debug output
* @requires_gl43 %Extension @extension{KHR,debug}
* @requires_es_extension %Extension @es_extension{KHR,debug}
* @see @ref DebugMessage, @ref Feature::DebugOutputSynchronous
*/
#ifndef MAGNUM_TARGET_GLES
DebugOutput = GL_DEBUG_OUTPUT,
#else
DebugOutput = GL_DEBUG_OUTPUT_KHR,
#endif
/**
* Synchronous debug output. Has effect only if @ref Feature::DebugOutput
* is enabled.
* @requires_gl43 %Extension @extension{KHR,debug}
* @requires_es_extension %Extension @es_extension{KHR,debug}
* @see @ref DebugMessage
*/
#ifndef MAGNUM_TARGET_GLES
DebugOutputSynchronous = GL_DEBUG_OUTPUT_SYNCHRONOUS,
#else
DebugOutputSynchronous = GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* Depth clamping. If enabled, ignores near and far clipping plane.

13
src/Test/DebugGLTest.cpp

@ -24,6 +24,8 @@
#include "Test/AbstractOpenGLTester.h"
#include <sstream>
#include "Context.h"
#include "DebugMessage.h"
#include "Extensions.h"
@ -72,10 +74,21 @@ void DebugGLTest::insertMessage() {
if(!Context::current()->isExtensionSupported<Extensions::GL::KHR::debug>())
CORRADE_SKIP(Extensions::GL::KHR::debug::string() + std::string(" is not supported"));
Renderer::setFeature(Renderer::Feature::DebugOutput, true);
Renderer::setFeature(Renderer::Feature::DebugOutputSynchronous, true);
std::ostringstream out;
Debug::setOutput(&out);
DebugMessage::setDefaultCallback();
DebugMessage::insert(DebugMessage::Source::Application, DebugMessage::Type::Marker,
1337, DebugMessage::Severity::Notification, "Hello from OpenGL command stream!");
Renderer::setFeature(Renderer::Feature::DebugOutput, false);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(out.str(),
"DebugMessage::Source::Application DebugMessage::Type::Marker 1337 DebugMessage::Severity::Notification \n"
" Hello from OpenGL command stream!\n");
}
void DebugGLTest::insertMessageFallback() {

Loading…
Cancel
Save