mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
layout: Allow changes transform
and filter
to skip layout
Chaneges to `transform` and `filter`-related properties do not need a new layout. Instead, they can simply cause a regeneration of the display list. The one caveat is that any pre-existing compositor scroll tree needs to be patched up with new reference frame values before being sent to the compositor. This should improve performance of `transform`-only changes, commonly used during animations. Co-authored-by: Oriol Brufau <obrufau@igalia.com> Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
325ac9e416
commit
6431aba718
4 changed files with 122 additions and 118 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -6634,7 +6634,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"cssparser",
|
"cssparser",
|
||||||
|
@ -6929,7 +6929,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo_arc"
|
name = "servo_arc"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
|
@ -7390,7 +7390,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo"
|
name = "stylo"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
@ -7448,7 +7448,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_atoms"
|
name = "stylo_atoms"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"string_cache",
|
"string_cache",
|
||||||
"string_cache_codegen",
|
"string_cache_codegen",
|
||||||
|
@ -7457,12 +7457,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_config"
|
name = "stylo_config"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_derive"
|
name = "stylo_derive"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -7474,7 +7474,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_dom"
|
name = "stylo_dom"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"stylo_malloc_size_of",
|
"stylo_malloc_size_of",
|
||||||
|
@ -7483,7 +7483,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_malloc_size_of"
|
name = "stylo_malloc_size_of"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
"cssparser",
|
"cssparser",
|
||||||
|
@ -7500,12 +7500,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_static_prefs"
|
name = "stylo_static_prefs"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stylo_traits"
|
name = "stylo_traits"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units",
|
"app_units",
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
|
@ -7914,7 +7914,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "to_shmem"
|
name = "to_shmem"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cssparser",
|
"cssparser",
|
||||||
"servo_arc",
|
"servo_arc",
|
||||||
|
@ -7927,7 +7927,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "to_shmem_derive"
|
name = "to_shmem_derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/stylo?branch=2025-05-01#1707256dd825f14e98161a49fdd6749f8ca0d506"
|
source = "git+https://github.com/servo/stylo?rev=refs%2Fpull%2F190%2Fhead#f63374493723974a6ec303f30a647ca22c3ae07b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
16
Cargo.toml
16
Cargo.toml
|
@ -119,7 +119,7 @@ rustls-pemfile = "2.0"
|
||||||
rustls-pki-types = "1.12"
|
rustls-pki-types = "1.12"
|
||||||
script_layout_interface = { path = "components/shared/script_layout" }
|
script_layout_interface = { path = "components/shared/script_layout" }
|
||||||
script_traits = { path = "components/shared/script" }
|
script_traits = { path = "components/shared/script" }
|
||||||
selectors = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
selectors = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
serde = "1.0.219"
|
serde = "1.0.219"
|
||||||
serde_bytes = "0.11"
|
serde_bytes = "0.11"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -127,7 +127,7 @@ servo-media = { git = "https://github.com/servo/media" }
|
||||||
servo-media-dummy = { git = "https://github.com/servo/media" }
|
servo-media-dummy = { git = "https://github.com/servo/media" }
|
||||||
servo-media-gstreamer = { git = "https://github.com/servo/media" }
|
servo-media-gstreamer = { git = "https://github.com/servo/media" }
|
||||||
servo-tracing = { path = "components/servo_tracing" }
|
servo-tracing = { path = "components/servo_tracing" }
|
||||||
servo_arc = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
servo_arc = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
smallbitvec = "2.6.0"
|
smallbitvec = "2.6.0"
|
||||||
smallvec = "1.15"
|
smallvec = "1.15"
|
||||||
snapshot = { path = "./components/shared/snapshot" }
|
snapshot = { path = "./components/shared/snapshot" }
|
||||||
|
@ -136,12 +136,12 @@ string_cache = "0.8"
|
||||||
string_cache_codegen = "0.5"
|
string_cache_codegen = "0.5"
|
||||||
strum = "0.26"
|
strum = "0.26"
|
||||||
strum_macros = "0.26"
|
strum_macros = "0.26"
|
||||||
stylo = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
stylo = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
stylo_atoms = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
stylo_atoms = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
stylo_config = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
stylo_config = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
stylo_dom = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
stylo_dom = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
stylo_malloc_size_of = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
stylo_malloc_size_of = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
stylo_traits = { git = "https://github.com/servo/stylo", branch = "2025-05-01" }
|
stylo_traits = { git = "https://github.com/servo/stylo", rev = "refs/pull/190/head" }
|
||||||
surfman = { git = "https://github.com/servo/surfman", rev = "f7688b4585f9e0b5d4bf8ee8e4a91e82349610b1", features = ["chains"] }
|
surfman = { git = "https://github.com/servo/surfman", rev = "f7688b4585f9e0b5d4bf8ee8e4a91e82349610b1", features = ["chains"] }
|
||||||
syn = { version = "2", default-features = false, features = ["clone-impls", "derive", "parsing"] }
|
syn = { version = "2", default-features = false, features = ["clone-impls", "derive", "parsing"] }
|
||||||
synstructure = "0.13"
|
synstructure = "0.13"
|
||||||
|
|
|
@ -14,8 +14,8 @@ use compositing_traits::display_list::{
|
||||||
AxesScrollSensitivity, CompositorDisplayListInfo, ReferenceFrameNodeInfo, ScrollableNodeInfo,
|
AxesScrollSensitivity, CompositorDisplayListInfo, ReferenceFrameNodeInfo, ScrollableNodeInfo,
|
||||||
SpatialTreeNodeInfo, StickyNodeInfo,
|
SpatialTreeNodeInfo, StickyNodeInfo,
|
||||||
};
|
};
|
||||||
use euclid::SideOffsets2D;
|
|
||||||
use euclid::default::{Point2D, Rect, Size2D};
|
use euclid::default::{Point2D, Rect, Size2D};
|
||||||
|
use euclid::{SideOffsets2D, Vector2D};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use servo_config::opts::DebugOptions;
|
use servo_config::opts::DebugOptions;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
|
@ -33,8 +33,7 @@ use style::values::generics::transform::{self, GenericRotate, GenericScale, Gene
|
||||||
use style::values::specified::box_::DisplayOutside;
|
use style::values::specified::box_::DisplayOutside;
|
||||||
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutTransform, LayoutVector2D};
|
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutTransform, LayoutVector2D};
|
||||||
use webrender_api::{self as wr, BorderRadius};
|
use webrender_api::{self as wr, BorderRadius};
|
||||||
use wr::StickyOffsetBounds;
|
use wr::units::LayoutSize;
|
||||||
use wr::units::{LayoutPixel, LayoutSize};
|
|
||||||
|
|
||||||
use super::ClipId;
|
use super::ClipId;
|
||||||
use super::clip::StackingContextTreeClipStore;
|
use super::clip::StackingContextTreeClipStore;
|
||||||
|
@ -113,6 +112,10 @@ pub(crate) struct StackingContextTree {
|
||||||
/// for things like `overflow`. More clips may be created later during WebRender
|
/// for things like `overflow`. More clips may be created later during WebRender
|
||||||
/// display list construction, but they are never added here.
|
/// display list construction, but they are never added here.
|
||||||
pub clip_store: StackingContextTreeClipStore,
|
pub clip_store: StackingContextTreeClipStore,
|
||||||
|
|
||||||
|
/// A vector of `Fragment`s that created spatial nodes in the Compositor's
|
||||||
|
/// `ScrollTree`. This is used to patch up spatial nodes during repaint-only layouts.
|
||||||
|
pub fragments_creating_spatial_nodes: Vec<Option<Fragment>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackingContextTree {
|
impl StackingContextTree {
|
||||||
|
@ -168,6 +171,10 @@ impl StackingContextTree {
|
||||||
root_stacking_context: StackingContext::create_root(root_scroll_node_id, debug),
|
root_stacking_context: StackingContext::create_root(root_scroll_node_id, debug),
|
||||||
compositor_info,
|
compositor_info,
|
||||||
clip_store: Default::default(),
|
clip_store: Default::default(),
|
||||||
|
// We are adding two empty slots here, because the Compositor `ScrollTree`
|
||||||
|
// adds two nodes for the root. These should never be patched during repaint
|
||||||
|
// only layouts.
|
||||||
|
fragments_creating_spatial_nodes: vec![None, None],
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut root_stacking_context = StackingContext::create_root(root_scroll_node_id, debug);
|
let mut root_stacking_context = StackingContext::create_root(root_scroll_node_id, debug);
|
||||||
|
@ -192,62 +199,35 @@ impl StackingContextTree {
|
||||||
stacking_context_tree
|
stacking_context_tree
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_reference_frame(
|
pub(crate) fn repair_scroll_tree_for_repaint_only_layout(&mut self) {
|
||||||
&mut self,
|
for (fragment, node) in self
|
||||||
origin: LayoutPoint,
|
.fragments_creating_spatial_nodes
|
||||||
parent_scroll_node_id: &ScrollTreeNodeId,
|
.iter()
|
||||||
transform_style: wr::TransformStyle,
|
.zip(self.compositor_info.scroll_tree.nodes.iter_mut())
|
||||||
transform: LayoutTransform,
|
{
|
||||||
kind: wr::ReferenceFrameKind,
|
let box_fragment = match fragment {
|
||||||
) -> ScrollTreeNodeId {
|
Some(Fragment::Box(box_fragment) | Fragment::Float(box_fragment)) => box_fragment,
|
||||||
self.compositor_info.scroll_tree.add_scroll_tree_node(
|
_ => continue,
|
||||||
Some(parent_scroll_node_id),
|
};
|
||||||
SpatialTreeNodeInfo::ReferenceFrame(ReferenceFrameNodeInfo {
|
|
||||||
origin,
|
|
||||||
transform_style,
|
|
||||||
transform,
|
|
||||||
kind,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn define_scroll_frame(
|
let SpatialTreeNodeInfo::ReferenceFrame(ref mut info) = node.info else {
|
||||||
&mut self,
|
continue;
|
||||||
parent_scroll_node_id: &ScrollTreeNodeId,
|
};
|
||||||
external_id: wr::ExternalScrollId,
|
|
||||||
content_rect: LayoutRect,
|
|
||||||
clip_rect: LayoutRect,
|
|
||||||
scroll_sensitivity: AxesScrollSensitivity,
|
|
||||||
) -> ScrollTreeNodeId {
|
|
||||||
self.compositor_info.scroll_tree.add_scroll_tree_node(
|
|
||||||
Some(parent_scroll_node_id),
|
|
||||||
SpatialTreeNodeInfo::Scroll(ScrollableNodeInfo {
|
|
||||||
external_id,
|
|
||||||
content_rect,
|
|
||||||
clip_rect,
|
|
||||||
scroll_sensitivity,
|
|
||||||
offset: LayoutVector2D::zero(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn define_sticky_frame(
|
// The argument to `reference_frame_node_info_if_necessary` here is only used to calculate the
|
||||||
&mut self,
|
// reference frame origin. If the origin changes, we will not be doing a repaint only layout,
|
||||||
parent_scroll_node_id: &ScrollTreeNodeId,
|
// and thus it's not necessary to pass a real value.
|
||||||
frame_rect: LayoutRect,
|
let box_fragment = box_fragment.borrow();
|
||||||
margins: SideOffsets2D<Option<f32>, LayoutPixel>,
|
let Some(reference_frame_data) =
|
||||||
vertical_offset_bounds: StickyOffsetBounds,
|
box_fragment.reference_frame_node_info_if_necessary(&PhysicalRect::zero())
|
||||||
horizontal_offset_bounds: StickyOffsetBounds,
|
else {
|
||||||
) -> ScrollTreeNodeId {
|
return;
|
||||||
self.compositor_info.scroll_tree.add_scroll_tree_node(
|
};
|
||||||
Some(parent_scroll_node_id),
|
|
||||||
SpatialTreeNodeInfo::Sticky(StickyNodeInfo {
|
info.kind = reference_frame_data.kind;
|
||||||
frame_rect,
|
info.transform = reference_frame_data.transform;
|
||||||
margins,
|
info.transform_style = reference_frame_data.transform_style;
|
||||||
vertical_offset_bounds,
|
}
|
||||||
horizontal_offset_bounds,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,11 +869,6 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReferenceFrameData {
|
|
||||||
origin: crate::geom::PhysicalPoint<Au>,
|
|
||||||
transform: LayoutTransform,
|
|
||||||
kind: wr::ReferenceFrameKind,
|
|
||||||
}
|
|
||||||
struct ScrollFrameData {
|
struct ScrollFrameData {
|
||||||
scroll_tree_node_id: ScrollTreeNodeId,
|
scroll_tree_node_id: ScrollTreeNodeId,
|
||||||
scroll_frame_rect: LayoutRect,
|
scroll_frame_rect: LayoutRect,
|
||||||
|
@ -966,8 +941,8 @@ impl BoxFragment {
|
||||||
parent_stacking_context: &mut StackingContext,
|
parent_stacking_context: &mut StackingContext,
|
||||||
text_decorations: &Arc<Vec<FragmentTextDecoration>>,
|
text_decorations: &Arc<Vec<FragmentTextDecoration>>,
|
||||||
) {
|
) {
|
||||||
let reference_frame_data =
|
let reference_frame_node_info =
|
||||||
match self.reference_frame_data_if_necessary(&containing_block.rect) {
|
match self.reference_frame_node_info_if_necessary(&containing_block.rect) {
|
||||||
Some(reference_frame_data) => reference_frame_data,
|
Some(reference_frame_data) => reference_frame_data,
|
||||||
None => {
|
None => {
|
||||||
return self.build_stacking_context_tree_maybe_creating_stacking_context(
|
return self.build_stacking_context_tree_maybe_creating_stacking_context(
|
||||||
|
@ -984,17 +959,24 @@ impl BoxFragment {
|
||||||
// <https://drafts.csswg.org/css-transforms/#transform-function-lists>
|
// <https://drafts.csswg.org/css-transforms/#transform-function-lists>
|
||||||
// > If a transform function causes the current transformation matrix of an object
|
// > If a transform function causes the current transformation matrix of an object
|
||||||
// > to be non-invertible, the object and its content do not get displayed.
|
// > to be non-invertible, the object and its content do not get displayed.
|
||||||
if !reference_frame_data.transform.is_invertible() {
|
if !reference_frame_node_info.transform.is_invertible() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_spatial_id = stacking_context_tree.push_reference_frame(
|
let reference_frame_origin = Vector2D::new(
|
||||||
reference_frame_data.origin.to_webrender(),
|
Au::from_f32_px(reference_frame_node_info.origin.x),
|
||||||
&containing_block.scroll_node_id,
|
Au::from_f32_px(reference_frame_node_info.origin.y),
|
||||||
self.style.get_box().transform_style.to_webrender(),
|
|
||||||
reference_frame_data.transform,
|
|
||||||
reference_frame_data.kind,
|
|
||||||
);
|
);
|
||||||
|
let new_spatial_id = stacking_context_tree
|
||||||
|
.compositor_info
|
||||||
|
.scroll_tree
|
||||||
|
.add_scroll_tree_node(
|
||||||
|
Some(&containing_block.scroll_node_id),
|
||||||
|
SpatialTreeNodeInfo::ReferenceFrame(reference_frame_node_info),
|
||||||
|
);
|
||||||
|
stacking_context_tree
|
||||||
|
.fragments_creating_spatial_nodes
|
||||||
|
.push(Some(fragment.clone()));
|
||||||
|
|
||||||
// WebRender reference frames establish a new coordinate system at their
|
// WebRender reference frames establish a new coordinate system at their
|
||||||
// origin (the border box of the fragment). We need to ensure that any
|
// origin (the border box of the fragment). We need to ensure that any
|
||||||
|
@ -1009,10 +991,9 @@ impl BoxFragment {
|
||||||
self.style
|
self.style
|
||||||
.establishes_containing_block_for_all_descendants(self.base.flags)
|
.establishes_containing_block_for_all_descendants(self.base.flags)
|
||||||
);
|
);
|
||||||
|
|
||||||
let adjusted_containing_block = ContainingBlock::new(
|
let adjusted_containing_block = ContainingBlock::new(
|
||||||
containing_block
|
containing_block.rect.translate(-reference_frame_origin),
|
||||||
.rect
|
|
||||||
.translate(-reference_frame_data.origin.to_vector()),
|
|
||||||
new_spatial_id,
|
new_spatial_id,
|
||||||
None,
|
None,
|
||||||
containing_block.clip_id,
|
containing_block.clip_id,
|
||||||
|
@ -1137,6 +1118,7 @@ impl BoxFragment {
|
||||||
.scroll_frame_size;
|
.scroll_frame_size;
|
||||||
|
|
||||||
if let Some(scroll_node_id) = self.build_sticky_frame_if_necessary(
|
if let Some(scroll_node_id) = self.build_sticky_frame_if_necessary(
|
||||||
|
&fragment,
|
||||||
stacking_context_tree,
|
stacking_context_tree,
|
||||||
&new_scroll_node_id,
|
&new_scroll_node_id,
|
||||||
&containing_block.rect,
|
&containing_block.rect,
|
||||||
|
@ -1209,6 +1191,7 @@ impl BoxFragment {
|
||||||
// We want to build the scroll frame after the background and border, because
|
// We want to build the scroll frame after the background and border, because
|
||||||
// they shouldn't scroll with the rest of the box content.
|
// they shouldn't scroll with the rest of the box content.
|
||||||
if let Some(overflow_frame_data) = self.build_overflow_frame_if_necessary(
|
if let Some(overflow_frame_data) = self.build_overflow_frame_if_necessary(
|
||||||
|
&fragment,
|
||||||
stacking_context_tree,
|
stacking_context_tree,
|
||||||
&new_scroll_node_id,
|
&new_scroll_node_id,
|
||||||
new_clip_id,
|
new_clip_id,
|
||||||
|
@ -1371,6 +1354,7 @@ impl BoxFragment {
|
||||||
|
|
||||||
fn build_overflow_frame_if_necessary(
|
fn build_overflow_frame_if_necessary(
|
||||||
&self,
|
&self,
|
||||||
|
fragment: &Fragment,
|
||||||
stacking_context_tree: &mut StackingContextTree,
|
stacking_context_tree: &mut StackingContextTree,
|
||||||
parent_scroll_node_id: &ScrollTreeNodeId,
|
parent_scroll_node_id: &ScrollTreeNodeId,
|
||||||
parent_clip_id: ClipId,
|
parent_clip_id: ClipId,
|
||||||
|
@ -1463,20 +1447,28 @@ impl BoxFragment {
|
||||||
stacking_context_tree.compositor_info.pipeline_id,
|
stacking_context_tree.compositor_info.pipeline_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
let sensitivity = AxesScrollSensitivity {
|
let scroll_sensitivity = AxesScrollSensitivity {
|
||||||
x: overflow.x.into(),
|
x: overflow.x.into(),
|
||||||
y: overflow.y.into(),
|
y: overflow.y.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let content_rect = self.reachable_scrollable_overflow_region().to_webrender();
|
let content_rect = self.reachable_scrollable_overflow_region().to_webrender();
|
||||||
|
let scroll_tree_node_id = stacking_context_tree
|
||||||
let scroll_tree_node_id = stacking_context_tree.define_scroll_frame(
|
.compositor_info
|
||||||
parent_scroll_node_id,
|
.scroll_tree
|
||||||
external_id,
|
.add_scroll_tree_node(
|
||||||
content_rect,
|
Some(parent_scroll_node_id),
|
||||||
scroll_frame_rect,
|
SpatialTreeNodeInfo::Scroll(ScrollableNodeInfo {
|
||||||
sensitivity,
|
external_id,
|
||||||
);
|
content_rect,
|
||||||
|
clip_rect: scroll_frame_rect,
|
||||||
|
scroll_sensitivity,
|
||||||
|
offset: LayoutVector2D::zero(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
stacking_context_tree
|
||||||
|
.fragments_creating_spatial_nodes
|
||||||
|
.push(Some(fragment.clone()));
|
||||||
|
|
||||||
Some(OverflowFrameData {
|
Some(OverflowFrameData {
|
||||||
clip_id,
|
clip_id,
|
||||||
|
@ -1489,6 +1481,7 @@ impl BoxFragment {
|
||||||
|
|
||||||
fn build_sticky_frame_if_necessary(
|
fn build_sticky_frame_if_necessary(
|
||||||
&self,
|
&self,
|
||||||
|
fragment: &Fragment,
|
||||||
stacking_context_tree: &mut StackingContextTree,
|
stacking_context_tree: &mut StackingContextTree,
|
||||||
parent_scroll_node_id: &ScrollTreeNodeId,
|
parent_scroll_node_id: &ScrollTreeNodeId,
|
||||||
containing_block_rect: &PhysicalRect<Au>,
|
containing_block_rect: &PhysicalRect<Au>,
|
||||||
|
@ -1559,22 +1552,30 @@ impl BoxFragment {
|
||||||
offsets.left.non_auto().map(|v| v.to_f32_px()),
|
offsets.left.non_auto().map(|v| v.to_f32_px()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let sticky_node_id = stacking_context_tree.define_sticky_frame(
|
let sticky_node_id = stacking_context_tree
|
||||||
parent_scroll_node_id,
|
.compositor_info
|
||||||
frame_rect,
|
.scroll_tree
|
||||||
margins,
|
.add_scroll_tree_node(
|
||||||
vertical_offset_bounds,
|
Some(parent_scroll_node_id),
|
||||||
horizontal_offset_bounds,
|
SpatialTreeNodeInfo::Sticky(StickyNodeInfo {
|
||||||
);
|
frame_rect,
|
||||||
|
margins,
|
||||||
|
vertical_offset_bounds,
|
||||||
|
horizontal_offset_bounds,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
stacking_context_tree
|
||||||
|
.fragments_creating_spatial_nodes
|
||||||
|
.push(Some(fragment.clone()));
|
||||||
|
|
||||||
Some(sticky_node_id)
|
Some(sticky_node_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optionally returns the data for building a reference frame, without yet building it.
|
/// Optionally returns the data for building a reference frame, without yet building it.
|
||||||
fn reference_frame_data_if_necessary(
|
fn reference_frame_node_info_if_necessary(
|
||||||
&self,
|
&self,
|
||||||
containing_block_rect: &PhysicalRect<Au>,
|
containing_block_rect: &PhysicalRect<Au>,
|
||||||
) -> Option<ReferenceFrameData> {
|
) -> Option<ReferenceFrameNodeInfo> {
|
||||||
if !self
|
if !self
|
||||||
.style
|
.style
|
||||||
.has_effective_transform_or_perspective(self.base.flags)
|
.has_effective_transform_or_perspective(self.base.flags)
|
||||||
|
@ -1612,9 +1613,10 @@ impl BoxFragment {
|
||||||
(None, None) => unreachable!(),
|
(None, None) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(ReferenceFrameData {
|
Some(ReferenceFrameNodeInfo {
|
||||||
origin: border_rect.origin,
|
origin: border_rect.origin.to_webrender(),
|
||||||
transform: reference_frame_transform,
|
transform: reference_frame_transform,
|
||||||
|
transform_style: self.style.get_box().transform_style.to_webrender(),
|
||||||
kind: reference_frame_kind,
|
kind: reference_frame_kind,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -846,10 +846,12 @@ impl LayoutThread {
|
||||||
let Some(fragment_tree) = &*self.fragment_tree.borrow() else {
|
let Some(fragment_tree) = &*self.fragment_tree.borrow() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if !damage.contains(RestyleDamage::REBUILD_STACKING_CONTEXT) &&
|
|
||||||
self.stacking_context_tree.borrow().is_some()
|
if !damage.contains(RestyleDamage::REBUILD_STACKING_CONTEXT) {
|
||||||
{
|
if let Some(stacking_context_tree) = &mut *self.stacking_context_tree.borrow_mut() {
|
||||||
return;
|
stacking_context_tree.repair_scroll_tree_for_repaint_only_layout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let viewport_size = self.stylist.device().au_viewport_size();
|
let viewport_size = self.stylist.device().au_viewport_size();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue