diff --git a/Cargo.lock b/Cargo.lock index 3553f4ac595..07ea3bf6d4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6222,7 +6222,7 @@ dependencies = [ [[package]] name = "peek-poke" version = "0.3.0" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "euclid", "peek-poke-derive", @@ -6231,7 +6231,7 @@ dependencies = [ [[package]] name = "peek-poke-derive" version = "0.3.0" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "proc-macro2", "quote", @@ -7666,6 +7666,7 @@ dependencies = [ "euclid", "malloc_size_of_derive", "servo_malloc_size_of", + "webrender", "webrender_api", ] @@ -9656,7 +9657,7 @@ dependencies = [ [[package]] name = "webrender" version = "0.66.0" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "allocator-api2", "bincode", @@ -9691,7 +9692,7 @@ dependencies = [ [[package]] name = "webrender_api" version = "0.66.0" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "app_units", "bitflags 2.9.1", @@ -9712,7 +9713,7 @@ dependencies = [ [[package]] name = "webrender_build" version = "0.0.2" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "bitflags 2.9.1", "lazy_static", @@ -10424,7 +10425,7 @@ dependencies = [ [[package]] name = "wr_glyph_rasterizer" version = "0.1.0" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "core-foundation 0.9.4", "core-graphics", @@ -10449,7 +10450,7 @@ dependencies = [ [[package]] name = "wr_malloc_size_of" version = "0.2.0" -source = "git+https://github.com/servo/webrender?branch=0.67#ae2477d9a6da403e5b5dce8a17415a2cd1563074" +source = "git+https://github.com/servo/webrender?branch=0.67#15318d6627e91ec19fc0a44a7434b08673413140" dependencies = [ "app_units", "euclid", diff --git a/components/geometry/Cargo.toml b/components/geometry/Cargo.toml index 4d0eff19868..8634bc1d18c 100644 --- a/components/geometry/Cargo.toml +++ b/components/geometry/Cargo.toml @@ -16,4 +16,5 @@ app_units = { workspace = true } euclid = { workspace = true } malloc_size_of = { workspace = true } malloc_size_of_derive = { workspace = true } +webrender = { workspace = true } webrender_api = { workspace = true } diff --git a/components/geometry/lib.rs b/components/geometry/lib.rs index ce4ec707e08..300fe015b20 100644 --- a/components/geometry/lib.rs +++ b/components/geometry/lib.rs @@ -8,9 +8,10 @@ use app_units::{Au, MAX_AU, MIN_AU}; use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect, Size2D as UntypedSize2D}; use euclid::{Box2D, Length, Point2D, Scale, SideOffsets2D, Size2D, Vector2D}; use malloc_size_of_derive::MallocSizeOf; +use webrender::FastTransform; use webrender_api::units::{ - DeviceIntRect, DeviceIntSize, DevicePixel, FramebufferPixel, LayoutPoint, LayoutRect, - LayoutSize, + DeviceIntRect, DeviceIntSize, DevicePixel, FramebufferPixel, LayoutPixel, LayoutPoint, + LayoutRect, LayoutSize, }; // Units for use with euclid::length and euclid::scale_factor. @@ -46,6 +47,8 @@ pub type DeviceIndependentPoint = Point2D; pub type DeviceIndependentVector2D = Vector2D; pub type DeviceIndependentSize = Size2D; +pub type FastLayoutTransform = FastTransform; + // An Au is an "App Unit" and represents 1/60th of a CSS pixel. It was // originally proposed in 2002 as a standard unit of measure in Gecko. // See https://bugzilla.mozilla.org/show_bug.cgi?id=177805 for more info. diff --git a/components/layout/display_list/hit_test.rs b/components/layout/display_list/hit_test.rs index 4ce1c29333c..55368d8b7bd 100644 --- a/components/layout/display_list/hit_test.rs +++ b/components/layout/display_list/hit_test.rs @@ -7,16 +7,17 @@ use std::collections::HashMap; use app_units::Au; use base::id::ScrollTreeNodeId; use embedder_traits::Cursor; -use euclid::{Box2D, Point2D, Point3D, Vector2D}; +use euclid::{Box2D, Vector2D}; use kurbo::{Ellipse, Shape}; use layout_api::{ElementsFromPointFlags, ElementsFromPointResult}; +use servo_geometry::FastLayoutTransform; use style::computed_values::backface_visibility::T as BackfaceVisibility; use style::computed_values::pointer_events::T as PointerEvents; use style::computed_values::visibility::T as Visibility; use style::properties::ComputedValues; use style::values::computed::ui::CursorKind; use webrender_api::BorderRadius; -use webrender_api::units::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, RectExt}; +use webrender_api::units::{LayoutPoint, LayoutRect, LayoutSize, RectExt}; use crate::display_list::clip::{Clip, ClipId}; use crate::display_list::stacking_context::StackingContextSection; @@ -33,7 +34,7 @@ pub(crate) struct HitTest<'a> { point_to_test: LayoutPoint, /// A cached version of [`Self::point_to_test`] projected to a spatial node, to avoid /// doing a lot of matrix math over and over. - projected_point_to_test: Option<(ScrollTreeNodeId, LayoutPoint, LayoutTransform)>, + projected_point_to_test: Option<(ScrollTreeNodeId, LayoutPoint, FastLayoutTransform)>, /// The stacking context tree against which to perform the hit test. stacking_context_tree: &'a StackingContextTree, /// The resulting [`HitTestResultItems`] for this hit test. @@ -89,7 +90,7 @@ impl<'a> HitTest<'a> { fn location_in_spatial_node( &mut self, scroll_tree_node_id: ScrollTreeNodeId, - ) -> Option<(LayoutPoint, LayoutTransform)> { + ) -> Option<(LayoutPoint, FastLayoutTransform)> { match self.projected_point_to_test { Some((cached_scroll_tree_node_id, projected_point, transform)) if cached_scroll_tree_node_id == scroll_tree_node_id => @@ -105,21 +106,7 @@ impl<'a> HitTest<'a> { .scroll_tree .cumulative_root_to_node_transform(&scroll_tree_node_id)?; - // This comes from WebRender at `webrender/utils.rs`. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=1765204#c3. - // - // We are going from world coordinate space to spatial node coordinate space. - // Normally, that transformation happens in the opposite direction, but for hit - // testing everything is reversed. The result of the display transformation comes - // with a z-coordinate that we do not have access to here. - // - // We must solve for a value of z here that transforms to 0 (the value of z for our - // point). - let point = self.point_to_test; - let z = - -(point.x * transform.m13 + point.y * transform.m23 + transform.m43) / transform.m33; - let projected_point = transform.transform_point3d(Point3D::new(point.x, point.y, z))?; - let projected_point = Point2D::new(projected_point.x, projected_point.y); + let projected_point = transform.project_point2d(self.point_to_test)?; self.projected_point_to_test = Some((scroll_tree_node_id, projected_point, transform)); Some((projected_point, transform)) diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs index bec719f106c..ccdf243493f 100644 --- a/components/layout/display_list/mod.rs +++ b/components/layout/display_list/mod.rs @@ -272,7 +272,7 @@ impl DisplayListBuilder<'_> { info.origin, *parent_spatial_node_id, info.transform_style, - PropertyBinding::Value(info.transform), + PropertyBinding::Value(*info.transform.to_transform()), info.kind, spatial_tree_item_key, ); diff --git a/components/layout/display_list/stacking_context.rs b/components/layout/display_list/stacking_context.rs index 081dc1068eb..2eb0580f24a 100644 --- a/components/layout/display_list/stacking_context.rs +++ b/components/layout/display_list/stacking_context.rs @@ -234,7 +234,7 @@ impl StackingContextTree { origin, frame_origin_for_query, transform_style, - transform, + transform: transform.into(), kind, }), ) diff --git a/components/layout/query.rs b/components/layout/query.rs index 64364e9551e..4dc25096677 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -14,7 +14,7 @@ use layout_api::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafe use layout_api::{LayoutElementType, LayoutNodeType, OffsetParentResponse}; use script::layout_dom::ServoLayoutNode; use servo_arc::Arc as ServoArc; -use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect}; +use servo_geometry::{FastLayoutTransform, au_rect_to_f32_rect, f32_rect_to_au_rect}; use servo_url::ServoUrl; use style::computed_values::display::T as Display; use style::computed_values::position::T as Position; @@ -39,7 +39,6 @@ use style::values::specified::GenericGridTemplateComponent; use style::values::specified::box_::DisplayInside; use style::values::specified::text::TextTransformCase; use style_traits::{ParsingMode, ToCss}; -use webrender_api::units::LayoutTransform; use crate::ArcRefCell; use crate::display_list::StackingContextTree; @@ -55,7 +54,7 @@ use crate::taffy::SpecificTaffyGridInfo; fn root_transform_for_layout_node( scroll_tree: &ScrollTree, node: ServoLayoutNode<'_>, -) -> Option { +) -> Option { let fragments = node.fragments_for_pseudo(None); let box_fragment = fragments .first() @@ -90,7 +89,7 @@ pub(crate) fn process_content_box_request( return Some(rect_union); }; - Some(transform_au_rectangle(rect_union, transform)) + transform_au_rectangle(rect_union, transform) } pub(crate) fn process_content_boxes_request( @@ -110,7 +109,7 @@ pub(crate) fn process_content_boxes_request( }; content_boxes - .map(|rect| transform_au_rectangle(rect, transform)) + .filter_map(|rect| transform_au_rectangle(rect, transform)) .collect() } @@ -1150,9 +1149,17 @@ where Some(computed_values.clone_font()) } -fn transform_au_rectangle(rect_to_transform: Rect, transform: LayoutTransform) -> Rect { - transform - .outer_transformed_rect(&au_rect_to_f32_rect(rect_to_transform).cast_unit()) +fn transform_au_rectangle( + rect_to_transform: Rect, + transform: FastLayoutTransform, +) -> Option> { + let rect_to_transform = &au_rect_to_f32_rect(rect_to_transform).cast_unit(); + let outer_transformed_rect = match transform { + FastLayoutTransform::Offset(offset) => Some(rect_to_transform.translate(offset)), + FastLayoutTransform::Transform { transform, .. } => { + transform.outer_transformed_rect(rect_to_transform) + }, + }; + outer_transformed_rect .map(|transformed_rect| f32_rect_to_au_rect(transformed_rect.to_untyped())) - .unwrap_or(rect_to_transform) } diff --git a/components/shared/compositing/display_list.rs b/components/shared/compositing/display_list.rs index b2c93271e6e..604ef5b3bf4 100644 --- a/components/shared/compositing/display_list.rs +++ b/components/shared/compositing/display_list.rs @@ -11,13 +11,12 @@ use base::id::ScrollTreeNodeId; use base::print_tree::PrintTree; use bitflags::bitflags; use embedder_traits::ViewportDetails; -use euclid::{SideOffsets2D, Transform3D}; +use euclid::SideOffsets2D; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; +use servo_geometry::FastLayoutTransform; use style::values::specified::Overflow; -use webrender_api::units::{ - LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, -}; +use webrender_api::units::{LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutVector2D}; use webrender_api::{ Epoch, ExternalScrollId, PipelineId, ReferenceFrameKind, ScrollLocation, SpatialId, StickyOffsetBounds, TransformStyle, @@ -167,7 +166,7 @@ pub struct ReferenceFrameNodeInfo { /// Origin of this frame relative to the document for bounding box queries. pub frame_origin_for_query: LayoutPoint, pub transform_style: TransformStyle, - pub transform: LayoutTransform, + pub transform: FastLayoutTransform, pub kind: ReferenceFrameKind, } @@ -281,8 +280,8 @@ impl ScrollableNodeInfo { /// multiplication when transforms are not involved. #[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)] pub struct ScrollTreeNodeTransformationCache { - node_to_root_transform: LayoutTransform, - root_to_node_transform: Option, + node_to_root_transform: FastLayoutTransform, + root_to_node_transform: Option, } #[derive(Default)] @@ -604,7 +603,10 @@ impl ScrollTree { /// Find a transformation that can convert a point in the node coordinate system to a /// point in the root coordinate system. - pub fn cumulative_node_to_root_transform(&self, node_id: &ScrollTreeNodeId) -> LayoutTransform { + pub fn cumulative_node_to_root_transform( + &self, + node_id: &ScrollTreeNodeId, + ) -> FastLayoutTransform { let node = self.get_node(node_id); if let Some(cached_transforms) = node.transformation_cache.get() { return cached_transforms.node_to_root_transform; @@ -621,7 +623,7 @@ impl ScrollTree { pub fn cumulative_root_to_node_transform( &self, node_id: &ScrollTreeNodeId, - ) -> Option { + ) -> Option { let node = self.get_node(node_id); if let Some(cached_transforms) = node.transformation_cache.get() { return cached_transforms.root_to_node_transform; @@ -642,25 +644,16 @@ impl ScrollTree { None => (Default::default(), Default::default()), }; - let change_basis = - |transform: &Transform3D, x: f32, y: f32| { - let pre_translation = Transform3D::translation(x, y, 0.0); - let post_translation = Transform3D::translation(-x, -y, 0.0); - post_translation.then(transform).then(&pre_translation) - }; - let (node_to_parent_transform, parent_to_node_transform) = match &node.info { SpatialTreeNodeInfo::ReferenceFrame(info) => { // To apply a transformation we need to make sure the rectangle's // coordinate space is the same as reference frame's coordinate space. - let node_to_parent_transform = change_basis( - &info.transform, - info.frame_origin_for_query.x, - info.frame_origin_for_query.y, - ); + let offset = info.frame_origin_for_query.to_vector(); + let node_to_parent_transform = + info.transform.pre_translate(-offset).then_translate(offset); let parent_to_node_transform = - Transform3D::translation(-info.origin.x, -info.origin.y, 0.0); + FastLayoutTransform::Offset(-info.origin.to_vector()); let parent_to_node_transform = info .transform .inverse() @@ -675,20 +668,15 @@ impl ScrollTree { SpatialTreeNodeInfo::Scroll(info) => { sticky_info.nearest_scrolling_ancestor_viewport = info.clip_rect; sticky_info.nearest_scrolling_ancestor_offset = -info.offset; - - ( - Transform3D::translation(-info.offset.x, -info.offset.y, 0.0), - Some(Transform3D::translation(info.offset.x, info.offset.y, 0.0)), - ) + let offset_transform = FastLayoutTransform::Offset(-info.offset); + (offset_transform, offset_transform.inverse()) }, SpatialTreeNodeInfo::Sticky(info) => { let offset = info.calculate_sticky_offset(&sticky_info); sticky_info.nearest_scrolling_ancestor_offset += offset; - ( - Transform3D::translation(offset.x, offset.y, 0.0), - Some(Transform3D::translation(-offset.x, -offset.y, 0.0)), - ) + let offset_transform = FastLayoutTransform::Offset(offset); + (offset_transform, offset_transform.inverse()) }, }; @@ -845,7 +833,7 @@ impl CompositorDisplayListInfo { origin: Default::default(), frame_origin_for_query: Default::default(), transform_style: TransformStyle::Flat, - transform: LayoutTransform::identity(), + transform: FastLayoutTransform::identity(), kind: ReferenceFrameKind::default(), }), );