diff --git a/src/raylib.h b/src/raylib.h index dd7a68bb5..c1c4a8501 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -498,7 +498,9 @@ typedef enum { FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X - FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D) + FLAG_INTERLACED_HINT = 0x00010000, // Set to try enabling interlaced video format (for V3D) + FLAG_OPENGL_DEBUG = 0x00004000, // Set to support GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints + FLAG_OPENGL_DEBUG_SYNC = 0x00008000 // Set to support GL_DEBUG_OUTPUT_SYNCHRONOUS - Callback is in sync with errors, so a breakpoint can be placed on the callback in order to get a stacktrace for the GL error. } ConfigFlags; // Trace log level diff --git a/src/rcore.c b/src/rcore.c index b95e85d8b..347f6f3f1 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -3614,6 +3614,41 @@ int GetTouchPointCount(void) //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- +#if defined(GRAPHICS_API_OPENGL_43) && defined(PLATFORM_DESKTOP) +static void GLAPIENTRY DebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* user_param) +{ + const char* msgSource = NULL; + switch (source) + { + case GL_DEBUG_SOURCE_API: msgSource = "API"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: msgSource = "SHADER_COMPILER"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: msgSource = "THIRD_PARTY"; break; + case GL_DEBUG_SOURCE_APPLICATION: msgSource = "APPLICATION"; break; + case GL_DEBUG_SOURCE_OTHER: msgSource = "OTHER"; break; + } + + const char* msgType = NULL; + switch (type) + { + case GL_DEBUG_TYPE_ERROR: msgType = "ERROR"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: msgType = "DEPRECATED_BEHAVIOR"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: msgType = "UNDEFINED_BEHAVIOR"; break; + case GL_DEBUG_TYPE_PORTABILITY: msgType = "PORTABILITY"; break; + case GL_DEBUG_TYPE_PERFORMANCE: msgType = "PERFORMANCE"; break; + case GL_DEBUG_TYPE_OTHER: msgType = "OTHER"; break; + } + + const char* msgSeverity = "DEFAULT"; + switch (severity) + { + case GL_DEBUG_SEVERITY_LOW: msgSeverity = "LOW"; break; + case GL_DEBUG_SEVERITY_MEDIUM: msgSeverity = "MEDIUM"; break; + case GL_DEBUG_SEVERITY_HIGH: msgSeverity = "HIGH"; break; + } + + TRACELOG(LOG_WARNING, "OpenGL Debug Message: %s, type = %s, source = %s, severity = %s", message, msgType, msgSource, msgSeverity); +} +#endif // GRAPHICS_API_OPENGL_43 && PLATFORM_DESKTOP // Initialize display device and framebuffer // NOTE: width and height represent the screen (framebuffer) desired size, not actual display size @@ -3764,6 +3799,14 @@ static bool InitGraphicsDevice(int width, int height) glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); + +#if defined(GRAPHICS_API_OPENGL_43) && defined(PLATFORM_DESKTOP) + // Enable OpenGl Debug Context + if ((CORE.Window.flags & FLAG_OPENGL_DEBUG) || (CORE.Window.flags & FLAG_OPENGL_DEBUG_SYNC)) + { + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); + } +#endif // GRAPHICS_API_OPENGL_43 && PLATFORM_DESKTOP } else if (rlGetVersion() == OPENGL_ES_20) // Request OpenGL ES 2.0 context { @@ -4314,6 +4357,20 @@ static bool InitGraphicsDevice(int width, int height) rlLoadExtensions(eglGetProcAddress); #endif +#if defined(GRAPHICS_API_OPENGL_43) && defined(PLATFORM_DESKTOP) + if (glDebugMessageCallback != NULL) + { + if ((CORE.Window.flags & FLAG_OPENGL_DEBUG) || (CORE.Window.flags & FLAG_OPENGL_DEBUG_SYNC)) + { + glDebugMessageCallback(DebugMessageCallback, 0); + // GL_DEBUG_OUTPUT - Faster version but not useful for breakpoints + // GL_DEBUG_OUTPUT_SYNCHRONUS - Callback is in sync with errors, so a breakpoint can be placed on the callback in order to get a stacktrace for the GL error. + if (CORE.Window.flags & FLAG_OPENGL_DEBUG) glEnable(GL_DEBUG_OUTPUT); + if (CORE.Window.flags & FLAG_OPENGL_DEBUG_SYNC) glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } + } +#endif + int fbWidth = CORE.Window.screen.width; int fbHeight = CORE.Window.screen.height;