0abfae188db9fe23e7e3335564f3032eb59569ae
[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 void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
224 {
225     TRACE_EVENT1("webkit", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(renderSurfaceLayerList.size()));
226
227     renderSurfaceLayerList.append(rootLayer());
228
229     if (!rootLayer()->renderSurface())
230         rootLayer()->createRenderSurface();
231     rootLayer()->renderSurface()->clearLayerList();
232     rootLayer()->renderSurface()->setContentRect(IntRect(IntPoint(), viewportSize()));
233
234     rootLayer()->setClipRect(IntRect(IntPoint(), viewportSize()));
235
236     {
237         TransformationMatrix identityMatrix;
238         TRACE_EVENT("CCLayerTreeHostImpl::calcDrawEtc", this, 0);
239         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer(), rootLayer(), identityMatrix, identityMatrix, renderSurfaceLayerList, rootLayer()->renderSurface()->layerList(), &m_layerSorter, layerRendererCapabilities().maxTextureSize);
240     }
241
242     if (layerRendererCapabilities().usingPartialSwap)
243         trackDamageForAllSurfaces(rootLayer(), renderSurfaceLayerList);
244     m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect();
245
246     // Create the render passes in dependency order.
247     HashMap<CCRenderSurface*, CCRenderPass*> surfacePassMap;
248     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
249         CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
250         CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
251
252         OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface);
253
254         FloatRect surfaceDamageRect;
255         if (layerRendererCapabilities().usingPartialSwap)
256             surfaceDamageRect = damageInSurfaceSpace(renderSurfaceLayer, m_rootDamageRect);
257         pass->setSurfaceDamageRect(surfaceDamageRect);
258
259         surfacePassMap.add(renderSurface, pass.get());
260         passes.append(pass.release());
261     }
262
263     IntRect scissorRect;
264     if (layerRendererCapabilities().usingPartialSwap)
265         scissorRect = enclosingIntRect(m_rootDamageRect);
266     else
267         scissorRect = IntRect(IntPoint(), viewportSize());
268
269     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
270     CCOcclusionTrackerImpl occlusionTracker(scissorRect, recordMetricsForFrame);
271
272     // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
273     typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
274
275     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
276     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
277         CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSurface();
278
279         if (it.representsItself())
280             occlusionTracker.enterTargetRenderSurface(renderSurface);
281         else if (it.representsTargetRenderSurface())
282             occlusionTracker.finishedTargetRenderSurface(*it, renderSurface);
283         else
284             occlusionTracker.leaveToTargetRenderSurface(renderSurface);
285
286         if (it.representsTargetRenderSurface())
287             continue;
288         if (it->visibleLayerRect().isEmpty())
289             continue;
290
291         CCRenderPass* pass = surfacePassMap.get(renderSurface);
292         if (it.representsContributingRenderSurface()) {
293             pass->appendQuadsForRenderSurfaceLayer(*it);
294             continue;
295         }
296
297         it->willDraw(m_layerRenderer.get());
298         pass->appendQuadsForLayer(*it, &occlusionTracker);
299         occlusionTracker.markOccludedBehindLayer(*it);
300     }
301
302     occlusionTracker.overdrawMetrics().recordMetrics(this);
303 }
304
305 void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
306 {
307     bool subtreeNeedsAnimateLayers = false;
308
309     CCLayerAnimationController* currentController = current->layerAnimationController();
310
311     bool hadActiveAnimation = currentController->hasActiveAnimation();
312     currentController->animate(monotonicTime, events);
313     bool startedAnimation = events->size() > 0;
314
315     // We animated if we either ticked a running animation, or started a new animation.
316     if (hadActiveAnimation || startedAnimation)
317         didAnimate = true;
318
319     // If the current controller still has an active animation, we must continue animating layers.
320     if (currentController->hasActiveAnimation())
321          subtreeNeedsAnimateLayers = true;
322
323     for (size_t i = 0; i < current->children().size(); ++i) {
324         bool childNeedsAnimateLayers = false;
325         animateLayersRecursive(current->children()[i].get(), monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
326         if (childNeedsAnimateLayers)
327             subtreeNeedsAnimateLayers = true;
328     }
329
330     needsAnimateLayers = subtreeNeedsAnimateLayers;
331 }
332
333 IntSize CCLayerTreeHostImpl::contentSize() const
334 {
335     // TODO(aelias): Hardcoding the first child here is weird. Think of
336     // a cleaner way to get the contentBounds on the Impl side.
337     if (!m_scrollLayerImpl || m_scrollLayerImpl->children().isEmpty())
338         return IntSize();
339     return m_scrollLayerImpl->children()[0]->contentBounds();
340 }
341
342 void CCLayerTreeHostImpl::drawLayers()
343 {
344     TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
345     ASSERT(m_layerRenderer);
346
347     if (!rootLayer())
348         return;
349
350     CCRenderPassList passes;
351     CCLayerList renderSurfaceLayerList;
352     calculateRenderPasses(passes, renderSurfaceLayerList);
353
354     m_layerRenderer->beginDrawingFrame();
355     for (size_t i = 0; i < passes.size(); ++i)
356         m_layerRenderer->drawRenderPass(passes[i].get());
357
358     typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
359
360     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
361     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
362         if (it.representsItself() && !it->visibleLayerRect().isEmpty())
363             it->didDraw();
364     }
365     m_layerRenderer->finishDrawingFrame();
366
367     ++m_frameNumber;
368
369     // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
370     rootLayer()->resetAllChangeTrackingForSubtree();
371 }
372
373 void CCLayerTreeHostImpl::finishAllRendering()
374 {
375     if (m_layerRenderer)
376         m_layerRenderer->finish();
377 }
378
379 bool CCLayerTreeHostImpl::isContextLost()
380 {
381     return m_layerRenderer && m_layerRenderer->isContextLost();
382 }
383
384 const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities() const
385 {
386     return m_layerRenderer->capabilities();
387 }
388
389 TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
390 {
391     return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
392 }
393
394 void CCLayerTreeHostImpl::swapBuffers()
395 {
396     ASSERT(m_layerRenderer);
397     m_layerRenderer->swapBuffers(enclosingIntRect(m_rootDamageRect));
398 }
399
400 void CCLayerTreeHostImpl::didLoseContext()
401 {
402     m_client->didLoseContextOnImplThread();
403 }
404
405 void CCLayerTreeHostImpl::onSwapBuffersComplete()
406 {
407     m_client->onSwapBuffersCompleteOnImplThread();
408 }
409
410 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
411 {
412     ASSERT(m_layerRenderer);
413     m_layerRenderer->getFramebufferPixels(pixels, rect);
414 }
415
416 static CCLayerImpl* findScrollLayer(CCLayerImpl* layer)
417 {
418     if (!layer)
419         return 0;
420
421     if (layer->scrollable())
422         return layer;
423
424     for (size_t i = 0; i < layer->children().size(); ++i) {
425         CCLayerImpl* found = findScrollLayer(layer->children()[i].get());
426         if (found)
427             return found;
428     }
429
430     return 0;
431 }
432
433 void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
434 {
435     m_rootLayerImpl = layer;
436
437     // FIXME: Currently, this only finds the first scrollable layer.
438     m_scrollLayerImpl = findScrollLayer(m_rootLayerImpl.get());
439 }
440
441 void CCLayerTreeHostImpl::setVisible(bool visible)
442 {
443     if (m_visible == visible)
444         return;
445     m_visible = visible;
446
447     if (!m_layerRenderer)
448         return;
449
450     m_layerRenderer->setVisible(visible);
451
452     // Reset the damage tracker because the front/back buffers may have been damaged by the GPU
453     // process on visibility change.
454     if (visible && m_layerRenderer->capabilities().usingPartialSwap)
455         setFullRootLayerDamage();
456
457     const bool shouldTickInBackground = !visible && m_needsAnimateLayers;
458     m_timeSourceClientAdapter->setActive(shouldTickInBackground);
459 }
460
461 bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D> context)
462 {
463     OwnPtr<LayerRendererChromium> layerRenderer;
464     layerRenderer = LayerRendererChromium::create(this, context);
465
466     if (m_layerRenderer) {
467         m_layerRenderer->close();
468         sendDidLoseContextRecursive(m_rootLayerImpl.get());
469     }
470
471     m_layerRenderer = layerRenderer.release();
472
473     if (!m_visible && m_layerRenderer)
474          m_layerRenderer->setVisible(m_visible);
475
476     return m_layerRenderer;
477 }
478
479 void CCLayerTreeHostImpl::setViewportSize(const IntSize& viewportSize)
480 {
481     if (viewportSize == m_viewportSize)
482         return;
483
484     m_viewportSize = viewportSize;
485     updateMaxScrollPosition();
486
487     if (m_layerRenderer)
488         m_layerRenderer->viewportChanged();
489 }
490
491 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
492 {
493     if (!pageScale)
494         return;
495
496     if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
497         return;
498
499     m_minPageScale = minPageScale;
500     m_maxPageScale = maxPageScale;
501
502     float pageScaleChange = pageScale / m_pageScale;
503     m_pageScale = pageScale;
504
505     adjustScrollsForPageScaleChange(pageScaleChange);
506
507     // Clamp delta to limits and refresh display matrix.
508     setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
509     m_sentPageScaleDelta = 1;
510     applyPageScaleDeltaToScrollLayer();
511 }
512
513 void CCLayerTreeHostImpl::adjustScrollsForPageScaleChange(float pageScaleChange)
514 {
515     if (pageScaleChange == 1)
516         return;
517
518     // We also need to convert impl-side scroll deltas to pageScale space.
519     if (m_scrollLayerImpl) {
520         FloatSize scrollDelta = m_scrollLayerImpl->scrollDelta();
521         scrollDelta.scale(pageScaleChange);
522         m_scrollLayerImpl->setScrollDelta(scrollDelta);
523     }
524 }
525
526 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
527 {
528     // Clamp to the current min/max limits.
529     float finalMagnifyScale = m_pageScale * delta;
530     if (m_minPageScale && finalMagnifyScale < m_minPageScale)
531         delta = m_minPageScale / m_pageScale;
532     else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
533         delta = m_maxPageScale / m_pageScale;
534
535     if (delta == m_pageScaleDelta)
536         return;
537
538     m_pageScaleDelta = delta;
539
540     updateMaxScrollPosition();
541     applyPageScaleDeltaToScrollLayer();
542 }
543
544 void CCLayerTreeHostImpl::applyPageScaleDeltaToScrollLayer()
545 {
546     if (m_scrollLayerImpl)
547         m_scrollLayerImpl->setPageScaleDelta(m_pageScaleDelta);
548 }
549
550 void CCLayerTreeHostImpl::updateMaxScrollPosition()
551 {
552     if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size())
553         return;
554
555     FloatSize viewBounds = m_viewportSize;
556     if (CCLayerImpl* clipLayer = m_scrollLayerImpl->parent()) {
557         if (clipLayer->masksToBounds())
558             viewBounds = clipLayer->bounds();
559     }
560     viewBounds.scale(1 / m_pageScaleDelta);
561
562     IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
563     // The viewport may be larger than the contents in some cases, such as
564     // having a vertical scrollbar but no horizontal overflow.
565     maxScroll.clampNegativeToZero();
566
567     m_scrollLayerImpl->setMaxScrollPosition(maxScroll);
568
569     // TODO(aelias): Also update sublayers.
570 }
571
572 void CCLayerTreeHostImpl::setNeedsRedraw()
573 {
574     m_client->setNeedsRedrawOnImplThread();
575 }
576
577 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
578 {
579     // TODO: Check for scrollable sublayers.
580     if (!m_scrollLayerImpl || !m_scrollLayerImpl->scrollable()) {
581         TRACE_EVENT("scrollBegin Ignored no scrollable", this, 0);
582         return ScrollIgnored;
583     }
584
585     if (m_scrollLayerImpl->shouldScrollOnMainThread()) {
586         TRACE_EVENT("scrollBegin Failed shouldScrollOnMainThread", this, 0);
587         return ScrollFailed;
588     }
589
590     IntPoint scrollLayerContentPoint(m_scrollLayerImpl->screenSpaceTransform().inverse().mapPoint(viewportPoint));
591     if (m_scrollLayerImpl->nonFastScrollableRegion().contains(scrollLayerContentPoint)) {
592         TRACE_EVENT("scrollBegin Failed nonFastScrollableRegion", this, 0);
593         return ScrollFailed;
594     }
595
596     if (type == CCInputHandlerClient::Wheel && m_scrollLayerImpl->haveWheelEventHandlers()) {
597         TRACE_EVENT("scrollBegin Failed wheelEventHandlers", this, 0);
598         return ScrollFailed;
599     }
600
601     return ScrollStarted;
602 }
603
604 void CCLayerTreeHostImpl::scrollBy(const IntSize& scrollDelta)
605 {
606     TRACE_EVENT("CCLayerTreeHostImpl::scrollBy", this, 0);
607     if (!m_scrollLayerImpl)
608         return;
609
610     m_scrollLayerImpl->scrollBy(scrollDelta);
611     m_client->setNeedsCommitOnImplThread();
612     m_client->setNeedsRedrawOnImplThread();
613 }
614
615 void CCLayerTreeHostImpl::scrollEnd()
616 {
617 }
618
619 void CCLayerTreeHostImpl::pinchGestureBegin()
620 {
621     m_pinchGestureActive = true;
622     m_previousPinchAnchor = IntPoint();
623 }
624
625 void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
626                                              const IntPoint& anchor)
627 {
628     TRACE_EVENT("CCLayerTreeHostImpl::pinchGestureUpdate", this, 0);
629
630     if (!m_scrollLayerImpl)
631         return;
632
633     if (m_previousPinchAnchor == IntPoint::zero())
634         m_previousPinchAnchor = anchor;
635
636     // Keep the center-of-pinch anchor specified by (x, y) in a stable
637     // position over the course of the magnify.
638     FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta);
639     setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
640     FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
641     FloatSize move = previousScaleAnchor - newScaleAnchor;
642
643     m_previousPinchAnchor = anchor;
644
645     m_scrollLayerImpl->scrollBy(roundedIntSize(move));
646     m_client->setNeedsCommitOnImplThread();
647     m_client->setNeedsRedrawOnImplThread();
648 }
649
650 void CCLayerTreeHostImpl::pinchGestureEnd()
651 {
652     m_pinchGestureActive = false;
653
654     m_client->setNeedsCommitOnImplThread();
655 }
656
657 void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
658 {
659     float pageScale = m_pageScaleAnimation->finalPageScale();
660     IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
661     scrollOffset.scale(m_pageScale / pageScale);
662     makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
663 }
664
665 void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
666 {
667     if (!m_scrollLayerImpl)
668         return;
669
670     // Only send fake scroll/zoom deltas if we're pinch zooming out by a
671     // significant amount. This also ensures only one fake delta set will be
672     // sent.
673     const float pinchZoomOutSensitivity = 0.95;
674     if (m_pageScaleDelta > pinchZoomOutSensitivity)
675         return;
676
677     // Compute where the scroll offset/page scale would be if fully pinch-zoomed
678     // out from the anchor point.
679     IntSize scrollBegin = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
680     scrollBegin.scale(m_pageScaleDelta);
681     float scaleBegin = m_pageScale * m_pageScaleDelta;
682     float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
683     FloatSize scaledContentsSize = contentSize();
684     scaledContentsSize.scale(pageScaleDeltaToSend);
685
686     FloatSize anchor = toSize(m_previousPinchAnchor);
687     FloatSize scrollEnd = scrollBegin + anchor;
688     scrollEnd.scale(m_minPageScale / scaleBegin);
689     scrollEnd -= anchor;
690     scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_viewportSize)).expandedTo(FloatSize(0, 0));
691     scrollEnd.scale(1 / pageScaleDeltaToSend);
692
693     makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale);
694 }
695
696 void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
697 {
698     if (!m_scrollLayerImpl)
699         return;
700
701     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
702     scroll.layerId = m_scrollLayerImpl->id();
703     scroll.scrollDelta = scrollOffset - toSize(m_scrollLayerImpl->scrollPosition());
704     scrollInfo->scrolls.append(scroll);
705     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
706     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
707 }
708
709 PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
710 {
711     OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
712     bool didMove = m_scrollLayerImpl && (!m_scrollLayerImpl->scrollDelta().isZero() || m_pageScaleDelta != 1.0f);
713     if (!didMove || m_pinchGestureActive || m_pageScaleAnimation) {
714         m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
715         if (m_pinchGestureActive)
716             computePinchZoomDeltas(scrollInfo.get());
717         else if (m_pageScaleAnimation.get())
718             computeDoubleTapZoomDeltas(scrollInfo.get());
719         return scrollInfo.release();
720     }
721
722     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
723
724     // FIXME: track scrolls from layers other than the root
725     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
726     scroll.layerId = m_scrollLayerImpl->id();
727     scroll.scrollDelta = flooredIntSize(m_scrollLayerImpl->scrollDelta());
728     scrollInfo->scrolls.append(scroll);
729
730     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
731
732     return scrollInfo.release();
733 }
734
735 void CCLayerTreeHostImpl::setFullRootLayerDamage()
736 {
737     if (rootLayer()) {
738         CCRenderSurface* renderSurface = rootLayer()->renderSurface();
739         if (renderSurface)
740             renderSurface->damageTracker()->forceFullDamageNextUpdate();
741     }
742 }
743
744 void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
745 {
746     if (!m_pageScaleAnimation)
747         return;
748
749     IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
750
751     setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
752     IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
753     nextScroll.scale(1 / m_pageScaleDelta);
754     m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal);
755     m_client->setNeedsRedrawOnImplThread();
756
757     if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
758         m_pageScaleAnimation.clear();
759         m_client->setNeedsCommitOnImplThread();
760     }
761 }
762
763 void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
764 {
765     if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayerImpl)
766         return;
767
768     TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
769
770     OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
771
772     bool didAnimate = false;
773     animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
774
775     if (!events->isEmpty())
776         m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
777
778     if (didAnimate)
779         m_client->setNeedsRedrawOnImplThread();
780
781     const bool shouldTickInBackground = m_needsAnimateLayers && !m_visible;
782     m_timeSourceClientAdapter->setActive(shouldTickInBackground);
783 }
784
785 void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
786 {
787     if (!current)
788         return;
789
790     current->didLoseContext();
791     sendDidLoseContextRecursive(current->maskLayer());
792     sendDidLoseContextRecursive(current->replicaLayer());
793     for (size_t i = 0; i < current->children().size(); ++i)
794         sendDidLoseContextRecursive(current->children()[i].get());
795 }
796
797 void CCLayerTreeHostImpl::animateGestures(double monotonicTime)
798 {
799     if (!m_activeGestureAnimation)
800         return;
801
802     bool isContinuing = m_activeGestureAnimation->animate(monotonicTime);
803     if (isContinuing)
804         m_client->setNeedsRedrawOnImplThread();
805     else
806         m_activeGestureAnimation.clear();
807 }
808
809 } // namespace WebCore