style: More fine-grained viewport units invalidation

This should speed up window resize significantly.

Differential Revision: https://phabricator.services.mozilla.com/D118878
This commit is contained in:
Emilio Cobos Álvarez 2023-05-22 10:01:09 +02:00 committed by Oriol Brufau
parent 85b7a60a69
commit 25edb3c21b
6 changed files with 88 additions and 1 deletions

View file

@ -175,6 +175,25 @@ impl ElementStyles {
self.primary().get_box().clone_display().is_none() self.primary().get_box().clone_display().is_none()
} }
/// Whether this element uses viewport units.
pub fn uses_viewport_units(&self) -> bool {
use crate::computed_value_flags::ComputedValueFlags;
if self.primary().flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) {
return true;
}
for pseudo_style in self.pseudos.as_array() {
if let Some(ref pseudo_style) = pseudo_style {
if pseudo_style.flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) {
return true;
}
}
}
false
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
fn size_of_excluding_cvs(&self, _ops: &mut MallocSizeOfOps) -> usize { fn size_of_excluding_cvs(&self, _ops: &mut MallocSizeOfOps) -> usize {
// As the method name suggests, we don't measures the ComputedValues // As the method name suggests, we don't measures the ComputedValues

View file

@ -60,7 +60,12 @@ impl RestyleHint {
/// Returns whether this hint invalidates the element and all its /// Returns whether this hint invalidates the element and all its
/// descendants. /// descendants.
pub fn contains_subtree(&self) -> bool { pub fn contains_subtree(&self) -> bool {
self.contains(RestyleHint::RESTYLE_SELF | RestyleHint::RESTYLE_DESCENDANTS) self.contains(Self::restyle_subtree())
}
/// Returns whether we'll recascade all of the descendants.
pub fn will_recascade_subtree(&self) -> bool {
self.contains_subtree() || self.contains(Self::recascade_subtree())
} }
/// Returns whether we need to restyle this element. /// Returns whether we need to restyle this element.

View file

@ -7,3 +7,4 @@
pub mod element; pub mod element;
pub mod media_queries; pub mod media_queries;
pub mod stylesheets; pub mod stylesheets;
pub mod viewport_units;

View file

@ -0,0 +1,57 @@
/* 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/. */
//! Invalidates style of all elements that depend on viewport units.
use crate::dom::{TElement, TNode};
use crate::invalidation::element::restyle_hints::RestyleHint;
/// Invalidates style of all elements that depend on viewport units.
///
/// Returns whether any element was invalidated.
pub fn invalidate<E>(root: E) -> bool
where
E: TElement,
{
debug!("invalidation::viewport_units::invalidate({:?})", root);
invalidate_recursively(root)
}
fn invalidate_recursively<E>(element: E) -> bool
where
E: TElement,
{
let mut data = match element.mutate_data() {
Some(data) => data,
None => return false,
};
if data.hint.will_recascade_subtree() {
debug!("invalidate_recursively: {:?} was already invalid", element);
return false;
}
let uses_viewport_units = data.styles.uses_viewport_units();
if uses_viewport_units {
debug!("invalidate_recursively: {:?} uses viewport units", element);
data.hint.insert(RestyleHint::RECASCADE_SELF);
}
let mut any_children_invalid = false;
for child in element.traversal_children() {
if let Some(child) = child.as_element() {
any_children_invalid |= invalidate_recursively(child);
}
}
if any_children_invalid {
debug!(
"invalidate_recursively: Children of {:?} changed, setting dirty descendants",
element
);
unsafe { element.set_dirty_descendants() }
}
uses_viewport_units || any_children_invalid
}

View file

@ -101,6 +101,9 @@ bitflags! {
/// Whether there are author-specified rules for `word-spacing`. /// Whether there are author-specified rules for `word-spacing`.
const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 19; const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 19;
/// Whether the style depends on viewport units.
const USES_VIEWPORT_UNITS = 1 << 20;
} }
} }

View file

@ -5,6 +5,7 @@
//! `<length>` computed values, and related ones. //! `<length>` computed values, and related ones.
use super::{Context, Number, ToComputedValue}; use super::{Context, Number, ToComputedValue};
use crate::computed_value_flags::ComputedValueFlags;
use crate::values::animated::ToAnimatedValue; use crate::values::animated::ToAnimatedValue;
use crate::values::computed::NonNegativeNumber; use crate::values::computed::NonNegativeNumber;
use crate::values::generics::length as generics; use crate::values::generics::length as generics;
@ -36,6 +37,7 @@ impl ToComputedValue for specified::NoCalcLength {
length.to_computed_value(context, FontBaseSize::CurrentStyle) length.to_computed_value(context, FontBaseSize::CurrentStyle)
}, },
specified::NoCalcLength::ViewportPercentage(length) => { specified::NoCalcLength::ViewportPercentage(length) => {
context.builder.add_flags(ComputedValueFlags::USES_VIEWPORT_UNITS);
length.to_computed_value(context.viewport_size_for_viewport_unit_resolution()) length.to_computed_value(context.viewport_size_for_viewport_unit_resolution())
}, },
specified::NoCalcLength::ServoCharacterWidth(length) => { specified::NoCalcLength::ServoCharacterWidth(length) => {