aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2015-05-13 17:13:59 -0700
committerPatrick Walton <pcwalton@mimiga.net>2015-05-19 16:53:51 -0700
commit6a197719b30a5731b168b4ca5b6351f3d487d651 (patch)
tree96e5d1f6f3be89512dabbe055e03cf2409b116a7 /components/layout
parentacb9824229bf9e02eaabdb9d924f7db242a1ac85 (diff)
downloadservo-6a197719b30a5731b168b4ca5b6351f3d487d651.tar.gz
servo-6a197719b30a5731b168b4ca5b6351f3d487d651.zip
compositing: Implement display ports and avoid creating display lists
for items outside it. This improves Servo's performance on large pages.
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/block.rs63
-rw-r--r--components/layout/context.rs7
-rw-r--r--components/layout/display_list_builder.rs36
-rw-r--r--components/layout/flow.rs25
-rw-r--r--components/layout/inline.rs14
-rw-r--r--components/layout/layout_task.rs94
-rw-r--r--components/layout/list_item.rs4
-rw-r--r--components/layout/multicol.rs4
-rw-r--r--components/layout/table.rs4
-rw-r--r--components/layout/table_caption.rs8
-rw-r--r--components/layout/table_cell.rs8
-rw-r--r--components/layout/table_row.rs4
-rw-r--r--components/layout/table_rowgroup.rs4
-rw-r--r--components/layout/table_wrapper.rs4
-rw-r--r--components/layout/traversal.rs2
15 files changed, 224 insertions, 57 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index c77c9266345..dccee7cfe27 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -43,6 +43,7 @@ use flow::{CLEARS_LEFT, CLEARS_RIGHT};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
+use layout_task::DISPLAY_PORT_SIZE_FACTOR;
use model::{IntrinsicISizes, MarginCollapseInfo};
use model::{MaybeAuto, CollapsibleMargins, specified, specified_or_none};
use wrapper::ThreadSafeLayoutNode;
@@ -59,7 +60,7 @@ use style::computed_values::{position, text_align};
use style::properties::ComputedValues;
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{LengthOrPercentageOrNone};
-use util::geometry::{Au, MAX_AU};
+use util::geometry::{Au, MAX_AU, MAX_RECT};
use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
use util::opts;
@@ -377,7 +378,9 @@ impl Iterator for CandidateBSizeIterator {
Some(max_block_size) if self.candidate_value > max_block_size => {
CandidateBSizeIteratorStatus::TryingMax
}
- _ if self.candidate_value < self.min_block_size => CandidateBSizeIteratorStatus::TryingMin,
+ _ if self.candidate_value < self.min_block_size => {
+ CandidateBSizeIteratorStatus::TryingMin
+ }
_ => CandidateBSizeIteratorStatus::Found,
}
}
@@ -718,13 +721,16 @@ impl BlockFlow {
return
}
- let (block_start_margin_value, block_end_margin_value) = match self.base.collapsible_margins {
- CollapsibleMargins::CollapseThrough(_) => panic!("Margins unexpectedly collapsed through root flow."),
- CollapsibleMargins::Collapse(block_start_margin, block_end_margin) => {
- (block_start_margin.collapse(), block_end_margin.collapse())
- }
- CollapsibleMargins::None(block_start, block_end) => (block_start, block_end),
- };
+ let (block_start_margin_value, block_end_margin_value) =
+ match self.base.collapsible_margins {
+ CollapsibleMargins::CollapseThrough(_) => {
+ panic!("Margins unexpectedly collapsed through root flow.")
+ }
+ CollapsibleMargins::Collapse(block_start_margin, block_end_margin) => {
+ (block_start_margin.collapse(), block_end_margin.collapse())
+ }
+ CollapsibleMargins::None(block_start, block_end) => (block_start, block_end),
+ };
// Shift all kids down (or up, if margins are negative) if necessary.
if block_start_margin_value != Au(0) {
@@ -757,7 +763,8 @@ impl BlockFlow {
pub fn assign_block_size_block_base<'a>(&mut self,
layout_context: &'a LayoutContext<'a>,
margins_may_collapse: MarginsMayCollapseFlag) {
- let _scope = layout_debug_scope!("assign_block_size_block_base {:x}", self.base.debug_id());
+ let _scope = layout_debug_scope!("assign_block_size_block_base {:x}",
+ self.base.debug_id());
if self.base.restyle_damage.contains(REFLOW) {
// Our current border-box position.
@@ -1661,13 +1668,14 @@ impl Flow for BlockFlow {
}
}
- fn compute_absolute_position(&mut self) {
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
// FIXME (mbrubeck): Get the real container size, taking the container writing mode into
// account. Must handle vertical writing modes.
let container_size = Size2D(self.base.block_container_inline_size, Au(0));
if self.is_root() {
- self.base.clip = ClippingRegion::max()
+ self.base.clip = ClippingRegion::max();
+ self.base.stacking_relative_position_of_display_port = MAX_RECT;
}
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
@@ -1761,7 +1769,8 @@ impl Flow for BlockFlow {
let relative_offset = relative_offset.to_physical(self.base.writing_mode);
let origin_for_children;
let clip_in_child_coordinate_system;
- if self.fragment.establishes_stacking_context() {
+ let is_stacking_context = self.fragment.establishes_stacking_context();
+ if is_stacking_context {
// We establish a stacking context, so the position of our children is vertically
// correct, but has to be adjusted to accommodate horizontal margins. (Note the
// calculation involving `position` below and recall that inline-direction flow
@@ -1771,11 +1780,31 @@ impl Flow for BlockFlow {
let margin = self.fragment.margin.to_physical(self.base.writing_mode);
origin_for_children = Point2D(-margin.left, Au(0)) + relative_offset;
clip_in_child_coordinate_system =
- self.base.clip.translate(&-self.base.stacking_relative_position)
+ self.base.clip.translate(&-self.base.stacking_relative_position);
} else {
origin_for_children = self.base.stacking_relative_position + relative_offset;
- clip_in_child_coordinate_system = self.base.clip.clone()
+ clip_in_child_coordinate_system = self.base.clip.clone();
}
+
+ let stacking_relative_position_of_display_port_for_children =
+ if (is_stacking_context && self.will_get_layer()) || self.is_root() {
+ let visible_rect =
+ match layout_context.shared.visible_rects.get(&self.layer_id(0)) {
+ Some(visible_rect) => *visible_rect,
+ None => Rect(Point2D::zero(), layout_context.shared.screen_size),
+ };
+
+ let screen_size = layout_context.shared.screen_size;
+ visible_rect.inflate(screen_size.width * DISPLAY_PORT_SIZE_FACTOR,
+ screen_size.height * DISPLAY_PORT_SIZE_FACTOR)
+ } else if is_stacking_context {
+ self.base
+ .stacking_relative_position_of_display_port
+ .translate(&-self.base.stacking_relative_position)
+ } else {
+ self.base.stacking_relative_position_of_display_port
+ };
+
let stacking_relative_border_box =
self.fragment
.stacking_relative_border_box(&self.base.stacking_relative_position,
@@ -1820,7 +1849,9 @@ impl Flow for BlockFlow {
}
flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
- flow::mut_base(kid).clip = clip.clone()
+ flow::mut_base(kid).clip = clip.clone();
+ flow::mut_base(kid).stacking_relative_position_of_display_port =
+ stacking_relative_position_of_display_port_for_children;
}
}
diff --git a/components/layout/context.rs b/components/layout/context.rs
index 9a7550fd2d6..e83f4453b04 100644
--- a/components/layout/context.rs
+++ b/components/layout/context.rs
@@ -12,17 +12,21 @@ use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_cache_task::FontCacheTask;
use gfx::font_context::FontContext;
+use msg::compositor_msg::LayerId;
use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageState};
use script::layout_interface::{Animation, LayoutChan, ReflowGoal};
use std::boxed;
use std::cell::Cell;
+use std::collections::HashMap;
+use std::collections::hash_state::DefaultState;
use std::ptr;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender};
use style::selector_matching::Stylist;
use url::Url;
+use util::fnv::FnvHasher;
use util::geometry::Au;
use util::opts;
@@ -99,6 +103,9 @@ pub struct SharedLayoutContext {
/// sent.
pub new_animations_sender: Sender<Animation>,
+ /// The visible rects for each layer, as reported to us by the compositor.
+ pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>,
+
/// Why is this reflow occurring
pub goal: ReflowGoal,
}
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 3c615ed0e9d..aac8a7c2317 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -176,6 +176,8 @@ pub trait FragmentDisplayListBuilding {
/// * `relative_containing_block_size`: The size of the containing block that
/// `position: relative` makes use of.
/// * `clip`: The region to clip the display items to.
+ /// * `stacking_relative_display_port`: The position and size of the display port with respect
+ /// to the nearest ancestor stacking context.
fn build_display_list(&mut self,
display_list: &mut DisplayList,
layout_context: &LayoutContext,
@@ -184,7 +186,8 @@ pub trait FragmentDisplayListBuilding {
relative_containing_block_mode: WritingMode,
border_painting_mode: BorderPaintingMode,
background_and_border_level: BackgroundAndBorderLevel,
- clip: &ClippingRegion);
+ clip: &ClippingRegion,
+ stacking_relative_display_port: &Rect<Au>);
/// Sends the size and position of this iframe fragment to the constellation. This is out of
/// line to guide inlining.
@@ -866,7 +869,8 @@ impl FragmentDisplayListBuilding for Fragment {
relative_containing_block_mode: WritingMode,
border_painting_mode: BorderPaintingMode,
background_and_border_level: BackgroundAndBorderLevel,
- clip: &ClippingRegion) {
+ clip: &ClippingRegion,
+ stacking_relative_display_port: &Rect<Au>) {
if self.style().get_inheritedbox().visibility != visibility::T::visible {
return
}
@@ -888,6 +892,11 @@ impl FragmentDisplayListBuilding for Fragment {
stacking_relative_flow_origin,
self);
+ if !stacking_relative_border_box.intersects(stacking_relative_display_port) {
+ debug!("Fragment::build_display_list: outside display port");
+ return
+ }
+
if !stacking_relative_border_box.intersects(&layout_context.shared.dirty) {
debug!("Fragment::build_display_list: Did not intersect...");
return
@@ -1076,7 +1085,8 @@ impl FragmentDisplayListBuilding for Fragment {
let (sender, receiver) = channel::<Vec<u8>>();
let canvas_data = match canvas_fragment_info.renderer {
Some(ref renderer) => {
- renderer.lock().unwrap().send(CanvasMsg::Common(CanvasCommonMsg::SendPixelContents(sender))).unwrap();
+ renderer.lock().unwrap().send(CanvasMsg::Common(
+ CanvasCommonMsg::SendPixelContents(sender))).unwrap();
receiver.recv().unwrap()
},
None => repeat(0xFFu8).take(width * height * 4).collect(),
@@ -1364,6 +1374,7 @@ pub trait BlockFlowDisplayListBuilding {
display_list: Box<DisplayList>,
layout_context: &LayoutContext,
border_painting_mode: BorderPaintingMode);
+ fn will_get_layer(&self) -> bool;
}
impl BlockFlowDisplayListBuilding for BlockFlow {
@@ -1386,7 +1397,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.base.absolute_position_info.relative_containing_block_mode,
border_painting_mode,
background_border_level,
- &clip);
+ &clip,
+ &self.base.stacking_relative_position_of_display_port);
// Add children.
for kid in self.base.children.iter_mut() {
@@ -1422,6 +1434,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
}
+ fn will_get_layer(&self) -> bool {
+ self.base.absolute_position_info.layers_needed_for_positioned_flows ||
+ self.base.flags.contains(NEEDS_LAYER)
+ }
+
fn build_display_list_for_absolutely_positioned_block(
&mut self,
mut display_list: Box<DisplayList>,
@@ -1432,8 +1449,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
border_painting_mode,
BackgroundAndBorderLevel::RootOfStackingContext);
- if !self.base.absolute_position_info.layers_needed_for_positioned_flows &&
- !self.base.flags.contains(NEEDS_LAYER) {
+ if !self.will_get_layer() {
// We didn't need a layer.
self.base.display_list_building_result =
DisplayListBuildingResult::StackingContext(self.fragment.create_stacking_context(
@@ -1524,7 +1540,8 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
.relative_containing_block_mode,
BorderPaintingMode::Separate,
BackgroundAndBorderLevel::Content,
- &self.base.clip);
+ &self.base.clip,
+ &self.base.stacking_relative_position_of_display_port);
has_stacking_context = fragment.establishes_stacking_context();
match fragment.specific {
@@ -1597,7 +1614,10 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
.relative_containing_block_mode,
BorderPaintingMode::Separate,
BackgroundAndBorderLevel::Content,
- &self.block_flow.base.clip);
+ &self.block_flow.base.clip,
+ &self.block_flow
+ .base
+ .stacking_relative_position_of_display_port);
}
// Draw the rest of the block.
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 57edf9ccd45..11d1c017db6 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -271,7 +271,7 @@ pub trait Flow: fmt::Debug + Sync {
}
/// Phase 4 of reflow: computes absolute positions.
- fn compute_absolute_position(&mut self) {
+ fn compute_absolute_position(&mut self, _: &LayoutContext) {
// The default implementation is a no-op.
}
@@ -859,6 +859,12 @@ pub struct BaseFlow {
/// The clipping region for this flow and its descendants, in layer coordinates.
pub clip: ClippingRegion,
+ /// The stacking-relative position of the display port.
+ ///
+ /// FIXME(pcwalton): This might be faster as an Arc, since this varies only
+ /// 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: DisplayListBuildingResult,
@@ -909,10 +915,18 @@ impl Encodable for BaseFlow {
FlowClass::Block => c.as_immutable_block().encode(e),
FlowClass::Inline => c.as_immutable_inline().encode(e),
FlowClass::Table => c.as_immutable_table().encode(e),
- FlowClass::TableWrapper => c.as_immutable_table_wrapper().encode(e),
- FlowClass::TableRowGroup => c.as_immutable_table_rowgroup().encode(e),
- FlowClass::TableRow => c.as_immutable_table_row().encode(e),
- FlowClass::TableCell => c.as_immutable_table_cell().encode(e),
+ FlowClass::TableWrapper => {
+ c.as_immutable_table_wrapper().encode(e)
+ }
+ FlowClass::TableRowGroup => {
+ c.as_immutable_table_rowgroup().encode(e)
+ }
+ FlowClass::TableRow => {
+ c.as_immutable_table_row().encode(e)
+ }
+ FlowClass::TableCell => {
+ c.as_immutable_table_cell().encode(e)
+ }
_ => { Ok(()) } // TODO: Support captions
}
})
@@ -1024,6 +1038,7 @@ impl BaseFlow {
display_list_building_result: DisplayListBuildingResult::None,
absolute_position_info: AbsolutePositionInfo::new(writing_mode),
clip: ClippingRegion::max(),
+ stacking_relative_position_of_display_port: Rect::zero(),
flags: flags,
writing_mode: writing_mode,
thread_id: 0,
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 07a3068d65b..2ac426776a0 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -1464,7 +1464,7 @@ impl Flow for InlineFlow {
self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
- fn compute_absolute_position(&mut self) {
+ fn compute_absolute_position(&mut self, _: &LayoutContext) {
// First, gather up the positions of all the containing blocks (if any).
let mut containing_block_positions = Vec::new();
let container_size = Size2D(self.base.block_container_inline_size, Au(0));
@@ -1504,14 +1504,18 @@ impl Flow for InlineFlow {
let block_flow = info.flow_ref.as_block();
block_flow.base.absolute_position_info = self.base.absolute_position_info;
block_flow.base.stacking_relative_position =
- stacking_relative_border_box.origin
+ stacking_relative_border_box.origin;
+ block_flow.base.stacking_relative_position_of_display_port =
+ self.base.stacking_relative_position_of_display_port;
}
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
flow::mut_base(&mut *info.flow_ref).clip = clip;
let block_flow = info.flow_ref.as_block();
block_flow.base.absolute_position_info = self.base.absolute_position_info;
block_flow.base.stacking_relative_position =
- stacking_relative_border_box.origin
+ stacking_relative_border_box.origin;
+ block_flow.base.stacking_relative_position_of_display_port =
+ self.base.stacking_relative_position_of_display_port;
}
SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
@@ -1528,7 +1532,9 @@ impl Flow for InlineFlow {
stacking_relative_position + *padding_box_origin;
block_flow.base.stacking_relative_position =
- stacking_relative_border_box.origin
+ stacking_relative_border_box.origin;
+ block_flow.base.stacking_relative_position_of_display_port =
+ self.base.stacking_relative_position_of_display_port;
}
_ => {}
}
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs
index 7b30e10e727..0bf583627d1 100644
--- a/components/layout/layout_task.rs
+++ b/components/layout/layout_task.rs
@@ -11,12 +11,12 @@ use animation;
use construct::ConstructionResult;
use context::{SharedLayoutContext, SharedLayoutContextWrapper};
use css::node_style::StyledNode;
+use data::{LayoutDataAccess, LayoutDataWrapper};
use display_list_builder::ToGfxColor;
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::FlowRef;
use fragment::{Fragment, FragmentBorderBoxIterator};
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
-use data::{LayoutDataAccess, LayoutDataWrapper};
use layout_debug;
use opaque_node::OpaqueNodeMethods;
use parallel::{self, UnsafeFlow};
@@ -39,7 +39,7 @@ use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::{PaintChan, PaintLayer};
use layout_traits::{LayoutControlMsg, LayoutTaskFactory};
use log;
-use msg::compositor_msg::{Epoch, ScrollPolicy};
+use msg::compositor_msg::{Epoch, LayerId, ScrollPolicy};
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId};
use profile_traits::mem::{self, Report, ReportsChan};
@@ -57,6 +57,8 @@ use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel};
use script_traits::{ScriptControlChan, StylesheetLoadResponder};
use std::borrow::ToOwned;
use std::cell::Cell;
+use std::collections::HashMap;
+use std::collections::hash_state::DefaultState;
use std::mem::transmute;
use std::ops::{Deref, DerefMut};
use std::ptr;
@@ -69,6 +71,7 @@ use style::selector_matching::Stylist;
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
use url::Url;
use util::cursor::Cursor;
+use util::fnv::FnvHasher;
use util::geometry::{Au, MAX_RECT};
use util::logical_geometry::LogicalPoint;
use util::mem::HeapSizeOf;
@@ -77,6 +80,12 @@ use util::task::spawn_named_with_send_on_failure;
use util::task_state;
use util::workqueue::WorkQueue;
+/// The number of screens of data we're allowed to generate display lists for in each direction.
+pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
+
+/// The number of screens we have to traverse before we decide to generate new display lists.
+const DISPLAY_PORT_THRESHOLD_SIZE_FACTOR: i32 = 4;
+
/// Mutable data belonging to the LayoutTask.
///
/// This needs to be protected by a mutex so we can do fast RPCs.
@@ -125,8 +134,12 @@ pub struct LayoutTaskData {
/// sent.
pub new_animations_sender: Sender<Animation>,
- /// A counter for epoch messages
+ /// A counter for epoch messages.
epoch: Epoch,
+
+ /// The position and size of the visible rect for each layer. We do not build display lists
+ /// for any areas more than `DISPLAY_PORT_SIZE_FACTOR` screens away from this area.
+ pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>,
}
/// Information needed by the layout task.
@@ -330,6 +343,7 @@ impl LayoutTask {
content_box_response: Rect::zero(),
content_boxes_response: Vec::new(),
running_animations: Vec::new(),
+ visible_rects: Arc::new(HashMap::with_hash_state(Default::default())),
new_animations_receiver: new_animations_receiver,
new_animations_sender: new_animations_sender,
epoch: Epoch(0),
@@ -365,6 +379,7 @@ impl LayoutTask {
url: (*url).clone(),
reflow_root: reflow_root.map(|node| OpaqueNodeMethods::from_layout_node(node)),
dirty: Rect::zero(),
+ visible_rects: rw_data.visible_rects.clone(),
generation: rw_data.generation,
new_animations_sender: rw_data.new_animations_sender.clone(),
goal: goal,
@@ -406,6 +421,10 @@ impl LayoutTask {
match port_to_read {
PortToRead::Pipeline => {
match self.pipeline_port.recv().unwrap() {
+ LayoutControlMsg::SetVisibleRects(new_visible_rects) => {
+ self.handle_request_helper(Msg::SetVisibleRects(new_visible_rects),
+ possibly_locked_rw_data)
+ }
LayoutControlMsg::TickAnimations => {
self.handle_request_helper(Msg::TickAnimations, possibly_locked_rw_data)
}
@@ -509,6 +528,9 @@ impl LayoutTask {
|| self.handle_reflow(&*data, possibly_locked_rw_data));
},
Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data),
+ Msg::SetVisibleRects(new_visible_rects) => {
+ self.set_visible_rects(new_visible_rects, possibly_locked_rw_data);
+ }
Msg::ReapLayoutData(dead_layout_data) => {
unsafe {
self.handle_reap_layout_data(dead_layout_data)
@@ -964,6 +986,64 @@ impl LayoutTask {
chan.send(ConstellationControlMsg::ReflowComplete(self.id, data.id)).unwrap();
}
+ fn set_visible_rects<'a>(&'a self,
+ new_visible_rects: Vec<(LayerId, Rect<Au>)>,
+ possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>)
+ -> bool {
+ let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
+
+ // First, determine if we need to regenerate the display lists. This will happen if the
+ // layers have moved more than `DISPLAY_PORT_THRESHOLD_SIZE_FACTOR` away from their last
+ // positions.
+ let mut must_regenerate_display_lists = false;
+ let mut old_visible_rects = HashMap::with_hash_state(Default::default());
+ let inflation_amount =
+ Size2D(rw_data.screen_size.width * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR,
+ rw_data.screen_size.height * DISPLAY_PORT_THRESHOLD_SIZE_FACTOR);
+ for &(ref layer_id, ref new_visible_rect) in new_visible_rects.iter() {
+ match rw_data.visible_rects.get(layer_id) {
+ None => {
+ old_visible_rects.insert(*layer_id, *new_visible_rect);
+ }
+ Some(old_visible_rect) => {
+ old_visible_rects.insert(*layer_id, *old_visible_rect);
+
+ if !old_visible_rect.inflate(inflation_amount.width, inflation_amount.height)
+ .intersects(new_visible_rect) {
+ must_regenerate_display_lists = true;
+ }
+ }
+ }
+ }
+
+ if !must_regenerate_display_lists {
+ // Update `visible_rects` in case there are new layers that were discovered.
+ rw_data.visible_rects = Arc::new(old_visible_rects);
+ return true
+ }
+
+ debug!("regenerating display lists!");
+ for &(ref layer_id, ref new_visible_rect) in new_visible_rects.iter() {
+ old_visible_rects.insert(*layer_id, *new_visible_rect);
+ }
+ rw_data.visible_rects = Arc::new(old_visible_rects);
+
+ // Regenerate the display lists.
+ let reflow_info = Reflow {
+ goal: ReflowGoal::ForDisplay,
+ page_clip_rect: MAX_RECT,
+ };
+
+ let mut layout_context = self.build_shared_layout_context(&*rw_data,
+ false,
+ None,
+ &self.url,
+ reflow_info.goal);
+
+ self.perform_post_main_layout_passes(&reflow_info, &mut *rw_data, &mut layout_context);
+ true
+ }
+
fn tick_all_animations<'a>(&'a self,
possibly_locked_rw_data: &mut Option<MutexGuard<'a,
LayoutTaskData>>) {
@@ -1045,7 +1125,15 @@ impl LayoutTask {
}
});
+ self.perform_post_main_layout_passes(data, rw_data, layout_context);
+ }
+
+ fn perform_post_main_layout_passes<'a>(&'a self,
+ data: &Reflow,
+ rw_data: &mut LayoutTaskData,
+ layout_context: &mut SharedLayoutContext) {
// Build the display list if necessary, and send it to the painter.
+ let mut root_flow = (*rw_data.root_flow.as_ref().unwrap()).clone();
self.compute_abs_pos_and_build_display_list(data,
&mut root_flow,
&mut *layout_context,
diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs
index c348986c69c..1840cc1fbde 100644
--- a/components/layout/list_item.rs
+++ b/components/layout/list_item.rs
@@ -117,8 +117,8 @@ impl Flow for ListItemFlow {
}
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn place_float_if_applicable<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs
index f33b2774a40..1ce84a365f1 100644
--- a/components/layout/multicol.rs
+++ b/components/layout/multicol.rs
@@ -63,8 +63,8 @@ impl Flow for MulticolFlow {
self.block_flow.assign_block_size(ctx);
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
diff --git a/components/layout/table.rs b/components/layout/table.rs
index 3c9b832b190..9bb86eb9129 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -503,8 +503,8 @@ impl Flow for TableFlow {
self.block_flow.assign_block_size_for_table_like_flow(layout_context, vertical_spacing)
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize<Au> {
diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs
index 628b90c41c5..ab98e9b3261 100644
--- a/components/layout/table_caption.rs
+++ b/components/layout/table_caption.rs
@@ -59,13 +59,13 @@ impl Flow for TableCaptionFlow {
self.block_flow.assign_inline_sizes(ctx);
}
- fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
+ fn assign_block_size<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_caption");
- self.block_flow.assign_block_size(ctx);
+ self.block_flow.assign_block_size(layout_context);
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs
index 54ebe61c212..d44de741e60 100644
--- a/components/layout/table_cell.rs
+++ b/components/layout/table_cell.rs
@@ -160,13 +160,13 @@ impl Flow for TableCellFlow {
|_, _, _, _, _, _| {});
}
- fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
+ fn assign_block_size<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_cell");
- self.assign_block_size_table_cell_base(ctx);
+ self.assign_block_size_table_cell_base(layout_context);
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index b3a1ee93e91..ee9411a0513 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -403,8 +403,8 @@ impl Flow for TableRowFlow {
self.assign_block_size_table_row_base(layout_context);
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs
index 088103188c7..2c76c30c832 100644
--- a/components/layout/table_rowgroup.rs
+++ b/components/layout/table_rowgroup.rs
@@ -203,8 +203,8 @@ impl Flow for TableRowGroupFlow {
self.spacing.vertical)
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index 592ad213f93..8f77e97dfd0 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -381,8 +381,8 @@ impl Flow for TableWrapperFlow {
MarginsMayCollapseFlag::MarginsMayNotCollapse);
}
- fn compute_absolute_position(&mut self) {
- self.block_flow.compute_absolute_position()
+ fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
+ self.block_flow.compute_absolute_position(layout_context)
}
fn place_float_if_applicable<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index 39169787cad..6106456876b 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -364,7 +364,7 @@ pub struct ComputeAbsolutePositions<'a> {
impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
#[inline]
fn process(&self, flow: &mut Flow) {
- flow.compute_absolute_position();
+ flow.compute_absolute_position(self.layout_context);
}
}