Verified Commit e415cc53 authored by Daniel van Vugt's avatar Daniel van Vugt Committed by Georges Basile Stavracas Neto
Browse files

clutter/master-clock: Remove fallback throttles

The presentation timing logic (via `master_clock_get_swap_wait_time`) now
works unconditionally. By "works" we mean that a result of zero from
`master_clock_get_swap_wait_time` actually means zero now. Previously
zero could mean either a successful result of zero milliseconds or that
the backend couldn't get an answer. And a non-zero result is the same as

This works even if the screen is "idle" and even if the backend doesn't
provide presentation timestamps. So now our two fallback throttling
mechanisms of relying on `CLUTTER_FEATURE_SWAP_THROTTLE` and decimating
to `clutter_get_default_frame_rate` can be deleted.

Closes: #406 and

parent 67a3715d
......@@ -64,9 +64,6 @@ struct _ClutterMasterClockDefault
/* the current state of the clock, in usecs */
gint64 cur_tick;
/* the previous state of the clock, in usecs, used to compute the delta */
gint64 prev_tick;
gint64 frame_budget;
gint64 remaining_budget;
......@@ -77,12 +74,6 @@ struct _ClutterMasterClockDefault
GSource *source;
/* If the master clock is idle that means it has
* fallen back to idle polling for timeline
* progressions and it may have been some time since
* the last real stage update.
guint idle : 1;
guint ensure_next_iteration : 1;
guint paused : 1;
......@@ -275,78 +266,12 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
static gint
master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
gint64 now, next;
gint swap_delay;
if (!master_clock_is_running (master_clock))
return -1;
/* If all of the stages are busy waiting for a swap-buffers to complete
* then we wait for one to be ready.. */
swap_delay = master_clock_get_swap_wait_time (master_clock);
if (swap_delay != 0)
return swap_delay;
/* When we have sync-to-vblank, we count on swap-buffer requests (or
* swap-buffer-complete events if supported in the backend) to throttle our
* frame rate so no additional delay is needed to start the next frame.
* If the master-clock has become idle due to no timeline progression causing
* redraws then we can no longer rely on vblank synchronization because the
* last real stage update/redraw may have happened a long time ago and so we
* fallback to polling for timeline progressions every 1/frame_rate seconds.
* (NB: if there aren't even any timelines running then the master clock will
* be completely stopped in master_clock_is_running())
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_THROTTLE) &&
CLUTTER_NOTE (SCHEDULER, "swap throttling available and updated stages");
return 0;
if (master_clock->prev_tick == 0)
/* If we weren't previously running, then draw the next frame
* immediately
CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately");
return 0;
/* Otherwise, wait at least 1/frame_rate seconds since we last
* started a frame
now = g_source_get_time (master_clock->source);
next = master_clock->prev_tick;
/* If time has gone backwards then there's no way of knowing how
long we should wait so let's just dispatch immediately */
if (now <= next)
CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
return 0;
next += (1000000L / clutter_get_default_frame_rate ());
if (next <= now)
CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
1000000L / (gulong) clutter_get_default_frame_rate ());
return 0;
(next - now) / 1000);
return (next - now) / 1000;
return master_clock_get_swap_wait_time (master_clock);
static void
......@@ -530,7 +455,6 @@ clutter_clock_dispatch (GSource *source,
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
gboolean stages_updated = FALSE;
GSList *stages;
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
......@@ -550,8 +474,6 @@ clutter_clock_dispatch (GSource *source,
stages = master_clock_list_ready_stages (master_clock);
master_clock->idle = FALSE;
/* Each frame is split into three separate phases: */
/* 1. process all the events; each stage goes through its events queue
......@@ -564,19 +486,12 @@ clutter_clock_dispatch (GSource *source,
master_clock_advance_timelines (master_clock);
/* 3. relayout and redraw the stages */
stages_updated = master_clock_update_stages (master_clock, stages);
/* The master clock goes idle if no stages were updated and falls back
* to polling for timeline progressions... */
if (!stages_updated)
master_clock->idle = TRUE;
master_clock_update_stages (master_clock, stages);
master_clock_reschedule_stage_updates (master_clock, stages);
g_slist_free_full (stages, g_object_unref);
master_clock->prev_tick = master_clock->cur_tick;
_clutter_threads_release_lock ();
return TRUE;
......@@ -608,7 +523,6 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
source = clutter_clock_source_new (self);
self->source = source;
self->idle = FALSE;
self->ensure_next_iteration = FALSE;
self->paused = FALSE;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment