xserver: Branch 'master' - 3 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Oct 25 15:47:54 UTC 2018


 hw/xwayland/xwayland-present.c |   79 ++++++++++++++++++++++++++---------------
 hw/xwayland/xwayland.h         |    1 
 2 files changed, 53 insertions(+), 27 deletions(-)

New commits:
commit ace551d8a2603e37b18237a52f62d627c75d9e2a
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Oct 18 17:42:01 2018 +0200

    xwayland: Complete "synchronous" Present flips from xwl_present_msc_bump
    
    Completing them from xwl_present_sync_callback had at least two issues:
    
    * It was before the MSC was incremented in xwl_present_frame_callback,
      so the MSC value in the completion event could be lower than the
      target specified by the client. This could cause hangs with the Mesa
      Vulkan drivers.
    * It allowed clients to run at a frame-rate higher than the Wayland
      compositor's frame-rate, wasting energy on generating frames which
      were never displayed. This isn't expected to happen unless the client
      specified PresentOptionAsync (in which case flips are still completed
      from xwl_present_sync_callback, allowing higher frame-rates).
    
    v2:
    * Make xwl_present_has_events return true when there's a pending
      "synchronous" flip, so those complete after at most ~1 second even if
      the Wayland server doesn't send a frame event.
    
    Bugzilla: https://bugs.freedesktop.org/106713

diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 7e9677ea4..792eaa69c 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -85,7 +85,8 @@ xwl_present_timer_callback(OsTimerPtr timer,
 static inline Bool
 xwl_present_has_events(struct xwl_present_window *xwl_present_window)
 {
-    return !xorg_list_is_empty(&xwl_present_window->event_list) ||
+    return !!xwl_present_window->sync_flip ||
+           !xorg_list_is_empty(&xwl_present_window->event_list) ||
            !xorg_list_is_empty(&xwl_present_window->release_queue);
 }
 
@@ -139,6 +140,16 @@ xwl_present_cleanup(WindowPtr window)
     }
 
     /* Clear remaining buffer releases and inform Present about free ressources */
+    event = xwl_present_window->sync_flip;
+    xwl_present_window->sync_flip = NULL;
+    if (event) {
+        if (event->buffer_released) {
+            free(event);
+        } else {
+            event->pending = FALSE;
+            event->abort = TRUE;
+        }
+    }
     xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) {
         xorg_list_del(&event->list);
         event->abort = TRUE;
@@ -199,6 +210,24 @@ xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
 
     xwl_present_window->ust = GetTimeInMicros();
 
+    event = xwl_present_window->sync_flip;
+    xwl_present_window->sync_flip = NULL;
+    if (event) {
+        event->pending = FALSE;
+
+        present_wnmd_event_notify(xwl_present_window->window, event->event_id,
+                                  xwl_present_window->ust, msc);
+
+        if (event->buffer_released) {
+            /* If the buffer was already released, clean up now */
+            present_wnmd_event_notify(xwl_present_window->window, event->event_id,
+                                      xwl_present_window->ust, msc);
+            free(event);
+        } else {
+            xorg_list_add(&event->list, &xwl_present_window->release_queue);
+        }
+    }
+
     xorg_list_for_each_entry_safe(event, tmp,
                                   &xwl_present_window->event_list,
                                   list) {
@@ -459,12 +488,17 @@ xwl_present_flip(WindowPtr present_window,
     event->event_id = event_id;
     event->xwl_present_window = xwl_present_window;
     event->buffer = buffer;
-    event->target_msc = xwl_present_window->msc;
+    event->target_msc = target_msc;
     event->pending = TRUE;
     event->abort = FALSE;
     event->buffer_released = FALSE;
 
-    xorg_list_add(&event->list, &xwl_present_window->release_queue);
+    if (sync_flip) {
+        xorg_list_init(&event->list);
+        xwl_present_window->sync_flip = event;
+    } else {
+        xorg_list_add(&event->list, &xwl_present_window->release_queue);
+    }
 
     if (buffer_created)
         wl_buffer_add_listener(buffer, &xwl_present_release_listener, NULL);
@@ -493,10 +527,13 @@ xwl_present_flip(WindowPtr present_window,
 
     wl_surface_commit(xwl_window->surface);
 
-    xwl_present_window->sync_callback = wl_display_sync(xwl_window->xwl_screen->display);
-    wl_callback_add_listener(xwl_present_window->sync_callback,
-                             &xwl_present_sync_listener,
-                             event);
+    if (!sync_flip) {
+        xwl_present_window->sync_callback =
+            wl_display_sync(xwl_window->xwl_screen->display);
+        wl_callback_add_listener(xwl_present_window->sync_callback,
+                                 &xwl_present_sync_listener,
+                                 event);
+    }
 
     wl_display_flush(xwl_window->xwl_screen->display);
     return TRUE;
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 67819e178..3f4a601fe 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -188,6 +188,7 @@ struct xwl_window {
 #ifdef GLAMOR_HAS_GBM
 struct xwl_present_window {
     struct xwl_screen *xwl_screen;
+    struct xwl_present_event *sync_flip;
     WindowPtr window;
     struct xorg_list link;
 
commit 2bfc46d4147dc0bec4cdbb80431a0f4cc1d3b030
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Oct 18 17:36:24 2018 +0200

    xwayland: Rename xwl_present_events_notify to xwl_present_msc_bump
    
    And consolidate more code from xwl_present_timer_callback and
    xwl_present_frame_callback in it.

diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index 7c626d742..7e9677ea4 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -192,11 +192,13 @@ static const struct wl_buffer_listener xwl_present_release_listener = {
 };
 
 static void
-xwl_present_events_notify(struct xwl_present_window *xwl_present_window)
+xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
 {
-    uint64_t                    msc = xwl_present_window->msc;
+    uint64_t msc = ++xwl_present_window->msc;
     struct xwl_present_event    *event, *tmp;
 
+    xwl_present_window->ust = GetTimeInMicros();
+
     xorg_list_for_each_entry_safe(event, tmp,
                                   &xwl_present_window->event_list,
                                   list) {
@@ -218,10 +220,8 @@ xwl_present_timer_callback(OsTimerPtr timer,
     struct xwl_present_window *xwl_present_window = arg;
 
     xwl_present_window->frame_timer_firing = TRUE;
-    xwl_present_window->msc++;
-    xwl_present_window->ust = GetTimeInMicros();
 
-    xwl_present_events_notify(xwl_present_window);
+    xwl_present_msc_bump(xwl_present_window);
     xwl_present_reset_timer(xwl_present_window);
 
     return 0;
@@ -242,10 +242,7 @@ xwl_present_frame_callback(void *data,
         return;
     }
 
-    xwl_present_window->msc++;
-    xwl_present_window->ust = GetTimeInMicros();
-
-    xwl_present_events_notify(xwl_present_window);
+    xwl_present_msc_bump(xwl_present_window);
 
     /* we do not need the timer anymore for this frame,
      * reset it for potentially the next one
commit 5e8b9a3a563047e3998d45e761f7a50e4b0f6cb3
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Oct 24 11:23:05 2018 +0200

    xwayland: Use xwl_present_reset_timer in xwl_present_timer_callback
    
    Apart from simplifying the code, this should also prevent a condition
    (which might only be possible with the following fix) reported in
    https://gitlab.freedesktop.org/wayland/weston/issues/115#note_52467:
    
    1. xwl_present_timer_callback indirectly calls xwl_present_reset_timer
       -> xwl_present_free_timer
    2. xwl_present_timer_callback then returns a non-0 value, so DoTimer
       calls TimerSet with the old xwl_present_window->frame_timer pointer
       which was freed in step 1 => use after free
    
    Calling xwl_present_reset_timer explicitly passes NULL to TimerSet if
    step 1 freed xwl_present_window->frame_timer, and it will allocate a new
    one.

diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index a1470751a..7c626d742 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -216,24 +216,15 @@ xwl_present_timer_callback(OsTimerPtr timer,
                            void *arg)
 {
     struct xwl_present_window *xwl_present_window = arg;
-    WindowPtr present_window = xwl_present_window->window;
-    struct xwl_window *xwl_window = xwl_window_from_window(present_window);
 
     xwl_present_window->frame_timer_firing = TRUE;
     xwl_present_window->msc++;
     xwl_present_window->ust = GetTimeInMicros();
 
     xwl_present_events_notify(xwl_present_window);
+    xwl_present_reset_timer(xwl_present_window);
 
-    if (xwl_present_has_events(xwl_present_window)) {
-        /* Still events, restart timer */
-        return xwl_present_is_flipping(present_window, xwl_window) ? TIMER_LEN_FLIP :
-                                                                     TIMER_LEN_COPY;
-    } else {
-        /* No more events, do not restart timer and delete it instead */
-        xwl_present_free_timer(xwl_present_window);
-        return 0;
-    }
+    return 0;
 }
 
 static void


More information about the xorg-commit mailing list