From 457b3a47ffe91b335ab18170cfb830d35217b9a8 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Thu, 25 Jul 2024 16:01:50 +0200 Subject: [PATCH] core/renderloop: don't move the target presentation timestamp back when rescheduling Re-doing the frame scheduling for an already scheduled composite cycle was meant to adjust to small timing changes in the presentation timestamp, but if the expected compositing time was close to vblank, it could happen that this would instead move the target presentation timestamp and effectively drop a frame. To fix that, this commit makes the presentation timestamp be adjusted only to be more accurate, but still target the same vblank interval. BUG: 488843 --- src/core/renderloop.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/renderloop.cpp b/src/core/renderloop.cpp index 588880ef10..739b5ba2e6 100644 --- a/src/core/renderloop.cpp +++ b/src/core/renderloop.cpp @@ -87,7 +87,17 @@ void RenderLoopPrivate::scheduleRepaint(std::chrono::nanoseconds lastTargetTimes } } - nextPresentationTimestamp = lastPresentationTimestamp + std::max(pageflipsSince + pageflipsInAdvance, pageflipsSinceLastToTarget + 1) * vblankInterval; + if (compositeTimer.isActive()) { + // we already scheduled this frame, but we got a new timestamp + // which might require starting to composite earlier than we planned + // It's important here that we do not change the targeted vblank interval, + // otherwise with a pessimistic compositing time estimation we might + // unnecessarily drop frames + const uint32_t intervalsSinceLastTimestamp = std::max(std::round((nextPresentationTimestamp - lastPresentationTimestamp).count() / double(vblankInterval.count())), 0); + nextPresentationTimestamp = lastPresentationTimestamp + intervalsSinceLastTimestamp * vblankInterval; + } else { + nextPresentationTimestamp = lastPresentationTimestamp + std::max(pageflipsSince + pageflipsInAdvance, pageflipsSinceLastToTarget + 1) * vblankInterval; + } } else { wasTripleBuffering = false; doubleBufferingCounter = 0;