Skip to content

Commit

Permalink
Remove the concept of nested stacking contexts from display list builder
Browse files Browse the repository at this point in the history
With the removal of the legacy rendering path, we don't need to worry
about nested stacking contexts. This change just pushes the
complication to the WebRender conversion step, but a later change will
remove the concept from WebRender as well.

This also helps to prepare for the introduction of ids for particular
scrolling regions, an integral part of multiple ScrollLayers per block.
  • Loading branch information
mrobinson committed Oct 19, 2016
1 parent 983edb9 commit 2219b14
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 110 deletions.
21 changes: 9 additions & 12 deletions components/gfx/display_list/mod.rs
Expand Up @@ -589,14 +589,14 @@ pub struct StackingContext {
/// Whether this stacking context creates a new 3d rendering context.
pub establishes_3d_context: bool,

/// Whether this stacking context scrolls its overflow area.
pub scrolls_overflow_area: bool,

/// The layer info for this stacking context, if there is any.
pub layer_info: Option<LayerInfo>,

/// Children of this StackingContext.
pub children: Vec<StackingContext>,

/// If this StackingContext scrolls its overflow area, this will contain the id.
pub overflow_scroll_id: Option<StackingContextId>,
}

impl StackingContext {
Expand All @@ -612,8 +612,8 @@ impl StackingContext {
transform: Matrix4D<f32>,
perspective: Matrix4D<f32>,
establishes_3d_context: bool,
scrolls_overflow_area: bool,
layer_info: Option<LayerInfo>)
layer_info: Option<LayerInfo>,
scroll_id: Option<StackingContextId>)
-> StackingContext {
StackingContext {
id: id,
Expand All @@ -626,9 +626,9 @@ impl StackingContext {
transform: transform,
perspective: perspective,
establishes_3d_context: establishes_3d_context,
scrolls_overflow_area: scrolls_overflow_area,
layer_info: layer_info,
children: Vec::new(),
overflow_scroll_id: scroll_id,
}
}

Expand All @@ -648,13 +648,10 @@ impl StackingContext {
fn update_overflow_for_all_children(&mut self) {
for child in self.children.iter() {
if self.context_type == StackingContextType::Real &&
child.context_type == StackingContextType::Real &&
!self.scrolls_overflow_area {
child.context_type == StackingContextType::Real {
// This child might be transformed, so we need to take into account
// its transformed overflow rect too, but at the correct position.
let overflow =
child.overflow_rect_in_parent_space();

let overflow = child.overflow_rect_in_parent_space();
self.overflow = self.overflow.union(&overflow);
}
}
Expand Down Expand Up @@ -740,7 +737,7 @@ impl fmt::Debug for StackingContext {
"Pseudo-StackingContext"
};

let scrollable_string = if self.scrolls_overflow_area {
let scrollable_string = if self.overflow_scroll_id.is_some() {
" (scrolls overflow area)"
} else {
""
Expand Down
127 changes: 45 additions & 82 deletions components/layout/display_list_builder.rs
Expand Up @@ -298,7 +298,8 @@ pub trait FragmentDisplayListBuilding {
id: StackingContextId,
base_flow: &BaseFlow,
scroll_policy: ScrollPolicy,
mode: StackingContextCreationMode)
mode: StackingContextCreationMode,
scroll_id: Option<StackingContextId>)
-> StackingContext;

/// Returns the 4D matrix representing this fragment's transform.
Expand Down Expand Up @@ -1354,36 +1355,26 @@ impl FragmentDisplayListBuilding for Fragment {
id: StackingContextId,
base_flow: &BaseFlow,
scroll_policy: ScrollPolicy,
mode: StackingContextCreationMode)
mode: StackingContextCreationMode,
scroll_id: Option<StackingContextId>)
-> StackingContext {
let border_box = match mode {
StackingContextCreationMode::InnerScrollWrapper => {
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
}
_ => {
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
&base_flow.early_absolute_position_info
.relative_containing_block_size,
base_flow.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Parent)
}
};
let overflow = match mode {
StackingContextCreationMode::InnerScrollWrapper => {
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
}
StackingContextCreationMode::OuterScrollWrapper => {
Rect::new(Point2D::zero(), border_box.size)
}
_ => {
// First, compute the offset of our border box (including relative positioning)
// from our flow origin, since that is what `BaseFlow::overflow` is relative to.
let border_box_offset =
border_box.translate(&-base_flow.stacking_relative_position).origin;
// Then, using that, compute our overflow region relative to our border box.
base_flow.overflow.paint.translate(&-border_box_offset)
}
let scrolls_overflow_area = mode == StackingContextCreationMode::ScrollWrapper;
let border_box =
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
&base_flow.early_absolute_position_info
.relative_containing_block_size,
base_flow.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Parent);
let overflow = if scrolls_overflow_area {
Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
} else {
// First, compute the offset of our border box (including relative positioning)
// from our flow origin, since that is what `BaseFlow::overflow` is relative to.
let border_box_offset =
border_box.translate(&-base_flow.stacking_relative_position).origin;
// Then, using that, compute our overflow region relative to our border box.
base_flow.overflow.paint.translate(&-border_box_offset)
};

let transform = self.transform_matrix(&border_box);
Expand Down Expand Up @@ -1419,20 +1410,12 @@ impl FragmentDisplayListBuilding for Fragment {
filters.push(Filter::Opacity(effects.opacity))
}

// There are two situations that need layers: when the fragment has the HAS_LAYER
// flag and when we are building a layer tree for overflow scrolling.
let layer_info = if mode == StackingContextCreationMode::InnerScrollWrapper {
Some(LayerInfo::new(self.layer_id_for_overflow_scroll(),
scroll_policy,
None,
color::transparent()))
} else if self.flags.contains(HAS_LAYER) {
let layer_info = if self.flags.contains(HAS_LAYER) {
Some(LayerInfo::new(self.layer_id(), scroll_policy, None, color::transparent()))
} else {
None
};

let scrolls_overflow_area = mode == StackingContextCreationMode::OuterScrollWrapper;
let transform_style = self.style().get_used_transform_style();
let establishes_3d_context = scrolls_overflow_area ||
transform_style == transform_style::T::flat;
Expand All @@ -1453,8 +1436,8 @@ impl FragmentDisplayListBuilding for Fragment {
transform,
perspective,
establishes_3d_context,
scrolls_overflow_area,
layer_info)
layer_info,
scroll_id)
}

fn adjust_clipping_region_for_children(&self,
Expand Down Expand Up @@ -1736,22 +1719,10 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}

let has_scrolling_overflow = self.has_scrolling_overflow();
let stacking_context_id = if has_scrolling_overflow {
StackingContextId::new_outer(self.fragment.fragment_type())
} else {
StackingContextId::new_of_type(self.fragment.node.id() as usize,
self.fragment.fragment_type())
};
let stacking_context_id = StackingContextId::new_of_type(self.fragment.node.id() as usize,
self.fragment.fragment_type());
self.base.stacking_context_id = stacking_context_id;

let inner_stacking_context_id = if has_scrolling_overflow {
StackingContextId::new_of_type(self.fragment.node.id() as usize,
self.fragment.fragment_type())
} else {
stacking_context_id
};


if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
self.fragment.style.get_box().position != position::T::static_ {
Expand All @@ -1764,7 +1735,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
let mut new_context = self.fragment.create_stacking_context(stacking_context_id,
&self.base,
ScrollPolicy::Scrollable,
creation_mode);
creation_mode,
None);
self.base.collect_stacking_contexts_for_children(&mut new_context);
let new_children: Vec<StackingContext> = new_context.children.drain(..).collect();

Expand All @@ -1788,32 +1760,23 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
ScrollPolicy::Scrollable
};

let stacking_context = if self.has_scrolling_overflow() {
let mut inner_stacking_context = self.fragment.create_stacking_context(
inner_stacking_context_id,
&self.base,
scroll_policy,
StackingContextCreationMode::InnerScrollWrapper);

self.base.collect_stacking_contexts_for_children(&mut inner_stacking_context);

let mut outer_stacking_context = self.fragment.create_stacking_context(
stacking_context_id,
&self.base,
scroll_policy,
StackingContextCreationMode::OuterScrollWrapper);
outer_stacking_context.add_child(inner_stacking_context);
outer_stacking_context
let (creation_mode, internal_id) = if has_scrolling_overflow {
(StackingContextCreationMode::ScrollWrapper,
Some(StackingContextId::new_of_type(self.fragment.node.id() as usize,
self.fragment.fragment_type())))

} else {
let mut stacking_context = self.fragment.create_stacking_context(
stacking_context_id,
&self.base,
scroll_policy,
StackingContextCreationMode::Normal);
self.base.collect_stacking_contexts_for_children(&mut stacking_context);
stacking_context
(StackingContextCreationMode::Normal, None)
};

let mut stacking_context = self.fragment.create_stacking_context(
stacking_context_id,
&self.base,
scroll_policy,
creation_mode,
internal_id);
self.base.collect_stacking_contexts_for_children(&mut stacking_context);

parent.add_child(stacking_context);
}

Expand Down Expand Up @@ -1931,7 +1894,8 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
fragment.stacking_context_id,
&self.base,
ScrollPolicy::Scrollable,
StackingContextCreationMode::Normal));
StackingContextCreationMode::Normal,
None));
}
_ => fragment.stacking_context_id = parent.id,
}
Expand Down Expand Up @@ -2135,8 +2099,7 @@ pub enum BorderPaintingMode<'a> {
#[derive(Copy, Clone, PartialEq)]
pub enum StackingContextCreationMode {
Normal,
OuterScrollWrapper,
InnerScrollWrapper,
ScrollWrapper,
PseudoPositioned,
PseudoFloat,
}
Expand Down
66 changes: 51 additions & 15 deletions components/layout/webrender_helpers.rs
Expand Up @@ -9,7 +9,7 @@

use app_units::Au;
use azure::azure_hl::Color;
use euclid::{Point2D, Rect, Size2D};
use euclid::{Matrix4D, Point2D, Rect, Size2D};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal};
use gfx::display_list::{GradientStop, StackingContext, StackingContextType};
Expand Down Expand Up @@ -266,7 +266,7 @@ impl WebRenderStackingContextConverter for StackingContext {
let stacking_context = &stacking_context_item.stacking_context;
debug_assert!(stacking_context.context_type == StackingContextType::Real);

let scroll_layer_id_for_children = if self.scrolls_overflow_area {
let scroll_layer_id_for_children = if self.overflow_scroll_id.is_some() {
scroll_layer_id
} else {
None
Expand Down Expand Up @@ -294,7 +294,7 @@ impl WebRenderStackingContextConverter for StackingContext {
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
mut scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
mut scroll_policy: ScrollPolicy,
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId {
Expand All @@ -309,12 +309,18 @@ impl WebRenderStackingContextConverter for StackingContext {

let webrender_stacking_context_id = self.id.convert_to_webrender();

let outer_overflow = if self.overflow_scroll_id.is_none() {
self.overflow.to_rectf()
} else {
Rect::new(Point2D::zero(), self.bounds.size).to_rectf()
};

let mut sc =
webrender_traits::StackingContext::new(webrender_stacking_context_id,
scroll_layer_id,
webrender_scroll_policy,
self.bounds.to_rectf(),
self.overflow.to_rectf(),
outer_overflow,
self.z_index,
&self.transform,
&self.perspective,
Expand All @@ -325,19 +331,49 @@ impl WebRenderStackingContextConverter for StackingContext {

let mut builder = webrender_traits::DisplayListBuilder::new();

if self.scrolls_overflow_area {
scroll_layer_id = Some(frame_builder.next_scroll_layer_id());
if let Some(inner_stacking_context_id) = self.overflow_scroll_id {
let inner_webrender_stacking_context_id =
inner_stacking_context_id.convert_to_webrender();
let mut inner_sc =
webrender_traits::StackingContext::new(inner_webrender_stacking_context_id,
Some(frame_builder.next_scroll_layer_id()),
webrender_scroll_policy,
self.overflow.to_rectf(),
self.overflow.to_rectf(),
self.z_index,
&Matrix4D::identity(),
&Matrix4D::identity(),
false,
webrender_traits::MixBlendMode::Normal,
Vec::new(),
&mut frame_builder.auxiliary_lists_builder);
let mut inner_builder = webrender_traits::DisplayListBuilder::new();
self.convert_children_to_webrender(traversal,
api,
pipeline_id,
epoch,
None,
scroll_policy,
&mut inner_builder,
frame_builder,
false);

frame_builder.add_display_list(api, inner_builder.finalize(), &mut inner_sc);
let new_id = frame_builder.add_stacking_context(api, pipeline_id, inner_sc);
builder.push_stacking_context(new_id);
} else {
self.convert_children_to_webrender(traversal,
api,
pipeline_id,
epoch,
scroll_layer_id,
scroll_policy,
&mut builder,
frame_builder,
false);
}

self.convert_children_to_webrender(traversal,
api,
pipeline_id,
epoch,
scroll_layer_id,
scroll_policy,
&mut builder,
frame_builder,
false);

frame_builder.add_display_list(api, builder.finalize(), &mut sc);
frame_builder.add_stacking_context(api, pipeline_id, sc)
}
Expand Down
2 changes: 1 addition & 1 deletion components/layout_thread/lib.rs
Expand Up @@ -935,7 +935,7 @@ impl LayoutThread {
Matrix4D::identity(),
Matrix4D::identity(),
true,
false,
None,
None);

let display_list_entries =
Expand Down

0 comments on commit 2219b14

Please sign in to comment.