summaryrefslogtreecommitdiffstats
path: root/src/egl
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2011-01-30 05:09:06 +0800
committerChia-I Wu <[email protected]>2011-01-30 05:28:24 +0800
commit218381d92755fa080bbb5635c0c4ed6d5296b79c (patch)
tree9566380058c5df94f3990d758c8d9b56343cf92f /src/egl
parentf36cba6cf3d51a3937d3bb429609d258399751a0 (diff)
egl_dri2: Export glapi symbols for DRI drivers.
When an app loads libEGL.so dynamically with RTLD_LOCAL, loading DRI drivers would fail because of missing glapi symbols. This commit makes egl_dri2 load libglapi.so with RTLD_GLOBAL to export glapi symbols for future symbol resolutions. The same trick can be found in GLX. However, egl_dri2 can only do so when --enable-shared-glapi is given. Because, otherwise, both libGL.so and libglapi.so define glapi symbols and egl_dri2 cannot tell which library to load.
Diffstat (limited to 'src/egl')
-rw-r--r--src/egl/drivers/dri2/Makefile4
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c33
2 files changed, 27 insertions, 10 deletions
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 553ee8771f8..bd3d7029337 100644
--- a/src/egl/drivers/dri2/Makefile
+++ b/src/egl/drivers/dri2/Makefile
@@ -20,4 +20,8 @@ EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB)
EGL_CFLAGS = -D_EGL_MAIN=_eglBuiltInDriverDRI2
EGL_BUILTIN = true
+ifeq ($(SHARED_GLAPI),1)
+EGL_CFLAGS += -DHAVE_SHARED_GLAPI
+endif
+
include ../Makefile.template
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 6fc1e49e773..92fc9df54a8 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -62,6 +62,7 @@ struct dri2_egl_driver
{
_EGLDriver base;
+ void *handle;
_EGLProc (*get_proc_address)(const char *procname);
void (*glFlush)(void);
};
@@ -2337,6 +2338,9 @@ static void
dri2_unload(_EGLDriver *drv)
{
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+
+ if (dri2_drv->handle)
+ dlclose(dri2_drv->handle);
free(dri2_drv);
}
@@ -2344,23 +2348,30 @@ static EGLBoolean
dri2_load(_EGLDriver *drv)
{
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
+#ifdef HAVE_SHARED_GLAPI
+ const char *libname = "libglapi.so.0";
+#else
+ /*
+ * Both libGL.so and libglapi.so are glapi providers. There is no way to
+ * tell which one to load.
+ */
+ const char *libname = NULL;
+#endif
void *handle;
- handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+ /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
+ handle = dlopen(libname, 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 (!dri2_drv->get_proc_address || !libname) {
+ /* no need to keep a reference */
+ dlclose(handle);
+ handle = NULL;
+ }
}
- /*
- * 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 glapi is not available, loading DRI drivers will fail */
if (!dri2_drv->get_proc_address) {
_eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
return EGL_FALSE;
@@ -2369,6 +2380,8 @@ dri2_load(_EGLDriver *drv)
dri2_drv->glFlush = (void (*)(void))
dri2_drv->get_proc_address("glFlush");
+ dri2_drv->handle = handle;
+
return EGL_TRUE;
}