bb6c06462b45100b4487f767b7eea6710337cac4
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCLayerTreeHost.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/CCLayerTreeHost.h"
28
29 #include "LayerChromium.h"
30 #include "ManagedTexture.h"
31 #include "Region.h"
32 #include "TraceEvent.h"
33 #include "TreeSynchronizer.h"
34 #include "cc/CCFontAtlas.h"
35 #include "cc/CCGraphicsContext.h"
36 #include "cc/CCLayerAnimationController.h"
37 #include "cc/CCLayerIterator.h"
38 #include "cc/CCLayerTreeHostCommon.h"
39 #include "cc/CCLayerTreeHostImpl.h"
40 #include "cc/CCOcclusionTracker.h"
41 #include "cc/CCOverdrawMetrics.h"
42 #include "cc/CCSettings.h"
43 #include "cc/CCSingleThreadProxy.h"
44 #include "cc/CCThreadProxy.h"
45
46 using namespace std;
47 using WebKit::WebTransformationMatrix;
48
49 namespace {
50 static int numLayerTreeInstances;
51 }
52
53 namespace WebCore {
54
55 bool CCLayerTreeHost::s_needsFilterContext = false;
56
57 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
58 {
59     return numLayerTreeInstances > 0;
60 }
61
62 PassOwnPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings)
63 {
64     OwnPtr<CCLayerTreeHost> layerTreeHost = adoptPtr(new CCLayerTreeHost(client, settings));
65     if (!layerTreeHost->initialize())
66         return nullptr;
67     return layerTreeHost.release();
68 }
69
70 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings)
71     : m_compositorIdentifier(-1)
72     , m_animating(false)
73     , m_needsAnimateLayers(false)
74     , m_client(client)
75     , m_frameNumber(0)
76     , m_frameIsForDisplay(false)
77     , m_layerRendererInitialized(false)
78     , m_contextLost(false)
79     , m_numTimesRecreateShouldFail(0)
80     , m_numFailedRecreateAttempts(0)
81     , m_settings(settings)
82     , m_deviceScaleFactor(1)
83     , m_visible(true)
84     , m_memoryAllocationBytes(0)
85     , m_memoryAllocationIsForDisplay(false)
86     , m_pageScaleFactor(1)
87     , m_minPageScaleFactor(1)
88     , m_maxPageScaleFactor(1)
89     , m_triggerIdlePaints(true)
90     , m_backgroundColor(Color::white)
91     , m_hasTransparentBackground(false)
92     , m_partialTextureUpdateRequests(0)
93 {
94     ASSERT(CCProxy::isMainThread());
95     numLayerTreeInstances++;
96 }
97
98 bool CCLayerTreeHost::initialize()
99 {
100     TRACE_EVENT("CCLayerTreeHost::initialize", this, 0);
101
102     if (CCProxy::hasImplThread())
103         m_proxy = CCThreadProxy::create(this);
104     else
105         m_proxy = CCSingleThreadProxy::create(this);
106     m_proxy->start();
107
108     if (!m_proxy->initializeContext())
109         return false;
110
111     // Only allocate the font atlas if we have reason to use the heads-up display.
112     if (m_settings.showFPSCounter || m_settings.showPlatformLayerTree) {
113         TRACE_EVENT0("cc", "CCLayerTreeHost::initialize::initializeFontAtlas");
114         OwnPtr<CCFontAtlas> fontAtlas(CCFontAtlas::create());
115         fontAtlas->initialize();
116         m_proxy->setFontAtlas(fontAtlas.release());
117     }
118
119     m_compositorIdentifier = m_proxy->compositorIdentifier();
120     return true;
121 }
122
123 CCLayerTreeHost::~CCLayerTreeHost()
124 {
125     ASSERT(CCProxy::isMainThread());
126     TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0);
127     ASSERT(m_proxy);
128     m_proxy->stop();
129     m_proxy.clear();
130     numLayerTreeInstances--;
131 }
132
133 void CCLayerTreeHost::setSurfaceReady()
134 {
135     m_proxy->setSurfaceReady();
136 }
137
138 void CCLayerTreeHost::initializeLayerRenderer()
139 {
140     TRACE_EVENT("CCLayerTreeHost::initializeLayerRenderer", this, 0);
141     if (!m_proxy->initializeLayerRenderer()) {
142         // Uh oh, better tell the client that we can't do anything with this context.
143         m_client->didRecreateContext(false);
144         return;
145     }
146
147     // Update m_settings based on capabilities that we got back from the renderer.
148     m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
149
150     // Update m_settings based on partial update capability.
151     m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates());
152
153     m_contentsTextureManager = TextureManager::create(0, 0, m_proxy->layerRendererCapabilities().maxTextureSize);
154
155     // FIXME: This is the same as setContentsMemoryAllocationLimitBytes, but
156     // we're in the middle of a commit here and don't want to force another.
157     m_memoryAllocationBytes = TextureManager::highLimitBytes(deviceViewportSize());
158     m_memoryAllocationIsForDisplay = true;
159
160     m_layerRendererInitialized = true;
161
162     m_settings.defaultTileSize = IntSize(min(m_settings.defaultTileSize.width(), m_proxy->layerRendererCapabilities().maxTextureSize),
163                                          min(m_settings.defaultTileSize.height(), m_proxy->layerRendererCapabilities().maxTextureSize));
164     m_settings.maxUntiledLayerSize = IntSize(min(m_settings.maxUntiledLayerSize.width(), m_proxy->layerRendererCapabilities().maxTextureSize),
165                                              min(m_settings.maxUntiledLayerSize.height(), m_proxy->layerRendererCapabilities().maxTextureSize));
166 }
167
168 CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext()
169 {
170     TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext");
171     ASSERT(m_contextLost);
172
173     bool recreated = false;
174     if (!m_numTimesRecreateShouldFail)
175         recreated = m_proxy->recreateContext();
176     else
177         m_numTimesRecreateShouldFail--;
178
179     if (recreated) {
180         m_client->didRecreateContext(true);
181         m_contextLost = false;
182         return RecreateSucceeded;
183     }
184
185     // Tolerate a certain number of recreation failures to work around races
186     // in the context-lost machinery.
187     m_numFailedRecreateAttempts++;
188     if (m_numFailedRecreateAttempts < 5) {
189         // FIXME: The single thread does not self-schedule context
190         // recreation. So force another recreation attempt to happen by requesting
191         // another commit.
192         if (!CCProxy::hasImplThread())
193             setNeedsCommit();
194         return RecreateFailedButTryAgain;
195     }
196
197     // We have tried too many times to recreate the context. Tell the host to fall
198     // back to software rendering.
199     m_client->didRecreateContext(false);
200     return RecreateFailedAndGaveUp;
201 }
202
203 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator)
204 {
205     ASSERT(CCProxy::isImplThread());
206     if (m_layerRendererInitialized)
207         m_contentsTextureManager->evictAndDeleteAllTextures(allocator);
208 }
209
210 void CCLayerTreeHost::acquireLayerTextures()
211 {
212     ASSERT(CCProxy::isMainThread());
213     m_proxy->acquireLayerTextures();
214 }
215
216 void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime)
217 {
218     m_animating = true;
219     m_client->updateAnimations(monotonicFrameBeginTime);
220     animateLayers(monotonicFrameBeginTime);
221     m_animating = false;
222 }
223
224 void CCLayerTreeHost::layout()
225 {
226     m_client->layout();
227 }
228
229 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
230 {
231     ASSERT(CCProxy::isImplThread());
232     TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0);
233
234     m_contentsTextureManager->reduceMemoryToLimit(m_contentsTextureManager->preferredMemoryLimitBytes());
235     m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
236 }
237
238 // This function commits the CCLayerTreeHost to an impl tree. When modifying
239 // this function, keep in mind that the function *runs* on the impl thread! Any
240 // code that is logically a main thread operation, e.g. deletion of a LayerChromium,
241 // should be delayed until the CCLayerTreeHost::commitComplete, which will run
242 // after the commit, but on the main thread.
243 void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
244 {
245     ASSERT(CCProxy::isImplThread());
246
247     hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->detachLayerTree(), hostImpl));
248
249     // We may have added an animation during the tree sync. This will cause both layer tree hosts
250     // to visit their controllers.
251     if (rootLayer() && m_needsAnimateLayers)
252         hostImpl->setNeedsAnimateLayers();
253
254     hostImpl->setSourceFrameNumber(frameNumber());
255     hostImpl->setViewportSize(viewportSize());
256     hostImpl->setDeviceScaleFactor(deviceScaleFactor());
257     hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
258     hostImpl->setBackgroundColor(m_backgroundColor);
259     hostImpl->setHasTransparentBackground(m_hasTransparentBackground);
260     hostImpl->setVisible(m_visible);
261     hostImpl->setSourceFrameCanBeDrawn(m_frameIsForDisplay);
262
263     m_frameNumber++;
264 }
265
266 void CCLayerTreeHost::commitComplete()
267 {
268     m_deleteTextureAfterCommitList.clear();
269     m_contentsTextureManager->unprotectAllTextures();
270     m_client->didCommit();
271 }
272
273 PassRefPtr<CCGraphicsContext> CCLayerTreeHost::createContext()
274 {
275     RefPtr<CCGraphicsContext> context;
276     if (settings().forceSoftwareCompositing)
277         return CCGraphicsContext::create2D();
278     return CCGraphicsContext::create3D(m_client->createContext3D());
279 }
280
281 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
282 {
283     return CCLayerTreeHostImpl::create(m_settings, client);
284 }
285
286 void CCLayerTreeHost::didLoseContext()
287 {
288     TRACE_EVENT("CCLayerTreeHost::didLoseContext", 0, this);
289     ASSERT(CCProxy::isMainThread());
290     m_contextLost = true;
291     m_numFailedRecreateAttempts = 0;
292     setNeedsCommit();
293 }
294
295 // Temporary hack until WebViewImpl context creation gets simplified
296 CCGraphicsContext* CCLayerTreeHost::context()
297 {
298     return m_proxy->context();
299 }
300
301 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
302 {
303     m_triggerIdlePaints = false;
304     bool ret = m_proxy->compositeAndReadback(pixels, rect);
305     m_triggerIdlePaints = true;
306     return ret;
307 }
308
309 void CCLayerTreeHost::finishAllRendering()
310 {
311     if (!m_layerRendererInitialized)
312         return;
313     m_proxy->finishAllRendering();
314 }
315
316 const LayerRendererCapabilities& CCLayerTreeHost::layerRendererCapabilities() const
317 {
318     return m_proxy->layerRendererCapabilities();
319 }
320
321 void CCLayerTreeHost::setNeedsAnimate()
322 {
323     ASSERT(CCProxy::hasImplThread());
324     m_proxy->setNeedsAnimate();
325 }
326
327 void CCLayerTreeHost::setNeedsCommit()
328 {
329     m_proxy->setNeedsCommit();
330 }
331
332 void CCLayerTreeHost::setNeedsForcedCommit()
333 {
334     m_proxy->setNeedsForcedCommit();
335 }
336
337 void CCLayerTreeHost::setNeedsRedraw()
338 {
339     m_proxy->setNeedsRedraw();
340     if (!CCThreadProxy::implThread())
341         m_client->scheduleComposite();
342 }
343
344 bool CCLayerTreeHost::commitRequested() const
345 {
346     return m_proxy->commitRequested();
347 }
348
349 void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
350 {
351     ASSERT(CCThreadProxy::isMainThread());
352     setAnimationEventsRecursive(*events, m_rootLayer.get(), wallClockTime);
353 }
354
355 void CCLayerTreeHost::didAddAnimation()
356 {
357     m_needsAnimateLayers = true;
358     m_proxy->didAddAnimation();
359 }
360
361 void CCLayerTreeHost::setRootLayer(PassRefPtr<LayerChromium> rootLayer)
362 {
363     if (m_rootLayer == rootLayer)
364         return;
365
366     if (m_rootLayer)
367         m_rootLayer->setLayerTreeHost(0);
368     m_rootLayer = rootLayer;
369     if (m_rootLayer)
370         m_rootLayer->setLayerTreeHost(this);
371     setNeedsCommit();
372 }
373
374 void CCLayerTreeHost::setViewportSize(const IntSize& viewportSize)
375 {
376     if (viewportSize == m_viewportSize)
377         return;
378
379     m_viewportSize = viewportSize;
380
381     m_deviceViewportSize = viewportSize;
382     m_deviceViewportSize.scale(m_deviceScaleFactor);
383
384     setNeedsCommit();
385 }
386
387 void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
388 {
389     if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
390         return;
391
392     m_pageScaleFactor = pageScaleFactor;
393     m_minPageScaleFactor = minPageScaleFactor;
394     m_maxPageScaleFactor = maxPageScaleFactor;
395     setNeedsCommit();
396 }
397
398 void CCLayerTreeHost::setVisible(bool visible)
399 {
400     if (m_visible == visible)
401         return;
402
403     m_visible = visible;
404
405     // FIXME: Remove this stuff, it is here just for the m20 merge.
406     if (!m_visible && m_layerRendererInitialized) {
407         if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer)
408             setContentsMemoryAllocationLimitBytes(0);
409         else
410             setContentsMemoryAllocationLimitBytes(m_contentsTextureManager->preferredMemoryLimitBytes());
411     }
412
413     setNeedsForcedCommit();
414 }
415
416 void CCLayerTreeHost::setContentsMemoryAllocationLimitBytes(size_t bytes)
417 {
418     ASSERT(CCProxy::isMainThread());
419     if (m_memoryAllocationBytes == bytes)
420         return;
421
422     m_memoryAllocationBytes = bytes;
423     m_memoryAllocationIsForDisplay = bytes;
424
425     // When not visible, force a commit so that we change our memory allocation
426     // and evict/delete any textures if we are being requested to.
427     if (!m_visible)
428         setNeedsForcedCommit();
429     else
430         setNeedsCommit();
431 }
432
433 void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec)
434 {
435     m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec);
436 }
437
438 void CCLayerTreeHost::loseContext(int numTimes)
439 {
440     TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes);
441     m_numTimesRecreateShouldFail = numTimes - 1;
442     m_proxy->loseContext();
443 }
444
445 TextureManager* CCLayerTreeHost::contentsTextureManager() const
446 {
447     return m_contentsTextureManager.get();
448 }
449
450 void CCLayerTreeHost::composite()
451 {
452     ASSERT(!CCThreadProxy::implThread());
453     static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
454 }
455
456 void CCLayerTreeHost::scheduleComposite()
457 {
458     m_client->scheduleComposite();
459 }
460
461 bool CCLayerTreeHost::initializeLayerRendererIfNeeded()
462 {
463     if (!m_layerRendererInitialized) {
464         initializeLayerRenderer();
465         // If we couldn't initialize, then bail since we're returning to software mode.
466         if (!m_layerRendererInitialized)
467             return false;
468     }
469     if (m_contextLost) {
470         if (recreateContext() != RecreateSucceeded)
471             return false;
472     }
473     return true;
474 }
475
476
477 void CCLayerTreeHost::updateLayers(CCTextureUpdater& updater)
478 {
479     ASSERT(m_layerRendererInitialized);
480     // The visible state and memory allocation are set independently and in
481     // arbitrary order, so do not change the memory allocation used for the
482     // current commit until both values match intentions.
483     // FIXME: These two states should be combined into a single action so we
484     // need a single commit to change visible state, and this can be removed.
485     bool memoryAllocationStateMatchesVisibility = m_visible == m_memoryAllocationIsForDisplay;
486     if (memoryAllocationStateMatchesVisibility) {
487         m_contentsTextureManager->setMemoryAllocationLimitBytes(m_memoryAllocationBytes);
488         m_frameIsForDisplay = m_memoryAllocationIsForDisplay;
489     }
490
491     if (!rootLayer())
492         return;
493
494     if (viewportSize().isEmpty())
495         return;
496
497     updateLayers(rootLayer(), updater);
498 }
499
500 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& updater)
501 {
502     TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
503
504     if (!rootLayer->renderSurface())
505         rootLayer->createRenderSurface();
506     rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), deviceViewportSize()));
507
508     IntRect rootClipRect(IntPoint(), deviceViewportSize());
509     rootLayer->setClipRect(rootClipRect);
510
511     LayerList updateList;
512     updateList.append(rootLayer);
513
514     RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
515     rootRenderSurface->clearLayerList();
516
517     {
518         TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
519         WebTransformationMatrix identityMatrix;
520         WebTransformationMatrix deviceScaleTransform;
521         deviceScaleTransform.scale(m_deviceScaleFactor);
522         CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
523
524         FloatRect rootScissorRect(FloatPoint(0, 0), viewportSize());
525         CCLayerTreeHostCommon::calculateVisibleAndScissorRects(updateList, rootScissorRect);
526     }
527
528     // Reset partial texture update requests.
529     m_partialTextureUpdateRequests = 0;
530
531     reserveTextures(updateList);
532
533     paintLayerContents(updateList, PaintVisible, updater);
534     if (!m_triggerIdlePaints)
535         return;
536
537     size_t preferredLimitBytes = m_contentsTextureManager->preferredMemoryLimitBytes();
538     size_t maxLimitBytes = m_contentsTextureManager->maxMemoryLimitBytes();
539     m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes);
540     if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes)
541         return;
542
543     // Idle painting should fail when we hit the preferred memory limit,
544     // otherwise it will always push us towards the maximum limit.
545     m_contentsTextureManager->setMaxMemoryLimitBytes(preferredLimitBytes);
546     // The second (idle) paint will be a no-op in layers where painting already occured above.
547     paintLayerContents(updateList, PaintIdle, updater);
548     m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes);
549
550     for (size_t i = 0; i < updateList.size(); ++i)
551         updateList[i]->clearRenderSurface();
552 }
553
554 void CCLayerTreeHost::reserveTextures(const LayerList& updateList)
555 {
556     // Use BackToFront since it's cheap and this isn't order-dependent.
557     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
558
559     CCLayerIteratorType end = CCLayerIteratorType::end(&updateList);
560     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) {
561         if (!it.representsItself() || !it->alwaysReserveTextures())
562             continue;
563         it->reserveTextures();
564     }
565 }
566
567 // static
568 void CCLayerTreeHost::update(LayerChromium* layer, PaintType paintType, CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
569 {
570     ASSERT(layer);
571     ASSERT(PaintVisible == paintType || PaintIdle == paintType);
572     if (PaintVisible == paintType)
573         layer->update(updater, occlusion);
574     else
575         layer->idleUpdate(updater, occlusion);
576 }
577
578 void CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType, CCTextureUpdater& updater)
579 {
580     // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
581     // in code, we already know that at least something will be drawn into this render surface, so the
582     // mask and replica should be painted.
583
584     LayerChromium* maskLayer = renderSurfaceLayer->maskLayer();
585     if (maskLayer)
586         update(maskLayer, paintType, updater, 0);
587
588     LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0;
589     if (replicaMaskLayer)
590         update(replicaMaskLayer, paintType, updater, 0);
591 }
592
593 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType, CCTextureUpdater& updater)
594 {
595     // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
596     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
597
598     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
599     CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), deviceViewportSize()), recordMetricsForFrame);
600     occlusionTracker.setMinimumTrackingSize(CCOcclusionTracker::preferredMinimumTrackingSize());
601
602     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
603     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
604         occlusionTracker.enterLayer(it);
605
606         if (it.representsTargetRenderSurface()) {
607             ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating());
608             paintMasksForRenderSurface(*it, paintType, updater);
609         } else if (it.representsItself()) {
610             ASSERT(!it->bounds().isEmpty());
611             update(*it, paintType, updater, &occlusionTracker);
612         }
613
614         occlusionTracker.leaveLayer(it);
615     }
616
617     occlusionTracker.overdrawMetrics().recordMetrics(this);
618 }
619
620 static LayerChromium* findFirstScrollableLayer(LayerChromium* layer)
621 {
622     if (!layer)
623         return 0;
624
625     if (layer->scrollable())
626         return layer;
627
628     for (size_t i = 0; i < layer->children().size(); ++i) {
629         LayerChromium* found = findFirstScrollableLayer(layer->children()[i].get());
630         if (found)
631             return found;
632     }
633
634     return 0;
635 }
636
637 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
638 {
639     if (!m_rootLayer)
640         return;
641
642     LayerChromium* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get());
643     IntSize rootScrollDelta;
644
645     for (size_t i = 0; i < info.scrolls.size(); ++i) {
646         LayerChromium* layer = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), info.scrolls[i].layerId);
647         if (!layer)
648             continue;
649         if (layer == rootScrollLayer)
650             rootScrollDelta += info.scrolls[i].scrollDelta;
651         else
652             layer->scrollBy(info.scrolls[i].scrollDelta);
653     }
654     if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1)
655         m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta);
656 }
657
658 void CCLayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D* context)
659 {
660     if (m_animating)
661         return;
662
663     ASSERT(context);
664     RateLimiterMap::iterator it = m_rateLimiters.find(context);
665     if (it != m_rateLimiters.end())
666         it->second->start();
667     else {
668         RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context, this);
669         m_rateLimiters.set(context, rateLimiter);
670         rateLimiter->start();
671     }
672 }
673
674 void CCLayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D* context)
675 {
676     RateLimiterMap::iterator it = m_rateLimiters.find(context);
677     if (it != m_rateLimiters.end()) {
678         it->second->stop();
679         m_rateLimiters.remove(it);
680     }
681 }
682
683 void CCLayerTreeHost::rateLimit()
684 {
685     // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing
686     // context, and therefore for the SwapBuffers.
687     m_proxy->forceSerializeOnSwapBuffers();
688 }
689
690 bool CCLayerTreeHost::bufferedUpdates()
691 {
692     return m_settings.maxPartialTextureUpdates != numeric_limits<size_t>::max();
693 }
694
695 bool CCLayerTreeHost::requestPartialTextureUpdate()
696 {
697     if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
698         return false;
699
700     m_partialTextureUpdateRequests++;
701     return true;
702 }
703
704 void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture)
705 {
706     m_deleteTextureAfterCommitList.append(texture);
707 }
708
709 void CCLayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor)
710 {
711     if (deviceScaleFactor ==  m_deviceScaleFactor)
712         return;
713     m_deviceScaleFactor = deviceScaleFactor;
714
715     m_deviceViewportSize = m_viewportSize;
716     m_deviceViewportSize.scale(m_deviceScaleFactor);
717     setNeedsCommit();
718 }
719
720 void CCLayerTreeHost::animateLayers(double monotonicTime)
721 {
722     if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers)
723         return;
724
725     TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
726     m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime);
727 }
728
729 bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime)
730 {
731     if (!current)
732         return false;
733
734     bool subtreeNeedsAnimateLayers = false;
735     CCLayerAnimationController* currentController = current->layerAnimationController();
736     currentController->animate(monotonicTime, 0);
737
738     // If the current controller still has an active animation, we must continue animating layers.
739     if (currentController->hasActiveAnimation())
740          subtreeNeedsAnimateLayers = true;
741
742     for (size_t i = 0; i < current->children().size(); ++i) {
743         if (animateLayersRecursive(current->children()[i].get(), monotonicTime))
744             subtreeNeedsAnimateLayers = true;
745     }
746
747     return subtreeNeedsAnimateLayers;
748 }
749
750 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
751 {
752     if (!layer)
753         return;
754
755     for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
756         if (layer->id() == events[eventIndex].layerId) {
757             if (events[eventIndex].type == CCAnimationEvent::Started)
758                 layer->notifyAnimationStarted(events[eventIndex], wallClockTime);
759             else
760                 layer->notifyAnimationFinished(wallClockTime);
761         }
762     }
763
764     for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
765         setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
766 }
767
768 } // namespace WebCore