layout: Add a REPOSITION restyle damage type.

Separating out `REPOSITION` from `REPAINT` allows us to compute
stacking-context-relative positions without rebuilding the display list.
This saves a lot of time when responding to script-to-layout queries.
This commit is contained in:
Patrick Walton 2016-09-20 16:14:54 -07:00
parent 1235f4bff6
commit 65e3db1c0d
6 changed files with 52 additions and 35 deletions

View file

@ -51,6 +51,7 @@ use model::{self, IntrinsicISizes, MarginCollapseInfo};
use model::{CollapsibleMargins, MaybeAuto, specified, specified_or_none};
use rustc_serialize::{Encodable, Encoder};
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
use script_layout_interface::restyle_damage::REPOSITION;
use std::cmp::{max, min};
use std::fmt;
use std::sync::Arc;
@ -2114,6 +2115,8 @@ impl Flow for BlockFlow {
flow::mut_base(kid).stacking_relative_position_of_display_port =
stacking_relative_position_of_display_port_for_children;
}
self.base.restyle_damage.remove(REPOSITION)
}
fn mark_as_root(&mut self) {

View file

@ -42,7 +42,8 @@ use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
use multicol::MulticolFlow;
use parallel::FlowParallelInfo;
use rustc_serialize::{Encodable, Encoder};
use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW};
use script_layout_interface::restyle_damage::{REPAINT, REPOSITION, RestyleDamage};
use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutNode};
use std::{fmt, mem, raw};
use std::iter::Zip;
@ -320,6 +321,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
/// Phase 4 of reflow: computes absolute positions.
fn compute_absolute_position(&mut self, _: &SharedLayoutContext) {
// The default implementation is a no-op.
mut_base(self).restyle_damage.remove(REPOSITION)
}
/// Phase 5 of reflow: builds display lists.

View file

@ -25,8 +25,8 @@ use gfx_traits::print_tree::PrintTree;
use layout_debug;
use model::IntrinsicISizesContribution;
use range::{Range, RangeIndex};
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW};
use script_layout_interface::restyle_damage::{REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT};
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
use script_layout_interface::restyle_damage::{REPOSITION, RESOLVE_GENERATED_CONTENT};
use script_layout_interface::wrapper_traits::PseudoElementType;
use std::{fmt, i32, isize, mem};
use std::cmp::max;
@ -1650,6 +1650,8 @@ impl Flow for InlineFlow {
_ => {}
}
}
self.base.restyle_damage.remove(REPOSITION)
}
fn update_late_computed_inline_position_if_necessary(&mut self, _: Au) {}

View file

@ -17,7 +17,7 @@ use generated_content::ResolveGeneratedContent;
use gfx::display_list::{DisplayItem, StackingContext};
use script_layout_interface::restyle_damage::{REFLOW, STORE_OVERFLOW};
use style::context::StyleContext;
use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList, ComputeAbsolutePositions};
use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList};
use util::opts;
pub use style::sequential::traverse_dom;
@ -78,7 +78,6 @@ pub fn build_display_list_for_subtree(flow_root: &mut Flow,
root_stacking_context: &mut StackingContext,
shared_layout_context: &SharedLayoutContext)
-> Vec<DisplayItem> {
flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: shared_layout_context });
let mut children = vec![];
flow_root.collect_stacking_contexts(root_stacking_context.id,
&mut children);

View file

@ -75,7 +75,7 @@ use layout::query::{process_margin_style_query, process_node_overflow_request, p
use layout::query::{process_node_geometry_request, process_node_layer_id_request, process_node_scroll_area_request};
use layout::query::process_offset_parent_query;
use layout::sequential;
use layout::traversal::RecalcStyleAndConstructFlows;
use layout::traversal::{ComputeAbsolutePositions, RecalcStyleAndConstructFlows};
use layout::webrender_helpers::{WebRenderDisplayListConverter, WebRenderFrameBuilder};
use layout::wrapper::{LayoutNodeLayoutData, NonOpaqueStyleAndLayoutData};
use layout_traits::LayoutThreadFactory;
@ -89,7 +89,8 @@ use script::layout_wrapper::{ServoLayoutDocument, ServoLayoutNode};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData};
use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow};
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, STORE_OVERFLOW};
use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION};
use script_layout_interface::restyle_damage::STORE_OVERFLOW;
use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowResponse, OffsetParentResponse};
use script_layout_interface::wrapper_traits::LayoutNode;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
@ -919,6 +920,12 @@ impl LayoutThread {
flow::mut_base(layout_root).clip =
ClippingRegion::from_rect(&data.page_clip_rect);
if flow::base(layout_root).restyle_damage.contains(REPOSITION) {
layout_root.traverse_preorder(&ComputeAbsolutePositions {
layout_context: shared_layout_context
});
}
if flow::base(layout_root).restyle_damage.contains(REPAINT) ||
rw_data.display_list.is_none() {
let mut root_stacking_context = StackingContext::new(StackingContextId::new(0),

View file

@ -15,31 +15,36 @@ bitflags! {
#[doc = "Currently unused; need to decide how this propagates."]
const REPAINT = 0x01,
#[doc = "The stacking-context-relative position of this node or its descendants has \
changed."]
#[doc = "Propagates both up and down the flow tree."]
const REPOSITION = 0x02,
#[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,
const STORE_OVERFLOW = 0x04,
#[doc = "Recompute intrinsic inline_sizes (minimum and preferred)."]
#[doc = "Propagates down the flow tree because the computation is"]
#[doc = "bottom-up."]
const BUBBLE_ISIZES = 0x04,
const BUBBLE_ISIZES = 0x08,
#[doc = "Recompute actual inline-sizes and block-sizes, only taking out-of-flow children \
into account. \
Propagates up the flow tree because the computation is top-down."]
const REFLOW_OUT_OF_FLOW = 0x08,
const REFLOW_OUT_OF_FLOW = 0x10,
#[doc = "Recompute actual inline_sizes and block_sizes."]
#[doc = "Propagates up the flow tree because the computation is"]
#[doc = "top-down."]
const REFLOW = 0x10,
const REFLOW = 0x20,
#[doc = "Re-resolve generated content. \
Propagates up the flow tree because the computation is inorder."]
const RESOLVE_GENERATED_CONTENT = 0x20,
const RESOLVE_GENERATED_CONTENT = 0x40,
#[doc = "The entire flow needs to be reconstructed."]
const RECONSTRUCT_FLOW = 0x40
const RECONSTRUCT_FLOW = 0x80
}
}
@ -63,7 +68,8 @@ impl TRestyleDamage for RestyleDamage {
/// `RestyleDamage::all()` will result in unnecessary sequential resolution
/// of generated content.
fn rebuild_and_reflow() -> RestyleDamage {
REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
REPAINT | REPOSITION | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW |
RECONSTRUCT_FLOW
}
}
@ -72,9 +78,10 @@ impl RestyleDamage {
/// returns the damage that we should add to the *parent* of this flow.
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
if child_is_absolutely_positioned {
self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
self & (REPAINT | REPOSITION | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW |
RESOLVE_GENERATED_CONTENT)
} else {
self & (REPAINT | STORE_OVERFLOW | REFLOW | REFLOW_OUT_OF_FLOW |
self & (REPAINT | REPOSITION | STORE_OVERFLOW | REFLOW | REFLOW_OUT_OF_FLOW |
RESOLVE_GENERATED_CONTENT)
}
}
@ -90,7 +97,7 @@ impl RestyleDamage {
// Absolute children are out-of-flow and therefore insulated from changes.
//
// FIXME(pcwalton): Au contraire, if the containing block dimensions change!
self & REPAINT
self & (REPAINT | REPOSITION)
}
(true, false) => {
// Changing the position of an absolutely-positioned block requires us to reflow
@ -103,7 +110,7 @@ impl RestyleDamage {
}
_ => {
// TODO(pcwalton): Take floatedness into account.
self & (REPAINT | REFLOW)
self & (REPAINT | REPOSITION | REFLOW)
}
}
}
@ -115,6 +122,7 @@ impl fmt::Display for RestyleDamage {
let to_iter =
[ (REPAINT, "Repaint")
, (REPOSITION, "Reposition")
, (STORE_OVERFLOW, "StoreOverflow")
, (BUBBLE_ISIZES, "BubbleISizes")
, (REFLOW_OUT_OF_FLOW, "ReflowOutOfFlow")
@ -163,14 +171,8 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Resty
// FIXME: Test somehow that every property is included.
add_if_not_equal!(old, new, damage,
[
REPAINT,
STORE_OVERFLOW,
BUBBLE_ISIZES,
REFLOW_OUT_OF_FLOW,
REFLOW,
RECONSTRUCT_FLOW
], [
[REPAINT, REPOSITION, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW,
REFLOW, RECONSTRUCT_FLOW], [
get_box.float, get_box.display, get_box.position, get_counters.content,
get_counters.counter_reset, get_counters.counter_increment,
get_inheritedbox._servo_under_display_none,
@ -191,8 +193,8 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Resty
get_column.column_width, get_column.column_count
]) || (new.get_box().display == display::T::inline &&
add_if_not_equal!(old, new, damage,
[REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW,
RECONSTRUCT_FLOW], [
[REPAINT, REPOSITION, STORE_OVERFLOW, BUBBLE_ISIZES,
REFLOW_OUT_OF_FLOW, REFLOW, RECONSTRUCT_FLOW], [
// For inline boxes only, border/padding styles are used in flow construction (to decide
// whether to create fragments for empty flows).
get_border.border_top_width, get_border.border_right_width,
@ -200,7 +202,8 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Resty
get_padding.padding_top, get_padding.padding_right,
get_padding.padding_bottom, get_padding.padding_left
])) || add_if_not_equal!(old, new, damage,
[ REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW ],
[REPAINT, REPOSITION, STORE_OVERFLOW, BUBBLE_ISIZES,
REFLOW_OUT_OF_FLOW, REFLOW],
[get_border.border_top_width, get_border.border_right_width,
get_border.border_bottom_width, get_border.border_left_width,
get_margin.margin_top, get_margin.margin_right,
@ -225,9 +228,12 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Resty
get_position.flex_shrink,
get_position.align_self
]) || add_if_not_equal!(old, new, damage,
[ REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW ], [
[REPAINT, REPOSITION, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW], [
get_position.top, get_position.left,
get_position.right, get_position.bottom
get_position.right, get_position.bottom,
get_effects.opacity,
get_effects.transform, get_effects.transform_style, get_effects.transform_origin,
get_effects.perspective, get_effects.perspective_origin
]) || add_if_not_equal!(old, new, damage,
[REPAINT], [
get_color.color, get_background.background_color,
@ -245,9 +251,7 @@ fn compute_damage(old: &ServoComputedValues, new: &ServoComputedValues) -> Resty
get_inheritedtext._servo_text_decorations_in_effect,
get_pointing.cursor, get_pointing.pointer_events,
get_effects.box_shadow, get_effects.clip, get_inheritedtext.text_shadow, get_effects.filter,
get_effects.transform, get_effects.backface_visibility, get_effects.transform_style,
get_effects.transform_origin, get_effects.perspective, get_effects.perspective_origin,
get_effects.mix_blend_mode, get_effects.opacity, get_inheritedbox.image_rendering,
get_effects.mix_blend_mode, get_inheritedbox.image_rendering,
// Note: May require REFLOW et al. if `visibility: collapse` is implemented.
get_inheritedbox.visibility