summaryrefslogtreecommitdiff
path: root/src/syncobject.cpp
diff options
context:
space:
mode:
authorPancakeTAS <pancake@mgnet.work>2026-05-18 10:45:34 +0200
committerPancakeTAS <pancake@mgnet.work>2026-05-18 10:45:34 +0200
commitbaf77bec541ef02659153a59118801c8002d7fdc (patch)
treea27986a1c66d2093c92c33638f6d044d36a7741d /src/syncobject.cpp
parentInitial commit (diff)
Implement (non-timeline) sync objects
Diffstat (limited to '')
-rw-r--r--src/syncobject.cpp156
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;
+}