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>
This commit is contained in:
Jonas Ådahl 2020-10-10 00:25:39 +02:00 committed by Marge Bot
parent fea8ebcca9
commit 84f454fd4f
3 changed files with 94 additions and 0 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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)
)