egl_dri2: add swrast
authorHaitao Feng <haitao.feng@intel.com>
Thu, 17 Feb 2011 04:05:15 +0000 (23:05 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 17 Feb 2011 04:06:36 +0000 (23:06 -0500)
This enables the egl_dri2 driver to load swrast driver
for software rendering. It could be used when hardware
dri2 drivers are not available, such as in VM.

Signed-off-by: Haitao Feng <haitao.feng@intel.com>
src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_drm.c
src/egl/drivers/dri2/platform_wayland.c
src/egl/drivers/dri2/platform_x11.c

index e0d2db9661f0d5da01360b654e3c15966f748f5b..99f87f076c1dba4b9661f4ba87ae903b39351911 100644 (file)
@@ -276,6 +276,17 @@ static struct dri2_extension_match dri2_core_extensions[] = {
    { NULL, 0, 0 }
 };
 
+static struct dri2_extension_match swrast_driver_extensions[] = {
+   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
+   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
+   { NULL }
+};
+
+static struct dri2_extension_match swrast_core_extensions[] = {
+   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
+   { NULL }
+};
+
 static EGLBoolean
 dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
                     struct dri2_extension_match *matches,
@@ -363,10 +374,17 @@ dri2_load_driver(_EGLDisplay *disp)
       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;
 }
@@ -379,9 +397,17 @@ dri2_create_screen(_EGLDisplay *disp)
    unsigned int api_mask;
 
    dri2_dpy = disp->DriverData;
-   dri2_dpy->dri_screen =
-      dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
-                                     &dri2_dpy->driver_configs, disp);
+
+   if (dri2_dpy->dri2) {
+      dri2_dpy->dri_screen =
+         dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
+                                        &dri2_dpy->driver_configs, disp);
+   } else {
+      assert(dri2_dpy->swrast);
+      dri2_dpy->dri_screen =
+         dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
+                                           &dri2_dpy->driver_configs, disp);
+   }
 
    if (dri2_dpy->dri_screen == NULL) {
       _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
@@ -389,13 +415,28 @@ dri2_create_screen(_EGLDisplay *disp)
    }
 
    extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
-   if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
-      goto cleanup_dri_screen;
+   
+   if (dri2_dpy->dri2) {
+      if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
+         goto cleanup_dri_screen;
+   } else {
+      assert(dri2_dpy->swrast);
+      if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
+         goto cleanup_dri_screen;
+   }
 
-   if (dri2_dpy->dri2->base.version >= 2)
-      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
-   else
-      api_mask = 1 << __DRI_API_OPENGL;
+   if (dri2_dpy->dri2) {
+      if (dri2_dpy->dri2->base.version >= 2)
+         api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
+      else
+         api_mask = 1 << __DRI_API_OPENGL;
+   } else {
+      assert(dri2_dpy->swrast);
+      if (dri2_dpy->swrast->base.version >= 2)
+         api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2;
+      else
+         api_mask = 1 << __DRI_API_OPENGL;
+   }
 
    disp->ClientAPIs = 0;
    if (api_mask & (1 <<__DRI_API_OPENGL))
@@ -405,10 +446,19 @@ dri2_create_screen(_EGLDisplay *disp)
    if (api_mask & (1 << __DRI_API_GLES2))
       disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
 
-   if (dri2_dpy->dri2->base.version >= 2) {
-      disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
-      disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
-      disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+   if (dri2_dpy->dri2) {
+      if (dri2_dpy->dri2->base.version >= 2) {
+         disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+      }
+   } else {
+      assert(dri2_dpy->swrast);
+      if (dri2_dpy->swrast->base.version >= 2) {
+         disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
+         disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
+      }
    }
 
    return EGL_TRUE;
@@ -465,7 +515,8 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
    _eglCleanupDisplay(disp);
 
    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
-   close(dri2_dpy->fd);
+   if (dri2_dpy->fd)
+      close(dri2_dpy->fd);
    dlclose(dri2_dpy->driver);
    if (disp->PlatformDisplay == NULL)
       xcb_disconnect(dri2_dpy->conn);
@@ -539,23 +590,45 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
    else
       dri_config = NULL;
 
-   if (dri2_dpy->dri2->base.version >= 2) {
-      dri2_ctx->dri_context =
-        dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
-                                               api,
-                                               dri_config,
-                                               dri2_ctx_shared ? 
-                                               dri2_ctx_shared->dri_context : NULL,
-                                               dri2_ctx);
-   } else if (api == __DRI_API_OPENGL) {
-      dri2_ctx->dri_context =
-        dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
-                                         dri_config,
-                                         dri2_ctx_shared ? 
-                                         dri2_ctx_shared->dri_context : NULL,
-                                         dri2_ctx);
+   if (dri2_dpy->dri2) {
+      if (dri2_dpy->dri2->base.version >= 2) {
+        dri2_ctx->dri_context =
+           dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
+                                                  api,
+                                                  dri_config,
+                                                  dri2_ctx_shared ? 
+                                                  dri2_ctx_shared->dri_context : NULL,
+                                                  dri2_ctx);
+      } else if (api == __DRI_API_OPENGL) {
+        dri2_ctx->dri_context =
+           dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
+                                            dri_config,
+                                            dri2_ctx_shared ? 
+                                            dri2_ctx_shared->dri_context : NULL,
+                                            dri2_ctx);
+      } else {
+        /* fail */
+      }
    } else {
-      /* fail */
+      assert(dri2_dpy->swrast);
+      if (dri2_dpy->swrast->base.version >= 2) {
+        dri2_ctx->dri_context =
+           dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
+                                                    api,
+                                                    dri_config,
+                                                    dri2_ctx_shared ? 
+                                                    dri2_ctx_shared->dri_context : NULL,
+                                                    dri2_ctx);
+      } else if (api == __DRI_API_OPENGL) {
+        dri2_ctx->dri_context =
+           dri2_dpy->core->createNewContext(dri2_dpy->dri_screen,
+                                            dri_config,
+                                            dri2_ctx_shared ?
+                                            dri2_ctx_shared->dri_context : NULL,
+                                            dri2_ctx);
+      } else {
+        /* fail */
+      }
    }
 
    if (!dri2_ctx->dri_context)
index 6f5a69cf579538ca1deb77e3b41f14faa62f51d3..235e30df3d87b353df836ac0050c2cf09ab48464 100644 (file)
@@ -71,6 +71,7 @@ struct dri2_egl_display
    void                     *driver;
    __DRIcoreExtension       *core;
    __DRIdri2Extension       *dri2;
+   __DRIswrastExtension     *swrast;
    __DRI2flushExtension     *flush;
    __DRItexBufferExtension  *tex_buffer;
    __DRIimageExtension      *image;
@@ -79,7 +80,8 @@ struct dri2_egl_display
    char                     *device_name;
    char                     *driver_name;
 
-   __DRIdri2LoaderExtension  dri2_loader_extension;
+   __DRIdri2LoaderExtension    dri2_loader_extension;
+   __DRIswrastLoaderExtension  swrast_loader_extension;
    const __DRIextension     *extensions[3];
 #ifdef HAVE_WAYLAND_PLATFORM
    struct wl_egl_display    *wl_dpy;
@@ -118,6 +120,12 @@ struct dri2_egl_surface
    xcb_xfixes_region_t  region;
    int                  have_fake_front;
    int                  swap_interval;
+
+   int                  depth;
+   int                  bytes_per_pixel;
+   xcb_gcontext_t       gc;
+   xcb_gcontext_t       swapgc;
+
    enum dri2_surface_type type;
 #ifdef HAVE_WAYLAND_PLATFORM
    struct wl_egl_window  *wl_win;
index a25cad6d0c585ab3660ad721c83f75476b6d0229..3dab899decb479aa5f9bbc6e4a898e36d615a351 100644 (file)
@@ -638,6 +638,8 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
    dri2_dpy = malloc(sizeof *dri2_dpy);
    if (!dri2_dpy)
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+   
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
 
    disp->DriverData = (void *) dri2_dpy;
    dri2_dpy->fd = (int) disp->PlatformDisplay;
index 859e99f7e7ae85c7c6df006c58a2d97f1f80695a..21b440624ff14b69f73384bb224520a48f386fe8 100644 (file)
@@ -599,6 +599,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_dpy)
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
 
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
    disp->DriverData = (void *) dri2_dpy;
    dri2_dpy->wl_dpy = disp->PlatformDisplay;
 
index 4d72335552b3c996733dea65d4f8f52710dc1571..1c7c8410c0cc58b1a133272ca17c7e7e76d1a927 100644 (file)
 
 #include "egl_dri2.h"
 
+static void
+swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
+                     struct dri2_egl_surface * dri2_surf,
+                     int depth)
+{
+   uint32_t           mask;
+   const uint32_t     function = GXcopy;
+   uint32_t           valgc[2];
+   
+   /* create GC's */
+   dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
+   mask = XCB_GC_FUNCTION;
+   xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function);
+
+   dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
+   mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
+   valgc[0] = function;
+   valgc[1] = False;
+   xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc);
+   dri2_surf->depth = depth;
+   switch (depth) {
+      case 32:
+      case 24:
+         dri2_surf->bytes_per_pixel = 4;
+         break;
+      case 16:
+         dri2_surf->bytes_per_pixel = 2;
+         break;
+      case 8:
+         dri2_surf->bytes_per_pixel = 1;
+         break;
+      case 0:
+         dri2_surf->bytes_per_pixel = 0;
+         break;
+      default:
+         _eglLog(_EGL_WARNING, "unsupported depth %d", depth);
+   }
+}
+
+static void
+swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy,
+                      struct dri2_egl_surface * dri2_surf)
+{
+   xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
+   xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
+}
+
+static void
+swrastGetDrawableInfo(__DRIdrawable * draw,
+                      int *x, int *y, int *w, int *h,
+                      void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   xcb_get_geometry_cookie_t cookie;
+   xcb_get_geometry_reply_t *reply;
+   xcb_generic_error_t *error;
+
+   *w = *h = 0;
+   cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
+   reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
+   if (reply == NULL)
+      return;
+
+   if (error != NULL) {
+      _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
+      free(error);
+   } else {
+      *w = reply->width;
+      *h = reply->height;
+   }
+   free(reply);
+}
+
+static void
+swrastPutImage(__DRIdrawable * draw, int op,
+               int x, int y, int w, int h,
+               char *data, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   xcb_gcontext_t gc;
+
+   switch (op) {
+   case __DRI_SWRAST_IMAGE_OP_DRAW:
+      gc = dri2_surf->gc;
+      break;
+   case __DRI_SWRAST_IMAGE_OP_SWAP:
+      gc = dri2_surf->swapgc;
+      break;
+   default:
+      return;
+   }
+
+   xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable,
+                 gc, w, h, x, y, 0, dri2_surf->depth,
+                 w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
+}
+
+static void
+swrastGetImage(__DRIdrawable * read,
+               int x, int y, int w, int h,
+               char *data, void *loaderPrivate)
+{
+   struct dri2_egl_surface *dri2_surf = loaderPrivate;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
+
+   xcb_get_image_cookie_t cookie;
+   xcb_get_image_reply_t *reply;
+   xcb_generic_error_t *error;
+
+   cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
+                           dri2_surf->drawable, x, y, w, h, ~0);
+   reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
+   if (reply == NULL)
+      return;
+
+   if (error != NULL) {
+      _eglLog(_EGL_WARNING, "error in xcb_get_image");
+      free(error);
+   } else {
+      uint32_t bytes = xcb_get_image_data_length(reply);
+      uint8_t *idata = xcb_get_image_data(reply);
+      memcpy(data, idata, bytes);
+   }
+   free(reply);
+}
+
+
 /**
  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  */
@@ -77,18 +208,31 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       dri2_surf->drawable = window;
    }
 
-   dri2_surf->dri_drawable = 
-      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
-                                           type == EGL_WINDOW_BIT ?
-                                           dri2_conf->dri_double_config : 
-                                           dri2_conf->dri_single_config,
-                                           dri2_surf);
+   if (dri2_dpy->dri2) {
+      dri2_surf->dri_drawable = 
+        (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
+                                              type == EGL_WINDOW_BIT ?
+                                              dri2_conf->dri_double_config : 
+                                              dri2_conf->dri_single_config,
+                                              dri2_surf);
+   } else {
+      assert(dri2_dpy->swrast);
+      dri2_surf->dri_drawable = 
+        (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
+                                                dri2_conf->dri_double_config,
+                                                dri2_surf);
+   }
+
    if (dri2_surf->dri_drawable == NULL) {
       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
       goto cleanup_pixmap;
    }
-
-   xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
+   
+   if (dri2_dpy->dri2) {
+      xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
+   } else {
+      swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_DEPTH_SIZE));
+   }
 
    if (type != EGL_PBUFFER_BIT) {
       cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
@@ -159,7 +303,12 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 
    (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
    
-   xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
+   if (dri2_dpy->dri2) {
+      xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
+   } else {
+      assert(dri2_dpy->swrast);
+      swrastDestroyDrawable(dri2_dpy, dri2_surf);
+   }
 
    if (surf->Type == EGL_PBUFFER_BIT)
       xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
@@ -351,7 +500,7 @@ dri2_connect(struct dri2_egl_display *dri2_dpy)
                                      xfixes_query_cookie, &error);
    if (xfixes_query == NULL ||
        error != NULL || xfixes_query->major_version < 2) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version");
+      _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
       free(error);
       return EGL_FALSE;
    }
@@ -360,7 +509,7 @@ dri2_connect(struct dri2_egl_display *dri2_dpy)
    dri2_query =
       xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
    if (dri2_query == NULL || error != NULL) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to query version");
+      _eglLog(_EGL_WARNING, "DRI2: failed to query version");
       free(error);
       return EGL_FALSE;
    }
@@ -371,7 +520,7 @@ dri2_connect(struct dri2_egl_display *dri2_dpy)
    connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
    if (connect == NULL ||
        connect->driver_name_length + connect->device_name_length == 0) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
+      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
       return EGL_FALSE;
    }
 
@@ -403,7 +552,7 @@ dri2_authenticate(struct dri2_egl_display *dri2_dpy)
    drm_magic_t magic;
 
    if (drmGetMagic(dri2_dpy->fd, &magic)) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic");
+      _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
       return EGL_FALSE;
    }
 
@@ -413,7 +562,7 @@ dri2_authenticate(struct dri2_egl_display *dri2_dpy)
    authenticate =
       xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
    if (authenticate == NULL || !authenticate->authenticated) {
-      _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
+      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
       free(authenticate);
       return EGL_FALSE;
    }
@@ -525,9 +674,17 @@ dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
 static EGLBoolean
 dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 {
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
 
-   return dri2_copy_region(drv, disp, draw, dri2_surf->region);
+   if (dri2_dpy->dri2) { 
+      return dri2_copy_region(drv, disp, draw, dri2_surf->region);
+   } else {
+      assert(dri2_dpy->swrast);
+     
+      dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
+      return EGL_TRUE;
+   }
 }
 
 static EGLBoolean
@@ -690,8 +847,88 @@ dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    }
 }
 
-EGLBoolean
-dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
+static EGLBoolean
+dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy;
+
+   drv->API.CreateWindowSurface = dri2_create_window_surface;
+   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
+   drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
+   drv->API.DestroySurface = dri2_destroy_surface;
+   drv->API.SwapBuffers = dri2_swap_buffers;
+   drv->API.CopyBuffers = dri2_copy_buffers;
+
+   drv->API.SwapBuffersRegionNOK = NULL;
+   drv->API.CreateImageKHR  = NULL;
+   drv->API.DestroyImageKHR = NULL;
+   drv->API.CreateDRMImageMESA = NULL;
+   drv->API.ExportDRMImageMESA = NULL;
+
+   dri2_dpy = malloc(sizeof *dri2_dpy);
+   if (!dri2_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
+   disp->DriverData = (void *) dri2_dpy;
+   if (disp->PlatformDisplay == NULL) {
+      dri2_dpy->conn = xcb_connect(0, 0);
+   } else {
+      dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
+   }
+
+   if (xcb_connection_has_error(dri2_dpy->conn)) {
+      _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
+      goto cleanup_dpy;
+   }
+
+   dri2_dpy->driver_name = dri2_strndup("swrast", strlen("swrast"));
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_conn;
+
+   dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
+   dri2_dpy->swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION;
+   dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo;
+   dri2_dpy->swrast_loader_extension.putImage = swrastPutImage;
+   dri2_dpy->swrast_loader_extension.getImage = swrastGetImage;
+
+   dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
+   dri2_dpy->extensions[1] = NULL;
+   dri2_dpy->extensions[2] = NULL;
+
+   if (!dri2_create_screen(disp))
+      goto cleanup_driver;
+
+   if (dri2_dpy->conn) {
+      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
+         goto cleanup_configs;
+   }
+
+   /* we're supporting EGL 1.4 */
+   disp->VersionMajor = 1;
+   disp->VersionMinor = 4;
+
+   return EGL_TRUE;
+
+ cleanup_configs:
+   _eglCleanupDisplay(disp);
+   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
+ cleanup_driver:
+   dlclose(dri2_dpy->driver);
+ cleanup_conn:
+   if (disp->PlatformDisplay == NULL)
+      xcb_disconnect(dri2_dpy->conn);
+ cleanup_dpy:
+   free(dri2_dpy);
+
+   return EGL_FALSE;
+}
+
+
+static EGLBoolean
+dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
 {
    struct dri2_egl_display *dri2_dpy;
 
@@ -708,6 +945,8 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_dpy)
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
 
+   memset(dri2_dpy, 0, sizeof *dri2_dpy);
+
    disp->DriverData = (void *) dri2_dpy;
    if (disp->PlatformDisplay == NULL) {
       dri2_dpy->conn = xcb_connect(0, 0);
@@ -797,3 +1036,22 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
 
    return EGL_FALSE;
 }
+
+EGLBoolean
+dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
+{
+   EGLBoolean initialized = EGL_TRUE;
+
+   int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
+
+   if (x11_dri2_accel) {
+      if (!dri2_initialize_x11_dri2(drv, disp)) {
+         initialized = dri2_initialize_x11_swrast(drv, disp);
+      }
+   } else {
+      initialized = dri2_initialize_x11_swrast(drv, disp);
+   }
+
+   return initialized;
+}
+