This change enables to change the window pixmap, and have xwayland send the correct buffer to the Wayland compositor.
Signed-off-by: Axel Davy <axel.d...@ens.fr> --- v2: fix indentation and remove a call that had to be in patch 4 hw/xfree86/xwayland/xwayland-drm.c | 10 +++- hw/xfree86/xwayland/xwayland-private.h | 10 +++- hw/xfree86/xwayland/xwayland-window.c | 83 +++++++++++++++++++++++++++++----- hw/xfree86/xwayland/xwayland.c | 38 ++++++++++------ 4 files changed, 113 insertions(+), 28 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c index 5250857..30ec176 100644 --- a/hw/xfree86/xwayland/xwayland-drm.c +++ b/hw/xfree86/xwayland/xwayland-drm.c @@ -217,6 +217,7 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window, VisualID visual; WindowPtr window = xwl_window->window; ScreenPtr screen = window->drawable.pScreen; + struct wl_buffer *buffer; uint32_t format; int i; @@ -238,7 +239,7 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window, break; } - xwl_window->buffer = + buffer = wl_drm_create_buffer(xwl_window->xwl_screen->drm, name, pixmap->drawable.width, @@ -246,5 +247,10 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window, pixmap->devKind, format); - return xwl_window->buffer ? Success : BadDrawable; + if (!buffer) + return BadDrawable; + + xwl_pixmap_attach_buffer(pixmap, buffer); + + return Success; } diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h index bdecf8a..853ab3b 100644 --- a/hw/xfree86/xwayland/xwayland-private.h +++ b/hw/xfree86/xwayland/xwayland-private.h @@ -29,13 +29,16 @@ struct xwl_window { struct xwl_screen *xwl_screen; struct wl_surface *surface; - struct wl_buffer *buffer; WindowPtr window; DamagePtr damage; struct xorg_list link; struct xorg_list link_damage; }; +struct xwl_pixmap { + struct wl_buffer *buffer; +}; + struct xwl_output; struct xwl_screen { @@ -72,6 +75,7 @@ struct xwl_screen { RealizeWindowProcPtr RealizeWindow; UnrealizeWindowProcPtr UnrealizeWindow; SetWindowPixmapProcPtr SetWindowPixmap; + DestroyPixmapProcPtr DestroyPixmap; MoveWindowProcPtr MoveWindow; miPointerSpriteFuncPtr sprite_funcs; }; @@ -135,6 +139,10 @@ void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); void xwl_output_remove(struct xwl_output *output); +void xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer); +struct xwl_pixmap *xwl_window_get_buffer(struct xwl_window *xwl_window); +struct xwl_window *get_xwl_window(WindowPtr window); + extern const struct xserver_listener xwl_server_listener; #endif /* _XWAYLAND_PRIVATE_H_ */ diff --git a/hw/xfree86/xwayland/xwayland-window.c b/hw/xfree86/xwayland/xwayland-window.c index a2a8206..1e6c09b 100644 --- a/hw/xfree86/xwayland/xwayland-window.c +++ b/hw/xfree86/xwayland/xwayland-window.c @@ -41,6 +41,13 @@ #include "xserver-client-protocol.h" static DevPrivateKeyRec xwl_window_private_key; +static DevPrivateKeyRec xwl_pixmap_private_key; + +struct xwl_window * +get_xwl_window(WindowPtr window) +{ + return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key); +} static void free_pixmap(void *data, struct wl_callback *callback, uint32_t time) @@ -56,25 +63,38 @@ static const struct wl_callback_listener free_pixmap_listener = { free_pixmap, }; +void +xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer) +{ + struct xwl_pixmap *xwl_pixmap = calloc(sizeof *xwl_pixmap, 1); + if (!xwl_pixmap) { + wl_buffer_destroy(buffer); + return; + } + xwl_pixmap->buffer = buffer; + dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap); +} + static void xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap) { struct xwl_screen *xwl_screen = xwl_window->xwl_screen; struct wl_callback *callback; + struct xwl_pixmap *xwl_pixmap = + dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); - /* We can safely destroy the buffer because we only use one buffer - * per surface in xwayland model */ - if (xwl_window->buffer) - wl_buffer_destroy(xwl_window->buffer); - - xwl_screen->driver->create_window_buffer(xwl_window, pixmap); + if (!xwl_pixmap) { + xwl_screen->driver->create_window_buffer(xwl_window, pixmap); + xwl_pixmap = + dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); - if (!xwl_window->buffer) { - ErrorF("failed to create buffer\n"); - return; + if (!xwl_pixmap) { + ErrorF("failed to create buffer\n"); + return; + } } - wl_surface_attach(xwl_window->surface, xwl_window->buffer, 0, 0); + wl_surface_attach(xwl_window->surface, xwl_pixmap->buffer, 0, 0); wl_surface_damage(xwl_window->surface, 0, 0, pixmap->drawable.width, pixmap->drawable.height); @@ -84,6 +104,23 @@ xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap) pixmap->refcnt++; } +struct xwl_pixmap * +xwl_window_get_buffer(struct xwl_window *xwl_window) +{ + PixmapPtr pixmap = (*xwl_window->xwl_screen->screen->GetWindowPixmap) + (xwl_window->window); + struct xwl_pixmap *xwl_pixmap = + dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); + + if (!xwl_pixmap) { + xwl_window_attach(xwl_window, pixmap); + return dixLookupPrivate(&pixmap->devPrivates, + &xwl_pixmap_private_key); + } else { + return xwl_pixmap; + } +} + static void damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) { @@ -184,8 +221,6 @@ xwl_unrealize_window(WindowPtr window) if (!xwl_window) return ret; - if (xwl_window->buffer) - wl_buffer_destroy(xwl_window->buffer); wl_surface_destroy(xwl_window->surface); xorg_list_del(&xwl_window->link); if (RegionNotEmpty(DamageRegion(xwl_window->damage))) @@ -218,6 +253,24 @@ xwl_set_window_pixmap(WindowPtr window, PixmapPtr pixmap) xwl_window_attach(xwl_window, pixmap); } +static Bool +xwl_destroy_pixmap(PixmapPtr pixmap) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + struct xwl_screen *xwl_screen = xwl_screen_get(screen); + if (pixmap->refcnt == 1) { + struct xwl_pixmap *xwl_pixmap = + dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); + if (xwl_pixmap) { + wl_buffer_destroy(xwl_pixmap->buffer); + dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, + NULL); + free(xwl_pixmap); + } + } + return xwl_screen->DestroyPixmap(pixmap); +} + static void xwl_move_window(WindowPtr window, int x, int y, WindowPtr sibling, VTKind kind) @@ -245,6 +298,9 @@ xwl_screen_init_window(struct xwl_screen *xwl_screen, ScreenPtr screen) if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0)) return BadAlloc; + if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0)) + return BadAlloc; + xwl_screen->RealizeWindow = screen->RealizeWindow; screen->RealizeWindow = xwl_realize_window; @@ -254,6 +310,9 @@ xwl_screen_init_window(struct xwl_screen *xwl_screen, ScreenPtr screen) xwl_screen->SetWindowPixmap = screen->SetWindowPixmap; screen->SetWindowPixmap = xwl_set_window_pixmap; + xwl_screen->DestroyPixmap = screen->DestroyPixmap; + screen->DestroyPixmap = xwl_destroy_pixmap; + xwl_screen->MoveWindow = screen->MoveWindow; screen->MoveWindow = xwl_move_window; diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c index c70a52d..15308b0 100644 --- a/hw/xfree86/xwayland/xwayland.c +++ b/hw/xfree86/xwayland/xwayland.c @@ -247,6 +247,7 @@ xwl_create_window_buffer_shm(struct xwl_window *xwl_window, WindowPtr window = xwl_window->window; ScreenPtr screen = window->drawable.pScreen; VisualID visual = wVisual(window); + struct wl_buffer *buffer; uint32_t format; int size, stride, bpp, i; @@ -277,13 +278,18 @@ xwl_create_window_buffer_shm(struct xwl_window *xwl_window, size = stride * pixmap->drawable.height; pool = wl_shm_create_pool(xwl_window->xwl_screen->shm, fd, size); - xwl_window->buffer = wl_shm_pool_create_buffer(pool, 0, + buffer = wl_shm_pool_create_buffer(pool, 0, pixmap->drawable.width, pixmap->drawable.height, stride, format); wl_shm_pool_destroy(pool); - return xwl_window->buffer ? Success : BadDrawable; + if (!buffer) + return BadDrawable; + + xwl_pixmap_attach_buffer(pixmap, buffer); + + return Success; } void xwl_screen_close(struct xwl_screen *xwl_screen) @@ -302,7 +308,6 @@ void xwl_screen_close(struct xwl_screen *xwl_screen) } xorg_list_for_each_entry_safe(xwl_window, wtmp, &xwl_screen->window_list, link) { - wl_buffer_destroy(xwl_window->buffer); wl_surface_destroy(xwl_window->surface); free(xwl_window); } @@ -334,22 +339,29 @@ void xwl_screen_post_damage(struct xwl_screen *xwl_screen) RegionPtr region; BoxPtr box; int count, i; + struct xwl_pixmap *xwl_pixmap; xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list, link_damage) { region = DamageRegion(xwl_window->damage); count = RegionNumRects(region); - for (i = 0; i < count; i++) { - box = &RegionRects(region)[i]; - wl_surface_damage(xwl_window->surface, - box->x1, box->y1, - box->x2 - box->x1, - box->y2 - box->y1); + xwl_pixmap = xwl_window_get_buffer(xwl_window); + /* in the case we have no xwl_buffer associated to a xwl_window, + * because of incompatible pixmap, or memory shortage, we are + * going to retry later to create the buffer */ + if (xwl_pixmap) { + for (i = 0; i < count; i++) { + box = &RegionRects(region)[i]; + wl_surface_damage(xwl_window->surface, + box->x1, box->y1, + box->x2 - box->x1, + box->y2 - box->y1); + } + wl_surface_attach(xwl_window->surface, + xwl_pixmap->buffer, + 0, 0); + wl_surface_commit(xwl_window->surface); } - wl_surface_attach(xwl_window->surface, - xwl_window->buffer, - 0, 0); - wl_surface_commit(xwl_window->surface); DamageEmpty(xwl_window->damage); } -- 1.8.3.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel