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