Expand description
Scene composition for drmkit.
Port of src/scene/ from drm-cxx @ dc2915b.
A LayerScene owns one CRTC’s stack of layers and the machinery that
turns them into a frame: which plane each layer lands on, what to composite
when there are more layers than planes, and when a buffer may go back to
whoever produced it.
§Driving a frame
let mut scene = LayerScene::new(crtc_id);
let handle = scene.add_layer(Box::new(source));
scene.layer_mut(handle)?.set_display(DisplayParams { .. });
// per frame
let mut build = scene.build_frame(®istry, crtc_index, kind, &mut committer)?;
emit_frame(&mut request, &map, &mut build, modeset)?;
arm_acquire_fences(&mut build, &mut request, &map, true)?;
let result = request.commit(&device, flags);
let report = scene.finalize_frame(build, classify(&result));
// ... and when the page-flip event arrives
scene.flip_landed();The split between build_frame and finalize_frame is the part worth
understanding. build_frame acquires a buffer from every source, runs the
allocator — which may issue TEST_ONLY commits through the committer to
ask the kernel whether an arrangement is legal — and hands back a
FrameBuild describing what to program. It does not commit: the caller
owns the request, so it can add a modeset, arm fences, or refuse the frame.
finalize_frame then takes the kernel’s answer and settles the
bookkeeping, which is what arms the flip and what decides which buffers are
now safe to release.
A FrameBuild dropped without finalize_frame leaks its acquisitions, and
says so in a debug assertion rather than silently.
§A source with nothing ready
SourceError::WouldBlock from a source is not an error. It is the
documented “no frame yet” signal — a V4L2 device before its first sample,
an appsink mid-preroll — and the layer is skipped for that frame and
counted in the report, keeping the plane it had and the framebuffer already
on it. A frame does not fail because one producer was late, and a starved
layer does not blink off screen.
§The release contract
Two of the four pinned invariants this crate carries are about when a buffer goes back to its source:
- Invariant 1 — a buffer is released only after the page flip that stops scanning it out completes, two commits deep, never when the ioctl returns. Releasing early lets a producer overwrite a buffer the display engine is still reading, which tears on hardware whose producer driver attaches no reservation fence.
- Invariant 2 — a failed commit releases that frame’s acquisitions
immediately, because no flip is in flight to gate them on, and a
non-
EACCESfailure does not suspend the scene. Self-healing producer rings depend on being able to reuse their buffers after a rejection.
AcquiredBuffer is move-only, so handing a buffer back early is a move
and using it afterwards does not compile — the ownership half of invariant 1
is enforced by the type. The timing half cannot be, and is pinned against a
real device in tests/release_invariants_vkms.rs.
Structs§
- Acquire
Tally - Accounting for one build pass’s acquire loop.
- Acquired
Buffer - A buffer handed over by
LayerBufferSource::acquire, valid until the matchingrelease. - Acquisition
- One buffer held on behalf of a layer.
- Commit
Report - A snapshot of a single commit.
- Composite
Canvas - A double-buffered software composition surface.
- Composite
Rect - A rectangle in whole pixels, half-open in extent.
- Composite
Src - A source surface to blend from.
- Damage
Rect - A region of a buffer that changed since the slot was last scanned out, in buffer pixels with a top-left origin.
- Device
Committer - A
TestCommitterthat issues realTEST_ONLYcommits. - Display
Params - How a layer should be displayed.
- DmaBuf
Desc - A borrowed view of a buffer’s DMA-BUF planes, for a consumer that imports the buffer directly rather than reading CPU pixels.
- Fixed
Rect - A source rectangle in 16.16 fixed point: the kernel’s own
SRC_*encoding, for a crop at sub-pixel precision. A Wayland viewport’s source rectangle, for one, is in 1/256ths of a pixel, and rounding it moves the image by up to half a pixel and changes its scale. 1.0 is0x10000. - Frame
Build - A frame that has been built and is awaiting the kernel’s answer.
- Frame
Lifecycle - Owns the state a commit reconciles: the release ring, the armed-flip tripwire, and whether the scene is suspended.
- Frame
Outcome - What the scene must do after a commit.
- Layer
Handle - Opaque, generation-tagged identity for a scene layer.
- Layer
Incompatibility - One layer the new output cannot display as it stands.
- Layer
Placement - One layer’s outcome.
- Layer
Scene - One CRTC’s layers and the commit machinery around them.
- Layer
Writes - What emitting one layer put on the wire.
- Lowering
Input - Everything
lower_layerneeds about a layer, without borrowing the scene. - Modeset
- The CRTC and connector writes that bring a display up.
- Output
Signaling - What the scene wants declared on the connector for one frame.
- Pending
Detach - Planes a scene left lit on the CRTC it moved away from.
- Plane
Plan - One plane’s share of a built frame.
- Plane
Property Map - Resolves a layer’s
PropTags to the DRM property ids of a given plane. - Rebind
Report - What a
rebindfound that will not fit. - Rect
- An axis-aligned rectangle in CRTC pixels.
- Release
Queue - The two-deep ring of in-flight acquisitions.
- Released
- The buffers to hand back, and why.
- Scene
Layer - A layer’s live scene state.
- Scene
Pending Flip - Tracks whether a commit armed a page-flip event that has not been dispatched.
- Source
Format - What a source’s buffer intrinsically is.
- Ycbcr
- How a plane converts a layer’s YCbCr to RGB: its
COLOR_ENCODINGandCOLOR_RANGE.
Enums§
- Binding
Model - How the scene and a source divide responsibility for
FB_ID. - Color
Encoding - Plane
COLOR_ENCODING: the YCbCr-to-RGB matrix applied when scanning out a YUV format. Ignored by the kernel for RGB. - Color
Primaries - The container colorimetry a producer says its layer is in.
- Color
Range - Plane
COLOR_RANGE: whether 8-bit YCbCr is full-range (0..255) or limited-range (16..235 luma, 16..240 chroma). - Commit
Kind - What one commit was.
- Fence
Action - What to do with a layer’s acquire fence, given what its plane can take.
- Incompatibility
Reason - Why a layer does not fit its new output.
- Kernel
Result - What the kernel said about a commit.
- Placement
- How a layer reached scanout.
- Release
Reason - Why a set of buffers is being handed back.
- Scene
Error - Why a frame could not be built.
- Source
Error - Why an
acquiredid not produce a buffer.
Traits§
- Layer
Buffer Source - Where a layer’s content comes from.
Functions§
- arm_
acquire_ fences - Give each fenced layer’s fence to its plane, or wait on it here.
- blend_
into - Blend
srcoverdst, premultipliedSRC_OVER. - canvas_
format_ for_ plane - The best canvas format this plane can scan out, if any.
- canvas_
output_ bpp - Bytes per pixel the canvas can write in
fourcc, or zero. - classify
- Classify a real commit’s outcome for
FrameLifecycle. - clear_
into - Zero-fill a rectangle of
dst, clipped to its extents. - commit_
detach - Turn off what a
rebindleft on the old CRTC. - convert_
row - Convert one row of the
ARGB8888shadow intoout_fourcc. - derive_
output_ signaling - Derive what the connector should signal for this frame’s layers.
- derive_
output_ signalling Deprecated - The 0.1.0 name of
derive_output_signaling, kept so code written against it still builds. - emit_
disable - Emit the writes that detach a plane.
- emit_
frame - Emit a built frame’s apply commit.
- emit_
frame_ damaged emit_frame, plus theFB_DAMAGE_CLIPSblobs partial repaint needs.- emit_
layer - Emit one layer’s properties onto a plane.
- fence_
action - Decide between the two, from whether the plane exposes a writable
IN_FENCE_FD. - format_
supported - Whether this module can blend from
fourcc. - lower_
layer - Copy a scene layer’s state into the plane property bag.
- to_
16_ 16 - Convert whole pixels to the 16.16 fixed point KMS expects for
SRC_*. - widest_
gamut - The widest-gamut primaries any layer names.
Type Aliases§
- Output
Signalling Deprecated - The 0.1.0 name of
OutputSignaling, kept so code written against it still builds.