[chromium] Early out in a new prepareToDraw() step if checkerboarding an accelerated...
[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 "Extensions3D.h"
30 #include "GraphicsContext3D.h"
31 #include "LayerRendererChromium.h"
32 #include "TraceEvent.h"
33 #include "cc/CCActiveGestureAnimation.h"
34 #include "cc/CCDamageTracker.h"
35 #include "cc/CCDelayBasedTimeSource.h"
36 #include "cc/CCGestureCurve.h"
37 #include "cc/CCLayerIterator.h"
38 #include "cc/CCLayerTreeHost.h"
39 #include "cc/CCLayerTreeHostCommon.h"
40 #include "cc/CCPageScaleAnimation.h"
41 #include "cc/CCRenderSurfaceDrawQuad.h"
42 #include "cc/CCThreadTask.h"
43 #include <wtf/CurrentTime.h>
44
45 namespace {
46 const double lowFrequencyAnimationInterval = 1;
47 } // namespace
48
49 namespace WebCore {
50
51 class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
52     WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImplTimeSourceAdapter);
53 public:
54     static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
55     {
56         return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
57     }
58     virtual ~CCLayerTreeHostImplTimeSourceAdapter()
59     {
60         m_timeSource->setClient(0);
61         m_timeSource->setActive(false);
62     }
63
64     virtual void onTimerTick()
65     {
66         m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime());
67     }
68
69     void setActive(bool active)
70     {
71         if (active != m_timeSource->active())
72             m_timeSource->setActive(active);
73     }
74
75 private:
76     CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
77         : m_layerTreeHostImpl(layerTreeHostImpl)
78         , m_timeSource(timeSource)
79     {
80         m_timeSource->setClient(this);
81     }
82
83     CCLayerTreeHostImpl* m_layerTreeHostImpl;
84     RefPtr<CCDelayBasedTimeSource> m_timeSource;
85 };
86
87 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCSettings& settings, CCLayerTreeHostImplClient* client)
88 {
89     return adoptPtr(new CCLayerTreeHostImpl(settings, client));
90 }
91
92 CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCSettings& settings, CCLayerTreeHostImplClient* client)
93     : m_client(client)
94     , m_sourceFrameNumber(-1)
95     , m_frameNumber(0)
96     , m_scrollLayerImpl(0)
97     , m_settings(settings)
98     , m_visible(true)
99     , m_pageScale(1)
100     , m_pageScaleDelta(1)
101     , m_sentPageScaleDelta(1)
102     , m_minPageScale(0)
103     , m_maxPageScale(0)
104     , m_needsAnimateLayers(false)
105     , m_pinchGestureActive(false)
106     , m_timeSourceClientAdapter(CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval * 1000.0, CCProxy::currentThread())))
107 {
108     ASSERT(CCProxy::isImplThread());
109 }
110
111 CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
112 {
113     ASSERT(CCProxy::isImplThread());
114     TRACE_EVENT("CCLayerTreeHostImpl::~CCLayerTreeHostImpl()", this, 0);
115     if (m_layerRenderer)
116         m_layerRenderer->close();
117 }
118
119 void CCLayerTreeHostImpl::beginCommit()
120 {
121 }
122
123 void CCLayerTreeHostImpl::commitComplete()
124 {
125     // Recompute max scroll position; must be after layer content bounds are
126     // updated.
127     updateMaxScrollPosition();
128 }
129
130 bool CCLayerTreeHostImpl::canDraw()
131 {
132     if (!rootLayer())
133         return false;
134     if (viewportSize().isEmpty())
135         return false;
136     return true;
137 }
138
139 GraphicsContext3D* CCLayerTreeHostImpl::context()
140 {
141     return m_layerRenderer ? m_layerRenderer->context() : 0;
142 }
143
144 void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
145 {
146     animatePageScale(monotonicTime);
147     animateLayers(monotonicTime, wallClockTime);
148     animateGestures(monotonicTime);
149 }
150
151 void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
152 {
153     if (!m_scrollLayerImpl)
154         return;
155
156     IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
157     scrollTotal.scale(m_pageScaleDelta);
158     float scaleTotal = m_pageScale * m_pageScaleDelta;
159     IntSize scaledContentSize = contentSize();
160     scaledContentSize.scale(m_pageScaleDelta);
161
162     m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, startTime);
163
164     if (anchorPoint) {
165         IntSize windowAnchor(targetPosition);
166         windowAnchor.scale(scaleTotal / pageScale);
167         windowAnchor -= scrollTotal;
168         m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration);
169     } else
170         m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration);
171
172     m_client->setNeedsRedrawOnImplThread();
173     m_client->setNeedsCommitOnImplThread();
174 }
175
176 void CCLayerTreeHostImpl::setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAnimation> gestureAnimation)
177 {
178     m_activeGestureAnimation = gestureAnimation;
179
180     if (m_activeGestureAnimation)
181         m_client->setNeedsRedrawOnImplThread();
182 }
183
184 void CCLayerTreeHostImpl::scheduleAnimation()
185 {
186     m_client->setNeedsRedrawOnImplThread();
187 }
188
189 void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
190 {
191     // For now, we use damage tracking to compute a global scissor. To do this, we must
192     // compute all damage tracking before drawing anything, so that we know the root
193     // damage rect. The root damage rect is then used to scissor each surface.
194
195     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
196         CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
197         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
198         ASSERT(renderSurface);
199         renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer());
200     }
201 }
202
203 static FloatRect damageInSurfaceSpace(CCLayerImpl* renderSurfaceLayer, const FloatRect& rootDamageRect)
204 {
205     FloatRect surfaceDamageRect;
206     // For now, we conservatively use the root damage as the damage for
207     // all surfaces, except perspective transforms.
208     const TransformationMatrix& screenSpaceTransform = renderSurfaceLayer->renderSurface()->screenSpaceTransform();
209     if (screenSpaceTransform.hasPerspective()) {
210         // Perspective projections do not play nice with mapRect of
211         // inverse transforms. In this uncommon case, its simpler to
212         // just redraw the entire surface.
213         // FIXME: use calculateVisibleRect to handle projections.
214         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
215         surfaceDamageRect = renderSurface->contentRect();
216     } else {
217         TransformationMatrix inverseScreenSpaceTransform = screenSpaceTransform.inverse();
218         surfaceDamageRect = inverseScreenSpaceTransform.mapRect(rootDamageRect);
219     }
220     return surfaceDamageRect;
221 }
222
223 bool CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
224 {
225     ASSERT(passes.isEmpty());
226     ASSERT(renderSurfaceLayerList.isEmpty());
227
228     renderSurfaceLayerList.append(rootLayer());
229
230     if (!rootLayer()->renderSurface())
231         rootLayer()->createRenderSurface();
232     rootLayer()->renderSurface()->clearLayerList();
233     rootLayer()->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize()));
234
235     rootLayer()->setClipRect(IntRect(IntPoint(), viewportSize()));
236
237     {
238         TransformationMatrix identityMatrix;
239         TRACE_EVENT("CCLayerTreeHostImpl::calcDrawEtc", this, 0);
240         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer(), rootLayer(), identityMatrix, identityMatrix, renderSurfaceLayerList, rootLayer()->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize);
241     }
242
243     TRACE_EVENT1("webkit", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(renderSurfaceLayerList.size()));
244
245     if (layerRendererCapabilities().usingPartialSwap)
246         trackDamageForAllSurfaces(rootLayer(), renderSurfaceLayerList);
247     m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect();
248
249     // Create the render passes in dependency order.
250     HashMap<CCRenderSurface*, CCRenderPass*> surfacePassMap;
251     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
252         CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
253         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
254
255         OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface);
256
257         FloatRect surfaceDamageRect;
258         if (layerRendererCapabilities().usingPartialSwap)
259             surfaceDamageRect = damageInSurfaceSpace(renderSurfaceLayer, m_rootDamageRect);
260         pass->setSurfaceDamageRect(surfaceDamageRect);
261
262         surfacePassMap.add(renderSurface, pass.get());
263         passes.append(pass.release());
264     }
265
266     IntRect scissorRect;
267     if (layerRendererCapabilities().usingPartialSwap)
268         scissorRect = enclosingIntRect(m_rootDamageRect);
269     else
270         scissorRect = IntRect(IntPoint(), viewportSize());
271
272     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
273     CCOcclusionTrackerImpl occlusionTracker(scissorRect, recordMetricsForFrame);
274
275     // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
276     typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
277
278     // If we are unable to draw an animation on some layer, then we abort the entire frame.
279     bool drawFrame = true;
280
281     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
282     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
283         CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSurface();
284
285         if (it.representsItself())
286             occlusionTracker.enterTargetRenderSurface(renderSurface);
287         else if (it.representsTargetRenderSurface())
288             occlusionTracker.finishedTargetRenderSurface(*it, renderSurface);
289         else
290             occlusionTracker.leaveToTargetRenderSurface(renderSurface);
291
292         if (it.representsTargetRenderSurface())
293             continue;
294         if (it->visibleLayerRect().isEmpty())
295             continue;
296
297         CCRenderPass* pass = surfacePassMap.get(renderSurface);
298         if (it.representsContributingRenderSurface()) {
299             pass->appendQuadsForRenderSurfaceLayer(*it);
300             continue;
301         }
302
303         it->willDraw(m_layerRenderer.get());
304
305         bool usedCheckerboard = false;
306         pass->appendQuadsForLayer(*it, &occlusionTracker, usedCheckerboard);
307         if (usedCheckerboard) {
308             bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
309             if (layerHasAnimatingTransform) {
310                 drawFrame = false;
311                 break;
312             }
313         }
314
315         occlusionTracker.markOccludedBehindLayer(*it);
316     }
317
318     if (drawFrame)
319         occlusionTracker.overdrawMetrics().recordMetrics(this);
320     return drawFrame;
321 }
322
323 void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
324 {
325     bool subtreeNeedsAnimateLayers = false;
326
327     CCLayerAnimationController* currentController = current->layerAnimationController();
328
329     bool hadActiveAnimation = currentController->hasActiveAnimation();
330     currentController->animate(monotonicTime, events);
331     bool startedAnimation = events->size() > 0;
332
333     // We animated if we either ticked a running animation, or started a new animation.
334     if (hadActiveAnimation || startedAnimation)
335         didAnimate = true;
336
337     // If the current controller still has an active animation, we must continue animating layers.
338     if (currentController->hasActiveAnimation())
339          subtreeNeedsAnimateLayers = true;
340
341     for (size_t i = 0; i < current->children().size(); ++i) {
342         bool childNeedsAnimateLayers = false;
343         animateLayersRecursive(current->children()[i].get(), monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
344         if (childNeedsAnimateLayers)
345             subtreeNeedsAnimateLayers = true;
346     }
347
348     needsAnimateLayers = subtreeNeedsAnimateLayers;
349 }
350
351 IntSize CCLayerTreeHostImpl::contentSize() const
352 {
353     // TODO(aelias): Hardcoding the first child here is weird. Think of
354     // a cleaner way to get the contentBounds on the Impl side.
355     if (!m_scrollLayerImpl || m_scrollLayerImpl->children().isEmpty())
356         return IntSize();
357     return m_scrollLayerImpl->children()[0]->contentBounds();
358 }
359
360 bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
361 {
362     TRACE_EVENT("CCLayerTreeHostImpl::prepareToDraw", this, 0);
363
364     frame.renderPasses.clear();
365     frame.renderSurfaceLayerList.clear();
366
367     if (!rootLayer())
368         return false;
369
370     if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList)) {
371         frame.renderPasses.clear();
372         frame.renderSurfaceLayerList.clear();
373         return false;
374     }
375
376     // If we return true, then we expect drawLayers() to be called before this function is called again.
377     return true;
378 }
379
380 void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
381 {
382     TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
383     ASSERT(m_layerRenderer);
384
385     m_layerRenderer->beginDrawingFrame();
386     for (size_t i = 0; i < frame.renderPasses.size(); ++i)
387         m_layerRenderer->drawRenderPass(frame.renderPasses[i].get());
388
389     typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
390
391     CCLayerIteratorType end = CCLayerIteratorType::end(&frame.renderSurfaceLayerList);
392     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&frame.renderSurfaceLayerList); it != end; ++it) {
393         if (it.representsItself() && !it->visibleLayerRect().isEmpty())
394             it->didDraw();
395     }
396     m_layerRenderer->finishDrawingFrame();
397
398     ++m_frameNumber;
399
400     // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
401     rootLayer()->resetAllChangeTrackingForSubtree();
402 }
403
404 void CCLayerTreeHostImpl::finishAllRendering()
405 {
406     if (m_layerRenderer)
407         m_layerRenderer->finish();
408 }
409
410 bool CCLayerTreeHostImpl::isContextLost()
411 {
412     return m_layerRenderer && m_layerRenderer->isContextLost();
413 }
414
415 const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities() const
416 {
417     return m_layerRenderer->capabilities();
418 }
419
420 TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
421 {
422     return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
423 }
424
425 void CCLayerTreeHostImpl::swapBuffers()
426 {
427     ASSERT(m_layerRenderer);
428     m_layerRenderer->swapBuffers(enclosingIntRect(m_rootDamageRect));
429 }
430
431 void CCLayerTreeHostImpl::didLoseContext()
432 {
433     m_client->didLoseContextOnImplThread();
434 }
435
436 void CCLayerTreeHostImpl::onSwapBuffersComplete()
437 {
438     m_client->onSwapBuffersCompleteOnImplThread();
439 }
440
441 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
442 {
443     ASSERT(m_layerRenderer);
444     m_layerRenderer->getFramebufferPixels(pixels, rect);
445 }
446
447 static CCLayerImpl* findScrollLayer(CCLayerImpl* layer)
448 {
449     if (!layer)
450         return 0;
451
452     if (layer->scrollable())
453         return layer;
454
455     for (size_t i = 0; i < layer->children().size(); ++i) {
456         CCLayerImpl* found = findScrollLayer(layer->children()[i].get());
457         if (found)
458             return found;
459     }
460
461     return 0;
462 }
463
464 void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
465 {
466     m_rootLayerImpl = layer;
467
468     // FIXME: Currently, this only finds the first scrollable layer.
469     m_scrollLayerImpl = findScrollLayer(m_rootLayerImpl.get());
470 }
471
472 void CCLayerTreeHostImpl::setVisible(bool visible)
473 {
474     if (m_visible == visible)
475         return;
476     m_visible = visible;
477
478     if (!m_layerRenderer)
479         return;
480
481     m_layerRenderer->setVisible(visible);
482
483     // Reset the damage tracker because the front/back buffers may have been damaged by the GPU
484     // process on visibility change.
485     if (visible && m_layerRenderer->capabilities().usingPartialSwap)
486         setFullRootLayerDamage();
487
488     const bool shouldTickInBackground = !visible && m_needsAnimateLayers;
489     m_timeSourceClientAdapter->setActive(shouldTickInBackground);
490 }
491
492 bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D> context)
493 {
494     OwnPtr<LayerRendererChromium> layerRenderer;
495     layerRenderer = LayerRendererChromium::create(this, context);
496
497     if (m_layerRenderer) {
498         m_layerRenderer->close();
499         sendDidLoseContextRecursive(m_rootLayerImpl.get());
500     }
501
502     m_layerRenderer = layerRenderer.release();
503
504     if (!m_visible && m_layerRenderer)
505          m_layerRenderer->setVisible(m_visible);
506
507     return m_layerRenderer;
508 }
509
510 void CCLayerTreeHostImpl::setViewportSize(const IntSize& viewportSize)
511 {
512     if (viewportSize == m_viewportSize)
513         return;
514
515     m_viewportSize = viewportSize;
516     updateMaxScrollPosition();
517
518     if (m_layerRenderer)
519         m_layerRenderer->viewportChanged();
520 }
521
522 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
523 {
524     if (!pageScale)
525         return;
526
527     if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
528         return;
529
530     m_minPageScale = minPageScale;
531     m_maxPageScale = maxPageScale;
532
533     float pageScaleChange = pageScale / m_pageScale;
534     m_pageScale = pageScale;
535
536     adjustScrollsForPageScaleChange(pageScaleChange);
537
538     // Clamp delta to limits and refresh display matrix.
539     setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
540     m_sentPageScaleDelta = 1;
541     applyPageScaleDeltaToScrollLayer();
542 }
543
544 void CCLayerTreeHostImpl::adjustScrollsForPageScaleChange(float pageScaleChange)
545 {
546     if (pageScaleChange == 1)
547         return;
548
549     // We also need to convert impl-side scroll deltas to pageScale space.
550     if (m_scrollLayerImpl) {
551         FloatSize scrollDelta = m_scrollLayerImpl->scrollDelta();
552         scrollDelta.scale(pageScaleChange);
553         m_scrollLayerImpl->setScrollDelta(scrollDelta);
554     }
555 }
556
557 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
558 {
559     // Clamp to the current min/max limits.
560     float finalMagnifyScale = m_pageScale * delta;
561     if (m_minPageScale && finalMagnifyScale < m_minPageScale)
562         delta = m_minPageScale / m_pageScale;
563     else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
564         delta = m_maxPageScale / m_pageScale;
565
566     if (delta == m_pageScaleDelta)
567         return;
568
569     m_pageScaleDelta = delta;
570
571     updateMaxScrollPosition();
572     applyPageScaleDeltaToScrollLayer();
573 }
574
575 void CCLayerTreeHostImpl::applyPageScaleDeltaToScrollLayer()
576 {
577     if (m_scrollLayerImpl)
578         m_scrollLayerImpl->setPageScaleDelta(m_pageScaleDelta);
579 }
580
581 void CCLayerTreeHostImpl::updateMaxScrollPosition()
582 {
583     if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size())
584         return;
585
586     FloatSize viewBounds = m_viewportSize;
587     if (CCLayerImpl* clipLayer = m_scrollLayerImpl->parent()) {
588         if (clipLayer->masksToBounds())
589             viewBounds = clipLayer->bounds();
590     }
591     viewBounds.scale(1 / m_pageScaleDelta);
592
593     IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
594     // The viewport may be larger than the contents in some cases, such as
595     // having a vertical scrollbar but no horizontal overflow.
596     maxScroll.clampNegativeToZero();
597
598     m_scrollLayerImpl->setMaxScrollPosition(maxScroll);
599
600     // TODO(aelias): Also update sublayers.
601 }
602
603 void CCLayerTreeHostImpl::setNeedsRedraw()
604 {
605     m_client->setNeedsRedrawOnImplThread();
606 }
607
608 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
609 {
610     // TODO: Check for scrollable sublayers.
611     if (!m_scrollLayerImpl || !m_scrollLayerImpl->scrollable()) {
612         TRACE_EVENT("scrollBegin Ignored no scrollable", this, 0);
613         return ScrollIgnored;
614     }
615
616     if (m_scrollLayerImpl->shouldScrollOnMainThread()) {
617         TRACE_EVENT("scrollBegin Failed shouldScrollOnMainThread", this, 0);
618         return ScrollFailed;
619     }
620
621     IntPoint scrollLayerContentPoint(m_scrollLayerImpl->screenSpaceTransform().inverse().mapPoint(viewportPoint));
622     if (m_scrollLayerImpl->nonFastScrollableRegion().contains(scrollLayerContentPoint)) {
623         TRACE_EVENT("scrollBegin Failed nonFastScrollableRegion", this, 0);
624         return ScrollFailed;
625     }
626
627     if (type == CCInputHandlerClient::Wheel && m_scrollLayerImpl->haveWheelEventHandlers()) {
628         TRACE_EVENT("scrollBegin Failed wheelEventHandlers", this, 0);
629         return ScrollFailed;
630     }
631
632     return ScrollStarted;
633 }
634
635 void CCLayerTreeHostImpl::scrollBy(const IntSize& scrollDelta)
636 {
637     TRACE_EVENT("CCLayerTreeHostImpl::scrollBy", this, 0);
638     if (!m_scrollLayerImpl)
639         return;
640
641     m_scrollLayerImpl->scrollBy(scrollDelta);
642     m_client->setNeedsCommitOnImplThread();
643     m_client->setNeedsRedrawOnImplThread();
644 }
645
646 void CCLayerTreeHostImpl::scrollEnd()
647 {
648 }
649
650 void CCLayerTreeHostImpl::pinchGestureBegin()
651 {
652     m_pinchGestureActive = true;
653     m_previousPinchAnchor = IntPoint();
654 }
655
656 void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
657                                              const IntPoint& anchor)
658 {
659     TRACE_EVENT("CCLayerTreeHostImpl::pinchGestureUpdate", this, 0);
660
661     if (!m_scrollLayerImpl)
662         return;
663
664     if (m_previousPinchAnchor == IntPoint::zero())
665         m_previousPinchAnchor = anchor;
666
667     // Keep the center-of-pinch anchor specified by (x, y) in a stable
668     // position over the course of the magnify.
669     FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta);
670     setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
671     FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
672     FloatSize move = previousScaleAnchor - newScaleAnchor;
673
674     m_previousPinchAnchor = anchor;
675
676     m_scrollLayerImpl->scrollBy(roundedIntSize(move));
677     m_client->setNeedsCommitOnImplThread();
678     m_client->setNeedsRedrawOnImplThread();
679 }
680
681 void CCLayerTreeHostImpl::pinchGestureEnd()
682 {
683     m_pinchGestureActive = false;
684
685     m_client->setNeedsCommitOnImplThread();
686 }
687
688 void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
689 {
690     float pageScale = m_pageScaleAnimation->finalPageScale();
691     IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
692     scrollOffset.scale(m_pageScale / pageScale);
693     makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
694 }
695
696 void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
697 {
698     if (!m_scrollLayerImpl)
699         return;
700
701     // Only send fake scroll/zoom deltas if we're pinch zooming out by a
702     // significant amount. This also ensures only one fake delta set will be
703     // sent.
704     const float pinchZoomOutSensitivity = 0.95;
705     if (m_pageScaleDelta > pinchZoomOutSensitivity)
706         return;
707
708     // Compute where the scroll offset/page scale would be if fully pinch-zoomed
709     // out from the anchor point.
710     IntSize scrollBegin = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
711     scrollBegin.scale(m_pageScaleDelta);
712     float scaleBegin = m_pageScale * m_pageScaleDelta;
713     float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
714     FloatSize scaledContentsSize = contentSize();
715     scaledContentsSize.scale(pageScaleDeltaToSend);
716
717     FloatSize anchor = toSize(m_previousPinchAnchor);
718     FloatSize scrollEnd = scrollBegin + anchor;
719     scrollEnd.scale(m_minPageScale / scaleBegin);
720     scrollEnd -= anchor;
721     scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_viewportSize)).expandedTo(FloatSize(0, 0));
722     scrollEnd.scale(1 / pageScaleDeltaToSend);
723
724     makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale);
725 }
726
727 void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
728 {
729     if (!m_scrollLayerImpl)
730         return;
731
732     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
733     scroll.layerId = m_scrollLayerImpl->id();
734     scroll.scrollDelta = scrollOffset - toSize(m_scrollLayerImpl->scrollPosition());
735     scrollInfo->scrolls.append(scroll);
736     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
737     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
738 }
739
740 PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
741 {
742     OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
743     bool didMove = m_scrollLayerImpl && (!m_scrollLayerImpl->scrollDelta().isZero() || m_pageScaleDelta != 1.0f);
744     if (!didMove || m_pinchGestureActive || m_pageScaleAnimation) {
745         m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
746         if (m_pinchGestureActive)
747             computePinchZoomDeltas(scrollInfo.get());
748         else if (m_pageScaleAnimation.get())
749             computeDoubleTapZoomDeltas(scrollInfo.get());
750         return scrollInfo.release();
751     }
752
753     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
754
755     // FIXME: track scrolls from layers other than the root
756     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
757     scroll.layerId = m_scrollLayerImpl->id();
758     scroll.scrollDelta = flooredIntSize(m_scrollLayerImpl->scrollDelta());
759     scrollInfo->scrolls.append(scroll);
760
761     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
762
763     return scrollInfo.release();
764 }
765
766 void CCLayerTreeHostImpl::setFullRootLayerDamage()
767 {
768     if (rootLayer()) {
769         CCRenderSurface* renderSurface = rootLayer()->renderSurface();
770         if (renderSurface)
771             renderSurface->damageTracker()->forceFullDamageNextUpdate();
772     }
773 }
774
775 void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
776 {
777     if (!m_pageScaleAnimation)
778         return;
779
780     IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
781
782     setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
783     IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
784     nextScroll.scale(1 / m_pageScaleDelta);
785     m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal);
786     m_client->setNeedsRedrawOnImplThread();
787
788     if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
789         m_pageScaleAnimation.clear();
790         m_client->setNeedsCommitOnImplThread();
791     }
792 }
793
794 void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
795 {
796     if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayerImpl)
797         return;
798
799     TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
800
801     OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
802
803     bool didAnimate = false;
804     animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
805
806     if (!events->isEmpty())
807         m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
808
809     if (didAnimate)
810         m_client->setNeedsRedrawOnImplThread();
811
812     const bool shouldTickInBackground = m_needsAnimateLayers && !m_visible;
813     m_timeSourceClientAdapter->setActive(shouldTickInBackground);
814 }
815
816 void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
817 {
818     if (!current)
819         return;
820
821     current->didLoseContext();
822     sendDidLoseContextRecursive(current->maskLayer());
823     sendDidLoseContextRecursive(current->replicaLayer());
824     for (size_t i = 0; i < current->children().size(); ++i)
825         sendDidLoseContextRecursive(current->children()[i].get());
826 }
827
828 void CCLayerTreeHostImpl::animateGestures(double monotonicTime)
829 {
830     if (!m_activeGestureAnimation)
831         return;
832
833     bool isContinuing = m_activeGestureAnimation->animate(monotonicTime);
834     if (isContinuing)
835         m_client->setNeedsRedrawOnImplThread();
836     else
837         m_activeGestureAnimation.clear();
838 }
839
840 } // namespace WebCore