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:
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user