From 218381d92755fa080bbb5635c0c4ed6d5296b79c Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 30 Jan 2011 05:09:06 +0800 Subject: [PATCH] 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. --- src/egl/drivers/dri2/Makefile | 4 ++++ src/egl/drivers/dri2/egl_dri2.c | 33 +++++++++++++++++++++++---------- 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; } -- 2.30.2