diff options
author | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-01 19:08:49 +0000 |
---|---|---|
committer | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-01 19:08:49 +0000 |
commit | 19aec37d615420b1001e3f0505b06307a4fcfe0d (patch) | |
tree | 0790994e5d7c71e6496ed3c9ea4963dc2f0a87d6 /cc/trees/layer_tree_impl_unittest.cc | |
parent | adc6eb89e31942c80eda20db6abb1391c5b0a159 (diff) | |
download | chromium_src-19aec37d615420b1001e3f0505b06307a4fcfe0d.zip chromium_src-19aec37d615420b1001e3f0505b06307a4fcfe0d.tar.gz chromium_src-19aec37d615420b1001e3f0505b06307a4fcfe0d.tar.bz2 |
Route selection bounds updates through the compositor
Currently, the selection bounds are queried at the start of each frame on the
main thread. If the bounds differ from the previous bounds, an updated
notification is sent to the browser. This approach is problematic for many
reasons, the chief of which being the inability of such updates to remain in
sync with content that is transformed on the compositor thread.
Instead, plumb the selection bounds region through the compositor, anchoring
each bound to the appropriate composited layer. This allows the compositor to
generated transformed bounds synchronized with transformed content, passed to
the browser with the CompositorFrameMetdadata.
Note that this patch only implements the compositor portion of the plumbing.
Enabling the feature in Blink and consuming the handle positions in the browser
will be done in https://codereview.chromium.org/359033002.
BUG=135959
Review URL: https://codereview.chromium.org/300323005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@280858 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/trees/layer_tree_impl_unittest.cc')
-rw-r--r-- | cc/trees/layer_tree_impl_unittest.cc | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index 006fc35..9edf838 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc @@ -2070,5 +2070,254 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) { EXPECT_FALSE(result_layer); } +TEST_F(LayerTreeImplTest, SelectionBoundsForSingleLayer) { + int root_layer_id = 12345; + scoped_ptr<LayerImpl> root = + LayerImpl::Create(host_impl().active_tree(), root_layer_id); + + gfx::Transform identity_matrix; + gfx::Point3F transform_origin; + gfx::PointF position; + gfx::Size bounds(100, 100); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + transform_origin, + position, + bounds, + true, + false); + root->SetDrawsContent(true); + + host_impl().SetViewportSize(root->bounds()); + host_impl().active_tree()->SetRootLayer(root.Pass()); + host_impl().active_tree()->UpdateDrawProperties(); + + // Sanity check the scenario we just created. + ASSERT_EQ(1u, RenderSurfaceLayerList().size()); + ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size()); + + LayerSelectionBound left_input; + left_input.type = SELECTION_BOUND_LEFT; + left_input.layer_rect = gfx::RectF(10, 10, 5, 20); + left_input.layer_id = root_layer_id; + + LayerSelectionBound right_input; + right_input.type = SELECTION_BOUND_RIGHT; + right_input.layer_rect = gfx::RectF(50, 10, 5, 20); + right_input.layer_id = root_layer_id; + + ViewportSelectionBound left_output, right_output; + + // Empty input bounds should produce empty output bounds. + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_EQ(ViewportSelectionBound(), left_output); + EXPECT_EQ(ViewportSelectionBound(), right_output); + + // Selection bounds should produce distinct left and right bounds. + host_impl().active_tree()->RegisterSelection(left_input, right_input); + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_EQ(left_input.type, left_output.type); + EXPECT_EQ(left_input.layer_rect, left_output.viewport_rect); + EXPECT_TRUE(left_output.visible); + EXPECT_EQ(right_input.type, right_output.type); + EXPECT_EQ(right_input.layer_rect, right_output.viewport_rect); + EXPECT_TRUE(right_output.visible); + + // Insertion bounds should produce identical left and right bounds. + LayerSelectionBound insertion_input; + insertion_input.type = SELECTION_BOUND_CENTER; + insertion_input.layer_rect = gfx::RectF(10, 10, 5, 20); + insertion_input.layer_id = root_layer_id; + host_impl().active_tree()->RegisterSelection(insertion_input, + LayerSelectionBound()); + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_EQ(insertion_input.type, left_output.type); + EXPECT_EQ(insertion_input.layer_rect, left_output.viewport_rect); + EXPECT_TRUE(left_output.visible); + EXPECT_EQ(left_output, right_output); +} + +TEST_F(LayerTreeImplTest, SelectionBoundsForPartialOccludedLayers) { + int root_layer_id = 12345; + int clip_layer_id = 1234; + int clipped_layer_id = 123; + scoped_ptr<LayerImpl> root = + LayerImpl::Create(host_impl().active_tree(), root_layer_id); + root->SetDrawsContent(true); + + gfx::Transform identity_matrix; + gfx::Point3F transform_origin; + gfx::PointF position; + gfx::Size bounds(100, 100); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + transform_origin, + position, + bounds, + true, + false); + + gfx::Vector2dF clipping_offset(10, 10); + { + scoped_ptr<LayerImpl> clipping_layer = + LayerImpl::Create(host_impl().active_tree(), clip_layer_id); + // The clipping layer should occlude the right selection bound. + gfx::PointF position = gfx::PointF() + clipping_offset; + gfx::Size bounds(50, 50); + SetLayerPropertiesForTesting(clipping_layer.get(), + identity_matrix, + transform_origin, + position, + bounds, + true, + false); + clipping_layer->SetMasksToBounds(true); + + scoped_ptr<LayerImpl> clipped_layer = + LayerImpl::Create(host_impl().active_tree(), clipped_layer_id); + position = gfx::PointF(); + bounds = gfx::Size(100, 100); + SetLayerPropertiesForTesting(clipped_layer.get(), + identity_matrix, + transform_origin, + position, + bounds, + true, + false); + clipped_layer->SetDrawsContent(true); + clipping_layer->AddChild(clipped_layer.Pass()); + root->AddChild(clipping_layer.Pass()); + } + + host_impl().SetViewportSize(root->bounds()); + host_impl().active_tree()->SetRootLayer(root.Pass()); + host_impl().active_tree()->UpdateDrawProperties(); + + // Sanity check the scenario we just created. + ASSERT_EQ(1u, RenderSurfaceLayerList().size()); + + LayerSelectionBound left_input; + left_input.type = SELECTION_BOUND_LEFT; + left_input.layer_rect = gfx::RectF(25, 10, 5, 20); + left_input.layer_id = clipped_layer_id; + + LayerSelectionBound right_input; + right_input.type = SELECTION_BOUND_RIGHT; + right_input.layer_rect = gfx::RectF(75, 10, 5, 20); + right_input.layer_id = clipped_layer_id; + host_impl().active_tree()->RegisterSelection(left_input, right_input); + + // The left bound should be occluded by the clip layer. + ViewportSelectionBound left_output, right_output; + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_EQ(left_input.type, left_output.type); + gfx::RectF expected_left_output_rect = left_input.layer_rect; + expected_left_output_rect.Offset(clipping_offset); + EXPECT_EQ(expected_left_output_rect, left_output.viewport_rect); + EXPECT_TRUE(left_output.visible); + EXPECT_EQ(right_input.type, right_output.type); + gfx::RectF expected_right_output_rect = right_input.layer_rect; + expected_right_output_rect.Offset(clipping_offset); + EXPECT_EQ(expected_right_output_rect, right_output.viewport_rect); + EXPECT_FALSE(right_output.visible); + + // Handles outside the viewport bounds should be marked invisible. + left_input.layer_rect = gfx::RectF(-25, 0, 5, 20); + host_impl().active_tree()->RegisterSelection(left_input, right_input); + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_FALSE(left_output.visible); + + left_input.layer_rect = gfx::RectF(0, -25, 5, 20); + host_impl().active_tree()->RegisterSelection(left_input, right_input); + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_FALSE(left_output.visible); + + // If the handle bottom is partially visible, the handle is marked visible. + left_input.layer_rect = gfx::RectF(0, -20, 5, 21); + host_impl().active_tree()->RegisterSelection(left_input, right_input); + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_TRUE(left_output.visible); +} + +TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) { + int root_layer_id = 1; + int sub_layer_id = 2; + scoped_ptr<LayerImpl> root = + LayerImpl::Create(host_impl().active_tree(), root_layer_id); + root->SetDrawsContent(true); + + gfx::Transform identity_matrix; + gfx::Point3F transform_origin; + gfx::PointF position; + gfx::Size bounds(100, 100); + SetLayerPropertiesForTesting(root.get(), + identity_matrix, + transform_origin, + position, + bounds, + true, + false); + + gfx::Vector2dF sub_layer_offset(10, 0); + { + scoped_ptr<LayerImpl> sub_layer = + LayerImpl::Create(host_impl().active_tree(), sub_layer_id); + gfx::PointF position = gfx::PointF() + sub_layer_offset; + gfx::Size bounds(50, 50); + SetLayerPropertiesForTesting(sub_layer.get(), + identity_matrix, + transform_origin, + position, + bounds, + true, + false); + sub_layer->SetDrawsContent(true); + root->AddChild(sub_layer.Pass()); + } + + float device_scale_factor = 3.f; + float page_scale_factor = 5.f; + gfx::Size scaled_bounds_for_root = gfx::ToCeiledSize( + gfx::ScaleSize(root->bounds(), device_scale_factor * page_scale_factor)); + host_impl().SetViewportSize(scaled_bounds_for_root); + + host_impl().SetDeviceScaleFactor(device_scale_factor); + host_impl().active_tree()->SetPageScaleFactorAndLimits( + page_scale_factor, page_scale_factor, page_scale_factor); + host_impl().active_tree()->SetRootLayer(root.Pass()); + host_impl().active_tree()->SetViewportLayersFromIds(1, 1, Layer::INVALID_ID); + host_impl().active_tree()->UpdateDrawProperties(); + + // Sanity check the scenario we just created. + ASSERT_EQ(1u, RenderSurfaceLayerList().size()); + + LayerSelectionBound left_input; + left_input.type = SELECTION_BOUND_LEFT; + left_input.layer_rect = gfx::RectF(10, 10, 5, 20); + left_input.layer_id = root_layer_id; + + LayerSelectionBound right_input; + right_input.type = SELECTION_BOUND_RIGHT; + right_input.layer_rect = gfx::RectF(0, 0, 5, 20); + right_input.layer_id = sub_layer_id; + host_impl().active_tree()->RegisterSelection(left_input, right_input); + + // The viewport bounds should be properly scaled by the page scale, but should + // remain in DIP coordinates. + ViewportSelectionBound left_output, right_output; + host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); + EXPECT_EQ(left_input.type, left_output.type); + gfx::RectF expected_left_output_rect = left_input.layer_rect; + expected_left_output_rect.Scale(page_scale_factor); + EXPECT_EQ(left_input.layer_rect, left_output.viewport_rect); + EXPECT_TRUE(left_output.visible); + EXPECT_EQ(right_input.type, right_output.type); + gfx::RectF expected_right_output_rect = right_input.layer_rect; + expected_right_output_rect.Offset(sub_layer_offset); + expected_right_output_rect.Scale(page_scale_factor); + EXPECT_EQ(expected_right_output_rect, right_output.viewport_rect); + EXPECT_TRUE(right_output.visible); +} + } // namespace } // namespace cc |