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/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