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.
5 #include "cc/tree_synchronizer.h"
10 #include "cc/layer_animation_controller.h"
11 #include "cc/layer_impl.h"
13 #include "cc/single_thread_proxy.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_impl.h"
17 #include "testing/gtest/include/gtest/gtest.h"
22 class MockLayerImpl
: public LayerImpl
{
24 static scoped_ptr
<MockLayerImpl
> create(LayerTreeImpl
* treeImpl
, int layerId
)
26 return make_scoped_ptr(new MockLayerImpl(treeImpl
, layerId
));
28 virtual ~MockLayerImpl()
30 if (m_layerImplDestructionList
)
31 m_layerImplDestructionList
->push_back(id());
34 void setLayerImplDestructionList(std::vector
<int>* list
) { m_layerImplDestructionList
= list
; }
37 MockLayerImpl(LayerTreeImpl
* treeImpl
, int layerId
)
38 : LayerImpl(treeImpl
, layerId
)
39 , m_layerImplDestructionList(0)
43 std::vector
<int>* m_layerImplDestructionList
;
46 class MockLayer
: public Layer
{
48 static scoped_refptr
<MockLayer
> create(std::vector
<int>* layerImplDestructionList
)
50 return make_scoped_refptr(new MockLayer(layerImplDestructionList
));
53 virtual scoped_ptr
<LayerImpl
> createLayerImpl(LayerTreeImpl
* treeImpl
) OVERRIDE
55 return MockLayerImpl::create(treeImpl
, m_layerId
).PassAs
<LayerImpl
>();
58 virtual void pushPropertiesTo(LayerImpl
* layerImpl
) OVERRIDE
60 Layer::pushPropertiesTo(layerImpl
);
62 MockLayerImpl
* mockLayerImpl
= static_cast<MockLayerImpl
*>(layerImpl
);
63 mockLayerImpl
->setLayerImplDestructionList(m_layerImplDestructionList
);
67 MockLayer(std::vector
<int>* layerImplDestructionList
)
69 , m_layerImplDestructionList(layerImplDestructionList
)
72 virtual ~MockLayer() { }
74 std::vector
<int>* m_layerImplDestructionList
;
77 class FakeLayerAnimationController
: public LayerAnimationController
{
79 static scoped_refptr
<LayerAnimationController
> create()
81 return static_cast<LayerAnimationController
*>(new FakeLayerAnimationController
);
84 bool synchronizedAnimations() const { return m_synchronizedAnimations
; }
87 FakeLayerAnimationController()
88 : LayerAnimationController(1)
89 , m_synchronizedAnimations(false)
92 virtual ~FakeLayerAnimationController() { }
94 virtual void pushAnimationUpdatesTo(LayerAnimationController
* controllerImpl
)
96 LayerAnimationController::pushAnimationUpdatesTo(controllerImpl
);
97 m_synchronizedAnimations
= true;
100 bool m_synchronizedAnimations
;
103 void expectTreesAreIdentical(Layer
* layer
, LayerImpl
* layerImpl
, LayerTreeImpl
* treeImpl
)
106 ASSERT_TRUE(layerImpl
);
108 EXPECT_EQ(layer
->id(), layerImpl
->id());
109 EXPECT_EQ(layerImpl
->layerTreeImpl(), treeImpl
);
111 EXPECT_EQ(layer
->nonFastScrollableRegion(), layerImpl
->nonFastScrollableRegion());
113 ASSERT_EQ(!!layer
->maskLayer(), !!layerImpl
->maskLayer());
114 if (layer
->maskLayer())
115 expectTreesAreIdentical(layer
->maskLayer(), layerImpl
->maskLayer(), treeImpl
);
117 ASSERT_EQ(!!layer
->replicaLayer(), !!layerImpl
->replicaLayer());
118 if (layer
->replicaLayer())
119 expectTreesAreIdentical(layer
->replicaLayer(), layerImpl
->replicaLayer(), treeImpl
);
121 const std::vector
<scoped_refptr
<Layer
> >& layerChildren
= layer
->children();
122 const ScopedPtrVector
<LayerImpl
>& layerImplChildren
= layerImpl
->children();
124 ASSERT_EQ(layerChildren
.size(), layerImplChildren
.size());
126 for (size_t i
= 0; i
< layerChildren
.size(); ++i
)
127 expectTreesAreIdentical(layerChildren
[i
].get(), layerImplChildren
[i
], treeImpl
);
130 class TreeSynchronizerTest
: public testing::Test
{
132 TreeSynchronizerTest()
133 : m_hostImpl(&m_proxy
)
138 FakeImplProxy m_proxy
;
139 FakeLayerTreeHostImpl m_hostImpl
;
142 // Attempts to synchronizes a null tree. This should not crash, and should
143 // return a null tree.
144 TEST_F(TreeSynchronizerTest
, syncNullTree
)
146 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(0, scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
148 EXPECT_TRUE(!layerImplTreeRoot
.get());
151 // Constructs a very simple tree and synchronizes it without trying to reuse any preexisting layers.
152 TEST_F(TreeSynchronizerTest
, syncSimpleTreeFromEmpty
)
154 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
155 layerTreeRoot
->addChild(Layer::create());
156 layerTreeRoot
->addChild(Layer::create());
158 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
160 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
163 // Constructs a very simple tree and synchronizes it attempting to reuse some layers
164 TEST_F(TreeSynchronizerTest
, syncSimpleTreeReusingLayers
)
166 std::vector
<int> layerImplDestructionList
;
168 scoped_refptr
<Layer
> layerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
169 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
170 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
172 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
173 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
175 // Add a new layer to the Layer side
176 layerTreeRoot
->children()[0]->addChild(MockLayer::create(&layerImplDestructionList
));
178 layerTreeRoot
->children()[1]->removeFromParent();
179 int secondLayerImplId
= layerImplTreeRoot
->children()[1]->id();
181 // Synchronize again. After the sync the trees should be equivalent and we should have created and destroyed one LayerImpl.
182 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
183 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
185 ASSERT_EQ(1u, layerImplDestructionList
.size());
186 EXPECT_EQ(secondLayerImplId
, layerImplDestructionList
[0]);
189 // Constructs a very simple tree and checks that a stacking-order change is tracked properly.
190 TEST_F(TreeSynchronizerTest
, syncSimpleTreeAndTrackStackingOrderChange
)
192 std::vector
<int> layerImplDestructionList
;
194 // Set up the tree and sync once. child2 needs to be synced here, too, even though we
195 // remove it to set up the intended scenario.
196 scoped_refptr
<Layer
> layerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
197 scoped_refptr
<Layer
> child2
= MockLayer::create(&layerImplDestructionList
);
198 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
199 layerTreeRoot
->addChild(child2
);
200 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
201 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
202 layerImplTreeRoot
->resetAllChangeTrackingForSubtree();
204 // re-insert the layer and sync again.
205 child2
->removeFromParent();
206 layerTreeRoot
->addChild(child2
);
207 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
208 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
210 // Check that the impl thread properly tracked the change.
211 EXPECT_FALSE(layerImplTreeRoot
->layerPropertyChanged());
212 EXPECT_FALSE(layerImplTreeRoot
->children()[0]->layerPropertyChanged());
213 EXPECT_TRUE(layerImplTreeRoot
->children()[1]->layerPropertyChanged());
216 TEST_F(TreeSynchronizerTest
, syncSimpleTreeAndProperties
)
218 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
219 layerTreeRoot
->addChild(Layer::create());
220 layerTreeRoot
->addChild(Layer::create());
222 // Pick some random properties to set. The values are not important, we're just testing that at least some properties are making it through.
223 gfx::PointF rootPosition
= gfx::PointF(2.3f
, 7.4f
);
224 layerTreeRoot
->setPosition(rootPosition
);
226 float firstChildOpacity
= 0.25f
;
227 layerTreeRoot
->children()[0]->setOpacity(firstChildOpacity
);
229 gfx::Size secondChildBounds
= gfx::Size(25, 53);
230 layerTreeRoot
->children()[1]->setBounds(secondChildBounds
);
232 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
233 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
235 // Check that the property values we set on the Layer tree are reflected in the LayerImpl tree.
236 gfx::PointF rootLayerImplPosition
= layerImplTreeRoot
->position();
237 EXPECT_EQ(rootPosition
.x(), rootLayerImplPosition
.x());
238 EXPECT_EQ(rootPosition
.y(), rootLayerImplPosition
.y());
240 EXPECT_EQ(firstChildOpacity
, layerImplTreeRoot
->children()[0]->opacity());
242 gfx::Size secondLayerImplChildBounds
= layerImplTreeRoot
->children()[1]->bounds();
243 EXPECT_EQ(secondChildBounds
.width(), secondLayerImplChildBounds
.width());
244 EXPECT_EQ(secondChildBounds
.height(), secondLayerImplChildBounds
.height());
247 TEST_F(TreeSynchronizerTest
, reuseLayerImplsAfterStructuralChange
)
249 std::vector
<int> layerImplDestructionList
;
251 // Set up a tree with this sort of structure:
252 // root --- A --- B ---+--- C
255 scoped_refptr
<Layer
> layerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
256 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
258 scoped_refptr
<Layer
> layerA
= layerTreeRoot
->children()[0].get();
259 layerA
->addChild(MockLayer::create(&layerImplDestructionList
));
261 scoped_refptr
<Layer
> layerB
= layerA
->children()[0].get();
262 layerB
->addChild(MockLayer::create(&layerImplDestructionList
));
264 scoped_refptr
<Layer
> layerC
= layerB
->children()[0].get();
265 layerB
->addChild(MockLayer::create(&layerImplDestructionList
));
266 scoped_refptr
<Layer
> layerD
= layerB
->children()[1].get();
268 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
269 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
271 // Now restructure the tree to look like this:
272 // root --- D ---+--- A
275 layerTreeRoot
->removeAllChildren();
276 layerD
->removeAllChildren();
277 layerTreeRoot
->addChild(layerD
);
278 layerA
->removeAllChildren();
279 layerD
->addChild(layerA
);
280 layerC
->removeAllChildren();
281 layerD
->addChild(layerC
);
282 layerB
->removeAllChildren();
283 layerC
->addChild(layerB
);
285 // After another synchronize our trees should match and we should not have destroyed any LayerImpls
286 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
287 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
289 EXPECT_EQ(0u, layerImplDestructionList
.size());
292 // Constructs a very simple tree, synchronizes it, then synchronizes to a totally new tree. All layers from the old tree should be deleted.
293 TEST_F(TreeSynchronizerTest
, syncSimpleTreeThenDestroy
)
295 std::vector
<int> layerImplDestructionList
;
297 scoped_refptr
<Layer
> oldLayerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
298 oldLayerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
299 oldLayerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
301 int oldTreeRootLayerId
= oldLayerTreeRoot
->id();
302 int oldTreeFirstChildLayerId
= oldLayerTreeRoot
->children()[0]->id();
303 int oldTreeSecondChildLayerId
= oldLayerTreeRoot
->children()[1]->id();
305 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(oldLayerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
306 expectTreesAreIdentical(oldLayerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
308 // Remove all children on the Layer side.
309 oldLayerTreeRoot
->removeAllChildren();
311 // Synchronize again. After the sync all LayerImpls from the old tree should be deleted.
312 scoped_refptr
<Layer
> newLayerTreeRoot
= Layer::create();
313 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(newLayerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
314 expectTreesAreIdentical(newLayerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
316 ASSERT_EQ(3u, layerImplDestructionList
.size());
318 EXPECT_TRUE(std::find(layerImplDestructionList
.begin(), layerImplDestructionList
.end(), oldTreeRootLayerId
) != layerImplDestructionList
.end());
319 EXPECT_TRUE(std::find(layerImplDestructionList
.begin(), layerImplDestructionList
.end(), oldTreeFirstChildLayerId
) != layerImplDestructionList
.end());
320 EXPECT_TRUE(std::find(layerImplDestructionList
.begin(), layerImplDestructionList
.end(), oldTreeSecondChildLayerId
) != layerImplDestructionList
.end());
323 // Constructs+syncs a tree with mask, replica, and replica mask layers.
324 TEST_F(TreeSynchronizerTest
, syncMaskReplicaAndReplicaMaskLayers
)
326 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
327 layerTreeRoot
->addChild(Layer::create());
328 layerTreeRoot
->addChild(Layer::create());
329 layerTreeRoot
->addChild(Layer::create());
331 // First child gets a mask layer.
332 scoped_refptr
<Layer
> maskLayer
= Layer::create();
333 layerTreeRoot
->children()[0]->setMaskLayer(maskLayer
.get());
335 // Second child gets a replica layer.
336 scoped_refptr
<Layer
> replicaLayer
= Layer::create();
337 layerTreeRoot
->children()[1]->setReplicaLayer(replicaLayer
.get());
339 // Third child gets a replica layer with a mask layer.
340 scoped_refptr
<Layer
> replicaLayerWithMask
= Layer::create();
341 scoped_refptr
<Layer
> replicaMaskLayer
= Layer::create();
342 replicaLayerWithMask
->setMaskLayer(replicaMaskLayer
.get());
343 layerTreeRoot
->children()[2]->setReplicaLayer(replicaLayerWithMask
.get());
345 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
347 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
349 // Remove the mask layer.
350 layerTreeRoot
->children()[0]->setMaskLayer(0);
351 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
352 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
354 // Remove the replica layer.
355 layerTreeRoot
->children()[1]->setReplicaLayer(0);
356 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
357 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
359 // Remove the replica mask.
360 replicaLayerWithMask
->setMaskLayer(0);
361 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
362 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), m_hostImpl
.activeTree());
365 TEST_F(TreeSynchronizerTest
, synchronizeAnimations
)
367 LayerTreeSettings settings
;
368 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
369 DebugScopedSetImplThread
impl(&proxy
);
370 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
372 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
374 layerTreeRoot
->setLayerAnimationController(FakeLayerAnimationController::create());
376 EXPECT_FALSE(static_cast<FakeLayerAnimationController
*>(layerTreeRoot
->layerAnimationController())->synchronizedAnimations());
378 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), m_hostImpl
.activeTree());
379 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), m_hostImpl
.activeTree());
381 EXPECT_TRUE(static_cast<FakeLayerAnimationController
*>(layerTreeRoot
->layerAnimationController())->synchronizedAnimations());