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

Robust TransformRect #1426

Merged
merged 2 commits into from Jun 23, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -1342,6 +1342,7 @@ impl FrameBuilder {
let group_index = self.stacking_context_store[stacking_context_index.0]
.clip_scroll_group(clip_and_scroll);
if self.clip_scroll_group_store[group_index.0].screen_bounding_rect.is_none() {
debug!("\tcs-group {:?} screen rect is None", group_index);
continue
}

@@ -1532,6 +1533,7 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
self.recalculate_clip_scroll_groups();
self.compute_stacking_context_visibility();

debug!("processing commands...");
let commands = mem::replace(&mut self.frame_builder.cmds, Vec::new());
for cmd in &commands {
match *cmd {
@@ -1605,6 +1607,7 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
}

fn recalculate_clip_scroll_groups(&mut self) {
debug!("recalculate_clip_scroll_groups");
for ref mut group in &mut self.frame_builder.clip_scroll_group_store {
let stacking_context_index = group.stacking_context_index;
let stacking_context = &mut self.frame_builder
@@ -1620,6 +1623,8 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
.pre_translate(stacking_context.reference_frame_offset.to_3d());

if !packed_layer.set_transform(transform) || !stacking_context.can_contribute_to_scene() {
debug!("\t{:?} unable to set transform or contribute with {:?}",
stacking_context_index, transform);
return;
}

@@ -1634,6 +1639,9 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
group.screen_bounding_rect = packed_layer.set_rect(&local_viewport_rect,
self.screen_rect,
self.device_pixel_ratio);

debug!("\t{:?} local viewport {:?} screen bound {:?}",
stacking_context_index, local_viewport_rect, group.screen_bounding_rect);
}
}

@@ -1760,6 +1768,7 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
&self.frame_builder.stacking_context_store[stacking_context_index.0];

if !stacking_context.is_visible {
debug!("{:?} of invisible {:?}", base_prim_index, stacking_context_index);
return;
}

@@ -1769,7 +1778,7 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> {
stacking_context.pipeline_id)
};

debug!("\t{:?} at {:?}", base_prim_index, packed_layer_index);
debug!("\t{:?} of {:?} at {:?}", base_prim_index, stacking_context_index, packed_layer_index);
let clip_bounds = match self.rebuild_clip_info_stack_if_necessary(clip_and_scroll.clip_node_id()) {
Some(rect) => rect,
None => return,
@@ -5,7 +5,7 @@
use std::f32::consts::{FRAC_1_SQRT_2};
use euclid::{Point2D, Rect, Size2D};
use euclid::{TypedRect, TypedPoint2D, TypedSize2D, TypedTransform2D, TypedTransform3D};
use webrender_traits::{DeviceIntRect, DeviceIntPoint, DeviceIntSize};
use webrender_traits::{DeviceIntRect, DevicePoint, DeviceRect, DeviceSize};
use webrender_traits::{LayerRect, WorldPoint3D, LayerToWorldTransform};
use webrender_traits::{BorderRadius, ComplexClipRegion, LayoutRect};
use num_traits::Zero;
@@ -202,6 +202,13 @@ pub struct TransformedRect {
pub kind: TransformedRectKind,
}

// Having an unlimited bounding box is fine up until we try
// to cast it to `i32`, where we get `-2147483648` for any
// values larger than or equal to 2^31.
//Note: clamping to i32::MIN and i32::MAX is not a solution,
// with explanation left as an exercise for the reader.
const MAX_COORD: f32 = 1.0e9;

impl TransformedRect {
pub fn new(rect: &LayerRect,
transform: &LayerToWorldTransform,
@@ -213,80 +220,43 @@ impl TransformedRect {
TransformedRectKind::Complex
};

// FIXME(gw): This code is meant to be a fast path for simple transforms.
// However, it fails on transforms that translate Z but result in an
// axis aligned rect.

/*
match kind {
TransformedRectKind::AxisAligned => {
let v0 = transform.transform_point(&rect.origin);
let v1 = transform.transform_point(&rect.top_right());
let v2 = transform.transform_point(&rect.bottom_left());
let v3 = transform.transform_point(&rect.bottom_right());
let screen_min_dp = Point2D::new(DevicePixel((v0.x * device_pixel_ratio).floor() as i32),
DevicePixel((v0.y * device_pixel_ratio).floor() as i32));
let screen_max_dp = Point2D::new(DevicePixel((v3.x * device_pixel_ratio).ceil() as i32),
DevicePixel((v3.y * device_pixel_ratio).ceil() as i32));
let screen_rect_dp = Rect::new(screen_min_dp, Size2D::new(screen_max_dp.x - screen_min_dp.x,
screen_max_dp.y - screen_min_dp.y));
TransformedRect {
local_rect: *rect,
vertices: [
Point4D::new(v0.x, v0.y, 0.0, 1.0),
Point4D::new(v1.x, v1.y, 0.0, 1.0),
Point4D::new(v2.x, v2.y, 0.0, 1.0),
Point4D::new(v3.x, v3.y, 0.0, 1.0),
],
bounding_rect: screen_rect_dp,
kind,
}
}
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 = DeviceIntPoint::new((xs[0] * device_pixel_ratio).floor() as i32,
(ys[0] * device_pixel_ratio).floor() as i32);
let outer_max_dp = DeviceIntPoint::new((xs[3] * device_pixel_ratio).ceil() as i32,
(ys[3] * device_pixel_ratio).ceil() as i32);
let inner_min_dp = DeviceIntPoint::new((xs[1] * device_pixel_ratio).ceil() as i32,
(ys[1] * device_pixel_ratio).ceil() as i32);
let inner_max_dp = DeviceIntPoint::new((xs[2] * device_pixel_ratio).floor() as i32,
(ys[2] * device_pixel_ratio).floor() as i32);

TransformedRect {
local_rect: *rect,
vertices,
bounding_rect: DeviceIntRect::new(outer_min_dp,
DeviceIntSize::new(outer_max_dp.x.saturating_sub(outer_min_dp.x),
outer_max_dp.y.saturating_sub(outer_min_dp.y))),
inner_rect: DeviceIntRect::new(inner_min_dp,
DeviceIntSize::new(inner_max_dp.x.saturating_sub(inner_min_dp.x),
inner_max_dp.y.saturating_sub(inner_min_dp.y))),
kind,
}
/*
}
}*/

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::new(DevicePoint::new(-MAX_COORD, -MAX_COORD),
DeviceSize::new(2.0*MAX_COORD, 2.0*MAX_COORD));
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,
}
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.