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