backends/drm: delay cursor updates with adaptive sync

While the primary plane delivers a high enough refresh rate for the cursor to be
at least usable, delay cursor updates to be in sync with the primary plane. This
avoids stutter of the content being shown on the primary plane.

Because amdgpu doesn't handle this correctly at the moment, this feature is guarded
behind the KWIN_DRM_DELAY_VRR_CURSOR_UPDATES environment variable.
See https://gitlab.freedesktop.org/drm/amd/-/issues/2186 for more details on that.
This commit is contained in:
Xaver Hugl 2024-02-20 21:19:18 +01:00
parent 080d28b3f9
commit 039fd39e34

View file

@ -22,6 +22,10 @@ namespace KWin
*/
static constexpr auto s_pageflipTimeout = 5s;
// amdgpu doesn't handle this correctly, so it's off by default
// https://gitlab.freedesktop.org/drm/amd/-/issues/2186
static const bool s_delayVrrCursorUpdates = qEnvironmentVariableIntValue("KWIN_DRM_DELAY_VRR_CURSOR_UPDATES") == 1;
DrmCommitThread::DrmCommitThread(DrmGpu *gpu, const QString &name)
{
if (!gpu->atomicModeSetting()) {
@ -73,6 +77,30 @@ DrmCommitThread::DrmCommitThread(DrmGpu *gpu, const QString &name)
}
continue;
}
if (m_commits.front()->isCursorOnly() && m_vrr && s_delayVrrCursorUpdates) {
// wait for a primary plane commit to be in, while still enforcing
// a minimum cursor refresh rate of 30Hz
const auto cursorTarget = m_lastPageflip + std::chrono::duration_cast<std::chrono::nanoseconds>(1s) / 30;
const bool cursorOnly = std::all_of(m_commits.begin(), m_commits.end(), [](const auto &commit) {
return commit->isCursorOnly();
});
if (cursorOnly) {
// no primary plane commit, just wait until a new one gets added or the cursorTarget time is reached
if (m_commitPending.wait_until(lock, cursorTarget) == std::cv_status::no_timeout) {
continue;
}
} else {
bool timeout = true;
while (std::chrono::steady_clock::now() < cursorTarget && timeout && m_commits.front()->isCursorOnly()) {
timeout = m_commitPending.wait_for(lock, 50us) == std::cv_status::timeout;
optimizeCommits();
}
if (!timeout) {
// some new commit was added, process that
continue;
}
}
}
submit();
}
}));