xserver: Branch 'master'

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jan 10 09:30:51 UTC 2022


 hw/xwayland/xwayland-present.c |   29 ++++++++++++++++++++++++-----
 hw/xwayland/xwayland-present.h |    2 ++
 2 files changed, 26 insertions(+), 5 deletions(-)

New commits:
commit 288ec0e046c4cb975367f5ad043b76666c30fe9b
Author: Michel Dänzer <mdaenzer at redhat.com>
Date:   Fri Dec 24 19:06:47 2021 +0100

    xwayland/present: Run fallback timer callback after more than a second
    
    If the Wayland compositor doesn't send a pending frame event, e.g.
    because the Wayland surface isn't visible anywhere, it could happen that
    the timer kept getting pushed back and never fired. This resulted in an
    enormous list of pending vblank events, which could take minutes to
    process when the frame event finally arrived.
    
    Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1110
    Reviewed-by: Olivier Fourdan <ofourdan at redhat.com>
    Tested-by: Jaap Buurman <jaapbuurman at gmail.com>

diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 69c02dce4..ed497832c 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -93,6 +93,7 @@ xwl_present_free_timer(struct xwl_present_window *xwl_present_window)
 {
     TimerFree(xwl_present_window->frame_timer);
     xwl_present_window->frame_timer = NULL;
+    xwl_present_window->timer_armed = 0;
 }
 
 static CARD32
@@ -130,6 +131,7 @@ static void
 xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
 {
     if (xwl_present_has_pending_events(xwl_present_window)) {
+        CARD32 now = GetTimeInMillis();
         CARD32 timeout;
 
         if (!xorg_list_is_empty(&xwl_present_window->frame_callback_list))
@@ -137,6 +139,21 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
         else
             timeout = TIMER_LEN_COPY;
 
+        /* Make sure the timer callback runs if at least a second has passed
+         * since we first armed the timer. This can happen e.g. if the Wayland
+         * compositor doesn't send a pending frame event, e.g. because the
+         * Wayland surface isn't visible anywhere.
+         */
+        if (xwl_present_window->timer_armed) {
+            if ((int)(now - xwl_present_window->timer_armed) > 1000) {
+                xwl_present_timer_callback(xwl_present_window->frame_timer, now,
+                                           xwl_present_window);
+                return;
+            }
+        } else {
+            xwl_present_window->timer_armed = now;
+        }
+
         xwl_present_window->frame_timer = TimerSet(xwl_present_window->frame_timer,
                                                    0, timeout,
                                                    &xwl_present_timer_callback,
@@ -386,6 +403,8 @@ xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
 
     xwl_present_window->ust = GetTimeInMicros();
 
+    xwl_present_window->timer_armed = 0;
+
     if (flip_pending && flip_pending->sync_flip)
         xwl_present_flip_notify_vblank(flip_pending, xwl_present_window->ust, msc);
 
@@ -801,14 +820,14 @@ xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
         present_execute_copy(vblank, crtc_msc);
         assert(!vblank->queued);
 
+        /* Clear the pixmap field, so this will fall through to present_execute_post next time */
+        dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
+        vblank->pixmap = NULL;
+
         if (xwl_present_queue_vblank(screen, window, vblank->crtc,
                                      vblank->event_id, crtc_msc + 1)
-            == Success) {
-            /* Clear the pixmap field, so this will fall through to present_execute_post next time */
-            dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
-            vblank->pixmap = NULL;
+            == Success)
             return;
-        }
     }
 
     present_execute_post(vblank, ust, crtc_msc);
diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h
index d3eff73f4..5d880e822 100644
--- a/hw/xwayland/xwayland-present.h
+++ b/hw/xwayland/xwayland-present.h
@@ -41,6 +41,8 @@ struct xwl_present_window {
     uint64_t ust;
 
     OsTimerPtr frame_timer;
+    /* Timestamp when the current timer was first armed */
+    CARD32 timer_armed;
 
     struct wl_callback *sync_callback;
 


More information about the xorg-commit mailing list