1 /// Check the `util` module to see how the `Card` structure is implemented.
2 pub mod utils;
3 
4 use crate::utils::*;
5 use rustix::event::PollFlags;
6 use std::{
7     io,
8     os::unix::io::{AsFd, OwnedFd},
9 };
10 
11 impl Card {
simulate_command_submission(&self) -> io::Result<OwnedFd>12     fn simulate_command_submission(&self) -> io::Result<OwnedFd> {
13         // Create a temporary syncobj to receive the command fence.
14         let syncobj = self.create_syncobj(false)?;
15 
16         let sync_file = {
17             // Fake a command submission by signalling the syncobj immediately. The kernel
18             // attaches a null fence object which is always signalled. Other than this, there
19             // isn't a good way to create and signal a fence object from user-mode, so an actual
20             // device is required to test this properly.
21             //
22             // For a real device, the syncobj handle should be passed to a command submission
23             // which is expected to set a fence to be signalled upon completion.
24             self.syncobj_signal(&[syncobj])?;
25 
26             // Export fence set by previous ioctl to file descriptor.
27             self.syncobj_to_fd(syncobj, true)
28         };
29 
30         // The sync file descriptor constitutes ownership of the fence, so the syncobj can be
31         // safely destroyed.
32         self.destroy_syncobj(syncobj)?;
33 
34         sync_file
35     }
36 }
37 
main()38 fn main() {
39     let card = Card::open_global();
40     let sync_file = card.simulate_command_submission().unwrap();
41     let fd = sync_file.as_fd();
42 
43     // Poll for readability. The DRM fence object will directly wake the thread when signalled.
44     //
45     // Alternatively, Tokio's AsyncFd may be used like so:
46     //
47     // use tokio::io::{Interest, unix::AsyncFd};
48     // let afd = AsyncFd::with_interest(sync_file, Interest::READABLE).unwrap();
49     // let future = async move { afd.readable().await.unwrap().retain_ready() };
50     // future.await;
51     let mut poll_fds = [rustix::event::PollFd::new(&fd, PollFlags::IN)];
52     rustix::event::poll(&mut poll_fds, -1).unwrap();
53 }
54