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 3 // found in the LICENSE file. 4 5 #include "cc/trees/tree_synchronizer.h" 6 7 #include <algorithm> 8 #include <set> 9 #include <vector> 10 11 #include "cc/animation/layer_animation_controller.h" 12 #include "cc/layers/layer.h" 13 #include "cc/layers/layer_impl.h" 14 #include "cc/test/animation_test_common.h" 15 #include "cc/test/fake_impl_proxy.h" 16 #include "cc/test/fake_layer_tree_host.h" 17 #include "cc/trees/proxy.h" 18 #include "cc/trees/single_thread_proxy.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 namespace cc { 22 namespace { 23 24 class MockLayerImpl : public LayerImpl { 25 public: 26 static scoped_ptr<MockLayerImpl> Create(LayerTreeImpl* tree_impl, 27 int layer_id) { 28 return make_scoped_ptr(new MockLayerImpl(tree_impl, layer_id)); 29 } 30 virtual ~MockLayerImpl() { 31 if (layer_impl_destruction_list_) 32 layer_impl_destruction_list_->push_back(id()); 33 } 34 35 void SetLayerImplDestructionList(std::vector<int>* list) { 36 layer_impl_destruction_list_ = list; 37 } 38 39 private: 40 MockLayerImpl(LayerTreeImpl* tree_impl, int layer_id) 41 : LayerImpl(tree_impl, layer_id), 42 layer_impl_destruction_list_(NULL) {} 43 44 std::vector<int>* layer_impl_destruction_list_; 45 }; 46 47 class MockLayer : public Layer { 48 public: 49 static scoped_refptr<MockLayer> Create( 50 std::vector<int>* layer_impl_destruction_list) { 51 return make_scoped_refptr(new MockLayer(layer_impl_destruction_list)); 52 } 53 54 virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) 55 OVERRIDE { 56 return MockLayerImpl::Create(tree_impl, layer_id_).PassAs<LayerImpl>(); 57 } 58 59 virtual void PushPropertiesTo(LayerImpl* layer_impl) OVERRIDE { 60 Layer::PushPropertiesTo(layer_impl); 61 62 MockLayerImpl* mock_layer_impl = static_cast<MockLayerImpl*>(layer_impl); 63 mock_layer_impl->SetLayerImplDestructionList(layer_impl_destruction_list_); 64 } 65 66 private: 67 explicit MockLayer(std::vector<int>* layer_impl_destruction_list) 68 : Layer(), layer_impl_destruction_list_(layer_impl_destruction_list) {} 69 virtual ~MockLayer() {} 70 71 std::vector<int>* layer_impl_destruction_list_; 72 }; 73 74 class FakeLayerAnimationController : public LayerAnimationController { 75 public: 76 static scoped_refptr<LayerAnimationController> Create() { 77 return static_cast<LayerAnimationController*>( 78 new FakeLayerAnimationController); 79 } 80 81 bool SynchronizedAnimations() const { return synchronized_animations_; } 82 83 private: 84 FakeLayerAnimationController() 85 : LayerAnimationController(1), 86 synchronized_animations_(false) {} 87 88 virtual ~FakeLayerAnimationController() {} 89 90 virtual void PushAnimationUpdatesTo(LayerAnimationController* controller_impl) 91 OVERRIDE { 92 LayerAnimationController::PushAnimationUpdatesTo(controller_impl); 93 synchronized_animations_ = true; 94 } 95 96 bool synchronized_animations_; 97 }; 98 99 void ExpectTreesAreIdentical(Layer* layer, 100 LayerImpl* layer_impl, 101 LayerTreeImpl* tree_impl) { 102 ASSERT_TRUE(layer); 103 ASSERT_TRUE(layer_impl); 104 105 EXPECT_EQ(layer->id(), layer_impl->id()); 106 EXPECT_EQ(layer_impl->layer_tree_impl(), tree_impl); 107 108 EXPECT_EQ(layer->non_fast_scrollable_region(), 109 layer_impl->non_fast_scrollable_region()); 110 111 ASSERT_EQ(!!layer->mask_layer(), !!layer_impl->mask_layer()); 112 if (layer->mask_layer()) { 113 ExpectTreesAreIdentical( 114 layer->mask_layer(), layer_impl->mask_layer(), tree_impl); 115 } 116 117 ASSERT_EQ(!!layer->replica_layer(), !!layer_impl->replica_layer()); 118 if (layer->replica_layer()) { 119 ExpectTreesAreIdentical( 120 layer->replica_layer(), layer_impl->replica_layer(), tree_impl); 121 } 122 123 const LayerList& layer_children = layer->children(); 124 const OwnedLayerImplList& layer_impl_children = layer_impl->children(); 125 126 ASSERT_EQ(layer_children.size(), layer_impl_children.size()); 127 128 const std::set<Layer*>* layer_scroll_children = layer->scroll_children(); 129 const std::set<LayerImpl*>* layer_impl_scroll_children = 130 layer_impl->scroll_children(); 131 132 ASSERT_EQ(!!layer_scroll_children, !!layer_impl_scroll_children); 133 134 if (layer_scroll_children) { 135 ASSERT_EQ( 136 layer_scroll_children->size(), 137 layer_impl_scroll_children->size()); 138 } 139 140 const Layer* layer_scroll_parent = layer->scroll_parent(); 141 const LayerImpl* layer_impl_scroll_parent = layer_impl->scroll_parent(); 142 143 ASSERT_EQ(!!layer_scroll_parent, !!layer_impl_scroll_parent); 144 145 if (layer_scroll_parent) { 146 ASSERT_EQ(layer_scroll_parent->id(), layer_impl_scroll_parent->id()); 147 ASSERT_TRUE(layer_scroll_parent->scroll_children()->find(layer) != 148 layer_scroll_parent->scroll_children()->end()); 149 ASSERT_TRUE(layer_impl_scroll_parent->scroll_children()->find(layer_impl) != 150 layer_impl_scroll_parent->scroll_children()->end()); 151 } 152 153 const std::set<Layer*>* layer_clip_children = layer->clip_children(); 154 const std::set<LayerImpl*>* layer_impl_clip_children = 155 layer_impl->clip_children(); 156 157 ASSERT_EQ(!!layer_clip_children, !!layer_impl_clip_children); 158 159 if (layer_clip_children) 160 ASSERT_EQ(layer_clip_children->size(), layer_impl_clip_children->size()); 161 162 const Layer* layer_clip_parent = layer->clip_parent(); 163 const LayerImpl* layer_impl_clip_parent = layer_impl->clip_parent(); 164 165 ASSERT_EQ(!!layer_clip_parent, !!layer_impl_clip_parent); 166 167 if (layer_clip_parent) { 168 const std::set<LayerImpl*>* clip_children_impl = 169 layer_impl_clip_parent->clip_children(); 170 const std::set<Layer*>* clip_children = 171 layer_clip_parent->clip_children(); 172 ASSERT_EQ(layer_clip_parent->id(), layer_impl_clip_parent->id()); 173 ASSERT_TRUE(clip_children->find(layer) != clip_children->end()); 174 ASSERT_TRUE(clip_children_impl->find(layer_impl) != 175 clip_children_impl->end()); 176 } 177 178 for (size_t i = 0; i < layer_children.size(); ++i) { 179 ExpectTreesAreIdentical( 180 layer_children[i].get(), layer_impl_children[i], tree_impl); 181 } 182 } 183 184 class TreeSynchronizerTest : public testing::Test { 185 public: 186 TreeSynchronizerTest() : host_(FakeLayerTreeHost::Create()) {} 187 188 protected: 189 scoped_ptr<FakeLayerTreeHost> host_; 190 }; 191 192 // Attempts to synchronizes a null tree. This should not crash, and should 193 // return a null tree. 194 TEST_F(TreeSynchronizerTest, SyncNullTree) { 195 scoped_ptr<LayerImpl> layer_impl_tree_root = 196 TreeSynchronizer::SynchronizeTrees(static_cast<Layer*>(NULL), 197 scoped_ptr<LayerImpl>(), 198 host_->active_tree()); 199 200 EXPECT_TRUE(!layer_impl_tree_root.get()); 201 } 202 203 // Constructs a very simple tree and synchronizes it without trying to reuse any 204 // preexisting layers. 205 TEST_F(TreeSynchronizerTest, SyncSimpleTreeFromEmpty) { 206 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 207 layer_tree_root->AddChild(Layer::Create()); 208 layer_tree_root->AddChild(Layer::Create()); 209 210 host_->SetRootLayer(layer_tree_root); 211 212 scoped_ptr<LayerImpl> layer_impl_tree_root = 213 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 214 scoped_ptr<LayerImpl>(), 215 host_->active_tree()); 216 217 ExpectTreesAreIdentical(layer_tree_root.get(), 218 layer_impl_tree_root.get(), 219 host_->active_tree()); 220 } 221 222 // Constructs a very simple tree and synchronizes it attempting to reuse some 223 // layers 224 TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { 225 std::vector<int> layer_impl_destruction_list; 226 227 scoped_refptr<Layer> layer_tree_root = 228 MockLayer::Create(&layer_impl_destruction_list); 229 layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 230 layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 231 232 host_->SetRootLayer(layer_tree_root); 233 234 scoped_ptr<LayerImpl> layer_impl_tree_root = 235 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 236 scoped_ptr<LayerImpl>(), 237 host_->active_tree()); 238 ExpectTreesAreIdentical(layer_tree_root.get(), 239 layer_impl_tree_root.get(), 240 host_->active_tree()); 241 242 // We have to push properties to pick up the destruction list pointer. 243 TreeSynchronizer::PushProperties(layer_tree_root.get(), 244 layer_impl_tree_root.get()); 245 246 // Add a new layer to the Layer side 247 layer_tree_root->children()[0]-> 248 AddChild(MockLayer::Create(&layer_impl_destruction_list)); 249 // Remove one. 250 layer_tree_root->children()[1]->RemoveFromParent(); 251 int second_layer_impl_id = layer_impl_tree_root->children()[1]->id(); 252 253 // Synchronize again. After the sync the trees should be equivalent and we 254 // should have created and destroyed one LayerImpl. 255 layer_impl_tree_root = 256 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 257 layer_impl_tree_root.Pass(), 258 host_->active_tree()); 259 ExpectTreesAreIdentical(layer_tree_root.get(), 260 layer_impl_tree_root.get(), 261 host_->active_tree()); 262 263 ASSERT_EQ(1u, layer_impl_destruction_list.size()); 264 EXPECT_EQ(second_layer_impl_id, layer_impl_destruction_list[0]); 265 } 266 267 // Constructs a very simple tree and checks that a stacking-order change is 268 // tracked properly. 269 TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndTrackStackingOrderChange) { 270 std::vector<int> layer_impl_destruction_list; 271 272 // Set up the tree and sync once. child2 needs to be synced here, too, even 273 // though we remove it to set up the intended scenario. 274 scoped_refptr<Layer> layer_tree_root = 275 MockLayer::Create(&layer_impl_destruction_list); 276 scoped_refptr<Layer> child2 = MockLayer::Create(&layer_impl_destruction_list); 277 layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 278 layer_tree_root->AddChild(child2); 279 280 host_->SetRootLayer(layer_tree_root); 281 282 scoped_ptr<LayerImpl> layer_impl_tree_root = 283 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 284 scoped_ptr<LayerImpl>(), 285 host_->active_tree()); 286 ExpectTreesAreIdentical(layer_tree_root.get(), 287 layer_impl_tree_root.get(), 288 host_->active_tree()); 289 290 // We have to push properties to pick up the destruction list pointer. 291 TreeSynchronizer::PushProperties(layer_tree_root.get(), 292 layer_impl_tree_root.get()); 293 294 layer_impl_tree_root->ResetAllChangeTrackingForSubtree(); 295 296 // re-insert the layer and sync again. 297 child2->RemoveFromParent(); 298 layer_tree_root->AddChild(child2); 299 layer_impl_tree_root = 300 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 301 layer_impl_tree_root.Pass(), 302 host_->active_tree()); 303 ExpectTreesAreIdentical(layer_tree_root.get(), 304 layer_impl_tree_root.get(), 305 host_->active_tree()); 306 307 TreeSynchronizer::PushProperties(layer_tree_root.get(), 308 layer_impl_tree_root.get()); 309 310 // Check that the impl thread properly tracked the change. 311 EXPECT_FALSE(layer_impl_tree_root->LayerPropertyChanged()); 312 EXPECT_FALSE(layer_impl_tree_root->children()[0]->LayerPropertyChanged()); 313 EXPECT_TRUE(layer_impl_tree_root->children()[1]->LayerPropertyChanged()); 314 } 315 316 TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndProperties) { 317 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 318 layer_tree_root->AddChild(Layer::Create()); 319 layer_tree_root->AddChild(Layer::Create()); 320 321 host_->SetRootLayer(layer_tree_root); 322 323 // Pick some random properties to set. The values are not important, we're 324 // just testing that at least some properties are making it through. 325 gfx::PointF root_position = gfx::PointF(2.3f, 7.4f); 326 layer_tree_root->SetPosition(root_position); 327 328 float first_child_opacity = 0.25f; 329 layer_tree_root->children()[0]->SetOpacity(first_child_opacity); 330 331 gfx::Size second_child_bounds = gfx::Size(25, 53); 332 layer_tree_root->children()[1]->SetBounds(second_child_bounds); 333 layer_tree_root->children()[1]->SavePaintProperties(); 334 335 scoped_ptr<LayerImpl> layer_impl_tree_root = 336 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 337 scoped_ptr<LayerImpl>(), 338 host_->active_tree()); 339 ExpectTreesAreIdentical(layer_tree_root.get(), 340 layer_impl_tree_root.get(), 341 host_->active_tree()); 342 343 TreeSynchronizer::PushProperties(layer_tree_root.get(), 344 layer_impl_tree_root.get()); 345 346 // Check that the property values we set on the Layer tree are reflected in 347 // the LayerImpl tree. 348 gfx::PointF root_layer_impl_position = layer_impl_tree_root->position(); 349 EXPECT_EQ(root_position.x(), root_layer_impl_position.x()); 350 EXPECT_EQ(root_position.y(), root_layer_impl_position.y()); 351 352 EXPECT_EQ(first_child_opacity, 353 layer_impl_tree_root->children()[0]->opacity()); 354 355 gfx::Size second_layer_impl_child_bounds = 356 layer_impl_tree_root->children()[1]->bounds(); 357 EXPECT_EQ(second_child_bounds.width(), 358 second_layer_impl_child_bounds.width()); 359 EXPECT_EQ(second_child_bounds.height(), 360 second_layer_impl_child_bounds.height()); 361 } 362 363 TEST_F(TreeSynchronizerTest, ReuseLayerImplsAfterStructuralChange) { 364 std::vector<int> layer_impl_destruction_list; 365 366 // Set up a tree with this sort of structure: 367 // root --- A --- B ---+--- C 368 // | 369 // +--- D 370 scoped_refptr<Layer> layer_tree_root = 371 MockLayer::Create(&layer_impl_destruction_list); 372 layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 373 374 scoped_refptr<Layer> layer_a = layer_tree_root->children()[0].get(); 375 layer_a->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 376 377 scoped_refptr<Layer> layer_b = layer_a->children()[0].get(); 378 layer_b->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 379 380 scoped_refptr<Layer> layer_c = layer_b->children()[0].get(); 381 layer_b->AddChild(MockLayer::Create(&layer_impl_destruction_list)); 382 scoped_refptr<Layer> layer_d = layer_b->children()[1].get(); 383 384 host_->SetRootLayer(layer_tree_root); 385 386 scoped_ptr<LayerImpl> layer_impl_tree_root = 387 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 388 scoped_ptr<LayerImpl>(), 389 host_->active_tree()); 390 ExpectTreesAreIdentical(layer_tree_root.get(), 391 layer_impl_tree_root.get(), 392 host_->active_tree()); 393 394 // We have to push properties to pick up the destruction list pointer. 395 TreeSynchronizer::PushProperties(layer_tree_root.get(), 396 layer_impl_tree_root.get()); 397 398 // Now restructure the tree to look like this: 399 // root --- D ---+--- A 400 // | 401 // +--- C --- B 402 layer_tree_root->RemoveAllChildren(); 403 layer_d->RemoveAllChildren(); 404 layer_tree_root->AddChild(layer_d); 405 layer_a->RemoveAllChildren(); 406 layer_d->AddChild(layer_a); 407 layer_c->RemoveAllChildren(); 408 layer_d->AddChild(layer_c); 409 layer_b->RemoveAllChildren(); 410 layer_c->AddChild(layer_b); 411 412 // After another synchronize our trees should match and we should not have 413 // destroyed any LayerImpls 414 layer_impl_tree_root = 415 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 416 layer_impl_tree_root.Pass(), 417 host_->active_tree()); 418 ExpectTreesAreIdentical(layer_tree_root.get(), 419 layer_impl_tree_root.get(), 420 host_->active_tree()); 421 422 EXPECT_EQ(0u, layer_impl_destruction_list.size()); 423 } 424 425 // Constructs a very simple tree, synchronizes it, then synchronizes to a 426 // totally new tree. All layers from the old tree should be deleted. 427 TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { 428 std::vector<int> layer_impl_destruction_list; 429 430 scoped_refptr<Layer> old_layer_tree_root = 431 MockLayer::Create(&layer_impl_destruction_list); 432 old_layer_tree_root->AddChild( 433 MockLayer::Create(&layer_impl_destruction_list)); 434 old_layer_tree_root->AddChild( 435 MockLayer::Create(&layer_impl_destruction_list)); 436 437 host_->SetRootLayer(old_layer_tree_root); 438 439 int old_tree_root_layer_id = old_layer_tree_root->id(); 440 int old_tree_first_child_layer_id = old_layer_tree_root->children()[0]->id(); 441 int old_tree_second_child_layer_id = old_layer_tree_root->children()[1]->id(); 442 443 scoped_ptr<LayerImpl> layer_impl_tree_root = 444 TreeSynchronizer::SynchronizeTrees(old_layer_tree_root.get(), 445 scoped_ptr<LayerImpl>(), 446 host_->active_tree()); 447 ExpectTreesAreIdentical(old_layer_tree_root.get(), 448 layer_impl_tree_root.get(), 449 host_->active_tree()); 450 451 // We have to push properties to pick up the destruction list pointer. 452 TreeSynchronizer::PushProperties(old_layer_tree_root.get(), 453 layer_impl_tree_root.get()); 454 455 // Remove all children on the Layer side. 456 old_layer_tree_root->RemoveAllChildren(); 457 458 // Synchronize again. After the sync all LayerImpls from the old tree should 459 // be deleted. 460 scoped_refptr<Layer> new_layer_tree_root = Layer::Create(); 461 host_->SetRootLayer(new_layer_tree_root); 462 layer_impl_tree_root = 463 TreeSynchronizer::SynchronizeTrees(new_layer_tree_root.get(), 464 layer_impl_tree_root.Pass(), 465 host_->active_tree()); 466 ExpectTreesAreIdentical(new_layer_tree_root.get(), 467 layer_impl_tree_root.get(), 468 host_->active_tree()); 469 470 ASSERT_EQ(3u, layer_impl_destruction_list.size()); 471 472 EXPECT_TRUE(std::find(layer_impl_destruction_list.begin(), 473 layer_impl_destruction_list.end(), 474 old_tree_root_layer_id) != 475 layer_impl_destruction_list.end()); 476 EXPECT_TRUE(std::find(layer_impl_destruction_list.begin(), 477 layer_impl_destruction_list.end(), 478 old_tree_first_child_layer_id) != 479 layer_impl_destruction_list.end()); 480 EXPECT_TRUE(std::find(layer_impl_destruction_list.begin(), 481 layer_impl_destruction_list.end(), 482 old_tree_second_child_layer_id) != 483 layer_impl_destruction_list.end()); 484 } 485 486 // Constructs+syncs a tree with mask, replica, and replica mask layers. 487 TEST_F(TreeSynchronizerTest, SyncMaskReplicaAndReplicaMaskLayers) { 488 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 489 layer_tree_root->AddChild(Layer::Create()); 490 layer_tree_root->AddChild(Layer::Create()); 491 layer_tree_root->AddChild(Layer::Create()); 492 493 // First child gets a mask layer. 494 scoped_refptr<Layer> mask_layer = Layer::Create(); 495 layer_tree_root->children()[0]->SetMaskLayer(mask_layer.get()); 496 497 // Second child gets a replica layer. 498 scoped_refptr<Layer> replica_layer = Layer::Create(); 499 layer_tree_root->children()[1]->SetReplicaLayer(replica_layer.get()); 500 501 // Third child gets a replica layer with a mask layer. 502 scoped_refptr<Layer> replica_layer_with_mask = Layer::Create(); 503 scoped_refptr<Layer> replica_mask_layer = Layer::Create(); 504 replica_layer_with_mask->SetMaskLayer(replica_mask_layer.get()); 505 layer_tree_root->children()[2]-> 506 SetReplicaLayer(replica_layer_with_mask.get()); 507 508 host_->SetRootLayer(layer_tree_root); 509 510 scoped_ptr<LayerImpl> layer_impl_tree_root = 511 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 512 scoped_ptr<LayerImpl>(), 513 host_->active_tree()); 514 515 ExpectTreesAreIdentical(layer_tree_root.get(), 516 layer_impl_tree_root.get(), 517 host_->active_tree()); 518 519 // Remove the mask layer. 520 layer_tree_root->children()[0]->SetMaskLayer(NULL); 521 layer_impl_tree_root = 522 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 523 layer_impl_tree_root.Pass(), 524 host_->active_tree()); 525 ExpectTreesAreIdentical(layer_tree_root.get(), 526 layer_impl_tree_root.get(), 527 host_->active_tree()); 528 529 // Remove the replica layer. 530 layer_tree_root->children()[1]->SetReplicaLayer(NULL); 531 layer_impl_tree_root = 532 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 533 layer_impl_tree_root.Pass(), 534 host_->active_tree()); 535 ExpectTreesAreIdentical(layer_tree_root.get(), 536 layer_impl_tree_root.get(), 537 host_->active_tree()); 538 539 // Remove the replica mask. 540 replica_layer_with_mask->SetMaskLayer(NULL); 541 layer_impl_tree_root = 542 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 543 layer_impl_tree_root.Pass(), 544 host_->active_tree()); 545 ExpectTreesAreIdentical(layer_tree_root.get(), 546 layer_impl_tree_root.get(), 547 host_->active_tree()); 548 } 549 550 TEST_F(TreeSynchronizerTest, SynchronizeAnimations) { 551 LayerTreeSettings settings; 552 FakeProxy proxy; 553 DebugScopedSetImplThread impl(&proxy); 554 FakeRenderingStatsInstrumentation stats_instrumentation; 555 scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( 556 settings, NULL, &proxy, &stats_instrumentation, NULL, 0); 557 558 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 559 host_->SetRootLayer(layer_tree_root); 560 561 layer_tree_root->SetLayerAnimationControllerForTest( 562 FakeLayerAnimationController::Create()); 563 564 EXPECT_FALSE(static_cast<FakeLayerAnimationController*>( 565 layer_tree_root->layer_animation_controller())->SynchronizedAnimations()); 566 567 scoped_ptr<LayerImpl> layer_impl_tree_root = 568 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 569 scoped_ptr<LayerImpl>(), 570 host_->active_tree()); 571 TreeSynchronizer::PushProperties(layer_tree_root.get(), 572 layer_impl_tree_root.get()); 573 layer_impl_tree_root = 574 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 575 layer_impl_tree_root.Pass(), 576 host_->active_tree()); 577 578 EXPECT_TRUE(static_cast<FakeLayerAnimationController*>( 579 layer_tree_root->layer_animation_controller())->SynchronizedAnimations()); 580 } 581 582 TEST_F(TreeSynchronizerTest, SynchronizeScrollParent) { 583 LayerTreeSettings settings; 584 FakeProxy proxy; 585 DebugScopedSetImplThread impl(&proxy); 586 FakeRenderingStatsInstrumentation stats_instrumentation; 587 scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( 588 settings, NULL, &proxy, &stats_instrumentation, NULL, 0); 589 590 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 591 scoped_refptr<Layer> scroll_parent = Layer::Create(); 592 layer_tree_root->AddChild(scroll_parent); 593 layer_tree_root->AddChild(Layer::Create()); 594 layer_tree_root->AddChild(Layer::Create()); 595 596 host_->SetRootLayer(layer_tree_root); 597 598 // First child is the second and third child's scroll parent. 599 layer_tree_root->children()[1]->SetScrollParent(scroll_parent); 600 layer_tree_root->children()[2]->SetScrollParent(scroll_parent); 601 602 scoped_ptr<LayerImpl> layer_impl_tree_root = 603 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 604 scoped_ptr<LayerImpl>(), 605 host_impl->active_tree()); 606 TreeSynchronizer::PushProperties(layer_tree_root.get(), 607 layer_impl_tree_root.get()); 608 ExpectTreesAreIdentical(layer_tree_root.get(), 609 layer_impl_tree_root.get(), 610 host_impl->active_tree()); 611 612 // Remove the first scroll child. 613 layer_tree_root->children()[1]->RemoveFromParent(); 614 layer_impl_tree_root = 615 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 616 layer_impl_tree_root.Pass(), 617 host_impl->active_tree()); 618 TreeSynchronizer::PushProperties(layer_tree_root.get(), 619 layer_impl_tree_root.get()); 620 ExpectTreesAreIdentical(layer_tree_root.get(), 621 layer_impl_tree_root.get(), 622 host_impl->active_tree()); 623 624 // Add an additional scroll layer. 625 scoped_refptr<Layer> additional_scroll_child = Layer::Create(); 626 layer_tree_root->AddChild(additional_scroll_child); 627 additional_scroll_child->SetScrollParent(scroll_parent); 628 layer_impl_tree_root = 629 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 630 layer_impl_tree_root.Pass(), 631 host_impl->active_tree()); 632 TreeSynchronizer::PushProperties(layer_tree_root.get(), 633 layer_impl_tree_root.get()); 634 ExpectTreesAreIdentical(layer_tree_root.get(), 635 layer_impl_tree_root.get(), 636 host_impl->active_tree()); 637 638 // Remove the scroll parent. 639 scroll_parent->RemoveFromParent(); 640 scroll_parent = NULL; 641 layer_impl_tree_root = 642 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 643 layer_impl_tree_root.Pass(), 644 host_impl->active_tree()); 645 TreeSynchronizer::PushProperties(layer_tree_root.get(), 646 layer_impl_tree_root.get()); 647 ExpectTreesAreIdentical(layer_tree_root.get(), 648 layer_impl_tree_root.get(), 649 host_impl->active_tree()); 650 651 // The scroll children should have been unhooked. 652 EXPECT_EQ(2u, layer_tree_root->children().size()); 653 EXPECT_FALSE(layer_tree_root->children()[0]->scroll_parent()); 654 EXPECT_FALSE(layer_tree_root->children()[1]->scroll_parent()); 655 } 656 657 TEST_F(TreeSynchronizerTest, SynchronizeClipParent) { 658 LayerTreeSettings settings; 659 FakeProxy proxy; 660 DebugScopedSetImplThread impl(&proxy); 661 FakeRenderingStatsInstrumentation stats_instrumentation; 662 scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( 663 settings, NULL, &proxy, &stats_instrumentation, NULL, 0); 664 665 scoped_refptr<Layer> layer_tree_root = Layer::Create(); 666 scoped_refptr<Layer> clip_parent = Layer::Create(); 667 scoped_refptr<Layer> intervening = Layer::Create(); 668 scoped_refptr<Layer> clip_child1 = Layer::Create(); 669 scoped_refptr<Layer> clip_child2 = Layer::Create(); 670 layer_tree_root->AddChild(clip_parent); 671 clip_parent->AddChild(intervening); 672 intervening->AddChild(clip_child1); 673 intervening->AddChild(clip_child2); 674 675 host_->SetRootLayer(layer_tree_root); 676 677 // First child is the second and third child's scroll parent. 678 clip_child1->SetClipParent(clip_parent); 679 clip_child2->SetClipParent(clip_parent); 680 681 scoped_ptr<LayerImpl> layer_impl_tree_root = 682 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 683 scoped_ptr<LayerImpl>(), 684 host_impl->active_tree()); 685 TreeSynchronizer::PushProperties(layer_tree_root.get(), 686 layer_impl_tree_root.get()); 687 ExpectTreesAreIdentical(layer_tree_root.get(), 688 layer_impl_tree_root.get(), 689 host_impl->active_tree()); 690 691 // Remove the first clip child. 692 clip_child1->RemoveFromParent(); 693 clip_child1 = NULL; 694 695 layer_impl_tree_root = 696 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 697 layer_impl_tree_root.Pass(), 698 host_impl->active_tree()); 699 TreeSynchronizer::PushProperties(layer_tree_root.get(), 700 layer_impl_tree_root.get()); 701 ExpectTreesAreIdentical(layer_tree_root.get(), 702 layer_impl_tree_root.get(), 703 host_impl->active_tree()); 704 705 // Add an additional clip child. 706 scoped_refptr<Layer> additional_clip_child = Layer::Create(); 707 intervening->AddChild(additional_clip_child); 708 additional_clip_child->SetClipParent(clip_parent); 709 layer_impl_tree_root = 710 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 711 layer_impl_tree_root.Pass(), 712 host_impl->active_tree()); 713 TreeSynchronizer::PushProperties(layer_tree_root.get(), 714 layer_impl_tree_root.get()); 715 ExpectTreesAreIdentical(layer_tree_root.get(), 716 layer_impl_tree_root.get(), 717 host_impl->active_tree()); 718 719 // Remove the nearest clipping ancestor. 720 clip_parent->RemoveFromParent(); 721 clip_parent = NULL; 722 layer_impl_tree_root = 723 TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), 724 layer_impl_tree_root.Pass(), 725 host_impl->active_tree()); 726 TreeSynchronizer::PushProperties(layer_tree_root.get(), 727 layer_impl_tree_root.get()); 728 ExpectTreesAreIdentical(layer_tree_root.get(), 729 layer_impl_tree_root.get(), 730 host_impl->active_tree()); 731 732 // The clip children should have been unhooked. 733 EXPECT_EQ(2u, intervening->children().size()); 734 EXPECT_FALSE(clip_child2->clip_parent()); 735 EXPECT_FALSE(additional_clip_child->clip_parent()); 736 } 737 738 } // namespace 739 } // namespace cc 740