Add ICU message format support
[chromium-blink-merge.git] / cc / trees / tree_synchronizer.cc
blob3646dcaa4f796f2b33746cd0fdf1372c0f86de65
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.
5 #include "cc/trees/tree_synchronizer.h"
7 #include <set>
9 #include "base/containers/hash_tables.h"
10 #include "base/containers/scoped_ptr_hash_map.h"
11 #include "base/logging.h"
12 #include "base/trace_event/trace_event.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"
20 namespace cc {
22 typedef base::ScopedPtrHashMap<int, scoped_ptr<LayerImpl>>
23 ScopedPtrLayerImplMap;
24 typedef base::hash_map<int, LayerImpl*> RawPtrLayerImplMap;
26 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap* old_layers,
27 scoped_ptr<LayerImpl> layer_impl) {
28 if (!layer_impl)
29 return;
31 layer_impl->ClearScrollbars();
32 if (ScrollbarLayerImplBase* scrollbar_layer =
33 layer_impl->ToScrollbarLayer()) {
34 scrollbar_layer->ClearClipLayer();
35 scrollbar_layer->ClearScrollLayer();
38 OwnedLayerImplList& children = layer_impl->children();
39 for (OwnedLayerImplList::iterator it = children.begin();
40 it != children.end();
41 ++it)
42 CollectExistingLayerImplRecursive(old_layers, children.take(it));
44 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeMaskLayer());
45 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeReplicaLayer());
47 int id = layer_impl->id();
48 old_layers->set(id, layer_impl.Pass());
51 template <typename LayerType>
52 scoped_ptr<LayerImpl> SynchronizeTreesInternal(
53 LayerType* layer_root,
54 scoped_ptr<LayerImpl> old_layer_impl_root,
55 LayerTreeImpl* tree_impl) {
56 DCHECK(tree_impl);
58 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees");
59 ScopedPtrLayerImplMap old_layers;
60 RawPtrLayerImplMap new_layers;
62 CollectExistingLayerImplRecursive(&old_layers, old_layer_impl_root.Pass());
64 scoped_ptr<LayerImpl> new_tree = SynchronizeTreesRecursive(
65 &new_layers, &old_layers, layer_root, tree_impl);
67 UpdateScrollbarLayerPointersRecursive(&new_layers, layer_root);
69 return new_tree.Pass();
72 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees(
73 Layer* layer_root,
74 scoped_ptr<LayerImpl> old_layer_impl_root,
75 LayerTreeImpl* tree_impl) {
76 return SynchronizeTreesInternal(
77 layer_root, old_layer_impl_root.Pass(), tree_impl);
80 scoped_ptr<LayerImpl> TreeSynchronizer::SynchronizeTrees(
81 LayerImpl* layer_root,
82 scoped_ptr<LayerImpl> old_layer_impl_root,
83 LayerTreeImpl* tree_impl) {
84 return SynchronizeTreesInternal(
85 layer_root, old_layer_impl_root.Pass(), tree_impl);
88 template <typename LayerType>
89 scoped_ptr<LayerImpl> ReuseOrCreateLayerImpl(RawPtrLayerImplMap* new_layers,
90 ScopedPtrLayerImplMap* old_layers,
91 LayerType* layer,
92 LayerTreeImpl* tree_impl) {
93 scoped_ptr<LayerImpl> layer_impl = old_layers->take(layer->id());
95 if (!layer_impl)
96 layer_impl = layer->CreateLayerImpl(tree_impl);
98 (*new_layers)[layer->id()] = layer_impl.get();
99 return layer_impl.Pass();
102 template <typename LayerType>
103 scoped_ptr<LayerImpl> SynchronizeTreesRecursiveInternal(
104 RawPtrLayerImplMap* new_layers,
105 ScopedPtrLayerImplMap* old_layers,
106 LayerType* layer,
107 LayerTreeImpl* tree_impl) {
108 if (!layer)
109 return nullptr;
111 scoped_ptr<LayerImpl> layer_impl =
112 ReuseOrCreateLayerImpl(new_layers, old_layers, layer, tree_impl);
114 layer_impl->ClearChildList();
115 for (size_t i = 0; i < layer->children().size(); ++i) {
116 layer_impl->AddChild(SynchronizeTreesRecursiveInternal(
117 new_layers, old_layers, layer->child_at(i), tree_impl));
120 layer_impl->SetMaskLayer(SynchronizeTreesRecursiveInternal(
121 new_layers, old_layers, layer->mask_layer(), tree_impl));
122 layer_impl->SetReplicaLayer(SynchronizeTreesRecursiveInternal(
123 new_layers, old_layers, layer->replica_layer(), tree_impl));
125 return layer_impl.Pass();
128 scoped_ptr<LayerImpl> SynchronizeTreesRecursive(
129 RawPtrLayerImplMap* new_layers,
130 ScopedPtrLayerImplMap* old_layers,
131 Layer* layer,
132 LayerTreeImpl* tree_impl) {
133 return SynchronizeTreesRecursiveInternal(
134 new_layers, old_layers, layer, tree_impl);
137 scoped_ptr<LayerImpl> SynchronizeTreesRecursive(
138 RawPtrLayerImplMap* new_layers,
139 ScopedPtrLayerImplMap* old_layers,
140 LayerImpl* layer,
141 LayerTreeImpl* tree_impl) {
142 return SynchronizeTreesRecursiveInternal(
143 new_layers, old_layers, layer, tree_impl);
146 template <typename LayerType, typename ScrollbarLayerType>
147 void UpdateScrollbarLayerPointersRecursiveInternal(
148 const RawPtrLayerImplMap* new_layers,
149 LayerType* layer) {
150 if (!layer)
151 return;
153 for (size_t i = 0; i < layer->children().size(); ++i) {
154 UpdateScrollbarLayerPointersRecursiveInternal<
155 LayerType, ScrollbarLayerType>(new_layers, layer->child_at(i));
158 ScrollbarLayerType* scrollbar_layer = layer->ToScrollbarLayer();
159 if (!scrollbar_layer)
160 return;
162 RawPtrLayerImplMap::const_iterator iter =
163 new_layers->find(layer->id());
164 ScrollbarLayerImplBase* scrollbar_layer_impl =
165 iter != new_layers->end()
166 ? static_cast<ScrollbarLayerImplBase*>(iter->second)
167 : NULL;
168 DCHECK(scrollbar_layer_impl);
170 scrollbar_layer->PushScrollClipPropertiesTo(scrollbar_layer_impl);
173 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers,
174 Layer* layer) {
175 UpdateScrollbarLayerPointersRecursiveInternal<Layer, ScrollbarLayerInterface>(
176 new_layers, layer);
179 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers,
180 LayerImpl* layer) {
181 UpdateScrollbarLayerPointersRecursiveInternal<
182 LayerImpl,
183 ScrollbarLayerImplBase>(new_layers, layer);
186 // static
187 template <typename LayerType>
188 void TreeSynchronizer::PushPropertiesInternal(
189 LayerType* layer,
190 LayerImpl* layer_impl,
191 int* num_dependents_need_push_properties_for_parent) {
192 if (!layer) {
193 DCHECK(!layer_impl);
194 return;
197 DCHECK_EQ(layer->id(), layer_impl->id());
199 bool push_layer = layer->needs_push_properties();
200 bool recurse_on_children_and_dependents =
201 layer->descendant_needs_push_properties();
203 if (push_layer)
204 layer->PushPropertiesTo(layer_impl);
205 else if (layer->ToScrollbarLayer())
206 layer->ToScrollbarLayer()->PushScrollClipPropertiesTo(layer_impl);
208 int num_dependents_need_push_properties = 0;
209 if (recurse_on_children_and_dependents) {
210 PushPropertiesInternal(layer->mask_layer(),
211 layer_impl->mask_layer(),
212 &num_dependents_need_push_properties);
213 PushPropertiesInternal(layer->replica_layer(),
214 layer_impl->replica_layer(),
215 &num_dependents_need_push_properties);
217 const OwnedLayerImplList& impl_children = layer_impl->children();
218 DCHECK_EQ(layer->children().size(), impl_children.size());
220 for (size_t i = 0; i < layer->children().size(); ++i) {
221 PushPropertiesInternal(layer->child_at(i),
222 impl_children[i],
223 &num_dependents_need_push_properties);
226 // When PushPropertiesTo completes for a layer, it may still keep
227 // its needs_push_properties() state if the layer must push itself
228 // every PushProperties tree walk. Here we keep track of those layers, and
229 // ensure that their ancestors know about them for the next PushProperties
230 // tree walk.
231 layer->num_dependents_need_push_properties_ =
232 num_dependents_need_push_properties;
235 bool add_self_to_parent = num_dependents_need_push_properties > 0 ||
236 layer->needs_push_properties();
237 *num_dependents_need_push_properties_for_parent += add_self_to_parent ? 1 : 0;
240 static void CheckScrollAndClipPointersRecursive(Layer* layer,
241 LayerImpl* layer_impl) {
242 DCHECK_EQ(!!layer, !!layer_impl);
243 if (!layer)
244 return;
246 // Having a scroll parent on the impl thread implies having one the main
247 // thread, too. The main thread may have a scroll parent that is not in the
248 // tree because it's been removed but not deleted. In this case, the layer
249 // impl will have no scroll parent. Same argument applies for clip parents and
250 // scroll/clip children.
251 DCHECK(!layer_impl->scroll_parent() || !!layer->scroll_parent());
252 DCHECK(!layer_impl->clip_parent() || !!layer->clip_parent());
253 DCHECK(!layer_impl->scroll_children() || !!layer->scroll_children());
254 DCHECK(!layer_impl->clip_children() || !!layer->clip_children());
256 if (layer_impl->scroll_parent())
257 DCHECK_EQ(layer->scroll_parent()->id(), layer_impl->scroll_parent()->id());
259 if (layer_impl->clip_parent())
260 DCHECK_EQ(layer->clip_parent()->id(), layer_impl->clip_parent()->id());
262 if (layer_impl->scroll_children()) {
263 for (std::set<Layer*>::iterator it = layer->scroll_children()->begin();
264 it != layer->scroll_children()->end();
265 ++it) {
266 DCHECK_EQ((*it)->scroll_parent(), layer);
268 for (std::set<LayerImpl*>::iterator it =
269 layer_impl->scroll_children()->begin();
270 it != layer_impl->scroll_children()->end();
271 ++it) {
272 DCHECK_EQ((*it)->scroll_parent(), layer_impl);
276 if (layer_impl->clip_children()) {
277 for (std::set<Layer*>::iterator it = layer->clip_children()->begin();
278 it != layer->clip_children()->end();
279 ++it) {
280 DCHECK_EQ((*it)->clip_parent(), layer);
282 for (std::set<LayerImpl*>::iterator it =
283 layer_impl->clip_children()->begin();
284 it != layer_impl->clip_children()->end();
285 ++it) {
286 DCHECK_EQ((*it)->clip_parent(), layer_impl);
290 for (size_t i = 0u; i < layer->children().size(); ++i) {
291 CheckScrollAndClipPointersRecursive(layer->child_at(i),
292 layer_impl->child_at(i));
296 void TreeSynchronizer::PushProperties(Layer* layer,
297 LayerImpl* layer_impl) {
298 int num_dependents_need_push_properties = 0;
299 PushPropertiesInternal(
300 layer, layer_impl, &num_dependents_need_push_properties);
301 #if DCHECK_IS_ON()
302 CheckScrollAndClipPointersRecursive(layer, layer_impl);
303 #endif
306 void TreeSynchronizer::PushProperties(LayerImpl* layer, LayerImpl* layer_impl) {
307 int num_dependents_need_push_properties = 0;
308 PushPropertiesInternal(
309 layer, layer_impl, &num_dependents_need_push_properties);
312 } // namespace cc