summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clutter/clutter/clutter-frame-clock.c59
1 files changed, 50 insertions, 9 deletions
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
index 2f617d0a5..bcc6bae6a 100644
--- a/clutter/clutter/clutter-frame-clock.c
+++ b/clutter/clutter/clutter-frame-clock.c
@@ -266,18 +266,59 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
last_presentation_time_us = frame_clock->last_presentation_time_us;
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
- /* Skip ahead to get close to the actual next presentation time. */
+ /*
+ * However, the last presentation could have happened more than a frame ago.
+ * For example, due to idling (nothing on screen changed, so no need to
+ * redraw) or due to frames missing deadlines (GPU busy with heavy rendering).
+ * The following code adjusts next_presentation_time_us to be in the future,
+ * but still aligned to display presentation times. Instead of
+ * next presentation = last presentation + 1 * refresh interval, it will be
+ * next presentation = last presentation + N * refresh interval.
+ */
if (next_presentation_time_us < now_us)
{
- int64_t logical_clock_offset_us;
- int64_t logical_clock_phase_us;
- int64_t hw_clock_offset_us;
+ int64_t presentation_phase_us;
+ int64_t current_phase_us;
+ int64_t current_refresh_interval_start_us;
+
+ /*
+ * Let's say we're just past next_presentation_time_us.
+ *
+ * First, we compute presentation_phase_us. Real presentation times don't
+ * have to be exact multiples of refresh_interval_us and
+ * presentation_phase_us represents this difference. Next, we compute
+ * current phase and the refresh interval start corresponding to now_us.
+ * Finally, add presentation_phase_us and a refresh interval to get the
+ * next presentation after now_us.
+ *
+ * last_presentation_time_us
+ * / next_presentation_time_us
+ * / / now_us
+ * / / / new next_presentation_time_us
+ * |--|-------|---o---|-------|--> presentation times
+ * | __|
+ * | |presentation_phase_us
+ * | |
+ * | | now_us - presentation_phase_us
+ * | | /
+ * |-------|---o---|-------|-----> integer multiples of refresh_interval_us
+ * | \__/
+ * | |current_phase_us
+ * | \
+ * | current_refresh_interval_start_us
+ * 0
+ *
+ */
+
+ presentation_phase_us = last_presentation_time_us % refresh_interval_us;
+ current_phase_us = (now_us - presentation_phase_us) % refresh_interval_us;
+ current_refresh_interval_start_us =
+ now_us - presentation_phase_us - current_phase_us;
- logical_clock_offset_us = now_us % refresh_interval_us;
- logical_clock_phase_us = now_us - logical_clock_offset_us;
- hw_clock_offset_us = last_presentation_time_us % refresh_interval_us;
-
- next_presentation_time_us = logical_clock_phase_us + hw_clock_offset_us;
+ next_presentation_time_us =
+ current_refresh_interval_start_us +
+ presentation_phase_us +
+ refresh_interval_us;
}
/*