diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2022-03-15 17:47:56 +0100 |
---|---|---|
committer | Olivier Fourdan <fourdan@gmail.com> | 2022-07-20 14:41:01 +0000 |
commit | b97c7c78c544a0cb0684a154a17c59d8c89be4a6 (patch) | |
tree | d295815901b9562ad48229916ad3940dc63f8436 | |
parent | bd134231e282d9eb126b6fdaa40bb383180fa72b (diff) | |
download | xserver-b97c7c78c544a0cb0684a154a17c59d8c89be4a6.tar.gz |
xwayland: Always hook up frame_callback_list in xwl_present_queue_vblank
Even if there's no pending frame callback yet.
Without this, if there was no pending frame callback yet in
xwl_present_queue_vblank, xwl_present_msc_bump would only get called
from xwl_present_timer_callback, resulting in the MSC ticking at ~58
Hertz.
Doing this requires some adjustments elsewhere:
1. xwl_present_reset_timer needs to check for a pending frame callback
as well.
2. xwl_window_create_frame_callback needs to call
xwl_present_reset_timer for all child windows hooked up to
frame_callback_list, to make sure the timer length takes the pending
frame callback into account.
3. xwl_present_flip needs to hook up the window to frame_callback_list
before calling xwl_window_create_frame_callback, for 2. to work.
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1309
Fixes: 9b31358c52e9 ("xwayland: Use frame callbacks for Present vblank events")
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
(cherry picked from commit 9e5a3796108e2b89212fa440f80e918d24b971c8)
-rw-r--r-- | hw/xwayland/xwayland-present.c | 16 | ||||
-rw-r--r-- | hw/xwayland/xwayland-present.h | 1 | ||||
-rw-r--r-- | hw/xwayland/xwayland-window.c | 12 |
3 files changed, 22 insertions, 7 deletions
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index 1a99228a1..7ae13e649 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -98,14 +98,16 @@ xwl_present_has_pending_events(struct xwl_present_window *xwl_present_window) !xorg_list_is_empty(&xwl_present_window->wait_list); } -static void +void xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) { if (xwl_present_has_pending_events(xwl_present_window)) { + struct xwl_window *xwl_window = xwl_window_from_window(xwl_present_window->window); CARD32 now = GetTimeInMillis(); CARD32 timeout; - if (!xorg_list_is_empty(&xwl_present_window->frame_callback_list)) + if (xwl_window && xwl_window->frame_callback && + !xorg_list_is_empty(&xwl_present_window->frame_callback_list)) timeout = TIMER_LEN_FLIP; else timeout = TIMER_LEN_COPY; @@ -359,8 +361,8 @@ xwl_present_queue_vblank(WindowPtr present_window, xorg_list_append(&event->list, &xwl_present_window->wait_list); - /* If there's a pending frame callback, use that */ - if (xwl_window && xwl_window->frame_callback && + /* Hook up to frame callback */ + if (xwl_window && xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { xorg_list_add(&xwl_present_window->frame_callback_list, &xwl_window->frame_callback_list); @@ -495,9 +497,6 @@ xwl_present_flip(WindowPtr present_window, /* We can flip directly to the main surface (full screen window without clips) */ wl_surface_attach(xwl_window->surface, buffer, 0, 0); - if (!xwl_window->frame_callback) - xwl_window_create_frame_callback(xwl_window); - if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { xorg_list_add(&xwl_present_window->frame_callback_list, &xwl_window->frame_callback_list); @@ -506,6 +505,9 @@ xwl_present_flip(WindowPtr present_window, /* Realign timer */ xwl_present_reset_timer(xwl_present_window); + if (!xwl_window->frame_callback) + xwl_window_create_frame_callback(xwl_window); + xwl_surface_damage(xwl_window->xwl_screen, xwl_window->surface, damage_box->x1 - present_window->drawable.x, damage_box->y1 - present_window->drawable.y, diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h index 40bd79459..ce91f557b 100644 --- a/hw/xwayland/xwayland-present.h +++ b/hw/xwayland/xwayland-present.h @@ -64,6 +64,7 @@ struct xwl_present_event { struct xorg_list list; }; +void xwl_present_reset_timer(struct xwl_present_window *xwl_present_window); void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window); Bool xwl_present_init(ScreenPtr screen); void xwl_present_cleanup(WindowPtr window); diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c index 92bcae326..41061e344 100644 --- a/hw/xwayland/xwayland-window.c +++ b/hw/xwayland/xwayland-window.c @@ -765,6 +765,18 @@ xwl_window_create_frame_callback(struct xwl_window *xwl_window) xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, xwl_window); + +#ifdef GLAMOR_HAS_GBM + if (xwl_window->xwl_screen->present) { + struct xwl_present_window *xwl_present_window, *tmp; + + xorg_list_for_each_entry_safe(xwl_present_window, tmp, + &xwl_window->frame_callback_list, + frame_callback_list) { + xwl_present_reset_timer(xwl_present_window); + } + } +#endif } Bool |