mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
layout: When there is no restyle damage, do not re-layout (#37048)
When the computed restyle damage is empty, do not do a layout. Instead, just rebuild the display list. In the future, even that can be omitted, but that requires changes to the compositor. These kind of relayouts commonly happen when the cursor is moving around the page and no style rules cause changes to :hover. Testing: This is covered existing WPT tests and should only have performance impacts. Unfortunately there are currently no performance tests. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
859a0ffbd5
commit
856ffa6ecb
6 changed files with 47 additions and 9 deletions
|
@ -773,7 +773,7 @@ impl LayoutThread {
|
|||
|
||||
let root_node = root_element.as_node();
|
||||
let damage = compute_damage_and_repair_style(layout_context.shared_context(), root_node);
|
||||
if damage == RestyleDamage::REPAINT {
|
||||
if damage.is_empty() || damage == RestyleDamage::REPAINT {
|
||||
layout_context.style_context.stylist.rule_tree().maybe_gc();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,9 @@ pub(crate) fn compute_damage_and_repair_style_inner(
|
|||
parent_restyle_damage: RestyleDamage,
|
||||
) -> RestyleDamage {
|
||||
let original_damage;
|
||||
let damage = {
|
||||
let damage;
|
||||
|
||||
{
|
||||
let mut element_data = node
|
||||
.style_data()
|
||||
.expect("Should not run `compute_damage` before styling.")
|
||||
|
@ -113,14 +115,14 @@ pub(crate) fn compute_damage_and_repair_style_inner(
|
|||
.borrow_mut();
|
||||
|
||||
original_damage = std::mem::take(&mut element_data.damage);
|
||||
damage = original_damage | parent_restyle_damage;
|
||||
|
||||
if let Some(ref style) = element_data.styles.primary {
|
||||
if style.get_box().display == Display::None {
|
||||
return parent_restyle_damage;
|
||||
return damage;
|
||||
}
|
||||
}
|
||||
|
||||
original_damage | parent_restyle_damage
|
||||
};
|
||||
}
|
||||
|
||||
let mut propagated_damage = damage;
|
||||
for child in iter_child_nodes(node) {
|
||||
|
|
|
@ -27,6 +27,7 @@ use servo_media::streams::registry::MediaStreamId;
|
|||
use snapshot::Snapshot;
|
||||
use style::attr::AttrValue;
|
||||
|
||||
use super::node::NodeDamage;
|
||||
pub(crate) use crate::canvas_context::*;
|
||||
use crate::conversions::Convert;
|
||||
use crate::dom::attr::Attr;
|
||||
|
@ -687,8 +688,11 @@ impl VirtualMethods for HTMLCanvasElement {
|
|||
.unwrap()
|
||||
.attribute_mutated(attr, mutation, can_gc);
|
||||
match attr.local_name() {
|
||||
&local_name!("width") | &local_name!("height") => self.recreate_contexts_after_resize(),
|
||||
_ => (),
|
||||
&local_name!("width") | &local_name!("height") => {
|
||||
self.recreate_contexts_after_resize();
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -520,6 +520,7 @@ impl HTMLInputElement {
|
|||
let mut value = textinput.single_line_content().clone();
|
||||
self.sanitize_value(&mut value);
|
||||
textinput.set_content(value);
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
|
||||
fn does_minmaxlength_apply(&self) -> bool {
|
||||
|
@ -2668,6 +2669,7 @@ impl VirtualMethods for HTMLInputElement {
|
|||
let mut value = textinput.single_line_content().clone();
|
||||
self.sanitize_value(&mut value);
|
||||
textinput.set_content(value);
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
|
||||
// Steps 7-9
|
||||
if !previously_selectable && self.selection_api_applies() {
|
||||
|
@ -2695,6 +2697,8 @@ impl VirtualMethods for HTMLInputElement {
|
|||
self.sanitize_value(&mut value);
|
||||
self.textinput.borrow_mut().set_content(value);
|
||||
self.update_placeholder_shown_state();
|
||||
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
},
|
||||
local_name!("name") if self.input_type() == InputType::Radio => {
|
||||
self.radio_group_updated(
|
||||
|
|
|
@ -9,6 +9,9 @@ use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
|||
use style::color::AbsoluteColor;
|
||||
use style::context::QuirksMode;
|
||||
|
||||
use super::attr::Attr;
|
||||
use super::element::AttributeMutation;
|
||||
use super::node::NodeDamage;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLTableCellElementBinding::HTMLTableCellElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
|
@ -174,6 +177,19 @@ impl VirtualMethods for HTMLTableCellElement {
|
|||
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
|
||||
}
|
||||
|
||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
|
||||
if let Some(super_type) = self.super_type() {
|
||||
super_type.attribute_mutated(attr, mutation, can_gc);
|
||||
}
|
||||
|
||||
if matches!(*attr.local_name(), local_name!("colspan")) {
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
if matches!(*attr.local_name(), local_name!("rowspan")) {
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_plain_attribute(&self, local_name: &LocalName, value: DOMString) -> AttrValue {
|
||||
match *local_name {
|
||||
local_name!("colspan") => {
|
||||
|
|
|
@ -7,8 +7,10 @@ use html5ever::{LocalName, Prefix, local_name, ns};
|
|||
use js::rust::HandleObject;
|
||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||
|
||||
use super::attr::Attr;
|
||||
use super::bindings::root::LayoutDom;
|
||||
use super::element::Element;
|
||||
use super::element::{AttributeMutation, Element};
|
||||
use super::node::NodeDamage;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLTableColElementBinding::HTMLTableColElementMethods;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
|
@ -93,6 +95,16 @@ impl VirtualMethods for HTMLTableColElement {
|
|||
Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
|
||||
}
|
||||
|
||||
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
|
||||
if let Some(super_type) = self.super_type() {
|
||||
super_type.attribute_mutated(attr, mutation, can_gc);
|
||||
}
|
||||
|
||||
if matches!(*attr.local_name(), local_name!("span")) {
|
||||
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_plain_attribute(&self, local_name: &LocalName, value: DOMString) -> AttrValue {
|
||||
match *local_name {
|
||||
local_name!("span") => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue