From 5ecc0315a2b9bea44ace886f5706a7a3f5cbc4f6 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Mon, 30 Jun 2014 13:53:50 -0400 Subject: [PATCH] xwayland: Implement throttling for surfaces based on the frame event 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. Reviewed-by: Daniel Stone Signed-off-by: Jasper St. Pierre --- 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 17b7bf7fd..e0ae2a957 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); @@ -320,18 +323,36 @@ xwl_save_screen(ScreenPtr pScreen, int on) return TRUE; } +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 60b0c2964..bfffa712f 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -102,6 +102,7 @@ struct xwl_window { WindowPtr window; DamagePtr damage; struct xorg_list link_damage; + struct wl_callback *frame_callback; }; #define MODIFIER_META 0x01