Commit 96d7010b authored by Sandor Molnar's avatar Sandor Molnar
Browse files

Backed out changeset e24b51679d83 (bug 1741781) on devs request. a=backout

parent 3ef6a5c0
Loading
Loading
Loading
Loading
+97 −17
Original line number Diff line number Diff line
@@ -110,7 +110,8 @@ use crate::render_task_cache::to_cache_size;
use crate::resource_cache::{ImageRequest, ResourceCache};
use crate::space::SpaceMapper;
use crate::util::{clamp_to_scale_factor, MaxRect, extract_inner_rect_safe, project_rect, ScaleOffset, VecHelper};
use std::{ops, u32, mem};
use euclid::approxeq::ApproxEq;
use std::{iter, ops, u32, mem};

// Type definitions for interning clip nodes.

@@ -539,7 +540,7 @@ impl ClipNodeRange {
enum ClipSpaceConversion {
    Local,
    ScaleOffset(ScaleOffset),
    Transform(LayoutTransform),
    Transform(LayoutToWorldTransform),
}

impl ClipSpaceConversion {
@@ -563,11 +564,9 @@ impl ClipSpaceConversion {
                .accumulate(&clip_spatial_node.content_transform);
            ClipSpaceConversion::ScaleOffset(scale_offset)
        } else {
            assert!(spatial_tree.is_ancestor(clip_spatial_node_index, prim_spatial_node_index));

            ClipSpaceConversion::Transform(
                spatial_tree
                    .get_relative_transform(prim_spatial_node_index, clip_spatial_node_index)
                    .get_world_transform(clip_spatial_node_index)
                    .into_transform()
            )
        }
@@ -1295,10 +1294,12 @@ impl ClipStore {
        &mut self,
        local_prim_rect: LayoutRect,
        prim_to_pic_mapper: &SpaceMapper<LayoutPixel, PicturePixel>,
        pic_to_world_mapper: &SpaceMapper<PicturePixel, WorldPixel>,
        spatial_tree: &SpatialTree,
        gpu_cache: &mut GpuCache,
        resource_cache: &mut ResourceCache,
        device_pixel_scale: DevicePixelScale,
        world_rect: &WorldRect,
        clip_data_store: &mut ClipDataStore,
        request_resources: bool,
        is_chased: bool,
@@ -1314,6 +1315,7 @@ impl ClipStore {

        let local_bounding_rect = local_prim_rect.intersection(&local_clip_rect)?;
        let mut pic_clip_rect = prim_to_pic_mapper.map(&local_bounding_rect)?;
        let world_clip_rect = pic_to_world_mapper.map(&pic_clip_rect)?;

        // Now, we've collected all the clip nodes that *potentially* affect this
        // primitive region, and reduced the size of the prim region as much as possible.
@@ -1340,8 +1342,9 @@ impl ClipStore {
                ClipSpaceConversion::Transform(ref transform) => {
                    has_non_local_clips = true;
                    node.item.kind.get_clip_result_complex(
                        &local_bounding_rect,
                        transform,
                        &world_clip_rect,
                        world_rect,
                    )
                }
            };
@@ -1800,9 +1803,15 @@ impl ClipItemKind {

    fn get_clip_result_complex(
        &self,
        local_prim_rect: &LayoutRect,
        prim_to_clip_transform: &LayoutTransform,
        transform: &LayoutToWorldTransform,
        prim_world_rect: &WorldRect,
        world_rect: &WorldRect,
    ) -> ClipResult {
        let visible_rect = match prim_world_rect.intersection(world_rect) {
            Some(rect) => rect,
            None => return ClipResult::Reject,
        };

        let (clip_rect, inner_rect, mode) = match *self {
            ClipItemKind::Rectangle { rect, mode } => {
                (rect, Some(rect), mode)
@@ -1820,15 +1829,8 @@ impl ClipItemKind {
            }
        };

        let prim_rect = match project_rect(prim_to_clip_transform, local_prim_rect, &clip_rect) {
            Some(rect) => rect,
            None => {
                return ClipResult::Reject;
            }
        };

        if let Some(ref inner_clip_rect) = inner_rect {
            if inner_clip_rect.contains_box(&prim_rect) {
            if let Some(()) = projected_rect_contains(inner_clip_rect, transform, &visible_rect) {
                return match mode {
                    ClipMode::Clip => ClipResult::Accept,
                    ClipMode::ClipOut => ClipResult::Reject,
@@ -1836,7 +1838,28 @@ impl ClipItemKind {
            }
        }

        return ClipResult::Partial;
        match mode {
            ClipMode::Clip => {
                let outer_clip_rect = match project_rect(
                    transform,
                    &clip_rect,
                    &world_rect,
                ) {
                    Some(outer_clip_rect) => outer_clip_rect,
                    None => return ClipResult::Partial,
                };

                match outer_clip_rect.intersection(prim_world_rect) {
                    Some(..) => {
                        ClipResult::Partial
                    }
                    None => {
                        ClipResult::Reject
                    }
                }
            }
            ClipMode::ClipOut => ClipResult::Partial,
        }
    }

    // Check how a given clip source affects a local primitive region.
@@ -2078,6 +2101,42 @@ pub fn polygon_contains_point(
    }
}

pub fn projected_rect_contains(
    source_rect: &LayoutRect,
    transform: &LayoutToWorldTransform,
    target_rect: &WorldRect,
) -> Option<()> {
    let points = [
        transform.transform_point2d(source_rect.top_left())?,
        transform.transform_point2d(source_rect.top_right())?,
        transform.transform_point2d(source_rect.bottom_right())?,
        transform.transform_point2d(source_rect.bottom_left())?,
    ];
    let target_points = [
        target_rect.top_left(),
        target_rect.top_right(),
        target_rect.bottom_right(),
        target_rect.bottom_left(),
    ];
    // iterate the edges of the transformed polygon
    for (a, b) in points
        .iter()
        .cloned()
        .zip(points[1..].iter().cloned().chain(iter::once(points[0])))
    {
        // If this edge is redundant, it's a weird, case, and we shouldn't go
        // length in trying to take the fast path (e.g. when the whole rectangle is a point).
        // If any of edges of the target rectangle crosses the edge, it's not completely
        // inside our transformed polygon either.
        if a.approx_eq(&b) || target_points.iter().any(|&c| (b - a).cross(c - a) < 0.0) {
            return None
        }
    }

    Some(())
}


// Add a clip node into the list of clips to be processed
// for the current clip chain. Returns false if the clip
// results in the entire primitive being culled out.
@@ -2119,6 +2178,8 @@ fn add_clip_node_to_current_chain(
                };
            }
            ClipSpaceConversion::Transform(..) => {
                assert!(spatial_tree.is_ancestor(node.spatial_node_index, prim_spatial_node_index));

                // Map the local clip rect directly into the same space as the picture
                // surface. This will often be the same space as the clip itself, which
                // results in a reduction in allocated clip mask size.
@@ -2163,6 +2224,25 @@ fn add_clip_node_to_current_chain(
    true
}

#[cfg(test)]
mod tests {
    use super::projected_rect_contains;
    use euclid::{Transform3D, rect};

    #[test]
    fn test_empty_projected_rect() {
        assert_eq!(
            None,
            projected_rect_contains(
                &rect(10.0, 10.0, 0.0, 0.0).to_box2d(),
                &Transform3D::identity(),
                &rect(20.0, 20.0, 10.0, 10.0).to_box2d(),
            ),
            "Empty rectangle is considered to include a non-empty!"
        );
    }
}

/// PolygonKeys get interned, because it's a convenient way to move the data
/// for the polygons out of the ClipItemKind and ClipItemKeyKind enums. The
/// polygon data is both interned and retrieved by the scene builder, and not
+2 −0
Original line number Diff line number Diff line
@@ -2164,10 +2164,12 @@ impl TileCacheInstance {
            let clip_chain_instance = frame_state.clip_store.build_clip_chain_instance(
                pic_rect.cast_unit(),
                &map_local_to_surface,
                &pic_to_world_mapper,
                frame_context.spatial_tree,
                frame_state.gpu_cache,
                frame_state.resource_cache,
                frame_context.global_device_pixel_scale,
                &frame_context.global_screen_world_rect,
                &mut frame_state.data_stores.clip,
                true,
                false,
+4 −0
Original line number Diff line number Diff line
@@ -1095,6 +1095,8 @@ fn update_clip_task_for_brush(
        );
        clip_mask_instances.push(clip_mask_kind);
    } else {
        let dirty_world_rect = frame_state.current_dirty_region().combined;

        for segment in segments {
            // Build a clip chain for the smaller segment rect. This will
            // often manage to eliminate most/all clips, and sometimes
@@ -1110,10 +1112,12 @@ fn update_clip_task_for_brush(
                .build_clip_chain_instance(
                    segment.local_rect.translate(prim_origin.to_vector()),
                    &pic_state.map_local_to_pic,
                    &pic_state.map_pic_to_world,
                    &frame_context.spatial_tree,
                    frame_state.gpu_cache,
                    frame_state.resource_cache,
                    device_pixel_scale,
                    &dirty_world_rect,
                    &mut data_stores.clip,
                    false,
                    instance.is_chased(),
+2 −0
Original line number Diff line number Diff line
@@ -398,10 +398,12 @@ pub fn update_primitive_visibility(
                    .build_clip_chain_instance(
                        local_rect,
                        &map_local_to_surface,
                        &map_surface_to_world,
                        &frame_context.spatial_tree,
                        frame_state.gpu_cache,
                        frame_state.resource_cache,
                        surface.device_pixel_scale,
                        &world_culling_rect,
                        &mut frame_state.data_stores.clip,
                        true,
                        prim_instance.is_chased(),