mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
layout: Move overflow calculation to be a separate, sequential,
bottom-up pass. Right now, the only reason that overflow calculation works is that we rely on script inducing extra reflows that are sent for display. This was preventing #10021 from landing. This change regresses layout performance by about 1% in my tests. Fixes #7797 properly.
This commit is contained in:
parent
2d6283c64b
commit
5ea8c34276
7 changed files with 60 additions and 17 deletions
|
@ -16,27 +16,31 @@ bitflags! {
|
||||||
#[doc = "Currently unused; need to decide how this propagates."]
|
#[doc = "Currently unused; need to decide how this propagates."]
|
||||||
const REPAINT = 0x01,
|
const REPAINT = 0x01,
|
||||||
|
|
||||||
|
#[doc = "Recompute the overflow regions (bounding box of object and all descendants)."]
|
||||||
|
#[doc = "Propagates down the flow tree because the computation is bottom-up."]
|
||||||
|
const STORE_OVERFLOW = 0x02,
|
||||||
|
|
||||||
#[doc = "Recompute intrinsic inline_sizes (minimum and preferred)."]
|
#[doc = "Recompute intrinsic inline_sizes (minimum and preferred)."]
|
||||||
#[doc = "Propagates down the flow tree because the computation is"]
|
#[doc = "Propagates down the flow tree because the computation is"]
|
||||||
#[doc = "bottom-up."]
|
#[doc = "bottom-up."]
|
||||||
const BUBBLE_ISIZES = 0x02,
|
const BUBBLE_ISIZES = 0x04,
|
||||||
|
|
||||||
#[doc = "Recompute actual inline-sizes and block-sizes, only taking out-of-flow children \
|
#[doc = "Recompute actual inline-sizes and block-sizes, only taking out-of-flow children \
|
||||||
into account. \
|
into account. \
|
||||||
Propagates up the flow tree because the computation is top-down."]
|
Propagates up the flow tree because the computation is top-down."]
|
||||||
const REFLOW_OUT_OF_FLOW = 0x04,
|
const REFLOW_OUT_OF_FLOW = 0x08,
|
||||||
|
|
||||||
#[doc = "Recompute actual inline_sizes and block_sizes."]
|
#[doc = "Recompute actual inline_sizes and block_sizes."]
|
||||||
#[doc = "Propagates up the flow tree because the computation is"]
|
#[doc = "Propagates up the flow tree because the computation is"]
|
||||||
#[doc = "top-down."]
|
#[doc = "top-down."]
|
||||||
const REFLOW = 0x08,
|
const REFLOW = 0x10,
|
||||||
|
|
||||||
#[doc = "Re-resolve generated content. \
|
#[doc = "Re-resolve generated content. \
|
||||||
Propagates up the flow tree because the computation is inorder."]
|
Propagates up the flow tree because the computation is inorder."]
|
||||||
const RESOLVE_GENERATED_CONTENT = 0x10,
|
const RESOLVE_GENERATED_CONTENT = 0x20,
|
||||||
|
|
||||||
#[doc = "The entire flow needs to be reconstructed."]
|
#[doc = "The entire flow needs to be reconstructed."]
|
||||||
const RECONSTRUCT_FLOW = 0x20
|
const RECONSTRUCT_FLOW = 0x40
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ impl TRestyleDamage for RestyleDamage {
|
||||||
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
||||||
/// unnecessary sequential resolution of generated content.
|
/// unnecessary sequential resolution of generated content.
|
||||||
fn rebuild_and_reflow() -> RestyleDamage {
|
fn rebuild_and_reflow() -> RestyleDamage {
|
||||||
REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +70,10 @@ impl RestyleDamage {
|
||||||
/// we should add to the *parent* of this flow.
|
/// we should add to the *parent* of this flow.
|
||||||
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
|
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
|
||||||
if child_is_absolutely_positioned {
|
if child_is_absolutely_positioned {
|
||||||
self & (REPAINT | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
||||||
} else {
|
} else {
|
||||||
self & (REPAINT | REFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
self & (REPAINT | STORE_OVERFLOW | REFLOW | REFLOW_OUT_OF_FLOW |
|
||||||
|
RESOLVE_GENERATED_CONTENT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +113,7 @@ impl fmt::Display for RestyleDamage {
|
||||||
|
|
||||||
let to_iter =
|
let to_iter =
|
||||||
[ (REPAINT, "Repaint")
|
[ (REPAINT, "Repaint")
|
||||||
|
, (STORE_OVERFLOW, "StoreOverflow")
|
||||||
, (BUBBLE_ISIZES, "BubbleISizes")
|
, (BUBBLE_ISIZES, "BubbleISizes")
|
||||||
, (REFLOW_OUT_OF_FLOW, "ReflowOutOfFlow")
|
, (REFLOW_OUT_OF_FLOW, "ReflowOutOfFlow")
|
||||||
, (REFLOW, "Reflow")
|
, (REFLOW, "Reflow")
|
||||||
|
@ -165,13 +171,13 @@ pub fn compute_damage(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -
|
||||||
]);
|
]);
|
||||||
|
|
||||||
add_if_not_equal!(old, new, damage,
|
add_if_not_equal!(old, new, damage,
|
||||||
[ REPAINT, REFLOW_OUT_OF_FLOW ], [
|
[ REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW ], [
|
||||||
get_positionoffsets.top, get_positionoffsets.left,
|
get_positionoffsets.top, get_positionoffsets.left,
|
||||||
get_positionoffsets.right, get_positionoffsets.bottom
|
get_positionoffsets.right, get_positionoffsets.bottom
|
||||||
]);
|
]);
|
||||||
|
|
||||||
add_if_not_equal!(old, new, damage,
|
add_if_not_equal!(old, new, damage,
|
||||||
[ REPAINT, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW ], [
|
[ REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW ], [
|
||||||
get_border.border_top_width, get_border.border_right_width,
|
get_border.border_top_width, get_border.border_right_width,
|
||||||
get_border.border_bottom_width, get_border.border_left_width,
|
get_border.border_bottom_width, get_border.border_left_width,
|
||||||
get_margin.margin_top, get_margin.margin_right,
|
get_margin.margin_top, get_margin.margin_right,
|
||||||
|
@ -183,7 +189,14 @@ pub fn compute_damage(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -
|
||||||
]);
|
]);
|
||||||
|
|
||||||
add_if_not_equal!(old, new, damage,
|
add_if_not_equal!(old, new, damage,
|
||||||
[ REPAINT, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW, RECONSTRUCT_FLOW ], [
|
[
|
||||||
|
REPAINT,
|
||||||
|
STORE_OVERFLOW,
|
||||||
|
BUBBLE_ISIZES,
|
||||||
|
REFLOW_OUT_OF_FLOW,
|
||||||
|
REFLOW,
|
||||||
|
RECONSTRUCT_FLOW
|
||||||
|
], [
|
||||||
get_box.float, get_box.display, get_box.position, get_box.content,
|
get_box.float, get_box.display, get_box.position, get_box.content,
|
||||||
get_counters.counter_reset, get_counters.counter_increment,
|
get_counters.counter_reset, get_counters.counter_increment,
|
||||||
get_list.quotes, get_list.list_style_type,
|
get_list.quotes, get_list.list_style_type,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use app_units::Au;
|
||||||
use azure::azure::AzColor;
|
use azure::azure::AzColor;
|
||||||
use canvas_traits::CanvasMsg;
|
use canvas_traits::CanvasMsg;
|
||||||
use construct::ConstructionResult;
|
use construct::ConstructionResult;
|
||||||
use context::{SharedLayoutContext, heap_size_of_local_context};
|
use context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context};
|
||||||
use display_list_builder::ToGfxColor;
|
use display_list_builder::ToGfxColor;
|
||||||
use euclid::Matrix4;
|
use euclid::Matrix4;
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
|
@ -1336,14 +1336,23 @@ impl LayoutThread {
|
||||||
Some(ref mut parallel) => {
|
Some(ref mut parallel) => {
|
||||||
// Parallel mode.
|
// Parallel mode.
|
||||||
LayoutThread::solve_constraints_parallel(parallel,
|
LayoutThread::solve_constraints_parallel(parallel,
|
||||||
&mut root_flow,
|
&mut root_flow,
|
||||||
profiler_metadata,
|
profiler_metadata,
|
||||||
self.time_profiler_chan.clone(),
|
self.time_profiler_chan.clone(),
|
||||||
&*layout_context);
|
&*layout_context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
profile(time::ProfilerCategory::LayoutStoreOverflow,
|
||||||
|
self.profiler_metadata(),
|
||||||
|
self.time_profiler_chan.clone(),
|
||||||
|
|| {
|
||||||
|
let layout_context = LayoutContext::new(&*layout_context);
|
||||||
|
sequential::store_overflow(&layout_context,
|
||||||
|
flow_ref::deref_mut(&mut root_flow) as &mut Flow);
|
||||||
|
});
|
||||||
|
|
||||||
self.perform_post_main_layout_passes(data, rw_data, layout_context);
|
self.perform_post_main_layout_passes(data, rw_data, layout_context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use flow_ref::{self, FlowRef};
|
||||||
use fragment::FragmentBorderBoxIterator;
|
use fragment::FragmentBorderBoxIterator;
|
||||||
use generated_content::ResolveGeneratedContent;
|
use generated_content::ResolveGeneratedContent;
|
||||||
use gfx::display_list::{DisplayListEntry, StackingContext};
|
use gfx::display_list::{DisplayListEntry, StackingContext};
|
||||||
|
use incremental::STORE_OVERFLOW;
|
||||||
use style::dom::TNode;
|
use style::dom::TNode;
|
||||||
use style::traversal::DomTraversalContext;
|
use style::traversal::DomTraversalContext;
|
||||||
use traversal::{AssignBSizes, AssignISizes};
|
use traversal::{AssignBSizes, AssignISizes};
|
||||||
|
@ -117,3 +118,18 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,
|
||||||
|
|
||||||
doit(flow_ref::deref_mut(root), 0, iterator, &Point2D::zero());
|
doit(flow_ref::deref_mut(root), 0, iterator, &Point2D::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn store_overflow(layout_context: &LayoutContext, flow: &mut Flow) {
|
||||||
|
if !flow::base(flow).restyle_damage.contains(STORE_OVERFLOW) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for mut kid in flow::mut_base(flow).child_iter() {
|
||||||
|
store_overflow(layout_context, kid);
|
||||||
|
}
|
||||||
|
|
||||||
|
flow.store_overflow(layout_context);
|
||||||
|
|
||||||
|
flow::mut_base(flow).restyle_damage.remove(STORE_OVERFLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,7 +210,6 @@ impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&self, flow: &mut Flow) {
|
fn process(&self, flow: &mut Flow) {
|
||||||
flow.compute_absolute_position(self.layout_context);
|
flow.compute_absolute_position(self.layout_context);
|
||||||
flow.store_overflow(self.layout_context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ impl Formattable for ProfilerCategory {
|
||||||
ProfilerCategory::LayoutGeneratedContent |
|
ProfilerCategory::LayoutGeneratedContent |
|
||||||
ProfilerCategory::LayoutDisplayListSorting |
|
ProfilerCategory::LayoutDisplayListSorting |
|
||||||
ProfilerCategory::LayoutMain |
|
ProfilerCategory::LayoutMain |
|
||||||
|
ProfilerCategory::LayoutStoreOverflow |
|
||||||
ProfilerCategory::LayoutDispListBuild |
|
ProfilerCategory::LayoutDispListBuild |
|
||||||
ProfilerCategory::LayoutDamagePropagate |
|
ProfilerCategory::LayoutDamagePropagate |
|
||||||
ProfilerCategory::PaintingPerTile |
|
ProfilerCategory::PaintingPerTile |
|
||||||
|
@ -83,6 +84,7 @@ impl Formattable for ProfilerCategory {
|
||||||
ProfilerCategory::LayoutDisplayListSorting => "Sorting Display List",
|
ProfilerCategory::LayoutDisplayListSorting => "Sorting Display List",
|
||||||
ProfilerCategory::LayoutGeneratedContent => "Generated Content Resolution",
|
ProfilerCategory::LayoutGeneratedContent => "Generated Content Resolution",
|
||||||
ProfilerCategory::LayoutMain => "Primary Layout Pass",
|
ProfilerCategory::LayoutMain => "Primary Layout Pass",
|
||||||
|
ProfilerCategory::LayoutStoreOverflow => "Store Overflow",
|
||||||
ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup",
|
ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup",
|
||||||
ProfilerCategory::LayoutDispListBuild => "Display List Construction",
|
ProfilerCategory::LayoutDispListBuild => "Display List Construction",
|
||||||
ProfilerCategory::PaintingPerTile => "Painting Per Tile",
|
ProfilerCategory::PaintingPerTile => "Painting Per Tile",
|
||||||
|
|
|
@ -50,6 +50,7 @@ pub enum ProfilerCategory {
|
||||||
LayoutGeneratedContent,
|
LayoutGeneratedContent,
|
||||||
LayoutDisplayListSorting,
|
LayoutDisplayListSorting,
|
||||||
LayoutMain,
|
LayoutMain,
|
||||||
|
LayoutStoreOverflow,
|
||||||
LayoutParallelWarmup,
|
LayoutParallelWarmup,
|
||||||
LayoutDispListBuild,
|
LayoutDispListBuild,
|
||||||
PaintingPerTile,
|
PaintingPerTile,
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[numbers-units-018.htm]
|
||||||
|
type: reftest
|
||||||
|
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue