summaryrefslogtreecommitdiff
path: root/glwrangle.h
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2017-01-23 18:23:42 +0200
committerJari Vetoniemi <mailroxas@gmail.com>2017-01-23 18:23:42 +0200
commit238b64b541d9c37a59a291980e07f0b5d9d9826b (patch)
tree3a6dc532fce3fd5a40b6015c16b4fa711147a307 /glwrangle.h
parent1d71fee4c0ba9be181fc48a447b7287754dc9bd1 (diff)
Add wider OpenGL coverage, more cleanups, etc..
Testing with some GLES 2.0 programs that I have made so I can profile this thing.
Diffstat (limited to 'glwrangle.h')
-rw-r--r--glwrangle.h132
1 files changed, 99 insertions, 33 deletions
diff --git a/glwrangle.h b/glwrangle.h
index f6b2555..3da96b7 100644
--- a/glwrangle.h
+++ b/glwrangle.h
@@ -2,45 +2,71 @@
static GLenum (*_glGetError)(void);
static void (*_glGetIntegerv)(GLenum, GLint*);
+static void (*_glGetFloatv)(GLenum, GLfloat*);
+static void (*_glGetBooleanv)(GLenum, GLboolean*);
+static const char* (*_glGetString)(GLenum);
static GLboolean (*_glIsBuffer)(GLuint);
static void (*_glGenBuffers)(GLsizei, GLuint*);
static void (*_glDeleteBuffers)(GLsizei, GLuint*);
static void (*_glBindBuffer)(GLenum, GLuint);
static void (*_glBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum);
-static void* (*_glMapBuffer)(GLenum, GLenum);
+static void* (*_glMapBufferRange)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
static void (*_glUnmapBuffer)(GLenum);
static void (*_glPixelStorei)(GLenum, GLint);
static void (*_glReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*);
-static void (*_glPushClientAttrib)(GLbitfield);
-static void (*_glPopClientAttrib)(void);
-static void (*_glPushAttrib)(GLbitfield);
-static void (*_glPopAttrib)(void);
static void (*_glEnable)(GLenum);
static void (*_glDisable)(GLenum);
static void (*_glScissor)(GLint, GLint, GLsizei, GLsizei);
static void (*_glClearColor)(GLclampf, GLclampf, GLclampf, GLclampf);
static void (*_glClear)(GLbitfield);
+static void (*_glDebugMessageCallback)(GLDEBUGPROC, const void*);
+
+enum gl_variant {
+ OPENGL_ES,
+ OPENGL,
+};
+
+struct gl_version {
+ uint32_t major, minor;
+};
+
+static enum gl_variant OPENGL_VARIANT;
+static struct gl_version OPENGL_VERSION;
#define glGetError _glGetError
#define glGetIntegerv _glGetIntegerv
+#define glGetFloatv _glGetFloatv
+#define glGetBooleanv _glGetBooleanv
+#define glGetString _glGetString
#define glIsBuffer _glIsBuffer
#define glGenBuffers _glGenBuffers
#define glDeleteBuffers _glDeleteBuffers
#define glBindBuffer _glBindBuffer
#define glBufferData _glBufferData
-#define glMapBuffer _glMapBuffer
+#define glMapBufferRange _glMapBufferRange
#define glUnmapBuffer _glUnmapBuffer
#define glPixelStorei _glPixelStorei
#define glReadPixels _glReadPixels
-#define glPushClientAttrib _glPushClientAttrib
-#define glPopClientAttrib _glPopClientAttrib
-#define glPushAttrib _glPushAttrib
-#define glPopAttrib _glPopAttrib
#define glEnable _glEnable
#define glDisable _glDisable
#define glScissor _glScissor
#define glClearColor _glClearColor
#define glClear _glClear
+#define glDebugMessageCallback _glDebugMessageCallback
+
+static void
+debug_cb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *data)
+{
+ (void)source, (void)type, (void)id, (void)severity, (void)length, (void)message, (void)data;
+ WARNX("%s", message);
+}
+
+static void*
+dlsym_proc(const char *procname)
+{
+ HOOK_DLSYM(dlsym);
+ return _dlsym(RTLD_NEXT, procname);
+}
static void
load_gl_function_pointers(void* (*procs[])(const char*), const size_t memb)
@@ -57,30 +83,70 @@ load_gl_function_pointers(void* (*procs[])(const char*), const size_t memb)
}
if (!proc)
- ERRX(EXIT_FAILURE, "There is no proc loader available");
-
-#define GL(x) do { if (!(_##x = proc(#x))) { ERRX(EXIT_FAILURE, "Failed to load %s", #x); } } while (0)
- GL(glGetError);
- GL(glGetIntegerv);
- GL(glIsBuffer);
- GL(glGenBuffers);
- GL(glDeleteBuffers);
- GL(glBindBuffer);
- GL(glBufferData);
- GL(glMapBuffer);
- GL(glUnmapBuffer);
- GL(glPixelStorei);
- GL(glReadPixels);
- GL(glPushClientAttrib);
- GL(glPopClientAttrib);
- GL(glPushAttrib);
- GL(glPopAttrib);
- GL(glEnable);
- GL(glDisable);
- GL(glScissor);
- GL(glClearColor);
- GL(glClear);
+ proc = dlsym_proc;
+
+ // We try to support wide range of OpenGL and variants as possible.
+ // Thus avoid using functions that only work in certain OpenGL versions.
+ // e.g. glPushAttrib, glPushClientAttrib, it's bit of shitty but such is life.
+ // Alternatively if code starts getting too much saving/restoring, consider hooking
+ // the gl state changes we care about and write our own push/pop around swap_buffer.
+ //
+ // Version / variant dependant code is still possible through GL_VARIANT and GL_VERSION variables.
+ //
+ // Note that we also rely on system GL/glx.h for typedefs / constants, which probably is plain wrong on ES
+ // for example, but seems to work fine so far. Main interest is to work with mainly GLX / Wine games anyways.
+
+#define GL_REQUIRED(x) do { if (!(_##x = proc(#x))) { ERRX(EXIT_FAILURE, "Failed to load %s", #x); } } while (0)
+#define GL_OPTIONAL(x) do { _##x = proc(#x); } while (0)
+ GL_REQUIRED(glGetError);
+ GL_REQUIRED(glGetIntegerv);
+ GL_REQUIRED(glGetFloatv);
+ GL_REQUIRED(glGetBooleanv);
+ GL_REQUIRED(glGetString);
+ GL_REQUIRED(glIsBuffer);
+ GL_REQUIRED(glGenBuffers);
+ GL_REQUIRED(glDeleteBuffers);
+ GL_REQUIRED(glBindBuffer);
+ GL_REQUIRED(glBufferData);
+ GL_REQUIRED(glMapBufferRange);
+ GL_REQUIRED(glUnmapBuffer);
+ GL_REQUIRED(glPixelStorei);
+ GL_REQUIRED(glReadPixels);
+ GL_REQUIRED(glEnable);
+ GL_REQUIRED(glDisable);
+ GL_REQUIRED(glScissor);
+ GL_REQUIRED(glClearColor);
+ GL_REQUIRED(glClear);
+ GL_OPTIONAL(glDebugMessageCallback);
#undef GL
+ if (glDebugMessageCallback) {
+ // GL_DEBUG_OUTPUT_SYNCHRONOUS for breakpoints (slower)
+ glEnable(GL_DEBUG_OUTPUT);
+ // glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ glDebugMessageCallback(debug_cb, NULL);
+ }
+
+ const struct { const char *p; enum gl_variant v; } variants[] = {
+ { .p = "OpenGL ES-CM ", .v = OPENGL_ES },
+ { .p = "OpenGL ES-CL ", .v = OPENGL_ES },
+ { .p = "OpenGL ES ", .v = OPENGL_ES },
+ { .p = "OpenGL ", .v = OPENGL },
+ };
+
+ const char *version = glGetString(GL_VERSION);
+ WARNX("%s", version);
+
+ for (size_t i = 0; i < ARRAY_SIZE(variants); ++i) {
+ const size_t len = strlen(variants[i].p);
+ if (strncmp(version, variants[i].p, len))
+ continue;
+
+ OPENGL_VARIANT = variants[i].v;
+ version += len;
+ break;
+ }
+
+ sscanf(version, "%u.%u", &OPENGL_VERSION.major, &OPENGL_VERSION.minor);
loaded = true;
}