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