From 99530810ef6a7595b413fcae1d46af13bc15e76c Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Fri, 31 Aug 2018 09:53:40 +1000 Subject: [PATCH] Force all calls to project_rect to include a bounding rect. This greatly improves the accuracy of the clipper code when required to calculate the world rect for a primitive that crosses the near plane. This patch by itself doesn't fix anything specific, but when combined with the fixes that are in progress in the plane-split crate, it will allow correct world rect calculations for primitives that cross the near plane in various edge cases. --- webrender/src/clip.rs | 9 ++++++++- webrender/src/frame_builder.rs | 19 +++++++++++++++---- webrender/src/prim_store.rs | 27 +++++++++++++++++++++++++-- webrender/src/util.rs | 21 +++++++++++---------- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index 3b86eb89d1..85582f9ae7 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -425,6 +425,7 @@ impl ClipStore { gpu_cache: &mut GpuCache, resource_cache: &mut ResourceCache, device_pixel_scale: DevicePixelScale, + world_rect: &WorldRect, ) -> Option { let mut local_clip_rect = local_prim_clip_rect; let spatial_nodes = &clip_scroll_tree.spatial_nodes; @@ -550,6 +551,7 @@ impl ClipStore { node.item.get_clip_result_complex( transform, &world_clip_rect, + world_rect, ) } }; @@ -869,6 +871,7 @@ impl ClipItem { &self, transform: &LayoutToWorldTransform, prim_world_rect: &WorldRect, + world_rect: &WorldRect, ) -> ClipResult { let (clip_rect, inner_rect) = match *self { ClipItem::Rectangle(clip_rect, ClipMode::Clip) => { @@ -897,7 +900,11 @@ impl ClipItem { } } - let outer_clip_rect = match project_rect(transform, &clip_rect) { + let outer_clip_rect = match project_rect( + transform, + &clip_rect, + world_rect, + ) { Some(outer_clip_rect) => outer_clip_rect, None => return ClipResult::Partial, }; diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index a7d5bdc221..004652e436 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -24,7 +24,7 @@ use std::f32; use std::sync::Arc; use tiling::{Frame, RenderPass, RenderPassKind, RenderTargetContext}; use tiling::{ScrollbarPrimitive, SpecialRenderPasses}; -use util; +use util::{self, MaxRect}; #[derive(Clone, Copy, Debug, PartialEq)] @@ -108,14 +108,24 @@ impl PictureState { pub fn new( ref_spatial_node_index: SpatialNodeIndex, clip_scroll_tree: &ClipScrollTree, + world_rect: WorldRect, ) -> Self { - let map_local_to_pic = SpaceMapper::new(ref_spatial_node_index); - - let mut map_pic_to_world = SpaceMapper::new(SpatialNodeIndex(0)); + let mut map_pic_to_world = SpaceMapper::new( + SpatialNodeIndex(0), + world_rect, + ); map_pic_to_world.set_target_spatial_node( ref_spatial_node_index, clip_scroll_tree, ); + let pic_bounds = map_pic_to_world.unmap( + &world_rect, + ).unwrap_or(PictureRect::max_rect()); + + let map_local_to_pic = SpaceMapper::new( + ref_spatial_node_index, + pic_bounds, + ); PictureState { tasks: Vec::new(), @@ -246,6 +256,7 @@ impl FrameBuilder { let mut pic_state = PictureState::new( root_spatial_node_index, &frame_context.clip_scroll_tree, + frame_context.world_rect, ); let pic_context = self diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index b58d84539e..3d89bf36ff 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -116,14 +116,19 @@ pub struct SpaceMapper { kind: CoordinateSpaceMapping, pub ref_spatial_node_index: SpatialNodeIndex, current_target_spatial_node_index: SpatialNodeIndex, + bounds: TypedRect, } impl SpaceMapper where F: fmt::Debug { - pub fn new(ref_spatial_node_index: SpatialNodeIndex) -> Self { + pub fn new( + ref_spatial_node_index: SpatialNodeIndex, + bounds: TypedRect, + ) -> Self { SpaceMapper { kind: CoordinateSpaceMapping::Local, ref_spatial_node_index, current_target_spatial_node_index: ref_spatial_node_index, + bounds, } } @@ -161,6 +166,21 @@ impl SpaceMapper where F: fmt::Debug { } } + pub fn unmap(&self, rect: &TypedRect) -> Option> { + match self.kind { + CoordinateSpaceMapping::Local => { + Some(TypedRect::from_untyped(&rect.to_untyped())) + } + CoordinateSpaceMapping::Offset(ref offset) => { + let offset = TypedVector2D::new(-offset.x, -offset.y); + Some(TypedRect::from_untyped(&rect.translate(&offset).to_untyped())) + } + CoordinateSpaceMapping::Transform(ref transform) => { + transform.inverse_rect_footprint(rect) + } + } + } + pub fn map(&self, rect: &TypedRect) -> Option> { match self.kind { CoordinateSpaceMapping::Local => { @@ -170,7 +190,7 @@ impl SpaceMapper where F: fmt::Debug { Some(TypedRect::from_untyped(&rect.translate(offset).to_untyped())) } CoordinateSpaceMapping::Transform(ref transform) => { - match project_rect(transform, rect) { + match project_rect(transform, rect, &self.bounds) { Some(bounds) => { Some(bounds) } @@ -1601,6 +1621,7 @@ impl PrimitiveStore { let mut pic_state_for_children = PictureState::new( root_spatial_node_index, frame_context.clip_scroll_tree, + frame_context.world_rect, ); // Mark whether this picture has a complex coordinate system. @@ -1693,6 +1714,7 @@ impl PrimitiveStore { frame_state.gpu_cache, frame_state.resource_cache, frame_context.device_pixel_scale, + &frame_context.world_rect, ); let clip_chain = match clip_chain { @@ -2210,6 +2232,7 @@ impl Primitive { frame_state.gpu_cache, frame_state.resource_cache, frame_context.device_pixel_scale, + &frame_context.world_rect, ); match segment_clip_chain { diff --git a/webrender/src/util.rs b/webrender/src/util.rs index df6cd5314b..2b2189a188 100644 --- a/webrender/src/util.rs +++ b/webrender/src/util.rs @@ -22,7 +22,7 @@ pub trait MatrixHelpers { fn has_2d_inverse(&self) -> bool; fn exceeds_2d_scale(&self, limit: f64) -> bool; fn inverse_project(&self, target: &TypedPoint2D) -> Option>; - fn inverse_rect_footprint(&self, rect: &TypedRect) -> TypedRect; + fn inverse_rect_footprint(&self, rect: &TypedRect) -> Option>; fn transform_kind(&self) -> TransformedRectKind; fn is_simple_translation(&self) -> bool; fn is_simple_2d_translation(&self) -> bool; @@ -90,13 +90,13 @@ impl MatrixHelpers for TypedTransform3D { m.inverse().map(|inv| TypedPoint2D::new(inv.m31, inv.m32)) } - fn inverse_rect_footprint(&self, rect: &TypedRect) -> TypedRect { - TypedRect::from_points(&[ - self.inverse_project(&rect.origin).unwrap_or(TypedPoint2D::zero()), - self.inverse_project(&rect.top_right()).unwrap_or(TypedPoint2D::zero()), - self.inverse_project(&rect.bottom_left()).unwrap_or(TypedPoint2D::zero()), - self.inverse_project(&rect.bottom_right()).unwrap_or(TypedPoint2D::zero()), - ]) + fn inverse_rect_footprint(&self, rect: &TypedRect) -> Option> { + Some(TypedRect::from_points(&[ + self.inverse_project(&rect.origin)?, + self.inverse_project(&rect.top_right())?, + self.inverse_project(&rect.bottom_left())?, + self.inverse_project(&rect.bottom_right())?, + ])) } fn transform_kind(&self) -> TransformedRectKind { @@ -393,7 +393,7 @@ impl FastTransform { FastTransform::Transform { inverse: Some(ref inverse), is_2d: true, .. } => inverse.transform_rect(rect), FastTransform::Transform { ref transform, is_2d: false, .. } => - Some(transform.inverse_rect_footprint(rect)), + transform.inverse_rect_footprint(rect), FastTransform::Transform { inverse: None, .. } => None, } } @@ -446,6 +446,7 @@ pub type LayoutToWorldFastTransform = FastTransform; pub fn project_rect( transform: &TypedTransform3D, rect: &TypedRect, + bounds: &TypedRect, ) -> Option> where F: fmt::Debug { @@ -462,7 +463,7 @@ pub fn project_rect( let mut clipper = Clipper::new(); clipper.add_frustum( transform, - None, + Some(*bounds), ); let polygon = Polygon::from_rect(*rect, 1);