From f72587ecc7e1dedfb20a999a0e600b83c06a1b29 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Date: Wed, 20 Dec 2017 13:18:45 +0200 Subject: [PATCH] xwayland: reduce over-damage If an X11 app draws a little here, some there, and a tiny bit in the opposite corner, using RegionExtents for the damage to be sent to the Wayland compositor will cause massive over-damaging. However, we cannot blindly send an arbitrary number of damage rectangles, because there is a risk of overflowing the Wayland connection. If that happens, it triggers an abort in libwayland-client. Try to be more accurate with the damage by sending up to 256 rectangles per window, and fall back to extents otherwise. The number is completely arbitrary. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Daniel Stone <daniels@collabora.com> --- hw/xwayland/xwayland.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index c5a3ae7ae7..7809ad8d02 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -629,6 +629,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window) BoxPtr box; struct wl_buffer *buffer; PixmapPtr pixmap; + int i; assert(!xwl_window->frame_callback); @@ -644,9 +645,20 @@ xwl_window_post_damage(struct xwl_window *xwl_window) wl_surface_attach(xwl_window->surface, buffer, 0, 0); - box = RegionExtents(region); - wl_surface_damage(xwl_window->surface, box->x1, box->y1, - box->x2 - box->x1, box->y2 - box->y1); + /* Arbitrary limit to try to avoid flooding the Wayland + * connection. If we flood it too much anyway, this could + * abort in libwayland-client. + */ + if (RegionNumRects(region) > 256) { + box = RegionExtents(region); + wl_surface_damage(xwl_window->surface, box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); + } else { + box = RegionRects(region); + for (i = 0; i < RegionNumRects(region); i++, box++) + wl_surface_damage(xwl_window->surface, box->x1, box->y1, + box->x2 - box->x1, box->y2 - box->y1); + } xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, xwl_window); -- GitLab