[mutter] clutter/frame-clock: Add notify_ready()



commit 84f454fd4fe976e4691fab9be3a9c5fd201ea119
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sat Oct 10 00:25:39 2020 +0200

    clutter/frame-clock: Add notify_ready()
    
    In constrast to notify_presented(), notify_ready() also returns the
    state machine to the idle state, but without providing new frame
    information, as no frame was actually presented.
    
    This will happen for example with the simple KMS impl backend will do a
    cursor movement, which will trigger a symbolic "page flip" reply in
    order to emulate atomic KMS behavior. When this happen, we should just
    try to reschedule again.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>

 clutter/clutter/clutter-frame-clock.c   | 18 ++++++++
 clutter/clutter/clutter-frame-clock.h   |  3 ++
 src/tests/clutter/conform/frame-clock.c | 73 +++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+)
---
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
index 355a2c00fb..38f7797320 100644
--- a/clutter/clutter/clutter-frame-clock.c
+++ b/clutter/clutter/clutter-frame-clock.c
@@ -215,6 +215,24 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
     }
 }
 
+void
+clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
+{
+  switch (frame_clock->state)
+    {
+    case CLUTTER_FRAME_CLOCK_STATE_INIT:
+    case CLUTTER_FRAME_CLOCK_STATE_IDLE:
+    case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
+      g_warn_if_reached ();
+      break;
+    case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
+    case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
+      frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
+      maybe_reschedule_update (frame_clock);
+      break;
+    }
+}
+
 static void
 calculate_next_update_time_us (ClutterFrameClock *frame_clock,
                                int64_t           *out_next_update_time_us,
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h
index cf6c5c8569..9f91b6bfd3 100644
--- a/clutter/clutter/clutter-frame-clock.h
+++ b/clutter/clutter/clutter-frame-clock.h
@@ -66,6 +66,9 @@ CLUTTER_EXPORT
 void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
                                            ClutterFrameInfo  *frame_info);
 
+CLUTTER_EXPORT
+void clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock);
+
 CLUTTER_EXPORT
 void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
 
diff --git a/src/tests/clutter/conform/frame-clock.c b/src/tests/clutter/conform/frame-clock.c
index 62a4176722..a055992b3a 100644
--- a/src/tests/clutter/conform/frame-clock.c
+++ b/src/tests/clutter/conform/frame-clock.c
@@ -747,6 +747,78 @@ frame_clock_destroy_signal (void)
   g_object_unref (frame_clock_backup);
 }
 
+static gboolean
+notify_ready_and_schedule_update_idle (gpointer user_data)
+{
+  ClutterFrameClock *frame_clock = user_data;
+
+  clutter_frame_clock_notify_ready (frame_clock);
+  clutter_frame_clock_schedule_update (frame_clock);
+
+  return G_SOURCE_REMOVE;
+}
+
+static ClutterFrameResult
+frame_clock_ready_frame (ClutterFrameClock *frame_clock,
+                         int64_t            frame_count,
+                         int64_t            time_us,
+                         gpointer           user_data)
+{
+  GMainLoop *main_loop = user_data;
+
+  g_assert_cmpint (frame_count, ==, expected_frame_count);
+
+  expected_frame_count++;
+
+  if (test_frame_count == 0)
+    {
+      g_main_loop_quit (main_loop);
+      return CLUTTER_FRAME_RESULT_IDLE;
+    }
+
+  test_frame_count--;
+
+  g_idle_add (notify_ready_and_schedule_update_idle, frame_clock);
+
+  return CLUTTER_FRAME_RESULT_PENDING_PRESENTED;
+}
+
+static const ClutterFrameListenerIface frame_clock_ready_listener_iface = {
+  .frame = frame_clock_ready_frame,
+};
+
+static void
+frame_clock_notify_ready (void)
+{
+  GMainLoop *main_loop;
+  ClutterFrameClock *frame_clock;
+  int64_t before_us;
+  int64_t after_us;
+
+  test_frame_count = 10;
+  expected_frame_count = 0;
+
+  main_loop = g_main_loop_new (NULL, FALSE);
+  frame_clock = clutter_frame_clock_new (refresh_rate,
+                                         &frame_clock_ready_listener_iface,
+                                         main_loop);
+
+  before_us = g_get_monotonic_time ();
+
+  clutter_frame_clock_schedule_update (frame_clock);
+  g_main_loop_run (main_loop);
+
+  after_us = g_get_monotonic_time ();
+
+  /* The initial frame will only be delayed by 2 ms, so we are checking one
+   * less.
+   */
+  g_assert_cmpint (after_us - before_us, >, 8 * refresh_interval_us);
+
+  g_main_loop_unref (main_loop);
+  clutter_frame_clock_destroy (frame_clock);
+}
+
 CLUTTER_TEST_SUITE (
   CLUTTER_TEST_UNIT ("/frame-clock/schedule-update", frame_clock_schedule_update)
   CLUTTER_TEST_UNIT ("/frame-clock/immediate-present", frame_clock_immediate_present)
@@ -757,4 +829,5 @@ CLUTTER_TEST_SUITE (
   CLUTTER_TEST_UNIT ("/frame-clock/inhibit", frame_clock_inhibit)
   CLUTTER_TEST_UNIT ("/frame-clock/reschedule-on-idle", frame_clock_reschedule_on_idle)
   CLUTTER_TEST_UNIT ("/frame-clock/destroy-signal", frame_clock_destroy_signal)
+  CLUTTER_TEST_UNIT ("/frame-clock/notify-ready", frame_clock_notify_ready)
 )


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