X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fplatform_x11.c;h=ff5dc32c03aa010e760bba8e363e9e968e9adc68;hb=d32c458de76c9e0cc08c9ee1a7de23c3fca69298;hp=74d3a164b6a634127d00a99ff10cd9e47bf5b134;hpb=9827547313c7239486efbd4067529575f98f1622;p=mesa.git diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 74d3a164b6a..ff5dc32c03a 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -40,7 +40,9 @@ #endif #include #include +#include "util/debug.h" #include "util/macros.h" +#include "util/bitscan.h" #include "egl_dri2.h" #include "egl_dri2_fallbacks.h" @@ -54,6 +56,9 @@ static EGLBoolean dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint interval); +uint32_t +dri2_format_for_depth(struct dri2_egl_display *dri2_dpy, uint32_t depth); + static void swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, struct dri2_egl_surface * dri2_surf) @@ -74,6 +79,7 @@ swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc); switch (dri2_surf->depth) { case 32: + case 30: case 24: dri2_surf->bytes_per_pixel = 4; break; @@ -99,8 +105,8 @@ swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy, xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc); } -static void -swrastGetDrawableInfo(__DRIdrawable * draw, +static bool +x11_get_drawable_info(__DRIdrawable * draw, int *x, int *y, int *w, int *h, void *loaderPrivate) { @@ -110,21 +116,35 @@ swrastGetDrawableInfo(__DRIdrawable * draw, xcb_get_geometry_cookie_t cookie; xcb_get_geometry_reply_t *reply; xcb_generic_error_t *error; + bool ret; - *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; + return false; if (error != NULL) { + ret = false; _eglLog(_EGL_WARNING, "error in xcb_get_geometry"); free(error); } else { + *x = reply->x; + *y = reply->y; *w = reply->width; *h = reply->height; + ret = true; } free(reply); + return ret; +} + +static void +swrastGetDrawableInfo(__DRIdrawable * draw, + int *x, int *y, int *w, int *h, + void *loaderPrivate) +{ + *x = *y = *w = *h = 0; + x11_get_drawable_info(draw, x, y, w, h, loaderPrivate); } static void @@ -193,6 +213,36 @@ get_xcb_screen(xcb_screen_iterator_t iter, int screen) return NULL; } +static xcb_visualtype_t * +get_xcb_visualtype_for_depth(struct dri2_egl_display *dri2_dpy, int depth) +{ + xcb_visualtype_iterator_t visual_iter; + xcb_screen_t *screen = dri2_dpy->screen; + xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen); + + for (; depth_iter.rem; xcb_depth_next(&depth_iter)) { + if (depth_iter.data->depth != depth) + continue; + + visual_iter = xcb_depth_visuals_iterator(depth_iter.data); + if (visual_iter.rem) + return visual_iter.data; + } + + return NULL; +} + +/* Get red channel mask for given depth. */ +unsigned int +dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth) +{ + xcb_visualtype_t *visual = get_xcb_visualtype_for_depth(dri2_dpy, depth); + + if (visual) + return visual->red_mask; + + return 0; +} /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). @@ -208,21 +258,18 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, xcb_get_geometry_cookie_t cookie; xcb_get_geometry_reply_t *reply; xcb_generic_error_t *error; - xcb_drawable_t drawable; const __DRIconfig *config; - STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); - drawable = (uintptr_t) native_surface; - (void) drv; - dri2_surf = malloc(sizeof *dri2_surf); + dri2_surf = calloc(1, sizeof *dri2_surf); if (!dri2_surf) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); return NULL; } - if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) + if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list, + false, native_surface)) goto cleanup_surf; dri2_surf->region = XCB_NONE; @@ -232,34 +279,20 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, dri2_surf->drawable, dri2_dpy->screen->root, dri2_surf->base.Width, dri2_surf->base.Height); } else { - if (!drawable) { - if (type == EGL_WINDOW_BIT) - _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface"); - else - _eglError(EGL_BAD_NATIVE_PIXMAP, "dri2_create_surface"); - goto cleanup_surf; - } - dri2_surf->drawable = drawable; + STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); + dri2_surf->drawable = (uintptr_t) native_surface; } config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace); - if (dri2_dpy->dri2) { - dri2_surf->dri_drawable = - dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, - dri2_surf); - } else { - assert(dri2_dpy->swrast); - dri2_surf->dri_drawable = - dri2_dpy->swrast->createNewDrawable(dri2_dpy->dri_screen, config, - dri2_surf); + if (!config) { + _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); + goto cleanup_pixmap; } - if (dri2_surf->dri_drawable == NULL) { - _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); + if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) goto cleanup_pixmap; - } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); @@ -306,7 +339,7 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, } } else { if (type == EGL_PBUFFER_BIT) { - dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE); + dri2_surf->depth = conf->BufferSize; } swrastCreateDrawable(dri2_dpy, dri2_surf); } @@ -367,7 +400,7 @@ dri2_x11_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, const EGLint *attrib_list) { return dri2_x11_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, - XCB_WINDOW_NONE, attrib_list); + NULL, attrib_list); } static EGLBoolean @@ -390,6 +423,7 @@ dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) if (surf->Type == EGL_PBUFFER_BIT) xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); + dri2_fini_surface(surf); free(surf); return EGL_TRUE; @@ -404,21 +438,20 @@ dri2_x11_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) * have. */ static EGLBoolean -dri2_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, +dri2_query_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint attribute, EGLint *value) { - struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); - int x, y, w = -1, h = -1; + int x, y, w, h; __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf); switch (attribute) { case EGL_WIDTH: case EGL_HEIGHT: - swrastGetDrawableInfo(drawable, &x, &y, &w, &h, dri2_surf); - if (w != -1 && h != -1) { + if (x11_get_drawable_info(drawable, &x, &y, &w, &h, dri2_surf)) { surf->Width = w; surf->Height = h; } @@ -426,7 +459,7 @@ dri2_query_surface(_EGLDriver *drv, _EGLDisplay *dpy, default: break; } - return _eglQuerySurface(drv, dpy, surf, attribute, value); + return _eglQuerySurface(drv, disp, surf, attribute, value); } /** @@ -442,14 +475,12 @@ dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf, struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); xcb_rectangle_t rectangle; - unsigned i; - dri2_surf->buffer_count = count; - dri2_surf->have_fake_front = 0; + dri2_surf->have_fake_front = false; /* This assumes the DRI2 buffer attachment tokens matches the * __DRIbuffer tokens. */ - for (i = 0; i < count; i++) { + for (unsigned i = 0; i < count; i++) { dri2_surf->buffers[i].attachment = buffers[i].attachment; dri2_surf->buffers[i].name = buffers[i].name; dri2_surf->buffers[i].pitch = buffers[i].pitch; @@ -462,7 +493,7 @@ dri2_x11_process_buffers(struct dri2_egl_surface *dri2_surf, * Note that EGL doesn't require that several clients rendering * to the same window must see the same aux buffers. */ if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) - dri2_surf->have_fake_front = 1; + dri2_surf->have_fake_front = true; } if (dri2_surf->region != XCB_NONE) @@ -646,6 +677,7 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy) error != NULL || xfixes_query->major_version < 2) { _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version"); free(error); + free(xfixes_query); return EGL_FALSE; } free(xfixes_query); @@ -700,7 +732,6 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy) if (dri2_dpy->driver_name == NULL) { close(dri2_dpy->fd); - free(dri2_dpy->driver_name); free(connect); return EGL_FALSE; } @@ -730,17 +761,10 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, { xcb_depth_iterator_t d; xcb_visualtype_t *visuals; - int i, j, count; - unsigned int rgba_masks[4]; + int config_count = 0; EGLint surface_type; - EGLint config_attrs[] = { - EGL_NATIVE_VISUAL_ID, 0, - EGL_NATIVE_VISUAL_TYPE, 0, - EGL_NONE - }; d = xcb_screen_allowed_depths_iterator(dri2_dpy->screen); - count = 0; surface_type = EGL_WINDOW_BIT | @@ -754,41 +778,64 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, EGLBoolean class_added[6] = { 0, }; visuals = xcb_depth_visuals(d.data); - for (i = 0; i < xcb_depth_visuals_length(d.data); i++) { + + for (int i = 0; i < xcb_depth_visuals_length(d.data); i++) { if (class_added[visuals[i]._class]) continue; class_added[visuals[i]._class] = EGL_TRUE; - for (j = 0; dri2_dpy->driver_configs[j]; j++) { + + for (int j = 0; dri2_dpy->driver_configs[j]; j++) { struct dri2_egl_config *dri2_conf; const __DRIconfig *config = dri2_dpy->driver_configs[j]; - config_attrs[1] = visuals[i].visual_id; - config_attrs[3] = visuals[i]._class; - - rgba_masks[0] = visuals[i].red_mask; - rgba_masks[1] = visuals[i].green_mask; - rgba_masks[2] = visuals[i].blue_mask; - rgba_masks[3] = 0; - dri2_conf = dri2_add_config(disp, config, count + 1, surface_type, - config_attrs, rgba_masks); + const EGLint config_attrs[] = { + EGL_NATIVE_VISUAL_ID, visuals[i].visual_id, + EGL_NATIVE_VISUAL_TYPE, visuals[i]._class, + EGL_NONE + }; + + int rgba_shifts[4] = { + ffs(visuals[i].red_mask) - 1, + ffs(visuals[i].green_mask) - 1, + ffs(visuals[i].blue_mask) - 1, + -1, + }; + + unsigned int rgba_sizes[4] = { + util_bitcount(visuals[i].red_mask), + util_bitcount(visuals[i].green_mask), + util_bitcount(visuals[i].blue_mask), + 0, + }; + + dri2_conf = dri2_add_config(disp, config, config_count + 1, + surface_type, config_attrs, + rgba_shifts, rgba_sizes); if (dri2_conf) - count++; + if (dri2_conf->base.ConfigID == config_count + 1) + config_count++; /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig. + * Ditto for 30-bit RGB visuals to match a 32-bit RGBA EGLConfig. * Otherwise it will only match a 32-bit RGBA visual. On a * composited window manager on X11, this will make all of the * EGLConfigs with destination alpha get blended by the * compositor. This is probably not what the application * wants... especially on drivers that only have 32-bit RGBA * EGLConfigs! */ - if (d.data->depth == 24) { - rgba_masks[3] = - ~(rgba_masks[0] | rgba_masks[1] | rgba_masks[2]); - dri2_conf = dri2_add_config(disp, config, count + 1, surface_type, - config_attrs, rgba_masks); + if (d.data->depth == 24 || d.data->depth == 30) { + unsigned int rgba_mask = ~(visuals[i].red_mask | + visuals[i].green_mask | + visuals[i].blue_mask); + rgba_shifts[3] = ffs(rgba_mask) - 1; + rgba_sizes[3] = util_bitcount(rgba_mask); + dri2_conf = dri2_add_config(disp, config, config_count + 1, + surface_type, config_attrs, + rgba_shifts, rgba_sizes); if (dri2_conf) - count++; + if (dri2_conf->base.ConfigID == config_count + 1) + config_count++; } } } @@ -796,7 +843,7 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, xcb_depth_next(&d); } - if (!count) { + if (!config_count) { _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); return EGL_FALSE; } @@ -850,23 +897,22 @@ dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, xcb_dri2_swap_buffers_reply_t *reply; int64_t swap_count = -1; - /* No-op for a pixmap or pbuffer surface */ - if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) - return 0; - - if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) - return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; - - dri2_flush_drawable_for_swapbuffers(disp, draw); + if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) { + swap_count = dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; + } else { + dri2_flush_drawable_for_swapbuffers(disp, draw); - cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable, - msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo); + cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, + dri2_surf->drawable, msc_hi, + msc_lo, divisor_hi, divisor_lo, + remainder_hi, remainder_lo); - reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL); + reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL); - if (reply) { - swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo; - free(reply); + if (reply) { + swap_count = combine_u32_into_u64(reply->swap_hi, reply->swap_lo); + free(reply); + } } /* Since we aren't watching for the server's invalidate events like we're @@ -898,8 +944,7 @@ dri2_x11_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) if (dri2_x11_swap_buffers_msc(drv, disp, draw, 0, 0, 0) == -1) { /* Swap failed with a window drawable. */ - _eglError(EGL_BAD_NATIVE_WINDOW, __func__); - return EGL_FALSE; + return _eglError(EGL_BAD_NATIVE_WINDOW, __func__); } return EGL_TRUE; } @@ -914,12 +959,11 @@ dri2_x11_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, EGLBoolean ret; xcb_xfixes_region_t region; xcb_rectangle_t rectangles[16]; - int i; if (numRects > (int)ARRAY_SIZE(rectangles)) return dri2_copy_region(drv, disp, draw, dri2_surf->region); - for (i = 0; i < numRects; i++) { + for (int i = 0; i < numRects; i++) { rectangles[i].x = rects[i * 4]; rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3]; rectangles[i].width = rects[i * 4 + 2]; @@ -953,16 +997,9 @@ dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); - if (interval > surf->Config->MaxSwapInterval) - interval = surf->Config->MaxSwapInterval; - else if (interval < surf->Config->MinSwapInterval) - interval = surf->Config->MinSwapInterval; - - if (interval != surf->SwapInterval && dri2_dpy->swap_available) + if (dri2_dpy->swap_available) xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval); - surf->SwapInterval = interval; - return EGL_TRUE; } @@ -997,6 +1034,27 @@ dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, return EGL_TRUE; } +uint32_t +dri2_format_for_depth(struct dri2_egl_display *dri2_dpy, uint32_t depth) +{ + switch (depth) { + case 16: + return __DRI_IMAGE_FORMAT_RGB565; + case 24: + return __DRI_IMAGE_FORMAT_XRGB8888; + case 30: + /* Different preferred formats for different hw */ + if (dri2_x11_get_red_mask_for_depth(dri2_dpy, 30) == 0x3ff) + return __DRI_IMAGE_FORMAT_XBGR2101010; + else + return __DRI_IMAGE_FORMAT_XRGB2101010; + case 32: + return __DRI_IMAGE_FORMAT_ARGB8888; + default: + return __DRI_IMAGE_FORMAT_NONE; + } +} + static _EGLImage * dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, EGLClientBuffer buffer, const EGLint *attr_list) @@ -1041,17 +1099,8 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, return NULL; } - switch (geometry_reply->depth) { - case 16: - format = __DRI_IMAGE_FORMAT_RGB565; - break; - case 24: - format = __DRI_IMAGE_FORMAT_XRGB8888; - break; - case 32: - format = __DRI_IMAGE_FORMAT_ARGB8888; - break; - default: + format = dri2_format_for_depth(dri2_dpy, geometry_reply->depth); + if (format == __DRI_IMAGE_FORMAT_NONE) { _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr: unsupported pixmap depth"); free(buffers_reply); @@ -1067,12 +1116,7 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, return EGL_NO_IMAGE_KHR; } - if (!_eglInitImage(&dri2_img->base, disp)) { - free(buffers_reply); - free(geometry_reply); - free(dri2_img); - return EGL_NO_IMAGE_KHR; - } + _eglInitImage(&dri2_img->base, disp); stride = buffers[0].pitch / buffers[0].cpp; dri2_img->dri_image = @@ -1118,10 +1162,8 @@ dri2_x11_get_sync_values(_EGLDisplay *display, _EGLSurface *surface, cookie = xcb_dri2_get_msc(dri2_dpy->conn, dri2_surf->drawable); reply = xcb_dri2_get_msc_reply(dri2_dpy->conn, cookie, NULL); - if (!reply) { - _eglError(EGL_BAD_ACCESS, __func__); - return EGL_FALSE; - } + if (!reply) + return _eglError(EGL_BAD_ACCESS, __func__); *ust = ((EGLuint64KHR) reply->ust_hi << 32) | reply->ust_lo; *msc = ((EGLuint64KHR) reply->msc_hi << 32) | reply->msc_lo; @@ -1137,13 +1179,12 @@ static const struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = { .create_pixmap_surface = dri2_x11_create_pixmap_surface, .create_pbuffer_surface = dri2_x11_create_pbuffer_surface, .destroy_surface = dri2_x11_destroy_surface, - .create_image = dri2_fallback_create_image_khr, - .swap_interval = dri2_fallback_swap_interval, + .create_image = dri2_create_image_khr, .swap_buffers = dri2_x11_swap_buffers, - .set_damage_region = dri2_fallback_set_damage_region, .swap_buffers_region = dri2_fallback_swap_buffers_region, .post_sub_buffer = dri2_fallback_post_sub_buffer, - .copy_buffers = dri2_x11_copy_buffers, + /* XXX: should really implement this since X11 has pixmaps */ + .copy_buffers = dri2_fallback_copy_buffers, .query_buffer_age = dri2_fallback_query_buffer_age, .query_surface = dri2_query_surface, .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, @@ -1162,7 +1203,6 @@ static const struct dri2_egl_display_vtbl dri2_x11_display_vtbl = { .swap_buffers = dri2_x11_swap_buffers, .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, .swap_buffers_region = dri2_x11_swap_buffers_region, - .set_damage_region = dri2_fallback_set_damage_region, .post_sub_buffer = dri2_x11_post_sub_buffer, .copy_buffers = dri2_x11_copy_buffers, .query_buffer_age = dri2_fallback_query_buffer_age, @@ -1182,24 +1222,38 @@ static const __DRIswrastLoaderExtension swrast_loader_extension = { static const __DRIextension *swrast_loader_extensions[] = { &swrast_loader_extension.base, + &image_lookup_extension.base, NULL, }; +static int +dri2_find_screen_for_display(const _EGLDisplay *disp, int fallback_screen) +{ + const EGLAttrib *attr; + + for (attr = disp->Options.Attribs; attr; attr += 2) { + if (attr[0] == EGL_PLATFORM_X11_SCREEN_EXT) + return attr[1]; + } + + return fallback_screen; +} + static EGLBoolean dri2_get_xcb_connection(_EGLDriver *drv, _EGLDisplay *disp, struct dri2_egl_display *dri2_dpy) { xcb_screen_iterator_t s; - int screen = (uintptr_t)disp->Options.Platform; + int screen; const char *msg; disp->DriverData = (void *) dri2_dpy; if (disp->PlatformDisplay == NULL) { dri2_dpy->conn = xcb_connect(NULL, &screen); dri2_dpy->own_device = true; + screen = dri2_find_screen_for_display(disp, screen); } else { Display *dpy = disp->PlatformDisplay; - dri2_dpy->conn = XGetXCBConnection(dpy); screen = DefaultScreen(dpy); } @@ -1227,6 +1281,7 @@ disconnect: static EGLBoolean dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) { + _EGLDevice *dev; struct dri2_egl_display *dri2_dpy; dri2_dpy = calloc(1, sizeof *dri2_dpy); @@ -1237,6 +1292,14 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) if (!dri2_get_xcb_connection(drv, disp, dri2_dpy)) goto cleanup; + dev = _eglAddDevice(dri2_dpy->fd, true); + if (!dev) { + _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); + goto cleanup; + } + + disp->Device = dev; + /* * Every hardware driver_name is set using strdup. Doing the same in * here will allow is to simply free the memory at dri2_terminate(). @@ -1271,9 +1334,9 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) } static void -dri2_x11_setup_swap_interval(struct dri2_egl_display *dri2_dpy) +dri2_x11_setup_swap_interval(_EGLDisplay *disp) { - GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); int arbitrary_max_interval = 1000; /* default behavior for no SwapBuffers support: no vblank syncing @@ -1281,39 +1344,15 @@ dri2_x11_setup_swap_interval(struct dri2_egl_display *dri2_dpy) */ dri2_dpy->min_swap_interval = 0; dri2_dpy->max_swap_interval = 0; + dri2_dpy->default_swap_interval = 0; if (!dri2_dpy->swap_available) return; /* If we do have swapbuffers, then we can support pretty much any swap - * interval, but we allow driconf to override applications. + * interval. */ - if (dri2_dpy->config) - dri2_dpy->config->configQueryi(dri2_dpy->dri_screen, - "vblank_mode", &vblank_mode); - switch (vblank_mode) { - case DRI_CONF_VBLANK_NEVER: - dri2_dpy->min_swap_interval = 0; - dri2_dpy->max_swap_interval = 0; - dri2_dpy->default_swap_interval = 0; - break; - case DRI_CONF_VBLANK_ALWAYS_SYNC: - dri2_dpy->min_swap_interval = 1; - dri2_dpy->max_swap_interval = arbitrary_max_interval; - dri2_dpy->default_swap_interval = 1; - break; - case DRI_CONF_VBLANK_DEF_INTERVAL_0: - dri2_dpy->min_swap_interval = 0; - dri2_dpy->max_swap_interval = arbitrary_max_interval; - dri2_dpy->default_swap_interval = 0; - break; - default: - case DRI_CONF_VBLANK_DEF_INTERVAL_1: - dri2_dpy->min_swap_interval = 0; - dri2_dpy->max_swap_interval = arbitrary_max_interval; - dri2_dpy->default_swap_interval = 1; - break; - } + dri2_setup_swap_interval(disp, arbitrary_max_interval); } #ifdef HAVE_DRI3 @@ -1322,12 +1361,14 @@ static const __DRIextension *dri3_image_loader_extensions[] = { &dri3_image_loader_extension.base, &image_lookup_extension.base, &use_invalidate.base, + &background_callable_extension.base, NULL, }; static EGLBoolean dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp) { + _EGLDevice *dev; struct dri2_egl_display *dri2_dpy; dri2_dpy = calloc(1, sizeof *dri2_dpy); @@ -1341,6 +1382,14 @@ dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp) if (!dri3_x11_connect(dri2_dpy)) goto cleanup; + dev = _eglAddDevice(dri2_dpy->fd, false); + if (!dev) { + _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); + goto cleanup; + } + + disp->Device = dev; + if (!dri2_load_driver_dri3(disp)) goto cleanup; @@ -1357,7 +1406,7 @@ dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp) dri2_setup_screen(disp); - dri2_x11_setup_swap_interval(dri2_dpy); + dri2_x11_setup_swap_interval(disp); if (!dri2_dpy->is_different_gpu) disp->Extensions.KHR_image_pixmap = EGL_TRUE; @@ -1418,6 +1467,7 @@ static const __DRIextension *dri2_loader_extensions_old[] = { static const __DRIextension *dri2_loader_extensions[] = { &dri2_loader_extension.base, &image_lookup_extension.base, + &use_invalidate.base, &background_callable_extension.base, NULL, }; @@ -1425,6 +1475,7 @@ static const __DRIextension *dri2_loader_extensions[] = { static EGLBoolean dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) { + _EGLDevice *dev; struct dri2_egl_display *dri2_dpy; dri2_dpy = calloc(1, sizeof *dri2_dpy); @@ -1438,6 +1489,14 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) if (!dri2_x11_connect(dri2_dpy)) goto cleanup; + dev = _eglAddDevice(dri2_dpy->fd, false); + if (!dev) { + _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); + goto cleanup; + } + + disp->Device = dev; + if (!dri2_load_driver(disp)) goto cleanup; @@ -1457,7 +1516,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) dri2_setup_screen(disp); - dri2_x11_setup_swap_interval(dri2_dpy); + dri2_x11_setup_swap_interval(disp); disp->Extensions.KHR_image_pixmap = EGL_TRUE; disp->Extensions.NOK_swap_region = EGL_TRUE; @@ -1489,9 +1548,9 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) { EGLBoolean initialized = EGL_FALSE; - if (!getenv("LIBGL_ALWAYS_SOFTWARE")) { + if (!disp->Options.ForceSoftware) { #ifdef HAVE_DRI3 - if (!getenv("LIBGL_DRI3_DISABLE")) + if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) initialized = dri2_initialize_x11_dri3(drv, disp); #endif @@ -1505,3 +1564,9 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp) return initialized; } +void +dri2_teardown_x11(struct dri2_egl_display *dri2_dpy) +{ + if (dri2_dpy->own_device) + xcb_disconnect(dri2_dpy->conn); +}