diff options
| author | PancakeTAS <pancake@mgnet.work> | 2026-05-18 10:45:34 +0200 |
|---|---|---|
| committer | PancakeTAS <pancake@mgnet.work> | 2026-05-18 10:45:34 +0200 |
| commit | baf77bec541ef02659153a59118801c8002d7fdc (patch) | |
| tree | a27986a1c66d2093c92c33638f6d044d36a7741d /src/syncobject.cpp | |
| parent | Initial commit (diff) | |
Implement (non-timeline) sync objects
Diffstat (limited to 'src/syncobject.cpp')
| -rw-r--r-- | src/syncobject.cpp | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/src/syncobject.cpp b/src/syncobject.cpp new file mode 100644 index 0000000..59c06fd --- /dev/null +++ b/src/syncobject.cpp @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: MIT */ + +#include "syncobject.hpp" +#include "priv/ioctl.hpp" + +#include <cstdint> +#include <optional> +#include <vector> + +#include <unistd.h> + +using namespace drm; + +SyncObject::SyncObject(int fd, bool signal) : m_fd(fd) { + drm_syncobj_create args{ + .flags = signal ? DRM_SYNCOBJ_CREATE_SIGNALED : 0U + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_CREATE, args); + + this->m_handle = args.handle; +} + +SyncObject::SyncObject(int fd, int syncobj_fd, bool close) : m_fd(fd) { + try { + drm_syncobj_handle args{ + .fd = syncobj_fd + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args); + + this->m_handle = args.handle; + } catch (...) { + if (close) { + ::close(syncobj_fd); + } + + throw; + } + + if (close) { + ::close(syncobj_fd); + } +} + +int SyncObject::exportFd() const { + drm_syncobj_handle args{ + .handle = this->m_handle, + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args); + + return args.fd; +} + +void SyncObject::importSyncFile(int syncfile_fd, bool close) const { + try { + drm_syncobj_handle args{ + .handle = this->m_handle, + .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, + .fd = syncfile_fd + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args); + } catch (...) { + if (close) { + ::close(syncfile_fd); + } + + throw; + } + + if (close) { + ::close(syncfile_fd); + } +} + +int SyncObject::exportSyncFile() const { + drm_syncobj_handle args{ + .handle = this->m_handle, + .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args); + + return args.fd; +} + +void SyncObject::signal(int fd, const std::vector<uint32_t>& objects) { + if (objects.empty()) { + return; + } + + drm_syncobj_array args{ + .handles = reinterpret_cast<uint64_t>(objects.data()), + .count_handles = static_cast<uint32_t>(objects.size()) + }; + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, args); +} + +void SyncObject::reset(int fd, const std::vector<uint32_t>& objects) { + if (objects.empty()) { + return; + } + + drm_syncobj_array args{ + .handles = reinterpret_cast<uint64_t>(objects.data()), + .count_handles = static_cast<uint32_t>(objects.size()) + }; + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_RESET, args); +} + +uint32_t SyncObject::wait( + int fd, + const std::vector<uint32_t>& objects, + int64_t timeout, + bool waitAll, + bool waitEmpty, + bool waitAvailable, + std::optional<uint64_t> deadlineHint +) { + if (objects.empty()) { + return 0; + } + + if (waitAvailable) { + waitEmpty = false; + } + + drm_syncobj_wait args{ + .handles = reinterpret_cast<uint64_t>(objects.data()), + .timeout_nsec = timeout, + .count_handles = static_cast<uint32_t>(objects.size()), + .flags = + (waitAll ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL : 0U) | + (waitEmpty ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT : 0U) | + (waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U) | + (deadlineHint.has_value() ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE : 0U), + .deadline_nsec = deadlineHint.value_or(0) + }; + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_WAIT, args); + + return args.first_signaled; +} + +void SyncObject::destruct() noexcept { + if (this->m_fd < 0) { + return; + } + + drm_syncobj_destroy args{ + .handle = this->m_handle + }; + try { + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_DESTROY, args); + } catch(...) { + (void) 0; // not much we can do about the leak + } + + this->m_fd = -1; +} |
