[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 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 | |
[email protected] | a8461d8 | 2012-10-16 21:11:14 | [diff] [blame] | 5 | #include "cc/tree_synchronizer.h" |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 6 | |
[email protected] | ac7c7f5 | 2012-11-08 06:26:50 | [diff] [blame] | 7 | #include <algorithm> |
| 8 | |
[email protected] | a8461d8 | 2012-10-16 21:11:14 | [diff] [blame] | 9 | #include "cc/layer.h" |
[email protected] | d50c686 | 2012-10-23 02:08:31 | [diff] [blame] | 10 | #include "cc/layer_animation_controller.h" |
| 11 | #include "cc/layer_impl.h" |
[email protected] | 55a124d0 | 2012-10-22 03:07:13 | [diff] [blame] | 12 | #include "cc/proxy.h" |
[email protected] | 4456eee2 | 2012-10-19 18:16:38 | [diff] [blame] | 13 | #include "cc/single_thread_proxy.h" |
[email protected] | 101441ce | 2012-10-16 01:45:03 | [diff] [blame] | 14 | #include "cc/test/animation_test_common.h" |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 15 | #include "cc/test/fake_impl_proxy.h" |
| 16 | #include "cc/test/fake_layer_tree_host_impl.h" |
[email protected] | 7f0c53db | 2012-10-02 00:23:18 | [diff] [blame] | 17 | #include "testing/gtest/include/gtest/gtest.h" |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 18 | |
[email protected] | ba56574 | 2012-11-10 09:29:48 | [diff] [blame] | 19 | namespace cc { |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 20 | namespace { |
| 21 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 22 | class MockLayerImpl : public LayerImpl { |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 23 | public: |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 24 | static scoped_ptr<MockLayerImpl> create(LayerTreeImpl* treeImpl, int layerId) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 25 | { |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 26 | return make_scoped_ptr(new MockLayerImpl(treeImpl, layerId)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 27 | } |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 28 | virtual ~MockLayerImpl() |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 29 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 30 | if (m_layerImplDestructionList) |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 31 | m_layerImplDestructionList->push_back(id()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 32 | } |
| 33 | |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 34 | void setLayerImplDestructionList(std::vector<int>* list) { m_layerImplDestructionList = list; } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 35 | |
| 36 | private: |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 37 | MockLayerImpl(LayerTreeImpl* treeImpl, int layerId) |
| 38 | : LayerImpl(treeImpl, layerId) |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 39 | , m_layerImplDestructionList(0) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 40 | { |
| 41 | } |
| 42 | |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 43 | std::vector<int>* m_layerImplDestructionList; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 44 | }; |
| 45 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 46 | class MockLayer : public Layer { |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 47 | public: |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 48 | static scoped_refptr<MockLayer> create(std::vector<int>* layerImplDestructionList) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 49 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 50 | return make_scoped_refptr(new MockLayer(layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 51 | } |
| 52 | |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 53 | virtual scoped_ptr<LayerImpl> createLayerImpl(LayerTreeImpl* treeImpl) OVERRIDE |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 54 | { |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 55 | return MockLayerImpl::create(treeImpl, m_layerId).PassAs<LayerImpl>(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 56 | } |
| 57 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 58 | virtual void pushPropertiesTo(LayerImpl* layerImpl) OVERRIDE |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 59 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 60 | Layer::pushPropertiesTo(layerImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 61 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 62 | MockLayerImpl* mockLayerImpl = static_cast<MockLayerImpl*>(layerImpl); |
| 63 | mockLayerImpl->setLayerImplDestructionList(m_layerImplDestructionList); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 64 | } |
[email protected] | d58499a | 2012-10-09 22:27:47 | [diff] [blame] | 65 | |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 66 | private: |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 67 | MockLayer(std::vector<int>* layerImplDestructionList) |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 68 | : Layer() |
| 69 | , m_layerImplDestructionList(layerImplDestructionList) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 70 | { |
| 71 | } |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 72 | virtual ~MockLayer() { } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 73 | |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 74 | std::vector<int>* m_layerImplDestructionList; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 75 | }; |
| 76 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 77 | class FakeLayerAnimationController : public LayerAnimationController { |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 78 | public: |
[email protected] | de4afb5e | 2012-12-20 00:11:34 | [diff] [blame] | 79 | static scoped_refptr<LayerAnimationController> create() |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 80 | { |
[email protected] | de4afb5e | 2012-12-20 00:11:34 | [diff] [blame] | 81 | return static_cast<LayerAnimationController*>(new FakeLayerAnimationController); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | bool synchronizedAnimations() const { return m_synchronizedAnimations; } |
| 85 | |
| 86 | private: |
[email protected] | de4afb5e | 2012-12-20 00:11:34 | [diff] [blame] | 87 | FakeLayerAnimationController() |
| 88 | : LayerAnimationController(1) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 89 | , m_synchronizedAnimations(false) |
[email protected] | de4afb5e | 2012-12-20 00:11:34 | [diff] [blame] | 90 | { } |
| 91 | |
| 92 | virtual ~FakeLayerAnimationController() { } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 93 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 94 | virtual void pushAnimationUpdatesTo(LayerAnimationController* controllerImpl) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 95 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 96 | LayerAnimationController::pushAnimationUpdatesTo(controllerImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 97 | m_synchronizedAnimations = true; |
| 98 | } |
| 99 | |
| 100 | bool m_synchronizedAnimations; |
| 101 | }; |
| 102 | |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 103 | void expectTreesAreIdentical(Layer* layer, LayerImpl* layerImpl, LayerTreeImpl* treeImpl) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 104 | { |
| 105 | ASSERT_TRUE(layer); |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 106 | ASSERT_TRUE(layerImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 107 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 108 | EXPECT_EQ(layer->id(), layerImpl->id()); |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 109 | EXPECT_EQ(layerImpl->layerTreeImpl(), treeImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 110 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 111 | EXPECT_EQ(layer->nonFastScrollableRegion(), layerImpl->nonFastScrollableRegion()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 112 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 113 | ASSERT_EQ(!!layer->maskLayer(), !!layerImpl->maskLayer()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 114 | if (layer->maskLayer()) |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 115 | expectTreesAreIdentical(layer->maskLayer(), layerImpl->maskLayer(), treeImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 116 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 117 | ASSERT_EQ(!!layer->replicaLayer(), !!layerImpl->replicaLayer()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 118 | if (layer->replicaLayer()) |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 119 | expectTreesAreIdentical(layer->replicaLayer(), layerImpl->replicaLayer(), treeImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 120 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 121 | const std::vector<scoped_refptr<Layer> >& layerChildren = layer->children(); |
| 122 | const ScopedPtrVector<LayerImpl>& layerImplChildren = layerImpl->children(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 123 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 124 | ASSERT_EQ(layerChildren.size(), layerImplChildren.size()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 125 | |
| 126 | for (size_t i = 0; i < layerChildren.size(); ++i) |
[email protected] | 8bef4057 | 2012-12-11 21:38:08 | [diff] [blame] | 127 | expectTreesAreIdentical(layerChildren[i].get(), layerImplChildren[i], treeImpl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 128 | } |
| 129 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 130 | class TreeSynchronizerTest : public testing::Test { |
| 131 | public: |
| 132 | TreeSynchronizerTest() |
| 133 | : m_hostImpl(&m_proxy) |
| 134 | { |
| 135 | } |
| 136 | |
| 137 | protected: |
| 138 | FakeImplProxy m_proxy; |
| 139 | FakeLayerTreeHostImpl m_hostImpl; |
| 140 | }; |
| 141 | |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 142 | // Attempts to synchronizes a null tree. This should not crash, and should |
| 143 | // return a null tree. |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 144 | TEST_F(TreeSynchronizerTest, syncNullTree) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 145 | { |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 146 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(0, scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 147 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 148 | EXPECT_TRUE(!layerImplTreeRoot.get()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | // Constructs a very simple tree and synchronizes it without trying to reuse any preexisting layers. |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 152 | TEST_F(TreeSynchronizerTest, syncSimpleTreeFromEmpty) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 153 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 154 | scoped_refptr<Layer> layerTreeRoot = Layer::create(); |
| 155 | layerTreeRoot->addChild(Layer::create()); |
| 156 | layerTreeRoot->addChild(Layer::create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 157 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 158 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 159 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 160 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | // Constructs a very simple tree and synchronizes it attempting to reuse some layers |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 164 | TEST_F(TreeSynchronizerTest, syncSimpleTreeReusingLayers) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 165 | { |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 166 | std::vector<int> layerImplDestructionList; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 167 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 168 | scoped_refptr<Layer> layerTreeRoot = MockLayer::create(&layerImplDestructionList); |
| 169 | layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList)); |
| 170 | layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 171 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 172 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
| 173 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 174 | |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 175 | // We have to push properties to pick up the destruction list pointer. |
| 176 | TreeSynchronizer::pushProperties(layerTreeRoot.get(), layerImplTreeRoot.get()); |
| 177 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 178 | // Add a new layer to the Layer side |
| 179 | layerTreeRoot->children()[0]->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 180 | // Remove one. |
| 181 | layerTreeRoot->children()[1]->removeFromParent(); |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 182 | int secondLayerImplId = layerImplTreeRoot->children()[1]->id(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 183 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 184 | // Synchronize again. After the sync the trees should be equivalent and we should have created and destroyed one LayerImpl. |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 185 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 186 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 187 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 188 | ASSERT_EQ(1u, layerImplDestructionList.size()); |
| 189 | EXPECT_EQ(secondLayerImplId, layerImplDestructionList[0]); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 190 | } |
| 191 | |
| 192 | // Constructs a very simple tree and checks that a stacking-order change is tracked properly. |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 193 | TEST_F(TreeSynchronizerTest, syncSimpleTreeAndTrackStackingOrderChange) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 194 | { |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 195 | std::vector<int> layerImplDestructionList; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 196 | |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 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. |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 199 | scoped_refptr<Layer> layerTreeRoot = MockLayer::create(&layerImplDestructionList); |
| 200 | scoped_refptr<Layer> child2 = MockLayer::create(&layerImplDestructionList); |
| 201 | layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 202 | layerTreeRoot->addChild(child2); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 203 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
| 204 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 205 | |
| 206 | // We have to push properties to pick up the destruction list pointer. |
| 207 | TreeSynchronizer::pushProperties(layerTreeRoot.get(), layerImplTreeRoot.get()); |
| 208 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 209 | layerImplTreeRoot->resetAllChangeTrackingForSubtree(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 210 | |
| 211 | // re-insert the layer and sync again. |
| 212 | child2->removeFromParent(); |
| 213 | layerTreeRoot->addChild(child2); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 214 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 215 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 216 | |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 217 | TreeSynchronizer::pushProperties(layerTreeRoot.get(), layerImplTreeRoot.get()); |
| 218 | |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 219 | // Check that the impl thread properly tracked the change. |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 220 | EXPECT_FALSE(layerImplTreeRoot->layerPropertyChanged()); |
| 221 | EXPECT_FALSE(layerImplTreeRoot->children()[0]->layerPropertyChanged()); |
| 222 | EXPECT_TRUE(layerImplTreeRoot->children()[1]->layerPropertyChanged()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 223 | } |
| 224 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 225 | TEST_F(TreeSynchronizerTest, syncSimpleTreeAndProperties) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 226 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 227 | scoped_refptr<Layer> layerTreeRoot = Layer::create(); |
| 228 | layerTreeRoot->addChild(Layer::create()); |
| 229 | layerTreeRoot->addChild(Layer::create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 230 | |
| 231 | // Pick some random properties to set. The values are not important, we're just testing that at least some properties are making it through. |
[email protected] | aad0a007 | 2012-11-01 18:15:58 | [diff] [blame] | 232 | gfx::PointF rootPosition = gfx::PointF(2.3f, 7.4f); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 233 | layerTreeRoot->setPosition(rootPosition); |
| 234 | |
| 235 | float firstChildOpacity = 0.25f; |
| 236 | layerTreeRoot->children()[0]->setOpacity(firstChildOpacity); |
| 237 | |
[email protected] | aad0a007 | 2012-11-01 18:15:58 | [diff] [blame] | 238 | gfx::Size secondChildBounds = gfx::Size(25, 53); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 239 | layerTreeRoot->children()[1]->setBounds(secondChildBounds); |
| 240 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 241 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
| 242 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 243 | |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 244 | TreeSynchronizer::pushProperties(layerTreeRoot.get(), layerImplTreeRoot.get()); |
| 245 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 246 | // Check that the property values we set on the Layer tree are reflected in the LayerImpl tree. |
[email protected] | aad0a007 | 2012-11-01 18:15:58 | [diff] [blame] | 247 | gfx::PointF rootLayerImplPosition = layerImplTreeRoot->position(); |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 248 | EXPECT_EQ(rootPosition.x(), rootLayerImplPosition.x()); |
| 249 | EXPECT_EQ(rootPosition.y(), rootLayerImplPosition.y()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 250 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 251 | EXPECT_EQ(firstChildOpacity, layerImplTreeRoot->children()[0]->opacity()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 252 | |
[email protected] | aad0a007 | 2012-11-01 18:15:58 | [diff] [blame] | 253 | gfx::Size secondLayerImplChildBounds = layerImplTreeRoot->children()[1]->bounds(); |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 254 | EXPECT_EQ(secondChildBounds.width(), secondLayerImplChildBounds.width()); |
| 255 | EXPECT_EQ(secondChildBounds.height(), secondLayerImplChildBounds.height()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 256 | } |
| 257 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 258 | TEST_F(TreeSynchronizerTest, reuseLayerImplsAfterStructuralChange) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 259 | { |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 260 | std::vector<int> layerImplDestructionList; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 261 | |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 262 | // Set up a tree with this sort of structure: |
| 263 | // root --- A --- B ---+--- C |
| 264 | // | |
| 265 | // +--- D |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 266 | scoped_refptr<Layer> layerTreeRoot = MockLayer::create(&layerImplDestructionList); |
| 267 | layerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 268 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 269 | scoped_refptr<Layer> layerA = layerTreeRoot->children()[0].get(); |
| 270 | layerA->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 271 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 272 | scoped_refptr<Layer> layerB = layerA->children()[0].get(); |
| 273 | layerB->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 274 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 275 | scoped_refptr<Layer> layerC = layerB->children()[0].get(); |
| 276 | layerB->addChild(MockLayer::create(&layerImplDestructionList)); |
| 277 | scoped_refptr<Layer> layerD = layerB->children()[1].get(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 278 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 279 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
| 280 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 281 | |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 282 | // We have to push properties to pick up the destruction list pointer. |
| 283 | TreeSynchronizer::pushProperties(layerTreeRoot.get(), layerImplTreeRoot.get()); |
| 284 | |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 285 | // Now restructure the tree to look like this: |
| 286 | // root --- D ---+--- A |
| 287 | // | |
| 288 | // +--- C --- B |
| 289 | layerTreeRoot->removeAllChildren(); |
| 290 | layerD->removeAllChildren(); |
| 291 | layerTreeRoot->addChild(layerD); |
| 292 | layerA->removeAllChildren(); |
| 293 | layerD->addChild(layerA); |
| 294 | layerC->removeAllChildren(); |
| 295 | layerD->addChild(layerC); |
| 296 | layerB->removeAllChildren(); |
| 297 | layerC->addChild(layerB); |
| 298 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 299 | // After another synchronize our trees should match and we should not have destroyed any LayerImpls |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 300 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 301 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 302 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 303 | EXPECT_EQ(0u, layerImplDestructionList.size()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 304 | } |
| 305 | |
| 306 | // Constructs a very simple tree, synchronizes it, then synchronizes to a totally new tree. All layers from the old tree should be deleted. |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 307 | TEST_F(TreeSynchronizerTest, syncSimpleTreeThenDestroy) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 308 | { |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 309 | std::vector<int> layerImplDestructionList; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 310 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 311 | scoped_refptr<Layer> oldLayerTreeRoot = MockLayer::create(&layerImplDestructionList); |
| 312 | oldLayerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList)); |
| 313 | oldLayerTreeRoot->addChild(MockLayer::create(&layerImplDestructionList)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 314 | |
| 315 | int oldTreeRootLayerId = oldLayerTreeRoot->id(); |
| 316 | int oldTreeFirstChildLayerId = oldLayerTreeRoot->children()[0]->id(); |
| 317 | int oldTreeSecondChildLayerId = oldLayerTreeRoot->children()[1]->id(); |
| 318 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 319 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(oldLayerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
| 320 | expectTreesAreIdentical(oldLayerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 321 | |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 322 | // We have to push properties to pick up the destruction list pointer. |
| 323 | TreeSynchronizer::pushProperties(oldLayerTreeRoot.get(), layerImplTreeRoot.get()); |
| 324 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 325 | // Remove all children on the Layer side. |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 326 | oldLayerTreeRoot->removeAllChildren(); |
| 327 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 328 | // Synchronize again. After the sync all LayerImpls from the old tree should be deleted. |
| 329 | scoped_refptr<Layer> newLayerTreeRoot = Layer::create(); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 330 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(newLayerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 331 | expectTreesAreIdentical(newLayerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 332 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 333 | ASSERT_EQ(3u, layerImplDestructionList.size()); |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 334 | |
| 335 | EXPECT_TRUE(std::find(layerImplDestructionList.begin(), layerImplDestructionList.end(), oldTreeRootLayerId) != layerImplDestructionList.end()); |
| 336 | EXPECT_TRUE(std::find(layerImplDestructionList.begin(), layerImplDestructionList.end(), oldTreeFirstChildLayerId) != layerImplDestructionList.end()); |
| 337 | EXPECT_TRUE(std::find(layerImplDestructionList.begin(), layerImplDestructionList.end(), oldTreeSecondChildLayerId) != layerImplDestructionList.end()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 338 | } |
| 339 | |
| 340 | // Constructs+syncs a tree with mask, replica, and replica mask layers. |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 341 | TEST_F(TreeSynchronizerTest, syncMaskReplicaAndReplicaMaskLayers) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 342 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 343 | scoped_refptr<Layer> layerTreeRoot = Layer::create(); |
| 344 | layerTreeRoot->addChild(Layer::create()); |
| 345 | layerTreeRoot->addChild(Layer::create()); |
| 346 | layerTreeRoot->addChild(Layer::create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 347 | |
| 348 | // First child gets a mask layer. |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 349 | scoped_refptr<Layer> maskLayer = Layer::create(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 350 | layerTreeRoot->children()[0]->setMaskLayer(maskLayer.get()); |
| 351 | |
| 352 | // Second child gets a replica layer. |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 353 | scoped_refptr<Layer> replicaLayer = Layer::create(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 354 | layerTreeRoot->children()[1]->setReplicaLayer(replicaLayer.get()); |
| 355 | |
| 356 | // Third child gets a replica layer with a mask layer. |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 357 | scoped_refptr<Layer> replicaLayerWithMask = Layer::create(); |
| 358 | scoped_refptr<Layer> replicaMaskLayer = Layer::create(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 359 | replicaLayerWithMask->setMaskLayer(replicaMaskLayer.get()); |
| 360 | layerTreeRoot->children()[2]->setReplicaLayer(replicaLayerWithMask.get()); |
| 361 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 362 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 363 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 364 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 365 | |
| 366 | // Remove the mask layer. |
| 367 | layerTreeRoot->children()[0]->setMaskLayer(0); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 368 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 369 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 370 | |
| 371 | // Remove the replica layer. |
| 372 | layerTreeRoot->children()[1]->setReplicaLayer(0); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 373 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 374 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 375 | |
| 376 | // Remove the replica mask. |
| 377 | replicaLayerWithMask->setMaskLayer(0); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 378 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
| 379 | expectTreesAreIdentical(layerTreeRoot.get(), layerImplTreeRoot.get(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 380 | } |
| 381 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 382 | TEST_F(TreeSynchronizerTest, synchronizeAnimations) |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 383 | { |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 384 | LayerTreeSettings settings; |
[email protected] | 61de581 | 2012-11-08 07:03:44 | [diff] [blame] | 385 | FakeProxy proxy(scoped_ptr<Thread>(NULL)); |
| 386 | DebugScopedSetImplThread impl(&proxy); |
| 387 | scoped_ptr<LayerTreeHostImpl> hostImpl = LayerTreeHostImpl::create(settings, 0, &proxy); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 388 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 389 | scoped_refptr<Layer> layerTreeRoot = Layer::create(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 390 | |
[email protected] | de4afb5e | 2012-12-20 00:11:34 | [diff] [blame] | 391 | layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 392 | |
| 393 | EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations()); |
| 394 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 395 | scoped_ptr<LayerImpl> layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), m_hostImpl.activeTree()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame^] | 396 | TreeSynchronizer::pushProperties(layerTreeRoot.get(), layerImplTreeRoot.get()); |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 397 | layerImplTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), layerImplTreeRoot.Pass(), m_hostImpl.activeTree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 398 | |
| 399 | EXPECT_TRUE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations()); |
| 400 | } |
| 401 | |
[email protected] | ba56574 | 2012-11-10 09:29:48 | [diff] [blame] | 402 | } // namespace |
| 403 | } // namespace cc |