diff options
Diffstat (limited to '')
| -rw-r--r-- | include/drm++/ioctl.hpp | 16 | ||||
| -rw-r--r-- | include/drm++/syncobject.hpp | 220 |
2 files changed, 102 insertions, 134 deletions
diff --git a/include/drm++/ioctl.hpp b/include/drm++/ioctl.hpp index 1851df6..1a68dae 100644 --- a/include/drm++/ioctl.hpp +++ b/include/drm++/ioctl.hpp @@ -11,28 +11,30 @@ namespace drm::ioctl { -/// Type of ioctl() error +/// Type of ioctl() error. enum class Error : u8 { BadFileDescriptor, InvalidArgument, NotSupported, - Other //!< check errno field + Other //!< Check errno field }; -/// Exception class wrapping around ioctl() +/// Exception class wrapping around ioctl(). class Exception : public std::exception { public: - /// Construct an exception from errno + /// Construct an exception from errno. explicit Exception(int fd, unsigned long op); + /// Convert the exception into human-readable form. + std::string readable(); + + // Private access GETTER(fd) GETTER(op) GETTER(code) GETTER(syserrno) - /// Convert the exception into human-readable form. - std::string readable(); - + // Default operators and destructor DEFAULT_OPERATORS(Exception) ~Exception() override; private: diff --git a/include/drm++/syncobject.hpp b/include/drm++/syncobject.hpp index 9751559..f530c49 100644 --- a/include/drm++/syncobject.hpp +++ b/include/drm++/syncobject.hpp @@ -9,70 +9,34 @@ namespace drm::syncobj { -/// Wait modes for waiting on binary sync objects -enum class WaitMode : u8 { - NoWaitEmpty, //!< Return -EINVAL when waiting on an empty sync object - WaitEmpty, //!< Wait for empty sync objects to be filled and signaled - WaitAvailable //!< Wait for empty sync objects to be filled, but do not wait for signaling -}; - +class SyncObject; class TimelineSyncObject; -/// A (binary) synchronization object is a reference-counted container which can hold a DRM fence -/// @throws drm::ioctl::Exception on failure -class SyncObject { +/// Common base class for SyncObject and TimelineSyncObject. +class SyncObjectBase { + friend class SyncObject; + friend class TimelineSyncObject; public: - /// Create a new sync object - SyncObject(int fd, bool signaled = false); + /// Create a new sync object. + SyncObjectBase(int fd, bool signaled = false); - /// Import an existing sync object + /// Import an existing sync object. /// @param close Close syncobj_fd after import (regardless of success) - SyncObject(int fd, int syncobj_fd, bool close = true); + SyncObjectBase(int fd, int syncobj_fd, bool close = true); - /// Export a new reference to sync object, increasing the reference counter + /// Export a new reference to sync object, incrementing the reference count. [[nodiscard]] int exportFd() const; - /// Import a sync file (DRM fence) into the sync object - /// @param close Close syncfile_fd after import (regardless of success) - void importSyncFile(int syncfile_fd, bool close = true) const; - - /// Export a sync file from the DRM fence within the sync object - /// Any subsequent modifications to the sync object are not applied to the exported sync file - [[nodiscard]] int exportSyncFile() const; - - /// Transfer a DRM fence into another sync object - void transfer(const SyncObject& dest) const; - void transfer(const TimelineSyncObject& dest, u64 destPoint) const; - - /// Signal the sync object by emplacing a signaled fence into it - void signal() const; - - /// Reset the sync object by removing the fence from it - void reset() const; - - /// Wait for the sync object to be signaled - /// @param timeout Absolute timeout in nanoseconds, or zero for polling - /// @param deadlineHint Set a CLOCK_MONOTONIC deadline hint in nanoseconds on the fence - void wait( - s64 timeout, - WaitMode waitMode = WaitMode::NoWaitEmpty, - std::optional<u64> deadlineHint = std::nullopt - ) const; - - /// Register an eventfd to the sync object - /// @param waitAvailable Trigger when a fence is emplaced, not when it is signaled - void registerEventFd(int eventfd_fd, bool waitAvailable = false) const; - // Private access GETTER(fd) GETTER(handle) // Move constructor/operator - SyncObject(SyncObject&& other) noexcept : m_fd(other.m_fd), m_handle(other.m_handle) { + SyncObjectBase(SyncObjectBase&& other) noexcept : m_fd(other.m_fd), m_handle(other.m_handle) { other.m_fd = -1; // invalidate other } - SyncObject& operator=(SyncObject&& other) noexcept { + SyncObjectBase& operator=(SyncObjectBase&& other) noexcept { if (this != &other) { this->destruct(); this->m_handle = other.m_handle; @@ -84,20 +48,23 @@ public: } // Copy constructor/operator - SyncObject(const SyncObject& other) - : SyncObject(other.m_fd, other.exportFd(), true) {} + SyncObjectBase(const SyncObjectBase& other) + : SyncObjectBase(other.m_fd, other.exportFd(), true) {} - SyncObject& operator=(const SyncObject& other) { + SyncObjectBase& operator=(const SyncObjectBase& other) { if (this != &other) { const int fd{other.exportFd()}; - *this = SyncObject(other.m_fd, fd, true); + *this = SyncObjectBase(other.m_fd, fd, true); } return *this; } // Destructor - ~SyncObject(); + ~SyncObjectBase() noexcept { + this->destruct(); + } + private: int m_fd; // indicates object validity (>= 0) u32 m_handle; @@ -105,37 +72,78 @@ private: void destruct() noexcept; }; -/// A timeline synchronization object can hold multiple DRM fences, identified via a -/// monotonically increasing 64-bit unsigned integer "point" +/// Wait modes for waiting on binary sync objects. +enum class WaitMode : u8 { + NoWaitEmpty, //!< Return -EINVAL when waiting on an empty sync object + WaitEmpty, //!< Wait for empty sync objects to be filled and signaled + WaitAvailable //!< Wait for empty sync objects to be filled, but do not wait for signaling +}; + +/// A (binary) synchronization object is a reference-counted container which can hold a DRM fence. +/// Requires DRM_CAP_SYNCOBJ. /// @throws drm::ioctl::Exception on failure -class TimelineSyncObject { +class SyncObject : public SyncObjectBase { public: - /// Create a new sync object - TimelineSyncObject(int fd); + using SyncObjectBase::SyncObjectBase; + using SyncObjectBase::operator=; - /// Import an existing sync object - /// @param close Close syncobj_fd after import (regardless of success) - TimelineSyncObject(int fd, int syncobj_fd, bool close = true); + /// Import a sync file (DRM fence) into the sync object. + /// @param close Close syncfile_fd after import (regardless of success) + void importSyncFile(int syncfile_fd, bool close = true) const; - /// Export a new reference to sync object, increasing the reference counter - [[nodiscard]] int exportFd() const; + /// Export a sync file from the DRM fence within the sync object. + /// Any subsequent modifications to the sync object are not applied to the exported sync file + [[nodiscard]] int exportSyncFile() const; + + /// Transfer a DRM fence into another binary sync object. + void transfer(const SyncObject& dest) const; + void transfer(const TimelineSyncObject& dest, u64 destPoint) const; + + /// Signal the sync object by emplacing a signaled fence into it. + void signal() const; + + /// Reset the sync object by removing the fence from it. + void reset() const; + + /// Wait for the sync object to be signaled. + /// @param timeout Absolute timeout in nanoseconds, or zero for polling + /// @param deadlineHint Set a CLOCK_MONOTONIC deadline hint in nanoseconds on the fence + void wait( + s64 timeout, + WaitMode waitMode = WaitMode::NoWaitEmpty, + std::optional<u64> deadlineHint = std::nullopt + ) const; + + /// Register an eventfd to the sync object. + /// @param waitAvailable Trigger when a fence is emplaced, not when it is signaled + void registerEventFd(int eventfd_fd, bool waitAvailable = false) const; +}; - /// Import a sync file (DRM fence) into the sync object +/// A timeline synchronization object can hold multiple DRM fences, identified via a +/// monotonically increasing 64-bit unsigned integer "point". +/// Requires DRM_CAP_SYNCOBJ_TIMELINE. +/// @throws drm::ioctl::Exception on failure +class TimelineSyncObject : public SyncObjectBase { +public: + using SyncObjectBase::SyncObjectBase; + using SyncObjectBase::operator=; + + /// Import a sync file (DRM fence) into the sync object. /// @param close Close syncfile_fd after import (regardless of success) void importSyncFile(int syncfile_fd, u64 point, bool close = true) const; - /// Export a sync file from the DRM fence within the sync object - /// Any subsequent modifications to the sync object are not applied to the exported sync file + /// Export a sync file from the DRM fence within the sync object. + /// Any subsequent modifications to the sync object are not applied to the exported sync file. [[nodiscard]] int exportSyncFile(u64 point) const; - /// Transfer a DRM fence into another sync object + /// Transfer a DRM fence into another sync object. void transfer(const TimelineSyncObject& dest, u64 srcPoint, u64 destPoint) const; void transfer(const SyncObject& dest, u64 srcPoint) const; - /// Signal the sync object by emplacing a signaled fence into it + /// Signal the sync object by emplacing a signaled fence into it. void signal(u64 point) const; - /// Wait for the sync object to be signaled + /// Wait for the sync object to be signaled. /// @param timeout Absolute timeout in nanoseconds, or zero for polling /// @param waitAvailable Only wait for a fence to become available, do not wait for signaling /// @param deadlineHint Set a CLOCK_MONOTONIC deadline hint in nanoseconds on the fence @@ -146,91 +154,49 @@ public: std::optional<u64> deadlineHint = std::nullopt ) const; - /// Query the current timeline point + /// Query the current timeline point. /// @param lastSubmitted If true, query the last submitted point instead [[nodiscard]] u64 query(bool lastSubmitted = false) const; - /// Register an eventfd to the sync object + /// Register an eventfd to the sync object. /// @param waitAvailable Trigger when a fence is emplaced, not when it is signaled void registerEventFd(int eventfd_fd, u64 point, bool waitAvailable = false) const; - - // Private access - GETTER(fd) - GETTER(handle) - - // Move constructor/operator - TimelineSyncObject(TimelineSyncObject&& other) noexcept - : m_fd(other.m_fd), m_handle(other.m_handle) { - other.m_fd = -1; // invalidate other - } - - TimelineSyncObject& operator=(TimelineSyncObject&& other) noexcept { - if (this != &other) { - this->destruct(); - this->m_handle = other.m_handle; - this->m_fd = other.m_fd; - other.m_fd = -1; // invalidate other - } - - return *this; - } - - // Copy constructor/operator - TimelineSyncObject(const TimelineSyncObject& other) - : TimelineSyncObject(other.m_fd, other.exportFd(), true) {} - - TimelineSyncObject& operator=(const TimelineSyncObject& other) { - if (this != &other) { - const int fd{other.exportFd()}; - *this = TimelineSyncObject(other.m_fd, fd, true); - } - - return *this; - } - - // Destructor - ~TimelineSyncObject(); -private: - int m_fd; // indicates object validity (>= 0) - u32 m_handle; - - void destruct() noexcept; }; -/// Signal several binary sync objects at once -void signal(const std::vector<ref<SyncObject>>& objs); +/// Signal several binary sync objects at once. +void signal(const std::vector<ref<const SyncObject>>& objs); -/// Reset several binary sync objects at once -void reset(const std::vector<ref<SyncObject>>& objs); +/// Reset several binary sync objects at once. +void reset(const std::vector<ref<const SyncObject>>& objs); -// Wait on several binary sync objects at once +/// Wait on several binary sync objects at once. /// @param timeout Absolute timeout in nanoseconds, or zero for polling /// @param waitAll Wait until all sync objects are signaled /// @param deadlineHint Set a CLOCK_MONOTONIC deadline hint in nanoseconds on the fence /// @return The first signaled sync object when waitAll is false /// @throws std::invalid_argument if objs is empty -SyncObject& wait( - const std::vector<ref<SyncObject>>& objs, +const SyncObject& wait( + const std::vector<ref<const SyncObject>>& objs, s64 timeout, bool waitAll = false, WaitMode waitMode = WaitMode::NoWaitEmpty, std::optional<u64> deadlineHint = std::nullopt ); -/// Signal several timeline sync objects at once +/// Signal several timeline sync objects at once. /// @throws std::invalid_argument if objs.size() != points.size() void signal( - const std::vector<ref<TimelineSyncObject>>& objs, - const std::vector<u64>& points + const std::vector<ref<const TimelineSyncObject>>& objs, + std::vector<u64> points ); -/// Wait on several timeline sync objects at once +/// Wait on several timeline sync objects at once. /// @param timeout Absolute timeout in nanoseconds, or zero for polling /// @param waitAvailable Only wait for a fence to become available, do not wait for signaling /// @param deadlineHint Set a CLOCK_MONOTONIC deadline hint in nanoseconds on the fence /// @throws std::invalid_argument if objs.size() != points.size() void wait( - const std::vector<ref<TimelineSyncObject>>& objs, + const std::vector<ref<const TimelineSyncObject>>& objs, const std::vector<u64>& points, s64 timeout, bool waitAll = false, @@ -238,10 +204,10 @@ void wait( std::optional<u64> deadlineHint = std::nullopt ); -/// Query several timeline sync objects at once +/// Query several timeline sync objects at once. /// @param lastSubmitted If true, query the last submitted point instead std::vector<u64> query( - const std::vector<ref<TimelineSyncObject>>& objs, + const std::vector<ref<const TimelineSyncObject>>& objs, bool lastSubmitted = false ); |
