summaryrefslogtreecommitdiffstats
path: root/src/egl/main/egldriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/main/egldriver.c')
-rw-r--r--src/egl/main/egldriver.c211
1 files changed, 205 insertions, 6 deletions
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index 018b06d3bea..5d603419a8a 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -22,6 +22,8 @@
#if defined(_EGL_PLATFORM_X)
#include <dlfcn.h>
+#include <sys/types.h>
+#include <dirent.h>
#endif
@@ -49,6 +51,13 @@ close_library(HMODULE lib)
}
+static const char *
+library_suffix(void)
+{
+ return "dll";
+}
+
+
#elif defined(_EGL_PLATFORM_X)
@@ -68,6 +77,14 @@ close_library(void *lib)
dlclose(lib);
}
+
+static const char *
+library_suffix(void)
+{
+ return "so";
+}
+
+
#else /* _EGL_PLATFORM_NO_OS */
static const char DefaultDriverName[] = "builtin";
@@ -86,6 +103,13 @@ close_library(void *lib)
}
+static const char *
+library_suffix(void)
+{
+ return NULL;
+}
+
+
#endif
@@ -208,11 +232,10 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle)
/**
- * Load the named driver. The path and args passed will be
- * owned by the driver and freed.
+ * Load the named driver.
*/
static _EGLDriver *
-_eglLoadDriver(char *path, char *args)
+_eglLoadDriver(const char *path, const char *args)
{
_EGLMain_t mainFunc;
lib_handle lib;
@@ -234,8 +257,19 @@ _eglLoadDriver(char *path, char *args)
drv->Name = "UNNAMED";
}
- drv->Path = path;
- drv->Args = args;
+ drv->Path = _eglstrdup(path);
+ drv->Args = (args) ? _eglstrdup(args) : NULL;
+ if (!drv->Path || (args && !drv->Args)) {
+ if (drv->Path)
+ free((char *) drv->Path);
+ if (drv->Args)
+ free((char *) drv->Args);
+ drv->Unload(drv);
+ if (lib)
+ close_library(lib);
+ return NULL;
+ }
+
drv->LibHandle = lib;
return drv;
@@ -300,8 +334,12 @@ _eglPreloadDriver(_EGLDisplay *dpy)
}
drv = _eglLoadDriver(path, args);
- if (!drv)
+ if (!drv) {
+ free(path);
+ if (args)
+ free(args);
return NULL;
+ }
_eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
@@ -331,6 +369,167 @@ _eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy)
/**
+ * Preload a user driver.
+ *
+ * A user driver can be specified by EGL_DRIVER.
+ */
+static EGLBoolean
+_eglPreloadUserDriver(void)
+{
+#if defined(_EGL_PLATFORM_X) || defined(_EGL_PLATFORM_WINDOWS)
+ _EGLDriver *drv;
+ char *env, *path;
+ const char *suffix, *p;
+
+ env = getenv("EGL_DRIVER");
+ if (!env)
+ return EGL_FALSE;
+
+ path = env;
+ suffix = library_suffix();
+
+ /* append suffix if there isn't */
+ p = strrchr(path, '.');
+ if (!p && suffix) {
+ size_t len = strlen(path);
+ char *tmp = malloc(len + strlen(suffix) + 2);
+ if (tmp) {
+ memcpy(tmp, path, len);
+ tmp[len++] = '.';
+ tmp[len] = '\0';
+ strcat(tmp + len, suffix);
+
+ path = tmp;
+ }
+ }
+
+ drv = _eglLoadDriver(path, NULL);
+ if (path != env)
+ free(path);
+ if (!drv)
+ return EGL_FALSE;
+
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+
+ return EGL_TRUE;
+#else /* _EGL_PLATFORM_X || _EGL_PLATFORM_WINDOWS */
+ return EGL_FALSE;
+#endif
+}
+
+
+/**
+ * Preload display drivers.
+ *
+ * Display drivers are a set of drivers that support a certain display system.
+ * The display system may be specified by EGL_DISPLAY.
+ *
+ * FIXME This makes libEGL a memory hog if an user driver is not specified and
+ * there are many display drivers.
+ */
+static EGLBoolean
+_eglPreloadDisplayDrivers(void)
+{
+#if defined(_EGL_PLATFORM_X)
+ const char *dpy, *suffix;
+ char path[1024], prefix[32];
+ DIR *dirp;
+ struct dirent *dirent;
+
+ dpy = getenv("EGL_DISPLAY");
+ if (!dpy || !dpy[0])
+ dpy = _EGL_DEFAULT_DISPLAY;
+ if (!dpy || !dpy[0])
+ return EGL_FALSE;
+
+ snprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
+ suffix = library_suffix();
+
+ dirp = opendir(_EGL_DRIVER_SEARCH_DIR);
+ if (!dirp)
+ return EGL_FALSE;
+
+ while ((dirent = readdir(dirp))) {
+ _EGLDriver *drv;
+ const char *p;
+
+ /* match the prefix */
+ if (strncmp(dirent->d_name, prefix, strlen(prefix)) != 0)
+ continue;
+
+ /* match the suffix */
+ p = strrchr(dirent->d_name, '.');
+ if ((p && !suffix) || (!p && suffix))
+ continue;
+ else if (p && suffix && strcmp(p + 1, suffix) != 0)
+ continue;
+
+ snprintf(path, sizeof(path),
+ _EGL_DRIVER_SEARCH_DIR"/%s", dirent->d_name);
+
+ drv = _eglLoadDriver(path, NULL);
+ if (drv)
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+ }
+
+ closedir(dirp);
+
+ return (_eglGlobal.NumDrivers > 0);
+#else /* _EGL_PLATFORM_X */
+ return EGL_FALSE;
+#endif
+}
+
+
+/**
+ * Preload the default driver.
+ */
+static EGLBoolean
+_eglPreloadDefaultDriver(void)
+{
+ _EGLDriver *drv;
+ char path[1024];
+ const char *suffix = library_suffix();
+
+ if (suffix)
+ snprintf(path, sizeof(path), "%s.%s", DefaultDriverName, suffix);
+ else
+ snprintf(path, sizeof(path), DefaultDriverName);
+
+ drv = _eglLoadDriver(path, NULL);
+ if (!drv)
+ return EGL_FALSE;
+
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Preload drivers.
+ *
+ * This function loads the driver modules and creates the corresponding
+ * _EGLDriver objects.
+ */
+EGLBoolean
+_eglPreloadDrivers(void)
+{
+ EGLBoolean loaded;
+
+ /* already preloaded */
+ if (_eglGlobal.NumDrivers)
+ return EGL_TRUE;
+
+ loaded = (_eglPreloadUserDriver() ||
+ _eglPreloadDisplayDrivers() ||
+ _eglPreloadDefaultDriver());
+
+ return loaded;
+}
+
+
+/**
* Unload preloaded drivers.
*/
void