core: wait for dmabuf readiness (#9806)
* add doOnReadable to event loop manager * move syncTimeline addWaiter to doOnReadable * wait on dmabuf buffers to be readable * don't over synchronize in scanout, also give present feedback on same buffer commit
This commit is contained in:
parent
ffd6cf65e4
commit
0e521788bc
8 changed files with 147 additions and 116 deletions
|
|
@ -26,6 +26,11 @@ CEventLoopManager::~CEventLoopManager() {
|
|||
wl_event_source_remove(eventSourceData.eventSource);
|
||||
}
|
||||
|
||||
for (auto const& w : m_vReadableWaiters) {
|
||||
if (w->source != nullptr)
|
||||
wl_event_source_remove(w->source);
|
||||
}
|
||||
|
||||
if (m_sWayland.eventSource)
|
||||
wl_event_source_remove(m_sWayland.eventSource);
|
||||
if (m_sIdle.eventSource)
|
||||
|
|
@ -50,6 +55,33 @@ static int configWatcherWrite(int fd, uint32_t mask, void* data) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int handleWaiterFD(int fd, uint32_t mask, void* data) {
|
||||
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
|
||||
Debug::log(ERR, "handleWaiterFD: readable waiter error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mask & WL_EVENT_READABLE)
|
||||
g_pEventLoopManager->onFdReadable((CEventLoopManager::SReadableWaiter*)data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CEventLoopManager::onFdReadable(SReadableWaiter* waiter) {
|
||||
auto it = std::ranges::find_if(m_vReadableWaiters, [waiter](const UP<SReadableWaiter>& w) { return waiter == w.get() && w->fd == waiter->fd && w->source == waiter->source; });
|
||||
|
||||
if (waiter->source) {
|
||||
wl_event_source_remove(waiter->source);
|
||||
waiter->source = nullptr;
|
||||
}
|
||||
|
||||
if (waiter->fn)
|
||||
waiter->fn();
|
||||
|
||||
if (it != m_vReadableWaiters.end())
|
||||
m_vReadableWaiters.erase(it);
|
||||
}
|
||||
|
||||
void CEventLoopManager::enterLoop() {
|
||||
m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd.get(), WL_EVENT_READABLE, timerWrite, nullptr);
|
||||
|
||||
|
|
@ -143,6 +175,16 @@ void CEventLoopManager::doLater(const std::function<void()>& fn) {
|
|||
&m_sIdle);
|
||||
}
|
||||
|
||||
void CEventLoopManager::doOnReadable(CFileDescriptor fd, const std::function<void()>& fn) {
|
||||
if (!fd.isValid() || fd.isReadable()) {
|
||||
fn();
|
||||
return;
|
||||
}
|
||||
|
||||
auto& waiter = m_vReadableWaiters.emplace_back(makeUnique<SReadableWaiter>(nullptr, std::move(fd), fn));
|
||||
waiter->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, waiter->fd.get(), WL_EVENT_READABLE, ::handleWaiterFD, waiter.get());
|
||||
}
|
||||
|
||||
void CEventLoopManager::syncPollFDs() {
|
||||
auto aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs();
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,17 @@ class CEventLoopManager {
|
|||
std::vector<std::function<void()>> fns;
|
||||
};
|
||||
|
||||
struct SReadableWaiter {
|
||||
wl_event_source* source;
|
||||
Hyprutils::OS::CFileDescriptor fd;
|
||||
std::function<void()> fn;
|
||||
};
|
||||
|
||||
// schedule function to when fd is readable (WL_EVENT_READABLE / POLLIN),
|
||||
// takes ownership of fd
|
||||
void doOnReadable(Hyprutils::OS::CFileDescriptor fd, const std::function<void()>& fn);
|
||||
void onFdReadable(SReadableWaiter* waiter);
|
||||
|
||||
private:
|
||||
// Manages the event sources after AQ pollFDs change.
|
||||
void syncPollFDs();
|
||||
|
|
@ -58,8 +69,9 @@ class CEventLoopManager {
|
|||
Hyprutils::OS::CFileDescriptor timerfd;
|
||||
} m_sTimers;
|
||||
|
||||
SIdleData m_sIdle;
|
||||
std::map<int, SEventSourceData> aqEventSources;
|
||||
SIdleData m_sIdle;
|
||||
std::map<int, SEventSourceData> aqEventSources;
|
||||
std::vector<UP<SReadableWaiter>> m_vReadableWaiters;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener pollFDsChanged;
|
||||
|
|
@ -67,7 +79,6 @@ class CEventLoopManager {
|
|||
|
||||
wl_event_source* m_configWatcherInotifySource = nullptr;
|
||||
|
||||
friend class CSyncTimeline;
|
||||
friend class CAsyncDialogBox;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue