1 //!
2 //! Bindings for DRM sync objects
3 //!
4 
5 use crate::ioctl;
6 use drm_sys::*;
7 
8 use std::{
9     io,
10     os::unix::io::{AsRawFd, BorrowedFd},
11 };
12 
13 /// Creates a syncobj.
create(fd: BorrowedFd<'_>, signaled: bool) -> io::Result<drm_syncobj_create>14 pub fn create(fd: BorrowedFd<'_>, signaled: bool) -> io::Result<drm_syncobj_create> {
15     let mut args = drm_syncobj_create {
16         handle: 0,
17         flags: if signaled {
18             DRM_SYNCOBJ_CREATE_SIGNALED
19         } else {
20             0
21         },
22     };
23 
24     unsafe {
25         ioctl::syncobj::create(fd, &mut args)?;
26     }
27 
28     Ok(args)
29 }
30 
31 /// Destroys a syncobj.
destroy(fd: BorrowedFd<'_>, handle: u32) -> io::Result<drm_syncobj_destroy>32 pub fn destroy(fd: BorrowedFd<'_>, handle: u32) -> io::Result<drm_syncobj_destroy> {
33     let mut args = drm_syncobj_destroy { handle, pad: 0 };
34 
35     unsafe {
36         ioctl::syncobj::destroy(fd, &mut args)?;
37     }
38 
39     Ok(args)
40 }
41 
42 /// Exports a syncobj as an inter-process file descriptor or as a poll()-able sync file.
handle_to_fd( fd: BorrowedFd<'_>, handle: u32, export_sync_file: bool, ) -> io::Result<drm_syncobj_handle>43 pub fn handle_to_fd(
44     fd: BorrowedFd<'_>,
45     handle: u32,
46     export_sync_file: bool,
47 ) -> io::Result<drm_syncobj_handle> {
48     let mut args = drm_syncobj_handle {
49         handle,
50         flags: if export_sync_file {
51             DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE
52         } else {
53             0
54         },
55         fd: 0,
56         pad: 0,
57     };
58 
59     unsafe {
60         ioctl::syncobj::handle_to_fd(fd, &mut args)?;
61     }
62 
63     Ok(args)
64 }
65 
66 /// Imports a file descriptor exported by [`handle_to_fd`] back into a process-local handle.
fd_to_handle( fd: BorrowedFd<'_>, syncobj_fd: BorrowedFd<'_>, import_sync_file: bool, ) -> io::Result<drm_syncobj_handle>67 pub fn fd_to_handle(
68     fd: BorrowedFd<'_>,
69     syncobj_fd: BorrowedFd<'_>,
70     import_sync_file: bool,
71 ) -> io::Result<drm_syncobj_handle> {
72     let mut args = drm_syncobj_handle {
73         handle: 0,
74         flags: if import_sync_file {
75             DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE
76         } else {
77             0
78         },
79         fd: syncobj_fd.as_raw_fd(),
80         pad: 0,
81     };
82 
83     unsafe {
84         ioctl::syncobj::fd_to_handle(fd, &mut args)?;
85     }
86 
87     Ok(args)
88 }
89 
90 /// Waits for one or more syncobjs to become signalled.
wait( fd: BorrowedFd<'_>, handles: &[u32], timeout_nsec: i64, wait_all: bool, wait_for_submit: bool, ) -> io::Result<drm_syncobj_wait>91 pub fn wait(
92     fd: BorrowedFd<'_>,
93     handles: &[u32],
94     timeout_nsec: i64,
95     wait_all: bool,
96     wait_for_submit: bool,
97 ) -> io::Result<drm_syncobj_wait> {
98     let mut args = drm_syncobj_wait {
99         handles: handles.as_ptr() as _,
100         timeout_nsec,
101         count_handles: handles.len() as _,
102         flags: if wait_all {
103             DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL
104         } else {
105             0
106         } | if wait_for_submit {
107             DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT
108         } else {
109             0
110         },
111         first_signaled: 0,
112         pad: 0,
113         deadline_nsec: 0,
114     };
115 
116     unsafe {
117         ioctl::syncobj::wait(fd, &mut args)?;
118     }
119 
120     Ok(args)
121 }
122 
123 /// Resets (un-signals) one or more syncobjs.
reset(fd: BorrowedFd<'_>, handles: &[u32]) -> io::Result<drm_syncobj_array>124 pub fn reset(fd: BorrowedFd<'_>, handles: &[u32]) -> io::Result<drm_syncobj_array> {
125     let mut args = drm_syncobj_array {
126         handles: handles.as_ptr() as _,
127         count_handles: handles.len() as _,
128         pad: 0,
129     };
130 
131     unsafe {
132         ioctl::syncobj::reset(fd, &mut args)?;
133     }
134 
135     Ok(args)
136 }
137 
138 /// Signals one or more syncobjs.
signal(fd: BorrowedFd<'_>, handles: &[u32]) -> io::Result<drm_syncobj_array>139 pub fn signal(fd: BorrowedFd<'_>, handles: &[u32]) -> io::Result<drm_syncobj_array> {
140     let mut args = drm_syncobj_array {
141         handles: handles.as_ptr() as _,
142         count_handles: handles.len() as _,
143         pad: 0,
144     };
145 
146     unsafe {
147         ioctl::syncobj::signal(fd, &mut args)?;
148     }
149 
150     Ok(args)
151 }
152 
153 /// Waits for one or more specific timeline syncobj points.
timeline_wait( fd: BorrowedFd<'_>, handles: &[u32], points: &[u64], timeout_nsec: i64, wait_all: bool, wait_for_submit: bool, wait_available: bool, ) -> io::Result<drm_syncobj_timeline_wait>154 pub fn timeline_wait(
155     fd: BorrowedFd<'_>,
156     handles: &[u32],
157     points: &[u64],
158     timeout_nsec: i64,
159     wait_all: bool,
160     wait_for_submit: bool,
161     wait_available: bool,
162 ) -> io::Result<drm_syncobj_timeline_wait> {
163     debug_assert_eq!(handles.len(), points.len());
164 
165     let mut args = drm_syncobj_timeline_wait {
166         handles: handles.as_ptr() as _,
167         points: points.as_ptr() as _,
168         timeout_nsec,
169         count_handles: handles.len() as _,
170         flags: if wait_all {
171             DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL
172         } else {
173             0
174         } | if wait_for_submit {
175             DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT
176         } else {
177             0
178         } | if wait_available {
179             DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
180         } else {
181             0
182         },
183         first_signaled: 0,
184         pad: 0,
185         deadline_nsec: 0,
186     };
187 
188     unsafe {
189         ioctl::syncobj::timeline_wait(fd, &mut args)?;
190     }
191 
192     Ok(args)
193 }
194 
195 /// Queries for state of one or more timeline syncobjs.
query( fd: BorrowedFd<'_>, handles: &[u32], points: &mut [u64], last_submitted: bool, ) -> io::Result<drm_syncobj_timeline_array>196 pub fn query(
197     fd: BorrowedFd<'_>,
198     handles: &[u32],
199     points: &mut [u64],
200     last_submitted: bool,
201 ) -> io::Result<drm_syncobj_timeline_array> {
202     debug_assert_eq!(handles.len(), points.len());
203 
204     let mut args = drm_syncobj_timeline_array {
205         handles: handles.as_ptr() as _,
206         points: points.as_mut_ptr() as _,
207         count_handles: handles.len() as _,
208         flags: if last_submitted {
209             DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED
210         } else {
211             0
212         },
213     };
214 
215     unsafe {
216         ioctl::syncobj::query(fd, &mut args)?;
217     }
218 
219     Ok(args)
220 }
221 
222 /// Transfers one timeline syncobj point to another.
transfer( fd: BorrowedFd<'_>, src_handle: u32, dst_handle: u32, src_point: u64, dst_point: u64, ) -> io::Result<drm_syncobj_transfer>223 pub fn transfer(
224     fd: BorrowedFd<'_>,
225     src_handle: u32,
226     dst_handle: u32,
227     src_point: u64,
228     dst_point: u64,
229 ) -> io::Result<drm_syncobj_transfer> {
230     let mut args = drm_syncobj_transfer {
231         src_handle,
232         dst_handle,
233         src_point,
234         dst_point,
235         flags: 0,
236         pad: 0,
237     };
238 
239     unsafe {
240         ioctl::syncobj::transfer(fd, &mut args)?;
241     }
242 
243     Ok(args)
244 }
245 
246 /// Signals one or more specific timeline syncobj points.
timeline_signal( fd: BorrowedFd<'_>, handles: &[u32], points: &[u64], ) -> io::Result<drm_syncobj_timeline_array>247 pub fn timeline_signal(
248     fd: BorrowedFd<'_>,
249     handles: &[u32],
250     points: &[u64],
251 ) -> io::Result<drm_syncobj_timeline_array> {
252     debug_assert_eq!(handles.len(), points.len());
253 
254     let mut args = drm_syncobj_timeline_array {
255         handles: handles.as_ptr() as _,
256         points: points.as_ptr() as _,
257         count_handles: handles.len() as _,
258         flags: 0,
259     };
260 
261     unsafe {
262         ioctl::syncobj::timeline_signal(fd, &mut args)?;
263     }
264 
265     Ok(args)
266 }
267 
268 /// Register an eventfd to be signalled by a syncobj.
eventfd( fd: BorrowedFd<'_>, handle: u32, point: u64, eventfd: BorrowedFd<'_>, wait_available: bool, ) -> io::Result<drm_syncobj_eventfd>269 pub fn eventfd(
270     fd: BorrowedFd<'_>,
271     handle: u32,
272     point: u64,
273     eventfd: BorrowedFd<'_>,
274     wait_available: bool,
275 ) -> io::Result<drm_syncobj_eventfd> {
276     let flags = if wait_available {
277         DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
278     } else {
279         0
280     };
281     let mut args = drm_syncobj_eventfd {
282         handle,
283         point,
284         flags,
285         fd: eventfd.as_raw_fd(),
286         pad: 0,
287     };
288 
289     unsafe {
290         ioctl::syncobj::eventfd(fd, &mut args)?;
291     }
292 
293     Ok(args)
294 }
295