egl_dri2: Look up _glapi_get_proc_address dynamically.
authorChia-I Wu <olv@lunarg.com>
Fri, 7 Jan 2011 07:02:41 +0000 (15:02 +0800)
committerChia-I Wu <olv@lunarg.com>
Mon, 10 Jan 2011 03:23:24 +0000 (11:23 +0800)
In preparation for making egl_dri2 built-in.  It also handles

  symbol lookup error: /usr/local/lib/egl/egl_dri2.so: undefined symbol:
  _glapi_get_proc_address

more gracefully.

src/egl/drivers/dri2/Makefile
src/egl/drivers/dri2/egl_dri2.c

index 8a3c9b6a0aa9c7409c8b65d2a117a35f622c86be..ec4d1bcd9be38adad4b54d341e21a4ef5a134807 100644 (file)
@@ -15,6 +15,6 @@ EGL_INCLUDES = \
        $(LIBUDEV_CFLAGS) \
        $(LIBDRM_CFLAGS)
 
-EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(LIBDRM_LIBS)
+EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB)
 
 include ../Makefile.template
index 7592984c99e7a56e7a08e9bb0eb9bf41e1ef03a5..5223298020747a38e33e310bbad76c03dee7a7c8 100644 (file)
@@ -47,7 +47,6 @@
 #include <libudev.h>
 #endif
 
-#include <glapi/glapi.h>
 #include "eglconfig.h"
 #include "eglcontext.h"
 #include "egldisplay.h"
@@ -63,6 +62,7 @@ struct dri2_egl_driver
 {
    _EGLDriver base;
 
+   _EGLProc (*get_proc_address)(const char *procname);
    void (*glFlush)(void);
 };
 
@@ -1867,11 +1867,9 @@ dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
 static _EGLProc
 dri2_get_proc_address(_EGLDriver *drv, const char *procname)
 {
-   (void) drv;
-
-   /* FIXME: Do we need to support lookup of EGL symbols too? */
+   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
 
-   return (_EGLProc) _glapi_get_proc_address(procname);
+   return dri2_drv->get_proc_address(procname);
 }
 
 static EGLBoolean
@@ -1903,13 +1901,6 @@ dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
    return EGL_TRUE;
 }
 
-static void
-dri2_unload(_EGLDriver *drv)
-{
-   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
-   free(dri2_drv);
-}
-
 static EGLBoolean
 dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
                  EGLNativePixmapType target)
@@ -2337,6 +2328,45 @@ dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
    return EGL_TRUE;
 }
 
+static void
+dri2_unload(_EGLDriver *drv)
+{
+   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+   free(dri2_drv);
+}
+
+static EGLBoolean
+dri2_load(_EGLDriver *drv)
+{
+   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+   void *handle;
+
+   handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+   if (handle) {
+      dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
+         dlsym(handle, "_glapi_get_proc_address");
+      /* no need to keep a reference */
+      dlclose(handle);
+   }
+
+   /*
+    * If glapi is not available, loading DRI drivers will fail.  Ideally, we
+    * should load one of libGL, libGLESv1_CM, or libGLESv2 and go on.  But if
+    * the app has loaded another one of them with RTLD_LOCAL, there may be
+    * unexpected behaviors later because there will be two copies of glapi
+    * (with global variables of the same names!) in the memory.
+    */
+   if (!dri2_drv->get_proc_address) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
+      return EGL_FALSE;
+   }
+
+   dri2_drv->glFlush = (void (*)(void))
+      dri2_drv->get_proc_address("glFlush");
+
+   return EGL_TRUE;
+}
+
 /**
  * This is the main entrypoint into the driver, called by libEGL.
  * Create a new _EGLDriver object and init its dispatch table.
@@ -2352,6 +2382,9 @@ _eglMain(const char *args)
    if (!dri2_drv)
       return NULL;
 
+   if (!dri2_load(&dri2_drv->base))
+      return NULL;
+
    memset(dri2_drv, 0, sizeof *dri2_drv);
    _eglInitDriverFallbacks(&dri2_drv->base);
    dri2_drv->base.API.Initialize = dri2_initialize;
@@ -2378,8 +2411,5 @@ _eglMain(const char *args)
    dri2_drv->base.Name = "DRI2";
    dri2_drv->base.Unload = dri2_unload;
 
-   dri2_drv->glFlush =
-      (void (*)(void)) dri2_get_proc_address(&dri2_drv->base, "glFlush");
-
    return &dri2_drv->base;
 }