egl: Improve driver selection.

The idea is to be able to match a driver using the following order

  try egl_gallium with hw renderer
  try egl_dri2
  try egl_gallium with sw renderer
  try egl_glx

given the module list

  egl_gallium
  egl_dri2
  egl_glx

For that, UseFallback initialization option is added.  The module list
is matched twice: with the option unset and with the option set.  In the
first pass, egl_gallium skips its sw renderer and egl_glx rejects to
initialize since UseFallback is not set.  In the second pass,
egl_gallium skips its hw renderer and egl_dri2 rejects to initialize
since UseFallback is set.  The process stops at the first driver that
initializes the display.
This commit is contained in:
Chia-I Wu
2011-01-13 04:40:38 +08:00
parent 655e459892
commit a22a332fc7
10 changed files with 111 additions and 64 deletions

View File

@@ -1470,6 +1470,10 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
static EGLBoolean
dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
{
/* not until swrast_dri is supported */
if (disp->Options.UseFallback)
return EGL_FALSE;
switch (disp->Platform) {
case _EGL_PLATFORM_X11:
if (disp->Options.TestOnly)

View File

@@ -589,6 +589,10 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp)
if (disp->Platform != _EGL_PLATFORM_X11)
return EGL_FALSE;
/* this is a fallback driver */
if (!disp->Options.UseFallback)
return EGL_FALSE;
if (disp->Options.TestOnly)
return EGL_TRUE;

View File

@@ -93,6 +93,7 @@ struct _egl_display
/* options that affect how the driver initializes the display */
struct {
EGLBoolean TestOnly; /**< Driver should not set fields when true */
EGLBoolean UseFallback; /**< Use fallback driver (sw or less features) */
} Options;
/* these fields are set by the driver during init */

View File

@@ -585,8 +585,13 @@ _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only)
/* set options */
dpy->Options.TestOnly = test_only;
dpy->Options.UseFallback = EGL_FALSE;
best_drv = _eglMatchAndInitialize(dpy);
if (!best_drv) {
dpy->Options.UseFallback = EGL_TRUE;
best_drv = _eglMatchAndInitialize(dpy);
}
_eglUnlockMutex(&_eglModuleMutex);

View File

@@ -38,6 +38,46 @@
#include "egl_g3d_loader.h"
#include "native.h"
static void
egl_g3d_invalid_surface(struct native_display *ndpy,
struct native_surface *nsurf,
unsigned int seq_num)
{
/* XXX not thread safe? */
struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
struct egl_g3d_context *gctx;
/*
* Some functions such as egl_g3d_copy_buffers create a temporary native
* surface. There is no gsurf associated with it.
*/
gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
if (gctx)
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
}
static struct pipe_screen *
egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
return gdpy->loader->create_drm_screen(name, fd);
}
static struct pipe_screen *
egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
return gdpy->loader->create_sw_screen(ws);
}
static struct native_event_handler egl_g3d_native_event_handler = {
egl_g3d_invalid_surface,
egl_g3d_new_drm_screen,
egl_g3d_new_sw_screen
};
/**
* Get the native platform.
*/
@@ -79,7 +119,9 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
break;
}
if (!nplat)
if (nplat)
nplat->set_event_handler(&egl_g3d_native_event_handler);
else
_eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
gdrv->platforms[plat] = nplat;
@@ -383,46 +425,6 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
return id;
}
static void
egl_g3d_invalid_surface(struct native_display *ndpy,
struct native_surface *nsurf,
unsigned int seq_num)
{
/* XXX not thread safe? */
struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
struct egl_g3d_context *gctx;
/*
* Some functions such as egl_g3d_copy_buffers create a temporary native
* surface. There is no gsurf associated with it.
*/
gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL;
if (gctx)
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
}
static struct pipe_screen *
egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
return gdpy->loader->create_drm_screen(name, fd);
}
static struct pipe_screen *
egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
return gdpy->loader->create_sw_screen(ws);
}
static struct native_event_handler egl_g3d_native_event_handler = {
egl_g3d_invalid_surface,
egl_g3d_new_drm_screen,
egl_g3d_new_sw_screen
};
static void
egl_g3d_free_config(void *conf)
{
@@ -497,7 +499,7 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
_eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay);
gdpy->native = nplat->create_display(dpy->PlatformDisplay,
&egl_g3d_native_event_handler, (void *) dpy);
dpy->Options.UseFallback, (void *) dpy);
if (!gdpy->native) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
goto fail;

View File

@@ -226,8 +226,9 @@ native_attachment_mask_test(uint mask, enum native_attachment att)
struct native_platform {
const char *name;
void (*set_event_handler)(struct native_event_handler *handler);
struct native_display *(*create_display)(void *dpy,
struct native_event_handler *handler,
boolean use_sw,
void *user_data);
};

View File

@@ -237,9 +237,16 @@ drm_create_display(int fd, struct native_event_handler *event_handler,
return &drmdpy->base;
}
static struct native_event_handler *drm_event_handler;
static void
native_set_event_handler(struct native_event_handler *event_handler)
{
drm_event_handler = event_handler;
}
static struct native_display *
native_create_display(void *dpy, struct native_event_handler *event_handler,
void *user_data)
native_create_display(void *dpy, boolean use_sw, void *user_data)
{
int fd;
@@ -252,11 +259,12 @@ native_create_display(void *dpy, struct native_event_handler *event_handler,
if (fd < 0)
return NULL;
return drm_create_display(fd, event_handler, user_data);
return drm_create_display(fd, drm_event_handler, user_data);
}
static const struct native_platform drm_platform = {
"DRM", /* name */
native_set_event_handler,
native_create_display
};

View File

@@ -459,9 +459,16 @@ fbdev_display_create(int fd, struct native_event_handler *event_handler,
return &fbdpy->base;
}
static struct native_event_handler *fbdev_event_handler;
static void
native_set_event_handler(struct native_event_handler *event_handler)
{
fbdev_event_handler = event_handler;
}
static struct native_display *
native_create_display(void *dpy, struct native_event_handler *event_handler,
void *user_data)
native_create_display(void *dpy, boolean use_sw, void *user_data)
{
struct native_display *ndpy;
int fd;
@@ -476,7 +483,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler,
if (fd < 0)
return NULL;
ndpy = fbdev_display_create(fd, event_handler, user_data);
ndpy = fbdev_display_create(fd, fbdev_event_handler, user_data);
if (!ndpy)
close(fd);
@@ -485,6 +492,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler,
static const struct native_platform fbdev_platform = {
"FBDEV", /* name */
native_set_event_handler,
native_create_display
};

View File

@@ -406,15 +406,23 @@ gdi_create_display(HDC hDC, struct native_event_handler *event_handler,
return &gdpy->base;
}
static struct native_display *
native_create_display(void *dpy, struct native_event_handler *event_handler,
void *user_data)
static struct native_event_handler *gdi_event_handler;
static void
native_set_event_handler(struct native_event_handler *event_handler)
{
return gdi_create_display((HDC) dpy, event_handler, user_data);
gdi_event_handler = event_handler;
}
static struct native_display *
native_create_display(void *dpy, boolean use_sw, void *user_data)
{
return gdi_create_display((HDC) dpy, gdi_event_handler, user_data);
}
static const struct native_platform gdi_platform = {
"GDI", /* name */
native_set_event_handler,
native_create_display
};

View File

@@ -30,25 +30,30 @@
#include "native_x11.h"
static struct native_event_handler *x11_event_handler;
static void
native_set_event_handler(struct native_event_handler *event_handler)
{
x11_event_handler = event_handler;
}
static struct native_display *
native_create_display(void *dpy, struct native_event_handler *event_handler,
void *user_data)
native_create_display(void *dpy, boolean use_sw, void *user_data)
{
struct native_display *ndpy = NULL;
boolean force_sw;
force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
if (!force_sw) {
ndpy = x11_create_dri2_display((Display *) dpy,
event_handler, user_data);
}
if (!ndpy) {
EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
_eglLog(level, "use software fallback");
if (force_sw || use_sw) {
_eglLog(_EGL_INFO, "use software fallback");
ndpy = x11_create_ximage_display((Display *) dpy,
event_handler, user_data);
x11_event_handler, user_data);
}
else {
ndpy = x11_create_dri2_display((Display *) dpy,
x11_event_handler, user_data);
}
return ndpy;
@@ -56,6 +61,7 @@ native_create_display(void *dpy, struct native_event_handler *event_handler,
static const struct native_platform x11_platform = {
"X11", /* name */
native_set_event_handler,
native_create_display
};