summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/egl/drivers/dri2/Makefile2
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c60
2 files changed, 46 insertions, 16 deletions
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 8a3c9b6a0a..ec4d1bcd9b 100644
--- a/src/egl/drivers/dri2/Makefile
+++ b/src/egl/drivers/dri2/Makefile
@@ -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
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 7592984c99..5223298020 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -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;
}