[Chromium] Compositor doesn't support translucent root 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_hasTransparentBackground(false)
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, CCLayerList& willDrawLayers)
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             CCRenderPass* contributingRenderPass = surfacePassMap.get(it->renderSurface());
308             pass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker);
309         } else if (it.representsItself() && !occlusionTracker.occluded(*it, it->visibleLayerRect()) && !it->visibleLayerRect().isEmpty() && !it->scissorRect().isEmpty()) {
310             it->willDraw(m_layerRenderer.get(), context());
311             willDrawLayers.append(*it);
312
313             pass->appendQuadsForLayer(*it, &occlusionTracker, hadMissingTiles);
314         }
315
316         if (hadMissingTiles) {
317             bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
318             if (layerHasAnimatingTransform)
319                 drawFrame = false;
320         }
321
322         occlusionTracker.leaveLayer(it);
323     }
324
325     if (!m_hasTransparentBackground) {
326         passes.last()->setHasTransparentBackground(false);
327         passes.last()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
328     }
329
330     if (drawFrame)
331         occlusionTracker.overdrawMetrics().recordMetrics(this);
332     return drawFrame;
333 }
334
335 void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
336 {
337     bool subtreeNeedsAnimateLayers = false;
338
339     CCLayerAnimationController* currentController = current->layerAnimationController();
340
341     bool hadActiveAnimation = currentController->hasActiveAnimation();
342     currentController->animate(monotonicTime, events);
343     bool startedAnimation = events->size() > 0;
344
345     // We animated if we either ticked a running animation, or started a new animation.
346     if (hadActiveAnimation || startedAnimation)
347         didAnimate = true;
348
349     // If the current controller still has an active animation, we must continue animating layers.
350     if (currentController->hasActiveAnimation())
351          subtreeNeedsAnimateLayers = true;
352
353     for (size_t i = 0; i < current->children().size(); ++i) {
354         bool childNeedsAnimateLayers = false;
355         animateLayersRecursive(current->children()[i].get(), monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
356         if (childNeedsAnimateLayers)
357             subtreeNeedsAnimateLayers = true;
358     }
359
360     needsAnimateLayers = subtreeNeedsAnimateLayers;
361 }
362
363 void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
364 {
365     // Lazily create the timeSource adapter so that we can vary the interval for testing.
366     if (!m_timeSourceClientAdapter)
367         m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread()));
368
369     m_timeSourceClientAdapter->setActive(enabled);
370 }
371
372 IntSize CCLayerTreeHostImpl::contentSize() const
373 {
374     // TODO(aelias): Hardcoding the first child here is weird. Think of
375     // a cleaner way to get the contentBounds on the Impl side.
376     if (!m_scrollLayerImpl || m_scrollLayerImpl->children().isEmpty())
377         return IntSize();
378     return m_scrollLayerImpl->children()[0]->contentBounds();
379 }
380
381 bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
382 {
383     TRACE_EVENT("CCLayerTreeHostImpl::prepareToDraw", this, 0);
384     ASSERT(canDraw());
385
386     frame.renderPasses.clear();
387     frame.renderSurfaceLayerList.clear();
388     frame.willDrawLayers.clear();
389
390     if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList, frame.willDrawLayers))
391         return false;
392
393     // If we return true, then we expect drawLayers() to be called before this function is called again.
394     return true;
395 }
396
397 void CCLayerTreeHostImpl::setContentsMemoryAllocationLimitBytes(size_t bytes)
398 {
399     m_client->postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(bytes);
400 }
401
402 void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
403 {
404     TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
405     ASSERT(canDraw());
406     ASSERT(!frame.renderPasses.isEmpty());
407
408     // FIXME: use the frame begin time from the overall compositor scheduler.
409     // This value is currently inaccessible because it is up in Chromium's
410     // RenderWidget.
411
412     // The root RenderPass is the last one to be drawn.
413     CCRenderPass* rootRenderPass = frame.renderPasses.last().get();
414
415     m_fpsCounter->markBeginningOfFrame(currentTime());
416     m_layerRenderer->beginDrawingFrame(rootRenderPass);
417
418     for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
419         CCRenderPass* renderPass = frame.renderPasses[i].get();
420
421         FloatRect rootScissorRectInCurrentSurface = renderPass->targetSurface()->computeRootScissorRectInCurrentSurface(m_rootScissorRect);
422         m_layerRenderer->drawRenderPass(renderPass, rootScissorRectInCurrentSurface);
423     }
424
425     if (m_debugRectHistory->enabled(settings()))
426         m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), frame.renderSurfaceLayerList, settings());
427
428     if (m_headsUpDisplay->enabled(settings()))
429         m_headsUpDisplay->draw(this);
430
431     m_layerRenderer->finishDrawingFrame();
432
433     ++m_frameNumber;
434
435     // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
436     m_rootLayerImpl->resetAllChangeTrackingForSubtree();
437 }
438
439 void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
440 {
441     for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
442         frame.willDrawLayers[i]->didDraw();
443 }
444
445 void CCLayerTreeHostImpl::finishAllRendering()
446 {
447     if (m_layerRenderer)
448         m_layerRenderer->finish();
449 }
450
451 bool CCLayerTreeHostImpl::isContextLost()
452 {
453     return m_layerRenderer && m_layerRenderer->isContextLost();
454 }
455
456 const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities() const
457 {
458     return m_layerRenderer->capabilities();
459 }
460
461 TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
462 {
463     return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
464 }
465
466 bool CCLayerTreeHostImpl::swapBuffers()
467 {
468     ASSERT(m_layerRenderer);
469
470     m_fpsCounter->markEndOfFrame();
471     return m_layerRenderer->swapBuffers(enclosingIntRect(m_rootScissorRect));
472 }
473
474 void CCLayerTreeHostImpl::didLoseContext()
475 {
476     m_client->didLoseContextOnImplThread();
477 }
478
479 void CCLayerTreeHostImpl::onSwapBuffersComplete()
480 {
481     m_client->onSwapBuffersCompleteOnImplThread();
482 }
483
484 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
485 {
486     ASSERT(m_layerRenderer);
487     m_layerRenderer->getFramebufferPixels(pixels, rect);
488 }
489
490 static CCLayerImpl* findScrollLayer(CCLayerImpl* layer)
491 {
492     if (!layer)
493         return 0;
494
495     if (layer->scrollable())
496         return layer;
497
498     for (size_t i = 0; i < layer->children().size(); ++i) {
499         CCLayerImpl* found = findScrollLayer(layer->children()[i].get());
500         if (found)
501             return found;
502     }
503
504     return 0;
505 }
506
507 void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
508 {
509     m_rootLayerImpl = layer;
510
511     // FIXME: Currently, this only finds the first scrollable layer.
512     m_scrollLayerImpl = findScrollLayer(m_rootLayerImpl.get());
513 }
514
515 void CCLayerTreeHostImpl::setVisible(bool visible)
516 {
517     ASSERT(CCProxy::isImplThread());
518
519     if (m_visible == visible)
520         return;
521     m_visible = visible;
522     didVisibilityChange(this, m_visible);
523
524     if (!m_layerRenderer)
525         return;
526
527     m_layerRenderer->setVisible(visible);
528
529     setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
530 }
531
532 bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<CCGraphicsContext> context, TextureUploaderOption textureUploader)
533 {
534     GraphicsContext3D* context3d = context->context3D();
535     if (!context3d) {
536         // FIXME: Implement this path for software compositing.
537         return false;
538     }
539
540     OwnPtr<LayerRendererChromium> layerRenderer;
541     layerRenderer = LayerRendererChromium::create(this, context3d, textureUploader);
542
543     // Since we now have a new context/layerRenderer, we cannot continue to use the old
544     // resources (i.e. renderSurfaces and texture IDs).
545     if (m_rootLayerImpl) {
546         clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
547         sendDidLoseContextRecursive(m_rootLayerImpl.get());
548     }
549
550     m_layerRenderer = layerRenderer.release();
551     if (m_layerRenderer)
552         m_context = context;
553
554     if (!m_visible && m_layerRenderer)
555          m_layerRenderer->setVisible(m_visible);
556
557     return m_layerRenderer;
558 }
559
560 void CCLayerTreeHostImpl::setViewportSize(const IntSize& viewportSize)
561 {
562     if (viewportSize == m_viewportSize)
563         return;
564
565     m_viewportSize = viewportSize;
566
567     m_deviceViewportSize = viewportSize;
568     m_deviceViewportSize.scale(m_settings.deviceScaleFactor);
569
570     updateMaxScrollPosition();
571
572     if (m_layerRenderer)
573         m_layerRenderer->viewportChanged();
574 }
575
576 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
577 {
578     if (!pageScale)
579         return;
580
581     if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
582         return;
583
584     m_minPageScale = minPageScale;
585     m_maxPageScale = maxPageScale;
586
587     float pageScaleChange = pageScale / m_pageScale;
588     m_pageScale = pageScale;
589
590     adjustScrollsForPageScaleChange(pageScaleChange);
591
592     // Clamp delta to limits and refresh display matrix.
593     setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
594     m_sentPageScaleDelta = 1;
595     applyPageScaleDeltaToScrollLayer();
596 }
597
598 void CCLayerTreeHostImpl::adjustScrollsForPageScaleChange(float pageScaleChange)
599 {
600     if (pageScaleChange == 1)
601         return;
602
603     // We also need to convert impl-side scroll deltas to pageScale space.
604     if (m_scrollLayerImpl) {
605         FloatSize scrollDelta = m_scrollLayerImpl->scrollDelta();
606         scrollDelta.scale(pageScaleChange);
607         m_scrollLayerImpl->setScrollDelta(scrollDelta);
608     }
609 }
610
611 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
612 {
613     // Clamp to the current min/max limits.
614     float finalMagnifyScale = m_pageScale * delta;
615     if (m_minPageScale && finalMagnifyScale < m_minPageScale)
616         delta = m_minPageScale / m_pageScale;
617     else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
618         delta = m_maxPageScale / m_pageScale;
619
620     if (delta == m_pageScaleDelta)
621         return;
622
623     m_pageScaleDelta = delta;
624
625     updateMaxScrollPosition();
626     applyPageScaleDeltaToScrollLayer();
627 }
628
629 void CCLayerTreeHostImpl::applyPageScaleDeltaToScrollLayer()
630 {
631     if (m_scrollLayerImpl)
632         m_scrollLayerImpl->setPageScaleDelta(m_pageScaleDelta);
633 }
634
635 void CCLayerTreeHostImpl::updateMaxScrollPosition()
636 {
637     if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size())
638         return;
639
640     FloatSize viewBounds = m_viewportSize;
641     if (CCLayerImpl* clipLayer = m_scrollLayerImpl->parent()) {
642         if (clipLayer->masksToBounds())
643             viewBounds = clipLayer->bounds();
644     }
645     viewBounds.scale(1 / m_pageScaleDelta);
646     viewBounds.scale(m_settings.deviceScaleFactor);
647
648     // maxScroll is computed in physical pixels, but scroll positions are in layout pixels.
649     IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
650     maxScroll.scale(1 / m_settings.deviceScaleFactor);
651     // The viewport may be larger than the contents in some cases, such as
652     // having a vertical scrollbar but no horizontal overflow.
653     maxScroll.clampNegativeToZero();
654
655     m_scrollLayerImpl->setMaxScrollPosition(maxScroll);
656
657     // TODO(aelias): Also update sublayers.
658 }
659
660 void CCLayerTreeHostImpl::setNeedsRedraw()
661 {
662     m_client->setNeedsRedrawOnImplThread();
663 }
664
665 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
666 {
667     // TODO: Check for scrollable sublayers.
668     if (!m_scrollLayerImpl || !m_scrollLayerImpl->scrollable()) {
669         TRACE_EVENT("scrollBegin Ignored no scrollable", this, 0);
670         return ScrollIgnored;
671     }
672
673     if (m_scrollLayerImpl->shouldScrollOnMainThread()) {
674         TRACE_EVENT("scrollBegin Failed shouldScrollOnMainThread", this, 0);
675         return ScrollFailed;
676     }
677
678     IntPoint deviceViewportPoint = viewportPoint;
679     deviceViewportPoint.scale(m_settings.deviceScaleFactor, m_settings.deviceScaleFactor);
680
681     // The inverse of the screen space transform takes us from physical pixels to layout pixels.
682     IntPoint scrollLayerPoint(m_scrollLayerImpl->screenSpaceTransform().inverse().mapPoint(deviceViewportPoint));
683
684     if (m_scrollLayerImpl->nonFastScrollableRegion().contains(scrollLayerPoint)) {
685         TRACE_EVENT("scrollBegin Failed nonFastScrollableRegion", this, 0);
686         return ScrollFailed;
687     }
688
689     if (type == CCInputHandlerClient::Wheel && m_scrollLayerImpl->haveWheelEventHandlers()) {
690         TRACE_EVENT("scrollBegin Failed wheelEventHandlers", this, 0);
691         return ScrollFailed;
692     }
693
694     return ScrollStarted;
695 }
696
697 void CCLayerTreeHostImpl::scrollBy(const IntSize& scrollDelta)
698 {
699     TRACE_EVENT("CCLayerTreeHostImpl::scrollBy", this, 0);
700     if (!m_scrollLayerImpl)
701         return;
702
703     m_scrollLayerImpl->scrollBy(scrollDelta);
704     m_client->setNeedsCommitOnImplThread();
705     m_client->setNeedsRedrawOnImplThread();
706 }
707
708 void CCLayerTreeHostImpl::scrollEnd()
709 {
710 }
711
712 void CCLayerTreeHostImpl::pinchGestureBegin()
713 {
714     m_pinchGestureActive = true;
715     m_previousPinchAnchor = IntPoint();
716 }
717
718 void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
719                                              const IntPoint& anchor)
720 {
721     TRACE_EVENT("CCLayerTreeHostImpl::pinchGestureUpdate", this, 0);
722
723     if (!m_scrollLayerImpl)
724         return;
725
726     if (m_previousPinchAnchor == IntPoint::zero())
727         m_previousPinchAnchor = anchor;
728
729     // Keep the center-of-pinch anchor specified by (x, y) in a stable
730     // position over the course of the magnify.
731     FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta);
732     setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
733     FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
734     FloatSize move = previousScaleAnchor - newScaleAnchor;
735
736     m_previousPinchAnchor = anchor;
737
738     m_scrollLayerImpl->scrollBy(roundedIntSize(move));
739     m_client->setNeedsCommitOnImplThread();
740     m_client->setNeedsRedrawOnImplThread();
741 }
742
743 void CCLayerTreeHostImpl::pinchGestureEnd()
744 {
745     m_pinchGestureActive = false;
746
747     m_client->setNeedsCommitOnImplThread();
748 }
749
750 void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
751 {
752     float pageScale = m_pageScaleAnimation->finalPageScale();
753     IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
754     scrollOffset.scale(m_pageScale / pageScale);
755     makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
756 }
757
758 void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
759 {
760     if (!m_scrollLayerImpl)
761         return;
762
763     // Only send fake scroll/zoom deltas if we're pinch zooming out by a
764     // significant amount. This also ensures only one fake delta set will be
765     // sent.
766     const float pinchZoomOutSensitivity = 0.95;
767     if (m_pageScaleDelta > pinchZoomOutSensitivity)
768         return;
769
770     // Compute where the scroll offset/page scale would be if fully pinch-zoomed
771     // out from the anchor point.
772     IntSize scrollBegin = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
773     scrollBegin.scale(m_pageScaleDelta);
774     float scaleBegin = m_pageScale * m_pageScaleDelta;
775     float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
776     FloatSize scaledContentsSize = contentSize();
777     scaledContentsSize.scale(pageScaleDeltaToSend);
778
779     FloatSize anchor = toSize(m_previousPinchAnchor);
780     FloatSize scrollEnd = scrollBegin + anchor;
781     scrollEnd.scale(m_minPageScale / scaleBegin);
782     scrollEnd -= anchor;
783     scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0));
784     scrollEnd.scale(1 / pageScaleDeltaToSend);
785     scrollEnd.scale(m_settings.deviceScaleFactor);
786
787     makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale);
788 }
789
790 void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
791 {
792     if (!m_scrollLayerImpl)
793         return;
794
795     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
796     scroll.layerId = m_scrollLayerImpl->id();
797     scroll.scrollDelta = scrollOffset - toSize(m_scrollLayerImpl->scrollPosition());
798     scrollInfo->scrolls.append(scroll);
799     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
800     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
801 }
802
803 PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
804 {
805     OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
806     bool didMove = m_scrollLayerImpl && (!m_scrollLayerImpl->scrollDelta().isZero() || m_pageScaleDelta != 1.0f);
807     if (!didMove || m_pinchGestureActive || m_pageScaleAnimation) {
808         m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
809         if (m_pinchGestureActive)
810             computePinchZoomDeltas(scrollInfo.get());
811         else if (m_pageScaleAnimation.get())
812             computeDoubleTapZoomDeltas(scrollInfo.get());
813         return scrollInfo.release();
814     }
815
816     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
817
818     // FIXME: track scrolls from layers other than the root
819     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
820     scroll.layerId = m_scrollLayerImpl->id();
821     scroll.scrollDelta = flooredIntSize(m_scrollLayerImpl->scrollDelta());
822     scrollInfo->scrolls.append(scroll);
823
824     m_scrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
825
826     return scrollInfo.release();
827 }
828
829 void CCLayerTreeHostImpl::setFullRootLayerDamage()
830 {
831     if (m_rootLayerImpl) {
832         CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
833         if (renderSurface)
834             renderSurface->damageTracker()->forceFullDamageNextUpdate();
835     }
836 }
837
838 void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
839 {
840     if (!m_pageScaleAnimation || !m_scrollLayerImpl)
841         return;
842
843     IntSize scrollTotal = flooredIntSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
844
845     setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
846     IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
847     nextScroll.scale(1 / m_pageScaleDelta);
848     m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal);
849     m_client->setNeedsRedrawOnImplThread();
850
851     if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
852         m_pageScaleAnimation.clear();
853         m_client->setNeedsCommitOnImplThread();
854     }
855 }
856
857 void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
858 {
859     if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayerImpl)
860         return;
861
862     TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
863
864     OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
865
866     bool didAnimate = false;
867     animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
868
869     if (!events->isEmpty())
870         m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
871
872     if (didAnimate)
873         m_client->setNeedsRedrawOnImplThread();
874
875     setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
876 }
877
878 double CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
879 {
880     return 1;
881 }
882
883 void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
884 {
885     ASSERT(current);
886     current->didLoseContext();
887     if (current->maskLayer())
888         sendDidLoseContextRecursive(current->maskLayer());
889     if (current->replicaLayer())
890         sendDidLoseContextRecursive(current->replicaLayer());
891     for (size_t i = 0; i < current->children().size(); ++i)
892         sendDidLoseContextRecursive(current->children()[i].get());
893 }
894
895 void CCLayerTreeHostImpl::clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
896 {
897     ASSERT(current);
898     for (size_t i = 0; i < current->children().size(); ++i)
899         clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i].get());
900     current->clearRenderSurface();
901 }
902
903 String CCLayerTreeHostImpl::layerTreeAsText() const
904 {
905     TextStream ts;
906     if (m_rootLayerImpl) {
907         ts << m_rootLayerImpl->layerTreeAsText();
908         ts << "RenderSurfaces:\n";
909         dumpRenderSurfaces(ts, 1, m_rootLayerImpl.get());
910     }
911     return ts.release();
912 }
913
914 void CCLayerTreeHostImpl::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
915 {
916     m_headsUpDisplay->setFontAtlas(fontAtlas);
917 }
918
919 void CCLayerTreeHostImpl::dumpRenderSurfaces(TextStream& ts, int indent, const CCLayerImpl* layer) const
920 {
921     if (layer->renderSurface())
922         layer->renderSurface()->dumpSurface(ts, indent);
923
924     for (size_t i = 0; i < layer->children().size(); ++i)
925         dumpRenderSurfaces(ts, indent, layer->children()[i].get());
926 }
927
928
929 void CCLayerTreeHostImpl::animateGestures(double monotonicTime)
930 {
931     if (!m_activeGestureAnimation)
932         return;
933
934     bool isContinuing = m_activeGestureAnimation->animate(monotonicTime);
935     if (isContinuing)
936         m_client->setNeedsRedrawOnImplThread();
937     else
938         m_activeGestureAnimation.clear();
939 }
940
941 } // namespace WebCore