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::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.
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.
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. Not holding one 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 more