[mutter] clutter/frame-clock: Apply error diffusion (dithering) to dispatch times



commit 0555a5bbc15dcb7dcf125a7969a42f171fe0bb72
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Thu Apr 15 20:30:31 2021 +0800

    clutter/frame-clock: Apply error diffusion (dithering) to dispatch times
    
    But only the dispatch times used when `last_presentation_time_us == 0`
    (Nvidia + Xorg).
    
    This ensures the average dispatch interval is always precisely equal
    to the refresh interval, regardless of any jitter in the mainloop.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1751,
           https://gitlab.gnome.org/GNOME/mutter/-/issues/1758,
           https://gitlab.gnome.org/GNOME/mutter/-/issues/1870
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1826>

 clutter/clutter/clutter-frame-clock.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)
---
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
index dc5a608348..65f6229b02 100644
--- a/clutter/clutter/clutter-frame-clock.c
+++ b/clutter/clutter/clutter-frame-clock.c
@@ -86,6 +86,7 @@ struct _ClutterFrameClock
 
   ClutterFrameClockState state;
   int64_t last_dispatch_time_us;
+  int64_t last_dispatch_lateness_us;
   int64_t last_presentation_time_us;
 
   gboolean is_next_presentation_time_valid;
@@ -378,7 +379,8 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
     {
       *out_next_update_time_us =
         frame_clock->last_dispatch_time_us ?
-        frame_clock->last_dispatch_time_us + refresh_interval_us :
+        ((frame_clock->last_dispatch_time_us -
+          frame_clock->last_dispatch_lateness_us) + refresh_interval_us) :
         now_us;
 
       *out_next_presentation_time_us = 0;
@@ -613,9 +615,20 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
 {
   int64_t frame_count;
   ClutterFrameResult result;
+  int64_t ideal_dispatch_time_us, lateness_us;
 
   COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockDispatch, "Frame Clock (dispatch)");
 
+  ideal_dispatch_time_us = (frame_clock->last_dispatch_time_us -
+                            frame_clock->last_dispatch_lateness_us) +
+                           frame_clock->refresh_interval_us;
+
+  lateness_us = time_us - ideal_dispatch_time_us;
+  if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us)
+    frame_clock->last_dispatch_lateness_us = 0;
+  else
+    frame_clock->last_dispatch_lateness_us = lateness_us;
+
   frame_clock->last_dispatch_time_us = time_us;
   g_source_set_ready_time (frame_clock->source, -1);
 


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