Skip to main content

DmaBufHandle

Struct DmaBufHandle 

Source
pub struct DmaBufHandle { /* private fields */ }
Available on Android or Linux only.
Expand description

Linux / Android DMA-BUF descriptor — the direct analogue of libva’s VADRMPRIMESurfaceDescriptor (va_drmcommon.h).

§Object / plane model (mirrors VADRMPRIMESurfaceDescriptor)

A surface is M DRM objects (fds) carrying N planes. libva’s descriptor splits this into objects[] (fd + size + modifier) and layers[] (each a drm_format + planes, every plane naming its object_index, offset, pitch). This type flattens the layer/plane nesting into one per-plane view — every plane names the object (fd) it lives in via Self::plane_object_index, plus its Self::plane_offsets and Self::plane_strides (libva pitch):

  • Self::fds — the objects[] fds, M of them (≤ 4, the libva objects[4] cap). Single-object NV12/P010 (the COMPOSED_LAYERS export common case) has M = 1 with every plane at object index 0.
  • Self::modifier — the DRM format modifier. libva stores it per-object, but a surface’s tiling is uniform across its objects and the Vulkan importer takes a single drmFormatModifier per VkImage (VkImageDrmFormatModifierExplicitCreateInfoEXT), so one modifier describes the whole surface.
  • Self::num_planes / Self::plane_object_index / Self::plane_offsets / Self::plane_strides — the flattened layers[].{num_planes, object_index, offset, pitch}.

The model therefore covers N planes across M objects, not just the single-fd / single-object NV12 case.

Import capacity note: a single-VkImage importer with an import cache keyed on the primary fd number supports only single-object surfaces (M = 1, every plane at object index 0) — the COMPOSED_LAYERS NV12/P010 export common case. M > 1 (fds.len() > 1 / distinct plane_object_index) is capacity in the carrier that such an importer cannot consume: it needs a DISJOINT multi-memory-plane import path and a multi-fd cache key, and without them it rejects a multi-object handle. A producer must not emit one expecting it to import there.

§FD discipline (dup once, Arc-share every emission)

Self::fds are Arc<OwnedFd>: Clone is an Arc refcount bump, and the last drop closes each fd via std’s OwnedFd::drop. A frame-pool producer dup(2)s each object fd exactly once when the slot is built and Arc-shares it into every per-frame carrier — a per-emission dup() is a bug, not a nicety, because an import cache keyed on the raw fd number sees a fresh dup as a new number, misses, and forces a new VkImage per frame. Emission never re-dups. Ownership-transferring importers still dup per the module-level “FD/handle consumer rule”; that dup is the driver’s private copy and does not perturb the cache-identity fd this carrier holds.

§keep_alive — pool-slot pinning

Self::keep_alive pins the producer’s recyclable pool slot (mirrors VaapiSurface::keep_alive on Linux) so the slot cannot be re-issued — and its backing memory overwritten — while a consumer-side clone of this handle is still live. Invariant: the handle must be held until the submit that samples the imported texture has been made (not retired); the standard playback ring-of-1 lease honours this. The import path invokes ResourceKeepAlive::mark_consumed after a successful import, which a pool anchor overrides to flip its “imported” flag and switch to the GPU-completion (rather than instant) recycle path.

§acquire_release — recycle-gate back-pressure

Self::acquire_release carries the consumer→producer slot-release gate (the shared VkSlotRelease protocol; see its docs). A ring-pool producer stamps it with the previous emission’s {gate, value} so the consumer’s on_submitted_work_done can publish “prior read retired” before the producer overwrites the slot. None for single-shot (non-recycling) producers where no reuse race exists.

Implementations§

Source§

impl DmaBufHandle

Source

pub fn new( fd: OwnedFd, desc: DmaBufImportDesc, ) -> Result<Self, InvalidHandleError>

Single-object constructor — every plane lives in one fd (the COMPOSED_LAYERS NV12/P010 case and every RGBA/BGRA/R/Rg surface). Adopts a freshly-minted OwnedFd (e.g. from vkGetMemoryFdKHR); keep_alive / acquire_release default to None (attach via Self::with_keep_alive / Self::with_acquire_release).

§Correctness, not safety

This constructor is deliberately safe, unlike every other entry point in this module: fd arrives as an OwnedFd, so ownership and validity are already carried by the type system, and the layout arguments are inert data that the kernel bounds when the buffer is finally mapped. Getting them wrong therefore yields wrong pixels or a driver-side import error, not undefined behaviour, so there is no safety contract to state here.

It is still a precondition of a correct import that fd name a real DMA-BUF and that desc describe its actual storage — vkImportMemoryFdKHR and EGL_EXT_image_dma_buf_import take it at face value.

§Errors

Delegates to Self::from_objects, so a desc naming any object other than the single fd (a non-zero DmaBufImportDesc::plane_object_index entry within num_planes) is rejected as plane_object_index rather than silently coerced.

Source

pub fn from_objects( fds: SmallVec<[Arc<OwnedFd>; 2]>, desc: DmaBufImportDesc, ) -> Result<Self, InvalidHandleError>

General multi-object constructor from pre-shared Arc<OwnedFd>s — the frame-pool emission path (fds already dup’d once at slot build, Arc-shared here per the type’s “FD discipline”). desc.plane_object_index names the object (index into fds) for each of the first desc.num_planes planes. keep_alive / acquire_release default to None; attach via the builders.

Safe for the same reason as Self::new — see its Correctness, not safety note. The same import-correctness precondition applies to every fd in fds and to the layout arrays that index them.

§Errors

This is the single funnel every carrier is built through, and the only place desc is cross-checked against the objects it describes: degenerate extent, num_planes outside 1..=4, fds.len() outside 1..=4 (libva’s objects[4] cap), or an active plane naming an object that does not exist.

Source

pub fn with_keep_alive(self, keep_alive: KeepAlive) -> Self

Attach a pool-slot keep-alive — see the type-level keep_alive doc.

Source

pub fn with_acquire_release(self, release: VkSlotRelease) -> Self

Attach the consumer→producer slot-release gate — see the type-level acquire_release doc and VkSlotRelease.

Source

pub fn fd(&self) -> &Arc<OwnedFd> ⓘ

Primary object fd (fds[0]) — the raw-fd-number cache-identity anchor and the fd used by the single-object import paths. Never empty (constructors reject a zero-object descriptor).

Source

pub fn fds(&self) -> &[Arc<OwnedFd>]

All DRM object fds (libva objects[]), 1..=4.

Source

pub fn desc(&self) -> &DmaBufImportDesc

The whole validated layout descriptor, as handed to Self::from_objects. Re-emitting a carrier over a duped fd is DmaBufHandle::new(dup, *src.desc()) — no field-by-field re-assembly, so a new descriptor field cannot be silently dropped on the way through. Importers that need the whole layout (EGL_EXT_image_dma_buf_import_modifiers attribute assembly, VkSubresourceLayout[] fill-in) take this rather than a dozen per-field calls.

Source

pub fn fourcc(&self) -> u32

Source

pub fn modifier(&self) -> u64

Source

pub fn width(&self) -> u32

Source

pub fn height(&self) -> u32

Source

pub fn num_planes(&self) -> u8

Source

pub fn plane_object_index(&self) -> [u8; 4]

Object index (into Self::fds) for each plane — libva layers[].object_index[]. Only the first Self::num_planes entries are meaningful.

Source

pub fn plane_strides(&self) -> [u32; 4]

Source

pub fn plane_offsets(&self) -> [u32; 4]

Source

pub fn keep_alive(&self) -> Option<&KeepAlive>

Pool-slot keep-alive set via Self::with_keep_alive.

Source

pub fn acquire_release(&self) -> Option<&VkSlotRelease>

Consumer→producer slot-release gate set via Self::with_acquire_release. See VkSlotRelease.

Trait Implementations§

Source§

impl Clone for DmaBufHandle

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DmaBufHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> MaybeSend for T
where T: Send + ?Sized,

Source§

impl<T> MaybeSendSync for T
where T: Send + Sync + ?Sized,

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,