[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] | 556fd29 | 2013-03-18 08:03:04 | [diff] [blame] | 5 | #include "cc/trees/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> |
[email protected] | bf691c2 | 2013-03-26 21:15:06 | [diff] [blame] | 8 | #include <vector> |
[email protected] | ac7c7f5 | 2012-11-08 06:26:50 | [diff] [blame] | 9 | |
[email protected] | 95e4e1a0 | 2013-03-18 07:09:09 | [diff] [blame] | 10 | #include "cc/animation/layer_animation_controller.h" |
[email protected] | cc3cfaa | 2013-03-18 09:05:52 | [diff] [blame] | 11 | #include "cc/layers/layer.h" |
| 12 | #include "cc/layers/layer_impl.h" |
[email protected] | 101441ce | 2012-10-16 01:45:03 | [diff] [blame] | 13 | #include "cc/test/animation_test_common.h" |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 14 | #include "cc/test/fake_impl_proxy.h" |
| 15 | #include "cc/test/fake_layer_tree_host_impl.h" |
[email protected] | 556fd29 | 2013-03-18 08:03:04 | [diff] [blame] | 16 | #include "cc/trees/proxy.h" |
| 17 | #include "cc/trees/single_thread_proxy.h" |
[email protected] | 7f0c53db | 2012-10-02 00:23:18 | [diff] [blame] | 18 | #include "testing/gtest/include/gtest/gtest.h" |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 19 | |
[email protected] | ba56574 | 2012-11-10 09:29:48 | [diff] [blame] | 20 | namespace cc { |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 21 | namespace { |
| 22 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 23 | class MockLayerImpl : public LayerImpl { |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 24 | public: |
| 25 | static scoped_ptr<MockLayerImpl> Create(LayerTreeImpl* tree_impl, |
| 26 | int layer_id) { |
| 27 | return make_scoped_ptr(new MockLayerImpl(tree_impl, layer_id)); |
| 28 | } |
| 29 | virtual ~MockLayerImpl() { |
| 30 | if (layer_impl_destruction_list_) |
| 31 | layer_impl_destruction_list_->push_back(id()); |
| 32 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 33 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 34 | void SetLayerImplDestructionList(std::vector<int>* list) { |
| 35 | layer_impl_destruction_list_ = list; |
| 36 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 37 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 38 | private: |
| 39 | MockLayerImpl(LayerTreeImpl* tree_impl, int layer_id) |
| 40 | : LayerImpl(tree_impl, layer_id), |
| 41 | layer_impl_destruction_list_(NULL) {} |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 42 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 43 | std::vector<int>* layer_impl_destruction_list_; |
[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] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 47 | public: |
| 48 | static scoped_refptr<MockLayer> Create( |
| 49 | std::vector<int>* layer_impl_destruction_list) { |
| 50 | return make_scoped_refptr(new MockLayer(layer_impl_destruction_list)); |
| 51 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 52 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 53 | virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) |
| 54 | OVERRIDE { |
| 55 | return MockLayerImpl::Create(tree_impl, layer_id_).PassAs<LayerImpl>(); |
| 56 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 57 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 58 | virtual void PushPropertiesTo(LayerImpl* layer_impl) OVERRIDE { |
| 59 | Layer::PushPropertiesTo(layer_impl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 60 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 61 | MockLayerImpl* mock_layer_impl = static_cast<MockLayerImpl*>(layer_impl); |
| 62 | mock_layer_impl->SetLayerImplDestructionList(layer_impl_destruction_list_); |
| 63 | } |
[email protected] | d58499a | 2012-10-09 22:27:47 | [diff] [blame] | 64 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 65 | private: |
[email protected] | bf691c2 | 2013-03-26 21:15:06 | [diff] [blame] | 66 | explicit MockLayer(std::vector<int>* layer_impl_destruction_list) |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 67 | : Layer(), layer_impl_destruction_list_(layer_impl_destruction_list) {} |
| 68 | virtual ~MockLayer() {} |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 69 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 70 | std::vector<int>* layer_impl_destruction_list_; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 71 | }; |
| 72 | |
[email protected] | 96baf3e | 2012-10-22 23:09:55 | [diff] [blame] | 73 | class FakeLayerAnimationController : public LayerAnimationController { |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 74 | public: |
| 75 | static scoped_refptr<LayerAnimationController> Create() { |
| 76 | return static_cast<LayerAnimationController*>( |
| 77 | new FakeLayerAnimationController); |
| 78 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 79 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 80 | bool SynchronizedAnimations() const { return synchronized_animations_; } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 81 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 82 | private: |
| 83 | FakeLayerAnimationController() |
| 84 | : LayerAnimationController(1), |
| 85 | synchronized_animations_(false) {} |
[email protected] | de4afb5e | 2012-12-20 00:11:34 | [diff] [blame] | 86 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 87 | virtual ~FakeLayerAnimationController() {} |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 88 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 89 | virtual void PushAnimationUpdatesTo(LayerAnimationController* controller_impl) |
| 90 | OVERRIDE { |
| 91 | LayerAnimationController::PushAnimationUpdatesTo(controller_impl); |
| 92 | synchronized_animations_ = true; |
| 93 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 94 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 95 | bool synchronized_animations_; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 96 | }; |
| 97 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 98 | void ExpectTreesAreIdentical(Layer* layer, |
| 99 | LayerImpl* layer_impl, |
| 100 | LayerTreeImpl* tree_impl) { |
| 101 | ASSERT_TRUE(layer); |
| 102 | ASSERT_TRUE(layer_impl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 103 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 104 | EXPECT_EQ(layer->id(), layer_impl->id()); |
| 105 | EXPECT_EQ(layer_impl->layer_tree_impl(), tree_impl); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 106 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 107 | EXPECT_EQ(layer->non_fast_scrollable_region(), |
| 108 | layer_impl->non_fast_scrollable_region()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 109 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 110 | ASSERT_EQ(!!layer->mask_layer(), !!layer_impl->mask_layer()); |
| 111 | if (layer->mask_layer()) { |
| 112 | ExpectTreesAreIdentical( |
| 113 | layer->mask_layer(), layer_impl->mask_layer(), tree_impl); |
| 114 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 115 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 116 | ASSERT_EQ(!!layer->replica_layer(), !!layer_impl->replica_layer()); |
| 117 | if (layer->replica_layer()) { |
| 118 | ExpectTreesAreIdentical( |
| 119 | layer->replica_layer(), layer_impl->replica_layer(), tree_impl); |
| 120 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 121 | |
[email protected] | 50761e9 | 2013-03-29 20:51:28 | [diff] [blame] | 122 | const LayerList& layer_children = layer->children(); |
| 123 | const OwnedLayerImplList& layer_impl_children = layer_impl->children(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 124 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 125 | ASSERT_EQ(layer_children.size(), layer_impl_children.size()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 126 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 127 | for (size_t i = 0; i < layer_children.size(); ++i) { |
| 128 | ExpectTreesAreIdentical( |
| 129 | layer_children[i].get(), layer_impl_children[i], tree_impl); |
| 130 | } |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 131 | } |
| 132 | |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 133 | class TreeSynchronizerTest : public testing::Test { |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 134 | public: |
| 135 | TreeSynchronizerTest() : host_impl_(&proxy_) {} |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 136 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 137 | protected: |
| 138 | FakeImplProxy proxy_; |
| 139 | FakeLayerTreeHostImpl host_impl_; |
[email protected] | c228238 | 2012-12-16 00:46:03 | [diff] [blame] | 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] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 144 | TEST_F(TreeSynchronizerTest, SyncNullTree) { |
| 145 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 146 | TreeSynchronizer::SynchronizeTrees(static_cast<Layer*>(NULL), |
| 147 | scoped_ptr<LayerImpl>(), |
| 148 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 149 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 150 | EXPECT_TRUE(!layer_impl_tree_root.get()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 151 | } |
| 152 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 153 | // Constructs a very simple tree and synchronizes it without trying to reuse any |
| 154 | // preexisting layers. |
| 155 | TEST_F(TreeSynchronizerTest, SyncSimpleTreeFromEmpty) { |
| 156 | scoped_refptr<Layer> layer_tree_root = Layer::Create(); |
| 157 | layer_tree_root->AddChild(Layer::Create()); |
| 158 | layer_tree_root->AddChild(Layer::Create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 159 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 160 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 161 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 162 | scoped_ptr<LayerImpl>(), |
| 163 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 164 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 165 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 166 | layer_impl_tree_root.get(), |
| 167 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 168 | } |
| 169 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 170 | // Constructs a very simple tree and synchronizes it attempting to reuse some |
| 171 | // layers |
| 172 | TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { |
| 173 | std::vector<int> layer_impl_destruction_list; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 174 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 175 | scoped_refptr<Layer> layer_tree_root = |
| 176 | MockLayer::Create(&layer_impl_destruction_list); |
| 177 | layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
| 178 | layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 179 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 180 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 181 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 182 | scoped_ptr<LayerImpl>(), |
| 183 | host_impl_.active_tree()); |
| 184 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 185 | layer_impl_tree_root.get(), |
| 186 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 187 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 188 | // We have to push properties to pick up the destruction list pointer. |
| 189 | TreeSynchronizer::PushProperties(layer_tree_root.get(), |
| 190 | layer_impl_tree_root.get()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 191 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 192 | // Add a new layer to the Layer side |
| 193 | layer_tree_root->children()[0]-> |
| 194 | AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
| 195 | // Remove one. |
| 196 | layer_tree_root->children()[1]->RemoveFromParent(); |
| 197 | int second_layer_impl_id = layer_impl_tree_root->children()[1]->id(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 198 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 199 | // Synchronize again. After the sync the trees should be equivalent and we |
| 200 | // should have created and destroyed one LayerImpl. |
| 201 | layer_impl_tree_root = |
| 202 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 203 | layer_impl_tree_root.Pass(), |
| 204 | host_impl_.active_tree()); |
| 205 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 206 | layer_impl_tree_root.get(), |
| 207 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 208 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 209 | ASSERT_EQ(1u, layer_impl_destruction_list.size()); |
| 210 | EXPECT_EQ(second_layer_impl_id, layer_impl_destruction_list[0]); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 211 | } |
| 212 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 213 | // Constructs a very simple tree and checks that a stacking-order change is |
| 214 | // tracked properly. |
| 215 | TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndTrackStackingOrderChange) { |
| 216 | std::vector<int> layer_impl_destruction_list; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 217 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 218 | // Set up the tree and sync once. child2 needs to be synced here, too, even |
| 219 | // though we remove it to set up the intended scenario. |
| 220 | scoped_refptr<Layer> layer_tree_root = |
| 221 | MockLayer::Create(&layer_impl_destruction_list); |
| 222 | scoped_refptr<Layer> child2 = MockLayer::Create(&layer_impl_destruction_list); |
| 223 | layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
| 224 | layer_tree_root->AddChild(child2); |
| 225 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 226 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 227 | scoped_ptr<LayerImpl>(), |
| 228 | host_impl_.active_tree()); |
| 229 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 230 | layer_impl_tree_root.get(), |
| 231 | host_impl_.active_tree()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 232 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 233 | // We have to push properties to pick up the destruction list pointer. |
| 234 | TreeSynchronizer::PushProperties(layer_tree_root.get(), |
| 235 | layer_impl_tree_root.get()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 236 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 237 | layer_impl_tree_root->ResetAllChangeTrackingForSubtree(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 238 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 239 | // re-insert the layer and sync again. |
| 240 | child2->RemoveFromParent(); |
| 241 | layer_tree_root->AddChild(child2); |
| 242 | layer_impl_tree_root = |
| 243 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 244 | layer_impl_tree_root.Pass(), |
| 245 | host_impl_.active_tree()); |
| 246 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 247 | layer_impl_tree_root.get(), |
| 248 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 249 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 250 | TreeSynchronizer::PushProperties(layer_tree_root.get(), |
| 251 | layer_impl_tree_root.get()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 252 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 253 | // Check that the impl thread properly tracked the change. |
| 254 | EXPECT_FALSE(layer_impl_tree_root->LayerPropertyChanged()); |
| 255 | EXPECT_FALSE(layer_impl_tree_root->children()[0]->LayerPropertyChanged()); |
| 256 | EXPECT_TRUE(layer_impl_tree_root->children()[1]->LayerPropertyChanged()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 257 | } |
| 258 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 259 | TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndProperties) { |
| 260 | scoped_refptr<Layer> layer_tree_root = Layer::Create(); |
| 261 | layer_tree_root->AddChild(Layer::Create()); |
| 262 | layer_tree_root->AddChild(Layer::Create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 263 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 264 | // Pick some random properties to set. The values are not important, we're |
| 265 | // just testing that at least some properties are making it through. |
| 266 | gfx::PointF root_position = gfx::PointF(2.3f, 7.4f); |
| 267 | layer_tree_root->SetPosition(root_position); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 268 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 269 | float first_child_opacity = 0.25f; |
| 270 | layer_tree_root->children()[0]->SetOpacity(first_child_opacity); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 271 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 272 | gfx::Size second_child_bounds = gfx::Size(25, 53); |
| 273 | layer_tree_root->children()[1]->SetBounds(second_child_bounds); |
[email protected] | 445881f | 2013-04-16 01:11:59 | [diff] [blame^] | 274 | layer_tree_root->children()[1]->SavePaintProperties(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 275 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 276 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 277 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 278 | scoped_ptr<LayerImpl>(), |
| 279 | host_impl_.active_tree()); |
| 280 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 281 | layer_impl_tree_root.get(), |
| 282 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 283 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 284 | TreeSynchronizer::PushProperties(layer_tree_root.get(), |
| 285 | layer_impl_tree_root.get()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 286 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 287 | // Check that the property values we set on the Layer tree are reflected in |
| 288 | // the LayerImpl tree. |
| 289 | gfx::PointF root_layer_impl_position = layer_impl_tree_root->position(); |
| 290 | EXPECT_EQ(root_position.x(), root_layer_impl_position.x()); |
| 291 | EXPECT_EQ(root_position.y(), root_layer_impl_position.y()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 292 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 293 | EXPECT_EQ(first_child_opacity, |
| 294 | layer_impl_tree_root->children()[0]->opacity()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 295 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 296 | gfx::Size second_layer_impl_child_bounds = |
| 297 | layer_impl_tree_root->children()[1]->bounds(); |
| 298 | EXPECT_EQ(second_child_bounds.width(), |
| 299 | second_layer_impl_child_bounds.width()); |
| 300 | EXPECT_EQ(second_child_bounds.height(), |
| 301 | second_layer_impl_child_bounds.height()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 302 | } |
| 303 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 304 | TEST_F(TreeSynchronizerTest, ReuseLayerImplsAfterStructuralChange) { |
| 305 | std::vector<int> layer_impl_destruction_list; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 306 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 307 | // Set up a tree with this sort of structure: |
| 308 | // root --- A --- B ---+--- C |
| 309 | // | |
| 310 | // +--- D |
| 311 | scoped_refptr<Layer> layer_tree_root = |
| 312 | MockLayer::Create(&layer_impl_destruction_list); |
| 313 | layer_tree_root->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 314 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 315 | scoped_refptr<Layer> layer_a = layer_tree_root->children()[0].get(); |
| 316 | layer_a->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 317 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 318 | scoped_refptr<Layer> layer_b = layer_a->children()[0].get(); |
| 319 | layer_b->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 320 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 321 | scoped_refptr<Layer> layer_c = layer_b->children()[0].get(); |
| 322 | layer_b->AddChild(MockLayer::Create(&layer_impl_destruction_list)); |
| 323 | scoped_refptr<Layer> layer_d = layer_b->children()[1].get(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 324 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 325 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 326 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 327 | scoped_ptr<LayerImpl>(), |
| 328 | host_impl_.active_tree()); |
| 329 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 330 | layer_impl_tree_root.get(), |
| 331 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 332 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 333 | // We have to push properties to pick up the destruction list pointer. |
| 334 | TreeSynchronizer::PushProperties(layer_tree_root.get(), |
| 335 | layer_impl_tree_root.get()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 336 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 337 | // Now restructure the tree to look like this: |
| 338 | // root --- D ---+--- A |
| 339 | // | |
| 340 | // +--- C --- B |
| 341 | layer_tree_root->RemoveAllChildren(); |
| 342 | layer_d->RemoveAllChildren(); |
| 343 | layer_tree_root->AddChild(layer_d); |
| 344 | layer_a->RemoveAllChildren(); |
| 345 | layer_d->AddChild(layer_a); |
| 346 | layer_c->RemoveAllChildren(); |
| 347 | layer_d->AddChild(layer_c); |
| 348 | layer_b->RemoveAllChildren(); |
| 349 | layer_c->AddChild(layer_b); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 350 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 351 | // After another synchronize our trees should match and we should not have |
| 352 | // destroyed any LayerImpls |
| 353 | layer_impl_tree_root = |
| 354 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 355 | layer_impl_tree_root.Pass(), |
| 356 | host_impl_.active_tree()); |
| 357 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 358 | layer_impl_tree_root.get(), |
| 359 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 360 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 361 | EXPECT_EQ(0u, layer_impl_destruction_list.size()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 362 | } |
| 363 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 364 | // Constructs a very simple tree, synchronizes it, then synchronizes to a |
| 365 | // totally new tree. All layers from the old tree should be deleted. |
| 366 | TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { |
| 367 | std::vector<int> layer_impl_destruction_list; |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 368 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 369 | scoped_refptr<Layer> old_layer_tree_root = |
| 370 | MockLayer::Create(&layer_impl_destruction_list); |
| 371 | old_layer_tree_root->AddChild( |
| 372 | MockLayer::Create(&layer_impl_destruction_list)); |
| 373 | old_layer_tree_root->AddChild( |
| 374 | MockLayer::Create(&layer_impl_destruction_list)); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 375 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 376 | int old_tree_root_layer_id = old_layer_tree_root->id(); |
| 377 | int old_tree_first_child_layer_id = old_layer_tree_root->children()[0]->id(); |
| 378 | int old_tree_second_child_layer_id = old_layer_tree_root->children()[1]->id(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 379 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 380 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 381 | TreeSynchronizer::SynchronizeTrees(old_layer_tree_root.get(), |
| 382 | scoped_ptr<LayerImpl>(), |
| 383 | host_impl_.active_tree()); |
| 384 | ExpectTreesAreIdentical(old_layer_tree_root.get(), |
| 385 | layer_impl_tree_root.get(), |
| 386 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 387 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 388 | // We have to push properties to pick up the destruction list pointer. |
| 389 | TreeSynchronizer::PushProperties(old_layer_tree_root.get(), |
| 390 | layer_impl_tree_root.get()); |
[email protected] | 5c4824e1 | 2013-01-12 16:34:53 | [diff] [blame] | 391 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 392 | // Remove all children on the Layer side. |
| 393 | old_layer_tree_root->RemoveAllChildren(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 394 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 395 | // Synchronize again. After the sync all LayerImpls from the old tree should |
| 396 | // be deleted. |
| 397 | scoped_refptr<Layer> new_layer_tree_root = Layer::Create(); |
| 398 | layer_impl_tree_root = |
| 399 | TreeSynchronizer::SynchronizeTrees(new_layer_tree_root.get(), |
| 400 | layer_impl_tree_root.Pass(), |
| 401 | host_impl_.active_tree()); |
| 402 | ExpectTreesAreIdentical(new_layer_tree_root.get(), |
| 403 | layer_impl_tree_root.get(), |
| 404 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 405 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 406 | ASSERT_EQ(3u, layer_impl_destruction_list.size()); |
[email protected] | 2cdbdba | 2012-10-28 13:15:05 | [diff] [blame] | 407 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 408 | EXPECT_TRUE(std::find(layer_impl_destruction_list.begin(), |
| 409 | layer_impl_destruction_list.end(), |
| 410 | old_tree_root_layer_id) != |
| 411 | layer_impl_destruction_list.end()); |
| 412 | EXPECT_TRUE(std::find(layer_impl_destruction_list.begin(), |
| 413 | layer_impl_destruction_list.end(), |
| 414 | old_tree_first_child_layer_id) != |
| 415 | layer_impl_destruction_list.end()); |
| 416 | EXPECT_TRUE(std::find(layer_impl_destruction_list.begin(), |
| 417 | layer_impl_destruction_list.end(), |
| 418 | old_tree_second_child_layer_id) != |
| 419 | layer_impl_destruction_list.end()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 420 | } |
| 421 | |
| 422 | // Constructs+syncs a tree with mask, replica, and replica mask layers. |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 423 | TEST_F(TreeSynchronizerTest, SyncMaskReplicaAndReplicaMaskLayers) { |
| 424 | scoped_refptr<Layer> layer_tree_root = Layer::Create(); |
| 425 | layer_tree_root->AddChild(Layer::Create()); |
| 426 | layer_tree_root->AddChild(Layer::Create()); |
| 427 | layer_tree_root->AddChild(Layer::Create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 428 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 429 | // First child gets a mask layer. |
| 430 | scoped_refptr<Layer> mask_layer = Layer::Create(); |
| 431 | layer_tree_root->children()[0]->SetMaskLayer(mask_layer.get()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 432 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 433 | // Second child gets a replica layer. |
| 434 | scoped_refptr<Layer> replica_layer = Layer::Create(); |
| 435 | layer_tree_root->children()[1]->SetReplicaLayer(replica_layer.get()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 436 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 437 | // Third child gets a replica layer with a mask layer. |
| 438 | scoped_refptr<Layer> replica_layer_with_mask = Layer::Create(); |
| 439 | scoped_refptr<Layer> replica_mask_layer = Layer::Create(); |
| 440 | replica_layer_with_mask->SetMaskLayer(replica_mask_layer.get()); |
| 441 | layer_tree_root->children()[2]-> |
| 442 | SetReplicaLayer(replica_layer_with_mask.get()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 443 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 444 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 445 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 446 | scoped_ptr<LayerImpl>(), |
| 447 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 448 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 449 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 450 | layer_impl_tree_root.get(), |
| 451 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 452 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 453 | // Remove the mask layer. |
| 454 | layer_tree_root->children()[0]->SetMaskLayer(NULL); |
| 455 | layer_impl_tree_root = |
| 456 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 457 | layer_impl_tree_root.Pass(), |
| 458 | host_impl_.active_tree()); |
| 459 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 460 | layer_impl_tree_root.get(), |
| 461 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 462 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 463 | // Remove the replica layer. |
| 464 | layer_tree_root->children()[1]->SetReplicaLayer(NULL); |
| 465 | layer_impl_tree_root = |
| 466 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 467 | layer_impl_tree_root.Pass(), |
| 468 | host_impl_.active_tree()); |
| 469 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 470 | layer_impl_tree_root.get(), |
| 471 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 472 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 473 | // Remove the replica mask. |
| 474 | replica_layer_with_mask->SetMaskLayer(NULL); |
| 475 | layer_impl_tree_root = |
| 476 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 477 | layer_impl_tree_root.Pass(), |
| 478 | host_impl_.active_tree()); |
| 479 | ExpectTreesAreIdentical(layer_tree_root.get(), |
| 480 | layer_impl_tree_root.get(), |
| 481 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 482 | } |
| 483 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 484 | TEST_F(TreeSynchronizerTest, SynchronizeAnimations) { |
| 485 | LayerTreeSettings settings; |
| 486 | FakeProxy proxy(scoped_ptr<Thread>(NULL)); |
| 487 | DebugScopedSetImplThread impl(&proxy); |
[email protected] | 372bad5f | 2013-03-21 16:38:43 | [diff] [blame] | 488 | FakeRenderingStatsInstrumentation stats_instrumentation; |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 489 | scoped_ptr<LayerTreeHostImpl> host_impl = |
[email protected] | 372bad5f | 2013-03-21 16:38:43 | [diff] [blame] | 490 | LayerTreeHostImpl::Create(settings, |
| 491 | NULL, |
| 492 | &proxy, |
| 493 | &stats_instrumentation); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 494 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 495 | scoped_refptr<Layer> layer_tree_root = Layer::Create(); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 496 | |
[email protected] | 7f5605c | 2013-04-08 18:08:35 | [diff] [blame] | 497 | layer_tree_root->SetLayerAnimationControllerForTest( |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 498 | FakeLayerAnimationController::Create()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 499 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 500 | EXPECT_FALSE(static_cast<FakeLayerAnimationController*>( |
| 501 | layer_tree_root->layer_animation_controller())->SynchronizedAnimations()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 502 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 503 | scoped_ptr<LayerImpl> layer_impl_tree_root = |
| 504 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 505 | scoped_ptr<LayerImpl>(), |
| 506 | host_impl_.active_tree()); |
| 507 | TreeSynchronizer::PushProperties(layer_tree_root.get(), |
| 508 | layer_impl_tree_root.get()); |
| 509 | layer_impl_tree_root = |
| 510 | TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), |
| 511 | layer_impl_tree_root.Pass(), |
| 512 | host_impl_.active_tree()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 513 | |
[email protected] | b5651c2 | 2013-03-14 15:06:33 | [diff] [blame] | 514 | EXPECT_TRUE(static_cast<FakeLayerAnimationController*>( |
| 515 | layer_tree_root->layer_animation_controller())->SynchronizedAnimations()); |
[email protected] | c0dd24c | 2012-08-30 23:25:27 | [diff] [blame] | 516 | } |
| 517 | |
[email protected] | ba56574 | 2012-11-10 09:29:48 | [diff] [blame] | 518 | } // namespace |
| 519 | } // namespace cc |