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 "base/containers/hash_tables.h"
8 #include "base/containers/scoped_ptr_hash_map.h"
9 #include "base/debug/trace_event.h"
10 #include "base/logging.h"
11 #include "cc/animation/scrollbar_animation_controller.h"
12 #include "cc/input/scrollbar.h"
13 #include "cc/layers/layer.h"
14 #include "cc/layers/layer_impl.h"
15 #include "cc/layers/scrollbar_layer_impl_base.h"
16 #include "cc/layers/scrollbar_layer_interface.h"
20 typedef base::ScopedPtrHashMap
<int, LayerImpl
> ScopedPtrLayerImplMap
;
21 typedef base::hash_map
<int, LayerImpl
*> RawPtrLayerImplMap
;
23 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap
* old_layers
,
24 scoped_ptr
<LayerImpl
> layer_impl
) {
28 OwnedLayerImplList
& children
= layer_impl
->children();
29 for (OwnedLayerImplList::iterator it
= children
.begin();
32 CollectExistingLayerImplRecursive(old_layers
, children
.take(it
));
34 CollectExistingLayerImplRecursive(old_layers
, layer_impl
->TakeMaskLayer());
35 CollectExistingLayerImplRecursive(old_layers
, layer_impl
->TakeReplicaLayer());
37 int id
= layer_impl
->id();
38 old_layers
->set(id
, layer_impl
.Pass());
41 template <typename LayerType
>
42 scoped_ptr
<LayerImpl
> SynchronizeTreesInternal(
43 LayerType
* layer_root
,
44 scoped_ptr
<LayerImpl
> old_layer_impl_root
,
45 LayerTreeImpl
* tree_impl
) {
48 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees");
49 ScopedPtrLayerImplMap old_layers
;
50 RawPtrLayerImplMap new_layers
;
52 CollectExistingLayerImplRecursive(&old_layers
, old_layer_impl_root
.Pass());
54 scoped_ptr
<LayerImpl
> new_tree
= SynchronizeTreesRecursive(
55 &new_layers
, &old_layers
, layer_root
, tree_impl
);
57 UpdateScrollbarLayerPointersRecursive(&new_layers
, layer_root
);
59 return new_tree
.Pass();
62 scoped_ptr
<LayerImpl
> TreeSynchronizer::SynchronizeTrees(
64 scoped_ptr
<LayerImpl
> old_layer_impl_root
,
65 LayerTreeImpl
* tree_impl
) {
66 return SynchronizeTreesInternal(
67 layer_root
, old_layer_impl_root
.Pass(), tree_impl
);
70 scoped_ptr
<LayerImpl
> TreeSynchronizer::SynchronizeTrees(
71 LayerImpl
* layer_root
,
72 scoped_ptr
<LayerImpl
> old_layer_impl_root
,
73 LayerTreeImpl
* tree_impl
) {
74 return SynchronizeTreesInternal(
75 layer_root
, old_layer_impl_root
.Pass(), tree_impl
);
78 template <typename LayerType
>
79 scoped_ptr
<LayerImpl
> ReuseOrCreateLayerImpl(RawPtrLayerImplMap
* new_layers
,
80 ScopedPtrLayerImplMap
* old_layers
,
82 LayerTreeImpl
* tree_impl
) {
83 scoped_ptr
<LayerImpl
> layer_impl
= old_layers
->take(layer
->id());
86 layer_impl
= layer
->CreateLayerImpl(tree_impl
);
88 (*new_layers
)[layer
->id()] = layer_impl
.get();
89 return layer_impl
.Pass();
92 template <typename LayerType
>
93 scoped_ptr
<LayerImpl
> SynchronizeTreesRecursiveInternal(
94 RawPtrLayerImplMap
* new_layers
,
95 ScopedPtrLayerImplMap
* old_layers
,
97 LayerTreeImpl
* tree_impl
) {
99 return scoped_ptr
<LayerImpl
>();
101 scoped_ptr
<LayerImpl
> layer_impl
=
102 ReuseOrCreateLayerImpl(new_layers
, old_layers
, layer
, tree_impl
);
104 layer_impl
->ClearChildList();
105 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
106 layer_impl
->AddChild(SynchronizeTreesRecursiveInternal(
107 new_layers
, old_layers
, layer
->child_at(i
), tree_impl
));
110 layer_impl
->SetMaskLayer(SynchronizeTreesRecursiveInternal(
111 new_layers
, old_layers
, layer
->mask_layer(), tree_impl
));
112 layer_impl
->SetReplicaLayer(SynchronizeTreesRecursiveInternal(
113 new_layers
, old_layers
, layer
->replica_layer(), tree_impl
));
115 // Remove all dangling pointers. The pointers will be setup later in
116 // UpdateScrollbarLayerPointersRecursive phase
117 layer_impl
->SetHorizontalScrollbarLayer(NULL
);
118 layer_impl
->SetVerticalScrollbarLayer(NULL
);
120 return layer_impl
.Pass();
123 scoped_ptr
<LayerImpl
> SynchronizeTreesRecursive(
124 RawPtrLayerImplMap
* new_layers
,
125 ScopedPtrLayerImplMap
* old_layers
,
127 LayerTreeImpl
* tree_impl
) {
128 return SynchronizeTreesRecursiveInternal(
129 new_layers
, old_layers
, layer
, tree_impl
);
132 scoped_ptr
<LayerImpl
> SynchronizeTreesRecursive(
133 RawPtrLayerImplMap
* new_layers
,
134 ScopedPtrLayerImplMap
* old_layers
,
136 LayerTreeImpl
* tree_impl
) {
137 return SynchronizeTreesRecursiveInternal(
138 new_layers
, old_layers
, layer
, tree_impl
);
141 template <typename LayerType
, typename ScrollbarLayerType
>
142 void UpdateScrollbarLayerPointersRecursiveInternal(
143 const RawPtrLayerImplMap
* new_layers
,
148 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
149 UpdateScrollbarLayerPointersRecursiveInternal
<
150 LayerType
, ScrollbarLayerType
>(new_layers
, layer
->child_at(i
));
153 ScrollbarLayerType
* scrollbar_layer
= layer
->ToScrollbarLayer();
154 if (!scrollbar_layer
)
157 RawPtrLayerImplMap::const_iterator iter
=
158 new_layers
->find(layer
->id());
159 ScrollbarLayerImplBase
* scrollbar_layer_impl
=
160 iter
!= new_layers
->end()
161 ? static_cast<ScrollbarLayerImplBase
*>(iter
->second
)
163 iter
= new_layers
->find(scrollbar_layer
->ScrollLayerId());
164 LayerImpl
* scroll_layer_impl
=
165 iter
!= new_layers
->end() ? iter
->second
: NULL
;
167 DCHECK(scrollbar_layer_impl
);
168 DCHECK(scroll_layer_impl
);
170 if (scrollbar_layer
->orientation() == HORIZONTAL
)
171 scroll_layer_impl
->SetHorizontalScrollbarLayer(scrollbar_layer_impl
);
173 scroll_layer_impl
->SetVerticalScrollbarLayer(scrollbar_layer_impl
);
176 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
178 UpdateScrollbarLayerPointersRecursiveInternal
<Layer
, ScrollbarLayerInterface
>(
182 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
184 UpdateScrollbarLayerPointersRecursiveInternal
<
186 ScrollbarLayerImplBase
>(new_layers
, layer
);
190 void TreeSynchronizer::SetNumDependentsNeedPushProperties(
191 Layer
* layer
, size_t num
) {
192 layer
->num_dependents_need_push_properties_
= num
;
196 void TreeSynchronizer::SetNumDependentsNeedPushProperties(
197 LayerImpl
* layer
, size_t num
) {
201 template <typename LayerType
>
202 void TreeSynchronizer::PushPropertiesInternal(
204 LayerImpl
* layer_impl
,
205 size_t* num_dependents_need_push_properties_for_parent
) {
211 DCHECK_EQ(layer
->id(), layer_impl
->id());
213 bool push_layer
= layer
->needs_push_properties();
214 bool recurse_on_children_and_dependents
=
215 layer
->descendant_needs_push_properties();
218 layer
->PushPropertiesTo(layer_impl
);
220 size_t num_dependents_need_push_properties
= 0;
221 if (recurse_on_children_and_dependents
) {
222 PushPropertiesInternal(layer
->mask_layer(),
223 layer_impl
->mask_layer(),
224 &num_dependents_need_push_properties
);
225 PushPropertiesInternal(layer
->replica_layer(),
226 layer_impl
->replica_layer(),
227 &num_dependents_need_push_properties
);
229 const OwnedLayerImplList
& impl_children
= layer_impl
->children();
230 DCHECK_EQ(layer
->children().size(), impl_children
.size());
232 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
233 PushPropertiesInternal(layer
->child_at(i
),
235 &num_dependents_need_push_properties
);
238 // When PushPropertiesTo completes for a layer, it may still keep
239 // its needs_push_properties() state if the layer must push itself
240 // every PushProperties tree walk. Here we keep track of those layers, and
241 // ensure that their ancestors know about them for the next PushProperties
243 SetNumDependentsNeedPushProperties(
244 layer
, num_dependents_need_push_properties
);
247 bool add_self_to_parent
= num_dependents_need_push_properties
> 0 ||
248 layer
->needs_push_properties();
249 *num_dependents_need_push_properties_for_parent
+= add_self_to_parent
? 1 : 0;
252 void TreeSynchronizer::PushProperties(Layer
* layer
,
253 LayerImpl
* layer_impl
) {
254 size_t num_dependents_need_push_properties
= 0;
255 PushPropertiesInternal(
256 layer
, layer_impl
, &num_dependents_need_push_properties
);
259 void TreeSynchronizer::PushProperties(LayerImpl
* layer
, LayerImpl
* layer_impl
) {
260 size_t num_dependents_need_push_properties
= 0;
261 PushPropertiesInternal(
262 layer
, layer_impl
, &num_dependents_need_push_properties
);