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:
commit
949ff558fd
2 changed files with 84 additions and 15 deletions
|
|
@ -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))))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue