Skip to main content

Module retained

Module retained 

Source
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§

RetainedBudget
How many bytes of retained pages a store may hold at once.
RetainedEntry
One resident page as the resident-key ledger reports it.
RetainedPages
The renderer’s retained pages: a budgeted, least-recently-used store keyed by the raw retained key (see the module doc).
RetainedPlan
One frame’s decisions, parallel to the frame’s CompiledFrame::retained, and the keys committing it evicts.

Enums§

RetainedDecision
What the store decided for one retained bracket of a frame.
RetainedRefusal
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.