pub struct ScanoutBackend { /* private fields */ }Expand description
One output, one layer, and everything between a producer and the screen.
Discovers the output, reads the driver’s profile, negotiates a modifier against what the CRTC’s planes can scan out, asks the producer for a buffer in one of them, and drives a single-layer scene over it. What is left for the caller is rendering and pacing.
The backend does not dispatch the page-flip event, for the reason
DumbScanoutSink does not: the scene deliberately has no commit() of its
own, so the caller drives its own PageFlip and calls
flip_landed.
§Teardown
Dropping the backend while a flip it armed is still outstanding waits, up to
100 ms, for the CRTC’s vblank sequence to move past that commit before the
scene lets go of its buffers. It never reads the event queue, so the event
stays queued for the caller. Dispatching it and calling
flip_landed first means there is nothing to wait for.
The device must outlive the backend: the wait reads the sequence on it.
Implementations§
Source§impl ScanoutBackend
impl ScanoutBackend
Sourcepub fn create(
device: &Device,
producer: &mut dyn ScanoutProducer,
config: &Config,
) -> Result<Self, PresentError>
pub fn create( device: &Device, producer: &mut dyn ScanoutProducer, config: &Config, ) -> Result<Self, PresentError>
Discover an output and build everything needed to present on it.
§Errors
PresentError::Bind if no output can be found, the planes cannot be
probed, or the producer cannot allocate.
Sourcepub fn present(
&mut self,
device: &Device,
flags: AtomicCommitFlags,
out_fence: Option<&mut Option<OwnedFd>>,
) -> Result<CommitReport, PresentError>
pub fn present( &mut self, device: &Device, flags: AtomicCommitFlags, out_fence: Option<&mut Option<OwnedFd>>, ) -> Result<CommitReport, PresentError>
Present one frame.
out_fence receives this commit’s OUT_FENCE where the CRTC exposes
OUT_FENCE_PTR — it signals once the frame is on screen, which is what
a producer waits on rather than blocking the CPU until the flip event.
§Errors
PresentError::Build if the scene cannot build the frame,
PresentError::Commit if the kernel refuses it.
Sourcepub fn present_if_changed(
&mut self,
device: &Device,
content_changed: bool,
flags: AtomicCommitFlags,
out_fence: Option<&mut Option<OwnedFd>>,
) -> Result<CommitReport, PresentError>
pub fn present_if_changed( &mut self, device: &Device, content_changed: bool, flags: AtomicCommitFlags, out_fence: Option<&mut Option<OwnedFd>>, ) -> Result<CommitReport, PresentError>
Present only if the content changed, suppressing an idle frame.
The first frame always commits, whatever content_changed says:
nothing is on screen yet, so “unchanged” describes nothing, and a
suppressed first frame leaves the scanout contents undefined.
A suppressed frame returns a report with
skipped_idle set and every other field
zero — there was no commit to count.
§Errors
As present.
Sourcepub const fn set_vrr(&mut self, enable: bool)
pub const fn set_vrr(&mut self, enable: bool)
Ask for variable refresh, or stop asking, from the next frame.
A no-op on a CRTC that exposes no VRR_ENABLED.
Sourcepub const fn vrr_capable(&self) -> bool
pub const fn vrr_capable(&self) -> bool
Whether the discovered output can do variable refresh.
Sourcepub const fn force_full_present(&mut self)
pub const fn force_full_present(&mut self)
Make the next frame a full commit, whatever the economy would decide.
Sourcepub const fn frames_committed(&self) -> u64
pub const fn frames_committed(&self) -> u64
How many frames reached the kernel.
Sourcepub const fn frames_skipped(&self) -> u64
pub const fn frames_skipped(&self) -> u64
How many frames were suppressed as idle.
Sourcepub const fn target(&self) -> &ScanoutTarget
pub const fn target(&self) -> &ScanoutTarget
The output this backend found.
Sourcepub const fn profile(&self) -> &DriverProfile
pub const fn profile(&self) -> &DriverProfile
The driver’s capabilities, as probed.
Sourcepub fn modifiers(&self) -> &[u64]
pub fn modifiers(&self) -> &[u64]
The negotiated modifiers the producer was allowed to allocate in.
Empty when no plane advertised IN_FORMATS, which is unconstrained
rather than nothing was acceptable.
Sourcepub const fn scene(&self) -> &LayerScene
pub const fn scene(&self) -> &LayerScene
The scene, for a caller adding layers of its own.
Sourcepub const fn scene_mut(&mut self) -> &mut LayerScene
pub const fn scene_mut(&mut self) -> &mut LayerScene
The scene, mutably.
Sourcepub const fn layer(&self) -> LayerHandle
pub const fn layer(&self) -> LayerHandle
The layer the producer’s buffer is presented on.
Sourcepub fn flip_landed(&mut self)
pub fn flip_landed(&mut self)
Tell the scene the flip it armed has landed.
Until this is called the scene believes a flip is outstanding, which is what keeps teardown from releasing a buffer the display engine is still reading — invariant 5.