From 238b64b541d9c37a59a291980e07f0b5d9d9826b Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 23 Jan 2017 18:23:42 +0200 Subject: Add wider OpenGL coverage, more cleanups, etc.. Testing with some GLES 2.0 programs that I have made so I can profile this thing. --- glwrangle.h | 132 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 33 deletions(-) (limited to 'glwrangle.h') 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; } -- cgit v1.2.3