dependencies: Upgrade to WebRender 0.64 (#31486)

This brings the version of WebRender used in Servo up-to-date with Gecko
upstream. The big change here is that HiDPI is no longer handled via
WebRender. Instead this happens via a scale applied to the root layer in
the compositor. In addition to this change, various changes are made to
Servo to adapt to the new WebRender API.

Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Martin Robinson 2024-03-14 18:40:54 +01:00 committed by GitHub
parent 4597aeae5f
commit ad37a54f59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
102 changed files with 704 additions and 600 deletions

View file

@ -29,6 +29,7 @@ use log::{debug, warn};
use msg::constellation_msg::{BrowsingContextId, PipelineId};
use net_traits::image_cache::UsePlaceholder;
use range::Range;
use script_traits::compositor::ScrollSensitivity;
use servo_config::opts;
use servo_geometry::{self, MaxRect};
use style::color::AbsoluteColor;
@ -51,7 +52,7 @@ use webrender_api::units::{LayoutRect, LayoutTransform, LayoutVector2D};
use webrender_api::{
self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF, ColorU,
ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LineStyle, NinePatchBorder,
NinePatchBorderSource, NormalBorder, PropertyBinding, ScrollSensitivity, StickyOffsetBounds,
NinePatchBorderSource, NormalBorder, PropertyBinding, StickyOffsetBounds,
};
use crate::block::BlockFlow;
@ -384,6 +385,7 @@ impl<'a> DisplayListBuildState<'a> {
&self,
clip_rect: Rect<Au>,
node: OpaqueNode,
unique_id: u64,
cursor: Option<Cursor>,
section: DisplayListSection,
) -> BaseDisplayItem {
@ -397,6 +399,7 @@ impl<'a> DisplayListBuildState<'a> {
self.create_base_display_item_with_clipping_and_scrolling(
clip_rect,
node,
unique_id,
cursor,
section,
clipping_and_scrolling,
@ -407,12 +410,17 @@ impl<'a> DisplayListBuildState<'a> {
&self,
clip_rect: Rect<Au>,
node: OpaqueNode,
unique_id: u64,
cursor: Option<Cursor>,
section: DisplayListSection,
clipping_and_scrolling: ClippingAndScrolling,
) -> BaseDisplayItem {
BaseDisplayItem::new(
DisplayItemMetadata { node, cursor },
DisplayItemMetadata {
node,
unique_id,
cursor,
},
clip_rect.to_layout(),
section,
self.current_stacking_context_id,
@ -702,6 +710,7 @@ impl Fragment {
let base = state.create_base_display_item(
bounds,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
display_list_section,
);
@ -842,6 +851,7 @@ impl Fragment {
let base = state.create_base_display_item(
placement.clip_rect,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
display_list_section,
);
@ -964,6 +974,7 @@ impl Fragment {
let base = state.create_base_display_item(
placement.clip_rect,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
display_list_section,
);
@ -1040,6 +1051,7 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
display_list_section,
);
@ -1126,6 +1138,7 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
display_list_section,
);
@ -1221,7 +1234,7 @@ impl Fragment {
)?;
width = image.width;
height = image.height;
NinePatchBorderSource::Image(image.key?)
NinePatchBorderSource::Image(image.key?, ImageRendering::Auto)
},
Image::PaintWorklet(ref paint_worklet) => {
let image = self.get_webrender_image_for_paint_worklet(
@ -1232,7 +1245,7 @@ impl Fragment {
)?;
width = image.width;
height = image.height;
NinePatchBorderSource::Image(image.key?)
NinePatchBorderSource::Image(image.key?, ImageRendering::Auto)
},
Image::Gradient(ref gradient) => match **gradient {
Gradient::Linear {
@ -1288,7 +1301,6 @@ impl Fragment {
fill: border_image_fill,
repeat_horizontal: border_image_repeat.0.to_layout(),
repeat_vertical: border_image_repeat.1.to_layout(),
outset: SideOffsets2D::zero(),
});
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
@ -1340,6 +1352,7 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
DisplayListSection::Outlines,
);
@ -1372,6 +1385,7 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
DisplayListSection::Content,
);
@ -1402,12 +1416,13 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(style, Cursor::Default),
DisplayListSection::Content,
);
// TODO(gw): Use a better estimate for wavy line thickness.
let area = baseline.to_layout();
let wavy_line_thickness = (0.33 * area.size.height).ceil();
let wavy_line_thickness = (0.33 * area.size().height).ceil();
state.add_display_item(DisplayItem::Line(CommonDisplayItem::new(
base,
webrender_api::LineDisplayItem {
@ -1432,6 +1447,7 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(&self.style, Cursor::Default),
DisplayListSection::Content,
);
@ -1475,6 +1491,7 @@ impl Fragment {
let base = state.create_base_display_item(
stacking_relative_border_box,
self.node,
self.unique_id(),
get_cursor(&self.style, Cursor::Default),
display_list_section,
);
@ -1522,6 +1539,7 @@ impl Fragment {
let base = state.create_base_display_item(
insertion_point_bounds,
self.node,
self.unique_id(),
get_cursor(&self.style, cursor),
display_list_section,
);
@ -1709,6 +1727,7 @@ impl Fragment {
let base = state.create_base_display_item_with_clipping_and_scrolling(
content_size,
self.node,
self.unique_id(),
// FIXME(emilio): Why does this ignore pointer-events?
get_cursor(&self.style, Cursor::Default).or(Some(Cursor::Default)),
display_list_section,
@ -1773,6 +1792,7 @@ impl Fragment {
state.create_base_display_item(
stacking_relative_border_box,
self.node,
self.unique_id(),
get_cursor(&self.style, Cursor::Default),
DisplayListSection::Content,
)
@ -1859,7 +1879,7 @@ impl Fragment {
// looks bogus.
state.iframe_sizes.insert(
browsing_context_id,
euclid::Size2D::new(bounds.size.width, bounds.size.height),
euclid::Size2D::new(bounds.size().width, bounds.size().height),
);
let pipeline_id = match fragment_info.pipeline_id {
@ -2067,6 +2087,7 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(&self.style, cursor),
DisplayListSection::Content,
);
@ -2230,13 +2251,14 @@ impl Fragment {
let base = state.create_base_display_item(
clip,
self.node,
self.unique_id(),
get_cursor(&self.style, Cursor::Default),
DisplayListSection::Content,
);
// TODO(gw): Use a better estimate for wavy line thickness.
let area = stacking_relative_box.to_layout();
let wavy_line_thickness = (0.33 * area.size.height).ceil();
let wavy_line_thickness = (0.33 * area.size().height).ceil();
state.add_display_item(DisplayItem::Line(CommonDisplayItem::new(
base,
webrender_api::LineDisplayItem {
@ -2945,8 +2967,15 @@ impl BaseFlow {
let mut color = THREAD_TINT_COLORS[thread_id as usize % THREAD_TINT_COLORS.len()];
color.a = 1.0;
let base =
state.create_base_display_item(self.clip, node, None, DisplayListSection::Content);
let base = state.create_base_display_item(
self.clip,
node,
// This item will never become a spatial tree node, so it's fine
// to pass 0 here.
0,
None,
DisplayListSection::Content,
);
let bounds = stacking_context_relative_bounds.inflate(Au::from_px(2), Au::from_px(2));
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
@ -3123,6 +3152,6 @@ trait ToF32Px {
impl ToF32Px for Rect<Au> {
type Output = LayoutRect;
fn to_f32_px(&self) -> LayoutRect {
LayoutRect::from_untyped(&servo_geometry::au_rect_to_f32_rect(*self))
LayoutRect::from_untyped(&servo_geometry::au_rect_to_f32_rect(*self).to_box2d())
}
}

View file

@ -139,7 +139,7 @@ impl ToLayout for Point2D<Au> {
impl ToLayout for Rect<Au> {
type Type = wr::units::LayoutRect;
fn to_layout(&self) -> Self::Type {
wr::units::LayoutRect::new(self.origin.to_layout(), self.size.to_layout())
wr::units::LayoutRect::from_origin_and_size(self.origin.to_layout(), self.size.to_layout())
}
}

View file

@ -24,7 +24,7 @@ use gfx_traits::print_tree::PrintTree;
use gfx_traits::{self, StackingContextId};
use msg::constellation_msg::PipelineId;
use net_traits::image::base::Image;
use script_traits::compositor::ScrollTreeNodeId;
use script_traits::compositor::{ScrollSensitivity, ScrollTreeNodeId};
use serde::Serialize;
use servo_geometry::MaxRect;
use style::computed_values::_servo_top_layer::T as InTopLayer;
@ -32,9 +32,9 @@ pub use style::dom::OpaqueNode;
use webrender_api as wr;
use webrender_api::units::{LayoutPixel, LayoutRect, LayoutTransform};
use webrender_api::{
BorderRadius, ClipChainId, ClipId, ClipMode, CommonItemProperties, ComplexClipRegion,
ExternalScrollId, FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode,
PrimitiveFlags, ScrollSensitivity, Shadow, SpatialId, StickyOffsetBounds, TransformStyle,
BorderRadius, ClipChainId, ClipMode, CommonItemProperties, ComplexClipRegion, ExternalScrollId,
FilterOp, GlyphInstance, GradientStop, ImageKey, MixBlendMode, PrimitiveFlags, Shadow,
SpatialId, StickyOffsetBounds, TransformStyle,
};
/// The factor that we multiply the blur radius by in order to inflate the boundaries of display
@ -479,6 +479,7 @@ impl BaseDisplayItem {
BaseDisplayItem {
metadata: DisplayItemMetadata {
node: OpaqueNode(0),
unique_id: 0,
cursor: None,
},
// Create a rectangle of maximal size.
@ -495,7 +496,7 @@ impl BaseDisplayItem {
pub fn empty_common_item_properties() -> CommonItemProperties {
CommonItemProperties {
clip_rect: LayoutRect::max_rect(),
clip_id: ClipId::root(wr::PipelineId::dummy()),
clip_chain_id: ClipChainId::INVALID,
spatial_id: SpatialId::root_scroll_node(wr::PipelineId::dummy()),
flags: PrimitiveFlags::empty(),
}
@ -553,6 +554,8 @@ impl fmt::Debug for ClippingRegion {
pub struct DisplayItemMetadata {
/// The DOM node from which this display item originated.
pub node: OpaqueNode,
/// The unique fragment id of the fragment of this item.
pub unique_id: u64,
/// The value of the `cursor` property when the mouse hovers over this display item. If `None`,
/// this display item is ineligible for pointer events (`pointer-events: none`).
pub cursor: Option<Cursor>,

View file

@ -10,12 +10,14 @@
use gfx_traits::WebRenderEpochToU16;
use log::trace;
use msg::constellation_msg::PipelineId;
use script_traits::compositor::{CompositorDisplayListInfo, ScrollTreeNodeId, ScrollableNodeInfo};
use script_traits::compositor::{
CompositorDisplayListInfo, ScrollSensitivity, ScrollTreeNodeId, ScrollableNodeInfo,
};
use webrender_api::units::{LayoutPoint, LayoutSize, LayoutVector2D};
use webrender_api::{
self, ClipChainId, ClipId, CommonItemProperties, DisplayItem as WrDisplayItem,
DisplayListBuilder, Epoch, PrimitiveFlags, PropertyBinding, PushStackingContextDisplayItem,
RasterSpace, ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext,
DisplayListBuilder, Epoch, HasScrollLinkedEffect, PrimitiveFlags, PropertyBinding, RasterSpace,
ReferenceFrameKind, SpaceAndClipInfo, SpatialId, SpatialTreeItemKey,
};
use crate::display_list::items::{
@ -32,7 +34,6 @@ impl<'a> ClipScrollState<'a> {
fn new(
clip_scroll_nodes: &'a mut Vec<ClipScrollNode>,
compositor_info: CompositorDisplayListInfo,
builder: &mut DisplayListBuilder,
) -> Self {
let mut state = ClipScrollState {
clip_scroll_nodes,
@ -48,9 +49,7 @@ impl<'a> ClipScrollState<'a> {
Some(state.compositor_info.root_reference_frame_id);
state.clip_scroll_nodes[1].scroll_node_id = Some(state.compositor_info.root_scroll_node_id);
let root_clip_chain =
builder.define_clip_chain(None, [ClipId::root(state.compositor_info.pipeline_id)]);
let root_clip_chain = ClipChainId::INVALID;
state.add_clip_node_mapping(0, root_clip_chain);
state.add_clip_node_mapping(1, root_clip_chain);
@ -100,6 +99,25 @@ impl<'a> ClipScrollState<'a> {
self.clip_scroll_nodes[index].scroll_node_id =
self.clip_scroll_nodes[parent_index].scroll_node_id
}
pub fn define_clip_chain<I>(
&self,
builder: &mut DisplayListBuilder,
parent: ClipChainId,
clips: I,
) -> ClipChainId
where
I: IntoIterator<Item = ClipId>,
I::IntoIter: ExactSizeIterator + Clone,
{
// We use INVALID to mean "no clipping", but that cannot be passed as an argument
// to `define_clip_chain()`, so it must be converted into `None`.
let parent = match parent {
ClipChainId::INVALID => None,
parent => Some(parent),
};
builder.define_clip_chain(parent, clips)
}
}
/// Contentful paint, for the purpose of
@ -117,8 +135,9 @@ impl DisplayList {
) -> (DisplayListBuilder, CompositorDisplayListInfo, IsContentful) {
let webrender_pipeline = pipeline_id.to_webrender();
let mut builder = DisplayListBuilder::new(webrender_pipeline);
builder.begin();
let content_size = self.bounds().size;
let content_size = self.bounds().size();
let mut state = ClipScrollState::new(
&mut self.clip_scroll_nodes,
CompositorDisplayListInfo::new(
@ -126,9 +145,8 @@ impl DisplayList {
content_size,
webrender_pipeline,
epoch,
webrender_api::ScrollSensitivity::ScriptAndInputEvents,
ScrollSensitivity::ScriptAndInputEvents,
),
&mut builder,
);
let mut is_contentful = IsContentful(false);
@ -141,6 +159,15 @@ impl DisplayList {
}
impl DisplayItem {
fn get_spatial_tree_item_key(
&self,
builder: &DisplayListBuilder,
node_index: usize,
) -> SpatialTreeItemKey {
let pipeline_tag = (builder.pipeline_id.0 as u64) << 32 | builder.pipeline_id.1 as u64;
SpatialTreeItemKey::new(pipeline_tag, node_index as u64)
}
fn convert_to_webrender(
&mut self,
state: &mut ClipScrollState,
@ -167,7 +194,7 @@ impl DisplayItem {
CommonItemProperties {
clip_rect: base.clip_rect,
spatial_id: current_scroll_node_id.spatial_id,
clip_id: ClipId::ClipChain(current_clip_chain_id),
clip_chain_id: current_clip_chain_id,
// TODO(gw): Make use of the WR backface visibility functionality.
flags: PrimitiveFlags::default(),
}
@ -191,12 +218,10 @@ impl DisplayItem {
);
builder.push_hit_test(
&CommonItemProperties {
clip_rect: bounds,
spatial_id: current_scroll_node_id.spatial_id,
clip_id: ClipId::ClipChain(current_clip_chain_id),
flags: PrimitiveFlags::default(),
},
bounds,
current_clip_chain_id,
current_scroll_node_id.spatial_id,
PrimitiveFlags::default(),
(hit_test_index as u64, state.compositor_info.epoch.as_u16()),
);
};
@ -268,7 +293,7 @@ impl DisplayItem {
builder.push_shadow(
&SpaceAndClipInfo {
spatial_id: common.spatial_id,
clip_id: common.clip_id,
clip_chain_id: common.clip_chain_id,
},
item.shadow,
true,
@ -287,7 +312,7 @@ impl DisplayItem {
common.clip_rect,
&SpaceAndClipInfo {
spatial_id: common.spatial_id,
clip_id: common.clip_id,
clip_chain_id: common.clip_chain_id,
},
item.iframe.to_webrender(),
true,
@ -315,6 +340,7 @@ impl DisplayItem {
ReferenceFrameKind::Transform {
is_2d_scale_translation: false,
should_snap: false,
paired_with_perspective: false,
},
),
(Some(t), Some(p)) => (
@ -326,15 +352,16 @@ impl DisplayItem {
(None, None) => unreachable!(),
};
let index = frame_index.to_index();
let new_spatial_id = builder.push_reference_frame(
stacking_context.bounds.origin,
stacking_context.bounds.min,
current_scroll_node_id.spatial_id,
stacking_context.transform_style,
PropertyBinding::Value(transform),
ref_frame,
self.get_spatial_tree_item_key(builder, index),
);
let index = frame_index.to_index();
state.add_clip_node_mapping(index, current_clip_chain_id);
state.register_spatial_node(
index,
@ -343,37 +370,32 @@ impl DisplayItem {
None,
);
bounds.origin = LayoutPoint::zero();
bounds.min = LayoutPoint::zero();
new_spatial_id
} else {
current_scroll_node_id.spatial_id
};
if !stacking_context.filters.is_empty() {
builder.push_item(&WrDisplayItem::SetFilterOps);
builder.push_iter(&stacking_context.filters);
}
// TODO(jdm): WebRender now requires us to create stacking context items
// with the IS_BLEND_CONTAINER flag enabled if any children
// of the stacking context have a blend mode applied.
// This will require additional tracking during layout
// before we start collecting stacking contexts so that
// information will be available when we reach this point.
let wr_item = PushStackingContextDisplayItem {
origin: bounds.origin,
builder.push_stacking_context(
bounds.min,
spatial_id,
prim_flags: PrimitiveFlags::default(),
stacking_context: StackingContext {
transform_style: stacking_context.transform_style,
mix_blend_mode: stacking_context.mix_blend_mode,
clip_id: None,
raster_space: RasterSpace::Screen,
flags: Default::default(),
},
};
PrimitiveFlags::default(),
None,
stacking_context.transform_style,
stacking_context.mix_blend_mode,
&stacking_context.filters,
&[],
&[],
RasterSpace::Screen,
Default::default(),
);
builder.push_item(&WrDisplayItem::PushStackingContext(wr_item));
IsContentful(false)
},
DisplayItem::PopStackingContext(ref item) => {
@ -392,43 +414,38 @@ impl DisplayItem {
let parent_spatial_id = state.webrender_spatial_id_for_index(parent_index);
let parent_clip_chain_id = state.webrender_clip_id_for_index(parent_index);
let parent_space_and_clip_info = SpaceAndClipInfo {
clip_id: ClipId::root(state.compositor_info.pipeline_id),
spatial_id: parent_spatial_id,
};
match node.node_type {
ClipScrollNodeType::Clip(clip_type) => {
let clip_id = match clip_type {
ClipType::Rect => {
builder.define_clip_rect(&parent_space_and_clip_info, item_rect)
builder.define_clip_rect(parent_spatial_id, item_rect)
},
ClipType::Rounded(complex) => {
builder.define_clip_rounded_rect(parent_spatial_id, complex)
},
ClipType::Rounded(complex) => builder
.define_clip_rounded_rect(&parent_space_and_clip_info, complex),
};
let clip_chain_id =
builder.define_clip_chain(Some(parent_clip_chain_id), [clip_id]);
state.define_clip_chain(builder, parent_clip_chain_id, [clip_id]);
state.add_clip_node_mapping(index, clip_chain_id);
state.add_spatial_node_mapping_to_parent_index(index, parent_index);
},
ClipScrollNodeType::ScrollFrame(scroll_sensitivity, external_id) => {
let clip_id =
builder.define_clip_rect(&parent_space_and_clip_info, item_rect);
let clip_id = builder.define_clip_rect(parent_spatial_id, item_rect);
let clip_chain_id =
builder.define_clip_chain(Some(parent_clip_chain_id), [clip_id]);
state.define_clip_chain(builder, parent_clip_chain_id, [clip_id]);
state.add_clip_node_mapping(index, clip_chain_id);
let spatial_id = builder
.define_scroll_frame(
&parent_space_and_clip_info,
external_id,
node.content_rect,
item_rect,
scroll_sensitivity,
LayoutVector2D::zero(),
)
.spatial_id;
let spatial_id = builder.define_scroll_frame(
parent_spatial_id,
external_id,
node.content_rect,
item_rect,
LayoutVector2D::zero(), /* external_scroll_offset */
0, /* scroll_offset_generation */
HasScrollLinkedEffect::No,
self.get_spatial_tree_item_key(builder, index),
);
state.register_spatial_node(
index,
@ -436,7 +453,7 @@ impl DisplayItem {
Some(parent_index),
Some(ScrollableNodeInfo {
external_id,
scrollable_size: node.content_rect.size - item_rect.size,
scrollable_size: node.content_rect.size() - item_rect.size(),
scroll_sensitivity,
offset: LayoutVector2D::zero(),
}),
@ -450,7 +467,8 @@ impl DisplayItem {
sticky_data.margins,
sticky_data.vertical_offset_bounds,
sticky_data.horizontal_offset_bounds,
LayoutVector2D::zero(),
LayoutVector2D::zero(), /* previously_applied_offset */
self.get_spatial_tree_item_key(builder, index),
);
state.add_clip_node_mapping(index, parent_clip_chain_id);