diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2022-03-15 17:47:56 +0100 |
---|---|---|
committer | Olivier Fourdan <ofourdan@redhat.com> | 2022-03-24 09:22:29 +0100 |
commit | 1a7e4e72182cf530504ea88053b0652872da3c13 (patch) | |
tree | 2925b11a26a34c565b66ee70dc127888bc61d341 | |
parent | 88ed88e8a70a759f5269f828fc0e54b1120c4a5b (diff) |
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 | 17 | ||||
-rw-r--r-- | hw/xwayland/xwayland-present.h | 3 | ||||
-rw-r--r-- | hw/xwayland/xwayland-window.c | 12 |
3 files changed, 25 insertions, 7 deletions
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index d727f8419..ce74482ef 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -66,6 +66,7 @@ xwl_present_window_get_priv(WindowPtr window) if (!xwl_present_window) return NULL; + xwl_present_window->window = window; xwl_present_window->msc = 1; xwl_present_window->ust = GetTimeInMicros(); @@ -127,14 +128,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; @@ -505,8 +508,8 @@ xwl_present_queue_vblank(ScreenPtr screen, xorg_list_del(&event->vblank.event_queue); xorg_list_append(&event->vblank.event_queue, &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); @@ -700,14 +703,14 @@ 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); } + 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 5d880e822..ab7f04a3b 100644 --- a/hw/xwayland/xwayland-present.h +++ b/hw/xwayland/xwayland-present.h @@ -35,6 +35,8 @@ #ifdef GLAMOR_HAS_GBM struct xwl_present_window { + WindowPtr window; + struct xorg_list frame_callback_list; uint64_t msc; @@ -59,6 +61,7 @@ struct xwl_present_event { PixmapPtr pixmap; }; +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 |