Home | History | Annotate | Download | only in trees
      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