From 0a7b09a041900069aa496ee02a29822203fbcbb2 Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Sat, 30 Mar 2024 07:42:53 -0700 Subject: [PATCH] xwayland: re-compute target msc during xwl_present_re_execute If a presentation request is delayed while waiting for a fence, the original target msc may no longer be correct. Instead, we should compute a new target msc in xwl_present_re_execute. Signed-off-by: Erik Kurzinger Part-of: --- hw/xwayland/xwayland-present.c | 52 +++++++++++++++++++++++++++------- hw/xwayland/xwayland-present.h | 5 +++- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index 91dc396fb..eee20c4ce 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -215,6 +215,13 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) static void xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); +static int +xwl_present_queue_vblank(ScreenPtr screen, + WindowPtr present_window, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc); + static uint32_t xwl_present_query_capabilities(present_screen_priv_ptr screen_priv) { @@ -237,6 +244,18 @@ xwl_present_get_ust_msc(ScreenPtr screen, return Success; } +static uint64_t +xwl_present_get_exec_msc(uint32_t options, uint64_t target_msc) +{ + /* Synchronous Xwayland presentations always complete (at least) one frame after they + * are executed + */ + if (options & PresentOptionAsyncMayTear) + return target_msc; + + return target_msc - 1; +} + /* * When the wait fence or previous flip is completed, it's time * to re-try the request @@ -244,9 +263,27 @@ xwl_present_get_ust_msc(ScreenPtr screen, static void xwl_present_re_execute(present_vblank_ptr vblank) { + struct xwl_present_event *event = xwl_present_event_from_vblank(vblank); uint64_t ust = 0, crtc_msc = 0; (void) xwl_present_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc); + /* re-compute target / exec msc */ + vblank->target_msc = present_get_target_msc(0, crtc_msc, + event->divisor, + event->remainder, + event->options); + vblank->exec_msc = xwl_present_get_exec_msc(event->options, + vblank->target_msc); + + vblank->queued = TRUE; + if (msc_is_after(vblank->exec_msc, crtc_msc) && + xwl_present_queue_vblank(vblank->screen, vblank->window, + vblank->crtc, + vblank->event_id, + vblank->exec_msc) == Success) { + return; + } + xwl_present_execute(vblank, ust, crtc_msc); } @@ -818,7 +855,7 @@ xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage) if (xwl_window->tearing_control) { uint32_t hint; - if (event->async_may_tear) + if (event->options & PresentOptionAsyncMayTear) hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC; else hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC; @@ -1047,15 +1084,10 @@ xwl_present_pixmap(WindowPtr window, } vblank->event_id = ++xwl_present_event_id; - event->async_may_tear = options & PresentOptionAsyncMayTear; - - /* Synchronous Xwayland presentations always complete (at least) one frame after they - * are executed - */ - if (event->async_may_tear) - vblank->exec_msc = vblank->target_msc; - else - vblank->exec_msc = vblank->target_msc - 1; + event->options = options; + event->divisor = divisor; + event->remainder = remainder; + vblank->exec_msc = xwl_present_get_exec_msc(options, vblank->target_msc); vblank->queued = TRUE; if (crtc_msc < vblank->exec_msc) { diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h index 34ec0422f..ced79868f 100644 --- a/hw/xwayland/xwayland-present.h +++ b/hw/xwayland/xwayland-present.h @@ -58,8 +58,11 @@ struct xwl_present_event { present_vblank_rec vblank; PixmapPtr pixmap; - Bool async_may_tear; Bool copy_executed; + + uint32_t options; + uint64_t divisor; + uint64_t remainder; }; Bool xwl_present_entered_for_each_frame_callback(void);