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