From 75863454a0c16e8713fab5662801fd1d15d4e89a Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Thu, 4 Nov 2021 17:34:17 +0100 Subject: [PATCH] RenderLoop: restrict repaint scheduling with fullscreen windows With an opaque fullscreen window we can be sure that items under it don't actually require us to repaint. This should yield some small efficiency improvements and resolves stutter with adaptive sync. BUG: 443872 FIXED-IN: 5.23.3 --- src/item.cpp | 8 ++++---- src/renderloop.cpp | 10 +++++----- src/renderloop.h | 6 +++--- src/renderloop_p.h | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/item.cpp b/src/item.cpp index 925a90876c..bfb5be4eff 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -261,12 +261,12 @@ void Item::scheduleRepaintInternal(const QRegion ®ion) const QRegion dirtyRegion = globalRegion & output->geometry(); if (!dirtyRegion.isEmpty()) { m_repaints[output] += dirtyRegion; - output->renderLoop()->scheduleRepaint(); + output->renderLoop()->scheduleRepaint(this); } } } else { m_repaints[nullptr] += globalRegion; - kwinApp()->platform()->renderLoop()->scheduleRepaint(); + kwinApp()->platform()->renderLoop()->scheduleRepaint(this); } } @@ -280,11 +280,11 @@ void Item::scheduleFrame() const QVector outputs = kwinApp()->platform()->enabledOutputs(); for (const AbstractOutput *output : outputs) { if (output->geometry().intersects(geometry)) { - output->renderLoop()->scheduleRepaint(); + output->renderLoop()->scheduleRepaint(this); } } } else { - kwinApp()->platform()->renderLoop()->scheduleRepaint(); + kwinApp()->platform()->renderLoop()->scheduleRepaint(this); } } diff --git a/src/renderloop.cpp b/src/renderloop.cpp index c583b54df1..310392c858 100644 --- a/src/renderloop.cpp +++ b/src/renderloop.cpp @@ -36,7 +36,7 @@ void RenderLoopPrivate::scheduleRepaint() if (kwinApp()->isTerminating() || compositeTimer.isActive()) { return; } - if (vrrPolicy == RenderLoop::VrrPolicy::Always || (vrrPolicy == RenderLoop::VrrPolicy::Automatic && hasFullscreenSurface)) { + if (vrrPolicy == RenderLoop::VrrPolicy::Always || (vrrPolicy == RenderLoop::VrrPolicy::Automatic && fullscreenItem != nullptr)) { presentMode = SyncMode::Adaptive; } else { presentMode = SyncMode::Fixed; @@ -216,9 +216,9 @@ void RenderLoop::setRefreshRate(int refreshRate) Q_EMIT refreshRateChanged(); } -void RenderLoop::scheduleRepaint() +void RenderLoop::scheduleRepaint(Item *item) { - if (d->pendingRepaint) { + if (d->pendingRepaint || (d->fullscreenItem != nullptr && item != nullptr && item != d->fullscreenItem)) { return; } if (!d->pendingFrameCount && !d->inhibitCount) { @@ -238,9 +238,9 @@ std::chrono::nanoseconds RenderLoop::nextPresentationTimestamp() const return d->nextPresentationTimestamp; } -void RenderLoop::setFullscreenSurface(SurfaceItem *surfaceItem) +void RenderLoop::setFullscreenSurface(Item *surfaceItem) { - d->hasFullscreenSurface = surfaceItem != nullptr; + d->fullscreenItem = surfaceItem; } RenderLoop::VrrPolicy RenderLoop::vrrPolicy() const diff --git a/src/renderloop.h b/src/renderloop.h index d867048efd..b9554ac6f7 100644 --- a/src/renderloop.h +++ b/src/renderloop.h @@ -14,7 +14,7 @@ namespace KWin { class RenderLoopPrivate; -class SurfaceItem; +class Item; /** * The RenderLoop class represents the compositing scheduler on a particular output. @@ -71,7 +71,7 @@ public: /** * Schedules a compositing cycle at the next available moment. */ - void scheduleRepaint(); + void scheduleRepaint(Item *item = nullptr); /** * Returns the timestamp of the last frame that has been presented on the screen. @@ -90,7 +90,7 @@ public: * Sets the surface that currently gets scanned out, * so that this RenderLoop can adjust its timing behavior to that surface */ - void setFullscreenSurface(SurfaceItem *surface); + void setFullscreenSurface(Item *surface); enum class VrrPolicy : uint32_t { Never = 0, diff --git a/src/renderloop_p.h b/src/renderloop_p.h index ff707a2667..224885bc0b 100644 --- a/src/renderloop_p.h +++ b/src/renderloop_p.h @@ -41,7 +41,7 @@ public: bool pendingReschedule = false; bool pendingRepaint = false; RenderLoop::VrrPolicy vrrPolicy = RenderLoop::VrrPolicy::Never; - bool hasFullscreenSurface = false; + Item *fullscreenItem = nullptr; enum class SyncMode { Fixed,