Settle growing layout branches in one frame
This commit is contained in:
1 parent
e212ed8d02
commit
5ece49b8d9
7 files changed
+139
-33
No files matched your search
+16
-11
@@ -281,12 +281,15 @@ always a leaf: `Rect`, `Image`, a fixed glyph). A widget that returns
|
||||
`false` (the default) is redrawn in full whenever `available` changes,
|
||||
which is correct always, just not free.
|
||||
|
||||
**Ancestor propagation** (a resized child changing its own reported size,
|
||||
requiring its parent to re-lay-out) is unchanged in spirit from today's
|
||||
`redraw` (`render_state.rs:270-305`), which already walks up exactly the
|
||||
ancestors whose cached size differs from the new one and stops as soon as
|
||||
a size is unchanged (`:274-286`). That loop moves from consulting
|
||||
`Cache.size` to consulting `ActiveData.size` (§5) but keeps its shape.
|
||||
**Size propagation goes both ways in the same frame.** A resized child first
|
||||
walks upward through exactly the ancestors whose cached size changes. That
|
||||
measurement pass gives each parent the new size but necessarily drew the
|
||||
branch in its old boxes. As the recursion returns, `redraw_and_settle` revisits
|
||||
those changed widgets from the outside in, after their parents have assigned
|
||||
the final boxes. Otherwise a newly appended child can retain the provisional
|
||||
(even inverted) region it was measured in until another update happens. The
|
||||
downward work is confined to the branch that changed; unchanged descendants
|
||||
still take `draw_inner`'s retained fast path.
|
||||
|
||||
### 4. Wrapped text, and "needs child height before choosing width"
|
||||
|
||||
@@ -667,9 +670,11 @@ A move alone cannot fix a changed size; `Painter::place` redraws in that
|
||||
case.
|
||||
|
||||
The cost is bounded and worth stating, because it is what makes the rule
|
||||
safe to apply everywhere: the second draw happens only on the frame a
|
||||
safe to apply everywhere: the settling draw happens only on the frame a
|
||||
widget's own size actually changes, which is a frame that was already
|
||||
redrawing it. A widget whose reported size is a function of the box it
|
||||
was *offered* would disagree every frame and redraw every frame — which
|
||||
is why `LazySpan` requires content-sized rows, and has since long before
|
||||
this.
|
||||
redrawing it. `Sized` also requires its final region before retaining its
|
||||
children: its own reported size may be known exactly while a descendant was
|
||||
drawn in the provisional box, so moving only the wrapper is insufficient. A
|
||||
widget whose reported size is a function of the box it was *offered* would
|
||||
disagree every frame and redraw every frame — which is why `LazySpan` requires
|
||||
content-sized rows, and has since long before this.
|
||||
+5
-6
@@ -682,10 +682,9 @@ report an exact `Len`; a debug assertion compares every hint with the real
|
||||
draw result. If final allocation changes a child's size, `Painter::place`
|
||||
redraws it in that box. Otherwise placement is one move-offset write.
|
||||
|
||||
Measured over the fixture's 401 streamed events: the busiest frame makes
|
||||
176 `Widget::draw` calls and the worst widget is called four times.
|
||||
Streamed-frame CPU p50 is 0.35ms, from 1.18ms before this layout change.
|
||||
Arena size and upload floors are unchanged.
|
||||
Measured over the fixture's 401 streamed events, streamed-frame CPU p50 is
|
||||
0.12ms, from 1.18ms before this layout change. Arena size and upload floors
|
||||
are unchanged.
|
||||
|
||||
Pinned growth now uses the same subtree translation as scrolling. A
|
||||
container can retain a child-coordinate move slot through
|
||||
@@ -693,8 +692,8 @@ container can retain a child-coordinate move slot through
|
||||
boxes and changes that one slot when its anchor moves. It still walks the
|
||||
visible run to virtualise it, but unchanged rows no longer acquire new
|
||||
absolute primitive regions. Over the fixture's 401 streamed events, instance
|
||||
upload is **2.9% against a 2.9% floor**, from 71.9% against 71.8%; median
|
||||
instance bytes per frame are **1,728**, from 176,496. This is framework
|
||||
upload is **1.1% against a 1.1% floor**, from 71.9% against 71.8%; median
|
||||
instance bytes per frame are **1,488**, from 176,496. This is framework
|
||||
layout/rendering behaviour and the transcript screen contains no special
|
||||
case for it.
|
||||
|
||||
|
||||
Reference in new issue
Block a user