Browse Source

Enable OpenGL’s debug output when the LOVE_GRAPHICS_DEBUG environment variable is ‘1’. Resolves issue #607.

Alex Szpakowski 11 years ago
parent
commit
d70023e350

+ 64 - 0
src/modules/graphics/opengl/Graphics.cpp

@@ -210,6 +210,18 @@ bool Graphics::setMode(int width, int height)
 	glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &matrixLimit);
 	glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &matrixLimit);
 	matrixLimit -= 5;
 	matrixLimit -= 5;
 
 
+	bool enabledebug = false;
+
+	if (GLEE_VERSION_3_0)
+	{
+		// Enable OpenGL's debug output if a debug context has been created.
+		GLint flags = 0;
+		glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
+		enabledebug = (flags & GL_CONTEXT_FLAG_DEBUG_BIT) != 0;
+	}
+
+	setDebug(enabledebug);
+
 	return true;
 	return true;
 }
 }
 
 
@@ -226,6 +238,58 @@ void Graphics::unSetMode()
 	gl.deInitContext();
 	gl.deInitContext();
 }
 }
 
 
+static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, GLvoid* /*usr*/)
+{
+	// Human-readable strings for the debug info.
+	const char *sourceStr = OpenGL::debugSourceString(source);
+	const char *typeStr = OpenGL::debugTypeString(type);
+	const char *severityStr = OpenGL::debugSeverityString(severity);
+
+	const char *fmt = "OpenGL: %s [source=%s, type=%s, severity=%s, id=%d]\n";
+	printf(fmt, msg, sourceStr, typeStr, severityStr, id);
+}
+
+void Graphics::setDebug(bool enable)
+{
+	// Make sure debug output is supported. The AMD ext. is a bit different
+	// so we don't make use of it, since AMD drivers now support KHR_debug.
+	if (!(GLEE_VERSION_4_3 || GLEE_KHR_debug || GLEE_ARB_debug_output))
+		return;
+
+	// Ugly hack to reduce code duplication.
+	if (GLEE_ARB_debug_output && !(GLEE_VERSION_4_3 || GLEE_KHR_debug))
+	{
+		glDebugMessageCallback = (GLEEPFNGLDEBUGMESSAGECALLBACKPROC) glDebugMessageCallbackARB;
+		glDebugMessageControl = (GLEEPFNGLDEBUGMESSAGECONTROLPROC) glDebugMessageControlARB;
+	}
+
+	if (!enable)
+	{
+		// Disable the debug callback function.
+		glDebugMessageCallback(nullptr, nullptr);
+
+		// We can disable debug output entirely with KHR_debug.
+		if (GLEE_VERSION_4_3 || GLEE_KHR_debug)
+			glDisable(GL_DEBUG_OUTPUT);
+
+		return;
+	}
+
+	// We don't want asynchronous debug output.
+	glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+	glDebugMessageCallback(debugCB, nullptr);
+
+	// Initially, enable everything.
+	glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
+
+	// Disable messages about deprecated OpenGL functionality.
+	glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE);
+	glDebugMessageControl(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, GL_DONT_CARE, 0, 0, GL_FALSE);
+
+	::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)");
+}
+
 void Graphics::reset()
 void Graphics::reset()
 {
 {
 	DisplayState s;
 	DisplayState s;

+ 2 - 0
src/modules/graphics/opengl/Graphics.h

@@ -115,6 +115,8 @@ public:
 	virtual bool setMode(int width, int height);
 	virtual bool setMode(int width, int height);
 	virtual void unSetMode();
 	virtual void unSetMode();
 
 
+	void setDebug(bool enable);
+
 	/**
 	/**
 	 * Resets the current color, background color,
 	 * Resets the current color, background color,
 	 * line style, and so forth. (This will be called
 	 * line style, and so forth. (This will be called

+ 61 - 0
src/modules/graphics/opengl/OpenGL.cpp

@@ -601,6 +601,67 @@ OpenGL::Vendor OpenGL::getVendor() const
 	return vendor;
 	return vendor;
 }
 }
 
 
+const char *OpenGL::debugSeverityString(GLenum severity)
+{
+	switch (severity)
+	{
+	case GL_DEBUG_SEVERITY_HIGH:
+		return "high";
+	case GL_DEBUG_SEVERITY_MEDIUM:
+		return "medium";
+	case GL_DEBUG_SEVERITY_LOW:
+		return "low";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
+const char *OpenGL::debugSourceString(GLenum source)
+{
+	switch (source)
+	{
+	case GL_DEBUG_SOURCE_API:
+		return "API";
+	case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+		return "window";
+	case GL_DEBUG_SOURCE_SHADER_COMPILER:
+		return "shader";
+	case GL_DEBUG_SOURCE_THIRD_PARTY:
+		return "external";
+	case GL_DEBUG_SOURCE_APPLICATION:
+		return "LOVE";
+	case GL_DEBUG_SOURCE_OTHER:
+		return "other";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
+const char *OpenGL::debugTypeString(GLenum type)
+{
+	switch (type)
+	{
+	case GL_DEBUG_TYPE_ERROR:
+		return "error";
+	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+		return "deprecated behavior";
+	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+		return "undefined behavior";
+	case GL_DEBUG_TYPE_PERFORMANCE:
+		return "performance";
+	case GL_DEBUG_TYPE_PORTABILITY:
+		return "portability";
+	case GL_DEBUG_TYPE_OTHER:
+		return "other";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
+
 // OpenGL class instance singleton.
 // OpenGL class instance singleton.
 OpenGL gl;
 OpenGL gl;
 
 

+ 5 - 0
src/modules/graphics/opengl/OpenGL.h

@@ -230,6 +230,11 @@ public:
 	 **/
 	 **/
 	Vendor getVendor() const;
 	Vendor getVendor() const;
 
 
+	// Get human-readable strings for debug info.
+	static const char *debugSeverityString(GLenum severity);
+	static const char *debugSourceString(GLenum source);
+	static const char *debugTypeString(GLenum type);
+
 private:
 private:
 
 
 	void initVendor();
 	void initVendor();

+ 25 - 0
src/modules/window/sdl/Window.cpp

@@ -250,6 +250,18 @@ bool Window::setContext(int fsaa, bool vsync)
 		context = SDL_GL_CreateContext(window);
 		context = SDL_GL_CreateContext(window);
 	}
 	}
 
 
+	if (!context)
+	{
+		int flags = 0;
+		SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &flags);
+		if (flags & SDL_GL_CONTEXT_DEBUG_FLAG)
+		{
+			SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+			SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
+			context = SDL_GL_CreateContext(window);
+		}
+	}
+
 	if (!context)
 	if (!context)
 	{
 	{
 		std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
 		std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
@@ -291,6 +303,19 @@ void Window::setWindowGLAttributes(int fsaa) const
 	// FSAA.
 	// FSAA.
 	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
 	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
 	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
 	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
+
+	// Do we want a debug context?
+	const char *debugenv = SDL_GetHint("LOVE_GRAPHICS_DEBUG");
+	if (debugenv && *debugenv == '1')
+	{
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
+	}
+	else
+	{
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
+	}
 }
 }
 
 
 void Window::updateSettings(const WindowSettings &newsettings)
 void Window::updateSettings(const WindowSettings &newsettings)