Skip to content

Commit

Permalink
core: move wayland event reading into the poll thread (#655)
Browse files Browse the repository at this point in the history
This was done, so that we can

  wl_display_prepare_read -> poll -> wl_display_read_events

That fixes synchronization issues on nvidia proprietary drivers.
  • Loading branch information
PaideiaDilemma authored Jan 21, 2025
1 parent 02639c2 commit d547d1d
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 41 deletions.
10 changes: 7 additions & 3 deletions src/core/LockSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ void CSessionLockSurface::onScaleUpdate() {
}

void CSessionLockSurface::render() {
Debug::log(TRACE, "render lock");

if (frameCallback || !readyForFrame) {
needsFrame = true;
return;
Expand All @@ -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();
});

Expand Down
3 changes: 3 additions & 0 deletions src/core/LockSurface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
65 changes: 33 additions & 32 deletions src/core/hyprlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

if (errno == EINTR)
continue;

for (size_t i = 0; i < fdcount; ++i) {
if (pollfds[i].revents & POLLHUP) {
Debug::log(CRIT, "[core] Disconnected from pollfd id {}", i);
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; });
}
}
});
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/core/hyprlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 0 additions & 6 deletions src/renderer/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit d547d1d

Please sign in to comment.