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.
This commit is contained in:
Maximilian Seidler 2025-01-21 13:42:11 +00:00 committed by GitHub
parent 02639c2759
commit d547d1d4e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 46 additions and 41 deletions

View file

@ -117,8 +117,6 @@ void CSessionLockSurface::onScaleUpdate() {
} }
void CSessionLockSurface::render() { void CSessionLockSurface::render() {
Debug::log(TRACE, "render lock");
if (frameCallback || !readyForFrame) { if (frameCallback || !readyForFrame) {
needsFrame = true; needsFrame = true;
return; return;
@ -127,10 +125,16 @@ void CSessionLockSurface::render() {
g_pAnimationManager->tick(); g_pAnimationManager->tick();
const auto FEEDBACK = g_pRenderer->renderLock(*this); const auto FEEDBACK = g_pRenderer->renderLock(*this);
frameCallback = makeShared<CCWlCallback>(surface->sendFrame()); frameCallback = makeShared<CCWlCallback>(surface->sendFrame());
frameCallback->setDone([this](CCWlCallback* r, uint32_t data) { frameCallback->setDone([this](CCWlCallback* r, uint32_t frameTime) {
if (g_pHyprlock->m_bTerminate) if (g_pHyprlock->m_bTerminate)
return; return;
Debug::log(TRACE, "[{}] frame {}, Current fps: {:.2f}", output->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime));
m_lastFrameTime = frameTime;
m_frames++;
onCallback(); onCallback();
}); });

View file

@ -42,6 +42,9 @@ class CSessionLockSurface {
bool needsFrame = false; bool needsFrame = false;
uint32_t m_lastFrameTime = 0;
uint32_t m_frames = 0;
// wayland callbacks // wayland callbacks
SP<CCWlCallback> frameCallback = nullptr; SP<CCWlCallback> frameCallback = nullptr;

View file

@ -368,32 +368,45 @@ void CHyprlock::run() {
std::thread pollThr([this, &pollfds, fdcount]() { std::thread pollThr([this, &pollfds, fdcount]() {
while (!m_bTerminate) { 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) { int events = 0;
if (errno == EINTR) if (preparedToRead) {
continue; events = poll(pollfds, fdcount, 5000);
Debug::log(CRIT, "[core] Polling fds failed with {}", errno); if (events < 0) {
attemptRestoreOnDeath(); if (preparedToRead)
m_bTerminate = true; wl_display_cancel_read(m_sWaylandState.display);
exit(1);
}
for (size_t i = 0; i < fdcount; ++i) { if (errno == EINTR)
if (pollfds[i].revents & POLLHUP) { continue;
Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i);
Debug::log(CRIT, "[core] Polling fds failed with {}", errno);
attemptRestoreOnDeath(); attemptRestoreOnDeath();
m_bTerminate = true; m_bTerminate = true;
exit(1); 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"); Debug::log(TRACE, "[core] got poll event");
std::lock_guard<std::mutex> lg2(m_sLoopState.eventLoopMutex); std::unique_lock lk(m_sLoopState.eventLoopMutex);
m_sLoopState.event = true; m_sLoopState.event = true;
m_sLoopState.loopCV.notify_all(); 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; 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 */) { if (pollfds[1].revents & POLLIN /* dbus */) {
while (dbusConn && dbusConn->processPendingEvent()) { 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 // do timers
m_sLoopState.timersMutex.lock(); m_sLoopState.timersMutex.lock();
auto timerscpy = m_vTimers; auto timerscpy = m_vTimers;

View file

@ -151,6 +151,9 @@ class CHyprlock {
std::condition_variable loopCV; std::condition_variable loopCV;
bool event = false; bool event = false;
std::condition_variable wlDispatchCV;
bool wlDispatched = false;
std::condition_variable timerCV; std::condition_variable timerCV;
std::mutex timerRequestMutex; std::mutex timerRequestMutex;
bool timerEvent = false; bool timerEvent = false;

View file

@ -198,8 +198,6 @@ CRenderer::CRenderer() {
g_pAnimationManager->createAnimation(0.f, opacity, g_pConfigManager->m_AnimationTree.getConfig("fadeIn")); g_pAnimationManager->createAnimation(0.f, opacity, g_pConfigManager->m_AnimationTree.getConfig("fadeIn"));
} }
static int frames = 0;
// //
CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf) { CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf) {
static auto* const PDISABLEBAR = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:disable_loading_bar"); 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; feedback.needsFrame = feedback.needsFrame || !asyncResourceGatherer->gathered;
glDisable(GL_BLEND); glDisable(GL_BLEND);