| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/layer_tree_host_impl.h" | 5 #include "cc/layer_tree_host_impl.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/hash_tables.h" | 11 #include "base/hash_tables.h" |
| 12 #include "cc/compositor_frame_metadata.h" | 12 #include "cc/compositor_frame_metadata.h" |
| 13 #include "cc/delegated_renderer_layer_impl.h" | 13 #include "cc/delegated_renderer_layer_impl.h" |
| 14 #include "cc/gl_renderer.h" | 14 #include "cc/gl_renderer.h" |
| 15 #include "cc/heads_up_display_layer_impl.h" | 15 #include "cc/heads_up_display_layer_impl.h" |
| 16 #include "cc/io_surface_layer_impl.h" | 16 #include "cc/io_surface_layer_impl.h" |
| 17 #include "cc/layer.h" |
| 17 #include "cc/layer_impl.h" | 18 #include "cc/layer_impl.h" |
| 18 #include "cc/layer_tiling_data.h" | 19 #include "cc/layer_tiling_data.h" |
| 19 #include "cc/layer_tree_impl.h" | 20 #include "cc/layer_tree_impl.h" |
| 20 #include "cc/math_util.h" | 21 #include "cc/math_util.h" |
| 21 #include "cc/quad_sink.h" | 22 #include "cc/quad_sink.h" |
| 22 #include "cc/render_pass_draw_quad.h" | 23 #include "cc/render_pass_draw_quad.h" |
| 23 #include "cc/scrollbar_geometry_fixed_thumb.h" | 24 #include "cc/scrollbar_geometry_fixed_thumb.h" |
| 24 #include "cc/scrollbar_layer_impl.h" | 25 #include "cc/scrollbar_layer_impl.h" |
| 25 #include "cc/single_thread_proxy.h" | 26 #include "cc/single_thread_proxy.h" |
| 26 #include "cc/solid_color_draw_quad.h" | 27 #include "cc/solid_color_draw_quad.h" |
| 27 #include "cc/test/animation_test_common.h" | 28 #include "cc/test/animation_test_common.h" |
| 29 #include "cc/test/fake_impl_proxy.h" |
| 30 #include "cc/test/fake_layer_tree_host_impl.h" |
| 28 #include "cc/test/fake_output_surface.h" | 31 #include "cc/test/fake_output_surface.h" |
| 29 #include "cc/test/fake_proxy.h" | 32 #include "cc/test/fake_proxy.h" |
| 30 #include "cc/test/fake_video_frame_provider.h" | 33 #include "cc/test/fake_video_frame_provider.h" |
| 31 #include "cc/test/fake_web_scrollbar_theme_geometry.h" | 34 #include "cc/test/fake_web_scrollbar_theme_geometry.h" |
| 32 #include "cc/test/geometry_test_utils.h" | 35 #include "cc/test/geometry_test_utils.h" |
| 33 #include "cc/test/layer_test_common.h" | 36 #include "cc/test/layer_test_common.h" |
| 34 #include "cc/test/render_pass_test_common.h" | 37 #include "cc/test/render_pass_test_common.h" |
| 35 #include "cc/test/test_web_graphics_context_3d.h" | 38 #include "cc/test/test_web_graphics_context_3d.h" |
| 36 #include "cc/texture_draw_quad.h" | 39 #include "cc/texture_draw_quad.h" |
| 37 #include "cc/texture_layer_impl.h" | 40 #include "cc/texture_layer_impl.h" |
| 38 #include "cc/tile_draw_quad.h" | 41 #include "cc/tile_draw_quad.h" |
| 39 #include "cc/tiled_layer_impl.h" | 42 #include "cc/tiled_layer_impl.h" |
| 40 #include "cc/video_layer_impl.h" | 43 #include "cc/video_layer_impl.h" |
| 41 #include "media/base/media.h" | 44 #include "media/base/media.h" |
| 42 #include "testing/gmock/include/gmock/gmock.h" | 45 #include "testing/gmock/include/gmock/gmock.h" |
| 43 #include "testing/gtest/include/gtest/gtest.h" | 46 #include "testing/gtest/include/gtest/gtest.h" |
| 44 #include "ui/gfx/size_conversions.h" | 47 #include "ui/gfx/size_conversions.h" |
| 45 #include "ui/gfx/vector2d_conversions.h" | 48 #include "ui/gfx/vector2d_conversions.h" |
| 46 | 49 |
| 47 using ::testing::Mock; | 50 using ::testing::Mock; |
| 48 using ::testing::Return; | 51 using ::testing::Return; |
| 49 using ::testing::AnyNumber; | 52 using ::testing::AnyNumber; |
| 50 using ::testing::AtLeast; | 53 using ::testing::AtLeast; |
| 51 using ::testing::_; | 54 using ::testing::_; |
| 52 using media::VideoFrame; | 55 using media::VideoFrame; |
| 53 | 56 |
| 54 namespace cc { | 57 namespace cc { |
| 55 namespace { | 58 namespace { |
| 56 | 59 |
| 60 template<typename LayerType> |
| 61 void setLayerPropertiesForTestingInternal(LayerType* layer, const gfx::Transform
& transform, const gfx::Transform& sublayerTransform, const gfx::PointF& anchor,
const gfx::PointF& position, const gfx::Size& bounds, bool preserves3D) |
| 62 { |
| 63 layer->setTransform(transform); |
| 64 layer->setSublayerTransform(sublayerTransform); |
| 65 layer->setAnchorPoint(anchor); |
| 66 layer->setPosition(position); |
| 67 layer->setBounds(bounds); |
| 68 layer->setPreserves3D(preserves3D); |
| 69 } |
| 70 |
| 71 void setLayerPropertiesForTesting(Layer* layer, const gfx::Transform& transform,
const gfx::Transform& sublayerTransform, const gfx::PointF& anchor, const gfx::
PointF& position, const gfx::Size& bounds, bool preserves3D) |
| 72 { |
| 73 setLayerPropertiesForTestingInternal<Layer>(layer, transform, sublayerTransf
orm, anchor, position, bounds, preserves3D); |
| 74 layer->setAutomaticallyComputeRasterScale(true); |
| 75 } |
| 76 |
| 77 void setLayerPropertiesForTesting(LayerImpl* layer, const gfx::Transform& transf
orm, const gfx::Transform& sublayerTransform, const gfx::PointF& anchor, const g
fx::PointF& position, const gfx::Size& bounds, bool preserves3D) |
| 78 { |
| 79 setLayerPropertiesForTestingInternal<LayerImpl>(layer, transform, sublayerTr
ansform, anchor, position, bounds, preserves3D); |
| 80 layer->setContentBounds(bounds); |
| 81 } |
| 82 |
| 57 // This test is parametrized to run all tests with the | 83 // This test is parametrized to run all tests with the |
| 58 // m_settings.pageScalePinchZoomEnabled field enabled and disabled. | 84 // m_settings.pageScalePinchZoomEnabled field enabled and disabled. |
| 59 class LayerTreeHostImplTest : public testing::TestWithParam<bool>, | 85 class LayerTreeHostImplTest : public testing::TestWithParam<bool>, |
| 60 public LayerTreeHostImplClient { | 86 public LayerTreeHostImplClient { |
| 61 public: | 87 public: |
| 62 LayerTreeHostImplTest() | 88 LayerTreeHostImplTest() |
| 63 : m_proxy(scoped_ptr<Thread>(NULL)) | 89 : m_proxy(scoped_ptr<Thread>(NULL)) |
| 64 , m_alwaysImplThread(&m_proxy) | 90 , m_alwaysImplThread(&m_proxy) |
| 65 , m_alwaysMainThreadBlocked(&m_proxy) | 91 , m_alwaysMainThreadBlocked(&m_proxy) |
| 66 , m_onCanDrawStateChangedCalled(false) | 92 , m_onCanDrawStateChangedCalled(false) |
| (...skipping 4269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4336 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->ma
terial); | 4362 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.renderPasses[0]->quad_list[0]->ma
terial); |
| 4337 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialC
ast(frame.renderPasses[0]->quad_list[0]); | 4363 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialC
ast(frame.renderPasses[0]->quad_list[0]); |
| 4338 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToS
tring()); | 4364 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToS
tring()); |
| 4339 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mas
k_uv_rect.ToString()); | 4365 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mas
k_uv_rect.ToString()); |
| 4340 | 4366 |
| 4341 m_hostImpl->drawLayers(frame); | 4367 m_hostImpl->drawLayers(frame); |
| 4342 m_hostImpl->didDrawAllLayers(frame); | 4368 m_hostImpl->didDrawAllLayers(frame); |
| 4343 } | 4369 } |
| 4344 } | 4370 } |
| 4345 | 4371 |
| 4372 TEST(LayerTreeHostImplTest, verifyHitTestingForEmptyLayerList) |
| 4373 { |
| 4374 FakeImplProxy proxy; |
| 4375 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4376 |
| 4377 // Hit testing on an empty renderSurfaceLayerList should return a null point
er. |
| 4378 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4379 |
| 4380 gfx::Point testPoint(0, 0); |
| 4381 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4382 EXPECT_FALSE(resultLayer); |
| 4383 |
| 4384 testPoint = gfx::Point(10, 20); |
| 4385 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4386 EXPECT_FALSE(resultLayer); |
| 4387 } |
| 4388 |
| 4389 TEST(LayerTreeHostImplTest, verifyHitTestingForSingleLayer) |
| 4390 { |
| 4391 FakeImplProxy proxy; |
| 4392 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4393 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 12345)
; |
| 4394 |
| 4395 gfx::Transform identityMatrix; |
| 4396 gfx::PointF anchor(0, 0); |
| 4397 gfx::PointF position(0, 0); |
| 4398 gfx::Size bounds(100, 100); |
| 4399 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, position, bounds, false); |
| 4400 root->setDrawsContent(true); |
| 4401 |
| 4402 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4403 int dummyMaxTextureSize = 512; |
| 4404 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4405 |
| 4406 // Sanity check the scenario we just created. |
| 4407 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4408 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4409 |
| 4410 // Hit testing for a point outside the layer should return a null pointer. |
| 4411 gfx::Point testPoint(101, 101); |
| 4412 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4413 EXPECT_FALSE(resultLayer); |
| 4414 |
| 4415 testPoint = gfx::Point(-1, -1); |
| 4416 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4417 EXPECT_FALSE(resultLayer); |
| 4418 |
| 4419 // Hit testing for a point inside should return the root layer. |
| 4420 testPoint = gfx::Point(1, 1); |
| 4421 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4422 ASSERT_TRUE(resultLayer); |
| 4423 EXPECT_EQ(12345, resultLayer->id()); |
| 4424 |
| 4425 testPoint = gfx::Point(99, 99); |
| 4426 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4427 ASSERT_TRUE(resultLayer); |
| 4428 EXPECT_EQ(12345, resultLayer->id()); |
| 4429 } |
| 4430 |
| 4431 TEST(LayerTreeHostImplTest, verifyHitTestingForUninvertibleTransform) |
| 4432 { |
| 4433 FakeImplProxy proxy; |
| 4434 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4435 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 12345)
; |
| 4436 |
| 4437 gfx::Transform uninvertibleTransform; |
| 4438 uninvertibleTransform.matrix().setDouble(0, 0, 0); |
| 4439 uninvertibleTransform.matrix().setDouble(1, 1, 0); |
| 4440 uninvertibleTransform.matrix().setDouble(2, 2, 0); |
| 4441 uninvertibleTransform.matrix().setDouble(3, 3, 0); |
| 4442 ASSERT_FALSE(uninvertibleTransform.IsInvertible()); |
| 4443 |
| 4444 gfx::Transform identityMatrix; |
| 4445 gfx::PointF anchor(0, 0); |
| 4446 gfx::PointF position(0, 0); |
| 4447 gfx::Size bounds(100, 100); |
| 4448 setLayerPropertiesForTesting(root.get(), uninvertibleTransform, identityMatr
ix, anchor, position, bounds, false); |
| 4449 root->setDrawsContent(true); |
| 4450 |
| 4451 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4452 int dummyMaxTextureSize = 512; |
| 4453 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4454 |
| 4455 // Sanity check the scenario we just created. |
| 4456 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4457 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4458 ASSERT_FALSE(root->screenSpaceTransform().IsInvertible()); |
| 4459 |
| 4460 // Hit testing any point should not hit the layer. If the invertible matrix
is |
| 4461 // accidentally ignored and treated like an identity, then the hit testing w
ill |
| 4462 // incorrectly hit the layer when it shouldn't. |
| 4463 gfx::Point testPoint(1, 1); |
| 4464 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4465 EXPECT_FALSE(resultLayer); |
| 4466 |
| 4467 testPoint = gfx::Point(10, 10); |
| 4468 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4469 EXPECT_FALSE(resultLayer); |
| 4470 |
| 4471 testPoint = gfx::Point(10, 30); |
| 4472 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4473 EXPECT_FALSE(resultLayer); |
| 4474 |
| 4475 testPoint = gfx::Point(50, 50); |
| 4476 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4477 EXPECT_FALSE(resultLayer); |
| 4478 |
| 4479 testPoint = gfx::Point(67, 48); |
| 4480 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4481 EXPECT_FALSE(resultLayer); |
| 4482 |
| 4483 testPoint = gfx::Point(99, 99); |
| 4484 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4485 EXPECT_FALSE(resultLayer); |
| 4486 |
| 4487 testPoint = gfx::Point(-1, -1); |
| 4488 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4489 EXPECT_FALSE(resultLayer); |
| 4490 } |
| 4491 |
| 4492 TEST(LayerTreeHostImplTest, verifyHitTestingForSinglePositionedLayer) |
| 4493 { |
| 4494 FakeImplProxy proxy; |
| 4495 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4496 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 12345)
; |
| 4497 |
| 4498 gfx::Transform identityMatrix; |
| 4499 gfx::PointF anchor(0, 0); |
| 4500 gfx::PointF position(50, 50); // this layer is positioned, and hit testing s
hould correctly know where the layer is located. |
| 4501 gfx::Size bounds(100, 100); |
| 4502 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, position, bounds, false); |
| 4503 root->setDrawsContent(true); |
| 4504 |
| 4505 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4506 int dummyMaxTextureSize = 512; |
| 4507 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4508 |
| 4509 // Sanity check the scenario we just created. |
| 4510 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4511 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4512 |
| 4513 // Hit testing for a point outside the layer should return a null pointer. |
| 4514 gfx::Point testPoint(49, 49); |
| 4515 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4516 EXPECT_FALSE(resultLayer); |
| 4517 |
| 4518 // Even though the layer exists at (101, 101), it should not be visible ther
e since the root renderSurface would clamp it. |
| 4519 testPoint = gfx::Point(101, 101); |
| 4520 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4521 EXPECT_FALSE(resultLayer); |
| 4522 |
| 4523 // Hit testing for a point inside should return the root layer. |
| 4524 testPoint = gfx::Point(51, 51); |
| 4525 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4526 ASSERT_TRUE(resultLayer); |
| 4527 EXPECT_EQ(12345, resultLayer->id()); |
| 4528 |
| 4529 testPoint = gfx::Point(99, 99); |
| 4530 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4531 ASSERT_TRUE(resultLayer); |
| 4532 EXPECT_EQ(12345, resultLayer->id()); |
| 4533 } |
| 4534 |
| 4535 TEST(LayerTreeHostImplTest, verifyHitTestingForSingleRotatedLayer) |
| 4536 { |
| 4537 FakeImplProxy proxy; |
| 4538 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4539 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 12345)
; |
| 4540 |
| 4541 gfx::Transform identityMatrix; |
| 4542 gfx::Transform rotation45DegreesAboutCenter; |
| 4543 rotation45DegreesAboutCenter.Translate(50, 50); |
| 4544 rotation45DegreesAboutCenter.RotateAboutZAxis(45); |
| 4545 rotation45DegreesAboutCenter.Translate(-50, -50); |
| 4546 gfx::PointF anchor(0, 0); |
| 4547 gfx::PointF position(0, 0); |
| 4548 gfx::Size bounds(100, 100); |
| 4549 setLayerPropertiesForTesting(root.get(), rotation45DegreesAboutCenter, ident
ityMatrix, anchor, position, bounds, false); |
| 4550 root->setDrawsContent(true); |
| 4551 |
| 4552 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4553 int dummyMaxTextureSize = 512; |
| 4554 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4555 |
| 4556 // Sanity check the scenario we just created. |
| 4557 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4558 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4559 |
| 4560 // Hit testing for points outside the layer. |
| 4561 // These corners would have been inside the un-transformed layer, but they s
hould not hit the correctly transformed layer. |
| 4562 gfx::Point testPoint(99, 99); |
| 4563 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4564 EXPECT_FALSE(resultLayer); |
| 4565 |
| 4566 testPoint = gfx::Point(1, 1); |
| 4567 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4568 EXPECT_FALSE(resultLayer); |
| 4569 |
| 4570 // Hit testing for a point inside should return the root layer. |
| 4571 testPoint = gfx::Point(1, 50); |
| 4572 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4573 ASSERT_TRUE(resultLayer); |
| 4574 EXPECT_EQ(12345, resultLayer->id()); |
| 4575 |
| 4576 // Hit testing the corners that would overlap the unclipped layer, but are o
utside the clipped region. |
| 4577 testPoint = gfx::Point(50, -1); |
| 4578 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4579 ASSERT_FALSE(resultLayer); |
| 4580 |
| 4581 testPoint = gfx::Point(-1, 50); |
| 4582 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4583 ASSERT_FALSE(resultLayer); |
| 4584 } |
| 4585 |
| 4586 TEST(LayerTreeHostImplTest, verifyHitTestingForSinglePerspectiveLayer) |
| 4587 { |
| 4588 FakeImplProxy proxy; |
| 4589 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4590 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 12345)
; |
| 4591 |
| 4592 gfx::Transform identityMatrix; |
| 4593 |
| 4594 // perspectiveProjectionAboutCenter * translationByZ is designed so that the
100 x 100 layer becomes 50 x 50, and remains centered at (50, 50). |
| 4595 gfx::Transform perspectiveProjectionAboutCenter; |
| 4596 perspectiveProjectionAboutCenter.Translate(50, 50); |
| 4597 perspectiveProjectionAboutCenter.ApplyPerspectiveDepth(1); |
| 4598 perspectiveProjectionAboutCenter.Translate(-50, -50); |
| 4599 gfx::Transform translationByZ; |
| 4600 translationByZ.Translate3d(0, 0, -1); |
| 4601 |
| 4602 gfx::PointF anchor(0, 0); |
| 4603 gfx::PointF position(0, 0); |
| 4604 gfx::Size bounds(100, 100); |
| 4605 setLayerPropertiesForTesting(root.get(), perspectiveProjectionAboutCenter *
translationByZ, identityMatrix, anchor, position, bounds, false); |
| 4606 root->setDrawsContent(true); |
| 4607 |
| 4608 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4609 int dummyMaxTextureSize = 512; |
| 4610 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4611 |
| 4612 // Sanity check the scenario we just created. |
| 4613 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4614 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4615 |
| 4616 // Hit testing for points outside the layer. |
| 4617 // These corners would have been inside the un-transformed layer, but they s
hould not hit the correctly transformed layer. |
| 4618 gfx::Point testPoint(24, 24); |
| 4619 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4620 EXPECT_FALSE(resultLayer); |
| 4621 |
| 4622 testPoint = gfx::Point(76, 76); |
| 4623 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4624 EXPECT_FALSE(resultLayer); |
| 4625 |
| 4626 // Hit testing for a point inside should return the root layer. |
| 4627 testPoint = gfx::Point(26, 26); |
| 4628 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4629 ASSERT_TRUE(resultLayer); |
| 4630 EXPECT_EQ(12345, resultLayer->id()); |
| 4631 |
| 4632 testPoint = gfx::Point(74, 74); |
| 4633 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4634 ASSERT_TRUE(resultLayer); |
| 4635 EXPECT_EQ(12345, resultLayer->id()); |
| 4636 } |
| 4637 |
| 4638 TEST(LayerTreeHostImplTest, verifyHitTestingForSingleLayerWithScaledContents) |
| 4639 { |
| 4640 // A layer's visibleContentRect is actually in the layer's content space. Th
e |
| 4641 // screenSpaceTransform converts from the layer's origin space to screen spa
ce. This |
| 4642 // test makes sure that hit testing works correctly accounts for the content
s scale. |
| 4643 // A contentsScale that is not 1 effectively forces a non-identity transform
between |
| 4644 // layer's content space and layer's origin space. The hit testing code must
take this into account. |
| 4645 // |
| 4646 // To test this, the layer is positioned at (25, 25), and is size (50, 50).
If |
| 4647 // contentsScale is ignored, then hit testing will mis-interpret the visible
ContentRect |
| 4648 // as being larger than the actual bounds of the layer. |
| 4649 // |
| 4650 FakeImplProxy proxy; |
| 4651 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4652 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 1); |
| 4653 |
| 4654 gfx::Transform identityMatrix; |
| 4655 gfx::PointF anchor(0, 0); |
| 4656 |
| 4657 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, gfx::PointF(0, 0), gfx::Size(100, 100), false); |
| 4658 |
| 4659 { |
| 4660 gfx::PointF position(25, 25); |
| 4661 gfx::Size bounds(50, 50); |
| 4662 scoped_ptr<LayerImpl> testLayer = LayerImpl::create(hostImpl.activeTree(
), 12345); |
| 4663 setLayerPropertiesForTesting(testLayer.get(), identityMatrix, identityMa
trix, anchor, position, bounds, false); |
| 4664 |
| 4665 // override contentBounds and contentsScale |
| 4666 testLayer->setContentBounds(gfx::Size(100, 100)); |
| 4667 testLayer->setContentsScale(2, 2); |
| 4668 |
| 4669 testLayer->setDrawsContent(true); |
| 4670 root->addChild(testLayer.Pass()); |
| 4671 } |
| 4672 |
| 4673 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4674 int dummyMaxTextureSize = 512; |
| 4675 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4676 |
| 4677 // Sanity check the scenario we just created. |
| 4678 // The visibleContentRect for testLayer is actually 100x100, even though its
layout size is 50x50, positioned at 25x25. |
| 4679 LayerImpl* testLayer = root->children()[0]; |
| 4680 EXPECT_RECT_EQ(gfx::Rect(gfx::Point(), gfx::Size(100, 100)), testLayer->visi
bleContentRect()); |
| 4681 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4682 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4683 |
| 4684 // Hit testing for a point outside the layer should return a null pointer (t
he root layer does not draw content, so it will not be hit tested either). |
| 4685 gfx::Point testPoint(101, 101); |
| 4686 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4687 EXPECT_FALSE(resultLayer); |
| 4688 |
| 4689 testPoint = gfx::Point(24, 24); |
| 4690 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4691 EXPECT_FALSE(resultLayer); |
| 4692 |
| 4693 testPoint = gfx::Point(76, 76); |
| 4694 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4695 EXPECT_FALSE(resultLayer); |
| 4696 |
| 4697 // Hit testing for a point inside should return the test layer. |
| 4698 testPoint = gfx::Point(26, 26); |
| 4699 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4700 ASSERT_TRUE(resultLayer); |
| 4701 EXPECT_EQ(12345, resultLayer->id()); |
| 4702 |
| 4703 testPoint = gfx::Point(74, 74); |
| 4704 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4705 ASSERT_TRUE(resultLayer); |
| 4706 EXPECT_EQ(12345, resultLayer->id()); |
| 4707 } |
| 4708 |
| 4709 TEST(LayerTreeHostImplTest, verifyHitTestingForSimpleClippedLayer) |
| 4710 { |
| 4711 // Test that hit-testing will only work for the visible portion of a layer,
and not |
| 4712 // the entire layer bounds. Here we just test the simple axis-aligned case. |
| 4713 gfx::Transform identityMatrix; |
| 4714 gfx::PointF anchor(0, 0); |
| 4715 |
| 4716 FakeImplProxy proxy; |
| 4717 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4718 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 1); |
| 4719 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, gfx::PointF(0, 0), gfx::Size(100, 100), false); |
| 4720 |
| 4721 { |
| 4722 scoped_ptr<LayerImpl> clippingLayer = LayerImpl::create(hostImpl.activeT
ree(), 123); |
| 4723 gfx::PointF position(25, 25); // this layer is positioned, and hit testi
ng should correctly know where the layer is located. |
| 4724 gfx::Size bounds(50, 50); |
| 4725 setLayerPropertiesForTesting(clippingLayer.get(), identityMatrix, identi
tyMatrix, anchor, position, bounds, false); |
| 4726 clippingLayer->setMasksToBounds(true); |
| 4727 |
| 4728 scoped_ptr<LayerImpl> child = LayerImpl::create(hostImpl.activeTree(), 4
56); |
| 4729 position = gfx::PointF(-50, -50); |
| 4730 bounds = gfx::Size(300, 300); |
| 4731 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix
, anchor, position, bounds, false); |
| 4732 child->setDrawsContent(true); |
| 4733 clippingLayer->addChild(child.Pass()); |
| 4734 root->addChild(clippingLayer.Pass()); |
| 4735 } |
| 4736 |
| 4737 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4738 int dummyMaxTextureSize = 512; |
| 4739 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4740 |
| 4741 // Sanity check the scenario we just created. |
| 4742 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4743 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4744 ASSERT_EQ(456, root->renderSurface()->layerList()[0]->id()); |
| 4745 |
| 4746 // Hit testing for a point outside the layer should return a null pointer. |
| 4747 // Despite the child layer being very large, it should be clipped to the roo
t layer's bounds. |
| 4748 gfx::Point testPoint(24, 24); |
| 4749 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4750 EXPECT_FALSE(resultLayer); |
| 4751 |
| 4752 // Even though the layer exists at (101, 101), it should not be visible ther
e since the clippingLayer would clamp it. |
| 4753 testPoint = gfx::Point(76, 76); |
| 4754 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4755 EXPECT_FALSE(resultLayer); |
| 4756 |
| 4757 // Hit testing for a point inside should return the child layer. |
| 4758 testPoint = gfx::Point(26, 26); |
| 4759 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4760 ASSERT_TRUE(resultLayer); |
| 4761 EXPECT_EQ(456, resultLayer->id()); |
| 4762 |
| 4763 testPoint = gfx::Point(74, 74); |
| 4764 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4765 ASSERT_TRUE(resultLayer); |
| 4766 EXPECT_EQ(456, resultLayer->id()); |
| 4767 } |
| 4768 |
| 4769 TEST(LayerTreeHostImplTest, verifyHitTestingForMultiClippedRotatedLayer) |
| 4770 { |
| 4771 // This test checks whether hit testing correctly avoids hit testing with mu
ltiple |
| 4772 // ancestors that clip in non axis-aligned ways. To pass this test, the hit
testing |
| 4773 // algorithm needs to recognize that multiple parent layers may clip the lay
er, and |
| 4774 // should not actually hit those clipped areas. |
| 4775 // |
| 4776 // The child and grandChild layers are both initialized to clip the rotatedL
eaf. The |
| 4777 // child layer is rotated about the top-left corner, so that the root + chil
d clips |
| 4778 // combined create a triangle. The rotatedLeaf will only be visible where it
overlaps |
| 4779 // this triangle. |
| 4780 // |
| 4781 FakeImplProxy proxy; |
| 4782 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4783 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 123); |
| 4784 |
| 4785 gfx::Transform identityMatrix; |
| 4786 gfx::PointF anchor(0, 0); |
| 4787 gfx::PointF position(0, 0); |
| 4788 gfx::Size bounds(100, 100); |
| 4789 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, position, bounds, false); |
| 4790 root->setMasksToBounds(true); |
| 4791 |
| 4792 { |
| 4793 scoped_ptr<LayerImpl> child = LayerImpl::create(hostImpl.activeTree(), 4
56); |
| 4794 scoped_ptr<LayerImpl> grandChild = LayerImpl::create(hostImpl.activeTree
(), 789); |
| 4795 scoped_ptr<LayerImpl> rotatedLeaf = LayerImpl::create(hostImpl.activeTre
e(), 2468); |
| 4796 |
| 4797 position = gfx::PointF(10, 10); |
| 4798 bounds = gfx::Size(80, 80); |
| 4799 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix
, anchor, position, bounds, false); |
| 4800 child->setMasksToBounds(true); |
| 4801 |
| 4802 gfx::Transform rotation45DegreesAboutCorner; |
| 4803 rotation45DegreesAboutCorner.RotateAboutZAxis(45); |
| 4804 |
| 4805 position = gfx::PointF(0, 0); // remember, positioned with respect to it
s parent which is already at 10, 10 |
| 4806 bounds = gfx::Size(200, 200); // to ensure it covers at least sqrt(2) *
100. |
| 4807 setLayerPropertiesForTesting(grandChild.get(), rotation45DegreesAboutCor
ner, identityMatrix, anchor, position, bounds, false); |
| 4808 grandChild->setMasksToBounds(true); |
| 4809 |
| 4810 // Rotates about the center of the layer |
| 4811 gfx::Transform rotatedLeafTransform; |
| 4812 rotatedLeafTransform.Translate(-10, -10); // cancel out the grandParent'
s position |
| 4813 rotatedLeafTransform.RotateAboutZAxis(-45); // cancel out the corner 45-
degree rotation of the parent. |
| 4814 rotatedLeafTransform.Translate(50, 50); |
| 4815 rotatedLeafTransform.RotateAboutZAxis(45); |
| 4816 rotatedLeafTransform.Translate(-50, -50); |
| 4817 position = gfx::PointF(0, 0); |
| 4818 bounds = gfx::Size(100, 100); |
| 4819 setLayerPropertiesForTesting(rotatedLeaf.get(), rotatedLeafTransform, id
entityMatrix, anchor, position, bounds, false); |
| 4820 rotatedLeaf->setDrawsContent(true); |
| 4821 |
| 4822 grandChild->addChild(rotatedLeaf.Pass()); |
| 4823 child->addChild(grandChild.Pass()); |
| 4824 root->addChild(child.Pass()); |
| 4825 } |
| 4826 |
| 4827 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4828 int dummyMaxTextureSize = 512; |
| 4829 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4830 |
| 4831 // Sanity check the scenario we just created. |
| 4832 // The grandChild is expected to create a renderSurface because it masksToBo
unds and is not axis aligned. |
| 4833 ASSERT_EQ(2u, renderSurfaceLayerList.size()); |
| 4834 ASSERT_EQ(1u, renderSurfaceLayerList[0]->renderSurface()->layerList().size()
); |
| 4835 ASSERT_EQ(789, renderSurfaceLayerList[0]->renderSurface()->layerList()[0]->i
d()); // grandChild's surface. |
| 4836 ASSERT_EQ(1u, renderSurfaceLayerList[1]->renderSurface()->layerList().size()
); |
| 4837 ASSERT_EQ(2468, renderSurfaceLayerList[1]->renderSurface()->layerList()[0]->
id()); |
| 4838 |
| 4839 // (11, 89) is close to the the bottom left corner within the clip, but it i
s not inside the layer. |
| 4840 gfx::Point testPoint(11, 89); |
| 4841 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4842 EXPECT_FALSE(resultLayer); |
| 4843 |
| 4844 // Closer inwards from the bottom left will overlap the layer. |
| 4845 testPoint = gfx::Point(25, 75); |
| 4846 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4847 ASSERT_TRUE(resultLayer); |
| 4848 EXPECT_EQ(2468, resultLayer->id()); |
| 4849 |
| 4850 // (4, 50) is inside the unclipped layer, but that corner of the layer shoul
d be |
| 4851 // clipped away by the grandParent and should not get hit. If hit testing bl
indly uses |
| 4852 // visibleContentRect without considering how parent may clip the layer, the
n hit |
| 4853 // testing would accidentally think that the point successfully hits the lay
er. |
| 4854 testPoint = gfx::Point(4, 50); |
| 4855 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4856 EXPECT_FALSE(resultLayer); |
| 4857 |
| 4858 // (11, 50) is inside the layer and within the clipped area. |
| 4859 testPoint = gfx::Point(11, 50); |
| 4860 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4861 ASSERT_TRUE(resultLayer); |
| 4862 EXPECT_EQ(2468, resultLayer->id()); |
| 4863 |
| 4864 // Around the middle, just to the right and up, would have hit the layer exc
ept that |
| 4865 // that area should be clipped away by the parent. |
| 4866 testPoint = gfx::Point(51, 51); |
| 4867 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4868 EXPECT_FALSE(resultLayer); |
| 4869 |
| 4870 // Around the middle, just to the left and down, should successfully hit the
layer. |
| 4871 testPoint = gfx::Point(49, 51); |
| 4872 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4873 ASSERT_TRUE(resultLayer); |
| 4874 EXPECT_EQ(2468, resultLayer->id()); |
| 4875 } |
| 4876 |
| 4877 TEST(LayerTreeHostImplTest, verifyHitTestingForNonClippingIntermediateLayer) |
| 4878 { |
| 4879 // This test checks that hit testing code does not accidentally clip to laye
r |
| 4880 // bounds for a layer that actually does not clip. |
| 4881 gfx::Transform identityMatrix; |
| 4882 gfx::PointF anchor(0, 0); |
| 4883 |
| 4884 FakeImplProxy proxy; |
| 4885 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4886 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 1); |
| 4887 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, gfx::PointF(0, 0), gfx::Size(100, 100), false); |
| 4888 |
| 4889 { |
| 4890 scoped_ptr<LayerImpl> intermediateLayer = LayerImpl::create(hostImpl.act
iveTree(), 123); |
| 4891 gfx::PointF position(10, 10); // this layer is positioned, and hit testi
ng should correctly know where the layer is located. |
| 4892 gfx::Size bounds(50, 50); |
| 4893 setLayerPropertiesForTesting(intermediateLayer.get(), identityMatrix, id
entityMatrix, anchor, position, bounds, false); |
| 4894 // Sanity check the intermediate layer should not clip. |
| 4895 ASSERT_FALSE(intermediateLayer->masksToBounds()); |
| 4896 ASSERT_FALSE(intermediateLayer->maskLayer()); |
| 4897 |
| 4898 // The child of the intermediateLayer is translated so that it does not
overlap intermediateLayer at all. |
| 4899 // If child is incorrectly clipped, we would not be able to hit it succe
ssfully. |
| 4900 scoped_ptr<LayerImpl> child = LayerImpl::create(hostImpl.activeTree(), 4
56); |
| 4901 position = gfx::PointF(60, 60); // 70, 70 in screen space |
| 4902 bounds = gfx::Size(20, 20); |
| 4903 setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix
, anchor, position, bounds, false); |
| 4904 child->setDrawsContent(true); |
| 4905 intermediateLayer->addChild(child.Pass()); |
| 4906 root->addChild(intermediateLayer.Pass()); |
| 4907 } |
| 4908 |
| 4909 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4910 int dummyMaxTextureSize = 512; |
| 4911 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4912 |
| 4913 // Sanity check the scenario we just created. |
| 4914 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4915 ASSERT_EQ(1u, root->renderSurface()->layerList().size()); |
| 4916 ASSERT_EQ(456, root->renderSurface()->layerList()[0]->id()); |
| 4917 |
| 4918 // Hit testing for a point outside the layer should return a null pointer. |
| 4919 gfx::Point testPoint(69, 69); |
| 4920 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 4921 EXPECT_FALSE(resultLayer); |
| 4922 |
| 4923 testPoint = gfx::Point(91, 91); |
| 4924 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4925 EXPECT_FALSE(resultLayer); |
| 4926 |
| 4927 // Hit testing for a point inside should return the child layer. |
| 4928 testPoint = gfx::Point(71, 71); |
| 4929 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4930 ASSERT_TRUE(resultLayer); |
| 4931 EXPECT_EQ(456, resultLayer->id()); |
| 4932 |
| 4933 testPoint = gfx::Point(89, 89); |
| 4934 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 4935 ASSERT_TRUE(resultLayer); |
| 4936 EXPECT_EQ(456, resultLayer->id()); |
| 4937 } |
| 4938 |
| 4939 |
| 4940 TEST(LayerTreeHostImplTest, verifyHitTestingForMultipleLayers) |
| 4941 { |
| 4942 FakeImplProxy proxy; |
| 4943 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 4944 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 1); |
| 4945 |
| 4946 gfx::Transform identityMatrix; |
| 4947 gfx::PointF anchor(0, 0); |
| 4948 gfx::PointF position(0, 0); |
| 4949 gfx::Size bounds(100, 100); |
| 4950 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, position, bounds, false); |
| 4951 root->setDrawsContent(true); |
| 4952 |
| 4953 { |
| 4954 // child 1 and child2 are initialized to overlap between x=50 and x=60. |
| 4955 // grandChild is set to overlap both child1 and child2 between y=50 and
y=60. |
| 4956 // The expected stacking order is: |
| 4957 // (front) child2, (second) grandChild, (third) child1, and (back) the
root layer behind all other layers. |
| 4958 |
| 4959 scoped_ptr<LayerImpl> child1 = LayerImpl::create(hostImpl.activeTree(),
2); |
| 4960 scoped_ptr<LayerImpl> child2 = LayerImpl::create(hostImpl.activeTree(),
3); |
| 4961 scoped_ptr<LayerImpl> grandChild1 = LayerImpl::create(hostImpl.activeTre
e(), 4); |
| 4962 |
| 4963 position = gfx::PointF(10, 10); |
| 4964 bounds = gfx::Size(50, 50); |
| 4965 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatri
x, anchor, position, bounds, false); |
| 4966 child1->setDrawsContent(true); |
| 4967 |
| 4968 position = gfx::PointF(50, 10); |
| 4969 bounds = gfx::Size(50, 50); |
| 4970 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatri
x, anchor, position, bounds, false); |
| 4971 child2->setDrawsContent(true); |
| 4972 |
| 4973 // Remember that grandChild is positioned with respect to its parent (i.
e. child1). |
| 4974 // In screen space, the intended position is (10, 50), with size 100 x 5
0. |
| 4975 position = gfx::PointF(0, 40); |
| 4976 bounds = gfx::Size(100, 50); |
| 4977 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identity
Matrix, anchor, position, bounds, false); |
| 4978 grandChild1->setDrawsContent(true); |
| 4979 |
| 4980 child1->addChild(grandChild1.Pass()); |
| 4981 root->addChild(child1.Pass()); |
| 4982 root->addChild(child2.Pass()); |
| 4983 } |
| 4984 |
| 4985 LayerImpl* child1 = root->children()[0]; |
| 4986 LayerImpl* child2 = root->children()[1]; |
| 4987 LayerImpl* grandChild1 = child1->children()[0]; |
| 4988 |
| 4989 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 4990 int dummyMaxTextureSize = 512; |
| 4991 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 4992 |
| 4993 // Sanity check the scenario we just created. |
| 4994 ASSERT_TRUE(child1); |
| 4995 ASSERT_TRUE(child2); |
| 4996 ASSERT_TRUE(grandChild1); |
| 4997 ASSERT_EQ(1u, renderSurfaceLayerList.size()); |
| 4998 ASSERT_EQ(4u, root->renderSurface()->layerList().size()); |
| 4999 ASSERT_EQ(1, root->renderSurface()->layerList()[0]->id()); // root layer |
| 5000 ASSERT_EQ(2, root->renderSurface()->layerList()[1]->id()); // child1 |
| 5001 ASSERT_EQ(4, root->renderSurface()->layerList()[2]->id()); // grandChild1 |
| 5002 ASSERT_EQ(3, root->renderSurface()->layerList()[3]->id()); // child2 |
| 5003 |
| 5004 // Nothing overlaps the rootLayer at (1, 1), so hit testing there should fin
d the root layer. |
| 5005 gfx::Point testPoint = gfx::Point(1, 1); |
| 5006 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 5007 ASSERT_TRUE(resultLayer); |
| 5008 EXPECT_EQ(1, resultLayer->id()); |
| 5009 |
| 5010 // At (15, 15), child1 and root are the only layers. child1 is expected to b
e on top. |
| 5011 testPoint = gfx::Point(15, 15); |
| 5012 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5013 ASSERT_TRUE(resultLayer); |
| 5014 EXPECT_EQ(2, resultLayer->id()); |
| 5015 |
| 5016 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top. |
| 5017 testPoint = gfx::Point(51, 20); |
| 5018 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5019 ASSERT_TRUE(resultLayer); |
| 5020 EXPECT_EQ(3, resultLayer->id()); |
| 5021 |
| 5022 // At (80, 51), child2 and grandChild1 overlap. child2 is expected to be on
top. |
| 5023 testPoint = gfx::Point(80, 51); |
| 5024 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5025 ASSERT_TRUE(resultLayer); |
| 5026 EXPECT_EQ(3, resultLayer->id()); |
| 5027 |
| 5028 // At (51, 51), all layers overlap each other. child2 is expected to be on t
op of all other layers. |
| 5029 testPoint = gfx::Point(51, 51); |
| 5030 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5031 ASSERT_TRUE(resultLayer); |
| 5032 EXPECT_EQ(3, resultLayer->id()); |
| 5033 |
| 5034 // At (20, 51), child1 and grandChild1 overlap. grandChild1 is expected to b
e on top. |
| 5035 testPoint = gfx::Point(20, 51); |
| 5036 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5037 ASSERT_TRUE(resultLayer); |
| 5038 EXPECT_EQ(4, resultLayer->id()); |
| 5039 } |
| 5040 |
| 5041 TEST(LayerTreeHostImplTest, verifyHitTestingForMultipleLayerLists) |
| 5042 { |
| 5043 // |
| 5044 // The geometry is set up similarly to the previous case, but |
| 5045 // all layers are forced to be renderSurfaces now. |
| 5046 // |
| 5047 FakeImplProxy proxy; |
| 5048 FakeLayerTreeHostImpl hostImpl(&proxy); |
| 5049 scoped_ptr<LayerImpl> root = LayerImpl::create(hostImpl.activeTree(), 1); |
| 5050 |
| 5051 gfx::Transform identityMatrix; |
| 5052 gfx::PointF anchor(0, 0); |
| 5053 gfx::PointF position(0, 0); |
| 5054 gfx::Size bounds(100, 100); |
| 5055 setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, anc
hor, position, bounds, false); |
| 5056 root->setDrawsContent(true); |
| 5057 |
| 5058 { |
| 5059 // child 1 and child2 are initialized to overlap between x=50 and x=60. |
| 5060 // grandChild is set to overlap both child1 and child2 between y=50 and
y=60. |
| 5061 // The expected stacking order is: |
| 5062 // (front) child2, (second) grandChild, (third) child1, and (back) the
root layer behind all other layers. |
| 5063 |
| 5064 scoped_ptr<LayerImpl> child1 = LayerImpl::create(hostImpl.activeTree(),
2); |
| 5065 scoped_ptr<LayerImpl> child2 = LayerImpl::create(hostImpl.activeTree(),
3); |
| 5066 scoped_ptr<LayerImpl> grandChild1 = LayerImpl::create(hostImpl.activeTre
e(), 4); |
| 5067 |
| 5068 position = gfx::PointF(10, 10); |
| 5069 bounds = gfx::Size(50, 50); |
| 5070 setLayerPropertiesForTesting(child1.get(), identityMatrix, identityMatri
x, anchor, position, bounds, false); |
| 5071 child1->setDrawsContent(true); |
| 5072 child1->setForceRenderSurface(true); |
| 5073 |
| 5074 position = gfx::PointF(50, 10); |
| 5075 bounds = gfx::Size(50, 50); |
| 5076 setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatri
x, anchor, position, bounds, false); |
| 5077 child2->setDrawsContent(true); |
| 5078 child2->setForceRenderSurface(true); |
| 5079 |
| 5080 // Remember that grandChild is positioned with respect to its parent (i.
e. child1). |
| 5081 // In screen space, the intended position is (10, 50), with size 100 x 5
0. |
| 5082 position = gfx::PointF(0, 40); |
| 5083 bounds = gfx::Size(100, 50); |
| 5084 setLayerPropertiesForTesting(grandChild1.get(), identityMatrix, identity
Matrix, anchor, position, bounds, false); |
| 5085 grandChild1->setDrawsContent(true); |
| 5086 grandChild1->setForceRenderSurface(true); |
| 5087 |
| 5088 child1->addChild(grandChild1.Pass()); |
| 5089 root->addChild(child1.Pass()); |
| 5090 root->addChild(child2.Pass()); |
| 5091 } |
| 5092 |
| 5093 LayerImpl* child1 = root->children()[0]; |
| 5094 LayerImpl* child2 = root->children()[1]; |
| 5095 LayerImpl* grandChild1 = child1->children()[0]; |
| 5096 |
| 5097 std::vector<LayerImpl*> renderSurfaceLayerList; |
| 5098 int dummyMaxTextureSize = 512; |
| 5099 LayerTreeHostCommon::calculateDrawProperties(root.get(), root->bounds(), 1,
1, dummyMaxTextureSize, false, renderSurfaceLayerList, false); |
| 5100 |
| 5101 // Sanity check the scenario we just created. |
| 5102 ASSERT_TRUE(child1); |
| 5103 ASSERT_TRUE(child2); |
| 5104 ASSERT_TRUE(grandChild1); |
| 5105 ASSERT_TRUE(child1->renderSurface()); |
| 5106 ASSERT_TRUE(child2->renderSurface()); |
| 5107 ASSERT_TRUE(grandChild1->renderSurface()); |
| 5108 ASSERT_EQ(4u, renderSurfaceLayerList.size()); |
| 5109 ASSERT_EQ(3u, root->renderSurface()->layerList().size()); // The root surfac
e has the root layer, and child1's and child2's renderSurfaces. |
| 5110 ASSERT_EQ(2u, child1->renderSurface()->layerList().size()); // The child1 su
rface has the child1 layer and grandChild1's renderSurface. |
| 5111 ASSERT_EQ(1u, child2->renderSurface()->layerList().size()); |
| 5112 ASSERT_EQ(1u, grandChild1->renderSurface()->layerList().size()); |
| 5113 ASSERT_EQ(1, renderSurfaceLayerList[0]->id()); // root layer |
| 5114 ASSERT_EQ(2, renderSurfaceLayerList[1]->id()); // child1 |
| 5115 ASSERT_EQ(4, renderSurfaceLayerList[2]->id()); // grandChild1 |
| 5116 ASSERT_EQ(3, renderSurfaceLayerList[3]->id()); // child2 |
| 5117 |
| 5118 // Nothing overlaps the rootLayer at (1, 1), so hit testing there should fin
d the root layer. |
| 5119 gfx::Point testPoint = gfx::Point(1, 1); |
| 5120 LayerImpl* resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, rende
rSurfaceLayerList); |
| 5121 ASSERT_TRUE(resultLayer); |
| 5122 EXPECT_EQ(1, resultLayer->id()); |
| 5123 |
| 5124 // At (15, 15), child1 and root are the only layers. child1 is expected to b
e on top. |
| 5125 testPoint = gfx::Point(15, 15); |
| 5126 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5127 ASSERT_TRUE(resultLayer); |
| 5128 EXPECT_EQ(2, resultLayer->id()); |
| 5129 |
| 5130 // At (51, 20), child1 and child2 overlap. child2 is expected to be on top. |
| 5131 testPoint = gfx::Point(51, 20); |
| 5132 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5133 ASSERT_TRUE(resultLayer); |
| 5134 EXPECT_EQ(3, resultLayer->id()); |
| 5135 |
| 5136 // At (80, 51), child2 and grandChild1 overlap. child2 is expected to be on
top. |
| 5137 testPoint = gfx::Point(80, 51); |
| 5138 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5139 ASSERT_TRUE(resultLayer); |
| 5140 EXPECT_EQ(3, resultLayer->id()); |
| 5141 |
| 5142 // At (51, 51), all layers overlap each other. child2 is expected to be on t
op of all other layers. |
| 5143 testPoint = gfx::Point(51, 51); |
| 5144 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5145 ASSERT_TRUE(resultLayer); |
| 5146 EXPECT_EQ(3, resultLayer->id()); |
| 5147 |
| 5148 // At (20, 51), child1 and grandChild1 overlap. grandChild1 is expected to b
e on top. |
| 5149 testPoint = gfx::Point(20, 51); |
| 5150 resultLayer = hostImpl.findLayerThatIsHitByPoint(testPoint, renderSurfaceLay
erList); |
| 5151 ASSERT_TRUE(resultLayer); |
| 5152 EXPECT_EQ(4, resultLayer->id()); |
| 5153 } |
| 5154 |
| 4346 INSTANTIATE_TEST_CASE_P(LayerTreeHostImplTests, | 5155 INSTANTIATE_TEST_CASE_P(LayerTreeHostImplTests, |
| 4347 LayerTreeHostImplTest, | 5156 LayerTreeHostImplTest, |
| 4348 ::testing::Values(false, true)); | 5157 ::testing::Values(false, true)); |
| 4349 | 5158 |
| 4350 } // namespace | 5159 } // namespace |
| 4351 } // namespace cc | 5160 } // namespace cc |
| OLD | NEW |