diff --git a/hw/xwayland/xwayland-pixmap.h b/hw/xwayland/xwayland-pixmap.h index 95eb4e1a2..036b532ef 100644 --- a/hw/xwayland/xwayland-pixmap.h +++ b/hw/xwayland/xwayland-pixmap.h @@ -45,4 +45,10 @@ void xwl_pixmap_del_buffer_release_cb(PixmapPtr pixmap); void xwl_pixmap_buffer_release_cb(void *data, struct wl_buffer *wl_buffer); Bool xwl_pixmap_init(void); +static inline Bool +xwl_is_client_pixmap(PixmapPtr pixmap) +{ + return clients[CLIENT_ID(pixmap->drawable.id)] != serverClient; +} + #endif /* XWAYLAND_PIXMAP_H */ diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c index 1fedaef19..47f27126d 100644 --- a/hw/xwayland/xwayland-window-buffers.c +++ b/hw/xwayland/xwayland-window-buffers.c @@ -78,8 +78,7 @@ xwl_window_buffer_new(struct xwl_window *xwl_window) xwl_window_buffer->pixmap = NullPixmap; xwl_window_buffer->refcnt = 1; - xorg_list_append(&xwl_window_buffer->link_buffer, - &xwl_window->window_buffers_available); + xorg_list_init(&xwl_window_buffer->link_buffer); return xwl_window_buffer; } @@ -331,7 +330,7 @@ xwl_window_realloc_pixmap(struct xwl_window *xwl_window) screen->DestroyPixmap(window_pixmap); } -static PixmapPtr +PixmapPtr xwl_window_swap_pixmap(struct xwl_window *xwl_window) { struct xwl_screen *xwl_screen = xwl_window->xwl_screen; @@ -360,17 +359,27 @@ xwl_window_swap_pixmap(struct xwl_window *xwl_window) } RegionEmpty(xwl_window_buffer->damage_region); + xorg_list_del(&xwl_window_buffer->link_buffer); + xwl_window_set_pixmap(xwl_window->window, xwl_window_buffer->pixmap); + + /* Can't re-use client pixmap as a window buffer */ + if (xwl_is_client_pixmap(window_pixmap)) { + xwl_window_buffer->pixmap = NULL; + xwl_window_buffer_maybe_dispose(xwl_window_buffer); + return window_pixmap; + } } else { + /* Can't re-use client pixmap as a window buffer */ + if (!xwl_is_client_pixmap(window_pixmap)) + xwl_window_buffer = xwl_window_buffer_new(xwl_window); + window_pixmap->refcnt++; xwl_window_realloc_pixmap(xwl_window); - xwl_window_buffer = xwl_window_buffer_new(xwl_window); if (!xwl_window_buffer) return window_pixmap; } - xorg_list_del(&xwl_window_buffer->link_buffer); - xwl_window_set_pixmap(xwl_window->window, xwl_window_buffer->pixmap); xwl_window_buffer->pixmap = window_pixmap; /* Hold a reference on the buffer until it's released by the compositor */ diff --git a/hw/xwayland/xwayland-window-buffers.h b/hw/xwayland/xwayland-window-buffers.h index b1a737094..ac4c9aa6e 100644 --- a/hw/xwayland/xwayland-window-buffers.h +++ b/hw/xwayland/xwayland-window-buffers.h @@ -31,10 +31,13 @@ #include "xwayland-types.h" +struct xwl_window_buffer; + void xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window); void xwl_window_buffers_init(struct xwl_window *xwl_window); void xwl_window_buffers_dispose(struct xwl_window *xwl_window); void xwl_window_realloc_pixmap(struct xwl_window *xwl_window); +PixmapPtr xwl_window_swap_pixmap(struct xwl_window *xwl_window); PixmapPtr xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window); #endif /* XWAYLAND_WINDOW_BUFFERS_H */ diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c index ea2a986ae..d19b383d0 100644 --- a/hw/xwayland/xwayland-window.c +++ b/hw/xwayland/xwayland-window.c @@ -188,6 +188,7 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) WindowPtr window = data; struct xwl_window *xwl_window = xwl_window_get(window); struct xwl_screen *xwl_screen; + PixmapPtr window_pixmap; if (!xwl_window) return; @@ -207,6 +208,10 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) if (xorg_list_is_empty(&xwl_window->link_damage)) xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list); + + window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->window); + if (xwl_is_client_pixmap(window_pixmap)) + xwl_screen->screen->DestroyPixmap(xwl_window_swap_pixmap(xwl_window)); } static void @@ -227,7 +232,6 @@ register_damage(WindowPtr window) } DamageRegister(&window->drawable, damage); - DamageSetReportAfterOp(damage, TRUE); dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);