[gtk: 2/3] frame clock: fix scheduling



commit 887aa2abdddf18d6d6e550b3f468346a0fc63119
Author: Yariv Barkan <21448-yarivb users noreply gitlab gnome org>
Date:   Wed Jun 10 10:54:07 2020 +0300

    frame clock: fix scheduling
    
    Fix scheduling of the frame clock when we don't receive "frame drawn"
    messages from the compositor.
    
    If we received "frame drawn" events recently, then the "smooth frame
    time" would be in sync with the vsync time. When we don't receive frame
    drawn events, the "smooth frame time" is simply incremented by constant
    multiples of the refresh interval. In both cases we can use this smooth
    time as the basis for scheduling the next clock cycle.
    
    By only using the "smooth frame time" as a basis we also benefit from
    more consistent scheduling cadence. If, for example, we got "frame
    drawn" events, then didn't receive them for a few frames, we would still
    be in sync when we start receiving these events again.

 gdk/gdkframeclockidle.c | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)
---
diff --git a/gdk/gdkframeclockidle.c b/gdk/gdkframeclockidle.c
index 4884a81fb9..ec66950b70 100644
--- a/gdk/gdkframeclockidle.c
+++ b/gdk/gdkframeclockidle.c
@@ -140,6 +140,7 @@ gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
     gdk_frame_clock_idle_get_instance_private (frame_clock_idle);
 
   priv->freeze_count = 0;
+  priv->smoothed_frame_time_period = FRAME_INTERVAL;
 }
 
 static void
@@ -346,23 +347,6 @@ maybe_stop_idle (GdkFrameClockIdle *clock_idle)
     }
 }
 
-static gint64
-compute_min_next_frame_time (GdkFrameClockIdle *clock_idle,
-                             gint64             last_frame_time)
-{
-  gint64 presentation_time;
-  gint64 refresh_interval;
-
-  gdk_frame_clock_get_refresh_info (GDK_FRAME_CLOCK (clock_idle),
-                                    last_frame_time,
-                                    &refresh_interval, &presentation_time);
-
-  if (presentation_time == 0)
-    return last_frame_time + refresh_interval;
-  else
-    return presentation_time + refresh_interval / 2;
-}
-
 static gboolean
 gdk_frame_clock_flush_idle (void *data)
 {
@@ -656,9 +640,19 @@ gdk_frame_clock_paint_idle (void *data)
    */
   if (priv->freeze_count == 0)
     {
-      priv->min_next_frame_time = compute_min_next_frame_time (clock_idle,
-                                                               priv->smoothed_frame_time_base -
-                                                               priv->smoothed_frame_time_phase);
+      /*
+       * If we don't receive "frame drawn" events, smooth_cycle_start will simply be advanced in constant 
increments of
+       * the refresh interval. That way we get absolute target times for the next cycles, which should 
prevent skewing
+       * in the scheduling of the frame clock.
+       *
+       * Once we do receive "frame drawn" events, smooth_cycle_start will track the vsync, and do so in a 
more stable
+       * way compared to frame_time. If we then no longer receive "frame drawn" events, smooth_cycle_start 
will again be
+       * simply advanced in increments of the refresh interval, but this time we are in sync with the vsync. 
If we start
+       * receiving "frame drawn" events shortly after loosing them, then we should still be in sync.
+       */
+      gint64 smooth_cycle_start = priv->smoothed_frame_time_base - priv->smoothed_frame_time_phase;
+      priv->min_next_frame_time = smooth_cycle_start + priv->smoothed_frame_time_period;
+
       maybe_start_idle (clock_idle, FALSE);
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]