Skip to content

Commit

Permalink
Force all calls to project_rect to include a bounding rect.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gw3583 committed Aug 31, 2018
1 parent 6415faa commit 9953081
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 17 deletions.
9 changes: 8 additions & 1 deletion webrender/src/clip.rs
Expand Up @@ -425,6 +425,7 @@ impl ClipStore {
gpu_cache: &mut GpuCache,
resource_cache: &mut ResourceCache,
device_pixel_scale: DevicePixelScale,
world_rect: &WorldRect,
) -> Option<ClipChainInstance> {
let mut local_clip_rect = local_prim_clip_rect;
let spatial_nodes = &clip_scroll_tree.spatial_nodes;
Expand Down Expand Up @@ -550,6 +551,7 @@ impl ClipStore {
node.item.get_clip_result_complex(
transform,
&world_clip_rect,
world_rect,
)
}
};
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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,
};
Expand Down
19 changes: 15 additions & 4 deletions webrender/src/frame_builder.rs
Expand Up @@ -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)]
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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
Expand Down
27 changes: 25 additions & 2 deletions webrender/src/prim_store.rs
Expand Up @@ -116,14 +116,19 @@ pub struct SpaceMapper<F, T> {
kind: CoordinateSpaceMapping<F, T>,
pub ref_spatial_node_index: SpatialNodeIndex,
current_target_spatial_node_index: SpatialNodeIndex,
bounds: TypedRect<f32, T>,
}

impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
pub fn new(ref_spatial_node_index: SpatialNodeIndex) -> Self {
pub fn new(
ref_spatial_node_index: SpatialNodeIndex,
bounds: TypedRect<f32, T>,
) -> Self {
SpaceMapper {
kind: CoordinateSpaceMapping::Local,
ref_spatial_node_index,
current_target_spatial_node_index: ref_spatial_node_index,
bounds,
}
}

Expand Down Expand Up @@ -161,6 +166,21 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
}
}

pub fn unmap(&self, rect: &TypedRect<f32, T>) -> Option<TypedRect<f32, F>> {
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<f32, F>) -> Option<TypedRect<f32, T>> {
match self.kind {
CoordinateSpaceMapping::Local => {
Expand All @@ -170,7 +190,7 @@ impl<F, T> SpaceMapper<F, T> 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)
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
21 changes: 11 additions & 10 deletions webrender/src/util.rs
Expand Up @@ -22,7 +22,7 @@ pub trait MatrixHelpers<Src, Dst> {
fn has_2d_inverse(&self) -> bool;
fn exceeds_2d_scale(&self, limit: f64) -> bool;
fn inverse_project(&self, target: &TypedPoint2D<f32, Dst>) -> Option<TypedPoint2D<f32, Src>>;
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src>;
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>>;
fn transform_kind(&self) -> TransformedRectKind;
fn is_simple_translation(&self) -> bool;
fn is_simple_2d_translation(&self) -> bool;
Expand Down Expand Up @@ -90,13 +90,13 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
m.inverse().map(|inv| TypedPoint2D::new(inv.m31, inv.m32))
}

fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> TypedRect<f32, Src> {
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<f32, Dst>) -> Option<TypedRect<f32, Src>> {
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 {
Expand Down Expand Up @@ -393,7 +393,7 @@ impl<Src, Dst> FastTransform<Src, Dst> {
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,
}
}
Expand Down Expand Up @@ -446,6 +446,7 @@ pub type LayoutToWorldFastTransform = FastTransform<LayoutPixel, WorldPixel>;
pub fn project_rect<F, T>(
transform: &TypedTransform3D<f32, F, T>,
rect: &TypedRect<f32, F>,
bounds: &TypedRect<f32, T>,
) -> Option<TypedRect<f32, T>>
where F: fmt::Debug
{
Expand All @@ -462,7 +463,7 @@ pub fn project_rect<F, T>(
let mut clipper = Clipper::new();
clipper.add_frustum(
transform,
None,
Some(*bounds),
);

let polygon = Polygon::from_rect(*rect, 1);
Expand Down

0 comments on commit 9953081

Please sign in to comment.