From 016da234d0e852de3ef20eb2e89ac58d2a85f6e7 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 21 Jul 2024 13:09:54 +0200 Subject: Core: Move to aquamarine (#6608) Moves Hyprland from wlroots to aquamarine for the backend. --------- Signed-off-by: Vaxry Co-authored-by: Mihai Fufezan Co-authored-by: Jan Beich Co-authored-by: vaxerski Co-authored-by: UjinT34 <41110182+UjinT34@users.noreply.github.com> Co-authored-by: Tom Englund Co-authored-by: Ikalco <73481042+ikalco@users.noreply.github.com> Co-authored-by: diniamo --- src/helpers/sync/SyncTimeline.cpp | 190 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 src/helpers/sync/SyncTimeline.cpp (limited to 'src/helpers/sync/SyncTimeline.cpp') diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp new file mode 100644 index 00000000..352120ea --- /dev/null +++ b/src/helpers/sync/SyncTimeline.cpp @@ -0,0 +1,190 @@ +#include "SyncTimeline.hpp" +#include "../../defines.hpp" +#include "../../managers/eventLoop/EventLoopManager.hpp" + +#include +#include + +SP CSyncTimeline::create(int drmFD_) { + auto timeline = SP(new CSyncTimeline); + timeline->drmFD = drmFD_; + timeline->self = timeline; + + if (drmSyncobjCreate(drmFD_, 0, &timeline->handle)) { + Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj??"); + return nullptr; + } + + return timeline; +} + +SP CSyncTimeline::create(int drmFD_, int drmSyncobjFD) { + auto timeline = SP(new CSyncTimeline); + timeline->drmFD = drmFD_; + timeline->self = timeline; + + if (drmSyncobjFDToHandle(drmFD_, drmSyncobjFD, &timeline->handle)) { + Debug::log(ERR, "CSyncTimeline: failed to create a drm syncobj from fd??"); + return nullptr; + } + + return timeline; +} + +CSyncTimeline::~CSyncTimeline() { + if (handle == 0) + return; + + drmSyncobjDestroy(drmFD, handle); +} + +std::optional CSyncTimeline::check(uint64_t point, uint32_t flags) { +#ifdef __FreeBSD__ + constexpr int ETIME_ERR = ETIMEDOUT; +#else + constexpr int ETIME_ERR = ETIME; +#endif + + uint32_t signaled = 0; + int ret = drmSyncobjTimelineWait(drmFD, &handle, &point, 1, 0, flags, &signaled); + if (ret != 0 && ret != -ETIME_ERR) { + Debug::log(ERR, "CSyncTimeline::check: drmSyncobjTimelineWait failed"); + return std::nullopt; + } + + 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& waiter, uint64_t point, uint32_t flags) { + auto w = makeShared(); + w->fn = waiter; + w->timeline = self; + + int eventFD = eventfd(0, EFD_CLOEXEC); + + if (eventFD < 0) { + Debug::log(ERR, "CSyncTimeline::addWaiter: failed to acquire an eventfd"); + return false; + } + + drm_syncobj_eventfd syncobjEventFD = { + .handle = handle, + .flags = flags, + .point = point, + .fd = eventFD, + }; + + if (drmIoctl(drmFD, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobjEventFD) != 0) { + Debug::log(ERR, "CSyncTimeline::addWaiter: drmIoctl failed"); + close(eventFD); + return false; + } + + w->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, eventFD, WL_EVENT_READABLE, ::handleWaiterFD, w.get()); + if (!w->source) { + Debug::log(ERR, "CSyncTimeline::addWaiter: wl_event_loop_add_fd failed"); + close(eventFD); + return false; + } + + waiters.emplace_back(w); + + 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; }); +} + +int CSyncTimeline::exportAsSyncFileFD(uint64_t src) { + int sync = -1; + + uint32_t syncHandle = 0; + if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjCreate failed"); + return -1; + } + + if (drmSyncobjTransfer(drmFD, syncHandle, 0, handle, src, 0)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjTransfer failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + if (drmSyncobjExportSyncFile(drmFD, syncHandle, &sync)) { + Debug::log(ERR, "exportAsSyncFileFD: drmSyncobjExportSyncFile failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return -1; + } + + drmSyncobjDestroy(drmFD, syncHandle); + return sync; +} + +bool CSyncTimeline::importFromSyncFileFD(uint64_t dst, int fd) { + uint32_t syncHandle = 0; + + if (drmSyncobjCreate(drmFD, 0, &syncHandle)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjCreate failed"); + return false; + } + + if (drmSyncobjImportSyncFile(drmFD, syncHandle, fd)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjImportSyncFile failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return false; + } + + if (drmSyncobjTransfer(drmFD, handle, dst, syncHandle, 0, 0)) { + Debug::log(ERR, "importFromSyncFileFD: drmSyncobjTransfer failed"); + drmSyncobjDestroy(drmFD, syncHandle); + return false; + } + + drmSyncobjDestroy(drmFD, syncHandle); + return true; +} + +bool CSyncTimeline::transfer(SP from, uint64_t fromPoint, uint64_t toPoint) { + if (drmFD != from->drmFD) { + Debug::log(ERR, "CSyncTimeline::transfer: cannot transfer timelines between gpus, {} -> {}", from->drmFD, drmFD); + return false; + } + + if (drmSyncobjTransfer(drmFD, handle, toPoint, from->handle, fromPoint, 0)) { + Debug::log(ERR, "CSyncTimeline::transfer: drmSyncobjTransfer failed"); + return false; + } + + return true; +} -- cgit v1.2.3