diff mbox

[20/21] gl: Fall back to dlsym() if *GetProcAddress() fails

Message ID 1311602208-5973-20-git-send-email-alexandros.frantzis@linaro.org
State Accepted
Headers show

Commit Message

alexandros.frantzis@linaro.org July 25, 2011, 1:56 p.m. UTC
From: Alexandros Frantzis <alexandros.frantzis@linaro.org>

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>
---
 configure.ac            |   11 +++++++++
 src/cairo-gl-dispatch.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/configure.ac b/configure.ac
index 9107b3e..72caa0d 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 6277f53..344b0eb 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