mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
layout: Skip box tree construction when possible (#37957)
When a style change does not chang the structure of the box tree, it is possible to skip box tree rebuilding for an element. This change adds support for reusing old box trees when no element has that type of damage. In order to make this happen, there needs to be a type of "empty" `LayoutDamage` that just indicates that a fragment tree layout is necessary. This is the first step toward incremental fragment tree layout. Testing: This should not change observable behavior and thus is covered by existing WPT tests. Performance numbers to follow. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
d5d131c172
commit
436c9072c4
13 changed files with 181 additions and 78 deletions
|
@ -251,10 +251,10 @@ impl InlineItem {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn invalidate_cached_fragment(&self) {
|
||||
pub(crate) fn clear_fragment_layout_cache(&self) {
|
||||
match self {
|
||||
InlineItem::StartInlineBox(inline_box) => {
|
||||
inline_box.borrow().base.invalidate_cached_fragment()
|
||||
inline_box.borrow().base.clear_fragment_layout_cache()
|
||||
},
|
||||
InlineItem::EndInlineBox | InlineItem::TextRun(..) => {},
|
||||
InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => {
|
||||
|
@ -262,18 +262,18 @@ impl InlineItem {
|
|||
.borrow()
|
||||
.context
|
||||
.base
|
||||
.invalidate_cached_fragment();
|
||||
.clear_fragment_layout_cache();
|
||||
},
|
||||
InlineItem::OutOfFlowFloatBox(float_box) => float_box
|
||||
.borrow()
|
||||
.contents
|
||||
.base
|
||||
.invalidate_cached_fragment(),
|
||||
.clear_fragment_layout_cache(),
|
||||
InlineItem::Atomic(independent_formatting_context, ..) => {
|
||||
independent_formatting_context
|
||||
.borrow()
|
||||
.base
|
||||
.invalidate_cached_fragment();
|
||||
.clear_fragment_layout_cache()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,8 +133,8 @@ impl BlockLevelBox {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn invalidate_cached_fragment(&self) {
|
||||
self.with_base(LayoutBoxBase::invalidate_cached_fragment);
|
||||
pub(crate) fn clear_fragment_layout_cache(&self) {
|
||||
self.with_base(|base| base.clear_fragment_layout_cache());
|
||||
}
|
||||
|
||||
pub(crate) fn fragments(&self) -> Vec<Fragment> {
|
||||
|
|
|
@ -417,25 +417,8 @@ impl<'dom> IncrementalBoxTreeUpdate<'dom> {
|
|||
},
|
||||
}
|
||||
|
||||
// We are going to rebuild the box tree from the update point downward, but this update
|
||||
// point is an absolute, which means that it needs to be laid out again in the containing
|
||||
// block for absolutes, which is established by one of its ancestors. In addition,
|
||||
// absolutes, when laid out, can produce more absolutes (either fixed or absolutely
|
||||
// positioned) elements, so there may be yet more layout that has to happen in this
|
||||
// ancestor.
|
||||
//
|
||||
// We do not know which ancestor is the one that established the containing block for this
|
||||
// update point, so just invalidate the fragment cache of all ancestors, meaning that even
|
||||
// though the box tree is preserved, the fragment tree from the root to the update point and
|
||||
// all of its descendants will need to be rebuilt. This isn't as bad as it seems, because
|
||||
// siblings and siblings of ancestors of this path through the tree will still have cached
|
||||
// fragments.
|
||||
//
|
||||
// TODO: Do better. This is still a very crude way to do incremental layout.
|
||||
let mut invalidate_start_point = self.node;
|
||||
while let Some(parent_node) = invalidate_start_point.parent_node() {
|
||||
parent_node.invalidate_cached_fragment();
|
||||
|
||||
// Box tree reconstruction doesn't need to involve these ancestors, so their
|
||||
// damage isn't useful for us.
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue