layout: Only create a LayoutContext if restyling (#37726)

The creation of `LayoutContext` does more work than necessary if layout
just needs to do something like make a display list and not restyle and
relayout. This change makes it so that these kind of non-restyle layouts
do not need to create a display list. In addition, the creation of
`LayoutContext` is better encapsulate

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2025-06-27 17:01:30 +02:00 committed by GitHub
parent 5e44582277
commit 9232b0f550
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 208 additions and 196 deletions

View file

@ -4,7 +4,6 @@
use std::sync::Arc;
use base::id::PipelineId;
use euclid::Size2D;
use fnv::FnvHashMap;
use fonts::FontContext;
@ -26,10 +25,8 @@ use webrender_api::units::{DeviceIntSize, DeviceSize};
pub(crate) type CachedImageOrError = Result<CachedImage, ResolveImageError>;
pub struct LayoutContext<'a> {
pub id: PipelineId,
pub(crate) struct LayoutContext<'a> {
pub use_rayon: bool,
pub origin: ImmutableOrigin,
/// Bits shared by the layout and style system.
pub style_context: SharedStyleContext<'a>,
@ -37,31 +34,12 @@ pub struct LayoutContext<'a> {
/// A FontContext to be used during layout.
pub font_context: Arc<FontContext>,
/// Reference to the script thread image cache.
pub image_cache: Arc<dyn ImageCache>,
/// A list of in-progress image loads to be shared with the script thread.
pub pending_images: Mutex<Vec<PendingImage>>,
/// A list of fully loaded vector images that need to be rasterized to a specific
/// size determined by layout. This will be shared with the script thread.
pub pending_rasterization_images: Mutex<Vec<PendingRasterizationImage>>,
/// A collection of `<iframe>` sizes to send back to script.
pub iframe_sizes: Mutex<IFrameSizes>,
// A cache that maps image resources used in CSS (e.g as the `url()` value
// for `background-image` or `content` property) to the final resolved image data.
pub resolved_images_cache:
Arc<RwLock<FnvHashMap<(ServoUrl, UsePlaceholder), CachedImageOrError>>>,
/// A shared reference to script's map of DOM nodes with animated images. This is used
/// to manage image animations in script and inform the script about newly animating
/// nodes.
pub node_to_animating_image_map: Arc<RwLock<FxHashMap<OpaqueNode, ImageAnimationState>>>,
/// The DOM node that is highlighted by the devtools inspector, if any
pub highlighted_dom_node: Option<OpaqueNode>,
/// An [`ImageResolver`] used for resolving images during box and fragment
/// tree construction. Later passed to display list construction.
pub image_resolver: Arc<ImageResolver>,
}
pub enum ResolvedImage<'a> {
@ -74,15 +52,6 @@ pub enum ResolvedImage<'a> {
},
}
impl Drop for LayoutContext<'_> {
fn drop(&mut self) {
if !std::thread::panicking() {
assert!(self.pending_images.lock().is_empty());
assert!(self.pending_rasterization_images.lock().is_empty());
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum ResolveImageError {
LoadError,
@ -103,12 +72,44 @@ pub(crate) enum LayoutImageCacheResult {
LoadError,
}
impl LayoutContext<'_> {
#[inline(always)]
pub fn shared_context(&self) -> &SharedStyleContext {
&self.style_context
}
pub(crate) struct ImageResolver {
/// The origin of the `Document` that this [`ImageResolver`] resolves images for.
pub origin: ImmutableOrigin,
/// Reference to the script thread image cache.
pub image_cache: Arc<dyn ImageCache>,
/// A list of in-progress image loads to be shared with the script thread.
pub pending_images: Mutex<Vec<PendingImage>>,
/// A list of fully loaded vector images that need to be rasterized to a specific
/// size determined by layout. This will be shared with the script thread.
pub pending_rasterization_images: Mutex<Vec<PendingRasterizationImage>>,
/// A shared reference to script's map of DOM nodes with animated images. This is used
/// to manage image animations in script and inform the script about newly animating
/// nodes.
pub node_to_animating_image_map: Arc<RwLock<FxHashMap<OpaqueNode, ImageAnimationState>>>,
// A cache that maps image resources used in CSS (e.g as the `url()` value
// for `background-image` or `content` property) to the final resolved image data.
pub resolved_images_cache:
Arc<RwLock<FnvHashMap<(ServoUrl, UsePlaceholder), CachedImageOrError>>>,
/// The current animation timeline value used to properly initialize animating images.
pub animation_timeline_value: f64,
}
impl Drop for ImageResolver {
fn drop(&mut self) {
if !std::thread::panicking() {
assert!(self.pending_images.lock().is_empty());
assert!(self.pending_rasterization_images.lock().is_empty());
}
}
}
impl ImageResolver {
pub(crate) fn get_or_request_image_or_meta(
&self,
node: OpaqueNode,
@ -155,18 +156,14 @@ impl LayoutContext<'_> {
}
}
pub fn handle_animated_image(&self, node: OpaqueNode, image: Arc<RasterImage>) {
pub(crate) fn handle_animated_image(&self, node: OpaqueNode, image: Arc<RasterImage>) {
let mut map = self.node_to_animating_image_map.write();
if !image.should_animate() {
map.remove(&node);
return;
}
let new_image_animation_state = || {
ImageAnimationState::new(
image.clone(),
self.shared_context().current_time_for_animations,
)
};
let new_image_animation_state =
|| ImageAnimationState::new(image.clone(), self.animation_timeline_value);
let entry = map.entry(node).or_insert_with(new_image_animation_state);
@ -218,7 +215,7 @@ impl LayoutContext<'_> {
}
}
pub fn rasterize_vector_image(
pub(crate) fn rasterize_vector_image(
&self,
image_id: PendingImageId,
size: DeviceIntSize,
@ -237,7 +234,7 @@ impl LayoutContext<'_> {
result
}
pub fn resolve_image<'a>(
pub(crate) fn resolve_image<'a>(
&self,
node: Option<OpaqueNode>,
image: &'a Image,