summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandros Frantzis <alexandros.frantzis@linaro.org>2011-03-21 16:12:00 +0200
committerChris Wilson <chris@chris-wilson.co.uk>2011-05-10 08:36:03 +0100
commitc2b4bc6dead3e1fd0aacd9d767a299259f895e4d (patch)
treeccf94236334b3e7c29f491148d0a05f5a8bdb1eb
parent2001d2074723c64b1e5a6cb4c550d6a0a8cea812 (diff)
gl: Fall back to dlsym() if *GetProcAddress() fails
In strictly conforming EGL implementations, eglGetProcAddress() can be used only to get extension functions, but some of the functions we want belong to core GL(ES). If the *GetProcAddress function provided by the context fails, try to get the address of the wanted GL function using standard system facilities (eg dlsym() in *nix systems). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--configure.ac11
-rw-r--r--src/cairo-gl-dispatch.c54
2 files changed, 65 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 9107b3e3..72caa0dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,9 @@ if test "x$have_dlsym" = "xno"; then
fi
AC_CHECK_HEADERS(dlfcn.h, [have_dlsym=yes], [have_dlsym=no])
AM_CONDITIONAL(CAIRO_HAS_DL, test "x$have_dl" = "xyes")
+if test "x$have_dlsym" = "xyes"; then
+ AC_DEFINE([CAIRO_HAS_DLSYM], 1, [Define to 1 if dlsym is available])
+fi
dnl ===========================================================================
@@ -317,6 +320,10 @@ CAIRO_ENABLE_SURFACE_BACKEND(gl, OpenGL, no, [
gl_NONPKGCONFIG_LIBS="-lGL"
fi])
+ if test "x$have_dl" = "xyes" -a "x$have_dlsym" = "xyes"; then
+ gl_LIBS="$gl_LIBS -ldl"
+ fi
+
need_glx_functions=yes
need_wgl_functions=yes
need_egl_functions=yes
@@ -333,6 +340,10 @@ CAIRO_ENABLE_SURFACE_BACKEND(glesv2, OpenGLESv2, no, [
glesv2_NONPKGCONFIG_LIBS="-lGLESv2"
fi])
+ if test "x$have_dl" = "xyes" -a "x$have_dlsym" = "xyes"; then
+ glesv2_LIBS="$glesv2_LIBS -ldl"
+ fi
+
need_egl_functions=yes
])
diff --git a/src/cairo-gl-dispatch.c b/src/cairo-gl-dispatch.c
index 6277f53d..344b0ebb 100644
--- a/src/cairo-gl-dispatch.c
+++ b/src/cairo-gl-dispatch.c
@@ -32,6 +32,48 @@
#include "cairoint.h"
#include "cairo-gl-private.h"
#include "cairo-gl-dispatch-private.h"
+#if CAIRO_HAS_DLSYM
+#include <dlfcn.h>
+#endif
+
+#if CAIRO_HAS_DLSYM
+static void *
+_cairo_gl_dispatch_open_lib (void)
+{
+ return dlopen (NULL, RTLD_LAZY);
+}
+
+static void
+_cairo_gl_dispatch_close_lib (void *handle)
+{
+ dlclose (handle);
+}
+
+static cairo_gl_generic_func_t
+_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name)
+{
+ return (cairo_gl_generic_func_t) dlsym (handle, name);
+}
+#else
+static void *
+_cairo_gl_dispatch_open_lib (void)
+{
+ return NULL;
+}
+
+static void
+_cairo_gl_dispatch_close_lib (void *handle)
+{
+ return;
+}
+
+static cairo_gl_generic_func_t
+_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name)
+{
+ return NULL;
+}
+#endif /* CAIRO_HAS_DLSYM */
+
static void
_cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch,
@@ -40,18 +82,30 @@ _cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch,
cairo_gl_dispatch_name_t dispatch_name)
{
cairo_gl_dispatch_entry_t *entry = entries;
+ void *handle = _cairo_gl_dispatch_open_lib ();
while (entry->name[CAIRO_GL_DISPATCH_NAME_CORE] != NULL) {
void *dispatch_ptr = &((char *) dispatch)[entry->offset];
const char *name = entry->name[dispatch_name];
+ /*
+ * In strictly conforming EGL implementations, eglGetProcAddress() can
+ * be used only to get extension functions, but some of the functions
+ * we want belong to core GL(ES). If the *GetProcAddress function
+ * provided by the context fails, try to get the address of the wanted
+ * GL function using standard system facilities (eg dlsym() in *nix
+ * systems).
+ */
cairo_gl_generic_func_t func = get_proc_addr (name);
+ if (func == NULL)
+ func = _cairo_gl_dispatch_get_proc_addr (handle, name);
*((cairo_gl_generic_func_t *) dispatch_ptr) = func;
++entry;
}
+ _cairo_gl_dispatch_close_lib (handle);
}
static cairo_status_t