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"
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"
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
) {
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();
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
) {
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(
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
,
91 LayerTreeImpl
* tree_impl
) {
92 scoped_ptr
<LayerImpl
> layer_impl
= old_layers
->take(layer
->id());
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
,
106 LayerTreeImpl
* tree_impl
) {
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
,
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
,
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
,
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
)
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
)
167 DCHECK(scrollbar_layer_impl
);
169 scrollbar_layer
->PushScrollClipPropertiesTo(scrollbar_layer_impl
);
172 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
174 UpdateScrollbarLayerPointersRecursiveInternal
<Layer
, ScrollbarLayerInterface
>(
178 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
180 UpdateScrollbarLayerPointersRecursiveInternal
<
182 ScrollbarLayerImplBase
>(new_layers
, layer
);
186 template <typename LayerType
>
187 void TreeSynchronizer::PushPropertiesInternal(
189 LayerImpl
* layer_impl
,
190 size_t* num_dependents_need_push_properties_for_parent
) {
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();
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
),
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
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
);
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();
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();
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();
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();
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
);
301 CheckScrollAndClipPointersRecursive(layer
, layer_impl
);
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
);