better logging and OpenGL ARB_debug_output
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 11 Jan 2018 06:22:51 +0000 (08:22 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 11 Jan 2018 06:22:51 +0000 (08:22 +0200)
src/app.cc
src/logger.cc
src/logger.h
src/main.cc
src/opengl.c [new file with mode: 0644]
src/opengl.h

index 6c9f374..dcfd3f3 100644 (file)
@@ -77,6 +77,12 @@ static Renderer *rend;
 
 bool app_init(int argc, char **argv)
 {
+       set_log_file("demo.log");
+
+       if(init_opengl() == -1) {
+               return false;
+       }
+
        if(!init_options(argc, argv, "demo.conf")) {
                return false;
        }
index 015c9bd..254c20d 100644 (file)
 enum { LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_FATAL, LOG_DEBUG };
 
 static int typecolor(int type);
+static const char *typeprefix(int type);
 
 static FILE *fp = stdout;
+static FILE *logfile;
 
 static void logmsg(int type, const char *fmt, va_list ap)
 {
+       va_list ap_orig;
+
+       va_copy(ap_orig, ap);
+
 #if defined(unix) || defined(__unix__) || (defined(__APPLE__) && !defined(TARGET_IPHONE))
        if(isatty(fileno(fp)) && type != LOG_INFO) {
                int c = typecolor(type);
@@ -28,20 +34,48 @@ static void logmsg(int type, const char *fmt, va_list ap)
        } else
 #endif
        {
+               fprintf(fp, "%s", typeprefix(type));
                vfprintf(fp, fmt, ap);
        }
        if(type == LOG_ERROR || type == LOG_FATAL || type == LOG_DEBUG) {
                fflush(fp);
        }
 
+       if(logfile) {
+               va_end(ap);
+               va_copy(ap, ap_orig);
+               fprintf(logfile, "%s", typeprefix(type));
+               vfprintf(logfile, fmt, ap);
+       }
+
 #ifdef WIN32
        if(type == LOG_FATAL) {
                static char msgbuf[1024];
-               vsnprintf(msgbuf, sizeof msgbuf - 1, fmt, ap);
+               vsnprintf(msgbuf, sizeof msgbuf - 1, fmt, ap_orig);
                msgbuf[sizeof msgbuf - 1] = 0;
                MessageBox(0, msgbuf, "Fatal error", MB_OK | MB_ICONSTOP);
        }
 #endif
+
+       va_end(ap_orig);
+}
+
+static void close_logfile(void)
+{
+       if(logfile) fclose(logfile);
+}
+
+extern "C" void set_log_file(const char *fname)
+{
+       static int init_once;
+
+       close_logfile();
+       logfile = fopen(fname, "w");
+
+       if(!init_once) {
+               atexit(close_logfile);
+               init_once = 1;
+       }
 }
 
 extern "C" void info_log(const char *fmt, ...)
@@ -127,3 +161,20 @@ static int typecolor(int type)
        }
        return 37;
 }
+
+static const char *typeprefix(int type)
+{
+       switch(type) {
+       case LOG_ERROR:
+               return "E: ";
+       case LOG_FATAL:
+               return "F: ";
+       case LOG_WARNING:
+               return "W: ";
+       case LOG_DEBUG:
+               return "D: ";
+       default:
+               break;
+       }
+       return "";
+}
index 978d634..28821cd 100644 (file)
@@ -1,10 +1,14 @@
 #ifndef LOGGER_H_
 #define LOGGER_H_
 
+#include <stdio.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+void set_log_file(const char *fname);
+
 void info_log(const char *fmt, ...);
 void warning_log(const char *fmt, ...);
 void error_log(const char *fmt, ...);
index c497dc1..e3c8a73 100644 (file)
@@ -32,6 +32,9 @@ int main(int argc, char **argv)
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
        SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
+#ifndef NDEBUG
+       SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
+#endif
 
        int defpos = SDL_WINDOWPOS_UNDEFINED;
        unsigned int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
@@ -154,8 +157,6 @@ bool app_is_mouse_grabbed()
 
 static bool init(int argc, char **argv)
 {
-       glewInit();
-
        if(!app_init(argc, argv)) {
                return false;
        }
diff --git a/src/opengl.c b/src/opengl.c
new file mode 100644 (file)
index 0000000..9fe7ea3
--- /dev/null
@@ -0,0 +1,104 @@
+#include "opengl.h"
+#include "logger.h"
+
+static void gldebug_logger(unsigned int src, unsigned int type, unsigned int id,
+               unsigned int severity, int len, const char *msg, const void *cls);
+static const char *gldebug_srcstr(unsigned int src);
+static const char *gldebug_typestr(unsigned int type);
+static const char *gldebug_sevstr(unsigned int sev);
+
+struct GLCaps glcaps;
+
+int init_opengl(void)
+{
+       glewInit();
+
+       glcaps.debug = GLEW_ARB_debug_output;
+
+#ifndef NDEBUG
+       if(glcaps.debug) {
+               info_log("Installing OpenGL debug callback\n");
+               glDebugMessageCallback(gldebug_logger, 0);
+       }
+#endif
+
+       return 0;
+}
+
+
+static void gldebug_logger(unsigned int src, unsigned int type, unsigned int id,
+               unsigned int severity, int len, const char *msg, const void *cls)
+{
+       static const char *fmt = "[GLDEBUG] (%s) %s: %s\n";
+       switch(type) {
+       case GL_DEBUG_TYPE_ERROR:
+               error_log(fmt, gldebug_srcstr(src), gldebug_typestr(type), msg);
+               break;
+
+       case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+       case GL_DEBUG_TYPE_PORTABILITY:
+       case GL_DEBUG_TYPE_PERFORMANCE:
+               warning_log(fmt, gldebug_srcstr(src), gldebug_typestr(type), msg);
+               break;
+
+       default:
+               debug_log(fmt, gldebug_srcstr(src), gldebug_typestr(type), msg);
+       }
+}
+
+static const char *gldebug_srcstr(unsigned int src)
+{
+       switch(src) {
+       case GL_DEBUG_SOURCE_API:
+               return "api";
+       case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+               return "wsys";
+       case GL_DEBUG_SOURCE_SHADER_COMPILER:
+               return "sdrc";
+       case GL_DEBUG_SOURCE_THIRD_PARTY:
+               return "3rdparty";
+       case GL_DEBUG_SOURCE_APPLICATION:
+               return "app";
+       case GL_DEBUG_SOURCE_OTHER:
+               return "other";
+       default:
+               break;
+       }
+       return "unknown";
+}
+
+static const char *gldebug_typestr(unsigned int type)
+{
+       switch(type) {
+       case GL_DEBUG_TYPE_ERROR:
+               return "error";
+       case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+               return "deprecated";
+       case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+               return "undefined behavior";
+       case GL_DEBUG_TYPE_PORTABILITY:
+               return "portability warning";
+       case GL_DEBUG_TYPE_PERFORMANCE:
+               return "performance warning";
+       case GL_DEBUG_TYPE_OTHER:
+               return "other";
+       default:
+               break;
+       }
+       return "unknown";
+}
+
+static const char *gldebug_sevstr(unsigned int sev)
+{
+       switch(sev) {
+       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";
+}
index deeddd3..6ef1733 100644 (file)
@@ -3,4 +3,20 @@
 
 #include <GL/glew.h>
 
-#endif // OPENGL_H_
+struct GLCaps {
+       int debug;      /* ARB_debug_output */
+};
+
+extern struct GLCaps glcaps;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int init_opengl(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPENGL_H_ */