Introduce a concept of restyle damage to the style system.

We can't hoist RestyleDamage itself, because it's very layout-dependent. But this
should be enough to let us hoist the things we need.
This commit is contained in:
Bobby Holley 2015-12-31 11:45:32 -08:00
parent 947134949a
commit 27987c3bb4
7 changed files with 61 additions and 31 deletions

View file

@ -35,7 +35,7 @@ use flow_ref::{self, FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use gfx::display_list::{ClippingRegion, DisplayList};
use gfx_traits::LayerId;
use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
use inline::InlineFlow;
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
use msg::compositor_msg::LayerType;
@ -48,6 +48,7 @@ use std::sync::Arc;
use std::sync::atomic::Ordering;
use std::{fmt, mem, raw};
use style::computed_values::{clear, display, empty_cells, float, position, text_align};
use style::dom::TRestyleDamage;
use style::properties::{self, ComputedValues};
use style::values::computed::LengthOrPercentageOrAuto;
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow};
@ -1046,7 +1047,7 @@ impl BaseFlow {
}
// New flows start out as fully damaged.
let mut damage = incremental::rebuild_and_reflow();
let mut damage = RestyleDamage::rebuild_and_reflow();
damage.remove(RECONSTRUCT_FLOW);
BaseFlow {

View file

@ -18,7 +18,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::CharIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use gfx_traits::LayerId;
use incremental::{self, RECONSTRUCT_FLOW, RestyleDamage};
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc::IpcSender;
@ -40,6 +40,7 @@ use style::computed_values::content::ContentItem;
use style::computed_values::{border_collapse, clear, display, mix_blend_mode, overflow_wrap};
use style::computed_values::{overflow_x, position, text_decoration, transform_style};
use style::computed_values::{white_space, word_break, z_index};
use style::dom::TRestyleDamage;
use style::properties::ComputedValues;
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{LengthOrPercentageOrNone};
@ -833,7 +834,7 @@ impl Fragment {
self.border_box.start,
size);
let mut restyle_damage = incremental::rebuild_and_reflow();
let mut restyle_damage = RestyleDamage::rebuild_and_reflow();
restyle_damage.remove(RECONSTRUCT_FLOW);
Fragment {

View file

@ -13,12 +13,13 @@ use flow::{InorderFlowTraversal};
use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils};
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
use gfx::display_list::OpaqueNode;
use incremental::{self, RESOLVE_GENERATED_CONTENT};
use incremental::{RESOLVE_GENERATED_CONTENT, RestyleDamage};
use smallvec::SmallVec;
use std::collections::{HashMap, LinkedList};
use std::sync::Arc;
use style::computed_values::content::ContentItem;
use style::computed_values::{display, list_style_type};
use style::dom::TRestyleDamage;
use style::properties::ComputedValues;
use text::TextRunScanner;
use wrapper::PseudoElementType;
@ -431,7 +432,7 @@ fn render_text(layout_context: &LayoutContext,
fragments.push_back(Fragment::from_opaque_node_and_style(node,
pseudo,
style,
incremental::rebuild_and_reflow(),
RestyleDamage::rebuild_and_reflow(),
info));
// FIXME(pcwalton): This should properly handle multiple marker fragments. This could happen
// due to text run splitting.

View file

@ -6,6 +6,7 @@ use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, IS_ABSO
use std::fmt;
use std::sync::Arc;
use style::computed_values::float;
use style::dom::TRestyleDamage;
use style::properties::ComputedValues;
bitflags! {
@ -47,6 +48,18 @@ bitflags! {
}
}
impl TRestyleDamage for RestyleDamage {
fn compute(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage { compute_damage(old, new) }
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
///
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
/// unnecessary sequential resolution of generated content.
fn rebuild_and_reflow() -> RestyleDamage {
REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
}
}
impl RestyleDamage {
/// Supposing a flow has the given `position` property and this damage, returns the damage that
@ -130,18 +143,10 @@ macro_rules! add_if_not_equal(
})
);
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
///
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
/// unnecessary sequential resolution of generated content.
pub fn rebuild_and_reflow() -> RestyleDamage {
REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
}
pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage {
let old: &ComputedValues =
match old.as_ref() {
None => return rebuild_and_reflow(),
None => return RestyleDamage::rebuild_and_reflow(),
Some(cv) => &**cv,
};
@ -195,7 +200,7 @@ pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -
// If the layer requirements of this flow have changed due to the value
// of the transform, then reflow is required to rebuild the layers.
if old.transform_requires_layer() != new.transform_requires_layer() {
damage.insert(rebuild_and_reflow());
damage.insert(RestyleDamage::rebuild_and_reflow());
}
// FIXME: test somehow that we checked every CSS property
@ -256,7 +261,7 @@ impl<'a> LayoutDamageComputation for &'a mut Flow {
fn reflow_entire_document(self) {
let self_base = flow::mut_base(self);
self_base.restyle_damage.insert(rebuild_and_reflow());
self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow());
self_base.restyle_damage.remove(RECONSTRUCT_FLOW);
for kid in self_base.children.iter_mut() {
kid.reflow_entire_document();

View file

@ -10,13 +10,13 @@ use css::matching::{ElementMatchMethods, MatchMethods, StyleSharingResult};
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
use flow::{self, Flow};
use gfx::display_list::OpaqueNode;
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use script::layout_interface::ReflowGoal;
use selectors::bloom::BloomFilter;
use std::cell::RefCell;
use std::mem;
use style::context::StyleContext;
use style::dom::UnsafeNode;
use style::dom::{TRestyleDamage, UnsafeNode};
use style::matching::ApplicableDeclarations;
use util::opts;
use util::tid::tid;
@ -209,8 +209,7 @@ fn recalc_style_at<'a, 'ln, N: LayoutNode<'ln>> (context: &'a DomTraversalContex
},
None => {
if node.has_changed() {
node.to_threadsafe().set_restyle_damage(
incremental::rebuild_and_reflow())
node.set_restyle_damage(N::ConcreteRestyleDamage::rebuild_and_reflow())
}
None
},

View file

@ -132,6 +132,7 @@ impl<'ln> ServoLayoutNode<'ln> {
impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> {
type ConcreteElement = ServoLayoutElement<'ln>;
type ConcreteDocument = ServoLayoutDocument<'ln>;
type ConcreteRestyleDamage = RestyleDamage;
fn to_unsafe(&self) -> UnsafeNode {
unsafe {
@ -237,6 +238,14 @@ impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> {
unsafe { self.mutate_layout_data().map(|d| transmute(d)) }
}
fn restyle_damage(self) -> RestyleDamage {
self.borrow_layout_data().unwrap().restyle_damage
}
fn set_restyle_damage(self, damage: RestyleDamage) {
self.mutate_layout_data().unwrap().restyle_damage = damage;
}
fn parent_node(&self) -> Option<ServoLayoutNode<'ln>> {
unsafe {
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
@ -714,16 +723,9 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized {
fn is_ignorable_whitespace(&self) -> bool;
/// Get the description of how to account for recent style changes.
/// This is a simple bitfield and fine to copy by value.
fn restyle_damage(self) -> RestyleDamage {
self.borrow_layout_data().unwrap().restyle_damage
}
fn restyle_damage(self) -> RestyleDamage;
/// Set the restyle damage field.
fn set_restyle_damage(self, damage: RestyleDamage) {
self.mutate_layout_data().unwrap().restyle_damage = damage;
}
fn set_restyle_damage(self, damage: RestyleDamage);
/// Returns the layout data flags for this node.
fn flags(self) -> LayoutDataFlags;
@ -909,6 +911,14 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> {
}
}
fn restyle_damage(self) -> RestyleDamage {
self.node.restyle_damage()
}
fn set_restyle_damage(self, damage: RestyleDamage) {
self.node.set_restyle_damage(damage)
}
fn flags(self) -> LayoutDataFlags {
unsafe {
(*self.node.borrow_layout_data_unchecked().unwrap()).flags

View file

@ -5,13 +5,15 @@
#![allow(unsafe_code)]
use data::PrivateStyleData;
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
use properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use selectors::matching::DeclarationBlock;
use selectors::states::ElementState;
use smallvec::VecLike;
use std::cell::{Ref, RefMut};
use std::marker::PhantomData;
use std::ops::BitOr;
use std::sync::Arc;
use string_cache::{Atom, Namespace};
/// Opaque type stored in type-unsafe work queues for parallel layout.
@ -39,10 +41,15 @@ impl OpaqueNode {
}
}
pub trait TRestyleDamage : BitOr<Output=Self> + Copy {
fn compute(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> Self;
fn rebuild_and_reflow() -> Self;
}
pub trait TNode<'ln> : Sized + Copy + Clone {
type ConcreteElement: TElement<'ln, ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>;
type ConcreteDocument: TDocument<'ln, ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>;
type ConcreteRestyleDamage: TRestyleDamage;
fn to_unsafe(&self) -> UnsafeNode;
unsafe fn from_unsafe(n: &UnsafeNode) -> Self;
@ -134,6 +141,12 @@ pub trait TNode<'ln> : Sized + Copy + Clone {
#[inline(always)]
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>>;
/// Get the description of how to account for recent style changes.
fn restyle_damage(self) -> Self::ConcreteRestyleDamage;
/// Set the restyle damage field.
fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage);
fn parent_node(&self) -> Option<Self>;
fn first_child(&self) -> Option<Self>;