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
|
|
@ -34,13 +34,6 @@ SP<CSyncTimeline> CSyncTimeline::create(int drmFD_, CFileDescriptor&& drmSyncobj
|
|||
}
|
||||
|
||||
CSyncTimeline::~CSyncTimeline() {
|
||||
for (auto& w : waiters) {
|
||||
if (w->source) {
|
||||
wl_event_source_remove(w->source);
|
||||
w->source = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle == 0)
|
||||
return;
|
||||
|
||||
|
|
@ -64,34 +57,8 @@ std::optional<bool> CSyncTimeline::check(uint64_t point, uint32_t flags) {
|
|||
return ret == 0;
|
||||
}
|
||||
|
||||
static int handleWaiterFD(int fd, uint32_t mask, void* data) {
|
||||
auto waiter = (CSyncTimeline::SWaiter*)data;
|
||||
|
||||
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
|
||||
Debug::log(ERR, "handleWaiterFD: eventfd error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mask & WL_EVENT_READABLE) {
|
||||
uint64_t value = 0;
|
||||
if (read(fd, &value, sizeof(value)) <= 0)
|
||||
Debug::log(ERR, "handleWaiterFD: failed to read from eventfd");
|
||||
}
|
||||
|
||||
wl_event_source_remove(waiter->source);
|
||||
waiter->source = nullptr;
|
||||
|
||||
if (waiter->fn)
|
||||
waiter->fn();
|
||||
|
||||
if (waiter->timeline)
|
||||
waiter->timeline->removeWaiter(waiter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CSyncTimeline::addWaiter(const std::function<void()>& waiter, uint64_t point, uint32_t flags) {
|
||||
CFileDescriptor eventFd = CFileDescriptor{eventfd(0, EFD_CLOEXEC)};
|
||||
auto eventFd = CFileDescriptor(eventfd(0, EFD_CLOEXEC));
|
||||
|
||||
if (!eventFd.isValid()) {
|
||||
Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd");
|
||||
|
|
@ -103,46 +70,11 @@ bool CSyncTimeline::addWaiter(const std::function<void()>& waiter, uint64_t poin
|
|||
return false;
|
||||
}
|
||||
|
||||
if (eventFd.isReadable()) {
|
||||
waiter();
|
||||
return true;
|
||||
}
|
||||
|
||||
auto w = makeShared<SWaiter>();
|
||||
w->fn = waiter;
|
||||
w->timeline = self;
|
||||
w->eventFd = std::move(eventFd);
|
||||
|
||||
w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, w->eventFd.get(), WL_EVENT_READABLE, ::handleWaiterFD, w.get());
|
||||
if (!w->source) {
|
||||
Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
waiters.emplace_back(w);
|
||||
g_pEventLoopManager->doOnReadable(std::move(eventFd), waiter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSyncTimeline::removeWaiter(SWaiter* w) {
|
||||
if (w->source) {
|
||||
wl_event_source_remove(w->source);
|
||||
w->source = nullptr;
|
||||
}
|
||||
std::erase_if(waiters, [w](const auto& e) { return e.get() == w; });
|
||||
}
|
||||
|
||||
void CSyncTimeline::removeAllWaiters() {
|
||||
for (auto& w : waiters) {
|
||||
if (w->source) {
|
||||
wl_event_source_remove(w->source);
|
||||
w->source = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
waiters.clear();
|
||||
}
|
||||
|
||||
CFileDescriptor CSyncTimeline::exportAsSyncFileFD(uint64_t src) {
|
||||
int sync = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,21 +20,12 @@ class CSyncTimeline {
|
|||
static SP<CSyncTimeline> create(int drmFD_, Hyprutils::OS::CFileDescriptor&& drmSyncobjFD);
|
||||
~CSyncTimeline();
|
||||
|
||||
struct SWaiter {
|
||||
std::function<void()> fn;
|
||||
wl_event_source* source = nullptr;
|
||||
WP<CSyncTimeline> timeline;
|
||||
Hyprutils::OS::CFileDescriptor eventFd;
|
||||
};
|
||||
|
||||
// check if the timeline point has been signaled
|
||||
// flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
|
||||
// std::nullopt on fail
|
||||
std::optional<bool> check(uint64_t point, uint32_t flags);
|
||||
|
||||
bool addWaiter(const std::function<void()>& waiter, uint64_t point, uint32_t flags);
|
||||
void removeWaiter(SWaiter*);
|
||||
void removeAllWaiters();
|
||||
Hyprutils::OS::CFileDescriptor exportAsSyncFileFD(uint64_t src);
|
||||
bool importFromSyncFileFD(uint64_t dst, Hyprutils::OS::CFileDescriptor& fd);
|
||||
bool transfer(SP<CSyncTimeline> from, uint64_t fromPoint, uint64_t toPoint);
|
||||
|
|
@ -47,6 +38,4 @@ class CSyncTimeline {
|
|||
|
||||
private:
|
||||
CSyncTimeline() = default;
|
||||
|
||||
std::vector<SP<SWaiter>> waiters;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue