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