mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
layout: Switch display list building from bottom-up to top-down.
This eliminates a lot of allocations and O(n^2) behavior.
This commit is contained in:
parent
f4b95dd00b
commit
d3d2dd05f2
5 changed files with 35 additions and 58 deletions
|
@ -18,7 +18,7 @@ use context::LayoutContext;
|
||||||
use euclid::num::Zero;
|
use euclid::num::Zero;
|
||||||
use euclid::{Matrix4, Point2D, Point3D, Rect, SideOffsets2D, Size2D};
|
use euclid::{Matrix4, Point2D, Point3D, Rect, SideOffsets2D, Size2D};
|
||||||
use flex::FlexFlow;
|
use flex::FlexFlow;
|
||||||
use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
||||||
use flow_ref;
|
use flow_ref;
|
||||||
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
|
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
|
||||||
use fragment::{SpecificFragmentInfo};
|
use fragment::{SpecificFragmentInfo};
|
||||||
|
@ -86,21 +86,15 @@ impl<'a> DisplayListBuildState<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_from(&mut self, other_list: &mut Option<Vec<DisplayListEntry>>) {
|
|
||||||
if let Some(mut other) = other_list.take() {
|
|
||||||
self.items.append(&mut other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stacking_context_id(&self) -> StackingContextId {
|
fn stacking_context_id(&self) -> StackingContextId {
|
||||||
self.stacking_context_id_stack.last().unwrap().clone()
|
self.stacking_context_id_stack.last().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_stacking_context_id(&mut self, stacking_context_id: StackingContextId) {
|
pub fn push_stacking_context_id(&mut self, stacking_context_id: StackingContextId) {
|
||||||
self.stacking_context_id_stack.push(stacking_context_id);
|
self.stacking_context_id_stack.push(stacking_context_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_stacking_context_id(&mut self) {
|
pub fn pop_stacking_context_id(&mut self) {
|
||||||
self.stacking_context_id_stack.pop();
|
self.stacking_context_id_stack.pop();
|
||||||
assert!(!self.stacking_context_id_stack.is_empty());
|
assert!(!self.stacking_context_id_stack.is_empty());
|
||||||
}
|
}
|
||||||
|
@ -1736,11 +1730,6 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
clip,
|
clip,
|
||||||
&self.base.stacking_relative_position_of_display_port);
|
&self.base.stacking_relative_position_of_display_port);
|
||||||
|
|
||||||
// Add children.
|
|
||||||
for kid in self.base.children.iter_mut() {
|
|
||||||
state.append_from(&mut flow::mut_base(kid).display_list_building_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
|
self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1805,22 +1794,6 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
DisplayListSection::Content,
|
DisplayListSection::Content,
|
||||||
&self.base.clip,
|
&self.base.clip,
|
||||||
&self.base.stacking_relative_position_of_display_port);
|
&self.base.stacking_relative_position_of_display_port);
|
||||||
|
|
||||||
match fragment.specific {
|
|
||||||
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
|
|
||||||
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
|
|
||||||
state.append_from(&mut flow::mut_base(block_flow).display_list_building_result)
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
|
|
||||||
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
|
|
||||||
state.append_from(&mut flow::mut_base(block_flow).display_list_building_result)
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::InlineAbsolute(ref mut block_flow) => {
|
|
||||||
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
|
|
||||||
state.append_from(&mut flow::mut_base(block_flow).display_list_building_result)
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState) {
|
fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ use floats::Floats;
|
||||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||||
use flow_ref::{self, FlowRef, WeakFlowRef};
|
use flow_ref::{self, FlowRef, WeakFlowRef};
|
||||||
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
|
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
|
||||||
use gfx::display_list::{ClippingRegion, DisplayListEntry, StackingContext, StackingContextId};
|
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
|
||||||
use gfx_traits::{LayerId, LayerType};
|
use gfx_traits::{LayerId, LayerType};
|
||||||
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||||
use inline::InlineFlow;
|
use inline::InlineFlow;
|
||||||
|
@ -957,9 +957,6 @@ pub struct BaseFlow {
|
||||||
/// per-stacking-context.
|
/// per-stacking-context.
|
||||||
pub stacking_relative_position_of_display_port: Rect<Au>,
|
pub stacking_relative_position_of_display_port: Rect<Au>,
|
||||||
|
|
||||||
/// The results of display list building for this flow.
|
|
||||||
pub display_list_building_result: Option<Vec<DisplayListEntry>>,
|
|
||||||
|
|
||||||
/// The writing mode for this flow.
|
/// The writing mode for this flow.
|
||||||
pub writing_mode: WritingMode,
|
pub writing_mode: WritingMode,
|
||||||
|
|
||||||
|
@ -1129,7 +1126,6 @@ impl BaseFlow {
|
||||||
block_container_writing_mode: writing_mode,
|
block_container_writing_mode: writing_mode,
|
||||||
block_container_explicit_block_size: None,
|
block_container_explicit_block_size: None,
|
||||||
absolute_cb: ContainingBlockLink::new(),
|
absolute_cb: ContainingBlockLink::new(),
|
||||||
display_list_building_result: None,
|
|
||||||
early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
|
early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
|
||||||
late_absolute_position_info: LateAbsolutePositionInfo::new(),
|
late_absolute_position_info: LateAbsolutePositionInfo::new(),
|
||||||
clip: ClippingRegion::max(),
|
clip: ClippingRegion::max(),
|
||||||
|
@ -1147,8 +1143,6 @@ impl BaseFlow {
|
||||||
children: children,
|
children: children,
|
||||||
restyle_damage: self.restyle_damage | REPAINT | REFLOW_OUT_OF_FLOW | REFLOW,
|
restyle_damage: self.restyle_damage | REPAINT | REFLOW_OUT_OF_FLOW | REFLOW,
|
||||||
parallel: FlowParallelInfo::new(),
|
parallel: FlowParallelInfo::new(),
|
||||||
display_list_building_result: None,
|
|
||||||
|
|
||||||
floats: self.floats.clone(),
|
floats: self.floats.clone(),
|
||||||
abs_descendants: self.abs_descendants.clone(),
|
abs_descendants: self.abs_descendants.clone(),
|
||||||
absolute_cb: self.absolute_cb.clone(),
|
absolute_cb: self.absolute_cb.clone(),
|
||||||
|
|
|
@ -875,9 +875,10 @@ impl LayoutThread {
|
||||||
false,
|
false,
|
||||||
None);
|
None);
|
||||||
|
|
||||||
sequential::build_display_list_for_subtree(layout_root,
|
let display_list_entries =
|
||||||
&mut root_stacking_context,
|
sequential::build_display_list_for_subtree(layout_root,
|
||||||
shared_layout_context);
|
&mut root_stacking_context,
|
||||||
|
shared_layout_context);
|
||||||
|
|
||||||
if data.goal == ReflowGoal::ForDisplay {
|
if data.goal == ReflowGoal::ForDisplay {
|
||||||
debug!("Done building display list.");
|
debug!("Done building display list.");
|
||||||
|
@ -900,11 +901,9 @@ impl LayoutThread {
|
||||||
ScrollPolicy::Scrollable,
|
ScrollPolicy::Scrollable,
|
||||||
None,
|
None,
|
||||||
root_background_color));
|
root_background_color));
|
||||||
let display_list = DisplayList::new(
|
|
||||||
root_stacking_context,
|
|
||||||
&mut flow::mut_base(flow_ref::deref_mut(layout_root))
|
|
||||||
.display_list_building_result);
|
|
||||||
|
|
||||||
|
let display_list = DisplayList::new(root_stacking_context,
|
||||||
|
&mut Some(display_list_entries));
|
||||||
if opts::get().dump_display_list {
|
if opts::get().dump_display_list {
|
||||||
display_list.print();
|
display_list.print();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use context::{LayoutContext, SharedLayoutContext};
|
use context::{LayoutContext, SharedLayoutContext};
|
||||||
|
use display_list_builder::DisplayListBuildState;
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
|
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
|
||||||
use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
|
use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
|
||||||
use flow_ref::{self, FlowRef};
|
use flow_ref::{self, FlowRef};
|
||||||
use fragment::FragmentBorderBoxIterator;
|
use fragment::FragmentBorderBoxIterator;
|
||||||
use generated_content::ResolveGeneratedContent;
|
use generated_content::ResolveGeneratedContent;
|
||||||
use gfx::display_list::StackingContext;
|
use gfx::display_list::{DisplayListEntry, StackingContext};
|
||||||
use style::dom::TNode;
|
use style::dom::TNode;
|
||||||
use style::traversal::DomTraversalContext;
|
use style::traversal::DomTraversalContext;
|
||||||
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
||||||
|
@ -77,13 +78,19 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
|
||||||
|
|
||||||
pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
||||||
root_stacking_context: &mut StackingContext,
|
root_stacking_context: &mut StackingContext,
|
||||||
shared_layout_context: &SharedLayoutContext) {
|
shared_layout_context: &SharedLayoutContext)
|
||||||
|
-> Vec<DisplayListEntry> {
|
||||||
let flow_root = flow_ref::deref_mut(root);
|
let flow_root = flow_ref::deref_mut(root);
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: &layout_context });
|
flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: &layout_context });
|
||||||
flow_root.collect_stacking_contexts(root_stacking_context.id,
|
flow_root.collect_stacking_contexts(root_stacking_context.id,
|
||||||
&mut root_stacking_context.children);
|
&mut root_stacking_context.children);
|
||||||
flow_root.traverse_postorder(&BuildDisplayList { layout_context: &layout_context });
|
let mut build_display_list = BuildDisplayList {
|
||||||
|
state: DisplayListBuildState::new(&layout_context,
|
||||||
|
flow::base(&**root).stacking_context_id),
|
||||||
|
};
|
||||||
|
build_display_list.traverse(&mut *flow_root);
|
||||||
|
build_display_list.state.items
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,
|
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,
|
||||||
|
|
|
@ -215,23 +215,27 @@ impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct BuildDisplayList<'a> {
|
pub struct BuildDisplayList<'a> {
|
||||||
pub layout_context: &'a LayoutContext<'a>,
|
pub state: DisplayListBuildState<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for BuildDisplayList<'a> {
|
impl<'a> BuildDisplayList<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&self, flow: &mut Flow) {
|
pub fn traverse(&mut self, flow: &mut Flow) {
|
||||||
let mut state = DisplayListBuildState::new(
|
if self.should_process() {
|
||||||
self.layout_context, flow::base(flow).stacking_context_id);
|
self.state.push_stacking_context_id(flow::base(flow).stacking_context_id);
|
||||||
flow.build_display_list(&mut state);
|
flow.build_display_list(&mut self.state);
|
||||||
flow::mut_base(flow).display_list_building_result = Some(state.items);
|
flow::mut_base(flow).restyle_damage.remove(REPAINT);
|
||||||
flow::mut_base(flow).restyle_damage.remove(REPAINT);
|
self.state.pop_stacking_context_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
for kid in flow::child_iter(flow) {
|
||||||
|
self.traverse(kid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn should_process(&self, _: &mut Flow) -> bool {
|
fn should_process(&self) -> bool {
|
||||||
self.layout_context.shared_context().goal == ReflowGoal::ForDisplay
|
self.state.layout_context.shared_context().goal == ReflowGoal::ForDisplay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue