egl_dri2: try swrastg_dri if swrast_dri fails
[mesa.git] / src / egl / drivers / dri2 / egl_dri2.c
index ea8c8fba8c05bcc5205bb4d670fbf70826f0267a..d430145d09c4b232672b8f4656bdaf9d1400f320 100644 (file)
@@ -97,6 +97,18 @@ EGLint dri2_to_egl_attribute_map[] = {
    0,                          /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
 };
 
+static EGLBoolean
+dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
+{
+   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
+      return EGL_FALSE;
+
+   if (!_eglMatchConfig(conf, criteria))
+      return EGL_FALSE;
+
+   return EGL_TRUE;
+}
+
 struct dri2_egl_config *
 dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
                int depth, EGLint surface_type, const EGLint *attr_list)
@@ -190,7 +202,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
    base.ConfigID    = EGL_DONT_CARE;
    base.SurfaceType = EGL_DONT_CARE;
    num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
-                                 (_EGLArrayForEach) _eglMatchConfig, &base);
+                                 (_EGLArrayForEach) dri2_match_config, &base);
 
    if (num_configs == 1) {
       conf = (struct dri2_egl_config *) matching_config;
@@ -322,8 +334,8 @@ dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
    return ret;
 }
 
-EGLBoolean
-dri2_load_driver(_EGLDisplay *disp)
+static const __DRIextension **
+dri2_open_driver(_EGLDisplay *disp)
 {
    struct dri2_egl_display *dri2_dpy = disp->DriverData;
    const __DRIextension **extensions;
@@ -362,9 +374,9 @@ dri2_load_driver(_EGLDisplay *disp)
 
    if (dri2_dpy->driver == NULL) {
       _eglLog(_EGL_WARNING,
-             "DRI2: failed to open any driver (search paths %s)",
-             search_paths);
-      return EGL_FALSE;
+             "DRI2: failed to open %s (search paths %s)",
+             dri2_dpy->driver_name, search_paths);
+      return NULL;
    }
 
    _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
@@ -373,20 +385,50 @@ dri2_load_driver(_EGLDisplay *disp)
       _eglLog(_EGL_WARNING,
              "DRI2: driver exports no extensions (%s)", dlerror());
       dlclose(dri2_dpy->driver);
+   }
+
+   return extensions;
+}
+
+EGLBoolean
+dri2_load_driver(_EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy = disp->DriverData;
+   const __DRIextension **extensions;
+
+   extensions = dri2_open_driver(disp);
+   if (!extensions)
+      return EGL_FALSE;
+
+   if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
+      dlclose(dri2_dpy->driver);
       return EGL_FALSE;
    }
 
-   if (strcmp(dri2_dpy->driver_name, "swrast") == 0) {
-      if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
-         dlclose(dri2_dpy->driver);
-         return EGL_FALSE;
-      }
-   } else {
-      if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
-         dlclose(dri2_dpy->driver);
-         return EGL_FALSE;
-      }
-   } 
+   return EGL_TRUE;
+}
+
+EGLBoolean
+dri2_load_driver_swrast(_EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy = disp->DriverData;
+   const __DRIextension **extensions;
+
+   dri2_dpy->driver_name = "swrast";
+   extensions = dri2_open_driver(disp);
+   if (!extensions) {
+      /* try again with swrastg */
+      dri2_dpy->driver_name = "swrastg";
+      extensions = dri2_open_driver(disp);
+   }
+
+   if (!extensions)
+      return EGL_FALSE;
+
+   if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
+      dlclose(dri2_dpy->driver);
+      return EGL_FALSE;
+   }
 
    return EGL_TRUE;
 }
@@ -528,10 +570,24 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
    if (dri2_dpy->fd)
       close(dri2_dpy->fd);
    dlclose(dri2_dpy->driver);
+
+   if (disp->PlatformDisplay == NULL) {
+      switch (disp->Platform) {
 #ifdef HAVE_X11_PLATFORM
-   if (disp->PlatformDisplay == NULL)
-      xcb_disconnect(dri2_dpy->conn);
+      case _EGL_PLATFORM_X11:
+         xcb_disconnect(dri2_dpy->conn);
+         break;
 #endif
+#ifdef HAVE_WAYLAND_PLATFORM
+      case _EGL_PLATFORM_WAYLAND:
+         wl_display_destroy(dri2_dpy->wl_dpy);
+         break;
+#endif
+      default:
+         break;
+      }
+   }
+
    free(dri2_dpy);
    disp->DriverData = NULL;