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,
2122 } ,
2223 } ,
2324 std:: {
25+ cell:: OnceCell ,
2426 rc:: Rc ,
2527 sync:: atomic:: { AtomicU64 , Ordering :: Relaxed } ,
2628 } ,
@@ -84,6 +86,7 @@ struct Handles {
8486pub struct SyncObjCtx {
8587 inner : Rc < Handles > ,
8688 dummy : CloneCell < Option < Rc < SyncObj > > > ,
89+ supports_timeline_import : OnceCell < bool > ,
8790}
8891
8992impl 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+ }
0 commit comments