[mutter] clutter/frame-clock: Handle reschedule then dispatch results in idle



commit 847e89d31f103ebdca527eacbb78d590e60a4dbd
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sat May 23 21:20:54 2020 +0200

    clutter/frame-clock: Handle reschedule then dispatch results in idle
    
    A frame clock dispatch doesn't necessarily result in a frame drawn,
    meaning we'll end up in the idle state. However, it may be the case that
    something still requires another frame, and will in that case have
    requested one to be scheduled. In order to not dead lock, try to
    reschedule directly if requested after dispatching, if we ended up in
    the idle state.
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285

 clutter/clutter/clutter-frame-clock.c   |  1 +
 src/tests/clutter/conform/frame-clock.c | 63 +++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
---
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
index c325c63fee..1ea524aca7 100644
--- a/clutter/clutter/clutter-frame-clock.c
+++ b/clutter/clutter/clutter-frame-clock.c
@@ -419,6 +419,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
           break;
         case CLUTTER_FRAME_RESULT_IDLE:
           frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
+          maybe_reschedule_update (frame_clock);
           break;
         }
       break;
diff --git a/src/tests/clutter/conform/frame-clock.c b/src/tests/clutter/conform/frame-clock.c
index b865b132c3..74bcc42289 100644
--- a/src/tests/clutter/conform/frame-clock.c
+++ b/src/tests/clutter/conform/frame-clock.c
@@ -628,6 +628,68 @@ frame_clock_inhibit (void)
   g_object_unref (test.frame_clock);
 }
 
+typedef struct _RescheduleOnIdleFrameClockTest
+{
+  FrameClockTest base;
+} RescheduleOnIdleFrameClockTest;
+
+static ClutterFrameResult
+reschedule_on_idle_clock_frame (ClutterFrameClock *frame_clock,
+                                int64_t            frame_count,
+                                int64_t            time_us,
+                                gpointer           user_data)
+{
+  RescheduleOnIdleFrameClockTest *test = user_data;
+  GMainLoop *main_loop = test->base.main_loop;
+
+  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--;
+
+  clutter_frame_clock_schedule_update (frame_clock);
+
+  return CLUTTER_FRAME_RESULT_IDLE;
+}
+
+static const ClutterFrameListenerIface reschedule_on_idle_listener_iface = {
+  .frame = reschedule_on_idle_clock_frame,
+};
+
+static void
+frame_clock_reschedule_on_idle (void)
+{
+  RescheduleOnIdleFrameClockTest test;
+  ClutterFrameClock *frame_clock;
+  FakeHwClock *fake_hw_clock;
+  GSource *source;
+
+  test_frame_count = 10;
+  expected_frame_count = 0;
+
+  test.base.main_loop = g_main_loop_new (NULL, FALSE);
+  frame_clock = clutter_frame_clock_new (refresh_rate,
+                                         &reschedule_on_idle_listener_iface,
+                                         &test);
+  fake_hw_clock = fake_hw_clock_new (frame_clock, NULL, NULL);
+  source = &fake_hw_clock->source;
+  g_source_attach (source, NULL);
+  test.base.fake_hw_clock = fake_hw_clock;
+
+  clutter_frame_clock_schedule_update (frame_clock);
+  g_main_loop_run (test.base.main_loop);
+
+  g_main_loop_unref (test.base.main_loop);
+  g_object_unref (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)
@@ -636,4 +698,5 @@ CLUTTER_TEST_SUITE (
   CLUTTER_TEST_UNIT ("/frame-clock/schedule-update-now", frame_clock_schedule_update_now)
   CLUTTER_TEST_UNIT ("/frame-clock/before-frame", frame_clock_before_frame)
   CLUTTER_TEST_UNIT ("/frame-clock/inhibit", frame_clock_inhibit)
+  CLUTTER_TEST_UNIT ("/frame-clock/reschedule-on-idle", frame_clock_reschedule_on_idle)
 )


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