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