#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; } static int mgl_gl_load_gl(mgl_gl *self) { const dlsym_assign required_dlsym[] = { { (void**)&self->glViewport, "glViewport" }, { (void**)&self->glScissor, "glScissor" }, { (void**)&self->glClearColor, "glClearColor" }, { (void**)&self->glClear, "glClear" }, { (void**)&self->glEnable, "glEnable" }, { (void**)&self->glBlendFunc, "glBlendFunc" }, { (void**)&self->glGenTextures, "glGenTextures" }, { (void**)&self->glDeleteTextures, "glDeleteTextures" }, { (void**)&self->glTexImage2D, "glTexImage2D" }, { (void**)&self->glTexSubImage2D, "glTexSubImage2D" }, { (void**)&self->glBindTexture, "glBindTexture" }, { (void**)&self->glTexParameteri, "glTexParameteri" }, { (void**)&self->glBegin, "glBegin" }, { (void**)&self->glEnd, "glEnd" }, { (void**)&self->glVertex3f, "glVertex3f" }, { (void**)&self->glColor4ub, "glColor4ub" }, { (void**)&self->glTexCoord2f, "glTexCoord2f" }, { (void**)&self->glOrtho, "glOrtho" }, { (void**)&self->glMatrixMode, "glMatrixMode" }, { (void**)&self->glPushMatrix, "glPushMatrix" }, { (void**)&self->glPopMatrix, "glPopMatrix" }, { (void**)&self->glLoadIdentity, "glLoadIdentity" }, { (void**)&self->glLoadMatrixf, "glLoadMatrixf" }, { (void**)&self->glTranslatef, "glTranslatef" }, { (void**)&self->glRotatef, "glRotatef" }, { (void**)&self->glGenBuffers, "glGenBuffers" }, { (void**)&self->glBindBuffer, "glBindBuffer" }, { (void**)&self->glDeleteBuffers, "glDeleteBuffers" }, { (void**)&self->glBufferData, "glBufferData" }, { (void**)&self->glBufferSubData, "glBufferSubData" }, { (void**)&self->glDrawArrays, "glDrawArrays" }, { (void**)&self->glEnableClientState, "glEnableClientState" }, { (void**)&self->glVertexPointer, "glVertexPointer" }, { (void**)&self->glColorPointer, "glColorPointer" }, { (void**)&self->glTexCoordPointer, "glTexCoordPointer" }, { (void**)&self->glCompileShader, "glCompileShader" }, { (void**)&self->glCreateProgram, "glCreateProgram" }, { (void**)&self->glCreateShader, "glCreateShader" }, { (void**)&self->glDeleteProgram, "glDeleteProgram" }, { (void**)&self->glDeleteShader, "glDeleteShader" }, { (void**)&self->glGetShaderiv, "glGetShaderiv" }, { (void**)&self->glGetShaderInfoLog, "glGetShaderInfoLog" }, { (void**)&self->glGetProgramiv, "glGetProgramiv" }, { (void**)&self->glGetProgramInfoLog, "glGetProgramInfoLog" }, { (void**)&self->glLinkProgram, "glLinkProgram" }, { (void**)&self->glShaderSource, "glShaderSource" }, { (void**)&self->glUseProgram, "glUseProgram" }, { (void**)&self->glAttachShader, "glAttachShader" }, { (void**)&self->glGetUniformLocation, "glGetUniformLocation" }, { (void**)&self->glUniform1f, "glUniform1f" }, { (void**)&self->glUniform2f, "glUniform2f" }, { (void**)&self->glUniform3f, "glUniform3f" }, { (void**)&self->glUniform4f, "glUniform4f" }, { (void**)&self->glGetError, "glGetError" }, { (void**)&self->glGetString, "glGetString" }, { (void**)&self->glGetIntegerv, "glGetIntegerv" }, { (void**)&self->glPixelStorei, "glPixelStorei" }, { (void**)&self->glFlush, "glFlush" }, { (void**)&self->glFinish, "glFinish" }, { NULL, NULL } }; for(int i = 0; required_dlsym[i].func; ++i) { *required_dlsym[i].func = dlsym_print_fail(self->gl_library, required_dlsym[i].name, 1); if(!*required_dlsym[i].func) return -1; } const dlsym_assign optional_dlsym[] = { { (void**)&self->glGenerateMipmap, "glGenerateMipmap" }, { NULL, NULL } }; for(int i = 0; optional_dlsym[i].func; ++i) { *optional_dlsym[i].func = dlsym_print_fail(self->gl_library, optional_dlsym[i].name, 0); } return 0; } static int mgl_gl_load_glx(mgl_gl *self) { const dlsym_assign required_dlsym[] = { { (void**)&self->glXGetProcAddress, "glXGetProcAddress" }, { (void**)&self->glXCreateNewContext, "glXCreateNewContext" }, { (void**)&self->glXMakeContextCurrent, "glXMakeContextCurrent" }, { (void**)&self->glXDestroyContext, "glXDestroyContext" }, { (void**)&self->glXSwapBuffers, "glXSwapBuffers" }, { (void**)&self->glXChooseFBConfig, "glXChooseFBConfig" }, { (void**)&self->glXGetVisualFromFBConfig, "glXGetVisualFromFBConfig" }, { NULL, NULL } }; for(int i = 0; required_dlsym[i].func; ++i) { *required_dlsym[i].func = dlsym_print_fail(self->glx_library, required_dlsym[i].name, 1); if(!*required_dlsym[i].func) return -1; } self->glXSwapIntervalEXT = (FUNC_glXSwapIntervalEXT)self->glXGetProcAddress((const unsigned char*)"glXSwapIntervalEXT"); self->glXSwapIntervalMESA = (FUNC_glXSwapIntervalMESA)self->glXGetProcAddress((const unsigned char*)"glXSwapIntervalMESA"); self->glXSwapIntervalSGI = (FUNC_glXSwapIntervalSGI)self->glXGetProcAddress((const unsigned char*)"glXSwapIntervalSGI"); return 0; } static int mgl_gl_load_egl(mgl_gl *self) { const dlsym_assign required_dlsym[] = { { (void**)&self->eglGetDisplay, "eglGetDisplay" }, { (void**)&self->eglInitialize, "eglInitialize" }, { (void**)&self->eglTerminate, "eglTerminate" }, { (void**)&self->eglGetConfigs, "eglGetConfigs" }, { (void**)&self->eglCreateWindowSurface, "eglCreateWindowSurface" }, { (void**)&self->eglCreateContext, "eglCreateContext" }, { (void**)&self->eglMakeCurrent, "eglMakeCurrent" }, { (void**)&self->eglDestroyContext, "eglDestroyContext" }, { (void**)&self->eglDestroySurface, "eglDestroySurface" }, { (void**)&self->eglSwapInterval, "eglSwapInterval" }, { (void**)&self->eglSwapBuffers, "eglSwapBuffers" }, { (void**)&self->eglBindAPI, "eglBindAPI" }, { (void**)&self->eglGetConfigAttrib, "eglGetConfigAttrib" }, { NULL, NULL } }; for(int i = 0; required_dlsym[i].func; ++i) { *required_dlsym[i].func = dlsym_print_fail(self->egl_library, required_dlsym[i].name, 1); if(!*required_dlsym[i].func) return -1; } return 0; } int mgl_gl_load(mgl_gl *self) { memset(self, 0, sizeof(*self)); self->gl_library = dlopen("libGL.so.1", RTLD_LAZY); if(!self->gl_library) { fprintf(stderr, "mgl error:dlopen(\"%s\", RTLD_LAZY) failed\n", "libGL.so.1"); mgl_gl_unload(self); return -1; } self->glx_library = dlopen("libGLX.so.0", RTLD_LAZY); if(!self->glx_library) { fprintf(stderr, "mgl error:dlopen(\"%s\", RTLD_LAZY) failed\n", "libGLX.so.0"); mgl_gl_unload(self); return -1; } self->egl_library = dlopen("libEGL.so.1", RTLD_LAZY); if(!self->egl_library) { fprintf(stderr, "mgl error:dlopen(\"%s\", RTLD_LAZY) failed\n", "libEGL.so.1"); mgl_gl_unload(self); return -1; } if(mgl_gl_load_gl(self) != 0) { mgl_gl_unload(self); return -1; } if(mgl_gl_load_glx(self) != 0) { mgl_gl_unload(self); return -1; } if(mgl_gl_load_egl(self) != 0) { mgl_gl_unload(self); return -1; } return 0; } void mgl_gl_unload(mgl_gl *self) { if(self->egl_library) { dlclose(self->egl_library); self->egl_library = NULL; } if(self->glx_library) { dlclose(self->glx_library); self->glx_library = NULL; } if(self->gl_library) { dlclose(self->gl_library); self->gl_library = NULL; } }