#include "../include/mgl/gl.h" #include #include #include typedef struct { void **func; const char *name; } dlsym_assign; static void* dlsym_print_fail(void *handle, const char *name, int required) { dlerror(); void *sym = dlsym(handle, name); char *err_str = dlerror(); if(!sym) fprintf(stderr, "mgl %s: dlsym(handle, \"%s\") failed, error: %s\n", required ? "error" : "warning", name, err_str ? err_str : "(null)"); return sym; } int mgl_gl_load(mgl_gl *self) { /* Threaded gl optimization doesn't improve performance here, it just increases cpu usage, so force disable it if the user has enabled it */ setenv("__GL_THREADED_OPTIMIZATIONS", "0", 1); const char *glx_path = "libGL.so.1"; self->handle = dlopen(glx_path, RTLD_LAZY); if(!self->handle) { fprintf(stderr, "mgl error:dlopen(\"%s\", RTLD_LAZY) failed\n", glx_path); return -1; } const dlsym_assign required_dlsym[] = { { &self->glXCreateNewContext, "glXCreateNewContext" }, { &self->glXMakeContextCurrent, "glXMakeContextCurrent" }, { &self->glXDestroyContext, "glXDestroyContext" }, { &self->glXSwapBuffers, "glXSwapBuffers" }, { &self->glXChooseFBConfig, "glXChooseFBConfig" }, { &self->glXGetVisualFromFBConfig, "glXGetVisualFromFBConfig" }, { &self->glViewport, "glViewport" }, { &self->glScissor, "glScissor" }, { &self->glClearColor, "glClearColor" }, { &self->glClear, "glClear" }, { &self->glEnable, "glEnable" }, { &self->glBlendFunc, "glBlendFunc" }, { &self->glGenTextures, "glGenTextures" }, { &self->glDeleteTextures, "glDeleteTextures" }, { &self->glTexImage2D, "glTexImage2D" }, { &self->glTexSubImage2D, "glTexSubImage2D" }, { &self->glBindTexture, "glBindTexture" }, { &self->glTexParameteri, "glTexParameteri" }, { &self->glHint, "glHint" }, { &self->glBegin, "glBegin" }, { &self->glEnd, "glEnd" }, { &self->glVertex3f, "glVertex3f" }, { &self->glColor4ub, "glColor4ub" }, { &self->glTexCoord2f, "glTexCoord2f" }, { &self->glOrtho, "glOrtho" }, { &self->glMatrixMode, "glMatrixMode" }, { &self->glPushMatrix, "glPushMatrix" }, { &self->glPopMatrix, "glPopMatrix" }, { &self->glLoadIdentity, "glLoadIdentity" }, { &self->glLoadMatrixf, "glLoadMatrixf" }, { &self->glTranslatef, "glTranslatef" }, { &self->glRotatef, "glRotatef" }, { &self->glGenBuffers, "glGenBuffers" }, { &self->glBindBuffer, "glBindBuffer" }, { &self->glDeleteBuffers, "glDeleteBuffers" }, { &self->glBufferData, "glBufferData" }, { &self->glBufferSubData, "glBufferSubData" }, { &self->glDrawArrays, "glDrawArrays" }, { &self->glEnableClientState, "glEnableClientState" }, { &self->glVertexPointer, "glVertexPointer" }, { &self->glColorPointer, "glColorPointer" }, { &self->glTexCoordPointer, "glTexCoordPointer" }, { &self->glCompileShader, "glCompileShader" }, { &self->glCreateProgram, "glCreateProgram" }, { &self->glCreateShader, "glCreateShader" }, { &self->glDeleteProgram, "glDeleteProgram" }, { &self->glDeleteShader, "glDeleteShader" }, { &self->glGetShaderiv, "glGetShaderiv" }, { &self->glGetShaderInfoLog, "glGetShaderInfoLog" }, { &self->glGetProgramiv, "glGetProgramiv" }, { &self->glGetProgramInfoLog, "glGetProgramInfoLog" }, { &self->glLinkProgram, "glLinkProgram" }, { &self->glShaderSource, "glShaderSource" }, { &self->glUseProgram, "glUseProgram" }, { &self->glAttachShader, "glAttachShader" }, { &self->glGetUniformLocation, "glGetUniformLocation" }, { &self->glUniform1f, "glUniform1f" }, { &self->glUniform2f, "glUniform2f" }, { &self->glGetError, "glGetError" }, { &self->glGetString, "glGetString" }, { &self->glGetIntegerv, "glGetIntegerv" }, { &self->glPixelStorei, "glPixelStorei" }, { NULL, NULL } }; for(int i = 0; required_dlsym[i].func; ++i) { *required_dlsym[i].func = dlsym_print_fail(self->handle, required_dlsym[i].name, 1); if(!*required_dlsym[i].func) { mgl_gl_unload(self); return -1; } } const dlsym_assign optional_dlsym[] = { { &self->glXSwapIntervalEXT, "glXSwapIntervalEXT" }, { &self->glXSwapIntervalMESA, "glXGetSwapIntervalMESA" }, { &self->glXSwapIntervalSGI, "glXSwapIntervalSGI" }, { NULL, NULL } }; for(int i = 0; optional_dlsym[i].func; ++i) { *optional_dlsym[i].func = dlsym_print_fail(self->handle, optional_dlsym[i].name, 0); } return 0; } void mgl_gl_unload(mgl_gl *self) { if(self->handle) { dlclose(self->handle); self->handle = NULL; } }