Skip to main content

DumbRingSource

Struct DumbRingSource 

Source
pub struct DumbRingSource { /* private fields */ }
Expand description

A ring of CPU-mapped dumb buffers, presented as a scene layer’s source.

This is what turns BufferRing’s bookkeeping into something a producer can use: paint hands a callback the leased buffer’s mapping and the region it must repaint, and whatever the callback says it changed becomes the next commit’s FB_DAMAGE_CLIPS.

§Why it lives here and not in drmkit-scene-sources

It depends on BufferRing, and the scene must not depend on the present spine — the producer seam points the other way. It is still an ordinary LayerBufferSource, so a scene layer holds one directly without knowing where it came from.

§The contract, for a CPU producer

Once per frame, call paint. The callback gets the stale region: Repaint::Full for a slot that is fresh or too old to track, otherwise the union of damage since this slot was last on screen — which is not the same as what changed this frame, and is the whole reason the ring exists. Paint at least that much, return what you actually touched, and the scene’s next commit scans out the slot and reports exactly that as its damage.

Under-reporting leaves stale pixels on screen. Over-reporting costs bandwidth and nothing else, which is why every path that cannot prove the stale region returns Full.

§Threading

Single-threaded: drive paint and the scene commit from one loop.

Implementations§

Source§

impl DumbRingSource

Source

pub fn new( width: u32, height: u32, fourcc: u32, max_slots: usize, ) -> Result<Self, PaintError>

A ring of up to max_slots linear dumb buffers.

Nothing is allocated here. Slots are allocated by paint as the ring grows under contention, which on a 4K display is the difference between reserving one buffer and reserving three.

§Errors

PaintError::Zero for a zero width, height or max_slots, and PaintError::UnknownFormat if fourcc’s bits-per-pixel is not known, since that is what sizes the allocation.

Source

pub fn paint<F>(&mut self, device: &Device, paint: F) -> Result<(), PaintError>
where F: FnOnce(&mut Mapping<'_>, &Repaint) -> Vec<Rect>,

Paint the next frame.

The callback receives the leased buffer’s writable mapping and the region it must repaint, and returns the region it actually changed, in buffer pixels.

device is a parameter rather than something the source holds. The reference keeps a raw const drm::Device* and swaps it on session resume; storing a borrow here would put a lifetime on the type and into every scene that holds one, and storing a pointer is the thing Rust is for avoiding. Passing it per call also means there is no stale device to swap when a session resumes — the next paint simply gets the new one.

§Errors

PaintError::WouldBlock when every slot is busy, which is flow control rather than failure. Otherwise whatever allocating a slot failed with.

Source

pub fn allocated(&self) -> usize

How many slots have been allocated so far.

Trait Implementations§

Source§

impl LayerBufferSource for DumbRingSource

Source§

fn acquire(&mut self) -> Result<AcquiredBuffer, SourceError>

Hand the scene the slot the last paint committed.

SourceError::WouldBlock when nothing has been painted since the last acquire — the same signal a camera gives before its first frame, and handled the same way: the layer keeps what it had rather than the frame failing.

Source§

fn release(&mut self, acquired: AcquiredBuffer)

Return a slot to the ring once its flip has landed.

Source§

fn on_session_paused(&mut self)

Drop every buffer without touching the dead descriptor, and the ring’s history with them.

The GEM handles and framebuffer ids belonged to it and the kernel reclaims them when it closes; issuing ioctls against it would fail and change nothing.

The history goes because it describes the buffers, not the slots: each slot is re-allocated zeroed after the resume, so a slot the ring remembered as nearly current would ask for a partial repaint of a blank buffer and leave the rest of it blank on screen. A fresh ring answers Repaint::Full for every slot, as for a new source. Slots still held by the scene are forgotten with it; a late release of one names no slot the fresh ring has and is ignored.

Source§

fn on_session_resumed(&mut self, _device: &Device) -> Result<(), SourceError>

Nothing to do: the next paint allocates against the device it is given.

The reference re-points its stored device here, drops the pending frame and reallocates every live slot. This port dropped the slots and the pending frame in on_session_paused, and holds no device to re-point, which is what makes this empty.

Source§

fn binding_model(&self) -> BindingModel

Which binding contract this source participates in.
Source§

fn format(&self) -> SourceFormat

The buffer’s shape, read during layer lowering to populate the properties the allocator consults.
Source§

fn release_with_fence( &mut self, acquired: AcquiredBuffer, release_fence: Option<SyncFence>, )

Release carrying the OUT_FENCE of the commit that displaced this buffer. Read more
Source§

fn wants_release_fence(&self) -> bool

Whether this source wants the per-buffer release fence. Read more
Source§

fn has_fresh_content(&self) -> bool

Whether a producer submitted something new since the last commit. Read more
Source§

fn on_retired(&mut self)

The scene acquires from this source no more: its layer was removed. Read more
Source§

fn map(&mut self, access: MapAccess) -> Result<Mapping<'_>, SourceError>

Acquire a CPU view of the pixel storage. Read more
Source§

fn with_mapping( &mut self, access: MapAccess, f: &mut dyn FnMut(&mut Mapping<'_>), ) -> Result<(), SourceError>

Run f over a CPU view of the pixel storage, writable when access allows it. Read more
Source§

fn export_dma_buf(&mut self) -> Result<DmaBufDesc<'_>, SourceError>

Export the currently-acquired buffer’s DMA-BUF planes. Read more
Source§

fn bind_to_plane(&mut self, plane_id: u32) -> Result<(), SourceError>

Bind a driver-owned producer to a plane. Read more
Source§

fn unbind_from_plane(&mut self, plane_id: u32)

Unbind from a plane, when the layer is reassigned or retired. Dormant, as bind_to_plane is.

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<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, 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.