libcamera/
fence.rs

1use std::{
2    io,
3    mem::ManuallyDrop,
4    os::fd::{FromRawFd, IntoRawFd, OwnedFd},
5    ptr::NonNull,
6};
7
8use libcamera_sys::*;
9
10/// A wrapper around libcamera::Fence for synchronizing buffer access.
11pub struct Fence {
12    ptr: NonNull<libcamera_fence_t>,
13}
14
15impl Fence {
16    /// Create a Fence from an owned file descriptor.
17    ///
18    /// The fd is consumed; on failure it is closed.
19    pub fn from_fd(fd: OwnedFd) -> io::Result<Self> {
20        let raw = fd.into_raw_fd();
21        let ptr = unsafe { libcamera_fence_from_fd(raw) };
22        match NonNull::new(ptr) {
23            Some(ptr) => Ok(Self { ptr }),
24            None => {
25                unsafe { libc::close(raw) };
26                Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid fence fd"))
27            }
28        }
29    }
30
31    /// Duplicate the fence fd.
32    pub fn to_owned_fd(&self) -> io::Result<OwnedFd> {
33        let fd = unsafe { libcamera_fence_fd(self.ptr.as_ptr()) };
34        if fd < 0 {
35            Err(io::Error::last_os_error())
36        } else {
37            Ok(unsafe { OwnedFd::from_raw_fd(fd) })
38        }
39    }
40
41    /// Consume the fence and return a duplicated fd.
42    pub fn into_owned_fd(self) -> io::Result<OwnedFd> {
43        let fd = self.to_owned_fd();
44        // Manually drop to avoid double-destroy after forgetting self.
45        let ptr = self.ptr;
46        let _ = ManuallyDrop::new(self);
47        unsafe {
48            libcamera_fence_destroy(ptr.as_ptr());
49        }
50        fd
51    }
52
53    pub(crate) fn into_raw(self) -> *mut libcamera_fence_t {
54        let ptr = self.ptr.as_ptr();
55        std::mem::forget(self);
56        ptr
57    }
58
59    pub(crate) unsafe fn from_ptr(ptr: *mut libcamera_fence_t) -> Option<Self> {
60        NonNull::new(ptr).map(|ptr| Self { ptr })
61    }
62}
63
64impl Drop for Fence {
65    fn drop(&mut self) {
66        unsafe { libcamera_fence_destroy(self.ptr.as_ptr()) }
67    }
68}
69
70unsafe impl Send for Fence {}