1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layer_tree_host_impl.h"
9 #include "base/basictypes.h"
10 #include "base/debug/trace_event.h"
11 #include "base/json/json_writer.h"
12 #include "base/metrics/histogram.h"
13 #include "base/stl_util.h"
14 #include "base/stringprintf.h"
15 #include "cc/append_quads_data.h"
16 #include "cc/compositor_frame_metadata.h"
17 #include "cc/damage_tracker.h"
18 #include "cc/debug_rect_history.h"
19 #include "cc/delay_based_time_source.h"
20 #include "cc/delegating_renderer.h"
21 #include "cc/frame_rate_counter.h"
22 #include "cc/gl_renderer.h"
23 #include "cc/heads_up_display_layer_impl.h"
24 #include "cc/layer_iterator.h"
25 #include "cc/layer_tree_host.h"
26 #include "cc/layer_tree_host_common.h"
27 #include "cc/layer_tree_impl.h"
28 #include "cc/math_util.h"
29 #include "cc/memory_history.h"
30 #include "cc/overdraw_metrics.h"
31 #include "cc/page_scale_animation.h"
32 #include "cc/paint_time_counter.h"
33 #include "cc/picture_layer_tiling.h"
34 #include "cc/prioritized_resource_manager.h"
35 #include "cc/quad_culler.h"
36 #include "cc/render_pass_draw_quad.h"
37 #include "cc/rendering_stats.h"
38 #include "cc/scrollbar_animation_controller.h"
39 #include "cc/scrollbar_layer_impl.h"
40 #include "cc/shared_quad_state.h"
41 #include "cc/single_thread_proxy.h"
42 #include "cc/software_renderer.h"
43 #include "cc/solid_color_draw_quad.h"
44 #include "cc/texture_uploader.h"
45 #include "cc/top_controls_manager.h"
46 #include "cc/tree_synchronizer.h"
48 #include "ui/gfx/size_conversions.h"
49 #include "ui/gfx/vector2d_conversions.h"
53 void didVisibilityChange(cc::LayerTreeHostImpl
* id
, bool visible
)
56 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id
, "LayerTreeHostImpl", id
);
60 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id
);
63 std::string
ValueToString(scoped_ptr
<base::Value
> value
)
66 base::JSONWriter::Write(value
.get(), &str
);
74 class LayerTreeHostImplTimeSourceAdapter
: public TimeSourceClient
{
76 static scoped_ptr
<LayerTreeHostImplTimeSourceAdapter
> create(LayerTreeHostImpl
* layerTreeHostImpl
, scoped_refptr
<DelayBasedTimeSource
> timeSource
)
78 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl
, timeSource
));
80 virtual ~LayerTreeHostImplTimeSourceAdapter()
82 m_timeSource
->setClient(0);
83 m_timeSource
->setActive(false);
86 virtual void onTimerTick() OVERRIDE
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()));
106 m_layerTreeHostImpl
->activatePendingTreeIfNeeded();
107 m_layerTreeHostImpl
->animate(base::TimeTicks::Now(), base::Time::Now());
108 m_layerTreeHostImpl
->beginNextFrame();
111 void setActive(bool active
)
113 if (active
!= m_timeSource
->active())
114 m_timeSource
->setActive(active
);
118 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl
* layerTreeHostImpl
, scoped_refptr
<DelayBasedTimeSource
> timeSource
)
119 : m_layerTreeHostImpl(layerTreeHostImpl
)
120 , m_timeSource(timeSource
)
122 m_timeSource
->setClient(this);
125 LayerTreeHostImpl
* m_layerTreeHostImpl
;
126 scoped_refptr
<DelayBasedTimeSource
> m_timeSource
;
128 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter
);
131 LayerTreeHostImpl::FrameData::FrameData()
132 : containsIncompleteTile(false)
136 LayerTreeHostImpl::FrameData::~FrameData()
140 scoped_ptr
<LayerTreeHostImpl
> LayerTreeHostImpl::create(const LayerTreeSettings
& settings
, LayerTreeHostImplClient
* client
, Proxy
* proxy
)
142 return make_scoped_ptr(new LayerTreeHostImpl(settings
, client
, proxy
));
145 LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings
& settings
, LayerTreeHostImplClient
* client
, Proxy
* proxy
)
148 , m_didLockScrollingLayer(false)
149 , m_shouldBubbleScrolls(false)
150 , m_wheelScrolling(false)
151 , m_settings(settings
)
152 , m_deviceScaleFactor(1)
154 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationLimit(),
155 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING
,
157 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING
)
158 , m_pinchGestureActive(false)
159 , m_fpsCounter(FrameRateCounter::create(m_proxy
->hasImplThread()))
160 , m_paintTimeCounter(PaintTimeCounter::create())
161 , m_memoryHistory(MemoryHistory::create())
162 , m_debugRectHistory(DebugRectHistory::create())
163 , m_numImplThreadScrolls(0)
164 , m_numMainThreadScrolls(0)
165 , m_cumulativeNumLayersDrawn(0)
166 , m_cumulativeNumMissingTiles(0)
167 , m_lastSentMemoryVisibleBytes(0)
168 , m_lastSentMemoryVisibleAndNearbyBytes(0)
169 , m_lastSentMemoryUseBytes(0)
170 , m_animationRegistrar(AnimationRegistrar::create())
172 DCHECK(m_proxy
->isImplThread());
173 didVisibilityChange(this, m_visible
);
175 setDebugState(settings
.initialDebugState
);
177 if (settings
.calculateTopControlsPosition
)
178 m_topControlsManager
= TopControlsManager::Create(this, settings
.topControlsHeight
);
180 setDebugState(settings
.initialDebugState
);
182 // LTHI always has an active tree.
183 m_activeTree
= LayerTreeImpl::create(this);
186 LayerTreeHostImpl::~LayerTreeHostImpl()
188 DCHECK(m_proxy
->isImplThread());
189 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
192 clearRenderSurfaces();
193 // The layer trees must be destroyed before the layer tree host. We've
194 // made a contract with our animation controllers that the registrar
195 // will outlive them, and we must make good.
196 m_recycleTree
.reset();
197 m_pendingTree
.reset();
198 m_activeTree
.reset();
202 void LayerTreeHostImpl::beginCommit()
206 void LayerTreeHostImpl::commitComplete()
208 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete");
210 // Impl-side painting needs an update immediately post-commit to have the
211 // opportunity to create tilings. Other paths can call updateDrawProperties
212 // more lazily when needed prior to drawing.
213 if (m_settings
.implSidePainting
) {
214 pendingTree()->set_needs_update_draw_properties();
215 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE
);
217 activeTree()->set_needs_update_draw_properties();
220 m_client
->sendManagedMemoryStats();
223 bool LayerTreeHostImpl::canDraw()
225 // Note: If you are changing this function or any other function that might
226 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
227 // in the proper places and update the notifyIfCanDrawChanged test.
230 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
233 if (deviceViewportSize().IsEmpty()) {
234 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
237 if (m_activeTree
->ViewportSizeInvalid()) {
238 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw viewport size recently changed");
242 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
245 if (m_activeTree
->ContentsTexturesPurged()) {
246 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
252 OutputSurface
* LayerTreeHostImpl::outputSurface() const
254 return m_outputSurface
.get();
257 void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime
, base::Time wallClockTime
)
259 animatePageScale(monotonicTime
);
260 animateLayers(monotonicTime
, wallClockTime
);
261 animateScrollbars(monotonicTime
);
262 if (m_topControlsManager
)
263 m_topControlsManager
->Animate(monotonicTime
);
266 void LayerTreeHostImpl::manageTiles()
268 DCHECK(m_tileManager
);
269 m_tileManager
->ManageTiles();
271 size_t memoryRequiredBytes
;
272 size_t memoryNiceToHaveBytes
;
273 size_t memoryUsedBytes
;
274 m_tileManager
->GetMemoryStats(&memoryRequiredBytes
,
275 &memoryNiceToHaveBytes
,
277 sendManagedMemoryStats(memoryRequiredBytes
,
278 memoryNiceToHaveBytes
,
282 void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset
, bool anchorPoint
, float pageScale
, base::TimeTicks startTime
, base::TimeDelta duration
)
284 if (!rootScrollLayer())
287 gfx::Vector2dF scrollTotal
= rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
288 gfx::SizeF scaledScrollableSize
= activeTree()->ScrollableSize();
289 if (!m_settings
.pageScalePinchZoomEnabled
) {
290 scrollTotal
.Scale(1 / activeTree()->page_scale_factor());
291 scaledScrollableSize
.Scale(1 / activeTree()->page_scale_factor());
293 gfx::SizeF viewportSize
= gfx::ScaleSize(m_deviceViewportSize
, 1 / m_deviceScaleFactor
);
295 double startTimeSeconds
= (startTime
- base::TimeTicks()).InSecondsF();
296 m_pageScaleAnimation
= PageScaleAnimation::create(scrollTotal
, activeTree()->total_page_scale_factor(), viewportSize
, scaledScrollableSize
, startTimeSeconds
);
299 gfx::Vector2dF
anchor(targetOffset
);
300 if (!m_settings
.pageScalePinchZoomEnabled
)
301 anchor
.Scale(1 / pageScale
);
302 m_pageScaleAnimation
->zoomWithAnchor(anchor
, pageScale
, duration
.InSecondsF());
304 gfx::Vector2dF scaledTargetOffset
= targetOffset
;
305 if (!m_settings
.pageScalePinchZoomEnabled
)
306 scaledTargetOffset
.Scale(1 / pageScale
);
307 m_pageScaleAnimation
->zoomTo(scaledTargetOffset
, pageScale
, duration
.InSecondsF());
310 m_client
->setNeedsRedrawOnImplThread();
311 m_client
->setNeedsCommitOnImplThread();
314 void LayerTreeHostImpl::scheduleAnimation()
316 m_client
->setNeedsRedrawOnImplThread();
319 bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point
& viewportPoint
)
321 if (!ensureRenderSurfaceLayerList())
324 gfx::PointF deviceViewportPoint
= gfx::ScalePoint(viewportPoint
, m_deviceScaleFactor
);
326 // First find out which layer was hit from the saved list of visible layers
327 // in the most recent frame.
328 LayerImpl
* layerImpl
= LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint
, activeTree()->RenderSurfaceLayerList());
330 // Walk up the hierarchy and look for a layer with a touch event handler region that the given point hits.
331 for (; layerImpl
; layerImpl
= layerImpl
->parent()) {
332 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(deviceViewportPoint
,layerImpl
))
339 void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl
* rootDrawLayer
, const LayerList
& renderSurfaceLayerList
)
341 // For now, we use damage tracking to compute a global scissor. To do this, we must
342 // compute all damage tracking before drawing anything, so that we know the root
343 // damage rect. The root damage rect is then used to scissor each surface.
345 for (int surfaceIndex
= renderSurfaceLayerList
.size() - 1; surfaceIndex
>= 0 ; --surfaceIndex
) {
346 LayerImpl
* renderSurfaceLayer
= renderSurfaceLayerList
[surfaceIndex
];
347 RenderSurfaceImpl
* renderSurface
= renderSurfaceLayer
->renderSurface();
348 DCHECK(renderSurface
);
349 renderSurface
->damageTracker()->updateDamageTrackingState(renderSurface
->layerList(), renderSurfaceLayer
->id(), renderSurface
->surfacePropertyChangedOnlyFromDescendant(), renderSurface
->contentRect(), renderSurfaceLayer
->maskLayer(), renderSurfaceLayer
->filters(), renderSurfaceLayer
->filter().get());
353 void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr
<RenderPass
> renderPass
)
355 renderPassesById
[renderPass
->id
] = renderPass
.get();
356 renderPasses
.push_back(renderPass
.Pass());
359 static void appendQuadsForLayer(RenderPass
* targetRenderPass
, LayerImpl
* layer
, OcclusionTrackerImpl
& occlusionTracker
, AppendQuadsData
& appendQuadsData
)
361 bool forSurface
= false;
362 QuadCuller
quadCuller(targetRenderPass
->quad_list
,
363 targetRenderPass
->shared_quad_state_list
,
366 layer
->showDebugBorders(),
368 layer
->appendQuads(quadCuller
, appendQuadsData
);
371 static void appendQuadsForRenderSurfaceLayer(RenderPass
* targetRenderPass
, LayerImpl
* layer
, const RenderPass
* contributingRenderPass
, OcclusionTrackerImpl
& occlusionTracker
, AppendQuadsData
& appendQuadsData
)
373 bool forSurface
= true;
374 QuadCuller
quadCuller(targetRenderPass
->quad_list
,
375 targetRenderPass
->shared_quad_state_list
,
378 layer
->showDebugBorders(),
381 bool isReplica
= false;
382 layer
->renderSurface()->appendQuads(quadCuller
,
385 contributingRenderPass
->id
);
387 // Add replica after the surface so that it appears below the surface.
388 if (layer
->hasReplica()) {
390 layer
->renderSurface()->appendQuads(quadCuller
,
393 contributingRenderPass
->id
);
397 static void appendQuadsToFillScreen(RenderPass
* targetRenderPass
, LayerImpl
* rootLayer
, SkColor screenBackgroundColor
, const OcclusionTrackerImpl
& occlusionTracker
)
399 if (!rootLayer
|| !SkColorGetA(screenBackgroundColor
))
402 Region fillRegion
= occlusionTracker
.computeVisibleRegionInScreen();
403 if (fillRegion
.IsEmpty())
406 bool forSurface
= false;
407 QuadCuller
quadCuller(targetRenderPass
->quad_list
,
408 targetRenderPass
->shared_quad_state_list
,
411 rootLayer
->showDebugBorders(),
414 // Manually create the quad state for the gutter quads, as the root layer
415 // doesn't have any bounds and so can't generate this itself.
416 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
418 gfx::Rect rootTargetRect
= rootLayer
->renderSurface()->contentRect();
420 SharedQuadState
* sharedQuadState
= quadCuller
.useSharedQuadState(SharedQuadState::Create());
421 sharedQuadState
->SetAll(rootLayer
->drawTransform(),
427 AppendQuadsData appendQuadsData
;
429 gfx::Transform
transformToLayerSpace(gfx::Transform::kSkipInitialization
);
430 bool didInvert
= rootLayer
->screenSpaceTransform().GetInverse(&transformToLayerSpace
);
432 for (Region::Iterator
fillRects(fillRegion
); fillRects
.has_rect(); fillRects
.next()) {
433 // The root layer transform is composed of translations and scales only,
434 // no perspective, so mapping is sufficient (as opposed to projecting).
435 gfx::Rect layerRect
= MathUtil::mapClippedRect(transformToLayerSpace
, fillRects
.rect());
436 // Skip the quad culler and just append the quads directly to avoid
438 scoped_ptr
<SolidColorDrawQuad
> quad
= SolidColorDrawQuad::Create();
439 quad
->SetNew(sharedQuadState
, layerRect
, screenBackgroundColor
);
440 quadCuller
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
444 bool LayerTreeHostImpl::calculateRenderPasses(FrameData
& frame
)
446 DCHECK(frame
.renderPasses
.empty());
448 if (!canDraw() || !rootLayer())
451 trackDamageForAllSurfaces(rootLayer(), *frame
.renderSurfaceLayerList
);
453 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame
.renderSurfaceLayerList
->size()));
455 // Create the render passes in dependency order.
456 for (int surfaceIndex
= frame
.renderSurfaceLayerList
->size() - 1; surfaceIndex
>= 0 ; --surfaceIndex
) {
457 LayerImpl
* renderSurfaceLayer
= (*frame
.renderSurfaceLayerList
)[surfaceIndex
];
458 renderSurfaceLayer
->renderSurface()->appendRenderPasses(frame
);
461 bool recordMetricsForFrame
= m_settings
.showOverdrawInTracing
&& base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
462 OcclusionTrackerImpl
occlusionTracker(rootLayer()->renderSurface()->contentRect(), recordMetricsForFrame
);
463 occlusionTracker
.setMinimumTrackingSize(m_settings
.minimumOcclusionTrackingSize
);
465 if (m_debugState
.showOccludingRects
)
466 occlusionTracker
.setOccludingScreenSpaceRectsContainer(&frame
.occludingScreenSpaceRects
);
467 if (m_debugState
.showNonOccludingRects
)
468 occlusionTracker
.setNonOccludingScreenSpaceRectsContainer(&frame
.nonOccludingScreenSpaceRects
);
470 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
471 typedef LayerIterator
<LayerImpl
, std::vector
<LayerImpl
*>, RenderSurfaceImpl
, LayerIteratorActions::FrontToBack
> LayerIteratorType
;
473 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
474 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
476 bool drawFrame
= true;
478 LayerIteratorType end
= LayerIteratorType::end(frame
.renderSurfaceLayerList
);
479 for (LayerIteratorType it
= LayerIteratorType::begin(frame
.renderSurfaceLayerList
); it
!= end
; ++it
) {
480 RenderPass::Id targetRenderPassId
= it
.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
481 RenderPass
* targetRenderPass
= frame
.renderPassesById
[targetRenderPassId
];
483 occlusionTracker
.enterLayer(it
);
485 AppendQuadsData
appendQuadsData(targetRenderPass
->id
);
487 if (it
.representsContributingRenderSurface()) {
488 RenderPass::Id contributingRenderPassId
= it
->renderSurface()->renderPassId();
489 RenderPass
* contributingRenderPass
= frame
.renderPassesById
[contributingRenderPassId
];
490 appendQuadsForRenderSurfaceLayer(targetRenderPass
, *it
, contributingRenderPass
, occlusionTracker
, appendQuadsData
);
491 } else if (it
.representsItself() && !it
->visibleContentRect().IsEmpty()) {
492 bool hasOcclusionFromOutsideTargetSurface
;
493 bool implDrawTransformIsUnknown
= false;
494 if (occlusionTracker
.occluded(it
->renderTarget(), it
->visibleContentRect(), it
->drawTransform(), implDrawTransformIsUnknown
, it
->isClipped(), it
->clipRect(), &hasOcclusionFromOutsideTargetSurface
))
495 appendQuadsData
.hadOcclusionFromOutsideTargetSurface
|= hasOcclusionFromOutsideTargetSurface
;
497 DCHECK_EQ(activeTree(), it
->layerTreeImpl());
498 it
->willDraw(m_resourceProvider
.get());
499 frame
.willDrawLayers
.push_back(*it
);
501 if (it
->hasContributingDelegatedRenderPasses()) {
502 RenderPass::Id contributingRenderPassId
= it
->firstContributingRenderPassId();
503 while (frame
.renderPassesById
.find(contributingRenderPassId
) != frame
.renderPassesById
.end()) {
504 RenderPass
* renderPass
= frame
.renderPassesById
[contributingRenderPassId
];
506 AppendQuadsData
appendQuadsData(renderPass
->id
);
507 appendQuadsForLayer(renderPass
, *it
, occlusionTracker
, appendQuadsData
);
509 contributingRenderPassId
= it
->nextContributingRenderPassId(contributingRenderPassId
);
513 appendQuadsForLayer(targetRenderPass
, *it
, occlusionTracker
, appendQuadsData
);
516 ++m_cumulativeNumLayersDrawn
;
519 if (appendQuadsData
.hadOcclusionFromOutsideTargetSurface
)
520 targetRenderPass
->has_occlusion_from_outside_target_surface
= true;
522 if (appendQuadsData
.numMissingTiles
) {
523 m_cumulativeNumMissingTiles
+= appendQuadsData
.numMissingTiles
;
524 bool layerHasAnimatingTransform
= it
->screenSpaceTransformIsAnimating() || it
->drawTransformIsAnimating();
525 if (layerHasAnimatingTransform
)
529 if (appendQuadsData
.hadIncompleteTile
)
530 frame
.containsIncompleteTile
= true;
532 occlusionTracker
.leaveLayer(it
);
536 for (size_t i
= 0; i
< frame
.renderPasses
.size(); ++i
) {
537 for (size_t j
= 0; j
< frame
.renderPasses
[i
]->quad_list
.size(); ++j
)
538 DCHECK(frame
.renderPasses
[i
]->quad_list
[j
]->shared_quad_state
);
539 DCHECK(frame
.renderPassesById
.find(frame
.renderPasses
[i
]->id
)
540 != frame
.renderPassesById
.end());
543 DCHECK(frame
.renderPasses
.back()->output_rect
.origin().IsOrigin());
545 if (!activeTree()->has_transparent_background()) {
546 frame
.renderPasses
.back()->has_transparent_background
= false;
547 appendQuadsToFillScreen(frame
.renderPasses
.back(), rootLayer(), activeTree()->background_color(), occlusionTracker
);
551 occlusionTracker
.overdrawMetrics().recordMetrics(this);
553 removeRenderPasses(CullRenderPassesWithNoQuads(), frame
);
554 m_renderer
->decideRenderPassAllocationsForFrame(frame
.renderPasses
);
555 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer
), frame
);
560 void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled
)
562 // Lazily create the timeSource adapter so that we can vary the interval for testing.
563 if (!m_timeSourceClientAdapter
)
564 m_timeSourceClientAdapter
= LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy
->currentThread()));
566 m_timeSourceClientAdapter
->setActive(enabled
);
569 static inline RenderPass
* findRenderPassById(RenderPass::Id renderPassId
, const LayerTreeHostImpl::FrameData
& frame
)
571 RenderPassIdHashMap::const_iterator it
= frame
.renderPassesById
.find(renderPassId
);
572 return it
!= frame
.renderPassesById
.end() ? it
->second
: NULL
;
575 static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId
, LayerTreeHostImpl::FrameData
& frame
)
577 RenderPass
* removeRenderPass
= findRenderPassById(removeRenderPassId
, frame
);
578 // The pass was already removed by another quad - probably the original, and we are the replica.
579 if (!removeRenderPass
)
581 RenderPassList
& renderPasses
= frame
.renderPasses
;
582 RenderPassList::iterator toRemove
= std::find(renderPasses
.begin(), renderPasses
.end(), removeRenderPass
);
584 DCHECK(toRemove
!= renderPasses
.end());
586 scoped_ptr
<RenderPass
> removedPass
= renderPasses
.take(toRemove
);
587 frame
.renderPasses
.erase(toRemove
);
588 frame
.renderPassesById
.erase(removeRenderPassId
);
590 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
591 const QuadList
& quadList
= removedPass
->quad_list
;
592 QuadList::constBackToFrontIterator quadListIterator
= quadList
.backToFrontBegin();
593 for (; quadListIterator
!= quadList
.backToFrontEnd(); ++quadListIterator
) {
594 DrawQuad
* currentQuad
= (*quadListIterator
);
595 if (currentQuad
->material
!= DrawQuad::RENDER_PASS
)
598 RenderPass::Id nextRemoveRenderPassId
= RenderPassDrawQuad::MaterialCast(currentQuad
)->render_pass_id
;
599 removeRenderPassesRecursive(nextRemoveRenderPassId
, frame
);
603 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad
& quad
, const FrameData
&) const
605 if (!quad
.contents_changed_since_last_frame
.IsEmpty()) {
606 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
608 } else if (!m_renderer
.haveCachedResourcesForRenderPassId(quad
.render_pass_id
)) {
609 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
612 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
616 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad
& quad
, const FrameData
& frame
) const
618 const RenderPass
* renderPass
= findRenderPassById(quad
.render_pass_id
, frame
);
622 // If any quad or RenderPass draws into this RenderPass, then keep it.
623 const QuadList
& quadList
= renderPass
->quad_list
;
624 for (QuadList::constBackToFrontIterator quadListIterator
= quadList
.backToFrontBegin(); quadListIterator
!= quadList
.backToFrontEnd(); ++quadListIterator
) {
625 DrawQuad
* currentQuad
= *quadListIterator
;
627 if (currentQuad
->material
!= DrawQuad::RENDER_PASS
)
630 const RenderPass
* contributingPass
= findRenderPassById(RenderPassDrawQuad::MaterialCast(currentQuad
)->render_pass_id
, frame
);
631 if (contributingPass
)
637 // Defined for linking tests.
638 template CC_EXPORT
void LayerTreeHostImpl::removeRenderPasses
<LayerTreeHostImpl::CullRenderPassesWithCachedTextures
>(CullRenderPassesWithCachedTextures
, FrameData
&);
639 template CC_EXPORT
void LayerTreeHostImpl::removeRenderPasses
<LayerTreeHostImpl::CullRenderPassesWithNoQuads
>(CullRenderPassesWithNoQuads
, FrameData
&);
642 template<typename RenderPassCuller
>
643 void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler
, FrameData
& frame
)
645 for (size_t it
= culler
.renderPassListBegin(frame
.renderPasses
); it
!= culler
.renderPassListEnd(frame
.renderPasses
); it
= culler
.renderPassListNext(it
)) {
646 const RenderPass
* currentPass
= frame
.renderPasses
[it
];
647 const QuadList
& quadList
= currentPass
->quad_list
;
648 QuadList::constBackToFrontIterator quadListIterator
= quadList
.backToFrontBegin();
650 for (; quadListIterator
!= quadList
.backToFrontEnd(); ++quadListIterator
) {
651 DrawQuad
* currentQuad
= *quadListIterator
;
653 if (currentQuad
->material
!= DrawQuad::RENDER_PASS
)
656 RenderPassDrawQuad
* renderPassQuad
= static_cast<RenderPassDrawQuad
*>(currentQuad
);
657 if (!culler
.shouldRemoveRenderPass(*renderPassQuad
, frame
))
660 // We are changing the vector in the middle of iteration. Because we
661 // delete render passes that draw into the current pass, we are
662 // guaranteed that any data from the iterator to the end will not
663 // change. So, capture the iterator position from the end of the
664 // list, and restore it after the change.
665 int positionFromEnd
= frame
.renderPasses
.size() - it
;
666 removeRenderPassesRecursive(renderPassQuad
->render_pass_id
, frame
);
667 it
= frame
.renderPasses
.size() - positionFromEnd
;
673 bool LayerTreeHostImpl::prepareToDraw(FrameData
& frame
)
675 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
677 activeTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRAW
);
679 frame
.renderSurfaceLayerList
= &activeTree()->RenderSurfaceLayerList();
680 frame
.renderPasses
.clear();
681 frame
.renderPassesById
.clear();
682 frame
.willDrawLayers
.clear();
684 if (!calculateRenderPasses(frame
))
687 // If we return true, then we expect drawLayers() to be called before this function is called again.
691 void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
693 bool evictedResources
= m_client
->reduceContentsTextureMemoryOnImplThread(
694 m_visible
? policy
.bytesLimitWhenVisible
: policy
.bytesLimitWhenNotVisible
,
695 ManagedMemoryPolicy::priorityCutoffToValue(
696 m_visible
? policy
.priorityCutoffWhenVisible
: policy
.priorityCutoffWhenNotVisible
));
697 if (evictedResources
) {
698 activeTree()->SetContentsTexturesPurged();
700 pendingTree()->SetContentsTexturesPurged();
701 m_client
->setNeedsCommitOnImplThread();
702 m_client
->onCanDrawStateChanged(canDraw());
703 m_client
->renewTreePriority();
705 m_client
->sendManagedMemoryStats();
708 GlobalStateThatImpactsTilePriority
new_state(m_tileManager
->GlobalState());
709 new_state
.memory_limit_in_bytes
= m_visible
? policy
.bytesLimitWhenVisible
: policy
.bytesLimitWhenNotVisible
;
710 new_state
.memory_limit_policy
= ManagedMemoryPolicy::priorityCutoffToTileMemoryLimitPolicy(
711 m_visible
? policy
.priorityCutoffWhenVisible
: policy
.priorityCutoffWhenNotVisible
);
712 m_tileManager
->SetGlobalState(new_state
);
716 bool LayerTreeHostImpl::hasImplThread() const
718 return m_proxy
->hasImplThread();
721 void LayerTreeHostImpl::ScheduleManageTiles()
724 m_client
->setNeedsManageTilesOnImplThread();
727 void LayerTreeHostImpl::DidUploadVisibleHighResolutionTile()
730 m_client
->didUploadVisibleHighResolutionTileOnImplThread();
733 bool LayerTreeHostImpl::shouldClearRootRenderPass() const
735 return m_settings
.shouldClearRootRenderPass
;
738 void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
740 if (m_managedMemoryPolicy
== policy
)
743 m_managedMemoryPolicy
= policy
;
744 if (!m_proxy
->hasImplThread()) {
745 // FIXME: In single-thread mode, this can be called on the main thread
746 // by GLRenderer::onMemoryAllocationChanged.
747 DebugScopedSetImplThread
implThread(m_proxy
);
748 enforceManagedMemoryPolicy(m_managedMemoryPolicy
);
750 DCHECK(m_proxy
->isImplThread());
751 enforceManagedMemoryPolicy(m_managedMemoryPolicy
);
753 // We always need to commit after changing the memory policy because the new
754 // limit can result in more or less content having texture allocated for it.
755 m_client
->setNeedsCommitOnImplThread();
758 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase
, base::TimeDelta interval
)
760 m_client
->onVSyncParametersChanged(timebase
, interval
);
763 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(const CompositorFrameAck
& ack
)
768 // TODO(piman): We may need to do some validation on this ack before processing it.
769 m_renderer
->receiveCompositorFrameAck(ack
);
772 void LayerTreeHostImpl::OnCanDrawStateChangedForTree(LayerTreeImpl
*)
774 m_client
->onCanDrawStateChanged(canDraw());
777 CompositorFrameMetadata
LayerTreeHostImpl::makeCompositorFrameMetadata() const
779 CompositorFrameMetadata metadata
;
780 metadata
.page_scale_factor
= activeTree()->total_page_scale_factor();
781 metadata
.viewport_size
= activeTree()->ScrollableViewportSize();
782 metadata
.root_layer_size
= activeTree()->ScrollableSize();
783 metadata
.min_page_scale_factor
= activeTree()->min_page_scale_factor();
784 metadata
.max_page_scale_factor
= activeTree()->max_page_scale_factor();
785 if (m_topControlsManager
) {
786 metadata
.location_bar_offset
= gfx::Vector2dF(0.f
, m_topControlsManager
->controls_top_offset());
787 metadata
.location_bar_content_translation
= gfx::Vector2dF(0.f
, m_topControlsManager
->content_top_offset());
790 if (!rootScrollLayer())
793 metadata
.root_scroll_offset
= rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
794 if (!m_settings
.pageScalePinchZoomEnabled
)
795 metadata
.root_scroll_offset
.Scale(1 / activeTree()->page_scale_factor());
800 void LayerTreeHostImpl::drawLayers(FrameData
& frame
)
802 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
804 DCHECK(!frame
.renderPasses
.empty());
806 // FIXME: use the frame begin time from the overall compositor scheduler.
807 // This value is currently inaccessible because it is up in Chromium's
809 m_fpsCounter
->saveTimeStamp(base::TimeTicks::Now());
812 m_memoryHistory
->SaveEntry(
813 m_tileManager
->memory_stats_from_last_assign());
816 if (m_debugState
.showHudRects())
817 m_debugRectHistory
->saveDebugRectsForCurrentFrame(rootLayer(), *frame
.renderSurfaceLayerList
, frame
.occludingScreenSpaceRects
, frame
.nonOccludingScreenSpaceRects
, m_debugState
);
819 if (m_debugState
.traceAllRenderedFrames
) {
820 TRACE_EVENT_INSTANT1("cc.debug", "Frame",
821 "frame", ValueToString(frameStateAsValue()));
824 // Because the contents of the HUD depend on everything else in the frame, the contents
825 // of its texture are updated as the last thing before the frame is drawn.
826 if (m_activeTree
->hud_layer())
827 m_activeTree
->hud_layer()->updateHudTexture(m_resourceProvider
.get());
829 m_renderer
->drawFrame(frame
.renderPasses
);
830 // The render passes should be consumed by the renderer.
831 DCHECK(frame
.renderPasses
.empty());
832 frame
.renderPassesById
.clear();
834 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
835 for (unsigned int i
= 0; i
< frame
.renderSurfaceLayerList
->size(); i
++)
836 (*frame
.renderSurfaceLayerList
)[i
]->renderSurface()->damageTracker()->didDrawDamagedArea();
837 rootLayer()->resetAllChangeTrackingForSubtree();
838 updateAnimationState();
841 void LayerTreeHostImpl::didDrawAllLayers(const FrameData
& frame
)
843 for (size_t i
= 0; i
< frame
.willDrawLayers
.size(); ++i
)
844 frame
.willDrawLayers
[i
]->didDraw(m_resourceProvider
.get());
846 // Once all layers have been drawn, pending texture uploads should no
847 // longer block future uploads.
848 m_resourceProvider
->markPendingUploadsAsNonBlocking();
851 void LayerTreeHostImpl::finishAllRendering()
854 m_renderer
->finish();
857 bool LayerTreeHostImpl::isContextLost()
859 DCHECK(m_proxy
->isImplThread());
860 return m_renderer
&& m_renderer
->isContextLost();
863 const RendererCapabilities
& LayerTreeHostImpl::rendererCapabilities() const
865 return m_renderer
->capabilities();
868 bool LayerTreeHostImpl::swapBuffers()
870 return m_renderer
->swapBuffers();
873 const gfx::Size
& LayerTreeHostImpl::deviceViewportSize() const
875 return m_deviceViewportSize
;
878 const LayerTreeSettings
& LayerTreeHostImpl::settings() const
883 void LayerTreeHostImpl::didLoseOutputSurface()
885 m_client
->didLoseOutputSurfaceOnImplThread();
888 void LayerTreeHostImpl::onSwapBuffersComplete()
890 m_client
->onSwapBuffersCompleteOnImplThread();
893 void LayerTreeHostImpl::readback(void* pixels
, const gfx::Rect
& rect
)
896 m_renderer
->getFramebufferPixels(pixels
, rect
);
899 bool LayerTreeHostImpl::haveRootScrollLayer() const {
900 return rootScrollLayer();
903 float LayerTreeHostImpl::rootScrollLayerTotalScrollY() const {
904 if (LayerImpl
* layer
= rootScrollLayer())
905 return layer
->scrollOffset().y() + layer
->scrollDelta().y();
909 LayerImpl
* LayerTreeHostImpl::rootLayer() const
911 return m_activeTree
->RootLayer();
914 LayerImpl
* LayerTreeHostImpl::rootScrollLayer() const
916 return m_activeTree
->RootScrollLayer();
919 LayerImpl
* LayerTreeHostImpl::currentlyScrollingLayer() const
921 return m_activeTree
->CurrentlyScrollingLayer();
924 // Content layers can be either directly scrollable or contained in an outer
925 // scrolling layer which applies the scroll transform. Given a content layer,
926 // this function returns the associated scroll layer if any.
927 static LayerImpl
* findScrollLayerForContentLayer(LayerImpl
* layerImpl
)
932 if (layerImpl
->scrollable())
935 if (layerImpl
->drawsContent() && layerImpl
->parent() && layerImpl
->parent()->scrollable())
936 return layerImpl
->parent();
941 void LayerTreeHostImpl::createPendingTree()
943 CHECK(!m_pendingTree
);
945 m_recycleTree
.swap(m_pendingTree
);
947 m_pendingTree
= LayerTreeImpl::create(this);
948 m_client
->onCanDrawStateChanged(canDraw());
949 m_client
->onHasPendingTreeStateChanged(pendingTree());
950 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", m_pendingTree
.get());
951 TRACE_EVENT_ASYNC_STEP0("cc",
952 "PendingTree", m_pendingTree
.get(), "waiting");
955 void LayerTreeHostImpl::checkForCompletedTileUploads()
957 DCHECK(!m_client
->isInsideDraw()) << "Checking for completed uploads within a draw may trigger spurious redraws.";
959 m_tileManager
->CheckForCompletedTileUploads();
962 void LayerTreeHostImpl::activatePendingTreeIfNeeded()
967 CHECK(m_tileManager
);
969 pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE
);
971 TRACE_EVENT_ASYNC_STEP1("cc",
972 "PendingTree", m_pendingTree
.get(), "activate",
973 "state", ValueToString(activationStateAsValue()));
975 // It's always fine to activate to an empty tree. Otherwise, only
976 // activate once all visible resources in pending tree are ready
977 // or tile manager has no work scheduled for pending tree.
978 if (activeTree()->RootLayer() &&
979 !pendingTree()->AreVisibleResourcesReady()) {
980 // In smoothness takes priority mode, the pending tree's priorities are
981 // ignored, so the tile manager may not have work for it even though it
982 // is simultaneously not ready to be activated.
983 if (m_tileManager
->GlobalState().tree_priority
==
984 SMOOTHNESS_TAKES_PRIORITY
||
985 m_tileManager
->HasPendingWorkScheduled(PENDING_TREE
)) {
986 TRACE_EVENT_ASYNC_STEP0("cc",
994 activatePendingTree();
997 void LayerTreeHostImpl::activatePendingTree()
999 CHECK(m_pendingTree
);
1000 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", m_pendingTree
.get());
1002 m_activeTree
->PushPersistedState(m_pendingTree
.get());
1003 if (m_pendingTree
->needs_full_tree_sync())
1004 m_activeTree
->SetRootLayer(TreeSynchronizer::synchronizeTrees(m_pendingTree
->RootLayer(), m_activeTree
->DetachLayerTree(), m_activeTree
.get()));
1005 TreeSynchronizer::pushProperties(m_pendingTree
->RootLayer(), m_activeTree
->RootLayer());
1006 DCHECK(!m_recycleTree
);
1008 m_pendingTree
->pushPropertiesTo(m_activeTree
.get());
1010 // Now that we've synced everything from the pending tree to the active
1011 // tree, rename the pending tree the recycle tree so we can reuse it on the
1013 m_pendingTree
.swap(m_recycleTree
);
1014 m_recycleTree
->ClearRenderSurfaces();
1016 m_activeTree
->DidBecomeActive();
1018 // Reduce wasted memory now that unlinked resources are guaranteed not
1020 m_client
->reduceWastedContentsTextureMemoryOnImplThread();
1022 m_client
->onCanDrawStateChanged(canDraw());
1023 m_client
->onHasPendingTreeStateChanged(pendingTree());
1024 m_client
->setNeedsRedrawOnImplThread();
1025 m_client
->renewTreePriority();
1028 void LayerTreeHostImpl::setVisible(bool visible
)
1030 DCHECK(m_proxy
->isImplThread());
1032 if (m_visible
== visible
)
1034 m_visible
= visible
;
1035 didVisibilityChange(this, m_visible
);
1036 enforceManagedMemoryPolicy(m_managedMemoryPolicy
);
1041 m_renderer
->setVisible(visible
);
1043 setBackgroundTickingEnabled(!m_visible
&& !m_animationRegistrar
->active_animation_controllers().empty());
1046 bool LayerTreeHostImpl::initializeRenderer(scoped_ptr
<OutputSurface
> outputSurface
)
1048 // Since we will create a new resource provider, we cannot continue to use
1049 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
1050 // before we destroy the old resource provider.
1052 clearRenderSurfaces();
1053 if (activeTree()->RootLayer())
1054 sendDidLoseOutputSurfaceRecursive(activeTree()->RootLayer());
1055 if (pendingTree() && pendingTree()->RootLayer())
1056 sendDidLoseOutputSurfaceRecursive(pendingTree()->RootLayer());
1057 if (m_recycleTree
&& m_recycleTree
->RootLayer())
1058 sendDidLoseOutputSurfaceRecursive(m_recycleTree
->RootLayer());
1060 // Note: order is important here.
1062 m_tileManager
.reset();
1063 m_resourceProvider
.reset();
1064 m_outputSurface
.reset();
1066 if (!outputSurface
->BindToClient(this))
1069 scoped_ptr
<ResourceProvider
> resourceProvider
= ResourceProvider::create(outputSurface
.get());
1070 if (!resourceProvider
)
1073 if (m_settings
.implSidePainting
) {
1074 m_tileManager
.reset(new TileManager(this, resourceProvider
.get(), m_settings
.numRasterThreads
, m_settings
.useCheapnessEstimator
));
1075 m_tileManager
->SetRecordRenderingStats(m_debugState
.recordRenderingStats());
1078 if (outputSurface
->capabilities().has_parent_compositor
)
1079 m_renderer
= DelegatingRenderer::Create(this, outputSurface
.get(), resourceProvider
.get());
1080 else if (outputSurface
->context3d())
1081 m_renderer
= GLRenderer::create(this, outputSurface
.get(), resourceProvider
.get());
1082 else if (outputSurface
->software_device())
1083 m_renderer
= SoftwareRenderer::create(this, resourceProvider
.get(), outputSurface
->software_device());
1087 m_resourceProvider
= resourceProvider
.Pass();
1088 m_outputSurface
= outputSurface
.Pass();
1091 m_renderer
->setVisible(m_visible
);
1093 m_client
->onCanDrawStateChanged(canDraw());
1095 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs
1096 // to be initialized to get max texture size.
1097 activeTree()->set_needs_update_draw_properties();
1099 pendingTree()->set_needs_update_draw_properties();
1104 void LayerTreeHostImpl::setViewportSize(const gfx::Size
& layoutViewportSize
, const gfx::Size
& deviceViewportSize
)
1106 if (layoutViewportSize
== m_layoutViewportSize
&& deviceViewportSize
== m_deviceViewportSize
)
1109 if (pendingTree() && m_deviceViewportSize
!= deviceViewportSize
)
1110 activeTree()->SetViewportSizeInvalid();
1112 m_layoutViewportSize
= layoutViewportSize
;
1113 m_deviceViewportSize
= deviceViewportSize
;
1115 updateMaxScrollOffset();
1118 m_renderer
->viewportChanged();
1120 m_client
->onCanDrawStateChanged(canDraw());
1123 static void adjustScrollsForPageScaleChange(LayerImpl
* layerImpl
, float pageScaleChange
)
1128 if (layerImpl
->scrollable()) {
1129 // We need to convert impl-side scroll deltas to pageScale space.
1130 gfx::Vector2dF scrollDelta
= layerImpl
->scrollDelta();
1131 scrollDelta
.Scale(pageScaleChange
);
1132 layerImpl
->setScrollDelta(scrollDelta
);
1135 for (size_t i
= 0; i
< layerImpl
->children().size(); ++i
)
1136 adjustScrollsForPageScaleChange(layerImpl
->children()[i
], pageScaleChange
);
1139 void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor
)
1141 if (deviceScaleFactor
== m_deviceScaleFactor
)
1143 m_deviceScaleFactor
= deviceScaleFactor
;
1145 updateMaxScrollOffset();
1148 void LayerTreeHostImpl::updateMaxScrollOffset()
1150 activeTree()->UpdateMaxScrollOffset();
1153 void LayerTreeHostImpl::setActiveTreeNeedsUpdateDrawProperties()
1155 activeTree()->set_needs_update_draw_properties();
1158 void LayerTreeHostImpl::setNeedsRedraw()
1160 m_client
->setNeedsRedrawOnImplThread();
1163 bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
1165 activeTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE
);
1166 return activeTree()->RenderSurfaceLayerList().size();
1169 InputHandlerClient::ScrollStatus
LayerTreeHostImpl::scrollBegin(gfx::Point viewportPoint
, InputHandlerClient::ScrollInputType type
)
1171 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
1173 if (m_topControlsManager
)
1174 m_topControlsManager
->ScrollBegin();
1176 DCHECK(!currentlyScrollingLayer());
1177 clearCurrentlyScrollingLayer();
1179 if (!ensureRenderSurfaceLayerList())
1180 return ScrollIgnored
;
1182 gfx::PointF deviceViewportPoint
= gfx::ScalePoint(viewportPoint
, m_deviceScaleFactor
);
1184 // First find out which layer was hit from the saved list of visible layers
1185 // in the most recent frame.
1186 LayerImpl
* layerImpl
= LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint
, activeTree()->RenderSurfaceLayerList());
1188 // Walk up the hierarchy and look for a scrollable layer.
1189 LayerImpl
* potentiallyScrollingLayerImpl
= 0;
1190 for (; layerImpl
; layerImpl
= layerImpl
->parent()) {
1191 // The content layer can also block attempts to scroll outside the main thread.
1192 if (layerImpl
->tryScroll(deviceViewportPoint
, type
) == ScrollOnMainThread
) {
1193 m_numMainThreadScrolls
++;
1194 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1195 return ScrollOnMainThread
;
1198 LayerImpl
* scrollLayerImpl
= findScrollLayerForContentLayer(layerImpl
);
1199 if (!scrollLayerImpl
)
1202 ScrollStatus status
= scrollLayerImpl
->tryScroll(deviceViewportPoint
, type
);
1204 // If any layer wants to divert the scroll event to the main thread, abort.
1205 if (status
== ScrollOnMainThread
) {
1206 m_numMainThreadScrolls
++;
1207 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1208 return ScrollOnMainThread
;
1211 if (status
== ScrollStarted
&& !potentiallyScrollingLayerImpl
)
1212 potentiallyScrollingLayerImpl
= scrollLayerImpl
;
1215 if (potentiallyScrollingLayerImpl
) {
1216 m_activeTree
->set_currently_scrolling_layer(potentiallyScrollingLayerImpl
);
1217 m_shouldBubbleScrolls
= (type
!= NonBubblingGesture
);
1218 m_wheelScrolling
= (type
== Wheel
);
1219 m_numImplThreadScrolls
++;
1220 m_client
->renewTreePriority();
1221 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
1222 return ScrollStarted
;
1224 return ScrollIgnored
;
1227 gfx::Vector2dF
LayerTreeHostImpl::scrollLayerWithViewportSpaceDelta(LayerImpl
* layerImpl
, float scaleFromViewportToScreenSpace
, gfx::PointF viewportPoint
, gfx::Vector2dF viewportDelta
)
1229 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1230 // test in the first place.
1231 DCHECK(layerImpl
->screenSpaceTransform().IsInvertible());
1232 gfx::Transform
inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization
);
1233 bool didInvert
= layerImpl
->screenSpaceTransform().GetInverse(&inverseScreenSpaceTransform
);
1234 // TODO: With the advent of impl-side crolling for non-root layers, we may
1235 // need to explicitly handle uninvertible transforms here.
1238 gfx::PointF screenSpacePoint
= gfx::ScalePoint(viewportPoint
, scaleFromViewportToScreenSpace
);
1240 gfx::Vector2dF screenSpaceDelta
= viewportDelta
;
1241 screenSpaceDelta
.Scale(scaleFromViewportToScreenSpace
);
1243 // First project the scroll start and end points to local layer space to find the scroll delta
1244 // in layer coordinates.
1245 bool startClipped
, endClipped
;
1246 gfx::PointF screenSpaceEndPoint
= screenSpacePoint
+ screenSpaceDelta
;
1247 gfx::PointF localStartPoint
= MathUtil::projectPoint(inverseScreenSpaceTransform
, screenSpacePoint
, startClipped
);
1248 gfx::PointF localEndPoint
= MathUtil::projectPoint(inverseScreenSpaceTransform
, screenSpaceEndPoint
, endClipped
);
1250 // In general scroll point coordinates should not get clipped.
1251 DCHECK(!startClipped
);
1252 DCHECK(!endClipped
);
1253 if (startClipped
|| endClipped
)
1254 return gfx::Vector2dF();
1256 // localStartPoint and localEndPoint are in content space but we want to move them to layer space for scrolling.
1257 float widthScale
= 1 / layerImpl
->contentsScaleX();
1258 float heightScale
= 1 / layerImpl
->contentsScaleY();
1259 localStartPoint
.Scale(widthScale
, heightScale
);
1260 localEndPoint
.Scale(widthScale
, heightScale
);
1262 // Apply the scroll delta.
1263 gfx::Vector2dF previousDelta
= layerImpl
->scrollDelta();
1264 layerImpl
->scrollBy(localEndPoint
- localStartPoint
);
1266 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
1267 gfx::PointF actualLocalEndPoint
= localStartPoint
+ layerImpl
->scrollDelta() - previousDelta
;
1268 gfx::PointF actualLocalContentEndPoint
= gfx::ScalePoint(actualLocalEndPoint
, 1 / widthScale
, 1 / heightScale
);
1270 // Calculate the applied scroll delta in viewport space coordinates.
1271 gfx::PointF actualScreenSpaceEndPoint
= MathUtil::mapPoint(layerImpl
->screenSpaceTransform(), actualLocalContentEndPoint
, endClipped
);
1272 DCHECK(!endClipped
);
1274 return gfx::Vector2dF();
1275 gfx::PointF actualViewportEndPoint
= gfx::ScalePoint(actualScreenSpaceEndPoint
, 1 / scaleFromViewportToScreenSpace
);
1276 return actualViewportEndPoint
- viewportPoint
;
1279 static gfx::Vector2dF
scrollLayerWithLocalDelta(LayerImpl
& layerImpl
, gfx::Vector2dF localDelta
)
1281 gfx::Vector2dF
previousDelta(layerImpl
.scrollDelta());
1282 layerImpl
.scrollBy(localDelta
);
1283 return layerImpl
.scrollDelta() - previousDelta
;
1286 bool LayerTreeHostImpl::scrollBy(const gfx::Point
& viewportPoint
,
1287 const gfx::Vector2d
& scrollDelta
)
1289 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
1290 if (!currentlyScrollingLayer())
1293 gfx::Vector2dF pendingDelta
= scrollDelta
;
1294 bool didScroll
= false;
1296 for (LayerImpl
* layerImpl
= currentlyScrollingLayer(); layerImpl
; layerImpl
= layerImpl
->parent()) {
1297 if (!layerImpl
->scrollable())
1300 gfx::Vector2dF appliedDelta
;
1301 if (m_topControlsManager
&& layerImpl
== rootScrollLayer())
1302 pendingDelta
= m_topControlsManager
->ScrollBy(pendingDelta
);
1304 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
1305 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1306 // events represent a fixed amount of scrolling so we can just apply them directly.
1307 if (!m_wheelScrolling
) {
1308 float scaleFromViewportToScreenSpace
= m_deviceScaleFactor
;
1309 appliedDelta
= scrollLayerWithViewportSpaceDelta(layerImpl
, scaleFromViewportToScreenSpace
, viewportPoint
, pendingDelta
);
1311 appliedDelta
= scrollLayerWithLocalDelta(*layerImpl
, pendingDelta
);
1313 // If the layer wasn't able to move, try the next one in the hierarchy.
1314 float moveThresholdSquared
= 0.1f
* 0.1f
;
1315 if (appliedDelta
.LengthSquared() < moveThresholdSquared
) {
1316 if (m_shouldBubbleScrolls
|| !m_didLockScrollingLayer
)
1322 m_didLockScrollingLayer
= true;
1323 if (!m_shouldBubbleScrolls
) {
1324 m_activeTree
->set_currently_scrolling_layer(layerImpl
);
1328 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1329 // to scroll just one layer in one direction without affecting any of its parents.
1330 float angleThreshold
= 45;
1331 if (MathUtil::smallestAngleBetweenVectors(appliedDelta
, pendingDelta
) < angleThreshold
) {
1332 pendingDelta
= gfx::Vector2d();
1336 // Allow further movement only on an axis perpendicular to the direction in which the layer
1338 gfx::Vector2dF
perpendicularAxis(-appliedDelta
.y(), appliedDelta
.x());
1339 pendingDelta
= MathUtil::projectVector(pendingDelta
, perpendicularAxis
);
1341 if (gfx::ToFlooredVector2d(pendingDelta
).IsZero())
1346 m_client
->setNeedsCommitOnImplThread();
1347 m_client
->setNeedsRedrawOnImplThread();
1348 m_client
->renewTreePriority();
1353 void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
1355 m_activeTree
->ClearCurrentlyScrollingLayer();
1356 m_didLockScrollingLayer
= false;
1359 void LayerTreeHostImpl::scrollEnd()
1361 if (m_topControlsManager
)
1362 m_topControlsManager
->ScrollEnd();
1363 clearCurrentlyScrollingLayer();
1366 void LayerTreeHostImpl::pinchGestureBegin()
1368 m_pinchGestureActive
= true;
1369 m_previousPinchAnchor
= gfx::Point();
1370 m_client
->renewTreePriority();
1373 void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta
, gfx::Point anchor
)
1375 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
1377 if (!rootScrollLayer())
1380 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1381 // position over the course of the magnify.
1382 float pageScaleDelta
= activeTree()->page_scale_delta();
1383 gfx::PointF previousScaleAnchor
= gfx::ScalePoint(anchor
, 1 / pageScaleDelta
);
1384 activeTree()->SetPageScaleDelta(pageScaleDelta
* magnifyDelta
);
1385 pageScaleDelta
= activeTree()->page_scale_delta();
1386 gfx::PointF newScaleAnchor
= gfx::ScalePoint(anchor
, 1 / pageScaleDelta
);
1387 gfx::Vector2dF move
= previousScaleAnchor
- newScaleAnchor
;
1389 m_previousPinchAnchor
= anchor
;
1391 if (m_settings
.pageScalePinchZoomEnabled
)
1392 move
.Scale(1 / activeTree()->page_scale_factor());
1394 rootScrollLayer()->scrollBy(move
);
1396 if (rootScrollLayer()->scrollbarAnimationController())
1397 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureUpdate(base::TimeTicks::Now());
1399 m_client
->setNeedsCommitOnImplThread();
1400 m_client
->setNeedsRedrawOnImplThread();
1401 m_client
->renewTreePriority();
1404 void LayerTreeHostImpl::pinchGestureEnd()
1406 m_pinchGestureActive
= false;
1408 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1409 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureEnd(base::TimeTicks::Now());
1411 m_client
->setNeedsCommitOnImplThread();
1414 void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet
* scrollInfo
)
1416 gfx::Vector2dF scaledScrollOffset
= m_pageScaleAnimation
->targetScrollOffset();
1417 if (!m_settings
.pageScalePinchZoomEnabled
)
1418 scaledScrollOffset
.Scale(activeTree()->page_scale_factor());
1419 makeScrollAndScaleSet(scrollInfo
, ToFlooredVector2d(scaledScrollOffset
), m_pageScaleAnimation
->targetPageScaleFactor());
1422 void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet
* scrollInfo
)
1424 if (!rootScrollLayer())
1427 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1428 // significant amount. This also ensures only one fake delta set will be
1430 const float pinchZoomOutSensitivity
= 0.95f
;
1431 if (activeTree()->page_scale_delta() > pinchZoomOutSensitivity
)
1434 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1435 // out from the anchor point.
1436 gfx::Vector2dF scrollBegin
= rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
1437 scrollBegin
.Scale(activeTree()->page_scale_delta());
1438 float scaleBegin
= activeTree()->total_page_scale_factor();
1439 float pageScaleDeltaToSend
= activeTree()->min_page_scale_factor() / activeTree()->page_scale_factor();
1440 gfx::SizeF scaledScrollableSize
= gfx::ScaleSize(activeTree()->ScrollableSize(), pageScaleDeltaToSend
);
1442 gfx::Vector2d anchorOffset
= m_previousPinchAnchor
.OffsetFromOrigin();
1443 gfx::Vector2dF scrollEnd
= scrollBegin
+ anchorOffset
;
1444 scrollEnd
.Scale(activeTree()->min_page_scale_factor() / scaleBegin
);
1445 scrollEnd
-= anchorOffset
;
1446 scrollEnd
.ClampToMax(gfx::RectF(scaledScrollableSize
).bottom_right() - gfx::Rect(m_deviceViewportSize
).bottom_right());
1447 scrollEnd
.ClampToMin(gfx::Vector2d());
1448 scrollEnd
.Scale(1 / pageScaleDeltaToSend
);
1449 scrollEnd
.Scale(m_deviceScaleFactor
);
1451 makeScrollAndScaleSet(scrollInfo
, gfx::ToRoundedVector2d(scrollEnd
), activeTree()->min_page_scale_factor());
1454 static void collectScrollDeltas(ScrollAndScaleSet
* scrollInfo
, LayerImpl
* layerImpl
)
1459 gfx::Vector2d scrollDelta
= gfx::ToFlooredVector2d(layerImpl
->scrollDelta());
1460 if (!scrollDelta
.IsZero()) {
1461 LayerTreeHostCommon::ScrollUpdateInfo scroll
;
1462 scroll
.layerId
= layerImpl
->id();
1463 scroll
.scrollDelta
= scrollDelta
;
1464 scrollInfo
->scrolls
.push_back(scroll
);
1465 layerImpl
->setSentScrollDelta(scrollDelta
);
1468 for (size_t i
= 0; i
< layerImpl
->children().size(); ++i
)
1469 collectScrollDeltas(scrollInfo
, layerImpl
->children()[i
]);
1472 void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet
* scrollInfo
, gfx::Vector2d scrollOffset
, float pageScale
)
1474 if (!rootScrollLayer())
1477 LayerTreeHostCommon::ScrollUpdateInfo scroll
;
1478 scroll
.layerId
= rootScrollLayer()->id();
1479 scroll
.scrollDelta
= scrollOffset
- rootScrollLayer()->scrollOffset();
1480 scrollInfo
->scrolls
.push_back(scroll
);
1481 activeTree()->RootScrollLayer()->setSentScrollDelta(scroll
.scrollDelta
);
1482 scrollInfo
->pageScaleDelta
= pageScale
/ activeTree()->page_scale_factor();
1483 activeTree()->set_sent_page_scale_delta(scrollInfo
->pageScaleDelta
);
1486 scoped_ptr
<ScrollAndScaleSet
> LayerTreeHostImpl::processScrollDeltas()
1488 scoped_ptr
<ScrollAndScaleSet
> scrollInfo(new ScrollAndScaleSet());
1490 if (!m_settings
.pageScalePinchZoomEnabled
&& (m_pinchGestureActive
|| m_pageScaleAnimation
)) {
1491 scrollInfo
->pageScaleDelta
= 1;
1492 activeTree()->set_sent_page_scale_delta(1);
1493 if (m_pinchGestureActive
)
1494 computePinchZoomDeltas(scrollInfo
.get());
1495 else if (m_pageScaleAnimation
.get())
1496 computeDoubleTapZoomDeltas(scrollInfo
.get());
1497 return scrollInfo
.Pass();
1500 collectScrollDeltas(scrollInfo
.get(), rootLayer());
1501 scrollInfo
->pageScaleDelta
= activeTree()->page_scale_delta();
1502 activeTree()->set_sent_page_scale_delta(scrollInfo
->pageScaleDelta
);
1504 return scrollInfo
.Pass();
1507 void LayerTreeHostImpl::setFullRootLayerDamage()
1510 RenderSurfaceImpl
* renderSurface
= rootLayer()->renderSurface();
1512 renderSurface
->damageTracker()->forceFullDamageNextUpdate();
1516 void LayerTreeHostImpl::animatePageScale(base::TimeTicks time
)
1518 if (!m_pageScaleAnimation
|| !rootScrollLayer())
1521 double monotonicTime
= (time
- base::TimeTicks()).InSecondsF();
1522 gfx::Vector2dF scrollTotal
= rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
1524 activeTree()->SetPageScaleDelta(m_pageScaleAnimation
->pageScaleFactorAtTime(monotonicTime
) / activeTree()->page_scale_factor());
1525 gfx::Vector2dF nextScroll
= m_pageScaleAnimation
->scrollOffsetAtTime(monotonicTime
);
1527 if (!m_settings
.pageScalePinchZoomEnabled
)
1528 nextScroll
.Scale(activeTree()->page_scale_factor());
1529 rootScrollLayer()->scrollBy(nextScroll
- scrollTotal
);
1530 m_client
->setNeedsRedrawOnImplThread();
1532 if (m_pageScaleAnimation
->isAnimationCompleteAtTime(monotonicTime
)) {
1533 m_pageScaleAnimation
.reset();
1534 m_client
->setNeedsCommitOnImplThread();
1538 void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime
, base::Time wallClockTime
)
1540 if (!m_settings
.acceleratedAnimationEnabled
|| m_animationRegistrar
->active_animation_controllers().empty() || !rootLayer())
1543 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
1545 m_lastAnimationTime
= wallClockTime
;
1546 double monotonicSeconds
= (monotonicTime
- base::TimeTicks()).InSecondsF();
1548 AnimationRegistrar::AnimationControllerMap copy
= m_animationRegistrar
->active_animation_controllers();
1549 for (AnimationRegistrar::AnimationControllerMap::iterator iter
= copy
.begin(); iter
!= copy
.end(); ++iter
)
1550 (*iter
).second
->animate(monotonicSeconds
);
1552 m_client
->setNeedsRedrawOnImplThread();
1553 setBackgroundTickingEnabled(!m_visible
&& !m_animationRegistrar
->active_animation_controllers().empty());
1556 void LayerTreeHostImpl::updateAnimationState()
1558 if (!m_settings
.acceleratedAnimationEnabled
|| m_animationRegistrar
->active_animation_controllers().empty() || !rootLayer())
1561 TRACE_EVENT0("cc", "LayerTreeHostImpl::updateAnimationState");
1562 scoped_ptr
<AnimationEventsVector
> events(make_scoped_ptr(new AnimationEventsVector
));
1563 AnimationRegistrar::AnimationControllerMap copy
= m_animationRegistrar
->active_animation_controllers();
1564 for (AnimationRegistrar::AnimationControllerMap::iterator iter
= copy
.begin(); iter
!= copy
.end(); ++iter
)
1565 (*iter
).second
->updateState(events
.get());
1567 if (!events
->empty())
1568 m_client
->postAnimationEventsToMainThreadOnImplThread(events
.Pass(), m_lastAnimationTime
);
1571 base::TimeDelta
LayerTreeHostImpl::lowFrequencyAnimationInterval() const
1573 return base::TimeDelta::FromSeconds(1);
1576 void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl
* current
)
1579 current
->didLoseOutputSurface();
1580 if (current
->maskLayer())
1581 sendDidLoseOutputSurfaceRecursive(current
->maskLayer());
1582 if (current
->replicaLayer())
1583 sendDidLoseOutputSurfaceRecursive(current
->replicaLayer());
1584 for (size_t i
= 0; i
< current
->children().size(); ++i
)
1585 sendDidLoseOutputSurfaceRecursive(current
->children()[i
]);
1588 void LayerTreeHostImpl::clearRenderSurfaces()
1590 activeTree()->ClearRenderSurfaces();
1592 pendingTree()->ClearRenderSurfaces();
1595 std::string
LayerTreeHostImpl::layerTreeAsText() const
1599 str
= rootLayer()->layerTreeAsText();
1600 str
+= "RenderSurfaces:\n";
1601 dumpRenderSurfaces(&str
, 1, rootLayer());
1606 std::string
LayerTreeHostImpl::layerTreeAsJson() const
1610 scoped_ptr
<base::Value
> json(rootLayer()->layerTreeAsJson());
1611 base::JSONWriter::WriteWithOptions(
1612 json
.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT
, &str
);
1617 void LayerTreeHostImpl::dumpRenderSurfaces(std::string
* str
, int indent
, const LayerImpl
* layer
) const
1619 if (layer
->renderSurface())
1620 layer
->renderSurface()->dumpSurface(str
, indent
);
1622 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
1623 dumpRenderSurfaces(str
, indent
, layer
->children()[i
]);
1626 int LayerTreeHostImpl::sourceAnimationFrameNumber() const
1628 return fpsCounter()->currentFrameNumber();
1631 void LayerTreeHostImpl::renderingStats(RenderingStats
* stats
) const
1633 stats
->numFramesSentToScreen
= fpsCounter()->currentFrameNumber();
1634 stats
->droppedFrameCount
= fpsCounter()->droppedFrameCount();
1635 stats
->numImplThreadScrolls
= m_numImplThreadScrolls
;
1636 stats
->numMainThreadScrolls
= m_numMainThreadScrolls
;
1637 stats
->numLayersDrawn
= m_cumulativeNumLayersDrawn
;
1638 stats
->numMissingTiles
= m_cumulativeNumMissingTiles
;
1641 m_tileManager
->GetRenderingStats(stats
);
1644 void LayerTreeHostImpl::sendManagedMemoryStats(
1645 size_t memoryVisibleBytes
,
1646 size_t memoryVisibleAndNearbyBytes
,
1647 size_t memoryUseBytes
)
1652 // Round the numbers being sent up to the next 8MB, to throttle the rate
1653 // at which we spam the GPU process.
1654 static const size_t roundingStep
= 8 * 1024 * 1024;
1655 memoryVisibleBytes
= RoundUp(memoryVisibleBytes
, roundingStep
);
1656 memoryVisibleAndNearbyBytes
= RoundUp(memoryVisibleAndNearbyBytes
, roundingStep
);
1657 memoryUseBytes
= RoundUp(memoryUseBytes
, roundingStep
);
1658 if (m_lastSentMemoryVisibleBytes
== memoryVisibleBytes
&&
1659 m_lastSentMemoryVisibleAndNearbyBytes
== memoryVisibleAndNearbyBytes
&&
1660 m_lastSentMemoryUseBytes
== memoryUseBytes
) {
1663 m_lastSentMemoryVisibleBytes
= memoryVisibleBytes
;
1664 m_lastSentMemoryVisibleAndNearbyBytes
= memoryVisibleAndNearbyBytes
;
1665 m_lastSentMemoryUseBytes
= memoryUseBytes
;
1667 renderer()->sendManagedMemoryStats(m_lastSentMemoryVisibleBytes
,
1668 m_lastSentMemoryVisibleAndNearbyBytes
,
1669 m_lastSentMemoryUseBytes
);
1672 void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time
)
1674 animateScrollbarsRecursive(rootLayer(), time
);
1677 void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl
* layer
, base::TimeTicks time
)
1682 ScrollbarAnimationController
* scrollbarController
= layer
->scrollbarAnimationController();
1683 if (scrollbarController
&& scrollbarController
->animate(time
))
1684 m_client
->setNeedsRedrawOnImplThread();
1686 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
1687 animateScrollbarsRecursive(layer
->children()[i
], time
);
1690 void LayerTreeHostImpl::setTreePriority(TreePriority priority
)
1695 GlobalStateThatImpactsTilePriority
new_state(m_tileManager
->GlobalState());
1696 if (new_state
.tree_priority
== priority
)
1699 new_state
.tree_priority
= priority
;
1700 m_tileManager
->SetGlobalState(new_state
);
1703 void LayerTreeHostImpl::beginNextFrame()
1705 m_currentFrameTime
= base::TimeTicks();
1708 base::TimeTicks
LayerTreeHostImpl::currentFrameTime()
1710 if (m_currentFrameTime
.is_null())
1711 m_currentFrameTime
= base::TimeTicks::Now();
1712 return m_currentFrameTime
;
1715 scoped_ptr
<base::Value
> LayerTreeHostImpl::asValue() const
1717 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1718 state
->Set("activation_state", activationStateAsValue().release());
1719 state
->Set("frame_state", frameStateAsValue().release());
1720 return state
.PassAs
<base::Value
>();
1723 scoped_ptr
<base::Value
> LayerTreeHostImpl::activationStateAsValue() const
1725 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1726 state
->SetString("lthi_id", StringPrintf("%p", this));
1727 state
->SetBoolean("visible_resources_ready", pendingTree()->AreVisibleResourcesReady());
1728 state
->Set("tile_manager", m_tileManager
->BasicStateAsValue().release());
1729 return state
.PassAs
<base::Value
>();
1732 scoped_ptr
<base::Value
> LayerTreeHostImpl::frameStateAsValue() const
1734 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1735 state
->SetString("lthi_id", StringPrintf("%p", this));
1736 state
->Set("device_viewport_size", MathUtil::asValue(m_deviceViewportSize
).release());
1738 state
->Set("tiles", m_tileManager
->AllTilesAsValue().release());
1739 state
->Set("active_tree", activeTree()->AsValue().release());
1740 return state
.PassAs
<base::Value
>();
1744 LayerImpl
* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl
* layer
)
1749 if (layer
->drawsContent())
1752 for (LayerImpl::LayerList::const_iterator it
= layer
->children().begin();
1753 it
!= layer
->children().end(); ++it
) {
1754 LayerImpl
* nccr
= getNonCompositedContentLayerRecursive(*it
);
1762 skia::RefPtr
<SkPicture
> LayerTreeHostImpl::capturePicture()
1764 LayerTreeImpl
* tree
= pendingTree() ? pendingTree() : activeTree();
1765 LayerImpl
* layer
= getNonCompositedContentLayerRecursive(tree
->RootLayer());
1766 return layer
? layer
->getPicture() : skia::RefPtr
<SkPicture
>();
1769 void LayerTreeHostImpl::setDebugState(const LayerTreeDebugState
& debugState
)
1771 m_debugState
= debugState
;
1774 m_tileManager
->SetRecordRenderingStats(m_debugState
.recordRenderingStats());
1777 void LayerTreeHostImpl::savePaintTime(const base::TimeDelta
& totalPaintTime
)
1779 m_paintTimeCounter
->SavePaintTime(totalPaintTime
);