egl: Simplify driver matching.

Add initialization options that drv->API.Initialize should support.
Replace drv->Probe by TestOnly initialization option and simplify
_eglMatchDriver.
This commit is contained in:
Chia-I Wu
2011-01-13 00:27:45 +08:00
parent a4a38dcf61
commit 655e459892
6 changed files with 74 additions and 102 deletions

View File

@@ -1472,10 +1472,14 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
{ {
switch (disp->Platform) { switch (disp->Platform) {
case _EGL_PLATFORM_X11: case _EGL_PLATFORM_X11:
if (disp->Options.TestOnly)
return EGL_TRUE;
return dri2_initialize_x11(drv, disp); return dri2_initialize_x11(drv, disp);
#ifdef HAVE_LIBUDEV #ifdef HAVE_LIBUDEV
case _EGL_PLATFORM_DRM: case _EGL_PLATFORM_DRM:
if (disp->Options.TestOnly)
return EGL_TRUE;
return dri2_initialize_drm(drv, disp); return dri2_initialize_drm(drv, disp);
#endif #endif

View File

@@ -589,6 +589,9 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp)
if (disp->Platform != _EGL_PLATFORM_X11) if (disp->Platform != _EGL_PLATFORM_X11)
return EGL_FALSE; return EGL_FALSE;
if (disp->Options.TestOnly)
return EGL_TRUE;
GLX_dpy = CALLOC_STRUCT(GLX_egl_display); GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
if (!GLX_dpy) if (!GLX_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize"); return _eglError(EGL_BAD_ALLOC, "eglInitialize");

View File

@@ -90,6 +90,11 @@ struct _egl_display
_EGLDriver *Driver; /**< Matched driver of the display */ _EGLDriver *Driver; /**< Matched driver of the display */
EGLBoolean Initialized; /**< True if the display is initialized */ EGLBoolean Initialized; /**< True if the display is initialized */
/* options that affect how the driver initializes the display */
struct {
EGLBoolean TestOnly; /**< Driver should not set fields when true */
} Options;
/* these fields are set by the driver during init */ /* these fields are set by the driver during init */
void *DriverData; /**< Driver private data */ void *DriverData; /**< Driver private data */
EGLint VersionMajor; /**< EGL major version */ EGLint VersionMajor; /**< EGL major version */

View File

@@ -525,100 +525,75 @@ _eglAddDrivers(void)
/** /**
* Match a display to a driver. The display is initialized unless use_probe is * A helper function for _eglMatchDriver. It finds the first driver that can
* true. * initialize the display and return.
* */
* The matching is done by finding the first driver that can initialize the static _EGLDriver *
* display, or when use_probe is true, the driver with highest score. _eglMatchAndInitialize(_EGLDisplay *dpy)
{
_EGLDriver *drv = NULL;
EGLint i = 0;
if (!_eglAddDrivers()) {
_eglLog(_EGL_WARNING, "failed to find any driver");
return NULL;
}
if (dpy->Driver) {
drv = dpy->Driver;
/* no re-matching? */
if (!drv->API.Initialize(drv, dpy))
drv = NULL;
return drv;
}
while (i < _eglModules->Size) {
_EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
if (!_eglLoadModule(mod)) {
/* remove invalid modules */
_eglEraseArray(_eglModules, i, _eglFreeModule);
continue;
}
if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
drv = mod->Driver;
break;
}
else {
i++;
}
}
return drv;
}
/**
* Match a display to a driver. The display is initialized unless test_only is
* true. The matching is done by finding the first driver that can initialize
* the display.
*/ */
_EGLDriver * _EGLDriver *
_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean use_probe) _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
{ {
_EGLModule *mod; _EGLDriver *best_drv;
_EGLDriver *best_drv = NULL;
EGLint best_score = 0; assert(!dpy->Initialized);
EGLint i;
_eglLockMutex(&_eglModuleMutex); _eglLockMutex(&_eglModuleMutex);
if (!_eglAddDrivers()) { /* set options */
_eglUnlockMutex(&_eglModuleMutex); dpy->Options.TestOnly = test_only;
_eglLog(_EGL_WARNING, "failed to find any driver");
return EGL_FALSE;
}
/* match the loaded modules */ best_drv = _eglMatchAndInitialize(dpy);
for (i = 0; i < _eglModules->Size; i++) {
mod = (_EGLModule *) _eglModules->Elements[i];
if (!mod->Driver)
break;
if (use_probe) {
EGLint score = (mod->Driver->Probe) ?
mod->Driver->Probe(mod->Driver, dpy) : 1;
if (score > best_score) {
best_drv = mod->Driver;
best_score = score;
}
}
else {
if (mod->Driver->API.Initialize(mod->Driver, dpy)) {
best_drv = mod->Driver;
best_score = 100;
}
}
/* perfect match */
if (best_score >= 100)
break;
}
/* load more modules */
if (!best_drv) {
EGLint first_unloaded = i;
while (i < _eglModules->Size) {
mod = (_EGLModule *) _eglModules->Elements[i];
assert(!mod->Driver);
if (!_eglLoadModule(mod)) {
/* remove invalid modules */
_eglEraseArray(_eglModules, i, _eglFreeModule);
continue;
}
if (use_probe) {
best_score = (mod->Driver->Probe) ?
mod->Driver->Probe(mod->Driver, dpy) : 1;
}
else {
if (mod->Driver->API.Initialize(mod->Driver, dpy))
best_score = 100;
}
if (best_score > 0) {
best_drv = mod->Driver;
/* loaded modules come before unloaded ones */
if (first_unloaded != i) {
void *tmp = _eglModules->Elements[i];
_eglModules->Elements[i] =
_eglModules->Elements[first_unloaded];
_eglModules->Elements[first_unloaded] = tmp;
}
break;
}
else {
_eglUnloadModule(mod);
i++;
}
}
}
_eglUnlockMutex(&_eglModuleMutex); _eglUnlockMutex(&_eglModuleMutex);
if (best_drv) { if (best_drv) {
_eglLog(_EGL_DEBUG, "the best driver is %s (score %d)", _eglLog(_EGL_DEBUG, "the best driver is %s%s",
best_drv->Name, best_score); best_drv->Name, (test_only) ? " (test only) " : "");
if (!use_probe) { if (!test_only) {
dpy->Driver = best_drv; dpy->Driver = best_drv;
dpy->Initialized = EGL_TRUE; dpy->Initialized = EGL_TRUE;
} }

View File

@@ -43,16 +43,6 @@ struct _egl_driver
{ {
const char *Name; /**< name of this driver */ const char *Name; /**< name of this driver */
/**
* Probe a display and return a score.
*
* Roughly,
* 50 means the driver supports the display;
* 90 means the driver can accelerate the display;
* 100 means a perfect match.
*/
EGLint (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy);
/** /**
* Release the driver resource. * Release the driver resource.
* *
@@ -81,7 +71,7 @@ _eglMain(const char *args);
extern _EGLDriver * extern _EGLDriver *
_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean probe_only); _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only);
extern __eglMustCastToProperFunctionPointerType extern __eglMustCastToProperFunctionPointerType

View File

@@ -484,6 +484,9 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
if (!nplat) if (!nplat)
return EGL_FALSE; return EGL_FALSE;
if (dpy->Options.TestOnly)
return EGL_TRUE;
gdpy = CALLOC_STRUCT(egl_g3d_display); gdpy = CALLOC_STRUCT(egl_g3d_display);
if (!gdpy) { if (!gdpy) {
_eglError(EGL_BAD_ALLOC, "eglInitialize"); _eglError(EGL_BAD_ALLOC, "eglInitialize");
@@ -572,12 +575,6 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
stapi->get_proc_address(stapi, procname) : NULL); stapi->get_proc_address(stapi, procname) : NULL);
} }
static EGLint
egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy)
{
return (egl_g3d_get_platform(drv, dpy->Platform)) ? 90 : 0;
}
_EGLDriver * _EGLDriver *
egl_g3d_create_driver(const struct egl_g3d_loader *loader) egl_g3d_create_driver(const struct egl_g3d_loader *loader)
{ {
@@ -594,8 +591,6 @@ egl_g3d_create_driver(const struct egl_g3d_loader *loader)
gdrv->base.API.Terminate = egl_g3d_terminate; gdrv->base.API.Terminate = egl_g3d_terminate;
gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
gdrv->base.Probe = egl_g3d_probe;
/* to be filled by the caller */ /* to be filled by the caller */
gdrv->base.Name = NULL; gdrv->base.Name = NULL;
gdrv->base.Unload = NULL; gdrv->base.Unload = NULL;