blob: de4bfa166829bb2816cf3ef3dc1a1b4d6e2e856b [file] [log] [blame]
[email protected]3b31c6ac2012-12-06 21:27:291// 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.
4
5#include "cc/layer_tree_impl.h"
6
7#include "cc/layer_tree_host_common.h"
8#include "cc/layer_tree_host_impl.h"
[email protected]caa567d2012-12-20 07:56:169#include "ui/gfx/vector2d_conversions.h"
[email protected]3b31c6ac2012-12-06 21:27:2910
11namespace cc {
12
[email protected]8bef40572012-12-11 21:38:0813LayerTreeImpl::LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl)
14 : layer_tree_host_impl_(layer_tree_host_impl)
[email protected]3b31c6ac2012-12-06 21:27:2915 , source_frame_number_(-1)
16 , hud_layer_(0)
17 , root_scroll_layer_(0)
18 , currently_scrolling_layer_(0)
19 , scrolling_layer_id_from_previous_tree_(0) {
20}
21
22LayerTreeImpl::~LayerTreeImpl() {
[email protected]361bc00d2012-12-14 07:03:2423 // Need to explicitly clear the tree prior to destroying this so that
24 // the LayerTreeImpl pointer is still valid in the LayerImpl dtor.
25 root_layer_.reset();
[email protected]3b31c6ac2012-12-06 21:27:2926}
27
28static LayerImpl* findRootScrollLayer(LayerImpl* layer)
29{
30 if (!layer)
31 return 0;
32
33 if (layer->scrollable())
34 return layer;
35
36 for (size_t i = 0; i < layer->children().size(); ++i) {
37 LayerImpl* found = findRootScrollLayer(layer->children()[i]);
38 if (found)
39 return found;
40 }
41
42 return 0;
43}
44
45void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
46 root_layer_ = layer.Pass();
47 root_scroll_layer_ = findRootScrollLayer(root_layer_.get());
48 currently_scrolling_layer_ = 0;
49
50 if (root_layer_ && scrolling_layer_id_from_previous_tree_) {
51 currently_scrolling_layer_ = LayerTreeHostCommon::findLayerInSubtree(
52 root_layer_.get(),
53 scrolling_layer_id_from_previous_tree_);
54 }
55
56 scrolling_layer_id_from_previous_tree_ = 0;
57
[email protected]8bef40572012-12-11 21:38:0858 layer_tree_host_impl_->OnCanDrawStateChangedForTree(this);
[email protected]3b31c6ac2012-12-06 21:27:2959}
60
61scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
62 // Clear all data structures that have direct references to the layer tree.
63 scrolling_layer_id_from_previous_tree_ =
64 currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0;
65 currently_scrolling_layer_ = NULL;
66
67 return root_layer_.Pass();
68}
69
70void LayerTreeImpl::ClearCurrentlyScrollingLayer() {
71 currently_scrolling_layer_ = NULL;
72 scrolling_layer_id_from_previous_tree_ = 0;
73}
74
[email protected]caa567d2012-12-20 07:56:1675void LayerTreeImpl::UpdateMaxScrollOffset() {
76 if (!root_scroll_layer() || !root_scroll_layer()->children().size())
77 return;
78
79 gfx::SizeF view_bounds = device_viewport_size();
80 if (LayerImpl* clip_layer = root_scroll_layer()->parent()) {
81 // Compensate for non-overlay scrollbars.
82 if (clip_layer->masksToBounds())
83 view_bounds = gfx::ScaleSize(clip_layer->bounds(), device_scale_factor());
84 }
85
86 gfx::Size content_bounds = ContentSize();
87 if (settings().pageScalePinchZoomEnabled) {
88 // Pinch with pageScale scrolls entirely in layout space. ContentSize
89 // returns the bounds including the page scale factor, so calculate the
90 // pre page-scale layout size here.
91 float page_scale_factor = pinch_zoom_viewport().pageScaleFactor();
92 content_bounds.set_width(content_bounds.width() / page_scale_factor);
93 content_bounds.set_height(content_bounds.height() / page_scale_factor);
94 } else {
95 view_bounds.Scale(1 / pinch_zoom_viewport().pageScaleDelta());
96 }
97
98 gfx::Vector2dF max_scroll = gfx::Rect(content_bounds).bottom_right() -
99 gfx::RectF(view_bounds).bottom_right();
100 max_scroll.Scale(1 / device_scale_factor());
101
102 // The viewport may be larger than the contents in some cases, such as
103 // having a vertical scrollbar but no horizontal overflow.
104 max_scroll.ClampToMin(gfx::Vector2dF());
105
106 root_scroll_layer()->setMaxScrollOffset(gfx::ToFlooredVector2d(max_scroll));
107}
108
109gfx::Size LayerTreeImpl::ContentSize() const {
110 // TODO(aelias): Hardcoding the first child here is weird. Think of
111 // a cleaner way to get the contentBounds on the Impl side.
112 if (!root_scroll_layer() || root_scroll_layer()->children().isEmpty())
113 return gfx::Size();
114 return root_scroll_layer()->children()[0]->contentBounds();
115}
116
[email protected]361bc00d2012-12-14 07:03:24117LayerImpl* LayerTreeImpl::LayerById(int id) {
118 LayerIdMap::iterator iter = layer_id_map_.find(id);
119 return iter != layer_id_map_.end() ? iter->second : NULL;
120}
121
122void LayerTreeImpl::RegisterLayer(LayerImpl* layer) {
123 DCHECK(!LayerById(layer->id()));
124 layer_id_map_[layer->id()] = layer;
125}
126
127void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) {
128 DCHECK(LayerById(layer->id()));
129 layer_id_map_.erase(layer->id());
130}
131
[email protected]ff762fb2012-12-12 19:18:37132const LayerTreeSettings& LayerTreeImpl::settings() const {
133 return layer_tree_host_impl_->settings();
134}
135
136OutputSurface* LayerTreeImpl::output_surface() const {
137 return layer_tree_host_impl_->outputSurface();
138}
139
140ResourceProvider* LayerTreeImpl::resource_provider() const {
141 return layer_tree_host_impl_->resourceProvider();
142}
143
144TileManager* LayerTreeImpl::tile_manager() const {
145 return layer_tree_host_impl_->tileManager();
146}
147
148FrameRateCounter* LayerTreeImpl::frame_rate_counter() const {
149 return layer_tree_host_impl_->fpsCounter();
150}
151
[email protected]f117a4c2012-12-16 04:53:10152bool LayerTreeImpl::IsActiveTree() const {
153 return layer_tree_host_impl_->activeTree() == this;
154}
155
156bool LayerTreeImpl::IsPendingTree() const {
157 return layer_tree_host_impl_->pendingTree() == this;
158}
159
160LayerImpl* LayerTreeImpl::FindActiveTreeLayerById(int id) {
161 LayerTreeImpl* tree = layer_tree_host_impl_->activeTree();
162 if (!tree)
163 return NULL;
164 return tree->LayerById(id);
165}
166
167LayerImpl* LayerTreeImpl::FindPendingTreeLayerById(int id) {
168 LayerTreeImpl* tree = layer_tree_host_impl_->pendingTree();
169 if (!tree)
170 return NULL;
171 return tree->LayerById(id);
172}
173
[email protected]ff762fb2012-12-12 19:18:37174void LayerTreeImpl::SetNeedsRedraw() {
175 layer_tree_host_impl_->setNeedsRedraw();
176}
177
178void LayerTreeImpl::SetNeedsUpdateDrawProperties() {
179 layer_tree_host_impl_->setNeedsUpdateDrawProperties();
180}
181
182const LayerTreeDebugState& LayerTreeImpl::debug_state() const {
183 return layer_tree_host_impl_->debugState();
184}
185
186float LayerTreeImpl::device_scale_factor() const {
187 return layer_tree_host_impl_->deviceScaleFactor();
188}
189
190const gfx::Size& LayerTreeImpl::device_viewport_size() const {
191 return layer_tree_host_impl_->deviceViewportSize();
192}
193
194const gfx::Size& LayerTreeImpl::layout_viewport_size() const {
195 return layer_tree_host_impl_->layoutViewportSize();
196}
197
198std::string LayerTreeImpl::layer_tree_as_text() const {
199 return layer_tree_host_impl_->layerTreeAsText();
200}
201
202DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
203 return layer_tree_host_impl_->debugRectHistory();
204}
205
[email protected]de4afb5e2012-12-20 00:11:34206AnimationRegistrar* LayerTreeImpl::animationRegistrar() const {
207 return layer_tree_host_impl_->animationRegistrar();
208}
[email protected]ff762fb2012-12-12 19:18:37209
[email protected]caa567d2012-12-20 07:56:16210const PinchZoomViewport& LayerTreeImpl::pinch_zoom_viewport() const {
211 return layer_tree_host_impl_->pinchZoomViewport();
212}
213
[email protected]3b31c6ac2012-12-06 21:27:29214} // namespace cc