From d5d1b16447e7fc83c5af54c2222fbabe579efd32 Mon Sep 17 00:00:00 2001 From: kub Date: Thu, 22 May 2025 22:10:12 +0200 Subject: [PATCH] make gl libraries dynamically loadable --- gl.c | 6 ++- gl_loader.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ gl_loader.h | 75 +++++++++++++++++++++++++++++ gl_platform.c | 8 +++- 4 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 gl_loader.c create mode 100644 gl_loader.h diff --git a/gl.c b/gl.c index 4040b7e..bf40acc 100644 --- a/gl.c +++ b/gl.c @@ -5,6 +5,7 @@ #include #include +#include "gl_loader.h" #include "gl_platform.h" #include "gl.h" @@ -56,7 +57,7 @@ int gl_init(void *display, void *window, int *quirks, int w, int h) ret = gl_platform_init(&display, &window, quirks); if (ret != 0) { fprintf(stderr, "gl_platform_init failed with %d\n", ret); - goto out; + return retval; } flip_old_w = flip_old_h = 0; @@ -251,6 +252,9 @@ void gl_clear(void) void gl_finish(void) { + if (edpy == EGL_NO_DISPLAY) + return; // nothing to do + // sometimes there is an error... from somewhere? //gl_have_error("finish"); glGetError(); diff --git a/gl_loader.c b/gl_loader.c new file mode 100644 index 0000000..efc6589 --- /dev/null +++ b/gl_loader.c @@ -0,0 +1,129 @@ +#include +#include +//#include "gl_loader.h" + +#include +#include + +#if defined(__linux__) + +static void *libegl; +static void *libgles; + +#define FPTR(f) typeof(f) * p##f +FPTR(eglGetError); +FPTR(eglBindAPI); +FPTR(eglGetDisplay); +FPTR(eglInitialize); +FPTR(eglChooseConfig); +FPTR(eglCreateWindowSurface); +FPTR(eglSwapInterval); +FPTR(eglCreateContext); +FPTR(eglMakeCurrent); +FPTR(eglSwapBuffers); +FPTR(eglDestroyContext); +FPTR(eglDestroySurface); +FPTR(eglTerminate); + +FPTR(glGetError); +FPTR(glGetString); +FPTR(glEnableClientState); +FPTR(glEnable); +FPTR(glGenTextures); +FPTR(glDeleteTextures); +FPTR(glBindTexture); +FPTR(glTexImage2D); +FPTR(glTexParameterf); +FPTR(glTexSubImage2D); +FPTR(glTexCoordPointer); +FPTR(glVertexPointer); +FPTR(glDrawArrays); +FPTR(glLoadIdentity); +FPTR(glClearColor); +FPTR(glClear); +FPTR(glFrontFace); + + +void gl_unload(void) +{ + if (libegl) + dlclose(libegl); + libegl = NULL; + if (libgles) + dlclose(libgles); + libgles = NULL; +} + +#define LOADSYM(l,n) p##n = dlsym(l,#n); if (!p##n) goto err; + +int gl_load(void) +{ + // possible library file name. Some systems have them versioned, others + // don't, old-style brcm naming on Raspberry Pi systems. + char *egl[] = { "libEGL.so.1", "libEGL.so", "libbrcmEGL.so", NULL }; + char *gles[] = { "libGLESv1_CM.so.1", "libGLESv1_CM.so", "libGLES_CM.so.1", + "libGLES_CM.so", "libbrcmGLESv2.so", "libGLESv2.so", NULL }; + int i; + + for (i = 0, libegl = NULL; egl[i] && !libegl; i++) + libegl = dlopen(egl[i], RTLD_LAZY); + if (!libegl) + goto err; + + LOADSYM(libegl, eglGetError); + LOADSYM(libegl, eglBindAPI); + LOADSYM(libegl, eglGetDisplay); + LOADSYM(libegl, eglInitialize); + LOADSYM(libegl, eglChooseConfig); + LOADSYM(libegl, eglCreateWindowSurface); + LOADSYM(libegl, eglSwapInterval); + LOADSYM(libegl, eglCreateContext); + LOADSYM(libegl, eglMakeCurrent); + LOADSYM(libegl, eglSwapBuffers); + LOADSYM(libegl, eglDestroyContext); + LOADSYM(libegl, eglDestroySurface); + LOADSYM(libegl, eglTerminate); + + for (i = 0, libgles = NULL; gles[i] && !libgles; i++) + libgles = dlopen(gles[i], RTLD_LAZY); + if (!libgles) + goto err; + + LOADSYM(libgles, glGetError); + LOADSYM(libgles, glGetString); + LOADSYM(libgles, glEnableClientState); + LOADSYM(libgles, glEnable); + LOADSYM(libgles, glGenTextures); + LOADSYM(libgles, glDeleteTextures); + LOADSYM(libgles, glBindTexture); + LOADSYM(libgles, glTexImage2D); + LOADSYM(libgles, glTexParameterf); + LOADSYM(libgles, glTexSubImage2D); + LOADSYM(libgles, glTexCoordPointer); + LOADSYM(libgles, glVertexPointer); + LOADSYM(libgles, glDrawArrays); + LOADSYM(libgles, glLoadIdentity); + LOADSYM(libgles, glClearColor); + LOADSYM(libgles, glClear); + LOADSYM(libgles, glFrontFace); + + return 0; + +err: + fprintf(stderr, "warning: OpenGLES libraries are not available\n"); + gl_unload(); + return 1; +} + +#else + +void gl_unload(void) +{ +} + +int gl_load(void) +{ + return 0; +} + +#endif diff --git a/gl_loader.h b/gl_loader.h new file mode 100644 index 0000000..60ba9f8 --- /dev/null +++ b/gl_loader.h @@ -0,0 +1,75 @@ +#if defined(__linux__) + +int gl_load(void); +void gl_unload(void); + + +#define FPTR(f) typeof(f) * p##f +extern FPTR(eglGetError); +extern FPTR(eglBindAPI); +extern FPTR(eglGetDisplay); +extern FPTR(eglInitialize); +extern FPTR(eglChooseConfig); +extern FPTR(eglCreateWindowSurface); +extern FPTR(eglSwapInterval); +extern FPTR(eglCreateContext); +extern FPTR(eglMakeCurrent); +extern FPTR(eglSwapBuffers); +extern FPTR(eglDestroyContext); +extern FPTR(eglDestroySurface); +extern FPTR(eglTerminate); + +extern FPTR(glGetError); +extern FPTR(glGetString); +extern FPTR(glEnableClientState); +extern FPTR(glEnable); +extern FPTR(glGenTextures); +extern FPTR(glDeleteTextures); +extern FPTR(glBindTexture); +extern FPTR(glTexImage2D); +extern FPTR(glTexParameterf); +extern FPTR(glTexSubImage2D); +extern FPTR(glTexCoordPointer); +extern FPTR(glVertexPointer); +extern FPTR(glDrawArrays); +extern FPTR(glLoadIdentity); +extern FPTR(glClearColor); +extern FPTR(glClear); +extern FPTR(glFrontFace); +#undef FPTR + + +#define eglGetError peglGetError +#define eglBindAPI peglBindAPI +#define eglGetDisplay peglGetDisplay +#define eglInitialize peglInitialize +#define eglChooseConfig peglChooseConfig +#define eglCreateWindowSurface peglCreateWindowSurface +#define eglSwapInterval peglSwapInterval +#define eglCreateContext peglCreateContext +#define eglMakeCurrent peglMakeCurrent +#define eglSwapBuffers peglSwapBuffers +#define eglDestroyContext peglDestroyContext +#define eglDestroySurface peglDestroySurface +#define eglTerminate peglTerminate + +#define glGetError pglGetError +#define glGetString pglGetString +#define glLoadIdentity pglLoadIdentity +#define glEnableClientState pglEnableClientState +#define glEnable pglEnable +#define glGenTextures pglGenTextures +#define glDeleteTextures pglDeleteTextures +#define glBindTexture pglBindTexture +#define glTexImage2D pglTexImage2D +#define glTexParameterf pglTexParameterf +#define glTexSubImage2D pglTexSubImage2D +#define glTexCoordPointer pglTexCoordPointer +#define glVertexPointer pglVertexPointer +#define glDrawArrays pglDrawArrays +#define glLoadIdentity pglLoadIdentity +#define glClearColor pglClearColor +#define glClear pglClear +#define glFrontFace pglFrontFace + +#endif diff --git a/gl_platform.c b/gl_platform.c index d5f0c20..2540949 100644 --- a/gl_platform.c +++ b/gl_platform.c @@ -3,6 +3,7 @@ #include #include +#include "gl_loader.h" #include "gl.h" #include "gl_platform.h" @@ -117,11 +118,13 @@ int gl_platform_init(void **display, void **window, int *quirks) *window = &m_nativeWindow; *quirks |= GL_QUIRK_ACTIVATE_RECREATE; - return 0; + return gl_load(); } void gl_platform_finish(void) { + gl_unload(); + vc_dispmanx_display_close(m_dispmanDisplay); bcm_host_deinit(); @@ -138,11 +141,12 @@ void gl_platform_finish(void) int gl_platform_init(void **display, void **window, int *quirks) { - return 0; + return gl_load(); } void gl_platform_finish(void) { + gl_unload(); } #endif -- 2.39.5