make gl libraries dynamically loadable
authorkub <derkub@gmail.com>
Thu, 22 May 2025 20:10:12 +0000 (22:10 +0200)
committerkub <derkub@gmail.com>
Thu, 22 May 2025 20:23:51 +0000 (22:23 +0200)
gl.c
gl_loader.c [new file with mode: 0644]
gl_loader.h [new file with mode: 0644]
gl_platform.c

diff --git a/gl.c b/gl.c
index 4040b7e..bf40acc 100644 (file)
--- a/gl.c
+++ b/gl.c
@@ -5,6 +5,7 @@
 
 #include <EGL/egl.h>
 #include <GLES/gl.h>
+#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 (file)
index 0000000..efc6589
--- /dev/null
@@ -0,0 +1,129 @@
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+//#include "gl_loader.h"
+
+#include <dlfcn.h>
+#include <stdio.h>
+
+#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 (file)
index 0000000..60ba9f8
--- /dev/null
@@ -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
index d5f0c20..2540949 100644 (file)
@@ -3,6 +3,7 @@
 #include <EGL/egl.h>
 #include <GLES/gl.h>
 
+#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