Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: cc/layer_tree_host_impl.cc

Issue 12648005: cc: Chromify the LayerTreeHostImpl class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Compl Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/layer_tree_host_impl.h ('k') | cc/layer_tree_host_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/layer_tree_host_impl.h" 5 #include "cc/layer_tree_host_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #include "cc/solid_color_draw_quad.h" 43 #include "cc/solid_color_draw_quad.h"
44 #include "cc/texture_uploader.h" 44 #include "cc/texture_uploader.h"
45 #include "cc/top_controls_manager.h" 45 #include "cc/top_controls_manager.h"
46 #include "cc/tree_synchronizer.h" 46 #include "cc/tree_synchronizer.h"
47 #include "cc/util.h" 47 #include "cc/util.h"
48 #include "ui/gfx/size_conversions.h" 48 #include "ui/gfx/size_conversions.h"
49 #include "ui/gfx/vector2d_conversions.h" 49 #include "ui/gfx/vector2d_conversions.h"
50 50
51 namespace { 51 namespace {
52 52
53 void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) 53 void DidVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) {
54 { 54 if (visible) {
55 if (visible) { 55 TRACE_EVENT_ASYNC_BEGIN1("webkit",
56 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id); 56 "LayerTreeHostImpl::SetVisible",
57 return; 57 id,
58 "LayerTreeHostImpl",
59 id);
60 return;
61 }
62
63 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::SetVisible", id);
64 }
65
66 std::string ValueToString(scoped_ptr<base::Value> value) {
67 std::string str;
68 base::JSONWriter::Write(value.get(), &str);
69 return str;
70 }
71
72 } // namespace
73
74 namespace cc {
75
76 class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
77 public:
78 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create(
79 LayerTreeHostImpl* layer_tree_host_impl,
80 scoped_refptr<DelayBasedTimeSource> time_source) {
81 return make_scoped_ptr(
82 new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl,
83 time_source));
84 }
85 virtual ~LayerTreeHostImplTimeSourceAdapter() {
86 time_source_->setClient(NULL);
87 time_source_->setActive(false);
88 }
89
90 virtual void onTimerTick() OVERRIDE {
91 // In single threaded mode we attempt to simulate changing the current
92 // thread by maintaining a fake thread id. When we switch from one
93 // thread to another, we construct DebugScopedSetXXXThread objects that
94 // update the thread id. This lets DCHECKS that ensure we're on the
95 // right thread to work correctly in single threaded mode. The problem
96 // here is that the timer tasks are run via the message loop, and when
97 // they run, we've had no chance to construct a DebugScopedSetXXXThread
98 // object. The result is that we report that we're running on the main
99 // thread. In multi-threaded mode, this timer is run on the compositor
100 // thread, so to keep this consistent in single-threaded mode, we'll
101 // construct a DebugScopedSetImplThread object. There is no need to do
102 // this in multi-threaded mode since the real thread id's will be
103 // correct. In fact, setting fake thread id's interferes with the real
104 // thread id's and causes breakage.
105 scoped_ptr<DebugScopedSetImplThread> set_impl_thread;
106 if (!layer_tree_host_impl_->proxy()->HasImplThread()) {
107 set_impl_thread.reset(
108 new DebugScopedSetImplThread(layer_tree_host_impl_->proxy()));
58 } 109 }
59 110
60 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id); 111 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
61 } 112 layer_tree_host_impl_->Animate(base::TimeTicks::Now(), base::Time::Now());
62 113 layer_tree_host_impl_->BeginNextFrame();
63 std::string ValueToString(scoped_ptr<base::Value> value) 114 }
64 { 115
65 std::string str; 116 void SetActive(bool active) {
66 base::JSONWriter::Write(value.get(), &str); 117 if (active != time_source_->active())
67 return str; 118 time_source_->setActive(active);
68 } 119 }
69 120
70 } // namespace 121 private:
71 122 LayerTreeHostImplTimeSourceAdapter(
72 namespace cc { 123 LayerTreeHostImpl* layer_tree_host_impl,
73 124 scoped_refptr<DelayBasedTimeSource> time_source)
74 class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient { 125 : layer_tree_host_impl_(layer_tree_host_impl),
75 public: 126 time_source_(time_source) {
76 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create(LayerTreeHostIm pl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource) 127 time_source_->setClient(this);
77 { 128 }
78 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeH ostImpl, timeSource)); 129
79 } 130 LayerTreeHostImpl* layer_tree_host_impl_;
80 virtual ~LayerTreeHostImplTimeSourceAdapter() 131 scoped_refptr<DelayBasedTimeSource> time_source_;
81 { 132
82 m_timeSource->setClient(0); 133 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
83 m_timeSource->setActive(false);
84 }
85
86 virtual void onTimerTick() OVERRIDE
87 {
88 // In single threaded mode we attempt to simulate changing the current
89 // thread by maintaining a fake thread id. When we switch from one
90 // thread to another, we construct DebugScopedSetXXXThread objects that
91 // update the thread id. This lets DCHECKS that ensure we're on the
92 // right thread to work correctly in single threaded mode. The problem
93 // here is that the timer tasks are run via the message loop, and when
94 // they run, we've had no chance to construct a DebugScopedSetXXXThread
95 // object. The result is that we report that we're running on the main
96 // thread. In multi-threaded mode, this timer is run on the compositor
97 // thread, so to keep this consistent in single-threaded mode, we'll
98 // construct a DebugScopedSetImplThread object. There is no need to do
99 // this in multi-threaded mode since the real thread id's will be
100 // correct. In fact, setting fake thread id's interferes with the real
101 // thread id's and causes breakage.
102 scoped_ptr<DebugScopedSetImplThread> setImplThread;
103 if (!m_layerTreeHostImpl->proxy()->HasImplThread())
104 setImplThread.reset(new DebugScopedSetImplThread(m_layerTreeHostImpl ->proxy()));
105
106 m_layerTreeHostImpl->activatePendingTreeIfNeeded();
107 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now());
108 m_layerTreeHostImpl->beginNextFrame();
109 }
110
111 void setActive(bool active)
112 {
113 if (active != m_timeSource->active())
114 m_timeSource->setActive(active);
115 }
116
117 private:
118 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, sco ped_refptr<DelayBasedTimeSource> timeSource)
119 : m_layerTreeHostImpl(layerTreeHostImpl)
120 , m_timeSource(timeSource)
121 {
122 m_timeSource->setClient(this);
123 }
124
125 LayerTreeHostImpl* m_layerTreeHostImpl;
126 scoped_refptr<DelayBasedTimeSource> m_timeSource;
127
128 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
129 }; 134 };
130 135
131 LayerTreeHostImpl::FrameData::FrameData() 136 LayerTreeHostImpl::FrameData::FrameData()
132 : containsIncompleteTile(false) 137 : contains_incomplete_tile(false) {}
133 { 138
134 } 139 LayerTreeHostImpl::FrameData::~FrameData() {}
135 140
136 LayerTreeHostImpl::FrameData::~FrameData() 141 scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
137 { 142 const LayerTreeSettings& settings,
138 } 143 LayerTreeHostImplClient* client,
139 144 Proxy* proxy) {
140 scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy) 145 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy));
141 { 146 }
142 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy)); 147
143 } 148 LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings,
144 149 LayerTreeHostImplClient* client,
145 LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTre eHostImplClient* client, Proxy* proxy) 150 Proxy* proxy)
146 : m_client(client) 151 : client_(client),
147 , m_proxy(proxy) 152 proxy_(proxy),
148 , m_didLockScrollingLayer(false) 153 did_lock_scrolling_layer_(false),
149 , m_shouldBubbleScrolls(false) 154 should_bubble_scrolls_(false),
150 , m_wheelScrolling(false) 155 wheel_scrolling_(false),
151 , m_settings(settings) 156 settings_(settings),
152 , m_deviceScaleFactor(1) 157 device_scale_factor_(1.f),
153 , m_visible(true) 158 visible_(true),
154 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationL imit(), 159 managed_memory_policy_(
155 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING, 160 PrioritizedResourceManager::defaultMemoryAllocationLimit(),
156 0, 161 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
157 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING) 162 0,
158 , m_pinchGestureActive(false) 163 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING),
159 , m_fpsCounter(FrameRateCounter::create(m_proxy->HasImplThread())) 164 pinch_gesture_active_(false),
160 , m_paintTimeCounter(PaintTimeCounter::create()) 165 fps_counter_(FrameRateCounter::create(proxy_->HasImplThread())),
161 , m_memoryHistory(MemoryHistory::Create()) 166 paint_time_counter_(PaintTimeCounter::create()),
162 , m_debugRectHistory(DebugRectHistory::create()) 167 memory_history_(MemoryHistory::Create()),
163 , m_numImplThreadScrolls(0) 168 debug_rect_history_(DebugRectHistory::create()),
164 , m_numMainThreadScrolls(0) 169 num_impl_thread_scrolls_(0),
165 , m_cumulativeNumLayersDrawn(0) 170 num_main_thread_scrolls_(0),
166 , m_cumulativeNumMissingTiles(0) 171 cumulative_num_layers_drawn_(0),
167 , m_lastSentMemoryVisibleBytes(0) 172 cumulative_num_missing_tiles_(0),
168 , m_lastSentMemoryVisibleAndNearbyBytes(0) 173 last_sent_memory_visible_bytes_(0),
169 , m_lastSentMemoryUseBytes(0) 174 last_sent_memory_visible_and_nearby_bytes_(0),
170 , m_animationRegistrar(AnimationRegistrar::create()) 175 last_sent_memory_use_bytes_(0),
171 { 176 animation_registrar_(AnimationRegistrar::create()) {
172 DCHECK(m_proxy->IsImplThread()); 177 DCHECK(proxy_->IsImplThread());
173 didVisibilityChange(this, m_visible); 178 DidVisibilityChange(this, visible_);
174 179
175 setDebugState(settings.initialDebugState); 180 SetDebugState(settings.initialDebugState);
176 181
177 if (settings.calculateTopControlsPosition) { 182 if (settings.calculateTopControlsPosition) {
178 m_topControlsManager = TopControlsManager::Create(this, 183 top_controls_manager_ =
179 settings.topControlsHe ight, 184 TopControlsManager::Create(this,
180 settings.topControlsSh owThreshold, 185 settings.topControlsHeight,
181 settings.topControlsHi deThreshold); 186 settings.topControlsShowThreshold,
182 } 187 settings.topControlsHideThreshold);
183 188 }
184 setDebugState(settings.initialDebugState); 189
185 190 SetDebugState(settings.initialDebugState);
186 // LTHI always has an active tree. 191
187 m_activeTree = LayerTreeImpl::create(this); 192 // LTHI always has an active tree.
188 } 193 active_tree_ = LayerTreeImpl::create(this);
189 194 }
190 LayerTreeHostImpl::~LayerTreeHostImpl() 195
191 { 196 LayerTreeHostImpl::~LayerTreeHostImpl() {
192 DCHECK(m_proxy->IsImplThread()); 197 DCHECK(proxy_->IsImplThread());
193 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()"); 198 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
194 199
195 if (rootLayer()) { 200 if (active_tree_->root_layer()) {
196 clearRenderSurfaces(); 201 ClearRenderSurfaces();
197 // The layer trees must be destroyed before the layer tree host. We've 202 // The layer trees must be destroyed before the layer tree host. We've
198 // made a contract with our animation controllers that the registrar 203 // made a contract with our animation controllers that the registrar
199 // will outlive them, and we must make good. 204 // will outlive them, and we must make good.
200 m_recycleTree.reset(); 205 recycle_tree_.reset();
201 m_pendingTree.reset(); 206 pending_tree_.reset();
202 m_activeTree.reset(); 207 active_tree_.reset();
203 } 208 }
204 } 209 }
205 210
206 void LayerTreeHostImpl::beginCommit() 211 void LayerTreeHostImpl::BeginCommit() {}
207 { 212
208 } 213 void LayerTreeHostImpl::CommitComplete() {
209 214 TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete");
210 void LayerTreeHostImpl::commitComplete() 215
211 { 216 // Impl-side painting needs an update immediately post-commit to have the
212 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete"); 217 // opportunity to create tilings. Other paths can call UpdateDrawProperties
213 218 // more lazily when needed prior to drawing.
214 // Impl-side painting needs an update immediately post-commit to have the 219 if (settings_.implSidePainting) {
215 // opportunity to create tilings. Other paths can call updateDrawProperties 220 pending_tree_->set_needs_update_draw_properties();
216 // more lazily when needed prior to drawing. 221 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE);
217 if (m_settings.implSidePainting) { 222 } else {
218 pendingTree()->set_needs_update_draw_properties(); 223 active_tree_->set_needs_update_draw_properties();
219 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); 224 }
220 } else { 225
221 activeTree()->set_needs_update_draw_properties(); 226 client_->SendManagedMemoryStats();
222 } 227 }
223 228
224 m_client->sendManagedMemoryStats(); 229 bool LayerTreeHostImpl::CanDraw() {
225 } 230 // Note: If you are changing this function or any other function that might
226 231 // affect the result of CanDraw, make sure to call
227 bool LayerTreeHostImpl::canDraw() 232 // client_->OnCanDrawStateChanged in the proper places and update the
228 { 233 // NotifyIfCanDrawChanged test.
229 // Note: If you are changing this function or any other function that might 234
230 // affect the result of canDraw, make sure to call m_client->onCanDrawStateC hanged 235 if (!active_tree_->root_layer()) {
231 // in the proper places and update the notifyIfCanDrawChanged test. 236 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no root layer");
232
233 if (!rootLayer()) {
234 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
235 return false;
236 }
237 if (DeviceViewportSize().IsEmpty()) {
238 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
239 return false;
240 }
241 if (m_activeTree->ViewportSizeInvalid()) {
242 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw viewport size rec ently changed");
243 return false;
244 }
245 if (!m_renderer) {
246 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
247 return false;
248 }
249 if (m_activeTree->ContentsTexturesPurged()) {
250 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
251 return false;
252 }
253 return true;
254 }
255
256 OutputSurface* LayerTreeHostImpl::outputSurface() const
257 {
258 return m_outputSurface.get();
259 }
260
261 void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallCl ockTime)
262 {
263 animatePageScale(monotonicTime);
264 animateLayers(monotonicTime, wallClockTime);
265 animateScrollbars(monotonicTime);
266 if (m_topControlsManager)
267 m_topControlsManager->Animate(monotonicTime);
268 }
269
270 void LayerTreeHostImpl::manageTiles()
271 {
272 DCHECK(m_tileManager);
273 m_tileManager->ManageTiles();
274
275 size_t memoryRequiredBytes;
276 size_t memoryNiceToHaveBytes;
277 size_t memoryUsedBytes;
278 m_tileManager->GetMemoryStats(&memoryRequiredBytes,
279 &memoryNiceToHaveBytes,
280 &memoryUsedBytes);
281 sendManagedMemoryStats(memoryRequiredBytes,
282 memoryNiceToHaveBytes,
283 memoryUsedBytes);
284 }
285
286 void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta durati on)
287 {
288 if (!rootScrollLayer())
289 return;
290
291 gfx::Vector2dF scrollTotal = rootScrollLayer()->scroll_offset() + rootScroll Layer()->scroll_delta();
292 gfx::SizeF scaledScrollableSize = activeTree()->ScrollableSize();
293 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceS caleFactor);
294
295 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF();
296 m_pageScaleAnimation = PageScaleAnimation::Create(scrollTotal, activeTree()- >total_page_scale_factor(), viewportSize, scaledScrollableSize, startTimeSeconds );
297
298 if (anchorPoint) {
299 gfx::Vector2dF anchor(targetOffset);
300 m_pageScaleAnimation->ZoomWithAnchor(anchor, pageScale, duration.InSecon dsF());
301 } else {
302 gfx::Vector2dF scaledTargetOffset = targetOffset;
303 m_pageScaleAnimation->ZoomTo(scaledTargetOffset, pageScale, duration.InS econdsF());
304 }
305
306 m_client->setNeedsRedrawOnImplThread();
307 m_client->setNeedsCommitOnImplThread();
308 m_client->renewTreePriority();
309 }
310
311 void LayerTreeHostImpl::scheduleAnimation()
312 {
313 m_client->setNeedsRedrawOnImplThread();
314 }
315
316 bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point& viewportPoint )
317 {
318 if (!ensureRenderSurfaceLayerList())
319 return false;
320
321 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceSca leFactor);
322
323 // First find out which layer was hit from the saved list of visible layers
324 // in the most recent frame.
325 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(device ViewportPoint, activeTree()->RenderSurfaceLayerList());
326
327 // Walk up the hierarchy and look for a layer with a touch event handler reg ion that the given point hits.
328 for (; layerImpl; layerImpl = layerImpl->parent()) {
329 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(deviceViewportPoint, layerImpl))
330 return true;
331 }
332
333 return false; 237 return false;
334 } 238 }
335 239 if (device_viewport_size_.IsEmpty()) {
336 void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, cons t LayerList& renderSurfaceLayerList) 240 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport");
337 { 241 return false;
338 // For now, we use damage tracking to compute a global scissor. To do this, we must 242 }
339 // compute all damage tracking before drawing anything, so that we know the root 243 if (active_tree_->ViewportSizeInvalid()) {
340 // damage rect. The root damage rect is then used to scissor each surface. 244 TRACE_EVENT_INSTANT0(
341 245 "cc", "LayerTreeHostImpl::CanDraw viewport size recently changed");
342 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { 246 return false;
343 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; 247 }
344 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->render_surface(); 248 if (!renderer_) {
345 DCHECK(renderSurface); 249 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no renderer");
346 renderSurface->damage_tracker()->UpdateDamageTrackingState(renderSurface ->layer_list(), renderSurfaceLayer->id(), renderSurface->SurfacePropertyChangedO nlyFromDescendant(), renderSurface->content_rect(), renderSurfaceLayer->mask_lay er(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter().get()); 250 return false;
347 } 251 }
348 } 252 if (active_tree_->ContentsTexturesPurged()) {
349 253 TRACE_EVENT_INSTANT0(
350 void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> rende rPass) 254 "cc", "LayerTreeHostImpl::CanDraw contents textures purged");
351 { 255 return false;
352 renderPassesById[renderPass->id] = renderPass.get(); 256 }
353 renderPasses.push_back(renderPass.Pass()); 257 return true;
354 } 258 }
355 259
356 static void appendQuadsForLayer(RenderPass* targetRenderPass, LayerImpl* layer, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData) 260 void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time,
357 { 261 base::Time wall_clock_time) {
358 bool forSurface = false; 262 AnimatePageScale(monotonic_time);
359 QuadCuller quadCuller(targetRenderPass->quad_list, 263 AnimateLayers(monotonic_time, wall_clock_time);
360 targetRenderPass->shared_quad_state_list, 264 AnimateScrollbars(monotonic_time);
361 layer, 265 if (top_controls_manager_)
362 occlusionTracker, 266 top_controls_manager_->Animate(monotonic_time);
363 layer->ShowDebugBorders(), 267 }
364 forSurface); 268
365 layer->AppendQuads(&quadCuller, &appendQuadsData); 269 void LayerTreeHostImpl::ManageTiles() {
366 } 270 DCHECK(tile_manager_);
367 271 tile_manager_->ManageTiles();
368 static void appendQuadsForRenderSurfaceLayer(RenderPass* targetRenderPass, Layer Impl* layer, const RenderPass* contributingRenderPass, OcclusionTrackerImpl& occ lusionTracker, AppendQuadsData& appendQuadsData) 272
369 { 273 size_t memory_required_bytes;
370 bool forSurface = true; 274 size_t memory_nice_to_have_bytes;
371 QuadCuller quadCuller(targetRenderPass->quad_list, 275 size_t memory_used_bytes;
372 targetRenderPass->shared_quad_state_list, 276 tile_manager_->GetMemoryStats(&memory_required_bytes,
373 layer, 277 &memory_nice_to_have_bytes,
374 occlusionTracker, 278 &memory_used_bytes);
375 layer->ShowDebugBorders(), 279 SendManagedMemoryStats(memory_required_bytes,
376 forSurface); 280 memory_nice_to_have_bytes,
377 281 memory_used_bytes);
378 bool isReplica = false; 282 }
379 layer->render_surface()->AppendQuads(&quadCuller, 283
380 &appendQuadsData, 284 void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset,
381 isReplica, 285 bool anchor_point,
382 contributingRenderPass->id); 286 float page_scale,
383 287 base::TimeTicks start_time,
384 // Add replica after the surface so that it appears below the surface. 288 base::TimeDelta duration) {
385 if (layer->has_replica()) { 289 if (!RootScrollLayer())
386 isReplica = true; 290 return;
387 layer->render_surface()->AppendQuads(&quadCuller, 291
388 &appendQuadsData, 292 gfx::Vector2dF scroll_total =
389 isReplica, 293 RootScrollLayer()->scroll_offset() + RootScrollLayer()->scroll_delta();
390 contributingRenderPass->id); 294 gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
391 } 295 gfx::SizeF viewport_size =
392 } 296 gfx::ScaleSize(device_viewport_size_, 1.f / device_scale_factor_);
393 297
394 static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* roo tLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTrac ker) 298 double start_time_seconds = (start_time - base::TimeTicks()).InSecondsF();
395 { 299 page_scale_animation_ =
396 if (!rootLayer || !SkColorGetA(screenBackgroundColor)) 300 PageScaleAnimation::Create(scroll_total,
397 return; 301 active_tree_->total_page_scale_factor(),
398 302 viewport_size,
399 Region fillRegion = occlusionTracker.ComputeVisibleRegionInScreen(); 303 scaled_scrollable_size,
400 if (fillRegion.IsEmpty()) 304 start_time_seconds);
401 return; 305
402 306 if (anchor_point) {
403 bool forSurface = false; 307 gfx::Vector2dF anchor(target_offset);
404 QuadCuller quadCuller(targetRenderPass->quad_list, 308 page_scale_animation_->ZoomWithAnchor(anchor,
405 targetRenderPass->shared_quad_state_list, 309 page_scale,
406 rootLayer, 310 duration.InSecondsF());
407 occlusionTracker, 311 } else {
408 rootLayer->ShowDebugBorders(), 312 gfx::Vector2dF scaled_target_offset = target_offset;
409 forSurface); 313 page_scale_animation_->ZoomTo(scaled_target_offset,
410 314 page_scale,
411 // Manually create the quad state for the gutter quads, as the root layer 315 duration.InSecondsF());
412 // doesn't have any bounds and so can't generate this itself. 316 }
413 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas). 317
414 318 client_->SetNeedsRedrawOnImplThread();
415 gfx::Rect rootTargetRect = rootLayer->render_surface()->content_rect(); 319 client_->SetNeedsCommitOnImplThread();
416 float opacity = 1; 320 client_->RenewTreePriority();
417 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadS tate::Create()); 321 }
418 sharedQuadState->SetAll(rootLayer->draw_transform(), 322
419 rootTargetRect.size(), 323 void LayerTreeHostImpl::ScheduleAnimation() {
420 rootTargetRect, 324 client_->SetNeedsRedrawOnImplThread();
421 rootTargetRect, 325 }
326
327 bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) {
328 if (!EnsureRenderSurfaceLayerList())
329 return false;
330
331 gfx::PointF device_viewport_point =
332 gfx::ScalePoint(viewport_point, device_scale_factor_);
333
334 // First find out which layer was hit from the saved list of visible layers
335 // in the most recent frame.
336 LayerImpl* layer_impl = LayerTreeHostCommon::findLayerThatIsHitByPoint(
337 device_viewport_point,
338 active_tree_->RenderSurfaceLayerList());
339
340 // Walk up the hierarchy and look for a layer with a touch event handler
341 // region that the given point hits.
342 for (; layer_impl; layer_impl = layer_impl->parent()) {
343 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(device_viewport_point,
344 layer_impl))
345 return true;
346 }
347
348 return false;
349 }
350
351 void LayerTreeHostImpl::TrackDamageForAllSurfaces(
352 LayerImpl* root_draw_layer,
353 const LayerList& render_surface_layer_list) {
354 // For now, we use damage tracking to compute a global scissor. To do this, we
355 // must compute all damage tracking before drawing anything, so that we know
356 // the root damage rect. The root damage rect is then used to scissor each
357 // surface.
358
359 for (int surface_index = render_surface_layer_list.size() - 1;
360 surface_index >= 0 ;
361 --surface_index) {
362 LayerImpl* render_surface_layer = render_surface_layer_list[surface_index];
363 RenderSurfaceImpl* render_surface = render_surface_layer->render_surface();
364 DCHECK(render_surface);
365 render_surface->damage_tracker()->UpdateDamageTrackingState(
366 render_surface->layer_list(),
367 render_surface_layer->id(),
368 render_surface->SurfacePropertyChangedOnlyFromDescendant(),
369 render_surface->content_rect(),
370 render_surface_layer->mask_layer(),
371 render_surface_layer->filters(),
372 render_surface_layer->filter().get());
373 }
374 }
375
376 void LayerTreeHostImpl::FrameData::AppendRenderPass(
377 scoped_ptr<RenderPass> render_pass) {
378 render_passes_by_id[render_pass->id] = render_pass.get();
379 render_passes.push_back(render_pass.Pass());
380 }
381
382 static void AppendQuadsForLayer(RenderPass* target_render_pass,
383 LayerImpl* layer,
384 const OcclusionTrackerImpl& occlusion_tracker,
385 AppendQuadsData* append_quads_data) {
386 bool for_surface = false;
387 QuadCuller quad_culler(target_render_pass->quad_list,
388 target_render_pass->shared_quad_state_list,
389 layer,
390 occlusion_tracker,
391 layer->ShowDebugBorders(),
392 for_surface);
393 layer->AppendQuads(&quad_culler, append_quads_data);
394 }
395
396 static void AppendQuadsForRenderSurfaceLayer(
397 RenderPass* target_render_pass,
398 LayerImpl* layer,
399 const RenderPass* contributing_render_pass,
400 const OcclusionTrackerImpl& occlusion_tracker,
401 AppendQuadsData* append_quads_data) {
402 bool for_surface = true;
403 QuadCuller quad_culler(target_render_pass->quad_list,
404 target_render_pass->shared_quad_state_list,
405 layer,
406 occlusion_tracker,
407 layer->ShowDebugBorders(),
408 for_surface);
409
410 bool is_replica = false;
411 layer->render_surface()->AppendQuads(&quad_culler,
412 append_quads_data,
413 is_replica,
414 contributing_render_pass->id);
415
416 // Add replica after the surface so that it appears below the surface.
417 if (layer->has_replica()) {
418 is_replica = true;
419 layer->render_surface()->AppendQuads(&quad_culler,
420 append_quads_data,
421 is_replica,
422 contributing_render_pass->id);
423 }
424 }
425
426 static void AppendQuadsToFillScreen(
427 RenderPass* target_render_pass,
428 LayerImpl* root_layer,
429 SkColor screen_background_color,
430 const OcclusionTrackerImpl& occlusion_tracker) {
431 if (!root_layer || !SkColorGetA(screen_background_color))
432 return;
433
434 Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen();
435 if (fill_region.IsEmpty())
436 return;
437
438 bool for_surface = false;
439 QuadCuller quad_culler(target_render_pass->quad_list,
440 target_render_pass->shared_quad_state_list,
441 root_layer,
442 occlusion_tracker,
443 root_layer->ShowDebugBorders(),
444 for_surface);
445
446 // Manually create the quad state for the gutter quads, as the root layer
447 // doesn't have any bounds and so can't generate this itself.
448 // TODO(danakj): Make the gutter quads generated by the solid color layer
449 // (make it smarter about generating quads to fill unoccluded areas).
450
451 gfx::Rect root_target_rect = root_layer->render_surface()->content_rect();
452 float opacity = 1.f;
453 SharedQuadState* shared_quad_state =
454 quad_culler.useSharedQuadState(SharedQuadState::Create());
455 shared_quad_state->SetAll(root_layer->draw_transform(),
456 root_target_rect.size(),
457 root_target_rect,
458 root_target_rect,
422 false, 459 false,
423 opacity); 460 opacity);
424 461
425 AppendQuadsData appendQuadsData; 462 AppendQuadsData append_quads_data;
426 463
427 gfx::Transform transformToLayerSpace(gfx::Transform::kSkipInitialization); 464 gfx::Transform transform_to_layer_space(gfx::Transform::kSkipInitialization);
428 bool didInvert = rootLayer->screen_space_transform().GetInverse(&transformTo LayerSpace); 465 bool did_invert = root_layer->screen_space_transform().GetInverse(
429 DCHECK(didInvert); 466 &transform_to_layer_space);
430 for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects .next()) { 467 DCHECK(did_invert);
431 // The root layer transform is composed of translations and scales only, 468 for (Region::Iterator fill_rects(fill_region);
432 // no perspective, so mapping is sufficient (as opposed to projecting). 469 fill_rects.has_rect();
433 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fi llRects.rect()); 470 fill_rects.next()) {
434 // Skip the quad culler and just append the quads directly to avoid 471 // The root layer transform is composed of translations and scales only,
435 // occlusion checks. 472 // no perspective, so mapping is sufficient (as opposed to projecting).
436 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); 473 gfx::Rect layer_rect =
437 quad->SetNew(sharedQuadState, layerRect, screenBackgroundColor); 474 MathUtil::mapClippedRect(transform_to_layer_space, fill_rects.rect());
438 quadCuller.append(quad.PassAs<DrawQuad>(), &appendQuadsData); 475 // Skip the quad culler and just append the quads directly to avoid
476 // occlusion checks.
477 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
478 quad->SetNew(shared_quad_state, layer_rect, screen_background_color);
479 quad_culler.append(quad.PassAs<DrawQuad>(), &append_quads_data);
480 }
481 }
482
483 bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
484 DCHECK(frame->render_passes.empty());
485
486 if (!CanDraw() || !active_tree_->root_layer())
487 return false;
488
489 TrackDamageForAllSurfaces(active_tree_->root_layer(),
490 *frame->render_surface_layer_list);
491
492 TRACE_EVENT1("cc",
493 "LayerTreeHostImpl::CalculateRenderPasses",
494 "render_surface_layer_list.size()",
495 static_cast<long long unsigned>(
496 frame->render_surface_layer_list->size()));
497
498 // Create the render passes in dependency order.
499 for (int surface_index = frame->render_surface_layer_list->size() - 1;
500 surface_index >= 0 ;
501 --surface_index) {
502 LayerImpl* render_surface_layer =
503 (*frame->render_surface_layer_list)[surface_index];
504 render_surface_layer->render_surface()->AppendRenderPasses(frame);
505 }
506
507 bool record_metrics_for_frame =
508 settings_.showOverdrawInTracing &&
509 base::debug::TraceLog::GetInstance() &&
510 base::debug::TraceLog::GetInstance()->IsEnabled();
511 OcclusionTrackerImpl occlusion_tracker(
512 active_tree_->root_layer()->render_surface()->content_rect(),
513 record_metrics_for_frame);
514 occlusion_tracker.set_minimum_tracking_size(
515 settings_.minimumOcclusionTrackingSize);
516
517 if (debug_state_.showOccludingRects) {
518 occlusion_tracker.set_occluding_screen_space_rects_container(
519 &frame->occluding_screen_space_rects);
520 }
521 if (debug_state_.showNonOccludingRects) {
522 occlusion_tracker.set_non_occluding_screen_space_rects_container(
523 &frame->non_occluding_screen_space_rects);
524 }
525
526 // Add quads to the Render passes in FrontToBack order to allow for testing
527 // occlusion and performing culling during the tree walk.
528 typedef LayerIterator<LayerImpl,
529 std::vector<LayerImpl*>,
530 RenderSurfaceImpl,
531 LayerIteratorActions::FrontToBack> LayerIteratorType;
532
533 // Typically when we are missing a texture and use a checkerboard quad, we
534 // still draw the frame. However when the layer being checkerboarded is moving
535 // due to an impl-animation, we drop the frame to avoid flashing due to the
536 // texture suddenly appearing in the future.
537 bool draw_frame = true;
538
539 LayerIteratorType end =
540 LayerIteratorType::end(frame->render_surface_layer_list);
541 for (LayerIteratorType it =
542 LayerIteratorType::begin(frame->render_surface_layer_list);
543 it != end;
544 ++it) {
545 RenderPass::Id target_render_pass_id =
546 it.targetRenderSurfaceLayer()->render_surface()->RenderPassId();
547 RenderPass* target_render_pass =
548 frame->render_passes_by_id[target_render_pass_id];
549
550 occlusion_tracker.EnterLayer(it);
551
552 AppendQuadsData append_quads_data(target_render_pass->id);
553
554 if (it.representsContributingRenderSurface()) {
555 RenderPass::Id contributing_render_pass_id =
556 it->render_surface()->RenderPassId();
557 RenderPass* contributing_render_pass =
558 frame->render_passes_by_id[contributing_render_pass_id];
559 AppendQuadsForRenderSurfaceLayer(target_render_pass,
560 *it,
561 contributing_render_pass,
562 occlusion_tracker,
563 &append_quads_data);
564 } else if (it.representsItself() && !it->visible_content_rect().IsEmpty()) {
565 bool has_occlusion_from_outside_target_surface;
566 bool impl_draw_transform_is_unknown = false;
567 if (occlusion_tracker.Occluded(
568 it->render_target(),
569 it->visible_content_rect(),
570 it->draw_transform(),
571 impl_draw_transform_is_unknown,
572 it->is_clipped(),
573 it->clip_rect(),
574 &has_occlusion_from_outside_target_surface)) {
575 append_quads_data.hadOcclusionFromOutsideTargetSurface |=
576 has_occlusion_from_outside_target_surface;
577 } else {
578 DCHECK_EQ(active_tree_, it->layer_tree_impl());
579 it->WillDraw(resource_provider_.get());
580 frame->will_draw_layers.push_back(*it);
581
582 if (it->HasContributingDelegatedRenderPasses()) {
583 RenderPass::Id contributing_render_pass_id =
584 it->FirstContributingRenderPassId();
585 while (frame->render_passes_by_id.find(contributing_render_pass_id) !=
586 frame->render_passes_by_id.end()) {
587 RenderPass* render_pass =
588 frame->render_passes_by_id[contributing_render_pass_id];
589
590 AppendQuadsData append_quads_data(render_pass->id);
591 AppendQuadsForLayer(render_pass,
592 *it,
593 occlusion_tracker,
594 &append_quads_data);
595
596 contributing_render_pass_id =
597 it->NextContributingRenderPassId(contributing_render_pass_id);
598 }
599 }
600
601 AppendQuadsForLayer(target_render_pass,
602 *it,
603 occlusion_tracker,
604 &append_quads_data);
605 }
606
607 ++cumulative_num_layers_drawn_;
439 } 608 }
440 } 609
441 610 if (append_quads_data.hadOcclusionFromOutsideTargetSurface)
442 bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame) 611 target_render_pass->has_occlusion_from_outside_target_surface = true;
443 { 612
444 DCHECK(frame.renderPasses.empty()); 613 if (append_quads_data.numMissingTiles) {
445 614 cumulative_num_missing_tiles_ += append_quads_data.numMissingTiles;
446 if (!canDraw() || !rootLayer()) 615 bool layer_has_animating_transform =
616 it->screen_space_transform_is_animating() ||
617 it->draw_transform_is_animating();
618 if (layer_has_animating_transform)
619 draw_frame = false;
620 }
621
622 if (append_quads_data.hadIncompleteTile)
623 frame->contains_incomplete_tile = true;
624
625 occlusion_tracker.LeaveLayer(it);
626 }
627
628 #ifndef NDEBUG
629 for (size_t i = 0; i < frame->render_passes.size(); ++i) {
630 for (size_t j = 0; j < frame->render_passes[i]->quad_list.size(); ++j)
631 DCHECK(frame->render_passes[i]->quad_list[j]->shared_quad_state);
632 DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id)
633 != frame->render_passes_by_id.end());
634 }
635 #endif
636 DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin());
637
638 if (!active_tree_->has_transparent_background()) {
639 frame->render_passes.back()->has_transparent_background = false;
640 AppendQuadsToFillScreen(frame->render_passes.back(),
641 active_tree_->root_layer(),
642 active_tree_->background_color(),
643 occlusion_tracker);
644 }
645
646 if (draw_frame)
647 occlusion_tracker.overdraw_metrics()->RecordMetrics(this);
648
649 RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame);
650 renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes);
651 RemoveRenderPasses(CullRenderPassesWithCachedTextures(*renderer_), frame);
652
653 return draw_frame;
654 }
655
656 void LayerTreeHostImpl::SetBackgroundTickingEnabled(bool enabled) {
657 // Lazily create the time_source adapter so that we can vary the interval for
658 // testing.
659 if (!time_source_client_adapter_) {
660 time_source_client_adapter_ = LayerTreeHostImplTimeSourceAdapter::Create(
661 this,
662 DelayBasedTimeSource::create(LowFrequencyAnimationInterval(),
663 proxy_->CurrentThread()));
664 }
665
666 time_source_client_adapter_->SetActive(enabled);
667 }
668
669 static inline RenderPass* FindRenderPassById(
670 RenderPass::Id render_pass_id,
671 const LayerTreeHostImpl::FrameData& frame) {
672 RenderPassIdHashMap::const_iterator it =
673 frame.render_passes_by_id.find(render_pass_id);
674 return it != frame.render_passes_by_id.end() ? it->second : NULL;
675 }
676
677 static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id,
678 LayerTreeHostImpl::FrameData* frame) {
679 RenderPass* remove_render_pass =
680 FindRenderPassById(remove_render_pass_id, *frame);
681 // The pass was already removed by another quad - probably the original, and
682 // we are the replica.
683 if (!remove_render_pass)
684 return;
685 RenderPassList& render_passes = frame->render_passes;
686 RenderPassList::iterator to_remove = std::find(render_passes.begin(),
687 render_passes.end(),
688 remove_render_pass);
689
690 DCHECK(to_remove != render_passes.end());
691
692 scoped_ptr<RenderPass> removed_pass = render_passes.take(to_remove);
693 frame->render_passes.erase(to_remove);
694 frame->render_passes_by_id.erase(remove_render_pass_id);
695
696 // Now follow up for all RenderPass quads and remove their RenderPasses
697 // recursively.
698 const QuadList& quad_list = removed_pass->quad_list;
699 QuadList::constBackToFrontIterator quad_list_iterator =
700 quad_list.backToFrontBegin();
701 for (; quad_list_iterator != quad_list.backToFrontEnd();
702 ++quad_list_iterator) {
703 DrawQuad* current_quad = (*quad_list_iterator);
704 if (current_quad->material != DrawQuad::RENDER_PASS)
705 continue;
706
707 RenderPass::Id next_remove_render_pass_id =
708 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id;
709 RemoveRenderPassesRecursive(next_remove_render_pass_id, frame);
710 }
711 }
712
713 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::
714 ShouldRemoveRenderPass(const RenderPassDrawQuad& quad,
715 const FrameData& frame) const {
716 bool quad_has_damage = !quad.contents_changed_since_last_frame.IsEmpty();
717 bool quad_has_cached_resource =
718 renderer_.HaveCachedResourcesForRenderPassId(quad.render_pass_id);
719 if (quad_has_damage) {
720 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
721 return false;
722 } else if (!quad_has_cached_resource) {
723 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
724 return false;
725 }
726 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
727 return true;
728 }
729
730 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass(
731 const RenderPassDrawQuad& quad, const FrameData& frame) const {
732 const RenderPass* render_pass =
733 FindRenderPassById(quad.render_pass_id, frame);
734 if (!render_pass)
735 return false;
736
737 // If any quad or RenderPass draws into this RenderPass, then keep it.
738 const QuadList& quad_list = render_pass->quad_list;
739 for (QuadList::constBackToFrontIterator quad_list_iterator =
740 quad_list.backToFrontBegin();
741 quad_list_iterator != quad_list.backToFrontEnd();
742 ++quad_list_iterator) {
743 DrawQuad* current_quad = *quad_list_iterator;
744
745 if (current_quad->material != DrawQuad::RENDER_PASS)
447 return false; 746 return false;
448 747
449 trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList); 748 const RenderPass* contributing_pass = FindRenderPassById(
450 749 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id, frame);
451 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfac eLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList ->size())); 750 if (contributing_pass)
452 751 return false;
453 // Create the render passes in dependency order. 752 }
454 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceInd ex >= 0 ; --surfaceIndex) { 753 return true;
455 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceI ndex]; 754 }
456 renderSurfaceLayer->render_surface()->AppendRenderPasses(&frame); 755
756 // Defined for linking tests.
757 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
758 LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(
759 CullRenderPassesWithCachedTextures culler, FrameData* frame);
760 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
761 LayerTreeHostImpl::CullRenderPassesWithNoQuads>(
762 CullRenderPassesWithNoQuads culler, FrameData*);
763
764 // static
765 template <typename RenderPassCuller>
766 void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler,
767 FrameData* frame) {
768 for (size_t it = culler.RenderPassListBegin(frame->render_passes);
769 it != culler.RenderPassListEnd(frame->render_passes);
770 it = culler.RenderPassListNext(it)) {
771 const RenderPass* current_pass = frame->render_passes[it];
772 const QuadList& quad_list = current_pass->quad_list;
773 QuadList::constBackToFrontIterator quad_list_iterator =
774 quad_list.backToFrontBegin();
775
776 for (; quad_list_iterator != quad_list.backToFrontEnd();
777 ++quad_list_iterator) {
778 DrawQuad* current_quad = *quad_list_iterator;
779
780 if (current_quad->material != DrawQuad::RENDER_PASS)
781 continue;
782
783 const RenderPassDrawQuad* render_pass_quad =
784 RenderPassDrawQuad::MaterialCast(current_quad);
785 if (!culler.ShouldRemoveRenderPass(*render_pass_quad, *frame))
786 continue;
787
788 // We are changing the vector in the middle of iteration. Because we
789 // delete render passes that draw into the current pass, we are
790 // guaranteed that any data from the iterator to the end will not
791 // change. So, capture the iterator position from the end of the
792 // list, and restore it after the change.
793 size_t position_from_end = frame->render_passes.size() - it;
794 RemoveRenderPassesRecursive(render_pass_quad->render_pass_id, frame);
795 it = frame->render_passes.size() - position_from_end;
796 DCHECK_GE(frame->render_passes.size(), position_from_end);
457 } 797 }
458 798 }
459 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug ::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled(); 799 }
460 OcclusionTrackerImpl occlusionTracker(rootLayer()->render_surface()->content _rect(), recordMetricsForFrame); 800
461 occlusionTracker.set_minimum_tracking_size(m_settings.minimumOcclusionTracki ngSize); 801 bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
462 802 TRACE_EVENT0("cc", "LayerTreeHostImpl::PrepareToDraw");
463 if (m_debugState.showOccludingRects) 803
464 occlusionTracker.set_occluding_screen_space_rects_container(&frame.occlu dingScreenSpaceRects); 804 active_tree_->UpdateDrawProperties(
465 if (m_debugState.showNonOccludingRects) 805 LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRAW);
466 occlusionTracker.set_non_occluding_screen_space_rects_container(&frame.n onOccludingScreenSpaceRects); 806
467 807 frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList();
468 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk. 808 frame->render_passes.clear();
469 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType; 809 frame->render_passes_by_id.clear();
470 810 frame->will_draw_layers.clear();
471 // Typically when we are missing a texture and use a checkerboard quad, we s till draw the frame. However when the layer being 811
472 // checkerboarded is moving due to an impl-animation, we drop the frame to a void flashing due to the texture suddenly appearing 812 if (!CalculateRenderPasses(frame))
473 // in the future. 813 return false;
474 bool drawFrame = true; 814
475 815 // If we return true, then we expect DrawLayers() to be called before this
476 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList) ; 816 // function is called again.
477 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLaye rList); it != end; ++it) { 817 return true;
478 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->rende r_surface()->RenderPassId(); 818 }
479 RenderPass* targetRenderPass = frame.renderPassesById[targetRenderPassId ]; 819
480 820 void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
481 occlusionTracker.EnterLayer(it); 821 const ManagedMemoryPolicy& policy) {
482 822 bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread(
483 AppendQuadsData appendQuadsData(targetRenderPass->id); 823 visible_ ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
484 824 ManagedMemoryPolicy::priorityCutoffToValue(
485 if (it.representsContributingRenderSurface()) { 825 visible_ ?
486 RenderPass::Id contributingRenderPassId = it->render_surface()->Rend erPassId(); 826 policy.priorityCutoffWhenVisible :
487 RenderPass* contributingRenderPass = frame.renderPassesById[contribu tingRenderPassId]; 827 policy.priorityCutoffWhenNotVisible));
488 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributing RenderPass, occlusionTracker, appendQuadsData); 828 if (evicted_resources) {
489 } else if (it.representsItself() && !it->visible_content_rect().IsEmpty( )) { 829 active_tree_->SetContentsTexturesPurged();
490 bool hasOcclusionFromOutsideTargetSurface; 830 if (pending_tree_)
491 bool implDrawTransformIsUnknown = false; 831 pending_tree_->SetContentsTexturesPurged();
492 if (occlusionTracker.Occluded(it->render_target(), it->visible_conte nt_rect(), it->draw_transform(), implDrawTransformIsUnknown, it->is_clipped(), i t->clip_rect(), &hasOcclusionFromOutsideTargetSurface)) 832 client_->SetNeedsCommitOnImplThread();
493 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclu sionFromOutsideTargetSurface; 833 client_->OnCanDrawStateChanged(CanDraw());
494 else { 834 client_->RenewTreePriority();
495 DCHECK_EQ(activeTree(), it->layer_tree_impl()); 835 }
496 it->WillDraw(m_resourceProvider.get()); 836 client_->SendManagedMemoryStats();
497 frame.willDrawLayers.push_back(*it); 837
498 838 if (tile_manager_) {
499 if (it->HasContributingDelegatedRenderPasses()) { 839 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
500 RenderPass::Id contributingRenderPassId = it->FirstContribut ingRenderPassId(); 840 new_state.memory_limit_in_bytes = visible_ ?
501 while (frame.renderPassesById.find(contributingRenderPassId) != frame.renderPassesById.end()) { 841 policy.bytesLimitWhenVisible :
502 RenderPass* renderPass = frame.renderPassesById[contribu tingRenderPassId]; 842 policy.bytesLimitWhenNotVisible;
503 843 new_state.memory_limit_policy =
504 AppendQuadsData appendQuadsData(renderPass->id); 844 ManagedMemoryPolicy::priorityCutoffToTileMemoryLimitPolicy(
505 appendQuadsForLayer(renderPass, *it, occlusionTracker, a ppendQuadsData); 845 visible_ ?
506 846 policy.priorityCutoffWhenVisible :
507 contributingRenderPassId = it->NextContributingRenderPas sId(contributingRenderPassId); 847 policy.priorityCutoffWhenNotVisible);
508 } 848 tile_manager_->SetGlobalState(new_state);
509 } 849 }
510 850 }
511 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, app endQuadsData); 851
512 } 852 bool LayerTreeHostImpl::HasImplThread() const {
513 853 return proxy_->HasImplThread();
514 ++m_cumulativeNumLayersDrawn; 854 }
515 } 855
516 856 void LayerTreeHostImpl::ScheduleManageTiles() {
517 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface) 857 if (client_)
518 targetRenderPass->has_occlusion_from_outside_target_surface = true; 858 client_->SetNeedsManageTilesOnImplThread();
519 859 }
520 if (appendQuadsData.numMissingTiles) { 860
521 m_cumulativeNumMissingTiles += appendQuadsData.numMissingTiles; 861 void LayerTreeHostImpl::DidUploadVisibleHighResolutionTile() {
522 bool layerHasAnimatingTransform = it->screen_space_transform_is_anim ating() || it->draw_transform_is_animating(); 862 if (client_)
523 if (layerHasAnimatingTransform) 863 client_->DidUploadVisibleHighResolutionTileOnImplThread();
524 drawFrame = false; 864 }
525 } 865
526 866 bool LayerTreeHostImpl::ShouldClearRootRenderPass() const {
527 if (appendQuadsData.hadIncompleteTile) 867 return settings_.shouldClearRootRenderPass;
528 frame.containsIncompleteTile = true; 868 }
529 869
530 occlusionTracker.LeaveLayer(it); 870 void LayerTreeHostImpl::SetManagedMemoryPolicy(
531 } 871 const ManagedMemoryPolicy& policy) {
532 872 if (managed_memory_policy_ == policy)
533 #ifndef NDEBUG 873 return;
534 for (size_t i = 0; i < frame.renderPasses.size(); ++i) { 874
535 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j) 875 managed_memory_policy_ = policy;
536 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state); 876 if (!proxy_->HasImplThread()) {
537 DCHECK(frame.renderPassesById.find(frame.renderPasses[i]->id) 877 // TODO(ccameron): In single-thread mode, this can be called on the main
538 != frame.renderPassesById.end()); 878 // thread by GLRenderer::OnMemoryAllocationChanged.
539 } 879 DebugScopedSetImplThread impl_thread(proxy_);
540 #endif 880 EnforceManagedMemoryPolicy(managed_memory_policy_);
541 DCHECK(frame.renderPasses.back()->output_rect.origin().IsOrigin()); 881 } else {
542 882 DCHECK(proxy_->IsImplThread());
543 if (!activeTree()->has_transparent_background()) { 883 EnforceManagedMemoryPolicy(managed_memory_policy_);
544 frame.renderPasses.back()->has_transparent_background = false; 884 }
545 appendQuadsToFillScreen(frame.renderPasses.back(), rootLayer(), activeTr ee()->background_color(), occlusionTracker); 885 // We always need to commit after changing the memory policy because the new
546 } 886 // limit can result in more or less content having texture allocated for it.
547 887 client_->SetNeedsCommitOnImplThread();
548 if (drawFrame) 888 }
549 occlusionTracker.overdraw_metrics()->RecordMetrics(this); 889
550 890 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase,
551 removeRenderPasses(CullRenderPassesWithNoQuads(), frame); 891 base::TimeDelta interval) {
552 m_renderer->DecideRenderPassAllocationsForFrame(frame.renderPasses); 892 client_->OnVSyncParametersChanged(timebase, interval);
553 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame); 893 }
554 894
555 return drawFrame; 895 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(
556 } 896 const CompositorFrameAck& ack) {
557 897 if (!renderer_)
558 void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled) 898 return;
559 { 899
560 // Lazily create the timeSource adapter so that we can vary the interval for testing. 900 // TODO(piman): We may need to do some validation on this ack before
561 if (!m_timeSourceClientAdapter) 901 // processing it.
562 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::Create(t his, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->Curr entThread())); 902 renderer_->ReceiveCompositorFrameAck(ack);
563 903 }
564 m_timeSourceClientAdapter->setActive(enabled); 904
565 } 905 void LayerTreeHostImpl::OnCanDrawStateChangedForTree() {
566 906 client_->OnCanDrawStateChanged(CanDraw());
567 static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame) 907 }
568 { 908
569 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderP assId); 909 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
570 return it != frame.renderPassesById.end() ? it->second : NULL; 910 CompositorFrameMetadata metadata;
571 } 911 metadata.device_scale_factor = device_scale_factor_;
572 912 metadata.page_scale_factor = active_tree_->total_page_scale_factor();
573 static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, Layer TreeHostImpl::FrameData& frame) 913 metadata.viewport_size = active_tree_->ScrollableViewportSize();
574 { 914 metadata.root_layer_size = active_tree_->ScrollableSize();
575 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame) ; 915 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
576 // The pass was already removed by another quad - probably the original, and we are the replica. 916 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor();
577 if (!removeRenderPass) 917 if (top_controls_manager_) {
578 return; 918 metadata.location_bar_offset =
579 RenderPassList& renderPasses = frame.renderPasses; 919 gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset());
580 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPa sses.end(), removeRenderPass); 920 metadata.location_bar_content_translation =
581 921 gfx::Vector2dF(0.f, top_controls_manager_->content_top_offset());
582 DCHECK(toRemove != renderPasses.end()); 922 }
583 923
584 scoped_ptr<RenderPass> removedPass = renderPasses.take(toRemove); 924 if (!RootScrollLayer())
585 frame.renderPasses.erase(toRemove);
586 frame.renderPassesById.erase(removeRenderPassId);
587
588 // Now follow up for all RenderPass quads and remove their RenderPasses recu rsively.
589 const QuadList& quadList = removedPass->quad_list;
590 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBe gin();
591 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
592 DrawQuad* currentQuad = (*quadListIterator);
593 if (currentQuad->material != DrawQuad::RENDER_PASS)
594 continue;
595
596 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::MaterialCast (currentQuad)->render_pass_id;
597 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
598 }
599 }
600
601 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPa ss(const RenderPassDrawQuad& quad, const FrameData&) const
602 {
603 if (!quad.contents_changed_since_last_frame.IsEmpty()) {
604 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
605 return false;
606 } else if (!m_renderer.HaveCachedResourcesForRenderPassId(quad.render_pass_i d)) {
607 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture") ;
608 return false;
609 }
610 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
611 return true;
612 }
613
614 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(cons t RenderPassDrawQuad& quad, const FrameData& frame) const
615 {
616 const RenderPass* renderPass = findRenderPassById(quad.render_pass_id, frame );
617 if (!renderPass)
618 return false;
619
620 // If any quad or RenderPass draws into this RenderPass, then keep it.
621 const QuadList& quadList = renderPass->quad_list;
622 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFr ontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
623 DrawQuad* currentQuad = *quadListIterator;
624
625 if (currentQuad->material != DrawQuad::RENDER_PASS)
626 return false;
627
628 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQu ad::MaterialCast(currentQuad)->render_pass_id, frame);
629 if (contributingPass)
630 return false;
631 }
632 return true;
633 }
634
635 // Defined for linking tests.
636 template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl: :CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameDa ta&);
637 template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl: :CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
638
639 // static
640 template<typename RenderPassCuller>
641 void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& f rame)
642 {
643 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culle r.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
644 const RenderPass* currentPass = frame.renderPasses[it];
645 const QuadList& quadList = currentPass->quad_list;
646 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFro ntBegin();
647
648 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator ) {
649 DrawQuad* currentQuad = *quadListIterator;
650
651 if (currentQuad->material != DrawQuad::RENDER_PASS)
652 continue;
653
654 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad* >(currentQuad);
655 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
656 continue;
657
658 // We are changing the vector in the middle of iteration. Because we
659 // delete render passes that draw into the current pass, we are
660 // guaranteed that any data from the iterator to the end will not
661 // change. So, capture the iterator position from the end of the
662 // list, and restore it after the change.
663 int positionFromEnd = frame.renderPasses.size() - it;
664 removeRenderPassesRecursive(renderPassQuad->render_pass_id, frame);
665 it = frame.renderPasses.size() - positionFromEnd;
666 DCHECK(frame.renderPasses.size() >= static_cast<size_t>(positionFrom End));
667 }
668 }
669 }
670
671 bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
672 {
673 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
674
675 activeTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRA W);
676
677 frame.renderSurfaceLayerList = &activeTree()->RenderSurfaceLayerList();
678 frame.renderPasses.clear();
679 frame.renderPassesById.clear();
680 frame.willDrawLayers.clear();
681
682 if (!calculateRenderPasses(frame))
683 return false;
684
685 // If we return true, then we expect drawLayers() to be called before this f unction is called again.
686 return true;
687 }
688
689 void LayerTreeHostImpl::EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& po licy)
690 {
691 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
692 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisib le,
693 ManagedMemoryPolicy::priorityCutoffToValue(
694 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoff WhenNotVisible));
695 if (evictedResources) {
696 activeTree()->SetContentsTexturesPurged();
697 if (pendingTree())
698 pendingTree()->SetContentsTexturesPurged();
699 m_client->setNeedsCommitOnImplThread();
700 m_client->onCanDrawStateChanged(canDraw());
701 m_client->renewTreePriority();
702 }
703 m_client->sendManagedMemoryStats();
704
705 if (m_tileManager) {
706 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState()) ;
707 new_state.memory_limit_in_bytes = m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible;
708 new_state.memory_limit_policy = ManagedMemoryPolicy::priorityCutoffToTileM emoryLimitPolicy(
709 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWh enNotVisible);
710 m_tileManager->SetGlobalState(new_state);
711 }
712 }
713
714 bool LayerTreeHostImpl::HasImplThread() const
715 {
716 return m_proxy->HasImplThread();
717 }
718
719 void LayerTreeHostImpl::ScheduleManageTiles()
720 {
721 if (m_client)
722 m_client->setNeedsManageTilesOnImplThread();
723 }
724
725 void LayerTreeHostImpl::DidUploadVisibleHighResolutionTile()
726 {
727 if (m_client)
728 m_client->didUploadVisibleHighResolutionTileOnImplThread();
729 }
730
731 bool LayerTreeHostImpl::ShouldClearRootRenderPass() const
732 {
733 return m_settings.shouldClearRootRenderPass;
734 }
735
736 void LayerTreeHostImpl::SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy )
737 {
738 if (m_managedMemoryPolicy == policy)
739 return;
740
741 m_managedMemoryPolicy = policy;
742 if (!m_proxy->HasImplThread()) {
743 // FIXME: In single-thread mode, this can be called on the main thread
744 // by GLRenderer::onMemoryAllocationChanged.
745 DebugScopedSetImplThread implThread(m_proxy);
746 EnforceManagedMemoryPolicy(m_managedMemoryPolicy);
747 } else {
748 DCHECK(m_proxy->IsImplThread());
749 EnforceManagedMemoryPolicy(m_managedMemoryPolicy);
750 }
751 // We always need to commit after changing the memory policy because the new
752 // limit can result in more or less content having texture allocated for it.
753 m_client->setNeedsCommitOnImplThread();
754 }
755
756 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, base: :TimeDelta interval)
757 {
758 m_client->onVSyncParametersChanged(timebase, interval);
759 }
760
761 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(const CompositorFrameAc k& ack)
762 {
763 if (!m_renderer)
764 return;
765
766 // TODO(piman): We may need to do some validation on this ack before process ing it.
767 m_renderer->ReceiveCompositorFrameAck(ack);
768 }
769
770 void LayerTreeHostImpl::OnCanDrawStateChangedForTree(LayerTreeImpl*)
771 {
772 m_client->onCanDrawStateChanged(canDraw());
773 }
774
775 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const
776 {
777 CompositorFrameMetadata metadata;
778 metadata.device_scale_factor = m_deviceScaleFactor;
779 metadata.page_scale_factor = activeTree()->total_page_scale_factor();
780 metadata.viewport_size = activeTree()->ScrollableViewportSize();
781 metadata.root_layer_size = activeTree()->ScrollableSize();
782 metadata.min_page_scale_factor = activeTree()->min_page_scale_factor();
783 metadata.max_page_scale_factor = activeTree()->max_page_scale_factor();
784 if (m_topControlsManager) {
785 metadata.location_bar_offset = gfx::Vector2dF(0.f, m_topControlsManager- >controls_top_offset());
786 metadata.location_bar_content_translation = gfx::Vector2dF(0.f, m_topCon trolsManager->content_top_offset());
787 }
788
789 if (!rootScrollLayer())
790 return metadata;
791
792 metadata.root_scroll_offset = rootScrollLayer()->scroll_offset() + rootScrol lLayer()->scroll_delta();
793
794 return metadata; 925 return metadata;
795 } 926
796 927 metadata.root_scroll_offset = RootScrollLayer()->scroll_offset() +
797 void LayerTreeHostImpl::drawLayers(FrameData& frame) 928 RootScrollLayer()->scroll_delta();
798 { 929
799 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers"); 930 return metadata;
800 DCHECK(canDraw()); 931 }
801 DCHECK(!frame.renderPasses.empty()); 932
802 933 void LayerTreeHostImpl::DrawLayers(FrameData* frame) {
803 // FIXME: use the frame begin time from the overall compositor scheduler. 934 TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
804 // This value is currently inaccessible because it is up in Chromium's 935 DCHECK(CanDraw());
805 // RenderWidget. 936 DCHECK(!frame->render_passes.empty());
806 m_fpsCounter->saveTimeStamp(base::TimeTicks::Now()); 937
807 938 // FIXME: use the frame begin time from the overall compositor scheduler.
808 if (m_tileManager) { 939 // This value is currently inaccessible because it is up in Chromium's
809 m_memoryHistory->SaveEntry( 940 // RenderWidget.
810 m_tileManager->memory_stats_from_last_assign()); 941 fps_counter_->saveTimeStamp(base::TimeTicks::Now());
811 } 942
812 943 if (tile_manager_) {
813 if (m_debugState.showHudRects()) 944 memory_history_->SaveEntry(
814 m_debugRectHistory->saveDebugRectsForCurrentFrame(rootLayer(), *frame.re nderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenS paceRects, m_debugState); 945 tile_manager_->memory_stats_from_last_assign());
815 946 }
816 if (m_debugState.traceAllRenderedFrames) { 947
817 TRACE_EVENT_INSTANT1("cc.debug", "Frame", 948 if (debug_state_.showHudRects()) {
818 "frame", ValueToString(frameStateAsValue())); 949 debug_rect_history_->saveDebugRectsForCurrentFrame(
819 } 950 active_tree_->root_layer(),
820 951 *frame->render_surface_layer_list,
821 // Because the contents of the HUD depend on everything else in the frame, t he contents 952 frame->occluding_screen_space_rects,
822 // of its texture are updated as the last thing before the frame is drawn. 953 frame->non_occluding_screen_space_rects,
823 if (m_activeTree->hud_layer()) 954 debug_state_);
824 m_activeTree->hud_layer()->updateHudTexture(m_resourceProvider.get()); 955 }
825 956
826 m_renderer->DrawFrame(frame.renderPasses); 957 if (debug_state_.traceAllRenderedFrames) {
827 // The render passes should be consumed by the renderer. 958 TRACE_EVENT_INSTANT1("cc.debug", "Frame",
828 DCHECK(frame.renderPasses.empty()); 959 "frame", ValueToString(FrameStateAsValue()));
829 frame.renderPassesById.clear(); 960 }
830 961
831 // The next frame should start by assuming nothing has changed, and changes are noted as they occur. 962 // Because the contents of the HUD depend on everything else in the frame, the
832 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++) 963 // contents of its texture are updated as the last thing before the frame is
833 (*frame.renderSurfaceLayerList)[i]->render_surface()->damage_tracker()-> DidDrawDamagedArea(); 964 // drawn.
834 rootLayer()->ResetAllChangeTrackingForSubtree(); 965 if (active_tree_->hud_layer())
835 updateAnimationState(); 966 active_tree_->hud_layer()->updateHudTexture(resource_provider_.get());
836 } 967
837 968 renderer_->DrawFrame(frame->render_passes);
838 void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame) 969 // The render passes should be consumed by the renderer.
839 { 970 DCHECK(frame->render_passes.empty());
840 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i) 971 frame->render_passes_by_id.clear();
841 frame.willDrawLayers[i]->DidDraw(m_resourceProvider.get()); 972
842 973 // The next frame should start by assuming nothing has changed, and changes
843 // Once all layers have been drawn, pending texture uploads should no 974 // are noted as they occur.
844 // longer block future uploads. 975 for (unsigned int i = 0; i < frame->render_surface_layer_list->size(); i++) {
845 m_resourceProvider->MarkPendingUploadsAsNonBlocking(); 976 (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()->
846 } 977 DidDrawDamagedArea();
847 978 }
848 void LayerTreeHostImpl::finishAllRendering() 979 active_tree_->root_layer()->ResetAllChangeTrackingForSubtree();
849 { 980 UpdateAnimationState();
850 if (m_renderer) 981 }
851 m_renderer->Finish(); 982
852 } 983 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) {
853 984 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i)
854 bool LayerTreeHostImpl::isContextLost() 985 frame.will_draw_layers[i]->DidDraw(resource_provider_.get());
855 { 986
856 DCHECK(m_proxy->IsImplThread()); 987 // Once all layers have been drawn, pending texture uploads should no
857 return m_renderer && m_renderer->IsContextLost(); 988 // longer block future uploads.
858 } 989 resource_provider_->MarkPendingUploadsAsNonBlocking();
859 990 }
860 const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const 991
861 { 992 void LayerTreeHostImpl::FinishAllRendering() {
862 return m_renderer->Capabilities(); 993 if (renderer_)
863 } 994 renderer_->Finish();
864 995 }
865 bool LayerTreeHostImpl::swapBuffers() 996
866 { 997 bool LayerTreeHostImpl::IsContextLost() {
867 if (m_tileManager) 998 DCHECK(proxy_->IsImplThread());
868 m_tileManager->DidCompleteFrame(); 999 return renderer_ && renderer_->IsContextLost();
869 return m_renderer->SwapBuffers(); 1000 }
870 } 1001
871 1002 const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const {
872 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const 1003 return renderer_->Capabilities();
873 { 1004 }
874 return m_deviceViewportSize; 1005
875 } 1006 bool LayerTreeHostImpl::SwapBuffers() {
876 1007 if (tile_manager_)
877 const LayerTreeSettings& LayerTreeHostImpl::Settings() const 1008 tile_manager_->DidCompleteFrame();
878 { 1009 return renderer_->SwapBuffers();
879 return m_settings; 1010 }
880 } 1011
881 1012 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const {
882 void LayerTreeHostImpl::DidLoseOutputSurface() 1013 return device_viewport_size();
883 { 1014 }
884 m_client->didLoseOutputSurfaceOnImplThread(); 1015
885 } 1016 const LayerTreeSettings& LayerTreeHostImpl::Settings() const {
886 1017 return settings();
887 void LayerTreeHostImpl::OnSwapBuffersComplete() 1018 }
888 { 1019
889 m_client->onSwapBuffersCompleteOnImplThread(); 1020 void LayerTreeHostImpl::DidLoseOutputSurface() {
890 } 1021 client_->DidLoseOutputSurfaceOnImplThread();
891 1022 }
892 void LayerTreeHostImpl::readback(void* pixels, 1023
893 gfx::Rect rect_in_device_viewport) 1024 void LayerTreeHostImpl::OnSwapBuffersComplete() {
894 { 1025 client_->OnSwapBuffersCompleteOnImplThread();
895 DCHECK(m_renderer); 1026 }
896 m_renderer->GetFramebufferPixels(pixels, rect_in_device_viewport); 1027
1028 void LayerTreeHostImpl::Readback(void* pixels,
1029 gfx::Rect rect_in_device_viewport) {
1030 DCHECK(renderer_);
1031 renderer_->GetFramebufferPixels(pixels, rect_in_device_viewport);
897 } 1032 }
898 1033
899 bool LayerTreeHostImpl::haveRootScrollLayer() const { 1034 bool LayerTreeHostImpl::haveRootScrollLayer() const {
900 return rootScrollLayer(); 1035 return RootScrollLayer();
901 } 1036 }
902 1037
903 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const { 1038 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const {
904 if (LayerImpl* layer = rootScrollLayer()) 1039 if (LayerImpl* layer = RootScrollLayer())
905 return layer->scroll_offset().y() + layer->scroll_delta().y(); 1040 return layer->scroll_offset().y() + layer->scroll_delta().y();
906 return 0.0f; 1041 return 0.0f;
907 } 1042 }
908 1043
909 LayerImpl* LayerTreeHostImpl::rootLayer() const 1044 LayerImpl* LayerTreeHostImpl::RootLayer() const {
910 { 1045 return active_tree_->root_layer();
911 return m_activeTree->RootLayer(); 1046 }
912 } 1047
913 1048 LayerImpl* LayerTreeHostImpl::RootScrollLayer() const {
914 LayerImpl* LayerTreeHostImpl::rootScrollLayer() const 1049 return active_tree_->RootScrollLayer();
915 { 1050 }
916 return m_activeTree->RootScrollLayer(); 1051
917 } 1052 LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
918 1053 return active_tree_->CurrentlyScrollingLayer();
919 LayerImpl* LayerTreeHostImpl::currentlyScrollingLayer() const
920 {
921 return m_activeTree->CurrentlyScrollingLayer();
922 } 1054 }
923 1055
924 // Content layers can be either directly scrollable or contained in an outer 1056 // Content layers can be either directly scrollable or contained in an outer
925 // scrolling layer which applies the scroll transform. Given a content layer, 1057 // scrolling layer which applies the scroll transform. Given a content layer,
926 // this function returns the associated scroll layer if any. 1058 // this function returns the associated scroll layer if any.
927 static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl) 1059 static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) {
928 { 1060 if (!layer_impl)
929 if (!layerImpl)
930 return 0;
931
932 if (layerImpl->scrollable())
933 return layerImpl;
934
935 if (layerImpl->DrawsContent() && layerImpl->parent() && layerImpl->parent()- >scrollable())
936 return layerImpl->parent();
937
938 return 0; 1061 return 0;
939 } 1062
940 1063 if (layer_impl->scrollable())
941 void LayerTreeHostImpl::createPendingTree() 1064 return layer_impl;
942 { 1065
943 CHECK(!m_pendingTree); 1066 if (layer_impl->DrawsContent() &&
944 if (m_recycleTree) 1067 layer_impl->parent() &&
945 m_recycleTree.swap(m_pendingTree); 1068 layer_impl->parent()->scrollable())
946 else 1069 return layer_impl->parent();
947 m_pendingTree = LayerTreeImpl::create(this); 1070
948 m_client->onCanDrawStateChanged(canDraw()); 1071 return 0;
949 m_client->onHasPendingTreeStateChanged(pendingTree()); 1072 }
950 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", m_pendingTree.get()); 1073
951 TRACE_EVENT_ASYNC_STEP0("cc", 1074 void LayerTreeHostImpl::CreatePendingTree() {
952 "PendingTree", m_pendingTree.get(), "waiting"); 1075 CHECK(!pending_tree_);
953 } 1076 if (recycle_tree_)
954 1077 recycle_tree_.swap(pending_tree_);
955 void LayerTreeHostImpl::checkForCompletedTileUploads() 1078 else
956 { 1079 pending_tree_ = LayerTreeImpl::create(this);
957 DCHECK(!m_client->isInsideDraw()) << "Checking for completed uploads within a draw may trigger spurious redraws."; 1080 client_->OnCanDrawStateChanged(CanDraw());
958 if (m_tileManager) 1081 client_->OnHasPendingTreeStateChanged(pending_tree_);
959 m_tileManager->CheckForCompletedTileUploads(); 1082 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get());
960 } 1083 TRACE_EVENT_ASYNC_STEP0("cc",
961 1084 "PendingTree", pending_tree_.get(), "waiting");
962 bool LayerTreeHostImpl::activatePendingTreeIfNeeded() 1085 }
963 { 1086
964 if (!pendingTree()) 1087 void LayerTreeHostImpl::CheckForCompletedTileUploads() {
965 return false; 1088 DCHECK(!client_->IsInsideDraw()) <<
966 1089 "Checking for completed uploads within a draw may trigger "
967 CHECK(m_tileManager); 1090 "spurious redraws.";
968 1091 if (tile_manager_)
969 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); 1092 tile_manager_->CheckForCompletedTileUploads();
970 1093 }
971 TRACE_EVENT_ASYNC_STEP1("cc", 1094
972 "PendingTree", m_pendingTree.get(), "activate", 1095 bool LayerTreeHostImpl::ActivatePendingTreeIfNeeded() {
973 "state", ValueToString(activationStateAsValue())); 1096 if (!pending_tree_)
974 1097 return false;
975 // It's always fine to activate to an empty tree. Otherwise, only 1098
976 // activate once all visible resources in pending tree are ready 1099 CHECK(tile_manager_);
977 // or tile manager has no work scheduled for pending tree. 1100
978 if (activeTree()->RootLayer() && 1101 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE);
979 !pendingTree()->AreVisibleResourcesReady()) { 1102
980 // In smoothness takes priority mode, the pending tree's priorities are 1103 TRACE_EVENT_ASYNC_STEP1("cc",
981 // ignored, so the tile manager may not have work for it even though it 1104 "PendingTree", pending_tree_.get(), "activate",
982 // is simultaneously not ready to be activated. 1105 "state", ValueToString(ActivationStateAsValue()));
983 if (m_tileManager->GlobalState().tree_priority == 1106
984 SMOOTHNESS_TAKES_PRIORITY || 1107 // It's always fine to activate to an empty tree. Otherwise, only
985 m_tileManager->HasPendingWorkScheduled(PENDING_TREE)) { 1108 // activate once all visible resources in pending tree are ready
986 TRACE_EVENT_ASYNC_STEP0("cc", 1109 // or tile manager has no work scheduled for pending tree.
987 "PendingTree", 1110 if (active_tree_->root_layer() &&
988 m_pendingTree.get(), 1111 !pending_tree_->AreVisibleResourcesReady()) {
989 "waiting"); 1112 // In smoothness takes priority mode, the pending tree's priorities are
990 return false; 1113 // ignored, so the tile manager may not have work for it even though it
991 } 1114 // is simultaneously not ready to be activated.
1115 if (tile_manager_->GlobalState().tree_priority ==
1116 SMOOTHNESS_TAKES_PRIORITY ||
1117 tile_manager_->HasPendingWorkScheduled(PENDING_TREE)) {
1118 TRACE_EVENT_ASYNC_STEP0("cc",
1119 "PendingTree",
1120 pending_tree_.get(),
1121 "waiting");
1122 return false;
992 } 1123 }
993 1124 }
994 activatePendingTree(); 1125
995 return true; 1126 ActivatePendingTree();
996 } 1127 return true;
997 1128 }
998 void LayerTreeHostImpl::activatePendingTree() 1129
999 { 1130 void LayerTreeHostImpl::ActivatePendingTree() {
1000 CHECK(m_pendingTree); 1131 CHECK(pending_tree_);
1001 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", m_pendingTree.get()); 1132 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get());
1002 1133
1003 m_activeTree->PushPersistedState(m_pendingTree.get()); 1134 active_tree_->PushPersistedState(pending_tree_.get());
1004 if (m_pendingTree->needs_full_tree_sync()) 1135 if (pending_tree_->needs_full_tree_sync()) {
1005 m_activeTree->SetRootLayer(TreeSynchronizer::synchronizeTrees(m_pendingT ree->RootLayer(), m_activeTree->DetachLayerTree(), m_activeTree.get())); 1136 active_tree_->SetRootLayer(
1006 TreeSynchronizer::pushProperties(m_pendingTree->RootLayer(), m_activeTree->R ootLayer()); 1137 TreeSynchronizer::synchronizeTrees(pending_tree_->root_layer(),
1007 DCHECK(!m_recycleTree); 1138 active_tree_->DetachLayerTree(),
1008 1139 active_tree_.get()));
1009 m_pendingTree->PushPropertiesTo(m_activeTree.get()); 1140 }
1010 1141 TreeSynchronizer::pushProperties(pending_tree_->root_layer(),
1011 // Now that we've synced everything from the pending tree to the active 1142 active_tree_->root_layer());
1012 // tree, rename the pending tree the recycle tree so we can reuse it on the 1143 DCHECK(!recycle_tree_);
1013 // next sync. 1144
1014 m_pendingTree.swap(m_recycleTree); 1145 pending_tree_->PushPropertiesTo(active_tree_.get());
1015 m_recycleTree->ClearRenderSurfaces(); 1146
1016 1147 // Now that we've synced everything from the pending tree to the active
1017 m_activeTree->DidBecomeActive(); 1148 // tree, rename the pending tree the recycle tree so we can reuse it on the
1018 1149 // next sync.
1019 // Reduce wasted memory now that unlinked resources are guaranteed not 1150 pending_tree_.swap(recycle_tree_);
1020 // to be used. 1151 recycle_tree_->ClearRenderSurfaces();
1021 m_client->reduceWastedContentsTextureMemoryOnImplThread(); 1152
1022 1153 active_tree_->DidBecomeActive();
1023 m_client->onCanDrawStateChanged(canDraw()); 1154
1024 m_client->onHasPendingTreeStateChanged(pendingTree()); 1155 // Reduce wasted memory now that unlinked resources are guaranteed not
1025 m_client->setNeedsRedrawOnImplThread(); 1156 // to be used.
1026 m_client->renewTreePriority(); 1157 client_->ReduceWastedContentsTextureMemoryOnImplThread();
1027 1158
1028 if (m_tileManager && m_debugState.continuousPainting) { 1159 client_->OnCanDrawStateChanged(CanDraw());
1029 RenderingStats stats; 1160 client_->OnHasPendingTreeStateChanged(pending_tree_);
1030 m_tileManager->GetRenderingStats(&stats); 1161 client_->SetNeedsRedrawOnImplThread();
1031 m_paintTimeCounter->SaveRasterizeTime(stats.totalRasterizeTimeForNowBins OnPendingTree, m_activeTree->source_frame_number()); 1162 client_->RenewTreePriority();
1163
1164 if (tile_manager_ && debug_state_.continuousPainting) {
1165 RenderingStats stats;
1166 tile_manager_->GetRenderingStats(&stats);
1167 paint_time_counter_->SaveRasterizeTime(
1168 stats.totalRasterizeTimeForNowBinsOnPendingTree,
1169 active_tree_->source_frame_number());
1170 }
1171 }
1172
1173 void LayerTreeHostImpl::SetVisible(bool visible) {
1174 DCHECK(proxy_->IsImplThread());
1175
1176 if (visible_ == visible)
1177 return;
1178 visible_ = visible;
1179 DidVisibilityChange(this, visible_);
1180 EnforceManagedMemoryPolicy(managed_memory_policy_);
1181
1182 if (!renderer_)
1183 return;
1184
1185 renderer_->SetVisible(visible);
1186
1187 SetBackgroundTickingEnabled(
1188 !visible_ &&
1189 !animation_registrar_->active_animation_controllers().empty());
1190 }
1191
1192 bool LayerTreeHostImpl::InitializeRenderer(
1193 scoped_ptr<OutputSurface> output_surface) {
1194 // Since we will create a new resource provider, we cannot continue to use
1195 // the old resources (i.e. render_surfaces and texture IDs). Clear them
1196 // before we destroy the old resource provider.
1197 if (active_tree_->root_layer())
1198 ClearRenderSurfaces();
1199 if (active_tree_->root_layer())
1200 SendDidLoseOutputSurfaceRecursive(active_tree_->root_layer());
1201 if (pending_tree_ && pending_tree_->root_layer())
1202 SendDidLoseOutputSurfaceRecursive(pending_tree_->root_layer());
1203 if (recycle_tree_ && recycle_tree_->root_layer())
1204 SendDidLoseOutputSurfaceRecursive(recycle_tree_->root_layer());
1205
1206 // Note: order is important here.
1207 renderer_.reset();
1208 tile_manager_.reset();
1209 resource_provider_.reset();
1210 output_surface_.reset();
1211
1212 if (!output_surface->BindToClient(this))
1213 return false;
1214
1215 scoped_ptr<ResourceProvider> resource_provider =
1216 ResourceProvider::Create(output_surface.get());
1217 if (!resource_provider)
1218 return false;
1219
1220 if (settings_.implSidePainting) {
1221 tile_manager_.reset(new TileManager(this,
1222 resource_provider.get(),
1223 settings_.numRasterThreads,
1224 settings_.useCheapnessEstimator,
1225 settings_.useColorEstimator,
1226 settings_.predictionBenchmarking));
1227 tile_manager_->SetRecordRenderingStats(debug_state_.recordRenderingStats());
1228 }
1229
1230 if (output_surface->capabilities().has_parent_compositor) {
1231 renderer_ = DelegatingRenderer::Create(this, output_surface.get(),
1232 resource_provider.get());
1233 } else if (output_surface->context3d()) {
1234 renderer_ = GLRenderer::Create(this,
1235 output_surface.get(),
1236 resource_provider.get());
1237 } else if (output_surface->software_device()) {
1238 renderer_ = SoftwareRenderer::Create(this,
1239 output_surface.get(),
1240 resource_provider.get());
1241 }
1242 if (!renderer_)
1243 return false;
1244
1245 resource_provider_ = resource_provider.Pass();
1246 output_surface_ = output_surface.Pass();
1247
1248 if (!visible_)
1249 renderer_->SetVisible(visible_);
1250
1251 client_->OnCanDrawStateChanged(CanDraw());
1252
1253 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs
1254 // to be initialized to get max texture size.
1255 active_tree_->set_needs_update_draw_properties();
1256 if (pending_tree_)
1257 pending_tree_->set_needs_update_draw_properties();
1258
1259 return true;
1260 }
1261
1262 void LayerTreeHostImpl::SetViewportSize(gfx::Size layout_viewport_size,
1263 gfx::Size device_viewport_size) {
1264 if (layout_viewport_size == layout_viewport_size_ &&
1265 device_viewport_size == device_viewport_size_)
1266 return;
1267
1268 if (pending_tree_ && device_viewport_size_ != device_viewport_size)
1269 active_tree_->SetViewportSizeInvalid();
1270
1271 layout_viewport_size_ = layout_viewport_size;
1272 device_viewport_size_ = device_viewport_size;
1273
1274 UpdateMaxScrollOffset();
1275
1276 if (renderer_)
1277 renderer_->ViewportChanged();
1278
1279 client_->OnCanDrawStateChanged(CanDraw());
1280 }
1281
1282 static void AdjustScrollsForPageScaleChange(LayerImpl* layer_impl,
1283 float page_scale_change) {
1284 if (!layer_impl)
1285 return;
1286
1287 if (layer_impl->scrollable()) {
1288 // We need to convert impl-side scroll deltas to page_scale space.
1289 gfx::Vector2dF scroll_delta = layer_impl->scroll_delta();
1290 scroll_delta.Scale(page_scale_change);
1291 layer_impl->SetScrollDelta(scroll_delta);
1292 }
1293
1294 for (size_t i = 0; i < layer_impl->children().size(); ++i)
1295 AdjustScrollsForPageScaleChange(layer_impl->children()[i],
1296 page_scale_change);
1297 }
1298
1299 void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
1300 if (device_scale_factor == device_scale_factor_)
1301 return;
1302 device_scale_factor_ = device_scale_factor;
1303
1304 UpdateMaxScrollOffset();
1305 }
1306
1307 void LayerTreeHostImpl::UpdateMaxScrollOffset() {
1308 active_tree_->UpdateMaxScrollOffset();
1309 }
1310
1311 void LayerTreeHostImpl::setActiveTreeNeedsUpdateDrawProperties() {
1312 active_tree_->set_needs_update_draw_properties();
1313 }
1314
1315 void LayerTreeHostImpl::setNeedsRedraw() {
1316 client_->SetNeedsRedrawOnImplThread();
1317 }
1318
1319 bool LayerTreeHostImpl::EnsureRenderSurfaceLayerList() {
1320 active_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE);
1321 return active_tree_->RenderSurfaceLayerList().size();
1322 }
1323
1324 InputHandlerClient::ScrollStatus LayerTreeHostImpl::ScrollBegin(
1325 gfx::Point viewport_point, InputHandlerClient::ScrollInputType type) {
1326 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
1327
1328 if (top_controls_manager_)
1329 top_controls_manager_->ScrollBegin();
1330
1331 DCHECK(!CurrentlyScrollingLayer());
1332 ClearCurrentlyScrollingLayer();
1333
1334 if (!EnsureRenderSurfaceLayerList())
1335 return ScrollIgnored;
1336
1337 gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
1338 device_scale_factor_);
1339
1340 // First find out which layer was hit from the saved list of visible layers
1341 // in the most recent frame.
1342 LayerImpl* layer_impl = LayerTreeHostCommon::findLayerThatIsHitByPoint(
1343 device_viewport_point, active_tree_->RenderSurfaceLayerList());
1344
1345 // Walk up the hierarchy and look for a scrollable layer.
1346 LayerImpl* potentially_scrolling_layer_impl = 0;
1347 for (; layer_impl; layer_impl = layer_impl->parent()) {
1348 // The content layer can also block attempts to scroll outside the main
1349 // thread.
1350 ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
1351 if (status == ScrollOnMainThread) {
1352 num_main_thread_scrolls_++;
1353 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1354 return ScrollOnMainThread;
1032 } 1355 }
1033 } 1356
1034 1357 LayerImpl* scroll_layer_impl = FindScrollLayerForContentLayer(layer_impl);
1035 void LayerTreeHostImpl::setVisible(bool visible) 1358 if (!scroll_layer_impl)
1036 { 1359 continue;
1037 DCHECK(m_proxy->IsImplThread()); 1360
1038 1361 status = scroll_layer_impl->TryScroll(device_viewport_point, type);
1039 if (m_visible == visible) 1362
1040 return; 1363 // If any layer wants to divert the scroll event to the main thread, abort.
1041 m_visible = visible; 1364 if (status == ScrollOnMainThread) {
1042 didVisibilityChange(this, m_visible); 1365 num_main_thread_scrolls_++;
1043 EnforceManagedMemoryPolicy(m_managedMemoryPolicy); 1366 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1044 1367 return ScrollOnMainThread;
1045 if (!m_renderer)
1046 return;
1047
1048 m_renderer->SetVisible(visible);
1049
1050 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_anim ation_controllers().empty());
1051 }
1052
1053 bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<OutputSurface> outputSurfa ce)
1054 {
1055 // Since we will create a new resource provider, we cannot continue to use
1056 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
1057 // before we destroy the old resource provider.
1058 if (rootLayer())
1059 clearRenderSurfaces();
1060 if (activeTree()->RootLayer())
1061 sendDidLoseOutputSurfaceRecursive(activeTree()->RootLayer());
1062 if (pendingTree() && pendingTree()->RootLayer())
1063 sendDidLoseOutputSurfaceRecursive(pendingTree()->RootLayer());
1064 if (m_recycleTree && m_recycleTree->RootLayer())
1065 sendDidLoseOutputSurfaceRecursive(m_recycleTree->RootLayer());
1066
1067 // Note: order is important here.
1068 m_renderer.reset();
1069 m_tileManager.reset();
1070 m_resourceProvider.reset();
1071 m_outputSurface.reset();
1072
1073 if (!outputSurface->BindToClient(this))
1074 return false;
1075
1076 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::Create(out putSurface.get());
1077 if (!resourceProvider)
1078 return false;
1079
1080 if (m_settings.implSidePainting) {
1081 m_tileManager.reset(new TileManager(this,
1082 resourceProvider.get(),
1083 m_settings.numRasterThreads,
1084 m_settings.useCheapnessEstimator,
1085 m_settings.useColorEstimator,
1086 m_settings.predictionBenchmarking));
1087 m_tileManager->SetRecordRenderingStats(m_debugState.recordRenderingStats ());
1088 } 1368 }
1089 1369
1090 if (outputSurface->capabilities().has_parent_compositor) 1370 if (status == ScrollStarted && !potentially_scrolling_layer_impl)
1091 m_renderer = DelegatingRenderer::Create(this, outputSurface.get(), resou rceProvider.get()); 1371 potentially_scrolling_layer_impl = scroll_layer_impl;
1092 else if (outputSurface->context3d()) 1372 }
1093 m_renderer = GLRenderer::Create(this, outputSurface.get(), resourceProvi der.get()); 1373
1094 else if (outputSurface->software_device()) 1374 // When hiding top controls is enabled and the controls are hidden or
1095 m_renderer = SoftwareRenderer::Create(this, outputSurface.get(), resourc eProvider.get()); 1375 // overlaying the content, force scrolls to be enabled on the root layer to
1096 if (!m_renderer) 1376 // allow bringing the top controls back into view.
1097 return false; 1377 if (!potentially_scrolling_layer_impl && top_controls_manager_ &&
1098 1378 top_controls_manager_->content_top_offset() !=
1099 m_resourceProvider = resourceProvider.Pass(); 1379 settings_.topControlsHeight) {
1100 m_outputSurface = outputSurface.Pass(); 1380 potentially_scrolling_layer_impl = RootScrollLayer();
1101 1381 }
1102 if (!m_visible) 1382
1103 m_renderer->SetVisible(m_visible); 1383 if (potentially_scrolling_layer_impl) {
1104 1384 active_tree_->set_currently_scrolling_layer(
1105 m_client->onCanDrawStateChanged(canDraw()); 1385 potentially_scrolling_layer_impl);
1106 1386 should_bubble_scrolls_ = (type != NonBubblingGesture);
1107 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs 1387 wheel_scrolling_ = (type == Wheel);
1108 // to be initialized to get max texture size. 1388 num_impl_thread_scrolls_++;
1109 activeTree()->set_needs_update_draw_properties(); 1389 client_->RenewTreePriority();
1110 if (pendingTree()) 1390 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
1111 pendingTree()->set_needs_update_draw_properties(); 1391 return ScrollStarted;
1112 1392 }
1113 return true; 1393 return ScrollIgnored;
1114 } 1394 }
1115 1395
1116 void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, con st gfx::Size& deviceViewportSize) 1396 gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta(
1117 { 1397 LayerImpl* layer_impl,
1118 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_de viceViewportSize) 1398 float scale_from_viewport_to_screen_space,
1119 return; 1399 gfx::PointF viewport_point,
1120 1400 gfx::Vector2dF viewport_delta) {
1121 if (pendingTree() && m_deviceViewportSize != deviceViewportSize) 1401 // Layers with non-invertible screen space transforms should not have passed
1122 activeTree()->SetViewportSizeInvalid(); 1402 // the scroll hit test in the first place.
1123 1403 DCHECK(layer_impl->screen_space_transform().IsInvertible());
1124 m_layoutViewportSize = layoutViewportSize; 1404 gfx::Transform inverse_screen_space_transform(
1125 m_deviceViewportSize = deviceViewportSize; 1405 gfx::Transform::kSkipInitialization);
1126 1406 bool did_invert = layer_impl->screen_space_transform().GetInverse(
1127 updateMaxScrollOffset(); 1407 &inverse_screen_space_transform);
1128 1408 // TODO: With the advent of impl-side crolling for non-root layers, we may
1129 if (m_renderer) 1409 // need to explicitly handle uninvertible transforms here.
1130 m_renderer->ViewportChanged(); 1410 DCHECK(did_invert);
1131 1411
1132 m_client->onCanDrawStateChanged(canDraw()); 1412 gfx::PointF screen_space_point =
1133 } 1413 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space);
1134 1414
1135 static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScal eChange) 1415 gfx::Vector2dF screen_space_delta = viewport_delta;
1136 { 1416 screen_space_delta.Scale(scale_from_viewport_to_screen_space);
1137 if (!layerImpl) 1417
1138 return; 1418 // First project the scroll start and end points to local layer space to find
1139 1419 // the scroll delta in layer coordinates.
1140 if (layerImpl->scrollable()) { 1420 bool start_clipped, end_clipped;
1141 // We need to convert impl-side scroll deltas to pageScale space. 1421 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta;
1142 gfx::Vector2dF scrollDelta = layerImpl->scroll_delta(); 1422 gfx::PointF local_start_point =
1143 scrollDelta.Scale(pageScaleChange); 1423 MathUtil::projectPoint(inverse_screen_space_transform,
1144 layerImpl->SetScrollDelta(scrollDelta); 1424 screen_space_point,
1425 start_clipped);
1426 gfx::PointF local_end_point =
1427 MathUtil::projectPoint(inverse_screen_space_transform,
1428 screen_space_end_point,
1429 end_clipped);
1430
1431 // In general scroll point coordinates should not get clipped.
1432 DCHECK(!start_clipped);
1433 DCHECK(!end_clipped);
1434 if (start_clipped || end_clipped)
1435 return gfx::Vector2dF();
1436
1437 // local_start_point and local_end_point are in content space but we want to
1438 // move them to layer space for scrolling.
1439 float width_scale = 1.f / layer_impl->contents_scale_x();
1440 float height_scale = 1.f / layer_impl->contents_scale_y();
1441 local_start_point.Scale(width_scale, height_scale);
1442 local_end_point.Scale(width_scale, height_scale);
1443
1444 // Apply the scroll delta.
1445 gfx::Vector2dF previous_delta = layer_impl->scroll_delta();
1446 layer_impl->ScrollBy(local_end_point - local_start_point);
1447
1448 // Get the end point in the layer's content space so we can apply its
1449 // ScreenSpaceTransform.
1450 gfx::PointF actual_local_end_point = local_start_point +
1451 layer_impl->scroll_delta() -
1452 previous_delta;
1453 gfx::PointF actual_local_content_end_point =
1454 gfx::ScalePoint(actual_local_end_point,
1455 1.f / width_scale,
1456 1.f / height_scale);
1457
1458 // Calculate the applied scroll delta in viewport space coordinates.
1459 gfx::PointF actual_screen_space_end_point =
1460 MathUtil::mapPoint(layer_impl->screen_space_transform(),
1461 actual_local_content_end_point,
1462 end_clipped);
1463 DCHECK(!end_clipped);
1464 if (end_clipped)
1465 return gfx::Vector2dF();
1466 gfx::PointF actual_viewport_end_point =
1467 gfx::ScalePoint(actual_screen_space_end_point,
1468 1.f / scale_from_viewport_to_screen_space);
1469 return actual_viewport_end_point - viewport_point;
1470 }
1471
1472 static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl,
1473 gfx::Vector2dF local_delta) {
1474 gfx::Vector2dF previous_delta(layer_impl->scroll_delta());
1475 layer_impl->ScrollBy(local_delta);
1476 return layer_impl->scroll_delta() - previous_delta;
1477 }
1478
1479 bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
1480 gfx::Vector2dF scroll_delta) {
1481 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
1482 if (!CurrentlyScrollingLayer())
1483 return false;
1484
1485 gfx::Vector2dF pending_delta = scroll_delta;
1486 bool did_scroll = false;
1487
1488 for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
1489 layer_impl;
1490 layer_impl = layer_impl->parent()) {
1491 if (!layer_impl->scrollable())
1492 continue;
1493
1494 gfx::Vector2dF applied_delta;
1495 if (top_controls_manager_ && layer_impl == RootScrollLayer())
1496 pending_delta = top_controls_manager_->ScrollBy(pending_delta);
1497
1498 // Gesture events need to be transformed from viewport coordinates to local
1499 // layer coordinates so that the scrolling contents exactly follow the
1500 // user's finger. In contrast, wheel events represent a fixed amount of
1501 // scrolling so we can just apply them directly.
1502 if (!wheel_scrolling_) {
1503 float scale_from_viewport_to_screen_space = device_scale_factor_;
1504 applied_delta =
1505 ScrollLayerWithViewportSpaceDelta(layer_impl,
1506 scale_from_viewport_to_screen_space,
1507 viewport_point, pending_delta);
1508 } else {
1509 applied_delta = ScrollLayerWithLocalDelta(layer_impl, pending_delta);
1145 } 1510 }
1146 1511
1147 for (size_t i = 0; i < layerImpl->children().size(); ++i) 1512 // If the layer wasn't able to move, try the next one in the hierarchy.
1148 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChang e); 1513 float move_threshold_squared = 0.1f * 0.1f;
1149 } 1514 if (applied_delta.LengthSquared() < move_threshold_squared) {
1150 1515 if (should_bubble_scrolls_ || !did_lock_scrolling_layer_)
1151 void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor) 1516 continue;
1152 { 1517 else
1153 if (deviceScaleFactor == m_deviceScaleFactor) 1518 break;
1154 return;
1155 m_deviceScaleFactor = deviceScaleFactor;
1156
1157 updateMaxScrollOffset();
1158 }
1159
1160 void LayerTreeHostImpl::updateMaxScrollOffset()
1161 {
1162 activeTree()->UpdateMaxScrollOffset();
1163 }
1164
1165 void LayerTreeHostImpl::setActiveTreeNeedsUpdateDrawProperties()
1166 {
1167 activeTree()->set_needs_update_draw_properties();
1168 }
1169
1170 void LayerTreeHostImpl::setNeedsRedraw()
1171 {
1172 m_client->setNeedsRedrawOnImplThread();
1173 }
1174
1175 bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
1176 {
1177 activeTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE);
1178 return activeTree()->RenderSurfaceLayerList().size();
1179 }
1180
1181 InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewp ortPoint, InputHandlerClient::ScrollInputType type)
1182 {
1183 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
1184
1185 if (m_topControlsManager)
1186 m_topControlsManager->ScrollBegin();
1187
1188 DCHECK(!currentlyScrollingLayer());
1189 clearCurrentlyScrollingLayer();
1190
1191 if (!ensureRenderSurfaceLayerList())
1192 return ScrollIgnored;
1193
1194 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceSca leFactor);
1195
1196 // First find out which layer was hit from the saved list of visible layers
1197 // in the most recent frame.
1198 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(device ViewportPoint, activeTree()->RenderSurfaceLayerList());
1199
1200 // Walk up the hierarchy and look for a scrollable layer.
1201 LayerImpl* potentiallyScrollingLayerImpl = 0;
1202 for (; layerImpl; layerImpl = layerImpl->parent()) {
1203 // The content layer can also block attempts to scroll outside the main thread.
1204 if (layerImpl->TryScroll(deviceViewportPoint, type) == ScrollOnMainThrea d) {
1205 m_numMainThreadScrolls++;
1206 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1207 return ScrollOnMainThread;
1208 }
1209
1210 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
1211 if (!scrollLayerImpl)
1212 continue;
1213
1214 ScrollStatus status = scrollLayerImpl->TryScroll(deviceViewportPoint, ty pe);
1215
1216 // If any layer wants to divert the scroll event to the main thread, abo rt.
1217 if (status == ScrollOnMainThread) {
1218 m_numMainThreadScrolls++;
1219 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1220 return ScrollOnMainThread;
1221 }
1222
1223 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1224 potentiallyScrollingLayerImpl = scrollLayerImpl;
1225 } 1519 }
1226 1520 did_scroll = true;
1227 // When hiding top controls is enabled and the controls are hidden or 1521 did_lock_scrolling_layer_ = true;
1228 // overlaying the content, force scrolls to be enabled on the root layer to 1522 if (!should_bubble_scrolls_) {
1229 // allow bringing the top controls back into view. 1523 active_tree_->set_currently_scrolling_layer(layer_impl);
1230 if (!potentiallyScrollingLayerImpl && m_topControlsManager && 1524 break;
1231 m_topControlsManager->content_top_offset() != m_settings.topControls Height) {
1232 potentiallyScrollingLayerImpl = rootScrollLayer();
1233 } 1525 }
1234 1526
1235 if (potentiallyScrollingLayerImpl) { 1527 // If the applied delta is within 45 degrees of the input delta, bail out to
1236 m_activeTree->set_currently_scrolling_layer(potentiallyScrollingLayerImp l); 1528 // make it easier to scroll just one layer in one direction without
1237 m_shouldBubbleScrolls = (type != NonBubblingGesture); 1529 // affecting any of its parents.
1238 m_wheelScrolling = (type == Wheel); 1530 float angle_threshold = 45;
1239 m_numImplThreadScrolls++; 1531 if (MathUtil::smallestAngleBetweenVectors(
1240 m_client->renewTreePriority(); 1532 applied_delta, pending_delta) < angle_threshold) {
1241 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); 1533 pending_delta = gfx::Vector2d();
1242 return ScrollStarted; 1534 break;
1243 } 1535 }
1244 return ScrollIgnored; 1536
1245 } 1537 // Allow further movement only on an axis perpendicular to the direction in
1246 1538 // which the layer moved.
1247 gfx::Vector2dF LayerTreeHostImpl::scrollLayerWithViewportSpaceDelta(LayerImpl* l ayerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx:: Vector2dF viewportDelta) 1539 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
1248 { 1540 pending_delta = MathUtil::projectVector(pending_delta, perpendicular_axis);
1249 // Layers with non-invertible screen space transforms should not have passed the scroll hit 1541
1250 // test in the first place. 1542 if (gfx::ToFlooredVector2d(pending_delta).IsZero())
1251 DCHECK(layerImpl->screen_space_transform().IsInvertible()); 1543 break;
1252 gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitializati on); 1544 }
1253 bool didInvert = layerImpl->screen_space_transform().GetInverse(&inverseScre enSpaceTransform); 1545
1254 // TODO: With the advent of impl-side crolling for non-root layers, we may 1546 if (did_scroll) {
1255 // need to explicitly handle uninvertible transforms here. 1547 client_->SetNeedsCommitOnImplThread();
1256 DCHECK(didInvert); 1548 client_->SetNeedsRedrawOnImplThread();
1257 1549 client_->RenewTreePriority();
1258 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewp ortToScreenSpace); 1550 }
1259 1551 return did_scroll;
1260 gfx::Vector2dF screenSpaceDelta = viewportDelta; 1552 }
1261 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace); 1553
1262 1554 void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() {
1263 // First project the scroll start and end points to local layer space to fin d the scroll delta 1555 active_tree_->ClearCurrentlyScrollingLayer();
1264 // in layer coordinates. 1556 did_lock_scrolling_layer_ = false;
1265 bool startClipped, endClipped; 1557 }
1266 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta; 1558
1267 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTrans form, screenSpacePoint, startClipped); 1559 void LayerTreeHostImpl::ScrollEnd() {
1268 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransfo rm, screenSpaceEndPoint, endClipped); 1560 if (top_controls_manager_)
1269 1561 top_controls_manager_->ScrollEnd();
1270 // In general scroll point coordinates should not get clipped. 1562 ClearCurrentlyScrollingLayer();
1271 DCHECK(!startClipped); 1563 }
1272 DCHECK(!endClipped); 1564
1273 if (startClipped || endClipped) 1565 void LayerTreeHostImpl::PinchGestureBegin() {
1274 return gfx::Vector2dF(); 1566 pinch_gesture_active_ = true;
1275 1567 previous_pinch_anchor_ = gfx::Point();
1276 // localStartPoint and localEndPoint are in content space but we want to mov e them to layer space for scrolling. 1568 client_->RenewTreePriority();
1277 float widthScale = 1.f / layerImpl->contents_scale_x(); 1569 }
1278 float heightScale = 1.f / layerImpl->contents_scale_y(); 1570
1279 localStartPoint.Scale(widthScale, heightScale); 1571 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
1280 localEndPoint.Scale(widthScale, heightScale); 1572 gfx::Point anchor) {
1281 1573 TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
1282 // Apply the scroll delta. 1574
1283 gfx::Vector2dF previousDelta = layerImpl->scroll_delta(); 1575 if (!RootScrollLayer())
1284 layerImpl->ScrollBy(localEndPoint - localStartPoint); 1576 return;
1285 1577
1286 // Get the end point in the layer's content space so we can apply its screen SpaceTransform. 1578 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1287 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl->scroll_delta( ) - previousDelta; 1579 // position over the course of the magnify.
1288 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint , 1 / widthScale, 1 / heightScale); 1580 float page_scale_delta = active_tree_->page_scale_delta();
1289 1581 gfx::PointF previous_scale_anchor =
1290 // Calculate the applied scroll delta in viewport space coordinates. 1582 gfx::ScalePoint(anchor, 1.f / page_scale_delta);
1291 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl->screen _space_transform(), actualLocalContentEndPoint, endClipped); 1583 active_tree_->SetPageScaleDelta(page_scale_delta * magnify_delta);
1292 DCHECK(!endClipped); 1584 page_scale_delta = active_tree_->page_scale_delta();
1293 if (endClipped) 1585 gfx::PointF new_scale_anchor =
1294 return gfx::Vector2dF(); 1586 gfx::ScalePoint(anchor, 1.f / page_scale_delta);
1295 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoi nt, 1 / scaleFromViewportToScreenSpace); 1587 gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor;
1296 return actualViewportEndPoint - viewportPoint; 1588
1297 } 1589 previous_pinch_anchor_ = anchor;
1298 1590
1299 static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vecto r2dF localDelta) 1591 move.Scale(1 / active_tree_->page_scale_factor());
1300 { 1592
1301 gfx::Vector2dF previousDelta(layerImpl.scroll_delta()); 1593 RootScrollLayer()->ScrollBy(move);
1302 layerImpl.ScrollBy(localDelta); 1594
1303 return layerImpl.scroll_delta() - previousDelta; 1595 if (RootScrollLayer()->scrollbar_animation_controller()) {
1304 } 1596 RootScrollLayer()->scrollbar_animation_controller()->
1305 1597 didPinchGestureUpdate(base::TimeTicks::Now());
1306 bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint, 1598 }
1307 const gfx::Vector2dF& scrollDelta) 1599
1308 { 1600 client_->SetNeedsCommitOnImplThread();
1309 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy"); 1601 client_->SetNeedsRedrawOnImplThread();
1310 if (!currentlyScrollingLayer()) 1602 client_->RenewTreePriority();
1311 return false; 1603 }
1312 1604
1313 gfx::Vector2dF pendingDelta = scrollDelta; 1605 void LayerTreeHostImpl::PinchGestureEnd() {
1314 bool didScroll = false; 1606 pinch_gesture_active_ = false;
1315 1607
1316 for (LayerImpl* layerImpl = currentlyScrollingLayer(); layerImpl; layerImpl = layerImpl->parent()) { 1608 if (RootScrollLayer() &&
1317 if (!layerImpl->scrollable()) 1609 RootScrollLayer()->scrollbar_animation_controller()) {
1318 continue; 1610 RootScrollLayer()->scrollbar_animation_controller()->
1319 1611 didPinchGestureEnd(base::TimeTicks::Now());
1320 gfx::Vector2dF appliedDelta; 1612 }
1321 if (m_topControlsManager && layerImpl == rootScrollLayer()) 1613
1322 pendingDelta = m_topControlsManager->ScrollBy(pendingDelta); 1614 client_->SetNeedsCommitOnImplThread();
1323 1615 }
1324 // Gesture events need to be transformed from viewport coordinates to lo cal layer coordinates 1616
1325 // so that the scrolling contents exactly follow the user's finger. In c ontrast, wheel 1617 static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info,
1326 // events represent a fixed amount of scrolling so we can just apply the m directly. 1618 LayerImpl* layer_impl) {
1327 if (!m_wheelScrolling) { 1619 if (!layer_impl)
1328 float scaleFromViewportToScreenSpace = m_deviceScaleFactor; 1620 return;
1329 appliedDelta = scrollLayerWithViewportSpaceDelta(layerImpl, scaleFro mViewportToScreenSpace, viewportPoint, pendingDelta); 1621
1330 } else 1622 gfx::Vector2d scroll_delta =
1331 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta); 1623 gfx::ToFlooredVector2d(layer_impl->scroll_delta());
1332 1624 if (!scroll_delta.IsZero()) {
1333 // If the layer wasn't able to move, try the next one in the hierarchy. 1625 LayerTreeHostCommon::ScrollUpdateInfo scroll;
1334 float moveThresholdSquared = 0.1f * 0.1f; 1626 scroll.layerId = layer_impl->id();
1335 if (appliedDelta.LengthSquared() < moveThresholdSquared) { 1627 scroll.scrollDelta = scroll_delta;
1336 if (m_shouldBubbleScrolls || !m_didLockScrollingLayer) 1628 scroll_info->scrolls.push_back(scroll);
1337 continue; 1629 layer_impl->SetSentScrollDelta(scroll_delta);
1338 else 1630 }
1339 break; 1631
1340 } 1632 for (size_t i = 0; i < layer_impl->children().size(); ++i)
1341 didScroll = true; 1633 CollectScrollDeltas(scroll_info, layer_impl->children()[i]);
1342 m_didLockScrollingLayer = true; 1634 }
1343 if (!m_shouldBubbleScrolls) { 1635
1344 m_activeTree->set_currently_scrolling_layer(layerImpl); 1636 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
1345 break; 1637 scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet());
1346 } 1638
1347 1639 CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer());
1348 // If the applied delta is within 45 degrees of the input delta, bail ou t to make it easier 1640 scroll_info->pageScaleDelta = active_tree_->page_scale_delta();
1349 // to scroll just one layer in one direction without affecting any of it s parents. 1641 active_tree_->set_sent_page_scale_delta(scroll_info->pageScaleDelta);
1350 float angleThreshold = 45; 1642
1351 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) { 1643 return scroll_info.Pass();
1352 pendingDelta = gfx::Vector2d(); 1644 }
1353 break; 1645
1354 } 1646 void LayerTreeHostImpl::SetFullRootLayerDamage() {
1355 1647 if (active_tree_->root_layer()) {
1356 // Allow further movement only on an axis perpendicular to the direction in which the layer 1648 RenderSurfaceImpl* render_surface =
1357 // moved. 1649 active_tree_->root_layer()->render_surface();
1358 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x()); 1650 if (render_surface)
1359 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis); 1651 render_surface->damage_tracker()->ForceFullDamageNextUpdate();
1360 1652 }
1361 if (gfx::ToFlooredVector2d(pendingDelta).IsZero()) 1653 }
1362 break; 1654
1363 } 1655 void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
1364 1656 if (!page_scale_animation_ || !RootScrollLayer())
1365 if (didScroll) { 1657 return;
1366 m_client->setNeedsCommitOnImplThread(); 1658
1367 m_client->setNeedsRedrawOnImplThread(); 1659 double monotonic_time = (time - base::TimeTicks()).InSecondsF();
1368 m_client->renewTreePriority(); 1660 gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() +
1369 } 1661 RootScrollLayer()->scroll_delta();
1370 return didScroll; 1662
1371 } 1663 active_tree_->SetPageScaleDelta(
1372 1664 page_scale_animation_->PageScaleFactorAtTime(monotonic_time) /
1373 void LayerTreeHostImpl::clearCurrentlyScrollingLayer() 1665 active_tree_->page_scale_factor());
1374 { 1666 gfx::Vector2dF next_scroll =
1375 m_activeTree->ClearCurrentlyScrollingLayer(); 1667 page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
1376 m_didLockScrollingLayer = false; 1668
1377 } 1669 RootScrollLayer()->ScrollBy(next_scroll - scroll_total);
1378 1670 client_->SetNeedsRedrawOnImplThread();
1379 void LayerTreeHostImpl::scrollEnd() 1671
1380 { 1672 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
1381 if (m_topControlsManager) 1673 page_scale_animation_.reset();
1382 m_topControlsManager->ScrollEnd(); 1674 client_->SetNeedsCommitOnImplThread();
1383 clearCurrentlyScrollingLayer(); 1675 client_->RenewTreePriority();
1384 } 1676 }
1385 1677 }
1386 void LayerTreeHostImpl::pinchGestureBegin() 1678
1387 { 1679 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time,
1388 m_pinchGestureActive = true; 1680 base::Time wall_clock_time) {
1389 m_previousPinchAnchor = gfx::Point(); 1681 if (!settings_.acceleratedAnimationEnabled ||
1390 m_client->renewTreePriority(); 1682 animation_registrar_->active_animation_controllers().empty() ||
1391 } 1683 !active_tree_->root_layer())
1392 1684 return;
1393 void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor ) 1685
1394 { 1686 TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers");
1395 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate"); 1687
1396 1688 last_animation_time_ = wall_clock_time;
1397 if (!rootScrollLayer()) 1689 double monotonic_seconds = (monotonic_time - base::TimeTicks()).InSecondsF();
1398 return; 1690
1399 1691 AnimationRegistrar::AnimationControllerMap copy =
1400 // Keep the center-of-pinch anchor specified by (x, y) in a stable 1692 animation_registrar_->active_animation_controllers();
1401 // position over the course of the magnify. 1693 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1402 float pageScaleDelta = activeTree()->page_scale_delta(); 1694 iter != copy.end();
1403 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta ); 1695 ++iter)
1404 activeTree()->SetPageScaleDelta(pageScaleDelta * magnifyDelta); 1696 (*iter).second->Animate(monotonic_seconds);
1405 pageScaleDelta = activeTree()->page_scale_delta(); 1697
1406 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta); 1698 client_->SetNeedsRedrawOnImplThread();
1407 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor; 1699 SetBackgroundTickingEnabled(
1408 1700 !visible_ &&
1409 m_previousPinchAnchor = anchor; 1701 !animation_registrar_->active_animation_controllers().empty());
1410 1702 }
1411 move.Scale(1 / activeTree()->page_scale_factor()); 1703
1412 1704 void LayerTreeHostImpl::UpdateAnimationState() {
1413 rootScrollLayer()->ScrollBy(move); 1705 if (!settings_.acceleratedAnimationEnabled ||
1414 1706 animation_registrar_->active_animation_controllers().empty() ||
1415 if (rootScrollLayer()->scrollbar_animation_controller()) 1707 !active_tree_->root_layer())
1416 rootScrollLayer()->scrollbar_animation_controller()->didPinchGestureUpda te(base::TimeTicks::Now()); 1708 return;
1417 1709
1418 m_client->setNeedsCommitOnImplThread(); 1710 TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState");
1419 m_client->setNeedsRedrawOnImplThread(); 1711 scoped_ptr<AnimationEventsVector> events =
1420 m_client->renewTreePriority(); 1712 make_scoped_ptr(new AnimationEventsVector);
1421 } 1713 AnimationRegistrar::AnimationControllerMap copy =
1422 1714 animation_registrar_->active_animation_controllers();
1423 void LayerTreeHostImpl::pinchGestureEnd() 1715 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1424 { 1716 iter != copy.end();
1425 m_pinchGestureActive = false; 1717 ++iter)
1426 1718 (*iter).second->UpdateState(events.get());
1427 if (rootScrollLayer() && rootScrollLayer()->scrollbar_animation_controller() ) 1719
1428 rootScrollLayer()->scrollbar_animation_controller()->didPinchGestureEnd( base::TimeTicks::Now()); 1720 if (!events->empty()) {
1429 1721 client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass(),
1430 m_client->setNeedsCommitOnImplThread(); 1722 last_animation_time_);
1431 } 1723 }
1432 1724 }
1433 static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerI mpl) 1725
1434 { 1726 base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const {
1435 if (!layerImpl) 1727 return base::TimeDelta::FromSeconds(1);
1436 return; 1728 }
1437 1729
1438 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scroll_delta() ); 1730 void LayerTreeHostImpl::SendDidLoseOutputSurfaceRecursive(LayerImpl* current) {
1439 if (!scrollDelta.IsZero()) { 1731 DCHECK(current);
1440 LayerTreeHostCommon::ScrollUpdateInfo scroll; 1732 current->DidLoseOutputSurface();
1441 scroll.layerId = layerImpl->id(); 1733 if (current->mask_layer())
1442 scroll.scrollDelta = scrollDelta; 1734 SendDidLoseOutputSurfaceRecursive(current->mask_layer());
1443 scrollInfo->scrolls.push_back(scroll); 1735 if (current->replica_layer())
1444 layerImpl->SetSentScrollDelta(scrollDelta); 1736 SendDidLoseOutputSurfaceRecursive(current->replica_layer());
1445 } 1737 for (size_t i = 0; i < current->children().size(); ++i)
1446 1738 SendDidLoseOutputSurfaceRecursive(current->children()[i]);
1447 for (size_t i = 0; i < layerImpl->children().size(); ++i) 1739 }
1448 collectScrollDeltas(scrollInfo, layerImpl->children()[i]); 1740
1449 } 1741 void LayerTreeHostImpl::ClearRenderSurfaces() {
1450 1742 active_tree_->ClearRenderSurfaces();
1451 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas() 1743 if (pending_tree_)
1452 { 1744 pending_tree_->ClearRenderSurfaces();
1453 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet()); 1745 }
1454 1746
1455 collectScrollDeltas(scrollInfo.get(), rootLayer()); 1747 std::string LayerTreeHostImpl::LayerTreeAsText() const {
1456 scrollInfo->pageScaleDelta = activeTree()->page_scale_delta(); 1748 std::string str;
1457 activeTree()->set_sent_page_scale_delta(scrollInfo->pageScaleDelta); 1749 if (active_tree_->root_layer()) {
1458 1750 str = active_tree_->root_layer()->LayerTreeAsText();
1459 return scrollInfo.Pass(); 1751 str += "RenderSurfaces:\n";
1460 } 1752 DumpRenderSurfaces(&str, 1, active_tree_->root_layer());
1461 1753 }
1462 void LayerTreeHostImpl::SetFullRootLayerDamage() 1754 return str;
1463 { 1755 }
1464 if (rootLayer()) { 1756
1465 RenderSurfaceImpl* renderSurface = rootLayer()->render_surface(); 1757 std::string LayerTreeHostImpl::LayerTreeAsJson() const {
1466 if (renderSurface) 1758 std::string str;
1467 renderSurface->damage_tracker()->ForceFullDamageNextUpdate(); 1759 if (active_tree_->root_layer()) {
1468 } 1760 scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson());
1469 } 1761 base::JSONWriter::WriteWithOptions(
1470 1762 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str);
1471 void LayerTreeHostImpl::animatePageScale(base::TimeTicks time) 1763 }
1472 { 1764 return str;
1473 if (!m_pageScaleAnimation || !rootScrollLayer()) 1765 }
1474 return; 1766
1475 1767 void LayerTreeHostImpl::DumpRenderSurfaces(std::string* str,
1476 double monotonicTime = (time - base::TimeTicks()).InSecondsF(); 1768 int indent,
1477 gfx::Vector2dF scrollTotal = rootScrollLayer()->scroll_offset() + rootScroll Layer()->scroll_delta(); 1769 const LayerImpl* layer) const {
1478 1770 if (layer->render_surface())
1479 activeTree()->SetPageScaleDelta(m_pageScaleAnimation->PageScaleFactorAtTime( monotonicTime) / activeTree()->page_scale_factor()); 1771 layer->render_surface()->DumpSurface(str, indent);
1480 gfx::Vector2dF nextScroll = m_pageScaleAnimation->ScrollOffsetAtTime(monoton icTime); 1772
1481 1773 for (size_t i = 0; i < layer->children().size(); ++i)
1482 rootScrollLayer()->ScrollBy(nextScroll - scrollTotal); 1774 DumpRenderSurfaces(str, indent, layer->children()[i]);
1483 m_client->setNeedsRedrawOnImplThread(); 1775 }
1484 1776
1485 if (m_pageScaleAnimation->IsAnimationCompleteAtTime(monotonicTime)) { 1777 int LayerTreeHostImpl::SourceAnimationFrameNumber() const {
1486 m_pageScaleAnimation.reset(); 1778 return fps_counter_->currentFrameNumber();
1487 m_client->setNeedsCommitOnImplThread(); 1779 }
1488 m_client->renewTreePriority(); 1780
1489 } 1781 void LayerTreeHostImpl::CollectRenderingStats(RenderingStats* stats) const {
1490 } 1782 stats->numFramesSentToScreen = fps_counter_->currentFrameNumber();
1491 1783 stats->droppedFrameCount = fps_counter_->droppedFrameCount();
1492 void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime) 1784 stats->numImplThreadScrolls = num_impl_thread_scrolls_;
1493 { 1785 stats->numMainThreadScrolls = num_main_thread_scrolls_;
1494 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_ animation_controllers().empty() || !rootLayer()) 1786 stats->numLayersDrawn = cumulative_num_layers_drawn_;
1495 return; 1787 stats->numMissingTiles = cumulative_num_missing_tiles_;
1496 1788
1497 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers"); 1789 if (tile_manager_)
1498 1790 tile_manager_->GetRenderingStats(stats);
1499 m_lastAnimationTime = wallClockTime; 1791 }
1500 double monotonicSeconds = (monotonicTime - base::TimeTicks()).InSecondsF(); 1792
1501 1793 void LayerTreeHostImpl::SendManagedMemoryStats(
1502 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->acti ve_animation_controllers(); 1794 size_t memory_visible_bytes,
1503 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin( ); iter != copy.end(); ++iter) 1795 size_t memory_visible_and_nearby_bytes,
1504 (*iter).second->Animate(monotonicSeconds); 1796 size_t memory_use_bytes) {
1505 1797 if (!renderer_)
1506 m_client->setNeedsRedrawOnImplThread(); 1798 return;
1507 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_anim ation_controllers().empty()); 1799
1508 } 1800 // Round the numbers being sent up to the next 8MB, to throttle the rate
1509 1801 // at which we spam the GPU process.
1510 void LayerTreeHostImpl::updateAnimationState() 1802 static const size_t rounding_step = 8 * 1024 * 1024;
1511 { 1803 memory_visible_bytes = RoundUp(memory_visible_bytes, rounding_step);
1512 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_ animation_controllers().empty() || !rootLayer()) 1804 memory_visible_and_nearby_bytes = RoundUp(memory_visible_and_nearby_bytes,
1513 return; 1805 rounding_step);
1514 1806 memory_use_bytes = RoundUp(memory_use_bytes, rounding_step);
1515 TRACE_EVENT0("cc", "LayerTreeHostImpl::updateAnimationState"); 1807 if (last_sent_memory_visible_bytes_ == memory_visible_bytes &&
1516 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEvents Vector)); 1808 last_sent_memory_visible_and_nearby_bytes_ ==
1517 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->acti ve_animation_controllers(); 1809 memory_visible_and_nearby_bytes &&
1518 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin( ); iter != copy.end(); ++iter) 1810 last_sent_memory_use_bytes_ == memory_use_bytes) {
1519 (*iter).second->UpdateState(events.get()); 1811 return;
1520 1812 }
1521 if (!events->empty()) 1813 last_sent_memory_visible_bytes_ = memory_visible_bytes;
1522 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), m_l astAnimationTime); 1814 last_sent_memory_visible_and_nearby_bytes_ = memory_visible_and_nearby_bytes;
1523 } 1815 last_sent_memory_use_bytes_ = memory_use_bytes;
1524 1816
1525 base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const 1817 renderer_->SendManagedMemoryStats(last_sent_memory_visible_bytes_,
1526 { 1818 last_sent_memory_visible_and_nearby_bytes_,
1527 return base::TimeDelta::FromSeconds(1); 1819 last_sent_memory_use_bytes_);
1528 } 1820 }
1529 1821
1530 void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl* current) 1822 void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) {
1531 { 1823 AnimateScrollbarsRecursive(active_tree_->root_layer(), time);
1532 DCHECK(current); 1824 }
1533 current->DidLoseOutputSurface(); 1825
1534 if (current->mask_layer()) 1826 void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer,
1535 sendDidLoseOutputSurfaceRecursive(current->mask_layer()); 1827 base::TimeTicks time) {
1536 if (current->replica_layer()) 1828 if (!layer)
1537 sendDidLoseOutputSurfaceRecursive(current->replica_layer()); 1829 return;
1538 for (size_t i = 0; i < current->children().size(); ++i) 1830
1539 sendDidLoseOutputSurfaceRecursive(current->children()[i]); 1831 ScrollbarAnimationController* scrollbar_controller =
1540 } 1832 layer->scrollbar_animation_controller();
1541 1833 if (scrollbar_controller && scrollbar_controller->animate(time))
1542 void LayerTreeHostImpl::clearRenderSurfaces() 1834 client_->SetNeedsRedrawOnImplThread();
1543 { 1835
1544 activeTree()->ClearRenderSurfaces(); 1836 for (size_t i = 0; i < layer->children().size(); ++i)
1545 if (pendingTree()) 1837 AnimateScrollbarsRecursive(layer->children()[i], time);
1546 pendingTree()->ClearRenderSurfaces(); 1838 }
1547 } 1839
1548 1840 void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
1549 std::string LayerTreeHostImpl::layerTreeAsText() const 1841 if (!tile_manager_)
1550 { 1842 return;
1551 std::string str; 1843
1552 if (rootLayer()) { 1844 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
1553 str = rootLayer()->LayerTreeAsText(); 1845 if (new_state.tree_priority == priority)
1554 str += "RenderSurfaces:\n"; 1846 return;
1555 dumpRenderSurfaces(&str, 1, rootLayer()); 1847
1556 } 1848 new_state.tree_priority = priority;
1557 return str; 1849 tile_manager_->SetGlobalState(new_state);
1558 } 1850 }
1559 1851
1560 std::string LayerTreeHostImpl::layerTreeAsJson() const 1852 void LayerTreeHostImpl::BeginNextFrame() {
1561 { 1853 current_frame_time_ = base::TimeTicks();
1562 std::string str; 1854 }
1563 if (rootLayer()) { 1855
1564 scoped_ptr<base::Value> json(rootLayer()->LayerTreeAsJson()); 1856 base::TimeTicks LayerTreeHostImpl::CurrentFrameTime() {
1565 base::JSONWriter::WriteWithOptions( 1857 if (current_frame_time_.is_null())
1566 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); 1858 current_frame_time_ = base::TimeTicks::Now();
1567 } 1859 return current_frame_time_;
1568 return str; 1860 }
1569 } 1861
1570 1862 scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const {
1571 void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const L ayerImpl* layer) const 1863 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1572 { 1864 state->Set("activation_state", ActivationStateAsValue().release());
1573 if (layer->render_surface()) 1865 state->Set("frame_state", FrameStateAsValue().release());
1574 layer->render_surface()->DumpSurface(str, indent); 1866 return state.PassAs<base::Value>();
1575 1867 }
1576 for (size_t i = 0; i < layer->children().size(); ++i) 1868
1577 dumpRenderSurfaces(str, indent, layer->children()[i]); 1869 scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const {
1578 } 1870 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1579 1871 state->SetString("lthi_id", StringPrintf("%p", this));
1580 int LayerTreeHostImpl::sourceAnimationFrameNumber() const 1872 state->SetBoolean("visible_resources_ready",
1581 { 1873 pending_tree_->AreVisibleResourcesReady());
1582 return fpsCounter()->currentFrameNumber(); 1874 state->Set("tile_manager", tile_manager_->BasicStateAsValue().release());
1583 } 1875 return state.PassAs<base::Value>();
1584 1876 }
1585 void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const 1877
1586 { 1878 scoped_ptr<base::Value> LayerTreeHostImpl::FrameStateAsValue() const {
1587 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber(); 1879 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1588 stats->droppedFrameCount = fpsCounter()->droppedFrameCount(); 1880 state->SetString("lthi_id", StringPrintf("%p", this));
1589 stats->numImplThreadScrolls = m_numImplThreadScrolls; 1881 state->Set("device_viewport_size",
1590 stats->numMainThreadScrolls = m_numMainThreadScrolls; 1882 MathUtil::asValue(device_viewport_size_).release());
1591 stats->numLayersDrawn = m_cumulativeNumLayersDrawn; 1883 if (tile_manager_)
1592 stats->numMissingTiles = m_cumulativeNumMissingTiles; 1884 state->Set("tiles", tile_manager_->AllTilesAsValue().release());
1593 1885 state->Set("active_tree", active_tree_->AsValue().release());
1594 if (m_tileManager) 1886 return state.PassAs<base::Value>();
1595 m_tileManager->GetRenderingStats(stats);
1596 }
1597
1598 void LayerTreeHostImpl::sendManagedMemoryStats(
1599 size_t memoryVisibleBytes,
1600 size_t memoryVisibleAndNearbyBytes,
1601 size_t memoryUseBytes)
1602 {
1603 if (!renderer())
1604 return;
1605
1606 // Round the numbers being sent up to the next 8MB, to throttle the rate
1607 // at which we spam the GPU process.
1608 static const size_t roundingStep = 8 * 1024 * 1024;
1609 memoryVisibleBytes = RoundUp(memoryVisibleBytes, roundingStep);
1610 memoryVisibleAndNearbyBytes = RoundUp(memoryVisibleAndNearbyBytes, roundingS tep);
1611 memoryUseBytes = RoundUp(memoryUseBytes, roundingStep);
1612 if (m_lastSentMemoryVisibleBytes == memoryVisibleBytes &&
1613 m_lastSentMemoryVisibleAndNearbyBytes == memoryVisibleAndNearbyBytes &&
1614 m_lastSentMemoryUseBytes == memoryUseBytes) {
1615 return;
1616 }
1617 m_lastSentMemoryVisibleBytes = memoryVisibleBytes;
1618 m_lastSentMemoryVisibleAndNearbyBytes = memoryVisibleAndNearbyBytes;
1619 m_lastSentMemoryUseBytes = memoryUseBytes;
1620
1621 renderer()->SendManagedMemoryStats(m_lastSentMemoryVisibleBytes,
1622 m_lastSentMemoryVisibleAndNearbyBytes,
1623 m_lastSentMemoryUseBytes);
1624 }
1625
1626 void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time)
1627 {
1628 animateScrollbarsRecursive(rootLayer(), time);
1629 }
1630
1631 void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeT icks time)
1632 {
1633 if (!layer)
1634 return;
1635
1636 ScrollbarAnimationController* scrollbarController = layer->scrollbar_animati on_controller();
1637 if (scrollbarController && scrollbarController->animate(time))
1638 m_client->setNeedsRedrawOnImplThread();
1639
1640 for (size_t i = 0; i < layer->children().size(); ++i)
1641 animateScrollbarsRecursive(layer->children()[i], time);
1642 }
1643
1644 void LayerTreeHostImpl::setTreePriority(TreePriority priority)
1645 {
1646 if (!m_tileManager)
1647 return;
1648
1649 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState());
1650 if (new_state.tree_priority == priority)
1651 return;
1652
1653 new_state.tree_priority = priority;
1654 m_tileManager->SetGlobalState(new_state);
1655 }
1656
1657 void LayerTreeHostImpl::beginNextFrame()
1658 {
1659 m_currentFrameTime = base::TimeTicks();
1660 }
1661
1662 base::TimeTicks LayerTreeHostImpl::currentFrameTime()
1663 {
1664 if (m_currentFrameTime.is_null())
1665 m_currentFrameTime = base::TimeTicks::Now();
1666 return m_currentFrameTime;
1667 }
1668
1669 scoped_ptr<base::Value> LayerTreeHostImpl::asValue() const
1670 {
1671 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1672 state->Set("activation_state", activationStateAsValue().release());
1673 state->Set("frame_state", frameStateAsValue().release());
1674 return state.PassAs<base::Value>();
1675 }
1676
1677 scoped_ptr<base::Value> LayerTreeHostImpl::activationStateAsValue() const
1678 {
1679 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1680 state->SetString("lthi_id", StringPrintf("%p", this));
1681 state->SetBoolean("visible_resources_ready", pendingTree()->AreVisibleResour cesReady());
1682 state->Set("tile_manager", m_tileManager->BasicStateAsValue().release());
1683 return state.PassAs<base::Value>();
1684 }
1685
1686 scoped_ptr<base::Value> LayerTreeHostImpl::frameStateAsValue() const
1687 {
1688 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1689 state->SetString("lthi_id", StringPrintf("%p", this));
1690 state->Set("device_viewport_size", MathUtil::asValue(m_deviceViewportSize).r elease());
1691 if (m_tileManager)
1692 state->Set("tiles", m_tileManager->AllTilesAsValue().release());
1693 state->Set("active_tree", activeTree()->AsValue().release());
1694 return state.PassAs<base::Value>();
1695 } 1887 }
1696 1888
1697 // static 1889 // static
1698 LayerImpl* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl* l ayer) 1890 LayerImpl* LayerTreeHostImpl::GetNonCompositedContentLayerRecursive(
1699 { 1891 LayerImpl* layer) {
1700 if (!layer) 1892 if (!layer)
1701 return NULL;
1702
1703 if (layer->DrawsContent())
1704 return layer;
1705
1706 for (LayerImpl::LayerList::const_iterator it = layer->children().begin();
1707 it != layer->children().end(); ++it) {
1708 LayerImpl* nccr = getNonCompositedContentLayerRecursive(*it);
1709 if (nccr)
1710 return nccr;
1711 }
1712
1713 return NULL; 1893 return NULL;
1714 } 1894
1715 1895 if (layer->DrawsContent())
1716 skia::RefPtr<SkPicture> LayerTreeHostImpl::capturePicture() 1896 return layer;
1717 { 1897
1718 LayerTreeImpl* tree = pendingTree() ? pendingTree() : activeTree(); 1898 for (LayerImpl::LayerList::const_iterator it = layer->children().begin();
1719 LayerImpl* layer = getNonCompositedContentLayerRecursive(tree->RootLayer()); 1899 it != layer->children().end(); ++it) {
1720 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>(); 1900 LayerImpl* nccr = GetNonCompositedContentLayerRecursive(*it);
1721 } 1901 if (nccr)
1722 1902 return nccr;
1723 void LayerTreeHostImpl::setDebugState(const LayerTreeDebugState& debugState) 1903 }
1724 { 1904
1725 if (m_debugState.continuousPainting != debugState.continuousPainting) 1905 return NULL;
1726 m_paintTimeCounter->ClearHistory(); 1906 }
1727 1907
1728 m_debugState = debugState; 1908 skia::RefPtr<SkPicture> LayerTreeHostImpl::CapturePicture() {
1729 1909 LayerTreeImpl* tree =
1730 if (m_tileManager) 1910 pending_tree_ ? pending_tree_.get() : active_tree_.get();
1731 m_tileManager->SetRecordRenderingStats(m_debugState.recordRenderingStats ()); 1911 LayerImpl* layer = GetNonCompositedContentLayerRecursive(tree->root_layer());
1732 } 1912 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>();
1733 1913 }
1734 void LayerTreeHostImpl::savePaintTime(const base::TimeDelta& totalPaintTime, int commitNumber) 1914
1735 { 1915 void LayerTreeHostImpl::SetDebugState(const LayerTreeDebugState& debug_state) {
1736 DCHECK(m_debugState.continuousPainting); 1916 if (debug_state_.continuousPainting != debug_state.continuousPainting)
1737 m_paintTimeCounter->SavePaintTime(totalPaintTime, commitNumber); 1917 paint_time_counter_->ClearHistory();
1918
1919 debug_state_ = debug_state;
1920
1921 if (tile_manager_)
1922 tile_manager_->SetRecordRenderingStats(debug_state_.recordRenderingStats());
1923 }
1924
1925 void LayerTreeHostImpl::SavePaintTime(const base::TimeDelta& total_paint_time,
1926 int commit_number) {
1927 DCHECK(debug_state_.continuousPainting);
1928 paint_time_counter_->SavePaintTime(total_paint_time, commit_number);
1738 } 1929 }
1739 1930
1740 } // namespace cc 1931 } // namespace cc
OLDNEW
« no previous file with comments | « cc/layer_tree_host_impl.h ('k') | cc/layer_tree_host_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698