[PATCH 2/2] xwayland: Implement throttling for surfaces based on the frame event

Jasper St. Pierre jstpierre at mecheye.net
Mon Jun 30 17:29:34 PDT 2014


This implements simple throttling that keeps us to one attach per
frame. There isn't really an active performance benefit, since the
buffers will be redrawn only once per frame anyway, but it does cut down
on the chatty network traffic. Since the Wayland sockets might fill
up as well, the cut down on the volume of data we send out also provides
us with a big stability benefit.

Namely, mutter is a lot more stable running gtkperf, a fairly intensive
X11 application, after this change.
---
 hw/xwayland/xwayland.c | 35 ++++++++++++++++++++++++++++++-----
 hw/xwayland/xwayland.h |  1 +
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 17b7bf7..e0ae2a9 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -308,6 +308,9 @@ xwl_unrealize_window(WindowPtr window)
         xorg_list_del(&xwl_window->link_damage);
     DamageUnregister(xwl_window->damage);
     DamageDestroy(xwl_window->damage);
+    if (xwl_window->frame_callback)
+        wl_callback_destroy(xwl_window->frame_callback);
+
     free(xwl_window);
     dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
 
@@ -321,17 +324,35 @@ xwl_save_screen(ScreenPtr pScreen, int on)
 }
 
 static void
+frame_callback(void *data,
+               struct wl_callback *callback,
+               uint32_t time)
+{
+    struct xwl_window *xwl_window = data;
+    xwl_window->frame_callback = NULL;
+}
+
+static const struct wl_callback_listener frame_listener = {
+    frame_callback
+};
+
+static void
 xwl_screen_post_damage(struct xwl_screen *xwl_screen)
 {
-    struct xwl_window *xwl_window;
+    struct xwl_window *xwl_window, *next_xwl_window;
     RegionPtr region;
     BoxPtr box;
     int count, i;
     struct wl_buffer *buffer;
     PixmapPtr pixmap;
 
-    xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list,
-                             link_damage) {
+    xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
+                                  &xwl_screen->damage_window_list, link_damage) {
+        /* If we're waiting on a frame callback from the server,
+         * don't attach a new buffer. */
+        if (xwl_window->frame_callback)
+            continue;
+
         region = DamageRegion(xwl_window->damage);
         count = RegionNumRects(region);
 
@@ -351,11 +372,15 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)
                               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);
+
         wl_surface_commit(xwl_window->surface);
         DamageEmpty(xwl_window->damage);
-    }
 
-    xorg_list_init(&xwl_screen->damage_window_list);
+        xorg_list_del(&xwl_window->link_damage);
+    }
 }
 
 static void
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index fc68550..51ed8d8 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -103,6 +103,7 @@ struct xwl_window {
     WindowPtr window;
     DamagePtr damage;
     struct xorg_list link_damage;
+    struct wl_callback *frame_callback;
 };
 
 #define MODIFIER_META 0x01
-- 
2.0.0



More information about the xorg-devel mailing list