Expand description
Retained pages: bodies the renderer rasterized once and keeps across frames, so a later frame can composite them instead of painting them again.
A PushRetained bracket’s body is an ordinary layer of the frame — the
compiler records it as one whatever its alpha (see
crate::compile::layers) — and this store decides, per frame, whether
that layer renders into a pooled page like any other (the inline lowering)
or into a page the store owns and keeps. A DrawRetained names a page by
key; the store resolves it to a composite of that page, or refuses the
frame when it cannot.
§What a page holds, and what it can be reused for
A page holds the body exactly as the inline lowering rasterizes it: on the
device grid, under the bracket’s own transform with its presentation scale
already applied, at the layer’s own tile-aligned bounds, and without the
bracket’s alpha — the alpha is the composite’s, so a page fades at no cost.
It is drawn through the same 1:1 PaintClass::LayerComposite quad a
pooled page is, never resampled, which is what makes a retained frame
pixel-identical to the inline one and also bounds what a page can serve: a
DrawRetained whose RetainedPlacement has the page’s linear part
(scale, rotation, skew) and whose translation differs by any amount is
composited at the page’s bounds moved by that translation rounded to whole
pixels; anything else — another scale, another extent — is not resident at
that placement, which is a refusal (below). The resident-key ledger reports
each page’s extent and scale as rasterized, presentation scale included,
so a widget asking for the extent it is about to draw at only ever asks for
a page that can serve it.
§Outside the pool, outside the page budget
A page is this store’s own allocation (gpu::targets::retained_page_descriptor),
never a pooled entry: the pool ages and re-lets textures frame by frame,
and a retained page’s whole point is to survive across frames. For the same
reason it is not one of the scheduler’s live pages: a round rendering a
body into its retained page, and the composite that later samples it, take
nothing from the two ping-pong groups or the spill page
(MAX_LIVE_PAGES) — the body’s own nested
translucent layers still do, exactly as they would inside any layer.
§Budget, eviction and refusals
The store is held to a byte budget (RetainedBudget) tiered by adapter
family the way the image atlas is (cache::images::choose_tier): a phone
keeps a few full-screen pages, a desktop a few more. A body that needs a
page evicts the least recently used pages until it fits, never one the frame
being planned draws or records. A body is refused — rendered inline this
frame, its key absent from the ledger — when the compiler marked it
unretainable (clipped on the way in, a hole punch or an external texture
inside it, an unbalanced bracket), when it drew nothing, drew outside its
own rectangle, is larger than MAX_INTERMEDIATE_DIMENSION or the
adapter’s ceiling on either axis, needs more than the whole budget, or names
a key the same frame already records or draws.
§A page holds this frame’s recording, or goes
The ledger is a promise to the widget tree: a key it lists can be drawn
instead of painted. So after any frame carrying a PushRetained for a key,
the ledger lists that key only if its page holds that frame’s recording
of the body — a page holding an older recording would composite stale
pixels on the next frame the widget asks for it. A re-record whose
recording does not reach the page therefore evicts the key’s page rather
than keep it:
- refused — any
RetainedRefusal, the body rendered inline; - nested — a bracket inside another one, which the compiler folds into
the outermost body and lists no bracket for
(
CompiledFrame::retained_superseded); - unrendered — an admitted body inside a layer the schedule dropped.
A key some bracket of the same frame draws, or records into its page and renders, keeps its page: that page is what the frame composited or recorded under the key. A key the frame does not name at all is untouched, and ages out least recently used like any other.
A DrawRetained the store cannot serve is a renderer error the display
list’s own contract anticipates: the frame is refused with
EngineError::RetainedKeyMissing before anything is recorded, and the
store is cleared, so the ledger published after it is empty and the next
frame paints every body again.
§Plan, then commit
RetainedPages::plan decides everything from plain values and changes
nothing of the store but its frame clock (and, on a refusal, its contents) —
of the frame, only the bounds of the recorded layers enclosing a served
DrawRetained, grown to hold its composite, since the empty layer standing
for it put nothing of it into theirs:
a frame can still be refused after it — by the scheduler, or a capacity
check — and a refused frame must leave every page and every ledger entry as
it was. RetainedPages::commit applies a plan once nothing can fail any
more: evictions first — the plan’s least recently used ones and every
refused, nested or unrendered re-record’s key (above) — then each admitted
body’s page — reused when the key’s current page is large enough, allocated
otherwise — and only for a body the schedule really rendered (a body inside
a dropped layer renders nothing, and a page claiming its key would
composite stale texels).
Generic over the texture and view types like the intermediate pool, so plan,
eviction and ledger behaviour is exercised against a counting fake
allocator with no GPU in the loop (tests/retained.rs).
Structs§
- Retained
Budget - How many bytes of retained pages a store may hold at once.
- Retained
Entry - One resident page as the resident-key ledger reports it.
- Retained
Pages - The renderer’s retained pages: a budgeted, least-recently-used store keyed by the raw retained key (see the module doc).
- Retained
Plan - One frame’s decisions, parallel to the frame’s
CompiledFrame::retained, and the keys committing it evicts.
Enums§
- Retained
Decision - What the store decided for one retained bracket of a frame.
- Retained
Refusal - Why a body was rendered inline rather than into a retained page.
Constants§
- RETAINED_
BYTES_ PER_ TEXEL - Bytes one retained-page texel costs — the intermediate format is
Rgba8Unorm.