1
0
Fork 0
forked from wry/wry

Merge pull request #766 from mahkoh/jorth/syncobj-direct-import

sync-obj: use DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE
This commit is contained in:
mahkoh 2026-03-01 13:40:36 +01:00 committed by GitHub
commit 949ff558fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 84 additions and 15 deletions

View file

@ -13,6 +13,7 @@ use {
DrmError, DrmError,
sys::{ sys::{
DRM_SYNCOBJ_CREATE_SIGNALED, DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, 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_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, sync_ioc_merge, sync_obj_create, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, sync_ioc_merge, sync_obj_create,
sync_obj_destroy, sync_obj_eventfd, sync_obj_fd_to_handle, sync_obj_handle_to_fd, sync_obj_destroy, sync_obj_eventfd, sync_obj_fd_to_handle, sync_obj_handle_to_fd,
@ -21,6 +22,7 @@ use {
}, },
}, },
std::{ std::{
cell::OnceCell,
rc::Rc, rc::Rc,
sync::atomic::{AtomicU64, Ordering::Relaxed}, sync::atomic::{AtomicU64, Ordering::Relaxed},
}, },
@ -84,6 +86,7 @@ struct Handles {
pub struct SyncObjCtx { pub struct SyncObjCtx {
inner: Rc<Handles>, inner: Rc<Handles>,
dummy: CloneCell<Option<Rc<SyncObj>>>, dummy: CloneCell<Option<Rc<SyncObj>>>,
supports_timeline_import: OnceCell<bool>,
} }
impl SyncObjCtx { impl SyncObjCtx {
@ -95,6 +98,7 @@ impl SyncObjCtx {
links: Default::default(), links: Default::default(),
}), }),
dummy: Default::default(), dummy: Default::default(),
supports_timeline_import: Default::default(),
} }
} }
@ -102,7 +106,7 @@ impl SyncObjCtx {
if let Some(handle) = self.inner.handles.get(&sync_obj.id) { if let Some(handle) = self.inner.handles.get(&sync_obj.id) {
return Ok(handle); return Ok(handle);
} }
let handle = sync_obj_fd_to_handle(self.inner.drm.raw(), sync_obj.fd.raw(), 0, 0) let handle = sync_obj_fd_to_handle(self.inner.drm.raw(), sync_obj.fd.raw(), 0, 0, 0)
.map_err(DrmError::ImportSyncObj)?; .map_err(DrmError::ImportSyncObj)?;
let handle = SyncObjHandle(handle); let handle = SyncObjHandle(handle);
let link = sync_obj.importers.add_last(self.inner.clone()); let link = sync_obj.importers.add_last(self.inner.clone());
@ -176,6 +180,40 @@ impl SyncObjCtx {
Ok(()) Ok(())
} }
fn supports_timeline_import(&self) -> bool {
*self
.supports_timeline_import
.get_or_init(|| match self.test_timeline_import() {
Ok(_) => {
log::info!("Kernel supports sync file timeline import");
true
}
Err(e) => {
log::warn!(
"Kernel does not support sync file timeline import: {}",
ErrorFmt(e),
);
false
}
})
}
fn test_timeline_import(&self) -> Result<(), DrmError> {
let sync_obj = self.create_sync_obj()?;
let sync_obj = self.get_handle(&sync_obj)?;
let sync_file = self.create_signaled_sync_file()?;
sync_obj_fd_to_handle(
self.inner.drm.raw(),
sync_file.raw(),
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE
| DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
sync_obj.0,
123,
)
.map(drop)
.map_err(DrmError::ImportSyncFile)
}
pub fn signal(&self, sync_obj: &SyncObj, point: SyncObjPoint) -> Result<(), DrmError> { pub fn signal(&self, sync_obj: &SyncObj, point: SyncObjPoint) -> Result<(), DrmError> {
let handle = self.get_handle(sync_obj)?; let handle = self.get_handle(sync_obj)?;
sync_obj_signal(self.inner.drm.raw(), handle.0, point.0).map_err(DrmError::SignalSyncObj) sync_obj_signal(self.inner.drm.raw(), handle.0, point.0).map_err(DrmError::SignalSyncObj)
@ -190,24 +228,28 @@ impl SyncObjCtx {
where where
I: IntoIterator<Item = &'a SyncFile>, I: IntoIterator<Item = &'a SyncFile>,
{ {
let mut sync_files = sync_files.into_iter(); let Some(fd) = merge_sync_files(sync_files)? else {
let Some(first) = sync_files.next() else {
return self.signal(sync_obj, point); return self.signal(sync_obj, point);
}; };
let mut stash; let import = |flags: u32, handle: SyncObjHandle| {
let mut fd = &*first.0; sync_obj_fd_to_handle(
for next in sync_files { self.inner.drm.raw(),
stash = sync_ioc_merge(fd.raw(), next.raw()).map_err(DrmError::Merge)?; fd.raw(),
fd = &stash; DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE | flags,
handle.0,
point.0,
)
.map(drop)
.map_err(DrmError::ImportSyncFile)
};
if self.supports_timeline_import() {
return import(
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
self.get_handle(sync_obj)?,
);
} }
let dummy = self.get_dummy()?; let dummy = self.get_dummy()?;
sync_obj_fd_to_handle( import(0, self.get_handle(&dummy)?)?;
self.inner.drm.raw(),
fd.raw(),
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
self.get_handle(&dummy)?.0,
)
.map_err(DrmError::ImportSyncFile)?;
self.transfer(&dummy, SyncObjPoint(0), sync_obj, point) self.transfer(&dummy, SyncObjPoint(0), sync_obj, point)
} }
@ -258,3 +300,24 @@ fn destroy(drm: &OwnedFd, handle: SyncObjHandle) {
log::error!("Could not destroy sync obj: {}", ErrorFmt(e)); log::error!("Could not destroy sync obj: {}", ErrorFmt(e));
} }
} }
fn merge_sync_files<'a, I>(sync_files: I) -> Result<Option<SyncFile>, DrmError>
where
I: IntoIterator<Item = &'a SyncFile>,
{
let mut sync_files = sync_files.into_iter();
let Some(first) = sync_files.next() else {
return Ok(None);
};
let Some(second) = sync_files.next() else {
return Ok(Some(first.clone()));
};
let merge = |left: &OwnedFd, right: &OwnedFd| {
sync_ioc_merge(left.raw(), right.raw()).map_err(DrmError::Merge)
};
let mut fd = merge(first, second)?;
for next in sync_files {
fd = merge(&fd, next)?;
}
Ok(Some(SyncFile(Rc::new(fd))))
}

View file

@ -1220,6 +1220,8 @@ pub fn sync_obj_destroy(drm: c::c_int, handle: u32) -> Result<(), OsError> {
} }
pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE: u32 = 1 << 0; 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_EXPORT_SYNC_FILE: u32 = 1 << 0;
#[repr(C)] #[repr(C)]
@ -1228,6 +1230,7 @@ struct drm_syncobj_handle {
flags: u32, flags: u32,
fd: i32, fd: i32,
pad: u32, pad: u32,
point: u64,
} }
const DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD: u64 = drm_iowr::<drm_syncobj_handle>(0xC1); const DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD: u64 = drm_iowr::<drm_syncobj_handle>(0xC1);
@ -1239,6 +1242,7 @@ pub fn sync_obj_handle_to_fd(drm: c::c_int, handle: u32, flags: u32) -> Result<O
flags, flags,
fd: 0, fd: 0,
pad: 0, pad: 0,
point: 0,
}; };
unsafe { unsafe {
ioctl(drm, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &mut res)?; ioctl(drm, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &mut res)?;
@ -1251,12 +1255,14 @@ pub fn sync_obj_fd_to_handle(
fd: c::c_int, fd: c::c_int,
flags: u32, flags: u32,
handle: u32, handle: u32,
point: u64,
) -> Result<u32, OsError> { ) -> Result<u32, OsError> {
let mut res = drm_syncobj_handle { let mut res = drm_syncobj_handle {
handle, handle,
flags, flags,
fd, fd,
pad: 0, pad: 0,
point,
}; };
unsafe { unsafe {
ioctl(drm, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &mut res)?; ioctl(drm, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &mut res)?;