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 <set>
      8 
      9 #include "base/containers/hash_tables.h"
     10 #include "base/containers/scoped_ptr_hash_map.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/logging.h"
     13 #include "cc/animation/scrollbar_animation_controller.h"
     14 #include "cc/input/scrollbar.h"
     15 #include "cc/layers/layer.h"
     16 #include "cc/layers/layer_impl.h"
     17 #include "cc/layers/scrollbar_layer_impl_base.h"
     18 #include "cc/layers/scrollbar_layer_interface.h"
     19 
     20 namespace cc {
     21 
     22 typedef base::ScopedPtrHashMap<int, LayerImpl> ScopedPtrLayerImplMap;
     23 typedef base::hash_map<int, LayerImpl*> RawPtrLayerImplMap;
     24 
     25 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap* old_layers,
     26                                        scoped_ptr<LayerImpl> layer_impl) {
     27   if (!layer_impl)
     28     return;
     29 
     30   layer_impl->ClearScrollbars();
     31   if (ScrollbarLayerImplBase* scrollbar_layer =
     32           layer_impl->ToScrollbarLayer()) {
     33     scrollbar_layer->ClearClipLayer();
     34     scrollbar_layer->ClearScrollLayer();
     35   }
     36 
     37   OwnedLayerImplList& children = layer_impl->children();
     38   for (OwnedLayerImplList::iterator it = children.begin();
     39        it != children.end();
     40        ++it)
     41     CollectExistingLayerImplRecursive(old_layers, children.take(it));
     42 
     43   CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeMaskLayer());
     44   CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeReplicaLayer());
     45 
     46   int id = layer_impl->id();
     47   old_layers->set(id, layer_impl.Pass());
     48 }
     49 
     50 template <typename LayerType>
     51 scoped_ptr<LayerImpl> SynchronizeTreesInternal(
     52     LayerType* layer_root,
     53     scoped_ptr<LayerImpl> old_layer_impl_root,
     54     LayerTreeImpl* tree_impl) {
     55   DCHECK(tree_impl);
     56 
     57   TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees");
     58   ScopedPtrLayerImplMap old_layers;
     59   RawPtrLayerImplMap new_layers;
     60 
     61   CollectExistingLayerImplRecursive(&old_layers, old_layer_impl_root.Pass());
     62 
     63   scoped_ptr<LayerImpl> new_tree = SynchronizeTreesRecursive(
     64       &new_layers, &old_layers, layer_root, tree_impl);
     65 
     66   UpdateScrollbarLayerPointersRecursive(&new_layers, layer_root);
     67 
     68   return new_tree.Pass();
     69 }
     70 
     71 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees(
     72     Layer* layer_root,
     73     scoped_ptr<LayerImpl> old_layer_impl_root,
     74     LayerTreeImpl* tree_impl) {
     75   return SynchronizeTreesInternal(
     76       layer_root, old_layer_impl_root.Pass(), tree_impl);
     77 }
     78 
     79 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees(
     80     LayerImpl* layer_root,
     81     scoped_ptr<LayerImpl> old_layer_impl_root,
     82     LayerTreeImpl* tree_impl) {
     83   return SynchronizeTreesInternal(
     84       layer_root, old_layer_impl_root.Pass(), tree_impl);
     85 }
     86 
     87 template <typename LayerType>
     88 scoped_ptr<LayerImpl> ReuseOrCreateLayerImpl(RawPtrLayerImplMap* new_layers,
     89                                              ScopedPtrLayerImplMap* old_layers,
     90                                              LayerType* layer,
     91                                              LayerTreeImpl* tree_impl) {
     92   scoped_ptr<LayerImpl> layer_impl = old_layers->take(layer->id());
     93 
     94   if (!layer_impl)
     95     layer_impl = layer->CreateLayerImpl(tree_impl);
     96 
     97   (*new_layers)[layer->id()] = layer_impl.get();
     98   return layer_impl.Pass();
     99 }
    100 
    101 template <typename LayerType>
    102 scoped_ptr<LayerImpl> SynchronizeTreesRecursiveInternal(
    103     RawPtrLayerImplMap* new_layers,
    104     ScopedPtrLayerImplMap* old_layers,
    105     LayerType* layer,
    106     LayerTreeImpl* tree_impl) {
    107   if (!layer)
    108     return scoped_ptr<LayerImpl>();
    109 
    110   scoped_ptr<LayerImpl> layer_impl =
    111       ReuseOrCreateLayerImpl(new_layers, old_layers, layer, tree_impl);
    112 
    113   layer_impl->ClearChildList();
    114   for (size_t i = 0; i < layer->children().size(); ++i) {
    115     layer_impl->AddChild(SynchronizeTreesRecursiveInternal(
    116         new_layers, old_layers, layer->child_at(i), tree_impl));
    117   }
    118 
    119   layer_impl->SetMaskLayer(SynchronizeTreesRecursiveInternal(
    120       new_layers, old_layers, layer->mask_layer(), tree_impl));
    121   layer_impl->SetReplicaLayer(SynchronizeTreesRecursiveInternal(
    122       new_layers, old_layers, layer->replica_layer(), tree_impl));
    123 
    124   return layer_impl.Pass();
    125 }
    126 
    127 scoped_ptr<LayerImpl> SynchronizeTreesRecursive(
    128     RawPtrLayerImplMap* new_layers,
    129     ScopedPtrLayerImplMap* old_layers,
    130     Layer* layer,
    131     LayerTreeImpl* tree_impl) {
    132   return SynchronizeTreesRecursiveInternal(
    133       new_layers, old_layers, layer, tree_impl);
    134 }
    135 
    136 scoped_ptr<LayerImpl> SynchronizeTreesRecursive(
    137     RawPtrLayerImplMap* new_layers,
    138     ScopedPtrLayerImplMap* old_layers,
    139     LayerImpl* layer,
    140     LayerTreeImpl* tree_impl) {
    141   return SynchronizeTreesRecursiveInternal(
    142       new_layers, old_layers, layer, tree_impl);
    143 }
    144 
    145 template <typename LayerType, typename ScrollbarLayerType>
    146 void UpdateScrollbarLayerPointersRecursiveInternal(
    147     const RawPtrLayerImplMap* new_layers,
    148     LayerType* layer) {
    149   if (!layer)
    150     return;
    151 
    152   for (size_t i = 0; i < layer->children().size(); ++i) {
    153     UpdateScrollbarLayerPointersRecursiveInternal<
    154         LayerType, ScrollbarLayerType>(new_layers, layer->child_at(i));
    155   }
    156 
    157   ScrollbarLayerType* scrollbar_layer = layer->ToScrollbarLayer();
    158   if (!scrollbar_layer)
    159     return;
    160 
    161   RawPtrLayerImplMap::const_iterator iter =
    162       new_layers->find(layer->id());
    163   ScrollbarLayerImplBase* scrollbar_layer_impl =
    164       iter != new_layers->end()
    165           ? static_cast<ScrollbarLayerImplBase*>(iter->second)
    166           : NULL;
    167   DCHECK(scrollbar_layer_impl);
    168 
    169   scrollbar_layer->PushScrollClipPropertiesTo(scrollbar_layer_impl);
    170 }
    171 
    172 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers,
    173                                            Layer* layer) {
    174   UpdateScrollbarLayerPointersRecursiveInternal<Layer, ScrollbarLayerInterface>(
    175       new_layers, layer);
    176 }
    177 
    178 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers,
    179                                            LayerImpl* layer) {
    180   UpdateScrollbarLayerPointersRecursiveInternal<
    181       LayerImpl,
    182       ScrollbarLayerImplBase>(new_layers, layer);
    183 }
    184 
    185 // static
    186 template <typename LayerType>
    187 void TreeSynchronizer::PushPropertiesInternal(
    188     LayerType* layer,
    189     LayerImpl* layer_impl,
    190     size_t* num_dependents_need_push_properties_for_parent) {
    191   if (!layer) {
    192     DCHECK(!layer_impl);
    193     return;
    194   }
    195 
    196   DCHECK_EQ(layer->id(), layer_impl->id());
    197 
    198   bool push_layer = layer->needs_push_properties();
    199   bool recurse_on_children_and_dependents =
    200       layer->descendant_needs_push_properties();
    201 
    202   if (push_layer)
    203     layer->PushPropertiesTo(layer_impl);
    204   else if (layer->ToScrollbarLayer())
    205     layer->ToScrollbarLayer()->PushScrollClipPropertiesTo(layer_impl);
    206 
    207   size_t num_dependents_need_push_properties = 0;
    208   if (recurse_on_children_and_dependents) {
    209     PushPropertiesInternal(layer->mask_layer(),
    210                            layer_impl->mask_layer(),
    211                            &num_dependents_need_push_properties);
    212     PushPropertiesInternal(layer->replica_layer(),
    213                            layer_impl->replica_layer(),
    214                            &num_dependents_need_push_properties);
    215 
    216     const OwnedLayerImplList& impl_children = layer_impl->children();
    217     DCHECK_EQ(layer->children().size(), impl_children.size());
    218 
    219     for (size_t i = 0; i < layer->children().size(); ++i) {
    220       PushPropertiesInternal(layer->child_at(i),
    221                              impl_children[i],
    222                              &num_dependents_need_push_properties);
    223     }
    224 
    225     // When PushPropertiesTo completes for a layer, it may still keep
    226     // its needs_push_properties() state if the layer must push itself
    227     // every PushProperties tree walk. Here we keep track of those layers, and
    228     // ensure that their ancestors know about them for the next PushProperties
    229     // tree walk.
    230     layer->num_dependents_need_push_properties_ =
    231         num_dependents_need_push_properties;
    232   }
    233 
    234   bool add_self_to_parent = num_dependents_need_push_properties > 0 ||
    235                             layer->needs_push_properties();
    236   *num_dependents_need_push_properties_for_parent += add_self_to_parent ? 1 : 0;
    237 }
    238 
    239 static void CheckScrollAndClipPointersRecursive(Layer* layer,
    240                                                 LayerImpl* layer_impl) {
    241   DCHECK_EQ(!!layer, !!layer_impl);
    242   if (!layer)
    243     return;
    244 
    245   // Having a scroll parent on the impl thread implies having one the main
    246   // thread, too. The main thread may have a scroll parent that is not in the
    247   // tree because it's been removed but not deleted. In this case, the layer
    248   // impl will have no scroll parent. Same argument applies for clip parents and
    249   // scroll/clip children.
    250   DCHECK(!layer_impl->scroll_parent() || !!layer->scroll_parent());
    251   DCHECK(!layer_impl->clip_parent() || !!layer->clip_parent());
    252   DCHECK(!layer_impl->scroll_children() || !!layer->scroll_children());
    253   DCHECK(!layer_impl->clip_children() || !!layer->clip_children());
    254 
    255   if (layer_impl->scroll_parent())
    256     DCHECK_EQ(layer->scroll_parent()->id(), layer_impl->scroll_parent()->id());
    257 
    258   if (layer_impl->clip_parent())
    259     DCHECK_EQ(layer->clip_parent()->id(), layer_impl->clip_parent()->id());
    260 
    261   if (layer_impl->scroll_children()) {
    262     for (std::set<Layer*>::iterator it = layer->scroll_children()->begin();
    263          it != layer->scroll_children()->end();
    264          ++it) {
    265       DCHECK_EQ((*it)->scroll_parent(), layer);
    266     }
    267     for (std::set<LayerImpl*>::iterator it =
    268              layer_impl->scroll_children()->begin();
    269          it != layer_impl->scroll_children()->end();
    270          ++it) {
    271       DCHECK_EQ((*it)->scroll_parent(), layer_impl);
    272     }
    273   }
    274 
    275   if (layer_impl->clip_children()) {
    276     for (std::set<Layer*>::iterator it = layer->clip_children()->begin();
    277          it != layer->clip_children()->end();
    278          ++it) {
    279       DCHECK_EQ((*it)->clip_parent(), layer);
    280     }
    281     for (std::set<LayerImpl*>::iterator it =
    282              layer_impl->clip_children()->begin();
    283          it != layer_impl->clip_children()->end();
    284          ++it) {
    285       DCHECK_EQ((*it)->clip_parent(), layer_impl);
    286     }
    287   }
    288 
    289   for (size_t i = 0u; i < layer->children().size(); ++i) {
    290     CheckScrollAndClipPointersRecursive(layer->child_at(i),
    291                                         layer_impl->child_at(i));
    292   }
    293 }
    294 
    295 void TreeSynchronizer::PushProperties(Layer* layer,
    296                                       LayerImpl* layer_impl) {
    297   size_t num_dependents_need_push_properties = 0;
    298   PushPropertiesInternal(
    299       layer, layer_impl, &num_dependents_need_push_properties);
    300 #if DCHECK_IS_ON
    301   CheckScrollAndClipPointersRecursive(layer, layer_impl);
    302 #endif
    303 }
    304 
    305 void TreeSynchronizer::PushProperties(LayerImpl* layer, LayerImpl* layer_impl) {
    306   size_t num_dependents_need_push_properties = 0;
    307   PushPropertiesInternal(
    308       layer, layer_impl, &num_dependents_need_push_properties);
    309 }
    310 
    311 }  // namespace cc
    312