egl: Improve driver selection.
authorChia-I Wu <olv@lunarg.com>
Wed, 12 Jan 2011 20:40:38 +0000 (04:40 +0800)
committerChia-I Wu <olv@lunarg.com>
Thu, 13 Jan 2011 10:15:45 +0000 (18:15 +0800)
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.

src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/glx/egl_glx.c
src/egl/main/egldisplay.h
src/egl/main/egldriver.c
src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/egl/common/native.h
src/gallium/state_trackers/egl/drm/native_drm.c
src/gallium/state_trackers/egl/fbdev/native_fbdev.c
src/gallium/state_trackers/egl/gdi/native_gdi.c
src/gallium/state_trackers/egl/x11/native_x11.c

index 2e827f4..6fc1e49 100644 (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)
index aecebae..c3c11c7 100644 (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;
 
index b42760b..dbc5d32 100644 (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 */
index 7baa24f..e133c22 100644 (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);
 
index bad32ac..9024f94 100644 (file)
 #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;
@@ -384,46 +426,6 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint 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)
 {
    struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) 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;
index 654f445..6461b5e 100644 (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);
 };
 
index 2441b43..14c134e 100644 (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
 };
 
index 1b5ea8b..a1e91ba 100644 (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
 };
 
index 2d04506..3cc4aef 100644 (file)
@@ -406,15 +406,23 @@ gdi_create_display(HDC hDC, struct native_event_handler *event_handler,
    return &gdpy->base;
 }
 
+static struct native_event_handler *gdi_event_handler;
+
+static void
+native_set_event_handler(struct native_event_handler *event_handler)
+{
+   gdi_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)
 {
-   return gdi_create_display((HDC) dpy, event_handler, 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
 };
 
index 37c8b01..a0bcad4 100644 (file)
 
 #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
 };