pub struct DmaBufHandle { /* private fields */ }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— theobjects[]fds,Mof them (≤ 4, the libvaobjects[4]cap). Single-object NV12/P010 (theCOMPOSED_LAYERSexport common case) hasM = 1with 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 singledrmFormatModifierperVkImage(VkImageDrmFormatModifierExplicitCreateInfoEXT), so one modifier describes the whole surface.Self::num_planes/Self::plane_object_index/Self::plane_offsets/Self::plane_strides— the flattenedlayers[].{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
impl DmaBufHandle
Sourcepub fn new(
fd: OwnedFd,
desc: DmaBufImportDesc,
) -> Result<Self, InvalidHandleError>
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.
Sourcepub fn from_objects(
fds: SmallVec<[Arc<OwnedFd>; 2]>,
desc: DmaBufImportDesc,
) -> Result<Self, InvalidHandleError>
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.
Sourcepub fn with_keep_alive(self, keep_alive: KeepAlive) -> Self
pub fn with_keep_alive(self, keep_alive: KeepAlive) -> Self
Attach a pool-slot keep-alive — see the type-level keep_alive doc.
Sourcepub fn with_acquire_release(self, release: VkSlotRelease) -> Self
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.
Sourcepub fn fd(&self) -> &Arc<OwnedFd> ⓘ
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).
Sourcepub fn desc(&self) -> &DmaBufImportDesc
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.
pub fn fourcc(&self) -> u32
pub fn modifier(&self) -> u64
pub fn width(&self) -> u32
pub fn height(&self) -> u32
pub fn num_planes(&self) -> u8
Sourcepub fn plane_object_index(&self) -> [u8; 4]
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.
pub fn plane_strides(&self) -> [u32; 4]
pub fn plane_offsets(&self) -> [u32; 4]
Sourcepub fn keep_alive(&self) -> Option<&KeepAlive>
pub fn keep_alive(&self) -> Option<&KeepAlive>
Pool-slot keep-alive set via Self::with_keep_alive.
Sourcepub fn acquire_release(&self) -> Option<&VkSlotRelease>
pub fn acquire_release(&self) -> Option<&VkSlotRelease>
Consumer→producer slot-release gate set via
Self::with_acquire_release. See VkSlotRelease.