Auto merge of #8334 - mrobinson:eliminate-layers-needed, r=pcwalton

Eliminate LAYERS_NEEDED_FOR_DESCENDANTS flag

This flag is no longer necessary, because stacking contexts can now
create layers lazily for content that needs to be stacked above a
layer. This should reduce the number of layers on pages, hopefully
reducing overdraw.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8334)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-11-05 07:04:11 +05:30
commit acc0bf6873
3 changed files with 3 additions and 56 deletions

View file

@ -39,8 +39,7 @@ use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC}; use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC};
use flow::{IS_ABSOLUTELY_POSITIONED}; use flow::{IS_ABSOLUTELY_POSITIONED};
use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow}; use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER}; use flow::{NEEDS_LAYER, PostorderFlowTraversal, PreorderFlowTraversal, mut_base};
use flow::{PostorderFlowTraversal, PreorderFlowTraversal, mut_base};
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag}; use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER};
use fragment::{SpecificFragmentInfo}; use fragment::{SpecificFragmentInfo};
@ -501,30 +500,6 @@ enum FormattingContextType {
Other, Other,
} }
// Propagates the `layers_needed_for_descendants` flag appropriately from a child. This is called
// as part of block-size assignment.
//
// If any fixed descendants of kids are present, this kid needs a layer.
//
// FIXME(#2006, pcwalton): This is too layer-happy. Like WebKit, we shouldn't do this unless
// the positioned descendants are actually on top of the fixed kids.
//
// TODO(#1244, #2007, pcwalton): Do this for CSS transforms and opacity too, at least if they're
// animating.
pub fn propagate_layer_flag_from_child(layers_needed_for_descendants: &mut bool, kid: &mut Flow) {
if kid.is_absolute_containing_block() {
let kid_base = flow::mut_base(kid);
if kid_base.flags.contains(NEEDS_LAYER) {
*layers_needed_for_descendants = true
}
} else {
let kid_base = flow::mut_base(kid);
if kid_base.flags.contains(LAYERS_NEEDED_FOR_DESCENDANTS) {
*layers_needed_for_descendants = true
}
}
}
// A block formatting context. // A block formatting context.
#[derive(RustcEncodable)] #[derive(RustcEncodable)]
pub struct BlockFlow { pub struct BlockFlow {
@ -828,7 +803,6 @@ impl BlockFlow {
// At this point, `cur_b` is at the content edge of our box. Now iterate over children. // At this point, `cur_b` is at the content edge of our box. Now iterate over children.
let mut floats = self.base.floats.clone(); let mut floats = self.base.floats.clone();
let mut layers_needed_for_descendants = false;
let thread_id = self.base.thread_id; let thread_id = self.base.thread_id;
for kid in self.base.child_iter() { for kid in self.base.child_iter() {
if flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) { if flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
@ -844,7 +818,6 @@ impl BlockFlow {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context, kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
thread_id); thread_id);
} }
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
// Skip the collapsing and float processing for absolute flow kids and continue // Skip the collapsing and float processing for absolute flow kids and continue
// with the next flow. // with the next flow.
@ -861,7 +834,6 @@ impl BlockFlow {
kid_block.float.as_mut().unwrap().float_ceiling = kid_block.float.as_mut().unwrap().float_ceiling =
margin_collapse_info.current_float_ceiling(); margin_collapse_info.current_float_ceiling();
} }
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
kid.place_float_if_applicable(layout_context); kid.place_float_if_applicable(layout_context);
let kid_base = flow::mut_base(kid); let kid_base = flow::mut_base(kid);
@ -885,9 +857,6 @@ impl BlockFlow {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context, kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
thread_id); thread_id);
// Mark flows for layerization if necessary to handle painting order correctly.
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
// Handle any (possibly collapsed) top margin. // Handle any (possibly collapsed) top margin.
let delta = margin_collapse_info.advance_block_start_margin( let delta = margin_collapse_info.advance_block_start_margin(
&flow::base(kid).collapsible_margins); &flow::base(kid).collapsible_margins);
@ -925,10 +894,6 @@ impl BlockFlow {
translate_including_floats(&mut cur_b, delta, &mut floats); translate_including_floats(&mut cur_b, delta, &mut floats);
} }
// Mark ourselves for layerization if that will be necessary to paint in the proper
// order (CSS 2.1, Appendix E).
self.base.flags.set(LAYERS_NEEDED_FOR_DESCENDANTS, layers_needed_for_descendants);
// Add in our block-end margin and compute our collapsible margins. // Add in our block-end margin and compute our collapsible margins.
let can_collapse_block_end_margin_with_kids = let can_collapse_block_end_margin_with_kids =
margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse && margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse &&
@ -1793,9 +1758,7 @@ impl Flow for BlockFlow {
} }
fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
if (self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) && if self.base.flags.contains(NEEDS_LAYER) {
self.base.late_absolute_position_info.layers_needed_for_positioned_flows) ||
self.base.flags.contains(NEEDS_LAYER) {
self.fragment.flags.insert(HAS_LAYER) self.fragment.flags.insert(HAS_LAYER)
} }
@ -1900,9 +1863,6 @@ impl Flow for BlockFlow {
let late_absolute_position_info_for_children = LateAbsolutePositionInfo { let late_absolute_position_info_for_children = LateAbsolutePositionInfo {
stacking_relative_position_of_absolute_containing_block: stacking_relative_position_of_absolute_containing_block:
stacking_relative_position_of_absolute_containing_block_for_children, stacking_relative_position_of_absolute_containing_block_for_children,
layers_needed_for_positioned_flows: self.base
.flags
.contains(LAYERS_NEEDED_FOR_DESCENDANTS),
}; };
let container_size_for_children = let container_size_for_children =
self.base.position.size.to_physical(self.base.writing_mode); self.base.position.size.to_physical(self.base.writing_mode);

View file

@ -580,9 +580,6 @@ bitflags! {
const IMPACTED_BY_RIGHT_FLOATS = 0b0000_0000_0000_0000_1000, const IMPACTED_BY_RIGHT_FLOATS = 0b0000_0000_0000_0000_1000,
// text align flags // text align flags
#[doc = "Whether this flow contains a flow that has its own layer within the same absolute"]
#[doc = "containing block."]
const LAYERS_NEEDED_FOR_DESCENDANTS = 0b0000_0000_0000_0001_0000,
#[doc = "Whether this flow must have its own layer. Even if this flag is not set, it might"] #[doc = "Whether this flow must have its own layer. Even if this flag is not set, it might"]
#[doc = "get its own layer if it's deemed to be likely to overlap flows with their own"] #[doc = "get its own layer if it's deemed to be likely to overlap flows with their own"]
#[doc = "layer."] #[doc = "layer."]
@ -810,18 +807,12 @@ pub struct LateAbsolutePositionInfo {
/// context. If the absolute containing block establishes the stacking context for this flow, /// context. If the absolute containing block establishes the stacking context for this flow,
/// and this flow is not itself absolutely-positioned, then this is (0, 0). /// and this flow is not itself absolutely-positioned, then this is (0, 0).
pub stacking_relative_position_of_absolute_containing_block: Point2D<Au>, pub stacking_relative_position_of_absolute_containing_block: Point2D<Au>,
/// Whether the absolute containing block forces positioned descendants to be layerized.
///
/// FIXME(pcwalton): Move into `FlowFlags`.
pub layers_needed_for_positioned_flows: bool,
} }
impl LateAbsolutePositionInfo { impl LateAbsolutePositionInfo {
pub fn new() -> LateAbsolutePositionInfo { pub fn new() -> LateAbsolutePositionInfo {
LateAbsolutePositionInfo { LateAbsolutePositionInfo {
stacking_relative_position_of_absolute_containing_block: Point2D::zero(), stacking_relative_position_of_absolute_containing_block: Point2D::zero(),
layers_needed_for_positioned_flows: false,
} }
} }
} }

View file

@ -7,8 +7,8 @@
#![deny(unsafe_code)] #![deny(unsafe_code)]
use app_units::Au; use app_units::Au;
use block::{BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use block::{ISizeConstraintInput, ISizeConstraintSolution}; use block::{ISizeConstraintInput, ISizeConstraintSolution};
use block::{self, BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use context::LayoutContext; use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use euclid::{Point2D, Rect}; use euclid::{Point2D, Rect};
@ -775,11 +775,7 @@ impl TableLikeFlow for BlockFlow {
// At this point, `current_block_offset` is at the content edge of our box. Now iterate // At this point, `current_block_offset` is at the content edge of our box. Now iterate
// over children. // over children.
let mut layers_needed_for_descendants = false;
for kid in self.base.child_iter() { for kid in self.base.child_iter() {
// Mark flows for layerization if necessary to handle painting order correctly.
block::propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
// Account for spacing or collapsed borders. // Account for spacing or collapsed borders.
if kid.is_table_row() { if kid.is_table_row() {
has_rows = true; has_rows = true;