From 6f030e60bf0ab210c0a92eb04afcbe7ef2ca7792 Mon Sep 17 00:00:00 2001 From: Maroun Deeb Date: Tue, 7 Jan 2025 18:37:04 +0200 Subject: [PATCH] GPU hotplug support --- src/managers/eventLoop/EventLoopManager.cpp | 30 ++++++++++++++++----- src/managers/eventLoop/EventLoopManager.hpp | 22 +++++++++++---- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index db8b49b6ebd..aaa6c107b0f 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -16,11 +17,12 @@ CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEvent m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); m_sWayland.loop = wlEventLoop; m_sWayland.display = display; + aqEventSources = std::map{}; } CEventLoopManager::~CEventLoopManager() { - for (auto const& eventSource : m_sWayland.aqEventSources) { - wl_event_source_remove(eventSource); + for (auto const& [_, eventSourceData] : aqEventSources) { + wl_event_source_remove(eventSourceData.eventSource); } if (m_sWayland.eventSource) @@ -45,10 +47,8 @@ static int aquamarineFDWrite(int fd, uint32_t mask, void* data) { void CEventLoopManager::enterLoop() { m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); - aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); - for (auto const& fd : aqPollFDs) { - m_sWayland.aqEventSources.emplace_back(wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get())); - } + syncPollFDs(); + m_sListeners.pollFDsChanged = g_pCompositor->m_pAqBackend->events.pollFDsChanged.registerListener([this](std::any d) { syncPollFDs(); }); // if we have a session, dispatch it to get the pending input devices if (g_pCompositor->m_pAqBackend->hasSession()) @@ -133,3 +133,21 @@ void CEventLoopManager::doLater(const std::function& fn) { }, &m_sIdle); } + +void CEventLoopManager::syncPollFDs() { + auto aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs(); + + for (auto it = aqEventSources.begin(); it != aqEventSources.end();) { + if (std::ranges::all_of(aqPollFDs, [&](SP fd) { return fd->fd != it->first; })) { + wl_event_source_remove(it->second.eventSource); + it = aqEventSources.erase(it); + } else { + ++it; + } + } + + for (auto& fd : aqPollFDs | std::views::filter([&](SP fd) { return !aqEventSources.contains(fd->fd); })) { + auto eventSource = wl_event_loop_add_fd(m_sWayland.loop, fd->fd, WL_EVENT_READABLE, aquamarineFDWrite, fd.get()); + aqEventSources[fd->fd] = {.pollFD = fd, .eventSource = eventSource}; + } +} diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 39d8bbebafa..96a984a2fe2 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "helpers/signal/Signal.hpp" #include "EventLoopTimer.hpp" @@ -36,11 +37,18 @@ class CEventLoopManager { }; private: + // Manages the event sources after AQ pollFDs change. + void syncPollFDs(); + + struct SEventSourceData { + SP pollFD; + wl_event_source* eventSource = nullptr; + }; + struct { - wl_event_loop* loop = nullptr; - wl_display* display = nullptr; - wl_event_source* eventSource = nullptr; - std::vector aqEventSources; + wl_event_loop* loop = nullptr; + wl_display* display = nullptr; + wl_event_source* eventSource = nullptr; } m_sWayland; struct { @@ -49,7 +57,11 @@ class CEventLoopManager { } m_sTimers; SIdleData m_sIdle; - std::vector> aqPollFDs; + std::map aqEventSources; + + struct { + CHyprSignalListener pollFDsChanged; + } m_sListeners; friend class CSyncTimeline; };