From 7e3d1e26a15b6ddd9a49d4e42718f125b57f4394 Mon Sep 17 00:00:00 2001 From: Daniel van Vugt Date: Tue, 14 Dec 2021 17:49:59 +0800 Subject: [PATCH] clutter/frame-clock: Advance timelines according to presentation time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures they remain perfectly smooth regardless of how the dispatch time has been adjusted/optimized/delayed/jittered. Idea by Ivan Molodetskikh For example, dragging a window on a 60Hz monitor: BEFORE delta(time_us) = 17014μs delta(time_us) = 15998μs delta(time_us) = 17006μs delta(time_us) = 16975μs delta(time_us) = 16001μs delta(time_us) = 17002μs delta(time_us) = 17006μs delta(time_us) = 16004μs AFTER delta(time_us) = 16667μs delta(time_us) = 16667μs delta(time_us) = 16670μs delta(time_us) = 16667μs delta(time_us) = 16669μs delta(time_us) = 16668μs delta(time_us) = 16664μs delta(time_us) = 16674μs Caveat 1: Because we don't know a "next presentation time" on the first frame, the interval between the first and second frame will usually be different to the subsequent steady interval. So this change increases the jitter of just frame 2, but eliminates jitter thereafter. Caveat 2: `clutter_frame_clock_schedule_update_now` schedules updates earlier than `clutter_frame_clock_schedule_update`. This means potentially you could get multiple frames targeting the same "next presentation time". That doesn't really change here though - we're dispatching at the same times as we used to and just giving timelines a better vsync-aligned timestamp now. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/25 Part-of: --- clutter/clutter/clutter-frame-clock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c index 24e0ec8a2..9be9898ee 100644 --- a/clutter/clutter/clutter-frame-clock.c +++ b/clutter/clutter/clutter-frame-clock.c @@ -642,6 +642,8 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, COGL_TRACE_END (ClutterFrameClockEvents); COGL_TRACE_BEGIN (ClutterFrameClockTimelines, "Frame Clock (timelines)"); + if (frame_clock->is_next_presentation_time_valid) + time_us = frame_clock->next_presentation_time_us; advance_timelines (frame_clock, time_us); COGL_TRACE_END (ClutterFrameClockTimelines);