From cbb7eb73b5399e31a7afb800363504d539df0ecf Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Wed, 27 May 2015 12:08:45 +0200 Subject: xwayland: Throttle our cursor surface updates with a frame callback In some extreme cases with animated cursors at a high frame rate we could end up filling the wl_display outgoing buffer and end up with wl_display_flush() failing. In any case, using the frame callback to throttle ourselves is the right thing to do. Signed-off-by: Rui Matos Reviewed-by: Daniel Stone Signed-off-by: Keith Packard --- hw/xwayland/xwayland-cursor.c | 26 ++++++++++++++++++++++++++ hw/xwayland/xwayland-input.c | 2 ++ hw/xwayland/xwayland.h | 4 +++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index 5a9d1fe70..c137e1ec0 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -82,6 +82,23 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) return xwl_shm_destroy_pixmap(pixmap); } +static void +frame_callback(void *data, + struct wl_callback *callback, + uint32_t time) +{ + struct xwl_seat *xwl_seat = data; + xwl_seat->cursor_frame_cb = NULL; + if (xwl_seat->cursor_needs_update) { + xwl_seat->cursor_needs_update = FALSE; + xwl_seat_set_cursor(xwl_seat); + } +} + +static const struct wl_callback_listener frame_listener = { + frame_callback +}; + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat) { @@ -98,6 +115,11 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) return; } + if (xwl_seat->cursor_frame_cb) { + xwl_seat->cursor_needs_update = TRUE; + return; + } + cursor = xwl_seat->x_cursor; pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); stride = cursor->bits->width * 4; @@ -117,6 +139,10 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) wl_surface_damage(xwl_seat->cursor, 0, 0, xwl_seat->x_cursor->bits->width, xwl_seat->x_cursor->bits->height); + + xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor); + wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat); + wl_surface_commit(xwl_seat->cursor); } diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 78d9702ac..a6fbab5bb 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -563,6 +563,8 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) RemoveDevice(xwl_seat->keyboard, FALSE); wl_seat_destroy(xwl_seat->seat); wl_surface_destroy(xwl_seat->cursor); + if (xwl_seat->cursor_frame_cb) + wl_callback_destroy(xwl_seat->cursor_frame_cb); wl_array_release(&xwl_seat->keys); free(xwl_seat); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index cfb343d36..28b0c995e 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -115,12 +115,14 @@ struct xwl_seat { struct wl_pointer *wl_pointer; struct wl_keyboard *wl_keyboard; struct wl_array keys; - struct wl_surface *cursor; struct xwl_window *focus_window; uint32_t id; uint32_t pointer_enter_serial; struct xorg_list link; CursorPtr x_cursor; + struct wl_surface *cursor; + struct wl_callback *cursor_frame_cb; + Bool cursor_needs_update; size_t keymap_size; char *keymap; -- cgit v1.2.3