diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c index 355a2c00f..38f779732 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 cf6c5c856..9f91b6bfd 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 62a417672..a055992b3 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) )