Module scroll_copy
Expand description
Scrolling by copying the pixels that stay on screen.
A scroll moves every pixel of a scroller’s content, so damage alone repaints its whole viewport on every frame of a scroll. When the content moved by a pure translation since the frame the host last presented, most of those pixels are already in the host’s retained target, one delta away.
A scroller says so from its collect_damage (offer) instead of
damaging its viewport: where its content paints, how far it moved, and
what it paints over its content that does not move with it (a scroll bar,
an edge fade). A host that keeps the last frame’s pixels collects damage
inside accepting; any other host gets the viewport damage as before,
because offer answers false there.
The host then plans each offer (plan) against the widget tree it just
drew: the copy is clipped by every ancestor’s child clip and kept to whole
device pixels; a delta that is not a whole number of device pixels, or a
scroller drawn under another transform than the window’s, is refused (the
viewport is damaged instead). What may paint over or under the content
without moving with it is damage: the scroller’s own overlays, every
other widget whose box (with its effect reach) reaches into the viewport,
and the edges of every ancestor and of every frame that holds the
viewport (a border or an inset shadow drawn over children). Damage a copy
reads, those overlays and whatever else changed in place this frame, is
carried to where the copy lands (carry), and what the copy exposed is
repainted. The renderer copies first (encode_copies, or
copy_pixels on a CPU canvas), then rasterizes the damage.
A relayout’s moves are checked against the offers ([moves_besides]):
content that moved by its scroller’s delta is the copy’s; content that
came, went or stayed put (a long list mounting rows, a pinned title, a
sticky header) is damage; anything else that moved makes the host
repaint as it would without copies.
Structs§
- Copy
Plan - What a host does with a frame’s offers, in device pixels: the copies, in
order; the damage they add where something does not move with the
content (each copy’s overlays, a refused offer’s viewport), which the
host carries along with the rest of its damage (
carry); and what the copies exposed, repainted as it is. - Copy
Scratch - A target’s scratch space for copies within it, which a copy cannot do in
place: WebGPU refuses a copy whose source and destination are the same
texture’s same subresource. Each copy moves through it in bands of at
most [
BAND] rows, so it holds a band, not a viewport. - Device
Copy - One planned copy within a host’s retained target, in device pixels: the source rectangle, and how far it moves.
- Host
Copies - While held, every
crate::app::EmbeddedAppdrawn on this thread is drawn for a host that presents each frame over the pixels it last presented and can move them, ascrate::app::EmbeddedApp::set_accepts_scroll_copiessays; an app that learned so keeps handing out copies, which a host that cannot make them repaints where they land. - Moved
Region - A copy as a host that composites the target elsewhere sees it: the rectangle it reads and how far it moves it, in the coordinates of the scene the target is drawn into (an embedded app’s region in a desktop section), before that scene is rasterised.
- Scroll
Offer - A scroller’s claim that, since the frame its host last presented, its content moved by a pure translation within an unchanged viewport.
Constants§
- EFFECT_
REACH - How far outside its layout box a widget may paint: anti-aliasing, a shadow, a hover lift. The native window grows every widget’s damage by as much, in logical pixels.
Functions§
- accepting
- Run
collect(a widget tree’scollect_damage) with scroll copies accepted, and return what the scrollers in it offered instead of damaging their viewports. Only a host that presents over its last frame’s pixels and copies each planned offer (plan,encode_copies) may call it. - carried
- Where
copiestake the pixelsrectscover (device pixels): each piece of a rect a copy reads, one delta away. - carry
- Add to
damage(device pixels, where a frame differs from the last in place) wherecopiestake what it covers: a pixel that changed in place and that a copy moves lands, stale, one delta away. Everything but what the copies exposed goes through here, the overlays the plan found included. - copy_
pixels - Apply
copiestopixels, awidth-pixel-wide RGBA8 image whose rows arestridebytes apart, in order. Returnsfalse, changing nothing, when a copy would leave the image. - drawing_
into_ cache - Record
drawinto a cache its caller then appends withtransform(a container that draws its children at the identity into a retained scene): a scroller drawn inside learns where its content lands on screen (on_screen). - encode_
copies - Record
copieswithintexture, in order, each throughscratch. Returnsfalse, recording nothing, when a copy would leave the texture: the caller must then repaint the target whole. - host_
copies - Whether the host drawing now copies (
HostCopies). - host_
device_ scale - How many pixels of the target of the host drawing now one unit of its
scene is (
HostCopies::begin_scaled); 1 outside any. - marks_
over_ copies - Add to
damagewhat marks painted over a window’s content without moving with it, and unseen by the planner (collaborators’ pointers and names), cost itscopies(device pixels, as each would be repainted): the target holds the marks of the frame on screen (shown), which a copy moves with the content, stale, one delta away; and this frame’s marks (painted) must be repainted wherever a copy wrote under them. Where a mark changed in place is the frame’s other damage, carried with it (carry). - offer
- From a scroller’s
collect_damage: offer to have its host copy what of its content stays on screen.viewportis where the content paints,deltahow far it moved on screen since the frame the host last presented, andoverlayswhat the scroller paints over its content that does not move with it, all in logical pixels;transformis the one its content landed on screen with this frame (on_screen). The scroller must still damage whatever inside its content changed besides moving. - on_
screen - Where
transform, the one a widget draws with, lands on screen: through every cache being recorded around it. - plan
- Plan
offersagainst the trees underrootsjust drawn (the app’s, then any the window draws beside it, such as History’s toolbar), atscaledevice pixels per logical pixel, for awidth×heighttarget: each becomes a copy and the damage around it, or, when it cannot be copied exactly, damage over its whole viewport. - plan_
scaled planfor a window drawn atdrawn_scalescene pixels per logical pixel into a host target ofdevice_per_scenepixels per scene pixel (an app drawn into a desktop’s logical scene, shown at 200 %): the plan is in those device pixels, for awidth×heighttarget of them.