blob: 60c083696b25be35141317b7541d63e03ee2a43a [file] [log] [blame]
From 04795169895335c2609b71da83ef675642c9ecb4 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 xserver] 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 c27787018..978df6ab6 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -465,6 +465,7 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)
BoxPtr box;
struct wl_buffer *buffer;
PixmapPtr pixmap;
+ int i;
xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
&xwl_screen->damage_window_list, link_damage) {
@@ -485,9 +486,20 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)
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);
--
2.11.0