Correct check for when VRR should be active

The old calculation ignored the render time and safety margin of the
frame scheduling algorithm, which makes VRR activate properly only when
the refresh rate is much lower than the maximum refresh rate.
This commit is contained in:
Xaver Hugl 2021-08-12 02:23:13 +02:00
parent ef9d541487
commit 724f9a5db0

View file

@ -33,7 +33,7 @@ RenderLoopPrivate::RenderLoopPrivate(RenderLoop *q)
void RenderLoopPrivate::scheduleRepaint()
{
if (kwinApp()->isTerminating()) {
if (kwinApp()->isTerminating() || compositeTimer.isActive()) {
return;
}
if (vrrPolicy == RenderLoop::VrrPolicy::Always || (vrrPolicy == RenderLoop::VrrPolicy::Automatic && hasFullscreenSurface)) {
@ -42,25 +42,11 @@ void RenderLoopPrivate::scheduleRepaint()
presentMode = SyncMode::Fixed;
}
const std::chrono::nanoseconds vblankInterval(1'000'000'000'000ull / refreshRate);
if (presentMode == SyncMode::Adaptive) {
std::chrono::nanoseconds timeSincePresent = std::chrono::steady_clock::now().time_since_epoch() - lastPresentationTimestamp;
if (timeSincePresent > vblankInterval) {
// client renders slower than refresh rate -> immediately present
compositeTimer.start(0);
return;
}
// client renders faster than refresh rate -> normal frame scheduling
}
if (compositeTimer.isActive()) {
return;
}
const std::chrono::nanoseconds currentTime(std::chrono::steady_clock::now().time_since_epoch());
// Estimate when the next presentation will occur. Note that this is a prediction.
nextPresentationTimestamp = lastPresentationTimestamp + vblankInterval;
if (nextPresentationTimestamp < currentTime) {
if (nextPresentationTimestamp < currentTime && presentMode == SyncMode::Fixed) {
nextPresentationTimestamp = lastPresentationTimestamp
+ alignTimestamp(currentTime - lastPresentationTimestamp, vblankInterval);
}