aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/egl/main/eglapi.c2
-rw-r--r--src/egl/main/egldisplay.c7
-rw-r--r--src/egl/main/egldisplay.h1
-rw-r--r--src/egl/main/egldriver.c269
-rw-r--r--src/egl/main/egldriver.h15
-rw-r--r--src/egl/main/eglglobals.c8
6 files changed, 199 insertions, 103 deletions
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index e8a5b189120..464da00fe2c 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -77,7 +77,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
drv = disp->Driver;
if (!drv) {
- drv = _eglOpenDriver(disp, disp->DriverName, disp->DriverArgs);
+ drv = _eglOpenDriver(disp);
if (!drv)
return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index c684e4291ee..ba7e634c9d6 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -94,7 +94,7 @@ _eglNewDisplay(NativeDisplayType nativeDisplay)
_eglInitDisplay();
dpy->SurfaceHash = _eglSurfaceHash;
- dpy->DriverName = _eglChooseDriver(dpy);
+ dpy->DriverName = _eglPreloadDriver(dpy);
if (!dpy->DriverName) {
free(dpy);
return NULL;
@@ -244,11 +244,6 @@ _eglCleanupDisplay(_EGLDisplay *disp)
disp->Configs = NULL;
/* XXX incomplete */
-
- free((void *) disp->DriverName);
- disp->DriverName = NULL;
-
- /* driver deletes the _EGLDisplay object */
}
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 1ebc0fcb59e..78fbf5b8401 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -15,7 +15,6 @@ struct _egl_display
EGLDisplay Handle;
const char *DriverName;
- const char *DriverArgs;
_EGLDriver *Driver;
EGLint NumScreens;
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index a8ac7b3233b..36cc2948c0e 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -114,11 +114,12 @@ _eglChooseDRMDriver(int card)
#endif
}
+
/**
* XXX this function is totally subject change!!!
*
*
- * Determine/return the name of the driver to use for the given _EGLDisplay.
+ * Determine/return the path of the driver to use for the given native display.
*
* Try to be clever and determine if nativeDisplay is an Xlib Display
* ptr or a string (naming a driver or screen number, etc).
@@ -128,89 +129,69 @@ _eglChooseDRMDriver(int card)
* Else if the first character is '!' we interpret it as specific driver name
* (i.e. "!r200" or "!i830".
*
- * Whatever follows ':' is copied and put into dpy->DriverArgs.
+ * Whatever follows ':' is interpreted as arguments.
*
- * The caller may free() the returned string.
+ * The caller may free() the returned strings.
*/
-const char *
-_eglChooseDriver(_EGLDisplay *dpy)
+static char *
+_eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
{
- /* Under Windows, the NativeDisplay is an HDC handle, therefore */
- /* it can't be interpreted as a string or a pointer. */
-#if defined(_EGL_PLATFORM_WINDOWS)
- const char *displayString = NULL;
-#else
- const char *displayString = (const char *) dpy->NativeDisplay;
-#endif
- const char *driverName = NULL;
+ char *path = NULL;
+ const char *args = NULL;
- (void) DefaultDriverName;
+ path = getenv("EGL_DRIVER");
+ if (path)
+ path = _eglstrdup(path);
#if defined(_EGL_PLATFORM_X)
- /* First, if the EGL_DRIVER env var is set, use that */
- driverName = getenv("EGL_DRIVER");
- if (driverName)
- return _eglstrdup(driverName);
-#endif
+ (void) DefaultDriverName;
-#if 0
- if (!displayString) {
- /* choose a default */
- displayString = DefaultDriverName;
- }
-#endif
- /* extract default DriverArgs = whatever follows ':' */
- if (displayString &&
- (displayString[0] == '!' ||
- displayString[0] == ':')) {
- const char *args = strchr(displayString, ':');
- if (args)
- dpy->DriverArgs = _eglstrdup(args + 1);
- }
+ if (!path && dpy->NativeDisplay) {
+ const char *dpyString = (const char *) dpy->NativeDisplay;
+ char *p;
+ /* parse the display string */
+ if (dpyString[0] == '!' || dpyString[0] == ':') {
+ if (dpyString[0] == '!') {
+ path = _eglstrdup(dpyString);
+ p = strchr(path, ':');
+ if (p)
+ *p++ = '\0';
+ } else {
+ p = strchr(dpyString, ':');
+ if (p)
+ p++;
+ }
- /* determine driver name now */
- if (displayString && displayString[0] == ':' &&
- (displayString[1] >= '0' && displayString[1] <= '9') &&
- !displayString[2]) {
- int card = atoi(displayString + 1);
- driverName = _eglChooseDRMDriver(card);
- }
- else if (displayString && displayString[0] == '!') {
- /* use user-specified driver name */
- driverName = _eglstrdup(displayString + 1);
- /* truncate driverName at ':' if present */
- {
- char *args = strchr(driverName, ':');
- if (args) {
- *args = 0;
+ if (p) {
+ if (!path && p[0] >= '0' && p[0] <= '9' && !p[1]) {
+ int card = atoi(p);
+ path = (char *) _eglChooseDRMDriver(card);
+ }
+ args = p;
}
}
+ else {
+ path = (char *) _xeglChooseDriver(dpy);
+ }
}
- else
- {
- /* NativeDisplay is not a string! */
-#if defined(_EGL_PLATFORM_X)
- driverName = _xeglChooseDriver(dpy);
-#else
- driverName = DefaultDriverName;
-#endif
- }
+#elif defined(_EGL_PLATFORM_WINDOWS)
+ if (!path)
+ path = _eglstrdup(DefaultDriverName);
+#endif /* _EGL_PLATFORM_X */
- return driverName;
+ if (path && argsRet)
+ *argsRet = (args) ? _eglstrdup(args) : NULL;
+
+ return path;
}
/**
- * Open/load the named driver and call its bootstrap function: _eglMain().
- * By the time this function is called, the dpy->DriverName should have
- * been determined.
- *
- * \return new _EGLDriver object.
+ * Open the named driver and find its bootstrap function: _eglMain().
*/
-_EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args)
+static _EGLMain_t
+_eglOpenLibrary(const char *driverName, lib_handle *handle)
{
- _EGLDriver *drv;
_EGLMain_t mainFunc;
lib_handle lib;
char driverFilename[1000];
@@ -249,58 +230,170 @@ _eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args)
if (!mainFunc) {
_eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
- close_library(lib);
+ if (lib)
+ close_library(lib);
return NULL;
}
+ *handle = lib;
+ return mainFunc;
+}
+
+
+/**
+ * Load the named driver. The path and args passed will be
+ * owned by the driver and freed.
+ */
+static _EGLDriver *
+_eglLoadDriver(_EGLDisplay *dpy, char *path, char *args)
+{
+ _EGLMain_t mainFunc;
+ lib_handle lib;
+ _EGLDriver *drv = NULL;
+
+ mainFunc = _eglOpenLibrary(path, &lib);
+ if (!mainFunc)
+ return NULL;
+
drv = mainFunc(dpy, args);
if (!drv) {
- close_library(lib);
+ if (lib)
+ close_library(lib);
return NULL;
}
- /* with a recurvise open you want the inner most handle */
- if (!drv->LibHandle) {
- drv->LibHandle = lib;
+ if (!drv->Name) {
+ _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path);
+ drv->Name = "UNNAMED";
}
- else {
- close_library(lib);
+
+ drv->Path = path;
+ drv->Args = args;
+ drv->LibHandle = lib;
+
+ return drv;
+}
+
+
+/**
+ * Match a display to a preloaded driver.
+ */
+static _EGLDriver *
+_eglMatchDriver(_EGLDisplay *dpy)
+{
+ _EGLDriver *defaultDriver = NULL;
+ EGLint i;
+
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ _EGLDriver *drv = _eglGlobal.Drivers[i];
+
+ /* display specifies a driver */
+ if (dpy->DriverName) {
+ if (strcmp(dpy->DriverName, drv->Name) == 0)
+ return drv;
+ }
+ else if (drv->Probe) {
+ if (drv->Probe(drv, dpy))
+ return drv;
+ }
+ else {
+ if (!defaultDriver)
+ defaultDriver = drv;
+ }
}
+ return defaultDriver;
+}
+
+
+/**
+ * Load a driver and save it.
+ */
+const char *
+_eglPreloadDriver(_EGLDisplay *dpy)
+{
+ char *path, *args;
+ _EGLDriver *drv;
+ EGLint i;
+
+ path = _eglChooseDriver(dpy, &args);
+ if (!path)
+ return NULL;
+
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ drv = _eglGlobal.Drivers[i];
+ if (strcmp(drv->Path, path) == 0) {
+ _eglLog(_EGL_DEBUG, "Driver %s is already preloaded",
+ drv->Name);
+ free(path);
+ if (args)
+ free(args);
+ return drv->Name;
+ }
+ }
+
+ drv = _eglLoadDriver(dpy, path, args);
+ if (!drv)
+ return NULL;
+
/* update the global notion of supported APIs */
_eglGlobal.ClientAPIsMask |= drv->ClientAPIsMask;
- _eglSaveDriver(drv);
+ _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+ return drv->Name;
+}
+
+
+/**
+ * Open a preloaded driver.
+ */
+_EGLDriver *
+_eglOpenDriver(_EGLDisplay *dpy)
+{
+ _EGLDriver *drv = _eglMatchDriver(dpy);
return drv;
}
+/**
+ * Close a preloaded driver.
+ */
EGLBoolean
_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy)
{
- void *handle = drv->LibHandle;
- EGLBoolean b;
-
- _eglLog(_EGL_DEBUG, "Closing %s", drv->Name);
-
_eglReleaseDisplayResources(drv, dpy);
-
- b = drv->API.Terminate(drv, dpy);
-
- close_library(handle);
-
- return b;
+ drv->API.Terminate(drv, dpy);
+ return EGL_TRUE;
}
/**
- * Save the given driver pointer in the list of all known drivers.
+ * Unload preloaded drivers.
*/
void
-_eglSaveDriver(_EGLDriver *drv)
+_eglUnloadDrivers(void)
{
- _eglGlobal.Drivers[ _eglGlobal.NumDrivers++ ] = drv;
+ EGLint i;
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ _EGLDriver *drv = _eglGlobal.Drivers[i];
+ lib_handle handle = drv->LibHandle;
+
+ if (drv->Path)
+ free((char *) drv->Path);
+ if (drv->Args)
+ free((char *) drv->Args);
+
+ /* destroy driver */
+ if (drv->Unload)
+ drv->Unload(drv);
+
+ if (handle)
+ close_library(handle);
+ _eglGlobal.Drivers[i] = NULL;
+ }
+
+ _eglGlobal.NumDrivers = 0;
}
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
index d97a24db1d5..430c0949d44 100644
--- a/src/egl/main/egldriver.h
+++ b/src/egl/main/egldriver.h
@@ -27,8 +27,14 @@ struct _egl_driver
EGLBoolean Initialized; /**< set by driver after initialized */
void *LibHandle; /**< dlopen handle */
+ const char *Path; /**< path to this driver */
+ const char *Args; /**< args to load this driver */
const char *Name; /**< name of this driver */
+ /**< probe a display to see if it is supported */
+ EGLBoolean (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy);
+ /**< called before dlclose to release this driver */
+ void (*Unload)(_EGLDriver *drv);
int APImajor, APIminor; /**< as returned by eglInitialize() */
char Version[1000]; /**< initialized from APImajor/minor, Name */
@@ -50,20 +56,21 @@ extern _EGLDriver *_eglMain(_EGLDisplay *dpy, const char *args);
extern const char *
_eglChooseDRMDriver(int card);
+
extern const char *
-_eglChooseDriver(_EGLDisplay *dpy);
+_eglPreloadDriver(_EGLDisplay *dpy);
extern _EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args);
+_eglOpenDriver(_EGLDisplay *dpy);
extern EGLBoolean
_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy);
-extern void
-_eglSaveDriver(_EGLDriver *drv);
+void
+_eglUnloadDrivers(void);
extern _EGLDriver *
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
index e93b48e03b8..a532f142b7e 100644
--- a/src/egl/main/eglglobals.c
+++ b/src/egl/main/eglglobals.c
@@ -1,7 +1,7 @@
#include <stdlib.h>
#include <assert.h>
#include "eglglobals.h"
-#include "egldisplay.h"
+#include "egldriver.h"
#include "egllog.h"
#include "eglmutex.h"
@@ -18,8 +18,10 @@ struct _egl_global _eglGlobal =
{ 0x0 }, /* ClientAPIs */
0, /* NumDrivers */
{ NULL }, /* Drivers */
- 0, /* NumAtExitCalls */
- { NULL }, /* AtExitCalls */
+ 1, /* NumAtExitCalls */
+ { /* AtExitCalls */
+ _eglUnloadDrivers
+ },
};