X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fdrivers%2Fdri2%2Fplatform_x11.c;h=ad40bd57aa64c4df2b8830c0be0605c505d39c83;hb=af2aea40d29dffd5e584432e0652db114113469b;hp=6be99130479b11e6384f9f6c217b3f994031b973;hpb=bc8b07a65722ad25aa52aa4918b51e236a13b09e;p=mesa.git diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 6be99130479..ad40bd57aa6 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -25,6 +25,8 @@ * Kristian Høgsberg */ +#include +#include #include #include #include @@ -41,6 +43,7 @@ #include "egl_dri2.h" #include "egl_dri2_fallbacks.h" +#include "loader.h" static EGLBoolean dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, @@ -48,13 +51,12 @@ dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, static void swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, - struct dri2_egl_surface * dri2_surf, - int depth) + struct dri2_egl_surface * dri2_surf) { 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; @@ -65,8 +67,7 @@ swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, 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) { + switch (dri2_surf->depth) { case 32: case 24: dri2_surf->bytes_per_pixel = 4; @@ -81,7 +82,7 @@ swrastCreateDrawable(struct dri2_egl_display * dri2_dpy, dri2_surf->bytes_per_pixel = 0; break; default: - _eglLog(_EGL_WARNING, "unsupported depth %d", depth); + _eglLog(_EGL_WARNING, "unsupported depth %d", dri2_surf->depth); } } @@ -177,12 +178,23 @@ swrastGetImage(__DRIdrawable * read, } +static xcb_screen_t * +get_xcb_screen(xcb_screen_iterator_t iter, int screen) +{ + for (; iter.rem; --screen, xcb_screen_next(&iter)) + if (screen == 0) + return iter.data; + + return NULL; +} + + /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ static _EGLSurface * dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, - _EGLConfig *conf, EGLNativeWindowType native_window, + _EGLConfig *conf, void *native_surface, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); @@ -192,7 +204,11 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, xcb_get_geometry_reply_t *reply; xcb_screen_iterator_t s; xcb_generic_error_t *error; - xcb_drawable_t window = (uintptr_t )native_window; + xcb_drawable_t drawable; + xcb_screen_t *screen; + + STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface)); + drawable = (uintptr_t) native_surface; (void) drv; @@ -207,13 +223,23 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, dri2_surf->region = XCB_NONE; if (type == EGL_PBUFFER_BIT) { - dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + screen = get_xcb_screen(s, dri2_dpy->screen); + if (!screen) { + _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface"); + goto cleanup_surf; + } + + dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, - dri2_surf->drawable, s.data->root, + dri2_surf->drawable, screen->root, dri2_surf->base.Width, dri2_surf->base.Height); } else { - dri2_surf->drawable = window; + if (!drawable) { + _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface"); + goto cleanup_surf; + } + dri2_surf->drawable = drawable; } if (dri2_dpy->dri2) { @@ -235,12 +261,6 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); goto cleanup_pixmap; } - - if (dri2_dpy->dri2) { - xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); - } else { - swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE)); - } if (type != EGL_PBUFFER_BIT) { cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); @@ -253,9 +273,19 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, dri2_surf->base.Width = reply->width; dri2_surf->base.Height = reply->height; + dri2_surf->depth = reply->depth; free(reply); } + if (dri2_dpy->dri2) { + xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); + } else { + if (type == EGL_PBUFFER_BIT) { + dri2_surf->depth = _eglGetConfigKey(conf, EGL_BUFFER_SIZE); + } + swrastCreateDrawable(dri2_dpy, dri2_surf); + } + /* we always copy the back buffer to front */ dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE; @@ -277,14 +307,14 @@ dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, */ static _EGLSurface * dri2_x11_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, - _EGLConfig *conf, EGLNativeWindowType window, + _EGLConfig *conf, void *native_window, const EGLint *attrib_list) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); _EGLSurface *surf; surf = dri2_x11_create_surface(drv, disp, EGL_WINDOW_BIT, conf, - window, attrib_list); + native_window, attrib_list); if (surf != NULL) { /* When we first create the DRI2 drawable, its swap interval on the * server side is 1. @@ -300,11 +330,11 @@ dri2_x11_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, static _EGLSurface * dri2_x11_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, - _EGLConfig *conf, EGLNativePixmapType pixmap, + _EGLConfig *conf, void *native_pixmap, const EGLint *attrib_list) { return dri2_x11_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, - pixmap, attrib_list); + native_pixmap, attrib_list); } static _EGLSurface * @@ -477,21 +507,6 @@ dri2_x11_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) #endif } -static char * -dri2_x11_strndup(const char *s, int length) -{ - char *d; - - d = malloc(length + 1); - if (d == NULL) - return NULL; - - memcpy(d, s, length); - d[length] = '\0'; - - return d; -} - static EGLBoolean dri2_x11_connect(struct dri2_egl_display *dri2_dpy) { @@ -503,6 +518,7 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy) xcb_dri2_connect_cookie_t connect_cookie; xcb_generic_error_t *error; xcb_screen_iterator_t s; + xcb_screen_t *screen; char *driver_name, *device_name; const xcb_query_extension_reply_t *extension; @@ -526,9 +542,13 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy) XCB_DRI2_MINOR_VERSION); s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn, - s.data->root, - XCB_DRI2_DRIVER_TYPE_DRI); + screen = get_xcb_screen(s, dri2_dpy->screen); + if (!screen) { + _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_x11_connect"); + return EGL_FALSE; + } + connect_cookie = xcb_dri2_connect_unchecked(dri2_dpy->conn, screen->root, + XCB_DRI2_DRIVER_TYPE_DRI); xfixes_query = xcb_xfixes_query_version_reply (dri2_dpy->conn, @@ -561,14 +581,14 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy) driver_name = xcb_dri2_connect_driver_name (connect); dri2_dpy->driver_name = - dri2_x11_strndup(driver_name, - xcb_dri2_connect_driver_name_length(connect)); + strndup(driver_name, + xcb_dri2_connect_driver_name_length(connect)); device_name = xcb_dri2_connect_device_name (connect); dri2_dpy->device_name = - dri2_x11_strndup(device_name, - xcb_dri2_connect_device_name_length(connect)); + strndup(device_name, + xcb_dri2_connect_device_name_length(connect)); if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { free(dri2_dpy->device_name); @@ -588,11 +608,19 @@ dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id) xcb_dri2_authenticate_reply_t *authenticate; xcb_dri2_authenticate_cookie_t authenticate_cookie; xcb_screen_iterator_t s; + xcb_screen_t *screen; int ret = 0; s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); + + screen = get_xcb_screen(s, dri2_dpy->screen); + if (!screen) { + _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_x11_authenticate"); + return -1; + } + authenticate_cookie = - xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, id); + xcb_dri2_authenticate_unchecked(dri2_dpy->conn, screen->root, id); authenticate = xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); @@ -641,7 +669,7 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, }; s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); - d = xcb_screen_allowed_depths_iterator(s.data); + d = xcb_screen_allowed_depths_iterator(get_xcb_screen(s, dri2_dpy->screen)); id = 1; surface_type = @@ -751,8 +779,7 @@ dri2_x11_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; - if (dri2_dpy->flush) - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); + 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); @@ -861,12 +888,15 @@ dri2_x11_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, static EGLBoolean dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, - EGLNativePixmapType native_target) + void *native_pixmap_target) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); xcb_gcontext_t gc; - xcb_pixmap_t target = (uintptr_t )native_target; + xcb_pixmap_t target; + + STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target)); + target = (uintptr_t) native_pixmap_target; (void) drv; @@ -992,21 +1022,65 @@ dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, } } +static EGLBoolean +dri2_x11_get_sync_values(_EGLDisplay *display, _EGLSurface *surface, + EGLuint64KHR *ust, EGLuint64KHR *msc, + EGLuint64KHR *sbc) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(display); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); + xcb_dri2_get_msc_cookie_t cookie; + xcb_dri2_get_msc_reply_t *reply; + + 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; + } + + *ust = ((EGLuint64KHR) reply->ust_hi << 32) | reply->ust_lo; + *msc = ((EGLuint64KHR) reply->msc_hi << 32) | reply->msc_lo; + *sbc = ((EGLuint64KHR) reply->sbc_hi << 32) | reply->sbc_lo; + free(reply); + + return EGL_TRUE; +} + static struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = { .authenticate = NULL, .create_window_surface = dri2_x11_create_window_surface, .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, .swap_buffers = dri2_x11_swap_buffers, + .swap_buffers_region = dri2_fallback_swap_buffers_region, + .post_sub_buffer = dri2_fallback_post_sub_buffer, + .copy_buffers = dri2_x11_copy_buffers, + .query_buffer_age = dri2_fallback_query_buffer_age, + .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, + .get_sync_values = dri2_fallback_get_sync_values, }; static struct dri2_egl_display_vtbl dri2_x11_display_vtbl = { .authenticate = dri2_x11_authenticate, .create_window_surface = dri2_x11_create_window_surface, .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_x11_create_image_khr, .swap_interval = dri2_x11_swap_interval, .swap_buffers = dri2_x11_swap_buffers, .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage, + .swap_buffers_region = dri2_x11_swap_buffers_region, + .post_sub_buffer = dri2_x11_post_sub_buffer, + .copy_buffers = dri2_x11_copy_buffers, + .query_buffer_age = dri2_fallback_query_buffer_age, + .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image, + .get_sync_values = dri2_x11_get_sync_values, }; static EGLBoolean @@ -1014,25 +1088,19 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy; - drv->API.CreatePbufferSurface = dri2_x11_create_pbuffer_surface; - drv->API.DestroySurface = dri2_x11_destroy_surface; - drv->API.CopyBuffers = dri2_x11_copy_buffers; - - drv->API.SwapBuffersRegionNOK = NULL; - drv->API.CreateImageKHR = NULL; - drv->API.DestroyImageKHR = NULL; - drv->API.CreateDRMImageMESA = NULL; - drv->API.ExportDRMImageMESA = NULL; - dri2_dpy = calloc(1, sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); disp->DriverData = (void *) dri2_dpy; if (disp->PlatformDisplay == NULL) { - dri2_dpy->conn = xcb_connect(0, 0); + dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen); + dri2_dpy->own_device = true; } else { - dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); + Display *dpy = disp->PlatformDisplay; + + dri2_dpy->conn = XGetXCBConnection(dpy); + dri2_dpy->screen = DefaultScreen(dpy); } if (xcb_connection_has_error(dri2_dpy->conn)) { @@ -1040,11 +1108,16 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) goto cleanup_dpy; } + /* + * Every hardware driver_name is set using strdup. Doing the same in + * here will allow is to simply free the memory at dri2_terminate(). + */ + dri2_dpy->driver_name = strdup("swrast"); if (!dri2_load_driver_swrast(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.base.version = 2; dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo; dri2_dpy->swrast_loader_extension.putImage = swrastPutImage; dri2_dpy->swrast_loader_extension.getImage = swrastGetImage; @@ -1061,10 +1134,6 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) goto cleanup_configs; } - /* we're supporting EGL 1.4 */ - disp->VersionMajor = 1; - disp->VersionMinor = 4; - /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. */ @@ -1078,6 +1147,7 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp) cleanup_driver: dlclose(dri2_dpy->driver); cleanup_conn: + free(dri2_dpy->driver_name); if (disp->PlatformDisplay == NULL) xcb_disconnect(dri2_dpy->conn); cleanup_dpy: @@ -1137,22 +1207,19 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) { struct dri2_egl_display *dri2_dpy; - drv->API.CreatePbufferSurface = dri2_x11_create_pbuffer_surface; - drv->API.DestroySurface = dri2_x11_destroy_surface; - drv->API.CopyBuffers = dri2_x11_copy_buffers; - drv->API.CreateImageKHR = dri2_x11_create_image_khr; - drv->API.SwapBuffersRegionNOK = dri2_x11_swap_buffers_region; - drv->API.PostSubBufferNV = dri2_x11_post_sub_buffer; - dri2_dpy = calloc(1, sizeof *dri2_dpy); if (!dri2_dpy) return _eglError(EGL_BAD_ALLOC, "eglInitialize"); disp->DriverData = (void *) dri2_dpy; if (disp->PlatformDisplay == NULL) { - dri2_dpy->conn = xcb_connect(0, 0); + dri2_dpy->conn = xcb_connect(0, &dri2_dpy->screen); + dri2_dpy->own_device = true; } else { - dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); + Display *dpy = disp->PlatformDisplay; + + dri2_dpy->conn = XGetXCBConnection(dpy); + dri2_dpy->screen = DefaultScreen(dpy); } if (xcb_connection_has_error(dri2_dpy->conn)) { @@ -1168,16 +1235,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) if (!dri2_load_driver(disp)) goto cleanup_conn; -#ifdef O_CLOEXEC - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC); - if (dri2_dpy->fd == -1 && errno == EINVAL) -#endif - { - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); - if (dri2_dpy->fd != -1) - fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) | - FD_CLOEXEC); - } + dri2_dpy->fd = loader_open_device(dri2_dpy->device_name); if (dri2_dpy->fd == -1) { _eglLog(_EGL_WARNING, "DRI2: could not open %s (%s)", dri2_dpy->device_name, @@ -1217,15 +1275,11 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) dri2_x11_setup_swap_interval(dri2_dpy); - if (dri2_dpy->conn) { - if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp)) - goto cleanup_configs; - } - disp->Extensions.KHR_image_pixmap = EGL_TRUE; disp->Extensions.NOK_swap_region = EGL_TRUE; disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; disp->Extensions.NV_post_sub_buffer = EGL_TRUE; + disp->Extensions.CHROMIUM_sync_control = EGL_TRUE; #ifdef HAVE_WAYLAND_PLATFORM disp->Extensions.WL_bind_wayland_display = EGL_TRUE; @@ -1236,10 +1290,6 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp) goto cleanup_configs; } - /* we're supporting EGL 1.4 */ - disp->VersionMajor = 1; - disp->VersionMinor = 4; - /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. */