Skip to content

Commit 949ff55

Browse files
authored
Merge pull request #766 from mahkoh/jorth/syncobj-direct-import
sync-obj: use DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE
2 parents 29f3aaa + 660dc28 commit 949ff55

File tree

2 files changed

+84
-15
lines changed

2 files changed

+84
-15
lines changed

src/video/drm/sync_obj.rs

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use {
1313
DrmError,
1414
sys::{
1515
DRM_SYNCOBJ_CREATE_SIGNALED, DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
16+
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
1617
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
1718
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, sync_ioc_merge, sync_obj_create,
1819
sync_obj_destroy, sync_obj_eventfd, sync_obj_fd_to_handle, sync_obj_handle_to_fd,
@@ -21,6 +22,7 @@ use {
2122
},
2223
},
2324
std::{
25+
cell::OnceCell,
2426
rc::Rc,
2527
sync::atomic::{AtomicU64, Ordering::Relaxed},
2628
},
@@ -84,6 +86,7 @@ struct Handles {
8486
pub struct SyncObjCtx {
8587
inner: Rc<Handles>,
8688
dummy: CloneCell<Option<Rc<SyncObj>>>,
89+
supports_timeline_import: OnceCell<bool>,
8790
}
8891

8992
impl SyncObjCtx {
@@ -95,14 +98,15 @@ impl SyncObjCtx {
9598
links: Default::default(),
9699
}),
97100
dummy: Default::default(),
101+
supports_timeline_import: Default::default(),
98102
}
99103
}
100104

101105
fn get_handle(&self, sync_obj: &SyncObj) -> Result<SyncObjHandle, DrmError> {
102106
if let Some(handle) = self.inner.handles.get(&sync_obj.id) {
103107
return Ok(handle);
104108
}
105-
let handle = sync_obj_fd_to_handle(self.inner.drm.raw(), sync_obj.fd.raw(), 0, 0)
109+
let handle = sync_obj_fd_to_handle(self.inner.drm.raw(), sync_obj.fd.raw(), 0, 0, 0)
106110
.map_err(DrmError::ImportSyncObj)?;
107111
let handle = SyncObjHandle(handle);
108112
let link = sync_obj.importers.add_last(self.inner.clone());
@@ -176,6 +180,40 @@ impl SyncObjCtx {
176180
Ok(())
177181
}
178182

183+
fn supports_timeline_import(&self) -> bool {
184+
*self
185+
.supports_timeline_import
186+
.get_or_init(|| match self.test_timeline_import() {
187+
Ok(_) => {
188+
log::info!("Kernel supports sync file timeline import");
189+
true
190+
}
191+
Err(e) => {
192+
log::warn!(
193+
"Kernel does not support sync file timeline import: {}",
194+
ErrorFmt(e),
195+
);
196+
false
197+
}
198+
})
199+
}
200+
201+
fn test_timeline_import(&self) -> Result<(), DrmError> {
202+
let sync_obj = self.create_sync_obj()?;
203+
let sync_obj = self.get_handle(&sync_obj)?;
204+
let sync_file = self.create_signaled_sync_file()?;
205+
sync_obj_fd_to_handle(
206+
self.inner.drm.raw(),
207+
sync_file.raw(),
208+
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE
209+
| DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
210+
sync_obj.0,
211+
123,
212+
)
213+
.map(drop)
214+
.map_err(DrmError::ImportSyncFile)
215+
}
216+
179217
pub fn signal(&self, sync_obj: &SyncObj, point: SyncObjPoint) -> Result<(), DrmError> {
180218
let handle = self.get_handle(sync_obj)?;
181219
sync_obj_signal(self.inner.drm.raw(), handle.0, point.0).map_err(DrmError::SignalSyncObj)
@@ -190,24 +228,28 @@ impl SyncObjCtx {
190228
where
191229
I: IntoIterator<Item = &'a SyncFile>,
192230
{
193-
let mut sync_files = sync_files.into_iter();
194-
let Some(first) = sync_files.next() else {
231+
let Some(fd) = merge_sync_files(sync_files)? else {
195232
return self.signal(sync_obj, point);
196233
};
197-
let mut stash;
198-
let mut fd = &*first.0;
199-
for next in sync_files {
200-
stash = sync_ioc_merge(fd.raw(), next.raw()).map_err(DrmError::Merge)?;
201-
fd = &stash;
234+
let import = |flags: u32, handle: SyncObjHandle| {
235+
sync_obj_fd_to_handle(
236+
self.inner.drm.raw(),
237+
fd.raw(),
238+
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE | flags,
239+
handle.0,
240+
point.0,
241+
)
242+
.map(drop)
243+
.map_err(DrmError::ImportSyncFile)
244+
};
245+
if self.supports_timeline_import() {
246+
return import(
247+
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
248+
self.get_handle(sync_obj)?,
249+
);
202250
}
203251
let dummy = self.get_dummy()?;
204-
sync_obj_fd_to_handle(
205-
self.inner.drm.raw(),
206-
fd.raw(),
207-
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
208-
self.get_handle(&dummy)?.0,
209-
)
210-
.map_err(DrmError::ImportSyncFile)?;
252+
import(0, self.get_handle(&dummy)?)?;
211253
self.transfer(&dummy, SyncObjPoint(0), sync_obj, point)
212254
}
213255

@@ -258,3 +300,24 @@ fn destroy(drm: &OwnedFd, handle: SyncObjHandle) {
258300
log::error!("Could not destroy sync obj: {}", ErrorFmt(e));
259301
}
260302
}
303+
304+
fn merge_sync_files<'a, I>(sync_files: I) -> Result<Option<SyncFile>, DrmError>
305+
where
306+
I: IntoIterator<Item = &'a SyncFile>,
307+
{
308+
let mut sync_files = sync_files.into_iter();
309+
let Some(first) = sync_files.next() else {
310+
return Ok(None);
311+
};
312+
let Some(second) = sync_files.next() else {
313+
return Ok(Some(first.clone()));
314+
};
315+
let merge = |left: &OwnedFd, right: &OwnedFd| {
316+
sync_ioc_merge(left.raw(), right.raw()).map_err(DrmError::Merge)
317+
};
318+
let mut fd = merge(first, second)?;
319+
for next in sync_files {
320+
fd = merge(&fd, next)?;
321+
}
322+
Ok(Some(SyncFile(Rc::new(fd))))
323+
}

src/video/drm/sys.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,8 @@ pub fn sync_obj_destroy(drm: c::c_int, handle: u32) -> Result<(), OsError> {
12201220
}
12211221

12221222
pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE: u32 = 1 << 0;
1223+
pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE: u32 = 1 << 1;
1224+
12231225
pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1 << 0;
12241226

12251227
#[repr(C)]
@@ -1228,6 +1230,7 @@ struct drm_syncobj_handle {
12281230
flags: u32,
12291231
fd: i32,
12301232
pad: u32,
1233+
point: u64,
12311234
}
12321235

12331236
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
12391242
flags,
12401243
fd: 0,
12411244
pad: 0,
1245+
point: 0,
12421246
};
12431247
unsafe {
12441248
ioctl(drm, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &mut res)?;
@@ -1251,12 +1255,14 @@ pub fn sync_obj_fd_to_handle(
12511255
fd: c::c_int,
12521256
flags: u32,
12531257
handle: u32,
1258+
point: u64,
12541259
) -> Result<u32, OsError> {
12551260
let mut res = drm_syncobj_handle {
12561261
handle,
12571262
flags,
12581263
fd,
12591264
pad: 0,
1265+
point,
12601266
};
12611267
unsafe {
12621268
ioctl(drm, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &mut res)?;

0 commit comments

Comments
 (0)