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/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "cc/animation/scrollbar_animation_controller.h"
10 #include "cc/layers/layer.h"
11 #include "cc/layers/layer_impl.h"
12 #include "cc/layers/scrollbar_layer.h"
13 #include "cc/layers/scrollbar_layer_impl.h"
17 typedef ScopedPtrHashMap
<int, LayerImpl
> ScopedPtrLayerImplMap
;
18 typedef base::hash_map
<int, LayerImpl
*> RawPtrLayerImplMap
;
20 void CollectExistingLayerImplRecursive(ScopedPtrLayerImplMap
* old_layers
,
21 scoped_ptr
<LayerImpl
> layer_impl
) {
25 OwnedLayerImplList
& children
= layer_impl
->children();
26 for (OwnedLayerImplList::iterator it
= children
.begin();
29 CollectExistingLayerImplRecursive(old_layers
, children
.take(it
));
31 CollectExistingLayerImplRecursive(old_layers
, layer_impl
->TakeMaskLayer());
32 CollectExistingLayerImplRecursive(old_layers
, layer_impl
->TakeReplicaLayer());
34 int id
= layer_impl
->id();
35 old_layers
->set(id
, layer_impl
.Pass());
38 template <typename LayerType
>
39 scoped_ptr
<LayerImpl
> SynchronizeTreesInternal(
40 LayerType
* layer_root
,
41 scoped_ptr
<LayerImpl
> old_layer_impl_root
,
42 LayerTreeImpl
* tree_impl
) {
45 TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees");
46 ScopedPtrLayerImplMap old_layers
;
47 RawPtrLayerImplMap new_layers
;
49 CollectExistingLayerImplRecursive(&old_layers
, old_layer_impl_root
.Pass());
51 scoped_ptr
<LayerImpl
> new_tree
= SynchronizeTreesRecursive(
52 &new_layers
, &old_layers
, layer_root
, tree_impl
);
54 UpdateScrollbarLayerPointersRecursive(&new_layers
, layer_root
);
56 return new_tree
.Pass();
59 scoped_ptr
<LayerImpl
> TreeSynchronizer::SynchronizeTrees(
61 scoped_ptr
<LayerImpl
> old_layer_impl_root
,
62 LayerTreeImpl
* tree_impl
) {
63 return SynchronizeTreesInternal(
64 layer_root
, old_layer_impl_root
.Pass(), tree_impl
);
67 scoped_ptr
<LayerImpl
> TreeSynchronizer::SynchronizeTrees(
68 LayerImpl
* layer_root
,
69 scoped_ptr
<LayerImpl
> old_layer_impl_root
,
70 LayerTreeImpl
* tree_impl
) {
71 return SynchronizeTreesInternal(
72 layer_root
, old_layer_impl_root
.Pass(), tree_impl
);
75 template <typename LayerType
>
76 scoped_ptr
<LayerImpl
> ReuseOrCreateLayerImpl(RawPtrLayerImplMap
* new_layers
,
77 ScopedPtrLayerImplMap
* old_layers
,
79 LayerTreeImpl
* tree_impl
) {
80 scoped_ptr
<LayerImpl
> layer_impl
= old_layers
->take(layer
->id());
83 layer_impl
= layer
->CreateLayerImpl(tree_impl
);
85 (*new_layers
)[layer
->id()] = layer_impl
.get();
86 return layer_impl
.Pass();
89 template <typename LayerType
>
90 scoped_ptr
<LayerImpl
> SynchronizeTreesRecursiveInternal(
91 RawPtrLayerImplMap
* new_layers
,
92 ScopedPtrLayerImplMap
* old_layers
,
94 LayerTreeImpl
* tree_impl
) {
96 return scoped_ptr
<LayerImpl
>();
98 scoped_ptr
<LayerImpl
> layer_impl
=
99 ReuseOrCreateLayerImpl(new_layers
, old_layers
, layer
, tree_impl
);
101 layer_impl
->ClearChildList();
102 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
103 layer_impl
->AddChild(SynchronizeTreesRecursiveInternal(
104 new_layers
, old_layers
, layer
->child_at(i
), tree_impl
));
107 layer_impl
->SetMaskLayer(SynchronizeTreesRecursiveInternal(
108 new_layers
, old_layers
, layer
->mask_layer(), tree_impl
));
109 layer_impl
->SetReplicaLayer(SynchronizeTreesRecursiveInternal(
110 new_layers
, old_layers
, layer
->replica_layer(), tree_impl
));
112 // Remove all dangling pointers. The pointers will be setup later in
113 // UpdateScrollbarLayerPointersRecursive phase
114 layer_impl
->SetHorizontalScrollbarLayer(NULL
);
115 layer_impl
->SetVerticalScrollbarLayer(NULL
);
117 return layer_impl
.Pass();
120 scoped_ptr
<LayerImpl
> SynchronizeTreesRecursive(
121 RawPtrLayerImplMap
* new_layers
,
122 ScopedPtrLayerImplMap
* old_layers
,
124 LayerTreeImpl
* tree_impl
) {
125 return SynchronizeTreesRecursiveInternal(
126 new_layers
, old_layers
, layer
, tree_impl
);
129 scoped_ptr
<LayerImpl
> SynchronizeTreesRecursive(
130 RawPtrLayerImplMap
* new_layers
,
131 ScopedPtrLayerImplMap
* old_layers
,
133 LayerTreeImpl
* tree_impl
) {
134 return SynchronizeTreesRecursiveInternal(
135 new_layers
, old_layers
, layer
, tree_impl
);
138 template <typename LayerType
, typename ScrollbarLayerType
>
139 void UpdateScrollbarLayerPointersRecursiveInternal(
140 const RawPtrLayerImplMap
* new_layers
,
145 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
146 UpdateScrollbarLayerPointersRecursiveInternal
<
147 LayerType
, ScrollbarLayerType
>(new_layers
, layer
->child_at(i
));
150 ScrollbarLayerType
* scrollbar_layer
= layer
->ToScrollbarLayer();
151 // Pinch-zoom scrollbars will have an invalid scroll_layer_id, but they are
152 // managed by LayerTreeImpl and not LayerImpl, so should not be
154 if (!scrollbar_layer
|| (scrollbar_layer
->scroll_layer_id() ==
155 Layer::PINCH_ZOOM_ROOT_SCROLL_LAYER_ID
))
158 RawPtrLayerImplMap::const_iterator iter
=
159 new_layers
->find(scrollbar_layer
->id());
160 ScrollbarLayerImpl
* scrollbar_layer_impl
=
161 iter
!= new_layers
->end() ? static_cast<ScrollbarLayerImpl
*>(iter
->second
)
163 iter
= new_layers
->find(scrollbar_layer
->scroll_layer_id());
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() == WebKit::WebScrollbar::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
, ScrollbarLayer
>(
182 void UpdateScrollbarLayerPointersRecursive(const RawPtrLayerImplMap
* new_layers
,
184 UpdateScrollbarLayerPointersRecursiveInternal
<LayerImpl
, ScrollbarLayerImpl
>(
188 template <typename LayerType
>
189 void PushPropertiesInternal(LayerType
* layer
, LayerImpl
* layer_impl
) {
195 DCHECK_EQ(layer
->id(), layer_impl
->id());
196 layer
->PushPropertiesTo(layer_impl
);
198 PushPropertiesInternal(layer
->mask_layer(), layer_impl
->mask_layer());
199 PushPropertiesInternal(layer
->replica_layer(), layer_impl
->replica_layer());
201 const OwnedLayerImplList
& impl_children
= layer_impl
->children();
202 DCHECK_EQ(layer
->children().size(), impl_children
.size());
204 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
205 PushPropertiesInternal(layer
->child_at(i
), impl_children
[i
]);
209 void TreeSynchronizer::PushProperties(Layer
* layer
, LayerImpl
* layer_impl
) {
210 PushPropertiesInternal(layer
, layer_impl
);
213 void TreeSynchronizer::PushProperties(LayerImpl
* layer
, LayerImpl
* layer_impl
) {
214 PushPropertiesInternal(layer
, layer_impl
);