From f55d027ac2e0423eba5d0664cc36668520597703 Mon Sep 17 00:00:00 2001 From: Haitao Feng Date: Wed, 16 Feb 2011 23:05:15 -0500 Subject: [PATCH] egl_dri2: add swrast 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 --- src/egl/drivers/dri2/egl_dri2.c | 141 +++++++++++---- src/egl/drivers/dri2/egl_dri2.h | 10 +- src/egl/drivers/dri2/platform_drm.c | 2 + src/egl/drivers/dri2/platform_wayland.c | 2 + src/egl/drivers/dri2/platform_x11.c | 292 ++++++++++++++++++++++++++++++-- 5 files changed, 395 insertions(+), 52 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index e0d2db9..99f87f0 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -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) diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 6f5a69c..235e30d 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -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; diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index a25cad6..3dab899 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -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; diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 859e99f..21b4406 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -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; diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 4d72335..1c7c841 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -39,6 +39,137 @@ #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; +} + -- 2.7.4