Upstream version 10.38.220.0
[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 <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