- add sources.
[platform/framework/web/crosswalk.git] / src / cc / trees / tree_synchronizer.cc
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