Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next set of ClipScrollTree optimizations #2156

Merged
merged 4 commits into from Dec 4, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Extract bounding rect calculation from TransformedRect

Instead of calculating some things that we no longer need for
TransformedRect, we simply calculate the screen bounding rect. We can
then completely remove TransformedRect. This significantly the presence
of getting the screen bounding rect on the CPU profile.
  • Loading branch information
mrobinson committed Dec 4, 2017
commit 1751eccd340da288a89521a41f71ed7ac7efff96
@@ -2,16 +2,15 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, ImageRendering, LayerPoint};
use api::{ClipMode, LayerRect};
use api::{LayerToWorldTransform, LayoutPoint, LayoutVector2D, LocalClip};
use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, ImageMask, ImageRendering};
use api::{LayerPoint, LayerRect, LayerToWorldTransform, LayoutPoint, LayoutVector2D, LocalClip};
use border::BorderCornerClipSource;
use ellipse::Ellipse;
use freelist::{FreeList, FreeListHandle, WeakFreeListHandle};
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use prim_store::{ClipData, ImageMaskData};
use resource_cache::ResourceCache;
use util::{extract_inner_rect_safe, MaxRect, TransformedRect};
use util::{MaxRect, calculate_screen_bounding_rect, extract_inner_rect_safe};

pub type ClipStore = FreeList<ClipSources>;
pub type ClipSourcesHandle = FreeListHandle<ClipSources>;
@@ -253,12 +252,12 @@ impl ClipSources {
device_pixel_ratio: f32,
) -> (DeviceIntRect, Option<DeviceIntRect>) {
let screen_inner_rect =
TransformedRect::new(&self.local_inner_rect, transform, device_pixel_ratio);
calculate_screen_bounding_rect(transform, &self.local_inner_rect, device_pixel_ratio);
let screen_outer_rect = self.local_outer_rect.map(|outer_rect|
TransformedRect::new(&outer_rect, transform, device_pixel_ratio).bounding_rect
calculate_screen_bounding_rect(transform, &outer_rect, device_pixel_ratio)
);

(screen_inner_rect.bounding_rect, screen_outer_rect)
(screen_inner_rect, screen_outer_rect)
}
}

@@ -5,9 +5,9 @@
use api::{BorderRadius, BuiltDisplayList, ClipAndScrollInfo, ClipId, ClipMode, ColorF};
use api::{ComplexClipRegion, DeviceIntRect, DevicePoint, ExtendMode, FontRenderMode};
use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag};
use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerTransform, LayerVector2D};
use api::{LineOrientation, LineStyle, PipelineId, PremultipliedColorF, TileOffset};
use api::{WorldToLayerTransform, YuvColorSpace, YuvFormat};
use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation};
use api::{LineStyle, PipelineId, PremultipliedColorF, TileOffset, WorldToLayerTransform};
use api::{YuvColorSpace, YuvFormat};
use border::BorderCornerInstance;
use clip_scroll_tree::{CoordinateSystemId, ClipScrollTree};
use clip::{ClipSource, ClipSourcesHandle, ClipStore};
@@ -26,8 +26,8 @@ use resource_cache::{ImageProperties, ResourceCache};
use scene::{ScenePipeline, SceneProperties};
use std::{mem, u16, usize};
use std::rc::Rc;
use util::{extract_inner_rect_safe, pack_as_float, recycle_vec};
use util::{MatrixHelpers, TransformedRect};
use util::{MatrixHelpers, calculate_screen_bounding_rect, extract_inner_rect_safe, pack_as_float};
use util::recycle_vec;

const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0;

@@ -1553,13 +1553,13 @@ impl PrimitiveStore {
let create_clip_task = segment_enabled &&
(!can_optimize_clip_mask || i <= BrushSegmentKind::BottomLeft as usize);
segment.clip_task_id = if create_clip_task {
let segment_rect = TransformedRect::new(
&segment.local_rect,
let segment_screen_rect = calculate_screen_bounding_rect(
&prim_context.scroll_node.world_content_transform,
&segment.local_rect,
prim_context.device_pixel_ratio
);

combined_outer_rect.intersection(&segment_rect.bounding_rect).map(|bounds| {
combined_outer_rect.intersection(&segment_screen_rect).map(|bounds| {
let clip_task = RenderTask::new_mask(
None,
bounds,
@@ -1710,20 +1710,20 @@ impl PrimitiveStore {
None => LayerRect::zero(),
};

let xf_rect = TransformedRect::new(
&local_rect,
let screen_bounding_rect = calculate_screen_bounding_rect(
&prim_context.scroll_node.world_content_transform,
&local_rect,
prim_context.device_pixel_ratio
);

let clip_bounds = &prim_context.clip_node.combined_clip_outer_bounds;
metadata.screen_rect = xf_rect.bounding_rect.intersection(clip_bounds);
metadata.screen_rect = screen_bounding_rect.intersection(clip_bounds);

if metadata.screen_rect.is_none() && perform_culling {
return None;
}

(local_rect, xf_rect.bounding_rect)
(local_rect, screen_bounding_rect)
};

if perform_culling && may_need_clip_mask && !self.update_clip_task(
@@ -4,7 +4,7 @@

use api::{BorderRadius, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{DevicePoint, DeviceRect, DeviceSize, LayerPoint, LayerRect, LayerSize};
use api::{LayerToWorldTransform, LayoutRect, WorldPoint3D};
use api::{LayerToWorldTransform, LayoutRect, WorldRect};
use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, TypedTransform2D};
use euclid::TypedTransform3D;
use num_traits::Zero;
@@ -95,14 +95,10 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {

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()),
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()),
])
}

@@ -158,6 +154,27 @@ pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
(b - a) * t + a
}

pub fn calculate_screen_bounding_rect(
transform: &LayerToWorldTransform,
rect: &LayerRect,
device_pixel_ratio: f32
) -> DeviceIntRect {
let rect = WorldRect::from_points(&[
transform.transform_point2d(&rect.origin),
transform.transform_point2d(&rect.top_right()),
transform.transform_point2d(&rect.bottom_left()),
transform.transform_point2d(&rect.bottom_right()),
]) * device_pixel_ratio;

let rect = DeviceRect::new(
DevicePoint::new(rect.origin.x, rect.origin.y),
DeviceSize::new(rect.size.width, rect.size.height),
);

let max_rect = DeviceRect::max_rect();
rect.round_out().intersection(&max_rect).unwrap_or(max_rect).to_i32()
}

pub fn _subtract_rect<U>(
rect: &TypedRect<f32, U>,
other: &TypedRect<f32, U>,
@@ -201,85 +218,13 @@ pub fn _subtract_rect<U>(
}
}

pub fn get_normal(x: f32) -> Option<f32> {
if x.is_normal() {
Some(x)
} else {
None
}
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[repr(u32)]
pub enum TransformedRectKind {
AxisAligned = 0,
Complex = 1,
}

#[derive(Debug, Clone)]
pub struct TransformedRect {
pub local_rect: LayerRect,
pub bounding_rect: DeviceIntRect,
pub inner_rect: DeviceIntRect,
pub vertices: [WorldPoint3D; 4],
pub kind: TransformedRectKind,
}

impl TransformedRect {
pub fn new(
rect: &LayerRect,
transform: &LayerToWorldTransform,
device_pixel_ratio: f32,
) -> TransformedRect {
let kind = if transform.preserves_2d_axis_alignment() {
TransformedRectKind::AxisAligned
} else {
TransformedRectKind::Complex
};


let vertices = [
transform.transform_point3d(&rect.origin.to_3d()),
transform.transform_point3d(&rect.bottom_left().to_3d()),
transform.transform_point3d(&rect.bottom_right().to_3d()),
transform.transform_point3d(&rect.top_right().to_3d()),
];

let (mut xs, mut ys) = ([0.0; 4], [0.0; 4]);

for (vertex, (x, y)) in vertices.iter().zip(xs.iter_mut().zip(ys.iter_mut())) {
*x = get_normal(vertex.x).unwrap_or(0.0);
*y = get_normal(vertex.y).unwrap_or(0.0);
}

xs.sort_by(|a, b| a.partial_cmp(b).unwrap());
ys.sort_by(|a, b| a.partial_cmp(b).unwrap());

let outer_min_dp = (DevicePoint::new(xs[0], ys[0]) * device_pixel_ratio).floor();
let outer_max_dp = (DevicePoint::new(xs[3], ys[3]) * device_pixel_ratio).ceil();
let inner_min_dp = (DevicePoint::new(xs[1], ys[1]) * device_pixel_ratio).ceil();
let inner_max_dp = (DevicePoint::new(xs[2], ys[2]) * device_pixel_ratio).floor();

let max_rect = DeviceRect::max_rect();
let bounding_rect = DeviceRect::new(outer_min_dp, (outer_max_dp - outer_min_dp).to_size())
.intersection(&max_rect)
.unwrap_or(max_rect)
.to_i32();
let inner_rect = DeviceRect::new(inner_min_dp, (inner_max_dp - inner_min_dp).to_size())
.intersection(&max_rect)
.unwrap_or(max_rect)
.to_i32();

TransformedRect {
local_rect: *rect,
vertices,
bounding_rect,
inner_rect,
kind,
}
}
}

#[inline(always)]
pub fn pack_as_float(value: u32) -> f32 {
value as f32 + 0.5
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.