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::{Matrix4, Point2D, Point3D, Rect, SideOffsets2D, Size2D};
|
||||
use flex::FlexFlow;
|
||||
use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
||||
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
||||
use flow_ref;
|
||||
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
fn pop_stacking_context_id(&mut self) {
|
||||
pub fn pop_stacking_context_id(&mut self) {
|
||||
self.stacking_context_id_stack.pop();
|
||||
assert!(!self.stacking_context_id_stack.is_empty());
|
||||
}
|
||||
|
@ -1736,11 +1730,6 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
clip,
|
||||
&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);
|
||||
}
|
||||
}
|
||||
|
@ -1805,22 +1794,6 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
DisplayListSection::Content,
|
||||
&self.base.clip,
|
||||
&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) {
|
||||
|
|
|
@ -34,7 +34,7 @@ use floats::Floats;
|
|||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||
use flow_ref::{self, FlowRef, WeakFlowRef};
|
||||
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 incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||
use inline::InlineFlow;
|
||||
|
@ -957,9 +957,6 @@ pub struct BaseFlow {
|
|||
/// per-stacking-context.
|
||||
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.
|
||||
pub writing_mode: WritingMode,
|
||||
|
||||
|
@ -1129,7 +1126,6 @@ impl BaseFlow {
|
|||
block_container_writing_mode: writing_mode,
|
||||
block_container_explicit_block_size: None,
|
||||
absolute_cb: ContainingBlockLink::new(),
|
||||
display_list_building_result: None,
|
||||
early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
|
||||
late_absolute_position_info: LateAbsolutePositionInfo::new(),
|
||||
clip: ClippingRegion::max(),
|
||||
|
@ -1147,8 +1143,6 @@ impl BaseFlow {
|
|||
children: children,
|
||||
restyle_damage: self.restyle_damage | REPAINT | REFLOW_OUT_OF_FLOW | REFLOW,
|
||||
parallel: FlowParallelInfo::new(),
|
||||
display_list_building_result: None,
|
||||
|
||||
floats: self.floats.clone(),
|
||||
abs_descendants: self.abs_descendants.clone(),
|
||||
absolute_cb: self.absolute_cb.clone(),
|
||||
|
|
|
@ -875,6 +875,7 @@ impl LayoutThread {
|
|||
false,
|
||||
None);
|
||||
|
||||
let display_list_entries =
|
||||
sequential::build_display_list_for_subtree(layout_root,
|
||||
&mut root_stacking_context,
|
||||
shared_layout_context);
|
||||
|
@ -900,11 +901,9 @@ impl LayoutThread {
|
|||
ScrollPolicy::Scrollable,
|
||||
None,
|
||||
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 {
|
||||
display_list.print();
|
||||
}
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
use app_units::Au;
|
||||
use context::{LayoutContext, SharedLayoutContext};
|
||||
use display_list_builder::DisplayListBuildState;
|
||||
use euclid::point::Point2D;
|
||||
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
|
||||
use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
|
||||
use flow_ref::{self, FlowRef};
|
||||
use fragment::FragmentBorderBoxIterator;
|
||||
use generated_content::ResolveGeneratedContent;
|
||||
use gfx::display_list::StackingContext;
|
||||
use gfx::display_list::{DisplayListEntry, StackingContext};
|
||||
use style::dom::TNode;
|
||||
use style::traversal::DomTraversalContext;
|
||||
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,
|
||||
root_stacking_context: &mut StackingContext,
|
||||
shared_layout_context: &SharedLayoutContext) {
|
||||
shared_layout_context: &SharedLayoutContext)
|
||||
-> Vec<DisplayListEntry> {
|
||||
let flow_root = flow_ref::deref_mut(root);
|
||||
let layout_context = LayoutContext::new(shared_layout_context);
|
||||
flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: &layout_context });
|
||||
flow_root.collect_stacking_contexts(root_stacking_context.id,
|
||||
&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,
|
||||
|
|
|
@ -215,23 +215,27 @@ impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
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]
|
||||
fn process(&self, flow: &mut Flow) {
|
||||
let mut state = DisplayListBuildState::new(
|
||||
self.layout_context, flow::base(flow).stacking_context_id);
|
||||
flow.build_display_list(&mut state);
|
||||
flow::mut_base(flow).display_list_building_result = Some(state.items);
|
||||
pub fn traverse(&mut self, flow: &mut Flow) {
|
||||
if self.should_process() {
|
||||
self.state.push_stacking_context_id(flow::base(flow).stacking_context_id);
|
||||
flow.build_display_list(&mut self.state);
|
||||
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]
|
||||
fn should_process(&self, _: &mut Flow) -> bool {
|
||||
self.layout_context.shared_context().goal == ReflowGoal::ForDisplay
|
||||
fn should_process(&self) -> bool {
|
||||
self.state.layout_context.shared_context().goal == ReflowGoal::ForDisplay
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue