From cad1bb32c8dc34290524e029cb27a930eb84fa78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 1 May 2014 14:36:54 +0200 Subject: [PATCH] gl: Try harder to load symbols from the correct place 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 --- configure.ac | 18 ++++ gst-libs/gst/gl/egl/gstglcontext_egl.c | 42 +++++++-- gst-libs/gst/gl/gstglcontext.c | 106 +++++++++++++++-------- gst-libs/gst/gl/win32/gstglcontext_wgl.c | 4 +- gst-libs/gst/gl/x11/gstglcontext_glx.c | 4 +- 5 files changed, 128 insertions(+), 46 deletions(-) diff --git a/configure.ac b/configure.ac index aad766c658..e73032f46e 100644 --- a/configure.ac +++ b/configure.ac @@ -527,6 +527,12 @@ AC_ARG_ENABLE([opengl], *) AC_MSG_ERROR([bad value ${enableval} for --enable-opengl]) ;; esac],[NEED_GL=auto]) +AC_ARG_WITH([opengl-module-name], + AS_HELP_STRING([--with-opengl-module-name],[library module name for OpenGL (default: libGL)])) +if test x$with_opengl_module_name != x; then + AC_DEFINE_UNQUOTED(GST_GL_LIBGL_MODULE_NAME, "$with_opengl_module_name", [OpenGL module name]) +fi + AC_ARG_ENABLE([gles2], [ --enable-gles2 Enable OpenGL|ES 2.0 support @<:@default=auto@:>@], [case "${enableval}" in @@ -536,6 +542,12 @@ AC_ARG_ENABLE([gles2], *) AC_MSG_ERROR([bad value ${enableval} for --enable-gles2]) ;; esac],[NEED_GLES2=auto]) +AC_ARG_WITH([gles2-module-name], + AS_HELP_STRING([--with-gles2-module-name],[library module name for GLES2 (default: libGLESv2)])) +if test x$with_gles2_module_name != x; then + AC_DEFINE_UNQUOTED(GST_GL_LIBGLESV2_MODULE_NAME, "$with_gles2_module_name", [GLES2 module name]) +fi + AC_ARG_ENABLE([egl], [ --enable-egl Enable EGL support @<:@default=auto@:>@], [case "${enableval}" in @@ -545,6 +557,12 @@ AC_ARG_ENABLE([egl], *) AC_MSG_ERROR([bad value ${enableval} for --enable-egl]) ;; esac],[NEED_EGL=auto]) +AC_ARG_WITH([egl-module-name], + AS_HELP_STRING([--with-egl-module-name],[library module name for EGL (default: libEGL)])) +if test x$with_egl_module_name != x; then + AC_DEFINE_UNQUOTED(GST_GL_LIBEGL_MODULE_NAME, "$with_egl_module_name", [EGL module name]) +fi + AC_ARG_ENABLE([wgl], [ --enable-wgl Enable WGL support @<:@default=auto@:>@], [case "${enableval}" in diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index f9a570d6f3..06e7a9b619 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -22,6 +22,8 @@ #include "config.h" #endif +#include + /* 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; } diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index 2b397f9ed2..8b5ab293fc 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -71,6 +71,59 @@ #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; + GstGLAPI gl_api = gst_gl_context_get_gl_api (context); -#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; - } - } - - 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; } diff --git a/gst-libs/gst/gl/win32/gstglcontext_wgl.c b/gst-libs/gst/gl/win32/gstglcontext_wgl.c index e237006f79..4886e9af52 100644 --- a/gst-libs/gst/gl/win32/gstglcontext_wgl.c +++ b/gst-libs/gst/gl/win32/gstglcontext_wgl.c @@ -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; diff --git a/gst-libs/gst/gl/x11/gstglcontext_glx.c b/gst-libs/gst/gl/x11/gstglcontext_glx.c index 22e79ef45a..7487faf6e0 100644 --- a/gst-libs/gst/gl/x11/gstglcontext_glx.c +++ b/gst-libs/gst/gl/x11/gstglcontext_glx.c @@ -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;