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
impl DumbRingSource
Sourcepub fn new(
width: u32,
height: u32,
fourcc: u32,
max_slots: usize,
) -> Result<Self, PaintError>
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.
Sourcepub fn paint<F>(&mut self, device: &Device, paint: F) -> Result<(), PaintError>
pub fn paint<F>(&mut self, device: &Device, paint: F) -> Result<(), PaintError>
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.
Trait Implementations§
Source§impl LayerBufferSource for DumbRingSource
impl LayerBufferSource for DumbRingSource
Source§fn acquire(&mut self) -> Result<AcquiredBuffer, SourceError>
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)
fn release(&mut self, acquired: AcquiredBuffer)
Return a slot to the ring once its flip has landed.
Source§fn on_session_paused(&mut self)
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>
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
fn binding_model(&self) -> BindingModel
Source§fn format(&self) -> SourceFormat
fn format(&self) -> SourceFormat
Source§fn release_with_fence(
&mut self,
acquired: AcquiredBuffer,
release_fence: Option<SyncFence>,
)
fn release_with_fence( &mut self, acquired: AcquiredBuffer, release_fence: Option<SyncFence>, )
OUT_FENCE of the commit that displaced this
buffer. Read moreSource§fn wants_release_fence(&self) -> bool
fn wants_release_fence(&self) -> bool
Source§fn has_fresh_content(&self) -> bool
fn has_fresh_content(&self) -> bool
Source§fn on_retired(&mut self)
fn on_retired(&mut self)
Source§fn map(&mut self, access: MapAccess) -> Result<Mapping<'_>, SourceError>
fn map(&mut self, access: MapAccess) -> Result<Mapping<'_>, SourceError>
Source§fn with_mapping(
&mut self,
access: MapAccess,
f: &mut dyn FnMut(&mut Mapping<'_>),
) -> Result<(), SourceError>
fn with_mapping( &mut self, access: MapAccess, f: &mut dyn FnMut(&mut Mapping<'_>), ) -> Result<(), SourceError>
Source§fn export_dma_buf(&mut self) -> Result<DmaBufDesc<'_>, SourceError>
fn export_dma_buf(&mut self) -> Result<DmaBufDesc<'_>, SourceError>
Source§fn bind_to_plane(&mut self, plane_id: u32) -> Result<(), SourceError>
fn bind_to_plane(&mut self, plane_id: u32) -> Result<(), SourceError>
Source§fn unbind_from_plane(&mut self, plane_id: u32)
fn unbind_from_plane(&mut self, plane_id: u32)
bind_to_plane is.