From d547d1d4e3b0912f71c4a4952e2a5935689e45a1 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:42:11 +0000 Subject: [PATCH] core: move wayland event reading into the poll thread (#655) This was done, so that we can wl_display_prepare_read -> poll -> wl_display_read_events That fixes synchronization issues on nvidia proprietary drivers. --- src/core/LockSurface.cpp | 10 ++++-- src/core/LockSurface.hpp | 3 ++ src/core/hyprlock.cpp | 65 ++++++++++++++++++++------------------- src/core/hyprlock.hpp | 3 ++ src/renderer/Renderer.cpp | 6 ---- 5 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/core/LockSurface.cpp b/src/core/LockSurface.cpp index 29ad05c..1625272 100644 --- a/src/core/LockSurface.cpp +++ b/src/core/LockSurface.cpp @@ -117,8 +117,6 @@ void CSessionLockSurface::onScaleUpdate() { } void CSessionLockSurface::render() { - Debug::log(TRACE, "render lock"); - if (frameCallback || !readyForFrame) { needsFrame = true; return; @@ -127,10 +125,16 @@ void CSessionLockSurface::render() { g_pAnimationManager->tick(); const auto FEEDBACK = g_pRenderer->renderLock(*this); frameCallback = makeShared(surface->sendFrame()); - frameCallback->setDone([this](CCWlCallback* r, uint32_t data) { + frameCallback->setDone([this](CCWlCallback* r, uint32_t frameTime) { if (g_pHyprlock->m_bTerminate) return; + Debug::log(TRACE, "[{}] frame {}, Current fps: {:.2f}", output->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime)); + + m_lastFrameTime = frameTime; + + m_frames++; + onCallback(); }); diff --git a/src/core/LockSurface.hpp b/src/core/LockSurface.hpp index 9461541..f4f64e7 100644 --- a/src/core/LockSurface.hpp +++ b/src/core/LockSurface.hpp @@ -42,6 +42,9 @@ class CSessionLockSurface { bool needsFrame = false; + uint32_t m_lastFrameTime = 0; + uint32_t m_frames = 0; + // wayland callbacks SP frameCallback = nullptr; diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index 5bce53c..50eef94 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -368,32 +368,45 @@ void CHyprlock::run() { std::thread pollThr([this, &pollfds, fdcount]() { while (!m_bTerminate) { - int ret = poll(pollfds, fdcount, 5000 /* 5 seconds, reasonable. Just in case we need to terminate and the signal fails */); + bool preparedToRead = wl_display_prepare_read(m_sWaylandState.display) == 0; - if (ret < 0) { - if (errno == EINTR) - continue; + int events = 0; + if (preparedToRead) { + events = poll(pollfds, fdcount, 5000); - Debug::log(CRIT, "[core] Polling fds failed with {}", errno); - attemptRestoreOnDeath(); - m_bTerminate = true; - exit(1); - } + if (events < 0) { + if (preparedToRead) + wl_display_cancel_read(m_sWaylandState.display); - for (size_t i = 0; i < fdcount; ++i) { - if (pollfds[i].revents & POLLHUP) { - Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i); + if (errno == EINTR) + continue; + + Debug::log(CRIT, "[core] Polling fds failed with {}", errno); attemptRestoreOnDeath(); m_bTerminate = true; exit(1); } + + for (size_t i = 0; i < fdcount; ++i) { + if (pollfds[i].revents & POLLHUP) { + Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i); + attemptRestoreOnDeath(); + m_bTerminate = true; + exit(1); + } + } + + wl_display_read_events(m_sWaylandState.display); + m_sLoopState.wlDispatched = false; } - if (ret != 0) { + if (events > 0 || !preparedToRead) { Debug::log(TRACE, "[core] got poll event"); - std::lock_guard lg2(m_sLoopState.eventLoopMutex); + std::unique_lock lk(m_sLoopState.eventLoopMutex); m_sLoopState.event = true; m_sLoopState.loopCV.notify_all(); + + m_sLoopState.wlDispatchCV.wait_for(lk, std::chrono::milliseconds(100), [this] { return m_sLoopState.wlDispatched; }); } } }); @@ -439,30 +452,18 @@ void CHyprlock::run() { m_sLoopState.event = false; + wl_display_dispatch_pending(m_sWaylandState.display); + wl_display_flush(m_sWaylandState.display); + + m_sLoopState.wlDispatched = true; + m_sLoopState.wlDispatchCV.notify_all(); + if (pollfds[1].revents & POLLIN /* dbus */) { while (dbusConn && dbusConn->processPendingEvent()) { ; } } - if (pollfds[0].revents & POLLIN /* wl */) { - Debug::log(TRACE, "got wl event"); - wl_display_flush(m_sWaylandState.display); - if (wl_display_prepare_read(m_sWaylandState.display) == 0) { - wl_display_read_events(m_sWaylandState.display); - wl_display_dispatch_pending(m_sWaylandState.display); - } else { - wl_display_dispatch(m_sWaylandState.display); - } - } - - // finalize wayland dispatching. Dispatch pending on the queue - int ret = 0; - do { - ret = wl_display_dispatch_pending(m_sWaylandState.display); - wl_display_flush(m_sWaylandState.display); - } while (ret > 0 && !m_bTerminate); - // do timers m_sLoopState.timersMutex.lock(); auto timerscpy = m_vTimers; diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index a2a0ca3..98608f0 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -151,6 +151,9 @@ class CHyprlock { std::condition_variable loopCV; bool event = false; + std::condition_variable wlDispatchCV; + bool wlDispatched = false; + std::condition_variable timerCV; std::mutex timerRequestMutex; bool timerEvent = false; diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index ffe9f8e..288ef7d 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -198,8 +198,6 @@ CRenderer::CRenderer() { g_pAnimationManager->createAnimation(0.f, opacity, g_pConfigManager->m_AnimationTree.getConfig("fadeIn")); } -static int frames = 0; - // CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf) { static auto* const PDISABLEBAR = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:disable_loading_bar"); @@ -238,10 +236,6 @@ CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf } } - frames++; - - Debug::log(TRACE, "frame {}", frames); - feedback.needsFrame = feedback.needsFrame || !asyncResourceGatherer->gathered; glDisable(GL_BLEND);