From 7e27fb6d56e45ccdd91017fc58d9febf39f58d6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Sat, 21 Mar 2020 23:23:23 +0100
Subject: [PATCH] clutter/frame-clock: Add API to schedule next frame
 immediately

Aimed to replace the 'skip-sync-delay' mechanism currently used by
XSyncAlarmNotify to schedule an more immediate redraw.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
---
 clutter/clutter/clutter-frame-clock.c | 45 ++++++++++++++++++++++++---
 clutter/clutter/clutter-frame-clock.h |  3 ++
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
index 3248b4dcc..1f3d10926 100644
--- a/clutter/clutter/clutter-frame-clock.c
+++ b/clutter/clutter/clutter-frame-clock.c
@@ -76,6 +76,7 @@ struct _ClutterFrameClock
   int64_t next_presentation_time_us;
 
   gboolean pending_reschedule;
+  gboolean pending_reschedule_now;
 };
 
 G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
@@ -108,14 +109,21 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
       break;
     case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
     case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
+      frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
+
       if (frame_clock->pending_reschedule)
         {
           frame_clock->pending_reschedule = FALSE;
-          clutter_frame_clock_schedule_update (frame_clock);
-        }
-      else
-        {
-          frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
+
+          if (frame_clock->pending_reschedule_now)
+            {
+              frame_clock->pending_reschedule_now = FALSE;
+              clutter_frame_clock_schedule_update_now (frame_clock);
+            }
+          else
+            {
+              clutter_frame_clock_schedule_update (frame_clock);
+            }
         }
       break;
     }
@@ -185,6 +193,33 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
   *out_next_presentation_time_us = next_presentation_time_us;
 }
 
+void
+clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
+{
+  int64_t next_update_time_us = -1;
+
+  switch (frame_clock->state)
+    {
+    case CLUTTER_FRAME_CLOCK_STATE_INIT:
+    case CLUTTER_FRAME_CLOCK_STATE_IDLE:
+      next_update_time_us = g_get_monotonic_time ();
+      break;
+    case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
+      return;
+    case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
+    case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
+      frame_clock->pending_reschedule = TRUE;
+      frame_clock->pending_reschedule_now = TRUE;
+      return;
+    }
+
+  g_warn_if_fail (next_update_time_us != -1);
+
+  g_source_set_ready_time (frame_clock->source, next_update_time_us);
+  frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
+  frame_clock->is_next_presentation_time_valid = FALSE;
+}
+
 void
 clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
 {
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h
index a7fee3dca..42bb212fe 100644
--- a/clutter/clutter/clutter-frame-clock.h
+++ b/clutter/clutter/clutter-frame-clock.h
@@ -55,4 +55,7 @@ void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
 CLUTTER_EXPORT
 void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
 
+CLUTTER_EXPORT
+void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock);
+
 #endif /* CLUTTER_FRAME_CLOCK_H */