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
This commit is contained in:
Xaver Hugl 2024-07-25 16:01:50 +02:00
parent d0f0481860
commit 457b3a47ff

View file

@ -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<int32_t>(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;