diff options
-rw-r--r-- | src/egl/main/eglapi.c | 2 | ||||
-rw-r--r-- | src/egl/main/egldisplay.c | 7 | ||||
-rw-r--r-- | src/egl/main/egldisplay.h | 1 | ||||
-rw-r--r-- | src/egl/main/egldriver.c | 269 | ||||
-rw-r--r-- | src/egl/main/egldriver.h | 15 | ||||
-rw-r--r-- | src/egl/main/eglglobals.c | 8 |
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 + }, }; |