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/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"
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
) {
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();
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
) {
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(
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
,
92 LayerTreeImpl
* tree_impl
) {
93 scoped_ptr
<LayerImpl
> layer_impl
= old_layers
->take(layer
->id());
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
,
107 LayerTreeImpl
* tree_impl
) {
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
,
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
,
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
,
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
)
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
)
168 DCHECK(scrollbar_layer_impl
);
170 scrollbar_layer
->PushScrollClipPropertiesTo(scrollbar_layer_impl
);
173 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
175 UpdateScrollbarLayerPointersRecursiveInternal
<Layer
, ScrollbarLayerInterface
>(
179 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
181 UpdateScrollbarLayerPointersRecursiveInternal
<
183 ScrollbarLayerImplBase
>(new_layers
, layer
);
187 template <typename LayerType
>
188 void TreeSynchronizer::PushPropertiesInternal(
190 LayerImpl
* layer_impl
,
191 int* num_dependents_need_push_properties_for_parent
) {
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();
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
),
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
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
);
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();
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();
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();
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();
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
);
302 CheckScrollAndClipPointersRecursive(layer
, layer_impl
);
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
);