<NME> dmabuf.rs
<BEF> //! Module for [dmabuf](https://01.org/linuxgraphics/gfx-docs/drm/driver-api/dma-buf.html) buffers.
//!
//! `Dmabuf`s act alike to smart pointers and can be freely cloned and passed around.

const MAX_PLANES: usize = 4;

struct DmabufInternal {
    src: Box<dyn Buffer + 'static>,

    num_planes: usize,
    offsets: [u32; MAX_PLANES],
    strides: [u32; MAX_PLANES],
    fds: [RawFd; MAX_PLANES],
}

#[derive(Clone)]

/// Maximum amount of planes this implementation supports
pub const MAX_PLANES: usize = 4;

#[derive(Debug)]
pub(crate) struct DmabufInternal {
    /// The submitted planes
    pub planes: Vec<Plane>,
    /// The size of this buffer
    pub size: Size<i32, BufferCoords>,
    /// The format in use
    pub format: Fourcc,
    /// The flags applied to it
    ///
    /// This is a bitflag, to be compared with the `Flags` enum re-exported by this module.
    pub flags: DmabufFlags,
}

#[derive(Debug)]
pub(crate) struct Plane {
    pub fd: OwnedFd,
    /// The plane index
    pub plane_idx: u32,
    /// Offset from the start of the Fd
    pub offset: u32,
    /// Stride for this plane
    pub stride: u32,
    /// Modifier for this plane
    pub modifier: Modifier,

impl Buffer for Dmabuf {
    fn width(&self) -> u32 {
        self.0.src.width()
    }

    fn height(&self) -> u32 {
        self.0.src.height()
    }

    fn format(&self) -> Format {
        self.0.src.format()
    }
}

        /// The buffer content if interlaced is bottom-field first
        const BOTTOM_FIRST = 4;
    }
}

#[derive(Debug, Clone)]
/// Strong reference to a dmabuf handle
pub struct Dmabuf(pub(crate) Arc<DmabufInternal>);

#[derive(Debug, Clone)]
/// Weak reference to a dmabuf handle
pub struct WeakDmabuf(pub(crate) Weak<DmabufInternal>);

impl PartialEq for Dmabuf {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.0, &other.0)
    }
}
impl Eq for Dmabuf {}

        let mut fds = fds.iter().take(planes).chain(end_fds.iter());

        Some(Dmabuf(Arc::new(DmabufInternal {
            src: Box::new(src),

            num_planes: planes,
            offsets: [*offsets.next().unwrap(), *offsets.next().unwrap(), *offsets.next().unwrap(), *offsets.next().unwrap()],
            strides: [*strides.next().unwrap(), *strides.next().unwrap(), *strides.next().unwrap(), *strides.next().unwrap()],
            fds: [*fds.next().unwrap(), *fds.next().unwrap(), *fds.next().unwrap(), *fds.next().unwrap()],
        })))
    }

        self.0.as_ptr().hash(state)
    }
}

impl Buffer for Dmabuf {
    fn size(&self) -> Size<i32, BufferCoords> {
        self.0.size
    }

    fn format(&self) -> Format {
    }

    pub fn has_modifier(&self) -> bool {
        self.0.src.format().modifier != Modifier::Invalid &&
        self.0.src.format().modifier != Modifier::Linear 
    }

    pub fn weak(&self) -> WeakDmabuf {
        WeakDmabuf(Arc::downgrade(&self.0))
    } 
}

impl WeakDmabuf {
    pub fn upgrade(&self) -> Option<Dmabuf> {
        self.0.upgrade().map(|internal| Dmabuf(internal))
    }
}
            modifier,
        });

        true
    }

    /// Build a `Dmabuf` out of the provided parameters and planes
    ///
    /// Returns `None` if the builder has no planes attached.
    pub fn build(mut self) -> Option<Dmabuf> {
        if self.internal.planes.is_empty() {
            return None;
        }

        self.internal.planes.sort_by_key(|plane| plane.plane_idx);
        Some(Dmabuf(Arc::new(self.internal)))
    }
}

impl Dmabuf {
    /// Create a new Dmabuf by initializing with values from an existing buffer
    ///
    // Note: the `src` Buffer is only used a reference for size and format.
    // The contents are determined by the provided file descriptors, which
    // do not need to refer to the same buffer `src` does.
    pub fn builder_from_buffer(src: &impl Buffer, flags: DmabufFlags) -> DmabufBuilder {
        DmabufBuilder {
            internal: DmabufInternal {
                planes: Vec::with_capacity(MAX_PLANES),
                size: src.size(),
                format: src.format().code,
                flags,
            },
        }
    }

    /// Create a new Dmabuf builder
    pub fn builder(
        size: impl Into<Size<i32, BufferCoords>>,
        format: Fourcc,
        flags: DmabufFlags,
    ) -> DmabufBuilder {
        DmabufBuilder {
            internal: DmabufInternal {
                planes: Vec::with_capacity(MAX_PLANES),
                size: size.into(),
                format,
                flags,
            },
        }
    }

    /// The amount of planes this Dmabuf has
    pub fn num_planes(&self) -> usize {
        self.0.planes.len()
    }

    /// Returns raw handles of the planes of this buffer
    pub fn handles(&self) -> impl Iterator<Item = BorrowedFd<'_>> + '_ {
        self.0.planes.iter().map(|p| p.fd.as_fd())
    }

    /// Returns offsets for the planes of this buffer
    pub fn offsets(&self) -> impl Iterator<Item = u32> + '_ {
        self.0.planes.iter().map(|p| p.offset)
    }

    /// Returns strides for the planes of this buffer
    pub fn strides(&self) -> impl Iterator<Item = u32> + '_ {
        self.0.planes.iter().map(|p| p.stride)
    }

    /// Returns if this buffer format has any vendor-specific modifiers set or is implicit/linear
    pub fn has_modifier(&self) -> bool {
        self.0.planes[0].modifier != Modifier::Invalid && self.0.planes[0].modifier != Modifier::Linear
    }

    /// Returns if the buffer is stored inverted on the y-axis
    pub fn y_inverted(&self) -> bool {
        self.0.flags.contains(DmabufFlags::Y_INVERT)
    }

    /// Create a weak reference to this dmabuf
    pub fn weak(&self) -> WeakDmabuf {
        WeakDmabuf(Arc::downgrade(&self.0))
    }
}

impl WeakDmabuf {
    /// Try to upgrade to a strong reference of this buffer.
    ///
    /// Fails if no strong references exist anymore and the handle was already closed.
    pub fn upgrade(&self) -> Option<Dmabuf> {
        self.0.upgrade().map(Dmabuf)
    }

    /// Returns true if there are not any strong references remaining
    pub fn is_gone(&self) -> bool {
        self.0.strong_count() == 0
    }
}

/// Buffer that can be exported as Dmabufs
pub trait AsDmabuf {
    /// Error type returned, if exporting fails
    type Error;

    /// Export this buffer as a new Dmabuf
    fn export(&self) -> Result<Dmabuf, Self::Error>;
}

impl AsDmabuf for Dmabuf {
    type Error = std::convert::Infallible;

    fn export(&self) -> Result<Dmabuf, std::convert::Infallible> {
        Ok(self.clone())
    }
}

<MSG> dmabuf's take ownership over their contents -> do not reference original buffer

<DFF> @@ -4,13 +4,14 @@ use std::os::unix::io::RawFd;
 
 const MAX_PLANES: usize = 4;
 
-struct DmabufInternal {
-    src: Box<dyn Buffer + 'static>,
-
-    num_planes: usize,
-    offsets: [u32; MAX_PLANES],
-    strides: [u32; MAX_PLANES],
-    fds: [RawFd; MAX_PLANES],
+pub(crate) struct DmabufInternal {
+    pub num_planes: usize,
+    pub offsets: [u32; MAX_PLANES],
+    pub strides: [u32; MAX_PLANES],
+    pub fds: [RawFd; MAX_PLANES],
+    pub width: u32,
+    pub height: u32,
+    pub format: Format,
 }
 
 #[derive(Clone)]
@@ -46,15 +47,15 @@ impl PartialEq for WeakDmabuf {
 
 impl Buffer for Dmabuf {
     fn width(&self) -> u32 {
-        self.0.src.width()
+        self.0.width
     }
 
     fn height(&self) -> u32 {
-        self.0.src.height()
+        self.0.height
     }
 
     fn format(&self) -> Format {
-        self.0.src.format()
+        self.0.format
     }
 }
 
@@ -81,12 +82,14 @@ impl Dmabuf {
         let mut fds = fds.iter().take(planes).chain(end_fds.iter());
 
         Some(Dmabuf(Arc::new(DmabufInternal {
-            src: Box::new(src),
-
             num_planes: planes,
             offsets: [*offsets.next().unwrap(), *offsets.next().unwrap(), *offsets.next().unwrap(), *offsets.next().unwrap()],
             strides: [*strides.next().unwrap(), *strides.next().unwrap(), *strides.next().unwrap(), *strides.next().unwrap()],
             fds: [*fds.next().unwrap(), *fds.next().unwrap(), *fds.next().unwrap(), *fds.next().unwrap()],
+
+            width: src.width(),
+            height: src.height(),
+            format: src.format(),
         })))
     }
 
@@ -103,17 +106,27 @@ impl Dmabuf {
     }
 
     pub fn has_modifier(&self) -> bool {
-        self.0.src.format().modifier != Modifier::Invalid &&
-        self.0.src.format().modifier != Modifier::Linear 
+        self.0.format.modifier != Modifier::Invalid &&
+        self.0.format.modifier != Modifier::Linear 
     }
 
     pub fn weak(&self) -> WeakDmabuf {
         WeakDmabuf(Arc::downgrade(&self.0))
-    } 
+    }
 }
 
 impl WeakDmabuf {
     pub fn upgrade(&self) -> Option<Dmabuf> {
         self.0.upgrade().map(|internal| Dmabuf(internal))
     }
+}
+
+impl Drop for DmabufInternal {
+    fn drop(&mut self) {
+        for fd in self.fds.iter() {
+            if *fd != 0 {
+                let _ = nix::unistd::close(*fd);
+            }
+        }
+    }
 }
\ No newline at end of file

dmabuf's take ownership over their contents -> do not reference original buffer