Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/trees/tree_synchronizer.h" | 5 #include "cc/trees/tree_synchronizer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <unordered_map> | |
| 11 | 10 |
| 12 #include "base/logging.h" | 11 #include "base/logging.h" |
| 13 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 14 #include "cc/layers/layer.h" | 13 #include "cc/layers/layer.h" |
| 14 #include "cc/layers/layer_collections.h" | |
| 15 #include "cc/layers/layer_impl.h" | 15 #include "cc/layers/layer_impl.h" |
| 16 #include "cc/trees/layer_tree_impl.h" | |
| 16 | 17 |
| 17 namespace cc { | 18 namespace cc { |
| 18 | 19 |
| 19 using ScopedPtrLayerImplMap = std::unordered_map<int, scoped_ptr<LayerImpl>>; | 20 template <typename LayerType> |
| 20 using RawPtrLayerImplMap = std::unordered_map<int, LayerImpl*>; | 21 void SynchronizeTreesInternal(LayerType* layer_root, LayerTreeImpl* tree_impl) { |
| 22 DCHECK(tree_impl); | |
| 21 | 23 |
| 22 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap* old_layers, | 24 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees"); |
| 23 scoped_ptr<LayerImpl> layer_impl) { | 25 scoped_ptr<OwnedLayerImplList> old_layers(tree_impl->DetachLayers()); |
| 24 if (!layer_impl) | |
| 25 return; | |
| 26 | 26 |
| 27 OwnedLayerImplList& children = layer_impl->children(); | 27 OwnedLayerImplMap old_layer_map; |
| 28 for (auto& child : children) | 28 for (auto& it : *old_layers) |
| 29 CollectExistingLayerImplRecursive(old_layers, std::move(child)); | 29 old_layer_map[it->id()] = std::move(it); |
| 30 | 30 |
| 31 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeMaskLayer()); | 31 SynchronizeTreesRecursive(&old_layer_map, layer_root, tree_impl); |
| 32 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeReplicaLayer()); | |
| 33 | 32 |
| 34 int id = layer_impl->id(); | 33 for (auto& it : old_layer_map) { |
| 35 (*old_layers)[id] = std::move(layer_impl); | 34 if (it.second) { |
| 35 // Need to ensure that layer destruction doesn't tear down child | |
| 36 // LayerImpl that have been used in the new tree. | |
| 37 it.second->children().clear(); | |
| 38 } | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 void TreeSynchronizer::SynchronizeTrees(Layer* layer_root, | |
| 43 LayerTreeImpl* tree_impl) { | |
| 44 if (!layer_root) | |
| 45 tree_impl->ClearLayers(); | |
| 46 else | |
| 47 SynchronizeTreesInternal(layer_root, tree_impl); | |
| 48 } | |
| 49 | |
| 50 void TreeSynchronizer::SynchronizeTrees(LayerImpl* layer_root, | |
| 51 LayerTreeImpl* tree_impl) { | |
| 52 if (!layer_root) | |
| 53 tree_impl->ClearLayers(); | |
| 54 else | |
| 55 SynchronizeTreesInternal(layer_root, tree_impl); | |
| 36 } | 56 } |
| 37 | 57 |
| 38 template <typename LayerType> | 58 template <typename LayerType> |
| 39 scoped_ptr<LayerImpl> SynchronizeTreesInternal( | 59 scoped_ptr<LayerImpl> ReuseOrCreateLayerImpl(OwnedLayerImplMap* old_layers, |
| 40 LayerType* layer_root, | |
| 41 scoped_ptr<LayerImpl> old_layer_impl_root, | |
| 42 LayerTreeImpl* tree_impl) { | |
| 43 DCHECK(tree_impl); | |
| 44 | |
| 45 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees"); | |
| 46 ScopedPtrLayerImplMap old_layers; | |
| 47 RawPtrLayerImplMap new_layers; | |
| 48 | |
| 49 CollectExistingLayerImplRecursive(&old_layers, | |
| 50 std::move(old_layer_impl_root)); | |
| 51 | |
| 52 scoped_ptr<LayerImpl> new_tree = SynchronizeTreesRecursive( | |
| 53 &new_layers, &old_layers, layer_root, tree_impl); | |
| 54 | |
| 55 return new_tree; | |
| 56 } | |
| 57 | |
| 58 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees( | |
| 59 Layer* layer_root, | |
| 60 scoped_ptr<LayerImpl> old_layer_impl_root, | |
| 61 LayerTreeImpl* tree_impl) { | |
| 62 return SynchronizeTreesInternal(layer_root, std::move(old_layer_impl_root), | |
| 63 tree_impl); | |
| 64 } | |
| 65 | |
| 66 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees( | |
| 67 LayerImpl* layer_root, | |
| 68 scoped_ptr<LayerImpl> old_layer_impl_root, | |
| 69 LayerTreeImpl* tree_impl) { | |
| 70 return SynchronizeTreesInternal(layer_root, std::move(old_layer_impl_root), | |
| 71 tree_impl); | |
| 72 } | |
| 73 | |
| 74 template <typename LayerType> | |
| 75 scoped_ptr<LayerImpl> ReuseOrCreateLayerImpl(RawPtrLayerImplMap* new_layers, | |
| 76 ScopedPtrLayerImplMap* old_layers, | |
| 77 LayerType* layer, | 60 LayerType* layer, |
| 78 LayerTreeImpl* tree_impl) { | 61 LayerTreeImpl* tree_impl) { |
| 62 if (!layer) | |
| 63 return nullptr; | |
| 79 scoped_ptr<LayerImpl> layer_impl = std::move((*old_layers)[layer->id()]); | 64 scoped_ptr<LayerImpl> layer_impl = std::move((*old_layers)[layer->id()]); |
| 80 | |
| 81 if (!layer_impl) | 65 if (!layer_impl) |
| 82 layer_impl = layer->CreateLayerImpl(tree_impl); | 66 layer_impl = layer->CreateLayerImpl(tree_impl); |
| 83 | |
| 84 (*new_layers)[layer->id()] = layer_impl.get(); | |
| 85 return layer_impl; | 67 return layer_impl; |
| 86 } | 68 } |
| 87 | 69 |
| 88 template <typename LayerType> | 70 template <typename LayerType> |
| 89 scoped_ptr<LayerImpl> SynchronizeTreesRecursiveInternal( | 71 scoped_ptr<LayerImpl> SynchronizeTreesRecursiveInternal( |
| 90 RawPtrLayerImplMap* new_layers, | 72 OwnedLayerImplMap* old_layers, |
| 91 ScopedPtrLayerImplMap* old_layers, | |
| 92 LayerType* layer, | 73 LayerType* layer, |
| 93 LayerTreeImpl* tree_impl) { | 74 LayerTreeImpl* tree_impl) { |
| 94 if (!layer) | 75 if (!layer) |
| 95 return nullptr; | 76 return nullptr; |
| 96 | 77 |
| 97 scoped_ptr<LayerImpl> layer_impl = | 78 scoped_ptr<LayerImpl> layer_impl( |
| 98 ReuseOrCreateLayerImpl(new_layers, old_layers, layer, tree_impl); | 79 ReuseOrCreateLayerImpl(old_layers, layer, tree_impl)); |
| 99 | 80 |
| 100 layer_impl->ClearChildList(); | 81 layer_impl->children().clear(); |
|
Ian Vollick
2016/03/21 15:01:49
The issue here was that ClearChildList had ownersh
| |
| 101 for (size_t i = 0; i < layer->children().size(); ++i) { | 82 for (size_t i = 0; i < layer->children().size(); ++i) { |
| 102 layer_impl->AddChild(SynchronizeTreesRecursiveInternal( | 83 layer_impl->AddChild(SynchronizeTreesRecursiveInternal( |
| 103 new_layers, old_layers, layer->child_at(i), tree_impl)); | 84 old_layers, layer->child_at(i), tree_impl)); |
| 104 } | 85 } |
| 105 | 86 |
| 106 layer_impl->SetMaskLayer(SynchronizeTreesRecursiveInternal( | 87 scoped_ptr<LayerImpl> mask_layer = SynchronizeTreesRecursiveInternal( |
| 107 new_layers, old_layers, layer->mask_layer(), tree_impl)); | 88 old_layers, layer->mask_layer(), tree_impl); |
| 108 layer_impl->SetReplicaLayer(SynchronizeTreesRecursiveInternal( | 89 if (layer_impl->mask_layer() && mask_layer && |
| 109 new_layers, old_layers, layer->replica_layer(), tree_impl)); | 90 layer_impl->mask_layer() == mask_layer.get()) { |
| 91 // In this case, we only need to update the ownership, as we're essentially | |
| 92 // just resetting the mask layer. | |
| 93 tree_impl->AddLayer(std::move(mask_layer)); | |
| 94 } else { | |
| 95 layer_impl->SetMaskLayer(std::move(mask_layer)); | |
| 96 } | |
| 97 | |
| 98 scoped_ptr<LayerImpl> replica_layer = SynchronizeTreesRecursiveInternal( | |
| 99 old_layers, layer->replica_layer(), tree_impl); | |
| 100 if (layer_impl->replica_layer() && replica_layer && | |
| 101 layer_impl->replica_layer() == replica_layer.get()) { | |
| 102 // In this case, we only need to update the ownership, as we're essentially | |
| 103 // just resetting the replica layer. | |
| 104 tree_impl->AddLayer(std::move(replica_layer)); | |
| 105 } else { | |
| 106 layer_impl->SetReplicaLayer(std::move(replica_layer)); | |
| 107 } | |
| 110 | 108 |
| 111 return layer_impl; | 109 return layer_impl; |
| 112 } | 110 } |
| 113 | 111 |
| 114 scoped_ptr<LayerImpl> SynchronizeTreesRecursive( | 112 void SynchronizeTreesRecursive(OwnedLayerImplMap* old_layers, |
| 115 RawPtrLayerImplMap* new_layers, | 113 Layer* old_root, |
| 116 ScopedPtrLayerImplMap* old_layers, | 114 LayerTreeImpl* tree_impl) { |
| 117 Layer* layer, | 115 tree_impl->SetRootLayer( |
| 118 LayerTreeImpl* tree_impl) { | 116 SynchronizeTreesRecursiveInternal(old_layers, old_root, tree_impl)); |
| 119 return SynchronizeTreesRecursiveInternal( | |
| 120 new_layers, old_layers, layer, tree_impl); | |
| 121 } | 117 } |
| 122 | 118 |
| 123 scoped_ptr<LayerImpl> SynchronizeTreesRecursive( | 119 void SynchronizeTreesRecursive(OwnedLayerImplMap* old_layers, |
| 124 RawPtrLayerImplMap* new_layers, | 120 LayerImpl* old_root, |
| 125 ScopedPtrLayerImplMap* old_layers, | 121 LayerTreeImpl* tree_impl) { |
| 126 LayerImpl* layer, | 122 tree_impl->SetRootLayer( |
| 127 LayerTreeImpl* tree_impl) { | 123 SynchronizeTreesRecursiveInternal(old_layers, old_root, tree_impl)); |
| 128 return SynchronizeTreesRecursiveInternal( | |
| 129 new_layers, old_layers, layer, tree_impl); | |
| 130 } | 124 } |
| 131 | 125 |
| 132 void TreeSynchronizer::PushPropertiesInternal( | 126 void TreeSynchronizer::PushPropertiesInternal( |
| 133 Layer* layer, | 127 Layer* layer, |
| 134 LayerImpl* layer_impl, | 128 LayerImpl* layer_impl, |
| 135 int* num_dependents_need_push_properties_for_parent) { | 129 int* num_dependents_need_push_properties_for_parent) { |
| 136 if (!layer) { | 130 if (!layer) { |
| 137 DCHECK(!layer_impl); | 131 DCHECK(!layer_impl); |
| 138 return; | 132 return; |
| 139 } | 133 } |
| 140 | 134 |
| 141 DCHECK_EQ(layer->id(), layer_impl->id()); | 135 DCHECK_EQ(layer->id(), layer_impl->id()); |
| 142 | 136 |
| 143 bool push_layer = layer->needs_push_properties(); | 137 bool push_layer = layer->needs_push_properties(); |
| 144 bool recurse_on_children_and_dependents = | 138 bool recurse_on_children_and_dependents = |
| 145 layer->descendant_needs_push_properties(); | 139 layer->descendant_needs_push_properties(); |
| 146 | 140 |
| 147 if (push_layer) | 141 if (push_layer) |
| 148 layer->PushPropertiesTo(layer_impl); | 142 layer->PushPropertiesTo(layer_impl); |
| 149 | 143 |
| 150 int num_dependents_need_push_properties = 0; | 144 int num_dependents_need_push_properties = 0; |
| 151 if (recurse_on_children_and_dependents) { | 145 if (recurse_on_children_and_dependents) { |
| 152 PushPropertiesInternal(layer->mask_layer(), | 146 PushPropertiesInternal(layer->mask_layer(), layer_impl->mask_layer(), |
| 153 layer_impl->mask_layer(), | |
| 154 &num_dependents_need_push_properties); | 147 &num_dependents_need_push_properties); |
| 155 PushPropertiesInternal(layer->replica_layer(), | 148 PushPropertiesInternal(layer->replica_layer(), layer_impl->replica_layer(), |
| 156 layer_impl->replica_layer(), | |
| 157 &num_dependents_need_push_properties); | 149 &num_dependents_need_push_properties); |
| 158 | 150 |
| 159 const OwnedLayerImplList& impl_children = layer_impl->children(); | 151 const LayerImplList& impl_children = layer_impl->children(); |
| 160 DCHECK_EQ(layer->children().size(), impl_children.size()); | 152 DCHECK_EQ(layer->children().size(), impl_children.size()); |
| 161 | 153 |
| 162 for (size_t i = 0; i < layer->children().size(); ++i) { | 154 for (size_t i = 0; i < layer->children().size(); ++i) { |
| 163 PushPropertiesInternal(layer->child_at(i), impl_children[i].get(), | 155 PushPropertiesInternal(layer->child_at(i), impl_children[i], |
| 164 &num_dependents_need_push_properties); | 156 &num_dependents_need_push_properties); |
| 165 } | 157 } |
| 166 | 158 |
| 167 // When PushPropertiesTo completes for a layer, it may still keep | 159 // When PushPropertiesTo completes for a layer, it may still keep |
| 168 // its needs_push_properties() state if the layer must push itself | 160 // its needs_push_properties() state if the layer must push itself |
| 169 // every PushProperties tree walk. Here we keep track of those layers, and | 161 // every PushProperties tree walk. Here we keep track of those layers, and |
| 170 // ensure that their ancestors know about them for the next PushProperties | 162 // ensure that their ancestors know about them for the next PushProperties |
| 171 // tree walk. | 163 // tree walk. |
| 172 layer->num_dependents_need_push_properties_ = | 164 layer->num_dependents_need_push_properties_ = |
| 173 num_dependents_need_push_properties; | 165 num_dependents_need_push_properties; |
| 174 } | 166 } |
| 175 | 167 |
| 176 bool add_self_to_parent = num_dependents_need_push_properties > 0 || | 168 bool add_self_to_parent = |
| 177 layer->needs_push_properties(); | 169 num_dependents_need_push_properties > 0 || layer->needs_push_properties(); |
| 178 *num_dependents_need_push_properties_for_parent += add_self_to_parent ? 1 : 0; | 170 *num_dependents_need_push_properties_for_parent += add_self_to_parent ? 1 : 0; |
| 179 } | 171 } |
| 180 | 172 |
| 181 static void CheckScrollAndClipPointersRecursive(Layer* layer, | 173 static void CheckScrollAndClipPointersRecursive(Layer* layer, |
| 182 LayerImpl* layer_impl) { | 174 LayerImpl* layer_impl) { |
| 183 DCHECK_EQ(!!layer, !!layer_impl); | 175 DCHECK_EQ(!!layer, !!layer_impl); |
| 184 if (!layer) | 176 if (!layer) |
| 185 return; | 177 return; |
| 186 | 178 |
| 187 // Having a scroll parent on the impl thread implies having one the main | 179 // Having a scroll parent on the impl thread implies having one the main |
| 188 // thread, too. The main thread may have a scroll parent that is not in the | 180 // thread, too. The main thread may have a scroll parent that is not in the |
| 189 // tree because it's been removed but not deleted. In this case, the layer | 181 // tree because it's been removed but not deleted. In this case, the layer |
| 190 // impl will have no scroll parent. Same argument applies for clip parents and | 182 // impl will have no scroll parent. Same argument applies for clip parents and |
| 191 // scroll/clip children. | 183 // scroll/clip children. |
| 192 DCHECK(!layer_impl->scroll_parent() || !!layer->scroll_parent()); | 184 DCHECK(!layer_impl->scroll_parent() || !!layer->scroll_parent()); |
| 193 DCHECK(!layer_impl->clip_parent() || !!layer->clip_parent()); | 185 DCHECK(!layer_impl->clip_parent() || !!layer->clip_parent()); |
| 194 DCHECK(!layer_impl->scroll_children() || !!layer->scroll_children()); | 186 DCHECK(!layer_impl->scroll_children() || !!layer->scroll_children()); |
| 195 DCHECK(!layer_impl->clip_children() || !!layer->clip_children()); | 187 DCHECK(!layer_impl->clip_children() || !!layer->clip_children()); |
| 196 | 188 |
| 197 if (layer_impl->scroll_parent()) | 189 if (layer_impl->scroll_parent()) |
| 198 DCHECK_EQ(layer->scroll_parent()->id(), layer_impl->scroll_parent()->id()); | 190 DCHECK_EQ(layer->scroll_parent()->id(), layer_impl->scroll_parent()->id()); |
| 199 | 191 |
| 200 if (layer_impl->clip_parent()) | 192 if (layer_impl->clip_parent()) |
| 201 DCHECK_EQ(layer->clip_parent()->id(), layer_impl->clip_parent()->id()); | 193 DCHECK_EQ(layer->clip_parent()->id(), layer_impl->clip_parent()->id()); |
| 202 | 194 |
| 203 if (layer_impl->scroll_children()) { | 195 if (layer_impl->scroll_children()) { |
| 204 for (std::set<Layer*>::iterator it = layer->scroll_children()->begin(); | 196 for (std::set<Layer*>::iterator it = layer->scroll_children()->begin(); |
| 205 it != layer->scroll_children()->end(); | 197 it != layer->scroll_children()->end(); ++it) { |
| 206 ++it) { | |
| 207 DCHECK_EQ((*it)->scroll_parent(), layer); | 198 DCHECK_EQ((*it)->scroll_parent(), layer); |
| 208 } | 199 } |
| 209 for (std::set<LayerImpl*>::iterator it = | 200 for (std::set<LayerImpl*>::iterator it = |
| 210 layer_impl->scroll_children()->begin(); | 201 layer_impl->scroll_children()->begin(); |
| 211 it != layer_impl->scroll_children()->end(); | 202 it != layer_impl->scroll_children()->end(); ++it) { |
| 212 ++it) { | |
| 213 DCHECK_EQ((*it)->scroll_parent(), layer_impl); | 203 DCHECK_EQ((*it)->scroll_parent(), layer_impl); |
| 214 } | 204 } |
| 215 } | 205 } |
| 216 | 206 |
| 217 if (layer_impl->clip_children()) { | 207 if (layer_impl->clip_children()) { |
| 218 for (std::set<Layer*>::iterator it = layer->clip_children()->begin(); | 208 for (std::set<Layer*>::iterator it = layer->clip_children()->begin(); |
| 219 it != layer->clip_children()->end(); | 209 it != layer->clip_children()->end(); ++it) { |
| 220 ++it) { | |
| 221 DCHECK_EQ((*it)->clip_parent(), layer); | 210 DCHECK_EQ((*it)->clip_parent(), layer); |
| 222 } | 211 } |
| 223 for (std::set<LayerImpl*>::iterator it = | 212 for (std::set<LayerImpl*>::iterator it = |
| 224 layer_impl->clip_children()->begin(); | 213 layer_impl->clip_children()->begin(); |
| 225 it != layer_impl->clip_children()->end(); | 214 it != layer_impl->clip_children()->end(); ++it) { |
| 226 ++it) { | |
| 227 DCHECK_EQ((*it)->clip_parent(), layer_impl); | 215 DCHECK_EQ((*it)->clip_parent(), layer_impl); |
| 228 } | 216 } |
| 229 } | 217 } |
| 230 | 218 |
| 231 for (size_t i = 0u; i < layer->children().size(); ++i) { | 219 for (size_t i = 0u; i < layer->children().size(); ++i) { |
| 232 CheckScrollAndClipPointersRecursive(layer->child_at(i), | 220 CheckScrollAndClipPointersRecursive(layer->child_at(i), |
| 233 layer_impl->child_at(i)); | 221 layer_impl->child_at(i)); |
| 234 } | 222 } |
| 235 } | 223 } |
| 236 | 224 |
| 237 void TreeSynchronizer::PushProperties(Layer* layer, | 225 void TreeSynchronizer::PushProperties(Layer* layer, LayerImpl* layer_impl) { |
| 238 LayerImpl* layer_impl) { | |
| 239 int num_dependents_need_push_properties = 0; | 226 int num_dependents_need_push_properties = 0; |
| 240 PushPropertiesInternal( | 227 PushPropertiesInternal(layer, layer_impl, |
| 241 layer, layer_impl, &num_dependents_need_push_properties); | 228 &num_dependents_need_push_properties); |
| 242 #if DCHECK_IS_ON() | 229 #if DCHECK_IS_ON() |
| 243 CheckScrollAndClipPointersRecursive(layer, layer_impl); | 230 CheckScrollAndClipPointersRecursive(layer, layer_impl); |
| 244 #endif | 231 #endif |
| 245 } | 232 } |
| 246 | 233 |
| 247 } // namespace cc | 234 } // namespace cc |
| OLD | NEW |