From 3b1e65ba08673abd79e84ceb46cebc9356a23be7 Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 14 Aug 2013 14:00:21 +0200 Subject: [PATCH] Add GL_DEBUG ifdef which forces full GL debugging. --- Makefile | 5 ++ Makefile.win | 5 ++ gfx/context/glx_ctx.c | 61 +++++++++++++--------- gfx/gl.c | 115 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 156 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index acf4054dbf..f7eb516e70 100644 --- a/Makefile +++ b/Makefile @@ -337,6 +337,11 @@ ifeq ($(DEBUG), 1) OPTIMIZE_FLAG = -O0 endif +ifeq ($(GL_DEBUG), 1) + CFLAGS += -DGL_DEBUG + CXXFLAGS += -DGL_DEBUG +endif + CFLAGS += -Wall $(OPTIMIZE_FLAG) $(INCLUDE_DIRS) -g -I. ifeq ($(CXX_BUILD), 1) LD = $(CXX) diff --git a/Makefile.win b/Makefile.win index 3003c672b1..71036ccf47 100644 --- a/Makefile.win +++ b/Makefile.win @@ -237,6 +237,11 @@ else LDCXXFLAGS += -s endif +ifeq ($(GL_DEBUG), 1) + CFLAGS += -DGL_DEBUG + CXXFLAGS += -DGL_DEBUG +endif + CFLAGS += -Wall -Wno-unused-result -Wno-unused-variable -I. CXXFLAGS += -Wall -Wno-unused-result -Wno-unused-variable -I. -std=c++0x -D__STDC_CONSTANT_MACROS ifeq ($(CXX_BUILD), 1) diff --git a/gfx/context/glx_ctx.c b/gfx/context/glx_ctx.c index a4d08652e1..cc64267351 100644 --- a/gfx/context/glx_ctx.c +++ b/gfx/context/glx_ctx.c @@ -42,6 +42,7 @@ static GLXFBConfig g_fbc; static unsigned g_major; static unsigned g_minor; static bool g_core; +static bool g_debug; typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); @@ -229,24 +230,22 @@ static bool gfx_ctx_init(void) int major, minor; glXQueryVersion(g_dpy, &major, &minor); - if (g_major * 1000 + g_minor >= 3001) // Core context - { - g_core = true; - // GLX 1.4+ required. - if ((major * 1000 + minor) < 1004) - goto error; - glx_create_context_attribs = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); - if (!glx_create_context_attribs) - goto error; - } - else - { - g_core = false; - // GLX 1.3+ required. - if ((major * 1000 + minor) < 1003) - goto error; - } + // GLX 1.3+ minimum required. + if ((major * 1000 + minor) < 1003) + goto error; + + glx_create_context_attribs = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + +#ifdef GL_DEBUG + g_debug = true; +#else + g_debug = g_extern.system.hw_render_callback.debug_context; +#endif + + g_core = (g_major * 1000 + g_minor) >= 3001; // Have to use ContextAttribs + if ((g_core || g_debug) && !glx_create_context_attribs) + goto error; int nelements; fbcs = glXChooseFBConfig(g_dpy, DefaultScreen(g_dpy), @@ -376,16 +375,28 @@ static bool gfx_ctx_set_video_mode( if (!g_ctx) { - if (g_core) + if (g_core || g_debug) { - const int attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, (int)g_major, - GLX_CONTEXT_MINOR_VERSION_ARB, (int)g_minor, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - GLX_CONTEXT_FLAGS_ARB, g_extern.system.hw_render_callback.debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0, - None, - }; + int attribs[16]; + int *aptr = attribs; + if (g_core) + { + *aptr++ = GLX_CONTEXT_MAJOR_VERSION_ARB; + *aptr++ = g_major; + *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB; + *aptr++ = g_minor; + *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB; + *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + } + + if (g_debug) + { + *aptr++ = GLX_CONTEXT_FLAGS_ARB; + *aptr++ = GLX_CONTEXT_DEBUG_BIT_ARB; + } + + *aptr = None; g_ctx = glx_create_context_attribs(g_dpy, g_fbc, NULL, True, attribs); } else diff --git a/gfx/gl.c b/gfx/gl.c index 628f743634..3810cd4373 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -23,6 +23,7 @@ #include "../performance.h" #include "scaler/scaler.h" #include "image.h" +#include "../file.h" #include #include "../libretro.h" @@ -1661,11 +1662,33 @@ static bool resolve_extensions(gl_t *gl) } #endif -#if 0 - // Useful for debugging, but kinda obnoxious. - const char *ext = (const char*)glGetString(GL_EXTENSIONS); - if (ext) - RARCH_LOG("[GL] Supported extensions: %s\n", ext); +#ifdef GL_DEBUG + // Useful for debugging, but kinda obnoxious otherwise. + RARCH_LOG("[GL]: Supported extensions:\n"); + if (gl->core_context) + { +#ifdef GL_NUM_EXTENSIONS + GLint exts = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &exts); + for (GLint i = 0; i < exts; i++) + { + const char *ext = (const char*)glGetStringi(GL_EXTENSIONS, i); + if (ext) + RARCH_LOG("\t%s\n", ext); + } +#endif + } + else + { + const char *ext = (const char*)glGetString(GL_EXTENSIONS); + if (ext) + { + struct string_list *list = string_split(ext, " "); + for (size_t i = 0; i < list->size; i++) + RARCH_LOG("\t%s\n", list->elems[i].data); + string_list_free(list); + } + } #endif return true; @@ -1814,6 +1837,84 @@ static const gfx_ctx_driver_t *gl_get_context(void) return gfx_ctx_init_first(api, major, minor); } +#ifdef GL_DEBUG +#ifdef HAVE_OPENGLES2 +#define DEBUG_CALLBACK_TYPE GL_APIENTRY +#else +#define DEBUG_CALLBACK_TYPE APIENTRY +#endif +static void DEBUG_CALLBACK_TYPE gl_debug_cb(GLenum source, GLenum type, + GLuint id, GLenum severity, GLsizei length, + const GLchar *message, void *userParam) +{ + (void)id; + (void)length; + + gl_t *gl = (gl_t*)userParam; // Useful for debugger. + (void)gl; + + const char *src; + switch (source) + { + case GL_DEBUG_SOURCE_API: src = "API"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: src = "Window system"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: src = "Shader compiler"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: src = "3rd party"; break; + case GL_DEBUG_SOURCE_APPLICATION: src = "Application"; break; + case GL_DEBUG_SOURCE_OTHER: src = "Other"; break; + default: src = "Unknown"; break; + } + + const char *typestr; + switch (type) + { + case GL_DEBUG_TYPE_ERROR: typestr = "Error"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typestr = "Deprecated behavior"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typestr = "Undefined behavior"; break; + case GL_DEBUG_TYPE_PORTABILITY: typestr = "Portability"; break; + case GL_DEBUG_TYPE_PERFORMANCE: typestr = "Performance"; break; + case GL_DEBUG_TYPE_MARKER: typestr = "Marker"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: typestr = "Push group"; break; + case GL_DEBUG_TYPE_POP_GROUP: typestr = "Pop group"; break; + case GL_DEBUG_TYPE_OTHER: typestr = "Other"; break; + default: typestr = "Unknown"; break; + } + + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: + RARCH_ERR("[GL debug (High, %s, %s)]: %s\n", src, typestr, message); + break; + case GL_DEBUG_SEVERITY_MEDIUM: + RARCH_WARN("[GL debug (Medium, %s, %s)]: %s\n", src, typestr, message); + break; + case GL_DEBUG_SEVERITY_LOW: + RARCH_LOG("[GL debug (Low, %s, %s)]: %s\n", src, typestr, message); + break; + } +} + +static void gl_begin_debug(gl_t *gl) +{ + if (gl_query_extension(gl, "KHR_debug")) + { + glDebugMessageCallback(gl_debug_cb, gl); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + } +#ifndef HAVE_OPENGLES2 + else if (gl_query_extension(gl, "ARB_debug_output")) + { + glDebugMessageCallbackARB(gl_debug_cb, gl); + glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); + } +#endif + else + RARCH_ERR("Neither GL_KHR_debug nor GL_ARB_debug_output are implemented. Cannot start GL debugging.\n"); +} +#endif + static void *gl_init(const video_info_t *video, const input_driver_t **input, void **input_data) { #ifdef _WIN32 @@ -1881,6 +1982,10 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo return NULL; } +#ifdef GL_DEBUG + gl_begin_debug(gl); +#endif + gl->vsync = video->vsync; gl->fullscreen = video->fullscreen;