frame-clock: Add API to inhibit/uninhibit updates
Equivalent to pause/resume, but ref counted. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
This commit is contained in:
parent
cae5b99537
commit
a132c8dc8e
3 changed files with 157 additions and 15 deletions
|
@ -78,11 +78,32 @@ struct _ClutterFrameClock
|
||||||
|
|
||||||
gboolean pending_reschedule;
|
gboolean pending_reschedule;
|
||||||
gboolean pending_reschedule_now;
|
gboolean pending_reschedule_now;
|
||||||
|
|
||||||
|
int inhibit_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
|
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||||
G_TYPE_OBJECT)
|
G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_reschedule_update (ClutterFrameClock *frame_clock)
|
||||||
|
{
|
||||||
|
if (frame_clock->pending_reschedule)
|
||||||
|
{
|
||||||
|
frame_clock->pending_reschedule = FALSE;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||||
int64_t presentation_time_us)
|
int64_t presentation_time_us)
|
||||||
|
@ -111,21 +132,7 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||||
|
maybe_reschedule_update (frame_clock);
|
||||||
if (frame_clock->pending_reschedule)
|
|
||||||
{
|
|
||||||
frame_clock->pending_reschedule = FALSE;
|
|
||||||
|
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,11 +201,54 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||||
*out_next_presentation_time_us = next_presentation_time_us;
|
*out_next_presentation_time_us = next_presentation_time_us;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
|
||||||
|
{
|
||||||
|
frame_clock->inhibit_count++;
|
||||||
|
|
||||||
|
if (frame_clock->inhibit_count == 1)
|
||||||
|
{
|
||||||
|
switch (frame_clock->state)
|
||||||
|
{
|
||||||
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||||
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||||
|
break;
|
||||||
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||||
|
frame_clock->pending_reschedule = TRUE;
|
||||||
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||||
|
break;
|
||||||
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||||
|
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_source_set_ready_time (frame_clock->source, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock)
|
||||||
|
{
|
||||||
|
g_return_if_fail (frame_clock->inhibit_count > 0);
|
||||||
|
|
||||||
|
frame_clock->inhibit_count--;
|
||||||
|
|
||||||
|
if (frame_clock->inhibit_count == 0)
|
||||||
|
maybe_reschedule_update (frame_clock);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
||||||
{
|
{
|
||||||
int64_t next_update_time_us = -1;
|
int64_t next_update_time_us = -1;
|
||||||
|
|
||||||
|
if (frame_clock->inhibit_count > 0)
|
||||||
|
{
|
||||||
|
frame_clock->pending_reschedule = TRUE;
|
||||||
|
frame_clock->pending_reschedule_now = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (frame_clock->state)
|
switch (frame_clock->state)
|
||||||
{
|
{
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||||
|
@ -226,6 +276,12 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
||||||
{
|
{
|
||||||
int64_t next_update_time_us = -1;
|
int64_t next_update_time_us = -1;
|
||||||
|
|
||||||
|
if (frame_clock->inhibit_count > 0)
|
||||||
|
{
|
||||||
|
frame_clock->pending_reschedule = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (frame_clock->state)
|
switch (frame_clock->state)
|
||||||
{
|
{
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||||
|
|
|
@ -61,4 +61,10 @@ void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
|
||||||
CLUTTER_EXPORT
|
CLUTTER_EXPORT
|
||||||
void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock);
|
void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
void clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
void clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock);
|
||||||
|
|
||||||
#endif /* CLUTTER_FRAME_CLOCK_H */
|
#endif /* CLUTTER_FRAME_CLOCK_H */
|
||||||
|
|
|
@ -524,6 +524,85 @@ frame_clock_before_frame (void)
|
||||||
g_object_unref (frame_clock);
|
g_object_unref (frame_clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _InhibitTest
|
||||||
|
{
|
||||||
|
GMainLoop *main_loop;
|
||||||
|
ClutterFrameClock *frame_clock;
|
||||||
|
|
||||||
|
gboolean frame_count;
|
||||||
|
gboolean pending_inhibit;
|
||||||
|
gboolean pending_quit;
|
||||||
|
} InhibitTest;
|
||||||
|
|
||||||
|
static ClutterFrameResult
|
||||||
|
inhibit_frame_clock_frame (ClutterFrameClock *frame_clock,
|
||||||
|
int64_t frame_count,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
InhibitTest *test = user_data;
|
||||||
|
|
||||||
|
g_assert_cmpint (frame_count, ==, test->frame_count);
|
||||||
|
|
||||||
|
test->frame_count++;
|
||||||
|
|
||||||
|
clutter_frame_clock_notify_presented (frame_clock, g_get_monotonic_time ());
|
||||||
|
clutter_frame_clock_schedule_update (frame_clock);
|
||||||
|
|
||||||
|
if (test->pending_inhibit)
|
||||||
|
{
|
||||||
|
test->pending_inhibit = FALSE;
|
||||||
|
clutter_frame_clock_inhibit (frame_clock);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_frame_clock_schedule_update (frame_clock);
|
||||||
|
|
||||||
|
if (test->pending_quit)
|
||||||
|
g_main_loop_quit (test->main_loop);
|
||||||
|
|
||||||
|
return CLUTTER_FRAME_RESULT_PENDING_PRESENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ClutterFrameListenerIface inhibit_frame_listener_iface = {
|
||||||
|
.frame = inhibit_frame_clock_frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
uninhibit_timeout (gpointer user_data)
|
||||||
|
{
|
||||||
|
InhibitTest *test = user_data;
|
||||||
|
|
||||||
|
g_assert_cmpint (test->frame_count, ==, 1);
|
||||||
|
|
||||||
|
clutter_frame_clock_uninhibit (test->frame_clock);
|
||||||
|
test->pending_quit = TRUE;
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
frame_clock_inhibit (void)
|
||||||
|
{
|
||||||
|
InhibitTest test = { 0 };
|
||||||
|
|
||||||
|
expected_frame_count = 0;
|
||||||
|
|
||||||
|
test.main_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
test.frame_clock = clutter_frame_clock_new (refresh_rate,
|
||||||
|
&inhibit_frame_listener_iface,
|
||||||
|
&test);
|
||||||
|
|
||||||
|
test.pending_inhibit = TRUE;
|
||||||
|
|
||||||
|
clutter_frame_clock_schedule_update (test.frame_clock);
|
||||||
|
g_timeout_add (100, uninhibit_timeout, &test);
|
||||||
|
g_main_loop_run (test.main_loop);
|
||||||
|
|
||||||
|
g_assert_cmpint (test.frame_count, ==, 2);
|
||||||
|
|
||||||
|
g_main_loop_unref (test.main_loop);
|
||||||
|
g_object_unref (test.frame_clock);
|
||||||
|
}
|
||||||
|
|
||||||
CLUTTER_TEST_SUITE (
|
CLUTTER_TEST_SUITE (
|
||||||
CLUTTER_TEST_UNIT ("/frame-clock/schedule-update", frame_clock_schedule_update)
|
CLUTTER_TEST_UNIT ("/frame-clock/schedule-update", frame_clock_schedule_update)
|
||||||
CLUTTER_TEST_UNIT ("/frame-clock/immediate-present", frame_clock_immediate_present)
|
CLUTTER_TEST_UNIT ("/frame-clock/immediate-present", frame_clock_immediate_present)
|
||||||
|
@ -531,4 +610,5 @@ CLUTTER_TEST_SUITE (
|
||||||
CLUTTER_TEST_UNIT ("/frame-clock/no-damage", frame_clock_no_damage)
|
CLUTTER_TEST_UNIT ("/frame-clock/no-damage", frame_clock_no_damage)
|
||||||
CLUTTER_TEST_UNIT ("/frame-clock/schedule-update-now", frame_clock_schedule_update_now)
|
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/before-frame", frame_clock_before_frame)
|
||||||
|
CLUTTER_TEST_UNIT ("/frame-clock/inhibit", frame_clock_inhibit)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue