[chromium] LayerRendererChromium is not getting visibility messages in single threade...
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCLayerTreeHostImpl.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCLayerTreeHostImpl.h"
28
29 #include "LayerRendererChromium.h"
30 #include "TextStream.h"
31 #include "TraceEvent.h"
32 #include "TrackingTextureAllocator.h"
33 #include "cc/CCActiveGestureAnimation.h"
34 #include "cc/CCDamageTracker.h"
35 #include "cc/CCDebugRectHistory.h"
36 #include "cc/CCDelayBasedTimeSource.h"
37 #include "cc/CCFontAtlas.h"
38 #include "cc/CCFrameRateCounter.h"
39 #include "cc/CCHeadsUpDisplay.h"
40 #include "cc/CCLayerIterator.h"
41 #include "cc/CCLayerTreeHost.h"
42 #include "cc/CCLayerTreeHostCommon.h"
43 #include "cc/CCOverdrawMetrics.h"
44 #include "cc/CCPageScaleAnimation.h"
45 #include "cc/CCRenderPassDrawQuad.h"
46 #include "cc/CCSettings.h"
47 #include "cc/CCSingleThreadProxy.h"
48 #include <wtf/CurrentTime.h>
49
50 using WebKit::WebTransformationMatrix;
51
52 namespace {
53
54 void didVisibilityChange(WebCore::CCLayerTreeHostImpl* id, bool visible)
55 {
56     if (visible) {
57         TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id);
58         return;
59     }
60
61     TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id);
62 }
63
64 } // namespace
65
66 namespace WebCore {
67
68 class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
69     WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImplTimeSourceAdapter);
70 public:
71     static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
72     {
73         return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
74     }
75     virtual ~CCLayerTreeHostImplTimeSourceAdapter()
76     {
77         m_timeSource->setClient(0);
78         m_timeSource->setActive(false);
79     }
80
81     virtual void onTimerTick() OVERRIDE
82     {
83         // FIXME: We require that animate be called on the impl thread. This
84         // avoids asserts in single threaded mode. Ideally background ticking
85         // would be handled by the proxy/scheduler and this could be removed.
86         DebugScopedSetImplThread impl;
87
88         m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime());
89     }
90
91     void setActive(bool active)
92     {
93         if (active != m_timeSource->active())
94             m_timeSource->setActive(active);
95     }
96
97 private:
98     CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
99         : m_layerTreeHostImpl(layerTreeHostImpl)
100         , m_timeSource(timeSource)
101     {
102         m_timeSource->setClient(this);
103     }
104
105     CCLayerTreeHostImpl* m_layerTreeHostImpl;
106     RefPtr<CCDelayBasedTimeSource> m_timeSource;
107 };
108
109 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
110 {
111     return adoptPtr(new CCLayerTreeHostImpl(settings, client));
112 }
113
114 CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
115     : m_client(client)
116     , m_sourceFrameNumber(-1)
117     , m_frameNumber(0)
118     , m_rootScrollLayerImpl(0)
119     , m_currentlyScrollingLayerImpl(0)
120     , m_scrollingLayerIdFromPreviousTree(-1)
121     , m_settings(settings)
122     , m_deviceScaleFactor(1)
123     , m_visible(true)
124     , m_contentsTexturesWerePurgedSinceLastCommit(false)
125     , m_memoryAllocationLimitBytes(TextureManager::highLimitBytes(viewportSize()))
126     , m_headsUpDisplay(CCHeadsUpDisplay::create())
127     , m_pageScale(1)
128     , m_pageScaleDelta(1)
129     , m_sentPageScaleDelta(1)
130     , m_minPageScale(0)
131     , m_maxPageScale(0)
132     , m_hasTransparentBackground(false)
133     , m_needsAnimateLayers(false)
134     , m_pinchGestureActive(false)
135     , m_fpsCounter(CCFrameRateCounter::create())
136     , m_debugRectHistory(CCDebugRectHistory::create())
137 {
138     ASSERT(CCProxy::isImplThread());
139     didVisibilityChange(this, m_visible);
140 }
141
142 CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
143 {
144     ASSERT(CCProxy::isImplThread());
145     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()");
146
147     if (m_rootLayerImpl)
148         clearRenderSurfaces();
149 }
150
151 void CCLayerTreeHostImpl::beginCommit()
152 {
153 }
154
155 void CCLayerTreeHostImpl::commitComplete()
156 {
157     // Recompute max scroll position; must be after layer content bounds are
158     // updated.
159     updateMaxScrollPosition();
160     m_contentsTexturesWerePurgedSinceLastCommit = false;
161 }
162
163 bool CCLayerTreeHostImpl::canDraw()
164 {
165     if (!m_rootLayerImpl)
166         return false;
167     if (viewportSize().isEmpty())
168         return false;
169     if (!m_layerRenderer)
170         return false;
171     if (m_contentsTexturesWerePurgedSinceLastCommit)
172         return false;
173     return true;
174 }
175
176 CCGraphicsContext* CCLayerTreeHostImpl::context() const
177 {
178     return m_context.get();
179 }
180
181 void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
182 {
183     animatePageScale(monotonicTime);
184     animateLayers(monotonicTime, wallClockTime);
185     animateGestures(monotonicTime);
186 }
187
188 void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
189 {
190     if (!m_rootScrollLayerImpl)
191         return;
192
193     IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
194     scrollTotal.scale(m_pageScaleDelta);
195     float scaleTotal = m_pageScale * m_pageScaleDelta;
196     IntSize scaledContentSize = contentSize();
197     scaledContentSize.scale(m_pageScaleDelta);
198
199     m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, startTime);
200
201     if (anchorPoint) {
202         IntSize windowAnchor(targetPosition);
203         windowAnchor.scale(scaleTotal / pageScale);
204         windowAnchor -= scrollTotal;
205         m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration);
206     } else
207         m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration);
208
209     m_client->setNeedsRedrawOnImplThread();
210     m_client->setNeedsCommitOnImplThread();
211 }
212
213 void CCLayerTreeHostImpl::setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAnimation> gestureAnimation)
214 {
215     m_activeGestureAnimation = gestureAnimation;
216
217     if (m_activeGestureAnimation)
218         m_client->setNeedsRedrawOnImplThread();
219 }
220
221 void CCLayerTreeHostImpl::scheduleAnimation()
222 {
223     m_client->setNeedsRedrawOnImplThread();
224 }
225
226 void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
227 {
228     // For now, we use damage tracking to compute a global scissor. To do this, we must
229     // compute all damage tracking before drawing anything, so that we know the root
230     // damage rect. The root damage rect is then used to scissor each surface.
231
232     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
233         CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
234         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
235         ASSERT(renderSurface);
236         renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters());
237     }
238 }
239
240 void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
241 {
242     ASSERT(renderSurfaceLayerList.isEmpty());
243     ASSERT(m_rootLayerImpl);
244
245     renderSurfaceLayerList.append(m_rootLayerImpl.get());
246
247     if (!m_rootLayerImpl->renderSurface())
248         m_rootLayerImpl->createRenderSurface();
249     m_rootLayerImpl->renderSurface()->clearLayerList();
250     m_rootLayerImpl->renderSurface()->setContentRect(IntRect(IntPoint(), deviceViewportSize()));
251
252     m_rootLayerImpl->setClipRect(IntRect(IntPoint(), deviceViewportSize()));
253
254     {
255         TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
256         WebTransformationMatrix identityMatrix;
257         WebTransformationMatrix deviceScaleTransform;
258         deviceScaleTransform.scale(m_deviceScaleFactor);
259         CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), m_rootLayerImpl.get(), deviceScaleTransform, identityMatrix, renderSurfaceLayerList, m_rootLayerImpl->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize);
260
261         trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
262
263         if (layerRendererCapabilities().usingPartialSwap)
264             m_rootScissorRect = m_rootLayerImpl->renderSurface()->damageTracker()->currentDamageRect();
265         else
266             m_rootScissorRect = FloatRect(FloatPoint(0, 0), deviceViewportSize());
267
268         CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, m_rootScissorRect);
269     }
270 }
271
272 bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
273 {
274     ASSERT(frame.renderPasses.isEmpty());
275
276     calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
277
278     TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
279
280     m_rootLayerImpl->setScissorRect(enclosingIntRect(m_rootScissorRect));
281
282     // Create the render passes in dependency order.
283     HashMap<CCRenderSurface*, CCRenderPass*> surfacePassMap;
284     for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
285         CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
286         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
287
288         OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface);
289         surfacePassMap.add(renderSurface, pass.get());
290         frame.renderPasses.append(pass.release());
291     }
292
293     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
294     CCOcclusionTrackerImpl occlusionTracker(enclosingIntRect(m_rootScissorRect), recordMetricsForFrame);
295     occlusionTracker.setMinimumTrackingSize(CCOcclusionTrackerImpl::preferredMinimumTrackingSize());
296
297     // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
298     typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
299
300     // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
301     // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
302     // in the future.
303     bool drawFrame = true;
304
305     CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerList);
306     for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
307         CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSurface();
308         CCRenderPass* pass = surfacePassMap.get(renderSurface);
309         bool hadMissingTiles = false;
310
311         occlusionTracker.enterLayer(it);
312
313         if (it.representsContributingRenderSurface() && !it->renderSurface()->scissorRect().isEmpty()) {
314             CCRenderPass* contributingRenderPass = surfacePassMap.get(it->renderSurface());
315             pass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker);
316         } else if (it.representsItself() && !occlusionTracker.occluded(*it, it->visibleLayerRect()) && !it->visibleLayerRect().isEmpty() && !it->scissorRect().isEmpty()) {
317             it->willDraw(m_layerRenderer.get(), context());
318             frame.willDrawLayers.append(*it);
319
320             pass->appendQuadsForLayer(*it, &occlusionTracker, hadMissingTiles);
321         }
322
323         if (hadMissingTiles) {
324             bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
325             if (layerHasAnimatingTransform)
326                 drawFrame = false;
327         }
328
329         occlusionTracker.leaveLayer(it);
330     }
331
332     if (!m_hasTransparentBackground) {
333         frame.renderPasses.last()->setHasTransparentBackground(false);
334         frame.renderPasses.last()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
335     }
336
337     if (drawFrame)
338         occlusionTracker.overdrawMetrics().recordMetrics(this);
339
340     m_layerRenderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
341     removePassesWithCachedTextures(frame.renderPasses, frame.skippedPasses);
342
343     return drawFrame;
344 }
345
346 void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
347 {
348     bool subtreeNeedsAnimateLayers = false;
349
350     CCLayerAnimationController* currentController = current->layerAnimationController();
351
352     bool hadActiveAnimation = currentController->hasActiveAnimation();
353     currentController->animate(monotonicTime, events);
354     bool startedAnimation = events->size() > 0;
355
356     // We animated if we either ticked a running animation, or started a new animation.
357     if (hadActiveAnimation || startedAnimation)
358         didAnimate = true;
359
360     // If the current controller still has an active animation, we must continue animating layers.
361     if (currentController->hasActiveAnimation())
362          subtreeNeedsAnimateLayers = true;
363
364     for (size_t i = 0; i < current->children().size(); ++i) {
365         bool childNeedsAnimateLayers = false;
366         animateLayersRecursive(current->children()[i].get(), monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
367         if (childNeedsAnimateLayers)
368             subtreeNeedsAnimateLayers = true;
369     }
370
371     needsAnimateLayers = subtreeNeedsAnimateLayers;
372 }
373
374 void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
375 {
376     // Lazily create the timeSource adapter so that we can vary the interval for testing.
377     if (!m_timeSourceClientAdapter)
378         m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread()));
379
380     m_timeSourceClientAdapter->setActive(enabled);
381 }
382
383 IntSize CCLayerTreeHostImpl::contentSize() const
384 {
385     // TODO(aelias): Hardcoding the first child here is weird. Think of
386     // a cleaner way to get the contentBounds on the Impl side.
387     if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
388         return IntSize();
389     return m_rootScrollLayerImpl->children()[0]->contentBounds();
390 }
391
392 void CCLayerTreeHostImpl::removeRenderPassesRecursive(CCRenderPassList& passes, size_t bottomPass, const CCRenderPass* firstToRemove, CCRenderPassList& skippedPasses)
393 {
394     size_t removeIndex = passes.find(firstToRemove);
395
396     // The pass was already removed by another quad - probably the original, and we are the replica.
397     if (removeIndex == notFound)
398         return;
399
400     OwnPtr<CCRenderPass> removedPass = passes[removeIndex].release();
401     passes.remove(removeIndex);
402
403     // Now follow up for all RenderPass quads and remove their render passes recursively.
404     const CCQuadList& quadList = removedPass->quadList();
405     CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
406     for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
407         CCDrawQuad* currentQuad = (*quadListIterator).get();
408         if (currentQuad->material() != CCDrawQuad::RenderPass)
409             continue;
410
411         CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad);
412         const CCRenderPass* nextRenderPass = renderPassQuad->renderPass();
413
414         // Our search is now limited up to the pass that we just removed.
415         // Substitute removeIndex for bottomPass now.
416         removeRenderPassesRecursive(passes, removeIndex, nextRenderPass, skippedPasses);
417     }
418     skippedPasses.append(removedPass.release());
419 }
420
421 void CCLayerTreeHostImpl::removePassesWithCachedTextures(CCRenderPassList& passes, CCRenderPassList& skippedPasses)
422 {
423     for (int passIndex = passes.size() - 1; passIndex >= 0; --passIndex) {
424         CCRenderPass* currentPass = passes[passIndex].get();
425         const CCQuadList& quadList = currentPass->quadList();
426         CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
427
428         for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
429             CCDrawQuad* currentQuad = quadListIterator->get();
430
431             if (currentQuad->material() != CCDrawQuad::RenderPass)
432                 continue;
433
434             CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad);
435             CCRenderSurface* targetSurface = renderPassQuad->renderPass()->targetSurface();
436
437             if (targetSurface->contentsChanged() || !targetSurface->hasCachedContentsTexture())
438                 continue;
439
440             // Reserve the texture immediately. We do not need to pass in layer renderer
441             // since the texture already exists, just needs to be reserved.
442             if (!targetSurface->prepareContentsTexture(0))
443                 continue;
444
445             // We are changing the vector in the middle of reverse iteration.
446             // We are guaranteed that any data from iterator to the end will not change.
447             // Capture the iterator position from the end, and restore it after the change.
448             int positionFromEnd = passes.size() - passIndex;
449             removeRenderPassesRecursive(passes, passIndex, renderPassQuad->renderPass(), skippedPasses);
450             passIndex = passes.size() - positionFromEnd;
451             ASSERT(passIndex >= 0);
452         }
453     }
454 }
455
456 bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
457 {
458     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw");
459     ASSERT(canDraw());
460
461     frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
462     frame.renderPasses.clear();
463     frame.renderSurfaceLayerList->clear();
464     frame.willDrawLayers.clear();
465
466     if (!calculateRenderPasses(frame))
467         return false;
468
469     // If we return true, then we expect drawLayers() to be called before this function is called again.
470     return true;
471 }
472
473 void CCLayerTreeHostImpl::releaseContentsTextures()
474 {
475     contentsTextureAllocator()->deleteAllTextures();
476     m_contentsTexturesWerePurgedSinceLastCommit = true;
477 }
478
479 void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
480 {
481     if (m_memoryAllocationLimitBytes == bytes)
482         return;
483     m_memoryAllocationLimitBytes = bytes;
484
485     ASSERT(bytes);
486     m_client->setNeedsCommitOnImplThread();
487 }
488
489 void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
490 {
491     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers");
492     ASSERT(canDraw());
493     ASSERT(!frame.renderPasses.isEmpty());
494
495     // FIXME: use the frame begin time from the overall compositor scheduler.
496     // This value is currently inaccessible because it is up in Chromium's
497     // RenderWidget.
498
499     // The root RenderPass is the last one to be drawn.
500     CCRenderPass* rootRenderPass = frame.renderPasses.last().get();
501
502     m_fpsCounter->markBeginningOfFrame(currentTime());
503     m_layerRenderer->beginDrawingFrame(rootRenderPass);
504
505     for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
506         CCRenderPass* renderPass = frame.renderPasses[i].get();
507
508         FloatRect rootScissorRectInCurrentSurface = renderPass->targetSurface()->computeRootScissorRectInCurrentSurface(m_rootScissorRect);
509         m_layerRenderer->drawRenderPass(renderPass, rootScissorRectInCurrentSurface);
510
511         renderPass->targetSurface()->damageTracker()->didDrawDamagedArea();
512     }
513
514     if (m_debugRectHistory->enabled(settings()))
515         m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, settings());
516
517     if (m_headsUpDisplay->enabled(settings()))
518         m_headsUpDisplay->draw(this);
519
520     m_layerRenderer->finishDrawingFrame();
521
522     ++m_frameNumber;
523
524     // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
525     m_rootLayerImpl->resetAllChangeTrackingForSubtree();
526 }
527
528 void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
529 {
530     for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
531         frame.willDrawLayers[i]->didDraw();
532 }
533
534 void CCLayerTreeHostImpl::finishAllRendering()
535 {
536     if (m_layerRenderer)
537         m_layerRenderer->finish();
538 }
539
540 bool CCLayerTreeHostImpl::isContextLost()
541 {
542     return m_layerRenderer && m_layerRenderer->isContextLost();
543 }
544
545 const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities() const
546 {
547     return m_layerRenderer->capabilities();
548 }
549
550 TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
551 {
552     return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
553 }
554
555 bool CCLayerTreeHostImpl::swapBuffers()
556 {
557     ASSERT(m_layerRenderer);
558
559     m_fpsCounter->markEndOfFrame();
560     return m_layerRenderer->swapBuffers(enclosingIntRect(m_rootScissorRect));
561 }
562
563 void CCLayerTreeHostImpl::didLoseContext()
564 {
565     m_client->didLoseContextOnImplThread();
566 }
567
568 void CCLayerTreeHostImpl::onSwapBuffersComplete()
569 {
570     m_client->onSwapBuffersCompleteOnImplThread();
571 }
572
573 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
574 {
575     ASSERT(m_layerRenderer);
576     m_layerRenderer->getFramebufferPixels(pixels, rect);
577 }
578
579 static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer)
580 {
581     if (!layer)
582         return 0;
583
584     if (layer->scrollable())
585         return layer;
586
587     for (size_t i = 0; i < layer->children().size(); ++i) {
588         CCLayerImpl* found = findRootScrollLayer(layer->children()[i].get());
589         if (found)
590             return found;
591     }
592
593     return 0;
594 }
595
596 // Content layers can be either directly scrollable or contained in an outer
597 // scrolling layer which applies the scroll transform. Given a content layer,
598 // this function returns the associated scroll layer if any.
599 static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl)
600 {
601     if (!layerImpl)
602         return 0;
603
604     if (layerImpl->scrollable())
605         return layerImpl;
606
607     if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
608         return layerImpl->parent();
609
610     return 0;
611 }
612
613 void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
614 {
615     m_rootLayerImpl = layer;
616     m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
617     m_currentlyScrollingLayerImpl = 0;
618
619     if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
620         m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
621
622     m_scrollingLayerIdFromPreviousTree = -1;
623 }
624
625 PassOwnPtr<CCLayerImpl> CCLayerTreeHostImpl::detachLayerTree()
626 {
627     // Clear all data structures that have direct references to the layer tree.
628     m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1;
629     m_currentlyScrollingLayerImpl = 0;
630     m_renderSurfaceLayerList.clear();
631
632     return m_rootLayerImpl.release();
633 }
634
635 void CCLayerTreeHostImpl::setVisible(bool visible)
636 {
637     ASSERT(CCProxy::isImplThread());
638
639     if (m_visible == visible)
640         return;
641     m_visible = visible;
642     didVisibilityChange(this, m_visible);
643
644     if (!m_layerRenderer)
645         return;
646
647     m_layerRenderer->setVisible(visible);
648
649     setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
650 }
651
652 bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<CCGraphicsContext> context, TextureUploaderOption textureUploader)
653 {
654     GraphicsContext3D* context3d = context->context3D();
655     if (!context3d) {
656         // FIXME: Implement this path for software compositing.
657         return false;
658     }
659
660     OwnPtr<LayerRendererChromium> layerRenderer;
661     layerRenderer = LayerRendererChromium::create(this, context3d, textureUploader);
662
663     // Since we now have a new context/layerRenderer, we cannot continue to use the old
664     // resources (i.e. renderSurfaces and texture IDs).
665     if (m_rootLayerImpl) {
666         clearRenderSurfaces();
667         sendDidLoseContextRecursive(m_rootLayerImpl.get());
668     }
669
670     m_layerRenderer = layerRenderer.release();
671     if (m_layerRenderer)
672         m_context = context;
673
674     if (!m_visible && m_layerRenderer)
675          m_layerRenderer->setVisible(m_visible);
676
677     return m_layerRenderer;
678 }
679
680 void CCLayerTreeHostImpl::setViewportSize(const IntSize& viewportSize)
681 {
682     if (viewportSize == m_viewportSize)
683         return;
684
685     m_viewportSize = viewportSize;
686
687     m_deviceViewportSize = viewportSize;
688     m_deviceViewportSize.scale(m_deviceScaleFactor);
689
690     updateMaxScrollPosition();
691
692     if (m_layerRenderer)
693         m_layerRenderer->viewportChanged();
694 }
695
696 static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange)
697 {
698     if (!layerImpl)
699         return;
700
701     if (layerImpl->scrollable()) {
702         // We need to convert impl-side scroll deltas to pageScale space.
703         FloatSize scrollDelta = layerImpl->scrollDelta();
704         scrollDelta.scale(pageScaleChange);
705         layerImpl->setScrollDelta(scrollDelta);
706     }
707
708     for (size_t i = 0; i < layerImpl->children().size(); ++i)
709         adjustScrollsForPageScaleChange(layerImpl->children()[i].get(), pageScaleChange);
710 }
711
712 static void applyPageScaleDeltaToScrollLayers(CCLayerImpl* layerImpl, float pageScaleDelta)
713 {
714     if (!layerImpl)
715         return;
716
717     if (layerImpl->scrollable())
718         layerImpl->setPageScaleDelta(pageScaleDelta);
719
720     for (size_t i = 0; i < layerImpl->children().size(); ++i)
721         applyPageScaleDeltaToScrollLayers(layerImpl->children()[i].get(), pageScaleDelta);
722 }
723
724 void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
725 {
726     if (deviceScaleFactor == m_deviceScaleFactor)
727         return;
728     m_deviceScaleFactor = deviceScaleFactor;
729
730     m_deviceViewportSize = viewportSize();
731     m_deviceViewportSize.scale(m_deviceScaleFactor);
732     updateMaxScrollPosition();
733     if (m_layerRenderer)
734         m_layerRenderer->viewportChanged();
735 }
736
737
738 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
739 {
740     if (!pageScale)
741         return;
742
743     if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
744         return;
745
746     m_minPageScale = minPageScale;
747     m_maxPageScale = maxPageScale;
748
749     float pageScaleChange = pageScale / m_pageScale;
750     m_pageScale = pageScale;
751
752     if (pageScaleChange != 1)
753         adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
754
755     // Clamp delta to limits and refresh display matrix.
756     setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
757     m_sentPageScaleDelta = 1;
758     applyPageScaleDeltaToScrollLayers(m_rootScrollLayerImpl, m_pageScaleDelta);
759 }
760
761 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
762 {
763     // Clamp to the current min/max limits.
764     float finalMagnifyScale = m_pageScale * delta;
765     if (m_minPageScale && finalMagnifyScale < m_minPageScale)
766         delta = m_minPageScale / m_pageScale;
767     else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
768         delta = m_maxPageScale / m_pageScale;
769
770     if (delta == m_pageScaleDelta)
771         return;
772
773     m_pageScaleDelta = delta;
774
775     updateMaxScrollPosition();
776     applyPageScaleDeltaToScrollLayers(m_rootScrollLayerImpl, m_pageScaleDelta);
777 }
778
779 void CCLayerTreeHostImpl::updateMaxScrollPosition()
780 {
781     if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
782         return;
783
784     FloatSize viewBounds = m_viewportSize;
785     if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
786         if (clipLayer->masksToBounds())
787             viewBounds = clipLayer->bounds();
788     }
789     viewBounds.scale(1 / m_pageScaleDelta);
790     viewBounds.scale(m_deviceScaleFactor);
791
792     // maxScroll is computed in physical pixels, but scroll positions are in layout pixels.
793     IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
794     maxScroll.scale(1 / m_deviceScaleFactor);
795     // The viewport may be larger than the contents in some cases, such as
796     // having a vertical scrollbar but no horizontal overflow.
797     maxScroll.clampNegativeToZero();
798
799     m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
800 }
801
802 void CCLayerTreeHostImpl::setNeedsRedraw()
803 {
804     m_client->setNeedsRedrawOnImplThread();
805 }
806
807 bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList()
808 {
809     if (!m_rootLayerImpl)
810         return false;
811
812     // We need both a non-empty render surface layer list and a root render
813     // surface to be able to iterate over the visible layers.
814     if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
815         return true;
816
817     // If we are called after setRootLayer() but before prepareToDraw(), we need
818     // to recalculate the visible layers. This prevents being unable to scroll
819     // during part of a commit.
820     m_renderSurfaceLayerList.clear();
821     calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
822
823     return m_renderSurfaceLayerList.size();
824 }
825
826 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
827 {
828     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin");
829
830     ASSERT(!m_currentlyScrollingLayerImpl);
831     clearCurrentlyScrollingLayer();
832
833     if (!ensureRenderSurfaceLayerList())
834         return ScrollIgnored;
835
836     IntPoint deviceViewportPoint = viewportPoint;
837     deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor);
838
839     // First find out which layer was hit from the saved list of visible layers
840     // in the most recent frame.
841     CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(viewportPoint, m_renderSurfaceLayerList);
842
843     // Walk up the hierarchy and look for a scrollable layer.
844     CCLayerImpl* potentiallyScrollingLayerImpl = 0;
845     for (; layerImpl; layerImpl = layerImpl->parent()) {
846         // The content layer can also block attempts to scroll outside the main thread.
847         if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread)
848             return ScrollOnMainThread;
849
850         CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
851         if (!scrollLayerImpl)
852             continue;
853
854         ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type);
855
856         // If any layer wants to divert the scroll event to the main thread, abort.
857         if (status == ScrollOnMainThread)
858             return ScrollOnMainThread;
859
860         if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
861             potentiallyScrollingLayerImpl = scrollLayerImpl;
862     }
863
864     if (potentiallyScrollingLayerImpl) {
865         m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
866         return ScrollStarted;
867     }
868     return ScrollIgnored;
869 }
870
871 void CCLayerTreeHostImpl::scrollBy(const IntSize& scrollDelta)
872 {
873     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy");
874     if (!m_currentlyScrollingLayerImpl)
875         return;
876
877     FloatSize pendingDelta(scrollDelta);
878     pendingDelta.scale(1 / m_pageScaleDelta);
879
880     for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl && !pendingDelta.isZero(); layerImpl = layerImpl->parent()) {
881         if (!layerImpl->scrollable())
882             continue;
883         FloatSize previousDelta(layerImpl->scrollDelta());
884         layerImpl->scrollBy(pendingDelta);
885         // Reset the pending scroll delta to zero if the layer was able to move along the requested
886         // axis. This is to ensure it is possible to scroll exactly to the beginning or end of a
887         // scroll area regardless of the scroll step. For diagonal scrolls this also avoids applying
888         // the scroll on one axis to multiple layers.
889         if (previousDelta.width() != layerImpl->scrollDelta().width())
890             pendingDelta.setWidth(0);
891         if (previousDelta.height() != layerImpl->scrollDelta().height())
892             pendingDelta.setHeight(0);
893     }
894
895     if (!scrollDelta.isZero() && pendingDelta.isEmpty()) {
896         m_client->setNeedsCommitOnImplThread();
897         m_client->setNeedsRedrawOnImplThread();
898     }
899 }
900
901 void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer()
902 {
903     m_currentlyScrollingLayerImpl = 0;
904     m_scrollingLayerIdFromPreviousTree = -1;
905 }
906
907 void CCLayerTreeHostImpl::scrollEnd()
908 {
909     clearCurrentlyScrollingLayer();
910 }
911
912 void CCLayerTreeHostImpl::pinchGestureBegin()
913 {
914     m_pinchGestureActive = true;
915     m_previousPinchAnchor = IntPoint();
916 }
917
918 void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
919                                              const IntPoint& anchor)
920 {
921     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate");
922
923     if (!m_rootScrollLayerImpl)
924         return;
925
926     if (m_previousPinchAnchor == IntPoint::zero())
927         m_previousPinchAnchor = anchor;
928
929     // Keep the center-of-pinch anchor specified by (x, y) in a stable
930     // position over the course of the magnify.
931     FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta);
932     setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
933     FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
934     FloatSize move = previousScaleAnchor - newScaleAnchor;
935
936     m_previousPinchAnchor = anchor;
937
938     m_rootScrollLayerImpl->scrollBy(roundedIntSize(move));
939     m_client->setNeedsCommitOnImplThread();
940     m_client->setNeedsRedrawOnImplThread();
941 }
942
943 void CCLayerTreeHostImpl::pinchGestureEnd()
944 {
945     m_pinchGestureActive = false;
946
947     m_client->setNeedsCommitOnImplThread();
948 }
949
950 void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
951 {
952     float pageScale = m_pageScaleAnimation->finalPageScale();
953     IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
954     scrollOffset.scale(m_pageScale / pageScale);
955     makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
956 }
957
958 void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
959 {
960     if (!m_rootScrollLayerImpl)
961         return;
962
963     // Only send fake scroll/zoom deltas if we're pinch zooming out by a
964     // significant amount. This also ensures only one fake delta set will be
965     // sent.
966     const float pinchZoomOutSensitivity = 0.95;
967     if (m_pageScaleDelta > pinchZoomOutSensitivity)
968         return;
969
970     // Compute where the scroll offset/page scale would be if fully pinch-zoomed
971     // out from the anchor point.
972     IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
973     scrollBegin.scale(m_pageScaleDelta);
974     float scaleBegin = m_pageScale * m_pageScaleDelta;
975     float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
976     FloatSize scaledContentsSize = contentSize();
977     scaledContentsSize.scale(pageScaleDeltaToSend);
978
979     FloatSize anchor = toSize(m_previousPinchAnchor);
980     FloatSize scrollEnd = scrollBegin + anchor;
981     scrollEnd.scale(m_minPageScale / scaleBegin);
982     scrollEnd -= anchor;
983     scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0));
984     scrollEnd.scale(1 / pageScaleDeltaToSend);
985     scrollEnd.scale(m_deviceScaleFactor);
986
987     makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale);
988 }
989
990 void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
991 {
992     if (!m_rootScrollLayerImpl)
993         return;
994
995     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
996     scroll.layerId = m_rootScrollLayerImpl->id();
997     scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
998     scrollInfo->scrolls.append(scroll);
999     m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
1000     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
1001 }
1002
1003 static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl)
1004 {
1005     if (!layerImpl)
1006         return;
1007
1008     if (!layerImpl->scrollDelta().isZero()) {
1009         IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
1010         CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
1011         scroll.layerId = layerImpl->id();
1012         scroll.scrollDelta = scrollDelta;
1013         scrollInfo->scrolls.append(scroll);
1014         layerImpl->setSentScrollDelta(scrollDelta);
1015     }
1016
1017     for (size_t i = 0; i < layerImpl->children().size(); ++i)
1018         collectScrollDeltas(scrollInfo, layerImpl->children()[i].get());
1019 }
1020
1021 PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
1022 {
1023     OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
1024
1025     if (m_pinchGestureActive || m_pageScaleAnimation) {
1026         m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
1027         if (m_pinchGestureActive)
1028             computePinchZoomDeltas(scrollInfo.get());
1029         else if (m_pageScaleAnimation.get())
1030             computeDoubleTapZoomDeltas(scrollInfo.get());
1031         return scrollInfo.release();
1032     }
1033
1034     collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
1035     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
1036
1037     return scrollInfo.release();
1038 }
1039
1040 void CCLayerTreeHostImpl::setFullRootLayerDamage()
1041 {
1042     if (m_rootLayerImpl) {
1043         CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
1044         if (renderSurface)
1045             renderSurface->damageTracker()->forceFullDamageNextUpdate();
1046     }
1047 }
1048
1049 void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
1050 {
1051     if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1052         return;
1053
1054     IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
1055
1056     setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
1057     IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
1058     nextScroll.scale(1 / m_pageScaleDelta);
1059     m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1060     m_client->setNeedsRedrawOnImplThread();
1061
1062     if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
1063         m_pageScaleAnimation.clear();
1064         m_client->setNeedsCommitOnImplThread();
1065     }
1066 }
1067
1068 void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
1069 {
1070     if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl)
1071         return;
1072
1073     TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
1074
1075     OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
1076
1077     bool didAnimate = false;
1078     animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1079
1080     if (!events->isEmpty())
1081         m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
1082
1083     if (didAnimate)
1084         m_client->setNeedsRedrawOnImplThread();
1085
1086     setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1087 }
1088
1089 double CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
1090 {
1091     return 1;
1092 }
1093
1094 void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
1095 {
1096     ASSERT(current);
1097     current->didLoseContext();
1098     if (current->maskLayer())
1099         sendDidLoseContextRecursive(current->maskLayer());
1100     if (current->replicaLayer())
1101         sendDidLoseContextRecursive(current->replicaLayer());
1102     for (size_t i = 0; i < current->children().size(); ++i)
1103         sendDidLoseContextRecursive(current->children()[i].get());
1104 }
1105
1106 static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
1107 {
1108     ASSERT(current);
1109     for (size_t i = 0; i < current->children().size(); ++i)
1110         clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i].get());
1111     current->clearRenderSurface();
1112 }
1113
1114 void CCLayerTreeHostImpl::clearRenderSurfaces()
1115 {
1116     clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
1117     m_renderSurfaceLayerList.clear();
1118 }
1119
1120 String CCLayerTreeHostImpl::layerTreeAsText() const
1121 {
1122     TextStream ts;
1123     if (m_rootLayerImpl) {
1124         ts << m_rootLayerImpl->layerTreeAsText();
1125         ts << "RenderSurfaces:\n";
1126         dumpRenderSurfaces(ts, 1, m_rootLayerImpl.get());
1127     }
1128     return ts.release();
1129 }
1130
1131 void CCLayerTreeHostImpl::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
1132 {
1133     m_headsUpDisplay->setFontAtlas(fontAtlas);
1134 }
1135
1136 void CCLayerTreeHostImpl::dumpRenderSurfaces(TextStream& ts, int indent, const CCLayerImpl* layer) const
1137 {
1138     if (layer->renderSurface())
1139         layer->renderSurface()->dumpSurface(ts, indent);
1140
1141     for (size_t i = 0; i < layer->children().size(); ++i)
1142         dumpRenderSurfaces(ts, indent, layer->children()[i].get());
1143 }
1144
1145
1146 void CCLayerTreeHostImpl::animateGestures(double monotonicTime)
1147 {
1148     if (!m_activeGestureAnimation)
1149         return;
1150
1151     bool isContinuing = m_activeGestureAnimation->animate(monotonicTime);
1152     if (isContinuing)
1153         m_client->setNeedsRedrawOnImplThread();
1154     else
1155         m_activeGestureAnimation.clear();
1156 }
1157
1158 } // namespace WebCore