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