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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user