core/renderloop: make repaint scheduling more robust against wrong render time estimations
When the render time estimation is much higher than the real render time, and triple buffering is enabled, the previous logic would schedule frames multiple vblanks in advance, which could drop the effective refresh rate by more than is necessary. This commit limits it to the second vblank after the current time, which ensures that we hit the full refresh rate even when render time prediction is wrong
This commit is contained in:
parent
97c1d335e5
commit
804ecb0e22
1 changed files with 5 additions and 14 deletions
|
@ -32,13 +32,6 @@ RenderLoopPrivate::RenderLoopPrivate(RenderLoop *q, Output *output)
|
|||
});
|
||||
}
|
||||
|
||||
static std::chrono::nanoseconds estimateNextPageflip(std::chrono::nanoseconds earliestSubmitTime, std::chrono::nanoseconds lastPageflip, std::chrono::nanoseconds vblankInterval)
|
||||
{
|
||||
// the last pageflip may be in the future
|
||||
const uint64_t pageflipsSince = earliestSubmitTime > lastPageflip ? (earliestSubmitTime - lastPageflip) / vblankInterval : 0;
|
||||
return lastPageflip + vblankInterval * (pageflipsSince + 1);
|
||||
}
|
||||
|
||||
void RenderLoopPrivate::scheduleNextRepaint()
|
||||
{
|
||||
if (kwinApp()->isTerminating() || compositeTimer.isActive()) {
|
||||
|
@ -59,13 +52,11 @@ void RenderLoopPrivate::scheduleRepaint(std::chrono::nanoseconds lastTargetTimes
|
|||
|
||||
if (presentationMode == PresentationMode::VSync) {
|
||||
// normal presentation: pageflips only happen at vblank
|
||||
if (maxPendingFrameCount == 1) {
|
||||
// keep the old behavior for backends not supporting triple buffering
|
||||
nextPresentationTimestamp = estimateNextPageflip(currentTime, lastPresentationTimestamp, vblankInterval);
|
||||
} else {
|
||||
// estimate the next pageflip that can realistically be hit
|
||||
nextPresentationTimestamp = estimateNextPageflip(std::max(lastTargetTimestamp, currentTime + expectedCompositingTime), lastPresentationTimestamp, vblankInterval);
|
||||
}
|
||||
const uint64_t pageflipsSince = std::max<int64_t>((currentTime - lastPresentationTimestamp) / vblankInterval, 0);
|
||||
const uint64_t pageflipsInAdvance = std::min<int64_t>(expectedCompositingTime / vblankInterval + 1, maxPendingFrameCount);
|
||||
const uint64_t pageflipsSinceLastToTarget = std::max<int64_t>(std::round((lastTargetTimestamp - lastPresentationTimestamp).count() / double(vblankInterval.count())), 0);
|
||||
|
||||
nextPresentationTimestamp = lastPresentationTimestamp + std::max(pageflipsSince + pageflipsInAdvance, pageflipsSinceLastToTarget + 1) * vblankInterval;
|
||||
} else if (presentationMode == PresentationMode::Async || presentationMode == PresentationMode::AdaptiveAsync) {
|
||||
// tearing: pageflips happen ASAP
|
||||
nextPresentationTimestamp = currentTime;
|
||||
|
|
Loading…
Reference in a new issue