servo/components/shared/layout/layout_damage.rs
Martin Robinson 436c9072c4
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>
2025-07-09 17:33:09 +00:00

53 lines
1.9 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use bitflags::bitflags;
use style::selector_parser::RestyleDamage;
bitflags! {
/// Individual layout actions that may be necessary after restyling. This is an extension
/// of `RestyleDamage` from stylo, which only uses the 4 lower bits.
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct LayoutDamage: u16 {
/// Recollect the box children for this element, because some of the them will be
/// rebuilt.
const RECOLLECT_BOX_TREE_CHILDREN = 0b011111111111 << 4;
/// Rebuild the entire box for this element, which means that every part of layout
/// needs to happena again.
const REBUILD_BOX = 0b111111111111 << 4;
}
}
impl LayoutDamage {
pub fn recollect_box_tree_children() -> RestyleDamage {
RestyleDamage::from_bits_retain(LayoutDamage::RECOLLECT_BOX_TREE_CHILDREN.bits()) |
RestyleDamage::RELAYOUT
}
pub fn rebuild_box_tree() -> RestyleDamage {
RestyleDamage::from_bits_retain(LayoutDamage::REBUILD_BOX.bits()) | RestyleDamage::RELAYOUT
}
pub fn has_box_damage(&self) -> bool {
self.intersects(Self::REBUILD_BOX)
}
}
impl From<RestyleDamage> for LayoutDamage {
fn from(restyle_damage: RestyleDamage) -> Self {
LayoutDamage::from_bits_retain(restyle_damage.bits())
}
}
impl std::fmt::Debug for LayoutDamage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.contains(Self::REBUILD_BOX) {
f.write_str("REBUILD_BOX")
} else if self.contains(Self::RECOLLECT_BOX_TREE_CHILDREN) {
f.write_str("RECOLLECT_BOX_TREE_CHILDREN")
} else {
f.write_str("EMPTY")
}
}
}