mirror of
https://github.com/servo/servo.git
synced 2025-08-15 10:25:32 +01:00
layout: Cache projected point in spatial node when hit testing (#38464)
Implement a simple one element cache for projected points in spatial nodes. This should reduce the amount matrix math done during hit testing. Testing: This should not change test results, but should improve performance a bit. Thus, tests are not necessary beyond existing performance tests. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
ec99e7a8b0
commit
0bf8676345
1 changed files with 17 additions and 5 deletions
|
@ -28,6 +28,9 @@ pub(crate) struct HitTest<'a> {
|
||||||
flags: ElementsFromPointFlags,
|
flags: ElementsFromPointFlags,
|
||||||
/// The point to test for this hit test, relative to the page.
|
/// The point to test for this hit test, relative to the page.
|
||||||
point_to_test: LayoutPoint,
|
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)>,
|
||||||
/// The stacking context tree against which to perform the hit test.
|
/// The stacking context tree against which to perform the hit test.
|
||||||
stacking_context_tree: &'a StackingContextTree,
|
stacking_context_tree: &'a StackingContextTree,
|
||||||
/// The resulting [`HitTestResultItems`] for this hit test.
|
/// The resulting [`HitTestResultItems`] for this hit test.
|
||||||
|
@ -45,6 +48,7 @@ impl<'a> HitTest<'a> {
|
||||||
let mut hit_test = Self {
|
let mut hit_test = Self {
|
||||||
flags,
|
flags,
|
||||||
point_to_test,
|
point_to_test,
|
||||||
|
projected_point_to_test: None,
|
||||||
stacking_context_tree,
|
stacking_context_tree,
|
||||||
results: Vec::new(),
|
results: Vec::new(),
|
||||||
clip_hit_test_results: HashMap::new(),
|
clip_hit_test_results: HashMap::new(),
|
||||||
|
@ -80,9 +84,18 @@ impl<'a> HitTest<'a> {
|
||||||
/// returning `None` if the transformation is uninvertible or the point cannot be
|
/// returning `None` if the transformation is uninvertible or the point cannot be
|
||||||
/// projected into the spatial node.
|
/// projected into the spatial node.
|
||||||
fn location_in_spatial_node(
|
fn location_in_spatial_node(
|
||||||
&self,
|
&mut self,
|
||||||
scroll_tree_node_id: ScrollTreeNodeId,
|
scroll_tree_node_id: ScrollTreeNodeId,
|
||||||
) -> Option<(LayoutPoint, LayoutTransform)> {
|
) -> Option<(LayoutPoint, LayoutTransform)> {
|
||||||
|
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 =>
|
||||||
|
{
|
||||||
|
return Some((projected_point, transform));
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
|
||||||
let transform = self
|
let transform = self
|
||||||
.stacking_context_tree
|
.stacking_context_tree
|
||||||
.compositor_info
|
.compositor_info
|
||||||
|
@ -103,11 +116,10 @@ impl<'a> HitTest<'a> {
|
||||||
let z =
|
let z =
|
||||||
-(point.x * transform.m13 + point.y * transform.m23 + transform.m43) / transform.m33;
|
-(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 = transform.transform_point3d(Point3D::new(point.x, point.y, z))?;
|
||||||
|
let projected_point = Point2D::new(projected_point.x, projected_point.y);
|
||||||
|
|
||||||
Some((
|
self.projected_point_to_test = Some((scroll_tree_node_id, projected_point, transform));
|
||||||
Point2D::new(projected_point.x, projected_point.y),
|
Some((projected_point, transform))
|
||||||
transform,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue