1
0
Fork 0
forked from wry/wry

gfx-api: add support for syncobj synchronization

This commit is contained in:
Julian Orth 2026-03-01 20:29:53 +01:00
parent 80a69ba7ef
commit 7e6facf4e3
20 changed files with 323 additions and 159 deletions

View file

@ -139,6 +139,8 @@ pub enum DrmError {
Merge(#[source] OsError),
#[error("Could not import a sync file into a syncobj")]
ImportSyncFile(#[source] OsError),
#[error("Could not export a sync file")]
ExportSyncFile(#[source] OsError),
#[error("Could not create a lease")]
CreateLease(#[source] OsError),
#[error("Could not drop DRM master")]

View file

@ -15,7 +15,8 @@ use {
DRM_SYNCOBJ_CREATE_SIGNALED, DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, sync_ioc_merge, syncobj_create,
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE,
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, sync_ioc_merge, syncobj_create,
syncobj_destroy, syncobj_eventfd, syncobj_fd_to_handle, syncobj_handle_to_fd,
syncobj_signal, syncobj_transfer,
},
@ -61,6 +62,10 @@ impl Syncobj {
pub fn fd(&self) -> &Rc<OwnedFd> {
&self.fd
}
pub fn id(&self) -> SyncobjId {
self.id
}
}
impl Drop for Syncobj {
@ -118,7 +123,7 @@ impl SyncobjCtx {
pub fn create_syncobj(&self) -> Result<Syncobj, DrmError> {
let handle = syncobj_create(self.inner.drm.raw(), 0).map_err(DrmError::CreateSyncobj)?;
let handle = SyncobjHandle(handle);
let fd = syncobj_handle_to_fd(self.inner.drm.raw(), handle.0, 0);
let fd = syncobj_handle_to_fd(self.inner.drm.raw(), handle.0, 0, 0);
if fd.is_err() {
destroy(&self.inner.drm, handle);
}
@ -138,6 +143,7 @@ impl SyncobjCtx {
self.inner.drm.raw(),
handle.0,
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
0,
);
destroy(&self.inner.drm, handle);
fd.map_err(DrmError::ExportSyncobj)
@ -250,7 +256,46 @@ impl SyncobjCtx {
}
let dummy = self.get_dummy()?;
import(0, self.get_handle(&dummy)?)?;
self.transfer(&dummy, SyncobjPoint(0), syncobj, point)
self.transfer(&dummy, SyncobjPoint(0), syncobj, point, 0)
}
pub fn export_sync_file_blocking(
&self,
syncobj: &Syncobj,
point: SyncobjPoint,
) -> Result<SyncFile, DrmError> {
let export = |flags: u32, handle: SyncobjHandle, point: SyncobjPoint| {
syncobj_handle_to_fd(
self.inner.drm.raw(),
handle.0,
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE | flags,
point.0,
)
.map(Rc::new)
.map(SyncFile)
};
if self.supports_timeline_import() {
let res = export(
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE,
self.get_handle(syncobj)?,
point,
);
match res {
Ok(sf) => return Ok(sf),
Err(e) if e.0 == c::EINVAL => {}
Err(e) => return Err(DrmError::ExportSyncFile(e)),
}
}
let dummy = self.get_dummy()?;
let zero = SyncobjPoint(0);
self.transfer(
syncobj,
point,
&dummy,
zero,
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
)?;
export(0, self.get_handle(&dummy)?, zero).map_err(DrmError::ExportSyncFile)
}
fn transfer(
@ -259,6 +304,7 @@ impl SyncobjCtx {
src_point: SyncobjPoint,
dst_syncobj: &Syncobj,
dst_point: SyncobjPoint,
flags: u32,
) -> Result<(), DrmError> {
let src_handle = self.get_handle(src_syncobj)?;
let dst_handle = self.get_handle(dst_syncobj)?;
@ -268,7 +314,7 @@ impl SyncobjCtx {
src_point.0,
dst_handle.0,
dst_point.0,
0,
flags,
)
.map_err(DrmError::TransferPoint)
}

View file

@ -1223,6 +1223,7 @@ pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE: u32 = 1 << 0;
pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE: u32 = 1 << 1;
pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1 << 0;
pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE: u32 = 1 << 1;
#[repr(C)]
struct drm_syncobj_handle {
@ -1236,13 +1237,18 @@ struct drm_syncobj_handle {
const DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD: u64 = drm_iowr::<drm_syncobj_handle>(0xC1);
const DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE: u64 = drm_iowr::<drm_syncobj_handle>(0xC2);
pub fn syncobj_handle_to_fd(drm: c::c_int, handle: u32, flags: u32) -> Result<OwnedFd, OsError> {
pub fn syncobj_handle_to_fd(
drm: c::c_int,
handle: u32,
flags: u32,
point: u64,
) -> Result<OwnedFd, OsError> {
let mut res = drm_syncobj_handle {
handle,
flags,
fd: 0,
pad: 0,
point: 0,
point,
};
unsafe {
ioctl(drm, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &mut res)?;
@ -1271,7 +1277,7 @@ pub fn syncobj_fd_to_handle(
}
// pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL: u32 = 1 << 0;
// pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT: u32 = 1 << 1;
pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT: u32 = 1 << 1;
pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE: u32 = 1 << 2;
#[repr(C)]