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 5 #include "cc/trees/tree_synchronizer.h" 6 7 #include "base/containers/hash_tables.h" 8 #include "base/containers/scoped_ptr_hash_map.h" 9 #include "base/debug/trace_event.h" 10 #include "base/logging.h" 11 #include "cc/animation/scrollbar_animation_controller.h" 12 #include "cc/input/scrollbar.h" 13 #include "cc/layers/layer.h" 14 #include "cc/layers/layer_impl.h" 15 #include "cc/layers/scrollbar_layer_impl_base.h" 16 #include "cc/layers/scrollbar_layer_interface.h" 17 18 namespace cc { 19 20 typedef base::ScopedPtrHashMap<int, LayerImpl> ScopedPtrLayerImplMap; 21 typedef base::hash_map<int, LayerImpl*> RawPtrLayerImplMap; 22 23 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap* old_layers, 24 scoped_ptr<LayerImpl> layer_impl) { 25 if (!layer_impl) 26 return; 27 28 OwnedLayerImplList& children = layer_impl->children(); 29 for (OwnedLayerImplList::iterator it = children.begin(); 30 it != children.end(); 31 ++it) 32 CollectExistingLayerImplRecursive(old_layers, children.take(it)); 33 34 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeMaskLayer()); 35 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeReplicaLayer()); 36 37 int id = layer_impl->id(); 38 old_layers->set(id, layer_impl.Pass()); 39 } 40 41 template <typename LayerType> 42 scoped_ptr<LayerImpl> SynchronizeTreesInternal( 43 LayerType* layer_root, 44 scoped_ptr<LayerImpl> old_layer_impl_root, 45 LayerTreeImpl* tree_impl) { 46 DCHECK(tree_impl); 47 48 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees"); 49 ScopedPtrLayerImplMap old_layers; 50 RawPtrLayerImplMap new_layers; 51 52 CollectExistingLayerImplRecursive(&old_layers, old_layer_impl_root.Pass()); 53 54 scoped_ptr<LayerImpl> new_tree = SynchronizeTreesRecursive( 55 &new_layers, &old_layers, layer_root, tree_impl); 56 57 UpdateScrollbarLayerPointersRecursive(&new_layers, layer_root); 58 59 return new_tree.Pass(); 60 } 61 62 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees( 63 Layer* layer_root, 64 scoped_ptr<LayerImpl> old_layer_impl_root, 65 LayerTreeImpl* tree_impl) { 66 return SynchronizeTreesInternal( 67 layer_root, old_layer_impl_root.Pass(), tree_impl); 68 } 69 70 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees( 71 LayerImpl* layer_root, 72 scoped_ptr<LayerImpl> old_layer_impl_root, 73 LayerTreeImpl* tree_impl) { 74 return SynchronizeTreesInternal( 75 layer_root, old_layer_impl_root.Pass(), tree_impl); 76 } 77 78 template <typename LayerType> 79 scoped_ptr<LayerImpl> ReuseOrCreateLayerImpl(RawPtrLayerImplMap* new_layers, 80 ScopedPtrLayerImplMap* old_layers, 81 LayerType* layer, 82 LayerTreeImpl* tree_impl) { 83 scoped_ptr<LayerImpl> layer_impl = old_layers->take(layer->id()); 84 85 if (!layer_impl) 86 layer_impl = layer->CreateLayerImpl(tree_impl); 87 88 (*new_layers)[layer->id()] = layer_impl.get(); 89 return layer_impl.Pass(); 90 } 91 92 template <typename LayerType> 93 scoped_ptr<LayerImpl> SynchronizeTreesRecursiveInternal( 94 RawPtrLayerImplMap* new_layers, 95 ScopedPtrLayerImplMap* old_layers, 96 LayerType* layer, 97 LayerTreeImpl* tree_impl) { 98 if (!layer) 99 return scoped_ptr<LayerImpl>(); 100 101 scoped_ptr<LayerImpl> layer_impl = 102 ReuseOrCreateLayerImpl(new_layers, old_layers, layer, tree_impl); 103 104 layer_impl->ClearChildList(); 105 for (size_t i = 0; i < layer->children().size(); ++i) { 106 layer_impl->AddChild(SynchronizeTreesRecursiveInternal( 107 new_layers, old_layers, layer->child_at(i), tree_impl)); 108 } 109 110 layer_impl->SetMaskLayer(SynchronizeTreesRecursiveInternal( 111 new_layers, old_layers, layer->mask_layer(), tree_impl)); 112 layer_impl->SetReplicaLayer(SynchronizeTreesRecursiveInternal( 113 new_layers, old_layers, layer->replica_layer(), tree_impl)); 114 115 // Remove all dangling pointers. The pointers will be setup later in 116 // UpdateScrollbarLayerPointersRecursive phase 117 layer_impl->SetHorizontalScrollbarLayer(NULL); 118 layer_impl->SetVerticalScrollbarLayer(NULL); 119 120 return layer_impl.Pass(); 121 } 122 123 scoped_ptr<LayerImpl> SynchronizeTreesRecursive( 124 RawPtrLayerImplMap* new_layers, 125 ScopedPtrLayerImplMap* old_layers, 126 Layer* layer, 127 LayerTreeImpl* tree_impl) { 128 return SynchronizeTreesRecursiveInternal( 129 new_layers, old_layers, layer, tree_impl); 130 } 131 132 scoped_ptr<LayerImpl> SynchronizeTreesRecursive( 133 RawPtrLayerImplMap* new_layers, 134 ScopedPtrLayerImplMap* old_layers, 135 LayerImpl* layer, 136 LayerTreeImpl* tree_impl) { 137 return SynchronizeTreesRecursiveInternal( 138 new_layers, old_layers, layer, tree_impl); 139 } 140 141 template <typename LayerType, typename ScrollbarLayerType> 142 void UpdateScrollbarLayerPointersRecursiveInternal( 143 const RawPtrLayerImplMap* new_layers, 144 LayerType* layer) { 145 if (!layer) 146 return; 147 148 for (size_t i = 0; i < layer->children().size(); ++i) { 149 UpdateScrollbarLayerPointersRecursiveInternal< 150 LayerType, ScrollbarLayerType>(new_layers, layer->child_at(i)); 151 } 152 153 ScrollbarLayerType* scrollbar_layer = layer->ToScrollbarLayer(); 154 if (!scrollbar_layer) 155 return; 156 157 RawPtrLayerImplMap::const_iterator iter = 158 new_layers->find(layer->id()); 159 ScrollbarLayerImplBase* scrollbar_layer_impl = 160 iter != new_layers->end() 161 ? static_cast<ScrollbarLayerImplBase*>(iter->second) 162 : NULL; 163 iter = new_layers->find(scrollbar_layer->ScrollLayerId()); 164 LayerImpl* scroll_layer_impl = 165 iter != new_layers->end() ? iter->second : NULL; 166 167 DCHECK(scrollbar_layer_impl); 168 DCHECK(scroll_layer_impl); 169 170 if (scrollbar_layer->orientation() == HORIZONTAL) 171 scroll_layer_impl->SetHorizontalScrollbarLayer(scrollbar_layer_impl); 172 else 173 scroll_layer_impl->SetVerticalScrollbarLayer(scrollbar_layer_impl); 174 } 175 176 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers, 177 Layer* layer) { 178 UpdateScrollbarLayerPointersRecursiveInternal<Layer, ScrollbarLayerInterface>( 179 new_layers, layer); 180 } 181 182 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers, 183 LayerImpl* layer) { 184 UpdateScrollbarLayerPointersRecursiveInternal< 185 LayerImpl, 186 ScrollbarLayerImplBase>(new_layers, layer); 187 } 188 189 // static 190 void TreeSynchronizer::SetNumDependentsNeedPushProperties( 191 Layer* layer, size_t num) { 192 layer->num_dependents_need_push_properties_ = num; 193 } 194 195 // static 196 void TreeSynchronizer::SetNumDependentsNeedPushProperties( 197 LayerImpl* layer, size_t num) { 198 } 199 200 // static 201 template <typename LayerType> 202 void TreeSynchronizer::PushPropertiesInternal( 203 LayerType* layer, 204 LayerImpl* layer_impl, 205 size_t* num_dependents_need_push_properties_for_parent) { 206 if (!layer) { 207 DCHECK(!layer_impl); 208 return; 209 } 210 211 DCHECK_EQ(layer->id(), layer_impl->id()); 212 213 bool push_layer = layer->needs_push_properties(); 214 bool recurse_on_children_and_dependents = 215 layer->descendant_needs_push_properties(); 216 217 if (push_layer) 218 layer->PushPropertiesTo(layer_impl); 219 220 size_t num_dependents_need_push_properties = 0; 221 if (recurse_on_children_and_dependents) { 222 PushPropertiesInternal(layer->mask_layer(), 223 layer_impl->mask_layer(), 224 &num_dependents_need_push_properties); 225 PushPropertiesInternal(layer->replica_layer(), 226 layer_impl->replica_layer(), 227 &num_dependents_need_push_properties); 228 229 const OwnedLayerImplList& impl_children = layer_impl->children(); 230 DCHECK_EQ(layer->children().size(), impl_children.size()); 231 232 for (size_t i = 0; i < layer->children().size(); ++i) { 233 PushPropertiesInternal(layer->child_at(i), 234 impl_children[i], 235 &num_dependents_need_push_properties); 236 } 237 238 // When PushPropertiesTo completes for a layer, it may still keep 239 // its needs_push_properties() state if the layer must push itself 240 // every PushProperties tree walk. Here we keep track of those layers, and 241 // ensure that their ancestors know about them for the next PushProperties 242 // tree walk. 243 SetNumDependentsNeedPushProperties( 244 layer, num_dependents_need_push_properties); 245 } 246 247 bool add_self_to_parent = num_dependents_need_push_properties > 0 || 248 layer->needs_push_properties(); 249 *num_dependents_need_push_properties_for_parent += add_self_to_parent ? 1 : 0; 250 } 251 252 void TreeSynchronizer::PushProperties(Layer* layer, 253 LayerImpl* layer_impl) { 254 size_t num_dependents_need_push_properties = 0; 255 PushPropertiesInternal( 256 layer, layer_impl, &num_dependents_need_push_properties); 257 } 258 259 void TreeSynchronizer::PushProperties(LayerImpl* layer, LayerImpl* layer_impl) { 260 size_t num_dependents_need_push_properties = 0; 261 PushPropertiesInternal( 262 layer, layer_impl, &num_dependents_need_push_properties); 263 } 264 265 } // namespace cc 266