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:
Martin Robinson 2025-01-13 10:59:59 +01:00 committed by GitHub
parent c936dd6c4e
commit de780dcde4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 257 additions and 233 deletions

View file

@ -27,6 +27,7 @@ use style::Zero;
use url::Url;
use webrender_api::ImageKey;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
@ -334,23 +335,25 @@ impl ReplacedContents {
.as_ref()
.and_then(|image| image.id)
.map(|image_key| {
Fragment::Image(ImageFragment {
Fragment::Image(ArcRefCell::new(ImageFragment {
base: self.base_fragment_info.into(),
style: style.clone(),
rect,
clip,
image_key: Some(image_key),
})
}))
})
.into_iter()
.collect(),
ReplacedContentKind::Video(video) => vec![Fragment::Image(ImageFragment {
base: self.base_fragment_info.into(),
style: style.clone(),
rect,
clip,
image_key: video.as_ref().map(|video| video.image_key),
})],
ReplacedContentKind::Video(video) => {
vec![Fragment::Image(ArcRefCell::new(ImageFragment {
base: self.base_fragment_info.into(),
style: style.clone(),
rect,
clip,
image_key: video.as_ref().map(|video| video.image_key),
}))]
},
ReplacedContentKind::IFrame(iframe) => {
let size = Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px());
layout_context.iframe_sizes.lock().insert(
@ -361,13 +364,13 @@ impl ReplacedContents {
size,
},
);
vec![Fragment::IFrame(IFrameFragment {
vec![Fragment::IFrame(ArcRefCell::new(IFrameFragment {
base: self.base_fragment_info.into(),
style: style.clone(),
pipeline_id: iframe.pipeline_id,
browsing_context_id: iframe.browsing_context_id,
rect,
})]
}))]
},
ReplacedContentKind::Canvas(canvas_info) => {
if self.natural_size.width == Some(Au::zero()) ||
@ -392,13 +395,13 @@ impl ReplacedContents {
},
CanvasSource::Empty => return vec![],
};
vec![Fragment::Image(ImageFragment {
vec![Fragment::Image(ArcRefCell::new(ImageFragment {
base: self.base_fragment_info.into(),
style: style.clone(),
rect,
clip,
image_key: Some(image_key),
})]
}))]
},
}
}