drm_ffi/
syncobj.rs

1//!
2//! Bindings for DRM sync objects
3//!
4
5use crate::ioctl;
6use drm_sys::*;
7
8use std::{
9    io,
10    os::unix::io::{AsRawFd, BorrowedFd},
11};
12
13/// Creates a syncobj.
14pub 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.
32pub 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.
43pub 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.
67pub 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.
91pub 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.
124pub 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.
139pub 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.
154pub 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.
196pub 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.
223pub 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.
247pub 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.
269pub 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}