gl: Try harder to load symbols from the correct place
authorSebastian Dröge <sebastian@centricular.com>
Thu, 1 May 2014 12:36:54 +0000 (14:36 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:38 +0000 (19:31 +0000)
This commit makes the loading of the GModules threadsafe, and
always first tries to load the symbol for the GL library that
is selected for the current context. Only then it falls back
to looking into the current module (NULL), and only as a last
resort the context specific function (e.g. eglGetProcAddress())
is called.

Also add configure parameters to select the names of the library
modules instead of using the defaults, and let the defaults be
independent of the G_MODULE_SUFFIX.

https://bugzilla.gnome.org/show_bug.cgi?id=728753

gst-libs/gst/gl/egl/gstglcontext_egl.c
gst-libs/gst/gl/gstglcontext.c
gst-libs/gst/gl/win32/gstglcontext_wgl.c
gst-libs/gst/gl/x11/gstglcontext_glx.c

index f9a570d..06e7a9b 100644 (file)
@@ -22,6 +22,8 @@
 #include "config.h"
 #endif
 
+#include <gmodule.h>
+
 /* FIXME: Sharing contexts requires the EGLDisplay to be the same
  * may need to box it.
  */
@@ -478,22 +480,48 @@ gst_gl_context_egl_get_gl_platform (GstGLContext * context)
   return GST_GL_PLATFORM_EGL;
 }
 
+static GModule *module_egl;
+
+static gpointer
+load_egl_module (gpointer user_data)
+{
+#ifdef GST_GL_LIBEGL_MODULE_NAME
+  module_egl = g_module_open (GST_GL_LIBEGL_MODULE_NAME, G_MODULE_BIND_LAZY);
+#else
+  /* This automatically handles the suffix and even .la files */
+  module_egl = g_module_open ("libEGL", G_MODULE_BIND_LAZY);
+
+  /* On Linux the .so is only in -dev packages, try with a real soname
+   * Proper compilers will optimize away the strcmp */
+  if (!module_egl && strcmp (G_MODULE_SUFFIX, "so") == 0)
+    module_egl = g_module_open ("libEGL.so.1", G_MODULE_BIND_LAZY);
+#endif
+
+  return NULL;
+}
+
 static gpointer
 gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name)
 {
   gpointer result = NULL;
+  static GOnce g_once = G_ONCE_INIT;
+
+  result = gst_gl_context_default_get_proc_address (context, name);
+
+  g_once (&g_once, load_egl_module, NULL);
+
+  if (!result && module_egl) {
+    g_module_symbol (module_egl, name, &result);
+  }
 
   /* FIXME: On Android this returns wrong addresses for non-EGL functions */
 #if GST_GL_HAVE_WINDOW_ANDROID
-  if (!(result = gst_gl_context_default_get_proc_address (context, name))) {
-    if (g_str_has_prefix (name, "egl"))
-      result = eglGetProcAddress (name);
-  }
+  if (!result && g_str_has_prefix (name, "egl")) {
 #else
-  if (!(result = eglGetProcAddress (name))) {
-    result = gst_gl_context_default_get_proc_address (context, name);
-  }
+  if (!result) {
+    result = eglGetProcAddress (name);
 #endif
+  }
 
   return result;
 }
index 2b397f9..8b5ab29 100644 (file)
 #define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2)
 #define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3)
 
+static GModule *module_self;
+
+#if GST_GL_HAVE_OPENGL
+static GOnce module_opengl_gonce = G_ONCE_INIT;
+static GModule *module_opengl;
+
+static gpointer
+load_opengl_module (gpointer user_data)
+{
+#ifdef GST_GL_LIBGL_MODULE_NAME
+  module_opengl = g_module_open (GST_GL_LIBGL_MODULE_NAME, G_MODULE_BIND_LAZY);
+#else
+  /* This automatically handles the suffix and even .la files */
+  module_opengl = g_module_open ("libGL", G_MODULE_BIND_LAZY);
+
+  /* On Linux the .so is only in -dev packages, try with a real soname
+   * Proper compilers will optimize away the strcmp */
+  if (!module_opengl && strcmp (G_MODULE_SUFFIX, "so") == 0)
+    module_opengl = g_module_open ("libGL.so.1", G_MODULE_BIND_LAZY);
+#endif
+
+  return NULL;
+}
+#endif
+
+#if GST_GL_HAVE_GLES2
+static GOnce module_gles2_gonce = G_ONCE_INIT;
+static GModule *module_gles2;
+
+static gpointer
+load_gles2_module (gpointer user_data)
+{
+#ifdef GST_GL_LIBGLESV2_MODULE_NAME
+  module_gles2 =
+      g_module_open (GST_GL_LIBGLESV2_MODULE_NAME, G_MODULE_BIND_LAZY);
+#else
+  /* This automatically handles the suffix and even .la files */
+  module_gles2 = g_module_open ("libGLESv2", G_MODULE_BIND_LAZY);
+
+  /* On Linux the .so is only in -dev packages, try with a real soname
+   * Proper compilers will optimize away the strcmp */
+  if (!module_gles2 && strcmp (G_MODULE_SUFFIX, "so") == 0)
+    module_gles2 = g_module_open ("libGLESv2.so.2", G_MODULE_BIND_LAZY);
+#endif
+
+  return NULL;
+}
+#endif
+
+#if GST_GL_HAVE_GLES3
+#error "Add module loading support for GLES3"
+#endif
+
 #define GST_CAT_DEFAULT gst_gl_context_debug
 GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
 
@@ -98,7 +151,6 @@ struct _GstGLContextPrivate
   gboolean alive;
 
   GstGLContext *other_context;
-  GstGLAPI gl_api;
   GError **error;
 
   gint gl_major;
@@ -171,6 +223,8 @@ gst_gl_context_class_init (GstGLContextClass * klass)
 {
   g_type_class_add_private (klass, sizeof (GstGLContextPrivate));
 
+  module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
+
   klass->get_proc_address =
       GST_DEBUG_FUNCPTR (gst_gl_context_default_get_proc_address);
 
@@ -412,46 +466,28 @@ gst_gl_context_default_get_proc_address (GstGLContext * context,
     const gchar * name)
 {
   gpointer ret = NULL;
-  static GModule *module = NULL;
-
-#if GST_GL_HAVE_PLATFORM_EGL
-  static GModule *module_egl = NULL;
-
-  if (!module_egl) {
-    module_egl = g_module_open ("libEGL.so.1", G_MODULE_BIND_LAZY);
-
-    /* fallback */
-    if (!module_egl)
-      module_egl = g_module_open (NULL, G_MODULE_BIND_LAZY);
-  }
-
-  if (module_egl) {
-    if (!g_module_symbol (module_egl, name, &ret)) {
-      ret = NULL;
-    }
-  }
+  GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
 
-  if (ret)
-    return ret;
-#endif
-
-  if (!module) {
-    const gchar *name = NULL;
+  /* First try to load symbol from the selected GL API for this context */
 #if GST_GL_HAVE_GLES2
-    name = "libGLESv2.so.2";
+  if (!ret && (gl_api & GST_GL_API_GLES2)) {
+    g_once (&module_gles2_gonce, load_gles2_module, NULL);
+    if (module_gles2)
+      g_module_symbol (module_gles2, name, &ret);
+  }
 #endif
-    module = g_module_open (name, G_MODULE_BIND_LAZY);
 
-    /* fallback */
-    if (!module)
-      module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+#if GST_GL_HAVE_OPENGL
+  if (!ret && (gl_api & (GST_GL_API_OPENGL | GST_GL_API_OPENGL3))) {
+    g_once (&module_opengl_gonce, load_opengl_module, NULL);
+    if (module_opengl)
+      g_module_symbol (module_opengl, name, &ret);
   }
+#endif
 
-  if (module) {
-    if (!g_module_symbol (module, name, &ret)) {
-      return NULL;
-    }
-  }
+  /* Otherwise fall back to the current module */
+  if (!ret)
+    g_module_symbol (module_self, name, &ret);
 
   return ret;
 }
index e237006..4886e9a 100644 (file)
@@ -290,8 +290,8 @@ gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name)
 {
   gpointer result;
 
-  if (!(result = wglGetProcAddress ((LPCSTR) name))) {
-    result = gst_gl_context_default_get_proc_address (context, name);
+  if (!(result = gst_gl_context_default_get_proc_address (context, name))) {
+    result = wglGetProcAddress ((LPCSTR) name);
   }
 
   return result;
index 22e79ef..7487faf 100644 (file)
@@ -421,8 +421,8 @@ gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name)
 {
   gpointer result;
 
-  if (!(result = glXGetProcAddressARB ((const GLubyte *) name))) {
-    result = gst_gl_context_default_get_proc_address (context, name);
+  if (!(result = gst_gl_context_default_get_proc_address (context, name))) {
+    result = glXGetProcAddressARB ((const GLubyte *) name);
   }
 
   return result;