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() {
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<CCWlCallback>(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();
});

View file

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

View file

@ -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<std::mutex> 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;

View file

@ -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;

View file

@ -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);