mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
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 before. 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: https://gitlab.gnome.org/GNOME/mutter/issues/406 and https://bugzilla.gnome.org/show_bug.cgi?id=781835 https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
This commit is contained in:
parent
67a3715ded
commit
e415cc538a
@ -64,9 +64,6 @@ struct _ClutterMasterClockDefault
|
|||||||
/* the current state of the clock, in usecs */
|
/* the current state of the clock, in usecs */
|
||||||
gint64 cur_tick;
|
gint64 cur_tick;
|
||||||
|
|
||||||
/* the previous state of the clock, in usecs, used to compute the delta */
|
|
||||||
gint64 prev_tick;
|
|
||||||
|
|
||||||
#ifdef CLUTTER_ENABLE_DEBUG
|
#ifdef CLUTTER_ENABLE_DEBUG
|
||||||
gint64 frame_budget;
|
gint64 frame_budget;
|
||||||
gint64 remaining_budget;
|
gint64 remaining_budget;
|
||||||
@ -77,12 +74,6 @@ struct _ClutterMasterClockDefault
|
|||||||
*/
|
*/
|
||||||
GSource *source;
|
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 ensure_next_iteration : 1;
|
||||||
|
|
||||||
guint paused : 1;
|
guint paused : 1;
|
||||||
@ -275,78 +266,12 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
|
|||||||
static gint
|
static gint
|
||||||
master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
|
master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
|
||||||
{
|
{
|
||||||
gint64 now, next;
|
|
||||||
gint swap_delay;
|
|
||||||
|
|
||||||
if (!master_clock_is_running (master_clock))
|
if (!master_clock_is_running (master_clock))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* If all of the stages are busy waiting for a swap-buffers to complete
|
/* If all of the stages are busy waiting for a swap-buffers to complete
|
||||||
* then we wait for one to be ready.. */
|
* then we wait for one to be ready.. */
|
||||||
swap_delay = master_clock_get_swap_wait_time (master_clock);
|
return 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) &&
|
|
||||||
!master_clock->idle)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
|
|
||||||
(next - now) / 1000);
|
|
||||||
|
|
||||||
return (next - now) / 1000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -530,7 +455,6 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
{
|
{
|
||||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||||
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
|
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
|
||||||
gboolean stages_updated = FALSE;
|
|
||||||
GSList *stages;
|
GSList *stages;
|
||||||
|
|
||||||
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
|
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
|
||||||
@ -550,8 +474,6 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
*/
|
*/
|
||||||
stages = master_clock_list_ready_stages (master_clock);
|
stages = master_clock_list_ready_stages (master_clock);
|
||||||
|
|
||||||
master_clock->idle = FALSE;
|
|
||||||
|
|
||||||
/* Each frame is split into three separate phases: */
|
/* Each frame is split into three separate phases: */
|
||||||
|
|
||||||
/* 1. process all the events; each stage goes through its events queue
|
/* 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);
|
master_clock_advance_timelines (master_clock);
|
||||||
|
|
||||||
/* 3. relayout and redraw the stages */
|
/* 3. relayout and redraw the stages */
|
||||||
stages_updated = master_clock_update_stages (master_clock, stages);
|
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_reschedule_stage_updates (master_clock, stages);
|
master_clock_reschedule_stage_updates (master_clock, stages);
|
||||||
|
|
||||||
g_slist_free_full (stages, g_object_unref);
|
g_slist_free_full (stages, g_object_unref);
|
||||||
|
|
||||||
master_clock->prev_tick = master_clock->cur_tick;
|
|
||||||
|
|
||||||
_clutter_threads_release_lock ();
|
_clutter_threads_release_lock ();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -608,7 +523,6 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
|
|||||||
source = clutter_clock_source_new (self);
|
source = clutter_clock_source_new (self);
|
||||||
self->source = source;
|
self->source = source;
|
||||||
|
|
||||||
self->idle = FALSE;
|
|
||||||
self->ensure_next_iteration = FALSE;
|
self->ensure_next_iteration = FALSE;
|
||||||
self->paused = FALSE;
|
self->paused = FALSE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user