timeline_syncobj 0.2.0

bindings for the timeline variant of drm_syncobjs
Documentation
use std::{
    io::ErrorKind,
    os::fd::{AsFd, OwnedFd},
    sync::Arc,
};

use rustix::fs::{Mode, OFlags};

use crate::bindings::{DrmSyncobjHandleToFd, RawDrmSyncobjHandle, SyncobjHandleToFdFlags};

#[derive(Debug, Clone)]
pub struct DrmRenderNode {
    fd: Arc<OwnedFd>,
    pub(crate) direct_syncfile: bool,
}
impl DrmRenderNode {
    pub fn new(id: u64) -> rustix::io::Result<Self> {
        let path = format!("/dev/dri/renderD{}", id & 0xFF);
        let fd =
            rustix::fs::open(path, OFlags::RDWR | OFlags::CLOEXEC, Mode::empty()).map(Arc::new)?;
        let ret = unsafe {
            rustix::ioctl::ioctl(
                &fd,
                DrmSyncobjHandleToFd {
                    handle: RawDrmSyncobjHandle::NULL,
                    flags: SyncobjHandleToFdFlags::EXPORT_SYNC_FILE
                        | SyncobjHandleToFdFlags::TIMELINE,
                    fd: -1,
                    _padding: 0,
                    point: 1,
                },
            )
        };
        let direct_syncfile = match ret {
            Ok(_) => true,
            Err(err) if err.kind() == ErrorKind::NotFound => true,
            Err(err) if err.kind() == ErrorKind::InvalidInput => false,
            Err(_) => false,
        };
        Ok(Self {
            fd,
            direct_syncfile,
        })
    }
}
impl PartialEq for DrmRenderNode {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.fd, &other.fd)
    }
}
impl AsFd for DrmRenderNode {
    fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
        self.fd.as_fd()
    }
}