Enable gaia services for enterprise autotests.
[chromium-blink-merge.git] / cc / trees / tree_synchronizer.cc
blob1faf0e04e679d468b91ab49ef5e209794d8abea5
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/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"
20 namespace cc {
22 typedef base::ScopedPtrHashMap<int, LayerImpl> ScopedPtrLayerImplMap;
23 typedef base::hash_map<int, LayerImpl*> RawPtrLayerImplMap;
25 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap* old_layers,
26 scoped_ptr<LayerImpl> layer_impl) {
27 if (!layer_impl)
28 return;
30 layer_impl->ClearScrollbars();
31 if (ScrollbarLayerImplBase* scrollbar_layer =
32 layer_impl->ToScrollbarLayer()) {
33 scrollbar_layer->ClearClipLayer();
34 scrollbar_layer->ClearScrollLayer();
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));
43 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeMaskLayer());
44 CollectExistingLayerImplRecursive(old_layers, layer_impl->TakeReplicaLayer());
46 int id = layer_impl->id();
47 old_layers->set(id, layer_impl.Pass());
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);
57 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees");
58 ScopedPtrLayerImplMap old_layers;
59 RawPtrLayerImplMap new_layers;
61 CollectExistingLayerImplRecursive(&old_layers, old_layer_impl_root.Pass());
63 scoped_ptr<LayerImpl> new_tree = SynchronizeTreesRecursive(
64 &new_layers, &old_layers, layer_root, tree_impl);
66 UpdateScrollbarLayerPointersRecursive(&new_layers, layer_root);
68 return new_tree.Pass();
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);
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);
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());
94 if (!layer_impl)
95 layer_impl = layer->CreateLayerImpl(tree_impl);
97 (*new_layers)[layer->id()] = layer_impl.get();
98 return layer_impl.Pass();
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>();
110 scoped_ptr<LayerImpl> layer_impl =
111 ReuseOrCreateLayerImpl(new_layers, old_layers, layer, tree_impl);
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));
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));
124 return layer_impl.Pass();
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);
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);
145 template <typename LayerType, typename ScrollbarLayerType>
146 void UpdateScrollbarLayerPointersRecursiveInternal(
147 const RawPtrLayerImplMap* new_layers,
148 LayerType* layer) {
149 if (!layer)
150 return;
152 for (size_t i = 0; i < layer->children().size(); ++i) {
153 UpdateScrollbarLayerPointersRecursiveInternal<
154 LayerType, ScrollbarLayerType>(new_layers, layer->child_at(i));
157 ScrollbarLayerType* scrollbar_layer = layer->ToScrollbarLayer();
158 if (!scrollbar_layer)
159 return;
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);
169 scrollbar_layer->PushScrollClipPropertiesTo(scrollbar_layer_impl);
172 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers,
173 Layer* layer) {
174 UpdateScrollbarLayerPointersRecursiveInternal<Layer, ScrollbarLayerInterface>(
175 new_layers, layer);
178 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap* new_layers,
179 LayerImpl* layer) {
180 UpdateScrollbarLayerPointersRecursiveInternal<
181 LayerImpl,
182 ScrollbarLayerImplBase>(new_layers, layer);
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;
196 DCHECK_EQ(layer->id(), layer_impl->id());
198 bool push_layer = layer->needs_push_properties();
199 bool recurse_on_children_and_dependents =
200 layer->descendant_needs_push_properties();
202 if (push_layer)
203 layer->PushPropertiesTo(layer_impl);
204 else if (layer->ToScrollbarLayer())
205 layer->ToScrollbarLayer()->PushScrollClipPropertiesTo(layer_impl);
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);
216 const OwnedLayerImplList& impl_children = layer_impl->children();
217 DCHECK_EQ(layer->children().size(), impl_children.size());
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);
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;
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;
239 static void CheckScrollAndClipPointersRecursive(Layer* layer,
240 LayerImpl* layer_impl) {
241 DCHECK_EQ(!!layer, !!layer_impl);
242 if (!layer)
243 return;
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());
255 if (layer_impl->scroll_parent())
256 DCHECK_EQ(layer->scroll_parent()->id(), layer_impl->scroll_parent()->id());
258 if (layer_impl->clip_parent())
259 DCHECK_EQ(layer->clip_parent()->id(), layer_impl->clip_parent()->id());
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);
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);
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);
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);
289 for (size_t i = 0u; i < layer->children().size(); ++i) {
290 CheckScrollAndClipPointersRecursive(layer->child_at(i),
291 layer_impl->child_at(i));
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
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);
311 } // namespace cc