layout: Support inline incremental reflow, and stop reconstructing all

flows when mousing over the document.

This exposes more "jumpiness" on sites like Hacker News, but the bug
that causes it was pre-existing.
This commit is contained in:
Patrick Walton 2015-05-18 12:22:17 -07:00
parent 90aacf00f8
commit 72f031e2a1
6 changed files with 57 additions and 44 deletions

View file

@ -1250,22 +1250,28 @@ impl<'a> FlowConstructor<'a> {
return false return false
} }
match node.swap_out_construction_result() { let mut layout_data_ref = node.mutate_layout_data();
ConstructionResult::None => true, let layout_data = layout_data_ref.as_mut().expect("no layout data");
ConstructionResult::Flow(mut flow, _) => { let style = (*node.get_style(&layout_data)).clone();
let damage = layout_data.data.restyle_damage;
match node.get_construction_result(layout_data) {
&mut ConstructionResult::None => true,
&mut ConstructionResult::Flow(ref mut flow, _) => {
// The node's flow is of the same type and has the same set of children and can // The node's flow is of the same type and has the same set of children and can
// therefore be repaired by simply propagating damage and style to the flow. // therefore be repaired by simply propagating damage and style to the flow.
flow::mut_base(&mut *flow).restyle_damage.insert(node.restyle_damage()); if !flow.is_block_flow() {
flow.repair_style_and_bubble_inline_sizes(node.style()); return false
}
flow::mut_base(&mut **flow).restyle_damage.insert(damage);
flow.repair_style_and_bubble_inline_sizes(&style);
true true
} }
ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( &mut ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments(
mut inline_fragments_construction_result)) => { ref mut inline_fragments_construction_result)) => {
if !inline_fragments_construction_result.splits.is_empty() { if !inline_fragments_construction_result.splits.is_empty() {
return false return false
} }
let damage = node.restyle_damage();
for fragment in inline_fragments_construction_result.fragments for fragment in inline_fragments_construction_result.fragments
.fragments .fragments
.iter_mut() { .iter_mut() {
@ -1274,17 +1280,34 @@ impl<'a> FlowConstructor<'a> {
flow::mut_base(&mut *inline_block_fragment.flow_ref).restyle_damage flow::mut_base(&mut *inline_block_fragment.flow_ref).restyle_damage
.insert(damage); .insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
inline_block_fragment.flow_ref.repair_style_and_bubble_inline_sizes( inline_block_fragment.flow_ref
node.style()); .repair_style_and_bubble_inline_sizes(&style);
}
SpecificFragmentInfo::InlineAbsoluteHypothetical(
ref mut inline_absolute_hypothetical_fragment) => {
flow::mut_base(&mut *inline_absolute_hypothetical_fragment.flow_ref)
.restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too?
inline_absolute_hypothetical_fragment
.flow_ref
.repair_style_and_bubble_inline_sizes(&style);
}
SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => {
flow::mut_base(&mut *inline_absolute_fragment.flow_ref).restyle_damage
.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too?
inline_absolute_fragment.flow_ref
.repair_style_and_bubble_inline_sizes(&style);
} }
_ => { _ => {
return false fragment.repair_style(&style);
return true
} }
} }
} }
true true
} }
ConstructionResult::ConstructionItem(_) => { &mut ConstructionResult::ConstructionItem(_) => {
false false
} }
} }
@ -1450,7 +1473,8 @@ trait NodeUtils {
/// Returns true if this node doesn't render its kids and false otherwise. /// Returns true if this node doesn't render its kids and false otherwise.
fn is_replaced_content(&self) -> bool; fn is_replaced_content(&self) -> bool;
fn get_construction_result<'a>(self, layout_data: &'a mut LayoutDataWrapper) -> &'a mut ConstructionResult; fn get_construction_result<'a>(self, layout_data: &'a mut LayoutDataWrapper)
-> &'a mut ConstructionResult;
/// Sets the construction result of a flow. /// Sets the construction result of a flow.
fn set_flow_construction_result(self, result: ConstructionResult); fn set_flow_construction_result(self, result: ConstructionResult);

View file

@ -4,6 +4,7 @@
//! Style retrieval from DOM elements. //! Style retrieval from DOM elements.
use data::LayoutDataWrapper;
use wrapper::{PseudoElementType, ThreadSafeLayoutNode}; use wrapper::{PseudoElementType, ThreadSafeLayoutNode};
use std::mem; use std::mem;
@ -12,6 +13,7 @@ use std::sync::Arc;
/// Node mixin providing `style` method that returns a `NodeStyle` /// Node mixin providing `style` method that returns a `NodeStyle`
pub trait StyledNode { pub trait StyledNode {
fn get_style<'a>(&'a self, layout_data_ref: &'a LayoutDataWrapper) -> &'a Arc<ComputedValues>;
/// Returns the style results for the given node. If CSS selector matching has not yet been /// Returns the style results for the given node. If CSS selector matching has not yet been
/// performed, fails. /// performed, fails.
fn style<'a>(&'a self) -> &'a Arc<ComputedValues>; fn style<'a>(&'a self) -> &'a Arc<ComputedValues>;
@ -22,37 +24,23 @@ pub trait StyledNode {
} }
impl<'ln> StyledNode for ThreadSafeLayoutNode<'ln> { impl<'ln> StyledNode for ThreadSafeLayoutNode<'ln> {
#[inline]
fn get_style<'a>(&self, layout_data_ref: &'a LayoutDataWrapper) -> &'a Arc<ComputedValues> {
match self.get_pseudo_element_type() {
PseudoElementType::Before(_) => layout_data_ref.data.before_style.as_ref().unwrap(),
PseudoElementType::After(_) => layout_data_ref.data.after_style.as_ref().unwrap(),
PseudoElementType::Normal => layout_data_ref.shared_data.style.as_ref().unwrap(),
}
}
#[inline] #[inline]
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn style<'a>(&'a self) -> &'a Arc<ComputedValues> { fn style<'a>(&'a self) -> &'a Arc<ComputedValues> {
unsafe { unsafe {
let layout_data_ref = self.borrow_layout_data(); let layout_data_ref = self.borrow_layout_data();
match self.get_pseudo_element_type() { let layout_data = layout_data_ref.as_ref().expect("no layout data");
PseudoElementType::Before(_) => { mem::transmute::<&Arc<ComputedValues>,
mem::transmute(layout_data_ref.as_ref() &'a Arc<ComputedValues>>(self.get_style(&layout_data))
.unwrap()
.data
.before_style
.as_ref()
.unwrap())
}
PseudoElementType::After(_) => {
mem::transmute(layout_data_ref.as_ref()
.unwrap()
.data
.after_style
.as_ref()
.unwrap())
}
PseudoElementType::Normal => {
mem::transmute(layout_data_ref.as_ref()
.unwrap()
.shared_data
.style
.as_ref()
.unwrap())
}
}
} }
} }

View file

@ -184,7 +184,6 @@ pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -
[ get_box.float, get_box.display, get_box.position ]); [ get_box.float, get_box.display, get_box.position ]);
// FIXME: test somehow that we checked every CSS property // FIXME: test somehow that we checked every CSS property
damage damage
} }

View file

@ -887,7 +887,8 @@ impl LayoutTask {
// let the constellation know about the viewport constraints // let the constellation know about the viewport constraints
let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan;
constellation_chan.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); constellation_chan.send(ConstellationMsg::ViewportConstrained(
self.id, constraints)).unwrap();
} }
} }
@ -1074,6 +1075,7 @@ impl LayoutTask {
} }
fn reflow_all_nodes(flow: &mut Flow) { fn reflow_all_nodes(flow: &mut Flow) {
debug!("reflowing all nodes!");
flow::mut_base(flow).restyle_damage.insert(REFLOW | REPAINT); flow::mut_base(flow).restyle_damage.insert(REFLOW | REPAINT);
for child in flow::child_iter(flow) { for child in flow::child_iter(flow) {

View file

@ -170,7 +170,7 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> {
&some_bf, &some_bf,
&mut applicable_declarations, &mut applicable_declarations,
&mut shareable); &mut shareable);
} else { } else if node.has_changed() {
ThreadSafeLayoutNode::new(&node).set_restyle_damage( ThreadSafeLayoutNode::new(&node).set_restyle_damage(
incremental::rebuild_and_reflow()) incremental::rebuild_and_reflow())
} }

View file

@ -629,7 +629,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn set_hover_state(self, state: bool) { fn set_hover_state(self, state: bool) {
self.set_flag(IN_HOVER_STATE, state); self.set_flag(IN_HOVER_STATE, state);
self.dirty(NodeDamage::OtherNodeDamage); self.dirty(NodeDamage::NodeStyleDamaged);
} }
fn get_focus_state(self) -> bool { fn get_focus_state(self) -> bool {
@ -638,7 +638,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
fn set_focus_state(self, state: bool) { fn set_focus_state(self, state: bool) {
self.set_flag(IN_FOCUS_STATE, state); self.set_flag(IN_FOCUS_STATE, state);
self.dirty(NodeDamage::OtherNodeDamage); self.dirty(NodeDamage::NodeStyleDamaged);
} }
fn get_disabled_state(self) -> bool { fn get_disabled_state(self) -> bool {