mirror of
https://github.com/servo/servo.git
synced 2025-08-24 14:48:21 +01:00
layout: Make Fragment
hold ArcRefCell
inside (#34923)
Push the interior mutability into enum variants of `Fragment`, so that they can be cloned. This saves memory in the `Fragment` tree as the `Fragment` enum is now a relatively wee 16 bytes and the interior parts can be a variety of sizes. Before, every `Fragment` was the size of the biggest kind (`BoxFragment` - 248 bytes). This a step on the way toward incremental layout. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
c936dd6c4e
commit
de780dcde4
18 changed files with 257 additions and 233 deletions
|
@ -246,6 +246,7 @@ impl Fragment {
|
|||
) {
|
||||
match self {
|
||||
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
|
||||
let box_fragment = &*box_fragment.borrow();
|
||||
match box_fragment.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => BuilderForBoxFragment::new(
|
||||
box_fragment,
|
||||
|
@ -259,6 +260,7 @@ impl Fragment {
|
|||
},
|
||||
Fragment::AbsoluteOrFixedPositioned(_) => {},
|
||||
Fragment::Positioning(positioning_fragment) => {
|
||||
let positioning_fragment = positioning_fragment.borrow();
|
||||
if let Some(style) = positioning_fragment.style.as_ref() {
|
||||
let rect = positioning_fragment
|
||||
.rect
|
||||
|
@ -272,65 +274,74 @@ impl Fragment {
|
|||
);
|
||||
}
|
||||
},
|
||||
Fragment::Image(image) => match image.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
builder.is_contentful = true;
|
||||
Fragment::Image(image) => {
|
||||
let image = image.borrow();
|
||||
match image.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
builder.is_contentful = true;
|
||||
|
||||
let image_rendering = image
|
||||
.style
|
||||
.get_inherited_box()
|
||||
.image_rendering
|
||||
.to_webrender();
|
||||
let rect = image
|
||||
.rect
|
||||
.translate(containing_block.origin.to_vector())
|
||||
.to_webrender();
|
||||
let clip = image
|
||||
.clip
|
||||
.translate(containing_block.origin.to_vector())
|
||||
.to_webrender();
|
||||
let common = builder.common_properties(clip, &image.style);
|
||||
let image_rendering = image
|
||||
.style
|
||||
.get_inherited_box()
|
||||
.image_rendering
|
||||
.to_webrender();
|
||||
let rect = image
|
||||
.rect
|
||||
.translate(containing_block.origin.to_vector())
|
||||
.to_webrender();
|
||||
let clip = image
|
||||
.clip
|
||||
.translate(containing_block.origin.to_vector())
|
||||
.to_webrender();
|
||||
let common = builder.common_properties(clip, &image.style);
|
||||
|
||||
if let Some(image_key) = image.image_key {
|
||||
builder.wr().push_image(
|
||||
&common,
|
||||
rect,
|
||||
image_rendering,
|
||||
wr::AlphaType::PremultipliedAlpha,
|
||||
image_key,
|
||||
wr::ColorF::WHITE,
|
||||
if let Some(image_key) = image.image_key {
|
||||
builder.wr().push_image(
|
||||
&common,
|
||||
rect,
|
||||
image_rendering,
|
||||
wr::AlphaType::PremultipliedAlpha,
|
||||
image_key,
|
||||
wr::ColorF::WHITE,
|
||||
);
|
||||
}
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
}
|
||||
},
|
||||
Fragment::IFrame(iframe) => {
|
||||
let iframe = iframe.borrow();
|
||||
match iframe.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
builder.is_contentful = true;
|
||||
let rect = iframe.rect.translate(containing_block.origin.to_vector());
|
||||
|
||||
let common = builder.common_properties(rect.to_webrender(), &iframe.style);
|
||||
builder.wr().push_iframe(
|
||||
rect.to_webrender(),
|
||||
common.clip_rect,
|
||||
&wr::SpaceAndClipInfo {
|
||||
spatial_id: common.spatial_id,
|
||||
clip_chain_id: common.clip_chain_id,
|
||||
},
|
||||
iframe.pipeline_id.into(),
|
||||
true,
|
||||
);
|
||||
}
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
}
|
||||
},
|
||||
Fragment::IFrame(iframe) => match iframe.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
builder.is_contentful = true;
|
||||
let rect = iframe.rect.translate(containing_block.origin.to_vector());
|
||||
|
||||
let common = builder.common_properties(rect.to_webrender(), &iframe.style);
|
||||
builder.wr().push_iframe(
|
||||
rect.to_webrender(),
|
||||
common.clip_rect,
|
||||
&wr::SpaceAndClipInfo {
|
||||
spatial_id: common.spatial_id,
|
||||
clip_chain_id: common.clip_chain_id,
|
||||
},
|
||||
iframe.pipeline_id.into(),
|
||||
true,
|
||||
);
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
},
|
||||
Fragment::Text(t) => match t.parent_style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
self.build_display_list_for_text_fragment(t, builder, containing_block)
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
Fragment::Text(text) => {
|
||||
let text = &*text.borrow();
|
||||
match text.parent_style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
self.build_display_list_for_text_fragment(text, builder, containing_block)
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ use wr::{ClipChainId, SpatialTreeItemKey, StickyOffsetBounds};
|
|||
|
||||
use super::clip_path::build_clip_path_clip_chain_if_necessary;
|
||||
use super::DisplayList;
|
||||
use crate::cell::ArcRefCell;
|
||||
use crate::display_list::conversions::{FilterToWebRender, ToWebRender};
|
||||
use crate::display_list::{BuilderForBoxFragment, DisplayListBuilder};
|
||||
use crate::fragment_tree::{
|
||||
|
@ -142,8 +141,7 @@ impl DisplayList {
|
|||
|
||||
let mut root_stacking_context = StackingContext::create_root(&self.wr, debug);
|
||||
for fragment in &fragment_tree.root_fragments {
|
||||
fragment.borrow_mut().build_stacking_context_tree(
|
||||
fragment,
|
||||
fragment.build_stacking_context_tree(
|
||||
self,
|
||||
&containing_block_info,
|
||||
&mut root_stacking_context,
|
||||
|
@ -260,7 +258,7 @@ pub(crate) enum StackingContextContent {
|
|||
clip_chain_id: wr::ClipChainId,
|
||||
section: StackingContextSection,
|
||||
containing_block: PhysicalRect<Au>,
|
||||
fragment: ArcRefCell<Fragment>,
|
||||
fragment: Fragment,
|
||||
is_hit_test_for_scrollable_overflow: bool,
|
||||
},
|
||||
|
||||
|
@ -296,7 +294,7 @@ impl StackingContextContent {
|
|||
builder.current_scroll_node_id = *scroll_node_id;
|
||||
builder.current_reference_frame_scroll_node_id = *reference_frame_scroll_node_id;
|
||||
builder.current_clip_chain_id = *clip_chain_id;
|
||||
fragment.borrow().build_display_list(
|
||||
fragment.build_display_list(
|
||||
builder,
|
||||
containing_block,
|
||||
*section,
|
||||
|
@ -632,13 +630,11 @@ impl StackingContext {
|
|||
else {
|
||||
debug_panic!("Expected a fragment, not a stacking container");
|
||||
};
|
||||
let fragment = fragment.borrow();
|
||||
let box_fragment = match &*fragment {
|
||||
let box_fragment = match fragment {
|
||||
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => box_fragment,
|
||||
_ => {
|
||||
debug_panic!("Expected a box-generated fragment");
|
||||
},
|
||||
_ => debug_panic!("Expected a box-generated fragment"),
|
||||
};
|
||||
let box_fragment = &*box_fragment.borrow();
|
||||
|
||||
// The `StackingContextFragment` we found is for the root DOM element:
|
||||
debug_assert_eq!(
|
||||
|
@ -849,16 +845,17 @@ pub(crate) enum StackingContextBuildMode {
|
|||
|
||||
impl Fragment {
|
||||
pub(crate) fn build_stacking_context_tree(
|
||||
&mut self,
|
||||
fragment_ref: &ArcRefCell<Fragment>,
|
||||
&self,
|
||||
display_list: &mut DisplayList,
|
||||
containing_block_info: &ContainingBlockInfo,
|
||||
stacking_context: &mut StackingContext,
|
||||
mode: StackingContextBuildMode,
|
||||
) {
|
||||
let containing_block = containing_block_info.get_containing_block_for_fragment(self);
|
||||
let fragment_clone = self.clone();
|
||||
match self {
|
||||
Fragment::Box(fragment) | Fragment::Float(fragment) => {
|
||||
let fragment = fragment.borrow();
|
||||
if mode == StackingContextBuildMode::SkipHoisted &&
|
||||
fragment.style.clone_position().is_absolutely_positioned()
|
||||
{
|
||||
|
@ -876,7 +873,7 @@ impl Fragment {
|
|||
}
|
||||
|
||||
fragment.build_stacking_context_tree(
|
||||
fragment_ref,
|
||||
fragment_clone,
|
||||
display_list,
|
||||
containing_block,
|
||||
containing_block_info,
|
||||
|
@ -890,8 +887,7 @@ impl Fragment {
|
|||
None => unreachable!("Found hoisted box with missing fragment."),
|
||||
};
|
||||
|
||||
fragment_ref.borrow_mut().build_stacking_context_tree(
|
||||
fragment_ref,
|
||||
fragment_ref.build_stacking_context_tree(
|
||||
display_list,
|
||||
containing_block_info,
|
||||
stacking_context,
|
||||
|
@ -899,6 +895,7 @@ impl Fragment {
|
|||
);
|
||||
},
|
||||
Fragment::Positioning(fragment) => {
|
||||
let fragment = fragment.borrow();
|
||||
fragment.build_stacking_context_tree(
|
||||
display_list,
|
||||
containing_block,
|
||||
|
@ -917,7 +914,7 @@ impl Fragment {
|
|||
.scroll_node_id,
|
||||
clip_chain_id: containing_block.clip_chain_id,
|
||||
containing_block: containing_block.rect,
|
||||
fragment: fragment_ref.clone(),
|
||||
fragment: fragment_clone,
|
||||
is_hit_test_for_scrollable_overflow: false,
|
||||
});
|
||||
},
|
||||
|
@ -971,8 +968,8 @@ impl BoxFragment {
|
|||
}
|
||||
|
||||
fn build_stacking_context_tree(
|
||||
&mut self,
|
||||
fragment: &ArcRefCell<Fragment>,
|
||||
&self,
|
||||
fragment: Fragment,
|
||||
display_list: &mut DisplayList,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block_info: &ContainingBlockInfo,
|
||||
|
@ -988,8 +985,8 @@ impl BoxFragment {
|
|||
}
|
||||
|
||||
fn build_stacking_context_tree_maybe_creating_reference_frame(
|
||||
&mut self,
|
||||
fragment: &ArcRefCell<Fragment>,
|
||||
&self,
|
||||
fragment: Fragment,
|
||||
display_list: &mut DisplayList,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block_info: &ContainingBlockInfo,
|
||||
|
@ -1052,8 +1049,8 @@ impl BoxFragment {
|
|||
}
|
||||
|
||||
fn build_stacking_context_tree_maybe_creating_stacking_context(
|
||||
&mut self,
|
||||
fragment: &ArcRefCell<Fragment>,
|
||||
&self,
|
||||
fragment: Fragment,
|
||||
display_list: &mut DisplayList,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block_info: &ContainingBlockInfo,
|
||||
|
@ -1128,8 +1125,8 @@ impl BoxFragment {
|
|||
}
|
||||
|
||||
fn build_stacking_context_tree_for_children(
|
||||
&mut self,
|
||||
fragment: &ArcRefCell<Fragment>,
|
||||
&self,
|
||||
fragment: Fragment,
|
||||
display_list: &mut DisplayList,
|
||||
containing_block: &ContainingBlock,
|
||||
containing_block_info: &ContainingBlockInfo,
|
||||
|
@ -1273,8 +1270,7 @@ impl BoxFragment {
|
|||
};
|
||||
|
||||
for child in &self.children {
|
||||
child.borrow_mut().build_stacking_context_tree(
|
||||
child,
|
||||
child.build_stacking_context_tree(
|
||||
display_list,
|
||||
&new_containing_block_info,
|
||||
stacking_context,
|
||||
|
@ -1381,7 +1377,7 @@ impl BoxFragment {
|
|||
}
|
||||
|
||||
fn build_sticky_frame_if_necessary(
|
||||
&mut self,
|
||||
&self,
|
||||
display_list: &mut DisplayList,
|
||||
parent_scroll_node_id: &ScrollTreeNodeId,
|
||||
containing_block_rect: &PhysicalRect<Au>,
|
||||
|
@ -1411,7 +1407,7 @@ impl BoxFragment {
|
|||
offsets.bottom.map(|v| v.to_used_value(scroll_frame_height)),
|
||||
offsets.left.map(|v| v.to_used_value(scroll_frame_width)),
|
||||
);
|
||||
self.resolved_sticky_insets = Some(offsets);
|
||||
*self.resolved_sticky_insets.borrow_mut() = Some(offsets);
|
||||
|
||||
if scroll_frame_size.is_none() {
|
||||
return None;
|
||||
|
@ -1610,8 +1606,7 @@ impl PositioningFragment {
|
|||
containing_block_info.new_for_non_absolute_descendants(&new_containing_block);
|
||||
|
||||
for child in &self.children {
|
||||
child.borrow_mut().build_stacking_context_tree(
|
||||
child,
|
||||
child.build_stacking_context_tree(
|
||||
display_list,
|
||||
&new_containing_block_info,
|
||||
stacking_context,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue