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
This commit is contained in:
Sebastian Dröge 2014-05-01 14:36:54 +02:00
parent 5681f78362
commit cad1bb32c8
5 changed files with 128 additions and 46 deletions

View file

@ -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

View 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;
}

View file

@ -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;
}

View 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;

View 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;