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_proxy.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using namespace WebKitTests
;
23 class MockLayerImpl
: public LayerImpl
{
25 static scoped_ptr
<MockLayerImpl
> create(int layerId
)
27 return make_scoped_ptr(new MockLayerImpl(layerId
));
29 virtual ~MockLayerImpl()
31 if (m_layerImplDestructionList
)
32 m_layerImplDestructionList
->push_back(id());
35 void setLayerImplDestructionList(std::vector
<int>* list
) { m_layerImplDestructionList
= list
; }
38 MockLayerImpl(int layerId
)
40 , m_layerImplDestructionList(0)
44 std::vector
<int>* m_layerImplDestructionList
;
47 class MockLayer
: public Layer
{
49 static scoped_refptr
<MockLayer
> create(std::vector
<int>* layerImplDestructionList
)
51 return make_scoped_refptr(new MockLayer(layerImplDestructionList
));
54 virtual scoped_ptr
<LayerImpl
> createLayerImpl() OVERRIDE
56 return MockLayerImpl::create(m_layerId
).PassAs
<LayerImpl
>();
59 virtual void pushPropertiesTo(LayerImpl
* layerImpl
) OVERRIDE
61 Layer::pushPropertiesTo(layerImpl
);
63 MockLayerImpl
* mockLayerImpl
= static_cast<MockLayerImpl
*>(layerImpl
);
64 mockLayerImpl
->setLayerImplDestructionList(m_layerImplDestructionList
);
68 MockLayer(std::vector
<int>* layerImplDestructionList
)
70 , m_layerImplDestructionList(layerImplDestructionList
)
73 virtual ~MockLayer() { }
75 std::vector
<int>* m_layerImplDestructionList
;
78 class FakeLayerAnimationController
: public LayerAnimationController
{
80 static scoped_ptr
<FakeLayerAnimationController
> create(LayerAnimationControllerClient
* client
)
82 return make_scoped_ptr(new FakeLayerAnimationController(client
));
85 bool synchronizedAnimations() const { return m_synchronizedAnimations
; }
88 explicit FakeLayerAnimationController(LayerAnimationControllerClient
* client
)
89 : LayerAnimationController(client
)
90 , m_synchronizedAnimations(false)
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
, LayerTreeHostImpl
* hostImpl
)
106 ASSERT_TRUE(layerImpl
);
108 EXPECT_EQ(layer
->id(), layerImpl
->id());
109 EXPECT_EQ(layerImpl
->layerTreeHostImpl(), hostImpl
);
111 EXPECT_EQ(layer
->nonFastScrollableRegion(), layerImpl
->nonFastScrollableRegion());
113 ASSERT_EQ(!!layer
->maskLayer(), !!layerImpl
->maskLayer());
114 if (layer
->maskLayer())
115 expectTreesAreIdentical(layer
->maskLayer(), layerImpl
->maskLayer(), hostImpl
);
117 ASSERT_EQ(!!layer
->replicaLayer(), !!layerImpl
->replicaLayer());
118 if (layer
->replicaLayer())
119 expectTreesAreIdentical(layer
->replicaLayer(), layerImpl
->replicaLayer(), hostImpl
);
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
], hostImpl
);
130 // Attempts to synchronizes a null tree. This should not crash, and should
131 // return a null tree.
132 TEST(TreeSynchronizerTest
, syncNullTree
)
134 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(0, scoped_ptr
<LayerImpl
>(), 0);
136 EXPECT_TRUE(!layerImplTreeRoot
.get());
139 // Constructs a very simple tree and synchronizes it without trying to reuse any preexisting layers.
140 TEST(TreeSynchronizerTest
, syncSimpleTreeFromEmpty
)
142 LayerTreeSettings settings
;
143 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
144 DebugScopedSetImplThread
impl(&proxy
);
145 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
147 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
148 layerTreeRoot
->addChild(Layer::create());
149 layerTreeRoot
->addChild(Layer::create());
151 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
153 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
156 // Constructs a very simple tree and synchronizes it attempting to reuse some layers
157 TEST(TreeSynchronizerTest
, syncSimpleTreeReusingLayers
)
159 std::vector
<int> layerImplDestructionList
;
161 LayerTreeSettings settings
;
162 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
163 DebugScopedSetImplThread
impl(&proxy
);
164 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
166 scoped_refptr
<Layer
> layerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
167 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
168 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
170 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
171 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
173 // Add a new layer to the Layer side
174 layerTreeRoot
->children()[0]->addChild(MockLayer::create(&layerImplDestructionList
));
176 layerTreeRoot
->children()[1]->removeFromParent();
177 int secondLayerImplId
= layerImplTreeRoot
->children()[1]->id();
179 // Synchronize again. After the sync the trees should be equivalent and we should have created and destroyed one LayerImpl.
180 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
181 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
183 ASSERT_EQ(1u, layerImplDestructionList
.size());
184 EXPECT_EQ(secondLayerImplId
, layerImplDestructionList
[0]);
187 // Constructs a very simple tree and checks that a stacking-order change is tracked properly.
188 TEST(TreeSynchronizerTest
, syncSimpleTreeAndTrackStackingOrderChange
)
190 std::vector
<int> layerImplDestructionList
;
192 LayerTreeSettings settings
;
193 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
194 DebugScopedSetImplThread
impl(&proxy
);
195 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
197 // Set up the tree and sync once. child2 needs to be synced here, too, even though we
198 // remove it to set up the intended scenario.
199 scoped_refptr
<Layer
> layerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
200 scoped_refptr
<Layer
> child2
= MockLayer::create(&layerImplDestructionList
);
201 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
202 layerTreeRoot
->addChild(child2
);
203 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
204 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
205 layerImplTreeRoot
->resetAllChangeTrackingForSubtree();
207 // re-insert the layer and sync again.
208 child2
->removeFromParent();
209 layerTreeRoot
->addChild(child2
);
210 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
211 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
213 // Check that the impl thread properly tracked the change.
214 EXPECT_FALSE(layerImplTreeRoot
->layerPropertyChanged());
215 EXPECT_FALSE(layerImplTreeRoot
->children()[0]->layerPropertyChanged());
216 EXPECT_TRUE(layerImplTreeRoot
->children()[1]->layerPropertyChanged());
219 TEST(TreeSynchronizerTest
, syncSimpleTreeAndProperties
)
221 LayerTreeSettings settings
;
222 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
223 DebugScopedSetImplThread
impl(&proxy
);
224 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
226 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
227 layerTreeRoot
->addChild(Layer::create());
228 layerTreeRoot
->addChild(Layer::create());
230 // Pick some random properties to set. The values are not important, we're just testing that at least some properties are making it through.
231 gfx::PointF rootPosition
= gfx::PointF(2.3f
, 7.4f
);
232 layerTreeRoot
->setPosition(rootPosition
);
234 float firstChildOpacity
= 0.25f
;
235 layerTreeRoot
->children()[0]->setOpacity(firstChildOpacity
);
237 gfx::Size secondChildBounds
= gfx::Size(25, 53);
238 layerTreeRoot
->children()[1]->setBounds(secondChildBounds
);
240 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
241 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
243 // Check that the property values we set on the Layer tree are reflected in the LayerImpl tree.
244 gfx::PointF rootLayerImplPosition
= layerImplTreeRoot
->position();
245 EXPECT_EQ(rootPosition
.x(), rootLayerImplPosition
.x());
246 EXPECT_EQ(rootPosition
.y(), rootLayerImplPosition
.y());
248 EXPECT_EQ(firstChildOpacity
, layerImplTreeRoot
->children()[0]->opacity());
250 gfx::Size secondLayerImplChildBounds
= layerImplTreeRoot
->children()[1]->bounds();
251 EXPECT_EQ(secondChildBounds
.width(), secondLayerImplChildBounds
.width());
252 EXPECT_EQ(secondChildBounds
.height(), secondLayerImplChildBounds
.height());
255 TEST(TreeSynchronizerTest
, reuseLayerImplsAfterStructuralChange
)
257 std::vector
<int> layerImplDestructionList
;
259 LayerTreeSettings settings
;
260 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
261 DebugScopedSetImplThread
impl(&proxy
);
262 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
264 // Set up a tree with this sort of structure:
265 // root --- A --- B ---+--- C
268 scoped_refptr
<Layer
> layerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
269 layerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
271 scoped_refptr
<Layer
> layerA
= layerTreeRoot
->children()[0].get();
272 layerA
->addChild(MockLayer::create(&layerImplDestructionList
));
274 scoped_refptr
<Layer
> layerB
= layerA
->children()[0].get();
275 layerB
->addChild(MockLayer::create(&layerImplDestructionList
));
277 scoped_refptr
<Layer
> layerC
= layerB
->children()[0].get();
278 layerB
->addChild(MockLayer::create(&layerImplDestructionList
));
279 scoped_refptr
<Layer
> layerD
= layerB
->children()[1].get();
281 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
282 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
284 // Now restructure the tree to look like this:
285 // root --- D ---+--- A
288 layerTreeRoot
->removeAllChildren();
289 layerD
->removeAllChildren();
290 layerTreeRoot
->addChild(layerD
);
291 layerA
->removeAllChildren();
292 layerD
->addChild(layerA
);
293 layerC
->removeAllChildren();
294 layerD
->addChild(layerC
);
295 layerB
->removeAllChildren();
296 layerC
->addChild(layerB
);
298 // After another synchronize our trees should match and we should not have destroyed any LayerImpls
299 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
300 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
302 EXPECT_EQ(0u, layerImplDestructionList
.size());
305 // Constructs a very simple tree, synchronizes it, then synchronizes to a totally new tree. All layers from the old tree should be deleted.
306 TEST(TreeSynchronizerTest
, syncSimpleTreeThenDestroy
)
308 std::vector
<int> layerImplDestructionList
;
310 LayerTreeSettings settings
;
311 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
312 DebugScopedSetImplThread
impl(&proxy
);
313 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
315 scoped_refptr
<Layer
> oldLayerTreeRoot
= MockLayer::create(&layerImplDestructionList
);
316 oldLayerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
317 oldLayerTreeRoot
->addChild(MockLayer::create(&layerImplDestructionList
));
319 int oldTreeRootLayerId
= oldLayerTreeRoot
->id();
320 int oldTreeFirstChildLayerId
= oldLayerTreeRoot
->children()[0]->id();
321 int oldTreeSecondChildLayerId
= oldLayerTreeRoot
->children()[1]->id();
323 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(oldLayerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
324 expectTreesAreIdentical(oldLayerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
326 // Remove all children on the Layer side.
327 oldLayerTreeRoot
->removeAllChildren();
329 // Synchronize again. After the sync all LayerImpls from the old tree should be deleted.
330 scoped_refptr
<Layer
> newLayerTreeRoot
= Layer::create();
331 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(newLayerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
332 expectTreesAreIdentical(newLayerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
334 ASSERT_EQ(3u, layerImplDestructionList
.size());
336 EXPECT_TRUE(std::find(layerImplDestructionList
.begin(), layerImplDestructionList
.end(), oldTreeRootLayerId
) != layerImplDestructionList
.end());
337 EXPECT_TRUE(std::find(layerImplDestructionList
.begin(), layerImplDestructionList
.end(), oldTreeFirstChildLayerId
) != layerImplDestructionList
.end());
338 EXPECT_TRUE(std::find(layerImplDestructionList
.begin(), layerImplDestructionList
.end(), oldTreeSecondChildLayerId
) != layerImplDestructionList
.end());
341 // Constructs+syncs a tree with mask, replica, and replica mask layers.
342 TEST(TreeSynchronizerTest
, syncMaskReplicaAndReplicaMaskLayers
)
344 LayerTreeSettings settings
;
345 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
346 DebugScopedSetImplThread
impl(&proxy
);
347 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
349 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
350 layerTreeRoot
->addChild(Layer::create());
351 layerTreeRoot
->addChild(Layer::create());
352 layerTreeRoot
->addChild(Layer::create());
354 // First child gets a mask layer.
355 scoped_refptr
<Layer
> maskLayer
= Layer::create();
356 layerTreeRoot
->children()[0]->setMaskLayer(maskLayer
.get());
358 // Second child gets a replica layer.
359 scoped_refptr
<Layer
> replicaLayer
= Layer::create();
360 layerTreeRoot
->children()[1]->setReplicaLayer(replicaLayer
.get());
362 // Third child gets a replica layer with a mask layer.
363 scoped_refptr
<Layer
> replicaLayerWithMask
= Layer::create();
364 scoped_refptr
<Layer
> replicaMaskLayer
= Layer::create();
365 replicaLayerWithMask
->setMaskLayer(replicaMaskLayer
.get());
366 layerTreeRoot
->children()[2]->setReplicaLayer(replicaLayerWithMask
.get());
368 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
370 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
372 // Remove the mask layer.
373 layerTreeRoot
->children()[0]->setMaskLayer(0);
374 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
375 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
377 // Remove the replica layer.
378 layerTreeRoot
->children()[1]->setReplicaLayer(0);
379 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
380 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
382 // Remove the replica mask.
383 replicaLayerWithMask
->setMaskLayer(0);
384 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
385 expectTreesAreIdentical(layerTreeRoot
.get(), layerImplTreeRoot
.get(), hostImpl
.get());
388 TEST(TreeSynchronizerTest
, synchronizeAnimations
)
390 LayerTreeSettings settings
;
391 FakeProxy
proxy(scoped_ptr
<Thread
>(NULL
));
392 DebugScopedSetImplThread
impl(&proxy
);
393 scoped_ptr
<LayerTreeHostImpl
> hostImpl
= LayerTreeHostImpl::create(settings
, 0, &proxy
);
395 scoped_refptr
<Layer
> layerTreeRoot
= Layer::create();
397 FakeLayerAnimationControllerClient dummy
;
398 layerTreeRoot
->setLayerAnimationController(FakeLayerAnimationController::create(&dummy
).PassAs
<LayerAnimationController
>());
400 EXPECT_FALSE(static_cast<FakeLayerAnimationController
*>(layerTreeRoot
->layerAnimationController())->synchronizedAnimations());
402 scoped_ptr
<LayerImpl
> layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), scoped_ptr
<LayerImpl
>(), hostImpl
.get());
403 layerImplTreeRoot
= TreeSynchronizer::synchronizeTrees(layerTreeRoot
.get(), layerImplTreeRoot
.Pass(), hostImpl
.get());
405 EXPECT_TRUE(static_cast<FakeLayerAnimationController
*>(layerTreeRoot
->layerAnimationController())->synchronizedAnimations());