[chromium] Use opaque contents for paint culling
[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 "LayerPainterChromium.h"
31 #include "LayerRendererChromium.h"
32 #include "Region.h"
33 #include "TraceEvent.h"
34 #include "TreeSynchronizer.h"
35 #include "cc/CCLayerAnimationController.h"
36 #include "cc/CCLayerIterator.h"
37 #include "cc/CCLayerTreeHostCommon.h"
38 #include "cc/CCLayerTreeHostImpl.h"
39 #include "cc/CCOcclusionTracker.h"
40 #include "cc/CCSingleThreadProxy.h"
41 #include "cc/CCThread.h"
42 #include "cc/CCThreadProxy.h"
43
44 using namespace std;
45
46 namespace {
47 static int numLayerTreeInstances;
48 }
49
50 namespace WebCore {
51
52 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
53 {
54     return numLayerTreeInstances > 0;
55 }
56
57 PassRefPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCSettings& settings)
58 {
59     RefPtr<CCLayerTreeHost> layerTreeHost = adoptRef(new CCLayerTreeHost(client, settings));
60     if (!layerTreeHost->initialize())
61         return 0;
62     return layerTreeHost;
63 }
64
65 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings& settings)
66     : m_compositorIdentifier(-1)
67     , m_animating(false)
68     , m_needsAnimateLayers(false)
69     , m_client(client)
70     , m_frameNumber(0)
71     , m_layerRendererInitialized(false)
72     , m_contextLost(false)
73     , m_numTimesRecreateShouldFail(0)
74     , m_numFailedRecreateAttempts(0)
75     , m_settings(settings)
76     , m_visible(true)
77     , m_pageScaleFactor(1)
78     , m_minPageScaleFactor(1)
79     , m_maxPageScaleFactor(1)
80     , m_triggerIdlePaints(true)
81     , m_partialTextureUpdateRequests(0)
82 {
83     ASSERT(CCProxy::isMainThread());
84     numLayerTreeInstances++;
85 }
86
87 bool CCLayerTreeHost::initialize()
88 {
89     TRACE_EVENT("CCLayerTreeHost::initialize", this, 0);
90     if (CCProxy::hasImplThread()) {
91         // The HUD does not work in threaded mode. Turn it off.
92         m_settings.showFPSCounter = false;
93         m_settings.showPlatformLayerTree = false;
94
95         m_proxy = CCThreadProxy::create(this);
96     } else
97         m_proxy = CCSingleThreadProxy::create(this);
98     m_proxy->start();
99
100     if (!m_proxy->initializeContext())
101         return false;
102
103     m_compositorIdentifier = m_proxy->compositorIdentifier();
104     return true;
105 }
106
107 CCLayerTreeHost::~CCLayerTreeHost()
108 {
109     ASSERT(CCProxy::isMainThread());
110     TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0);
111     ASSERT(m_proxy);
112     m_proxy->stop();
113     m_proxy.clear();
114     clearPendingUpdate();
115     numLayerTreeInstances--;
116 }
117
118 void CCLayerTreeHost::initializeLayerRenderer()
119 {
120     TRACE_EVENT("CCLayerTreeHost::initializeLayerRenderer", this, 0);
121     if (!m_proxy->initializeLayerRenderer()) {
122         // Uh oh, better tell the client that we can't do anything with this context.
123         m_client->didRecreateContext(false);
124         return;
125     }
126
127     // Update m_settings based on capabilities that we got back from the renderer.
128     m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
129
130     // Update m_settings based on partial update capability.
131     m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates());
132
133     m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
134                                                       TextureManager::reclaimLimitBytes(viewportSize()),
135                                                       m_proxy->layerRendererCapabilities().maxTextureSize);
136
137     m_layerRendererInitialized = true;
138 }
139
140 CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext()
141 {
142     TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext");
143     ASSERT(m_contextLost);
144
145     bool recreated = false;
146     if (!m_numTimesRecreateShouldFail)
147         recreated = m_proxy->recreateContext();
148     else
149         m_numTimesRecreateShouldFail--;
150
151     if (recreated) {
152         m_client->didRecreateContext(true);
153         m_contextLost = false;
154         return RecreateSucceeded;
155     }
156
157     // Tolerate a certain number of recreation failures to work around races
158     // in the context-lost machinery.
159     m_numFailedRecreateAttempts++;
160     if (m_numFailedRecreateAttempts < 5) {
161         // FIXME: The single thread does not self-schedule context
162         // recreation. So force another recreation attempt to happen by requesting
163         // another commit.
164         if (!CCProxy::hasImplThread())
165             setNeedsCommit();
166         return RecreateFailedButTryAgain;
167     }
168
169     // We have tried too many times to recreate the context. Tell the host to fall
170     // back to software rendering.
171     m_client->didRecreateContext(false);
172     return RecreateFailedAndGaveUp;
173 }
174
175 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator)
176 {
177     ASSERT(CCProxy::isImplThread());
178     if (m_contentsTextureManager)
179         m_contentsTextureManager->evictAndDeleteAllTextures(allocator);
180 }
181
182 void CCLayerTreeHost::updateAnimations(double frameBeginTime)
183 {
184     m_animating = true;
185     m_client->updateAnimations(frameBeginTime);
186     animateLayers(monotonicallyIncreasingTime());
187     m_animating = false;
188 }
189
190 void CCLayerTreeHost::layout()
191 {
192     m_client->layout();
193 }
194
195 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
196 {
197     ASSERT(CCProxy::isImplThread());
198     TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0);
199
200     m_contentsTextureManager->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
201     m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
202 }
203
204 // This function commits the CCLayerTreeHost to an impl tree. When modifying
205 // this function, keep in mind that the function *runs* on the impl thread! Any
206 // code that is logically a main thread operation, e.g. deletion of a LayerChromium,
207 // should be delayed until the CCLayerTreeHost::commitComplete, which will run
208 // after the commit, but on the main thread.
209 void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
210 {
211     ASSERT(CCProxy::isImplThread());
212
213     hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer()));
214
215     // We may have added an animation during the tree sync. This will cause both layer tree hosts
216     // to visit their controllers.
217     if (rootLayer()) {
218         hostImpl->setNeedsAnimateLayers();
219         m_needsAnimateLayers = true;
220     }
221
222     hostImpl->setSourceFrameNumber(frameNumber());
223     hostImpl->setViewportSize(viewportSize());
224     hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
225
226     m_frameNumber++;
227 }
228
229 void CCLayerTreeHost::commitComplete()
230 {
231     m_deleteTextureAfterCommitList.clear();
232     clearPendingUpdate();
233     m_contentsTextureManager->unprotectAllTextures();
234 }
235
236 PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createContext()
237 {
238     return m_client->createContext();
239 }
240
241 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
242 {
243     return CCLayerTreeHostImpl::create(m_settings, client);
244 }
245
246 void CCLayerTreeHost::didLoseContext()
247 {
248     TRACE_EVENT("CCLayerTreeHost::didLoseContext", 0, this);
249     ASSERT(CCProxy::isMainThread());
250     m_contextLost = true;
251     m_numFailedRecreateAttempts = 0;
252     setNeedsCommit();
253 }
254
255 // Temporary hack until WebViewImpl context creation gets simplified
256 GraphicsContext3D* CCLayerTreeHost::context()
257 {
258     return m_proxy->context();
259 }
260
261 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
262 {
263     if (!m_layerRendererInitialized) {
264         initializeLayerRenderer();
265         if (!m_layerRendererInitialized)
266             return false;
267     }
268     if (m_contextLost) {
269         if (recreateContext() != RecreateSucceeded)
270             return false;
271     }
272     m_triggerIdlePaints = false;
273     bool ret = m_proxy->compositeAndReadback(pixels, rect);
274     m_triggerIdlePaints = true;
275     return ret;
276 }
277
278 void CCLayerTreeHost::finishAllRendering()
279 {
280     if (!m_layerRendererInitialized)
281         return;
282     m_proxy->finishAllRendering();
283 }
284
285 const LayerRendererCapabilities& CCLayerTreeHost::layerRendererCapabilities() const
286 {
287     return m_proxy->layerRendererCapabilities();
288 }
289
290 void CCLayerTreeHost::setNeedsAnimate()
291 {
292     ASSERT(CCProxy::hasImplThread());
293     m_proxy->setNeedsAnimate();
294 }
295
296 void CCLayerTreeHost::setNeedsCommit()
297 {
298     if (CCThreadProxy::implThread())
299         m_proxy->setNeedsCommit();
300     else
301         m_client->scheduleComposite();
302 }
303
304 void CCLayerTreeHost::setNeedsRedraw()
305 {
306     m_proxy->setNeedsRedraw();
307     if (!CCThreadProxy::implThread())
308         m_client->scheduleComposite();
309 }
310
311 void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
312 {
313     ASSERT(CCThreadProxy::isMainThread());
314     setAnimationEventsRecursive(*events, m_rootLayer.get(), wallClockTime);
315 }
316
317 void CCLayerTreeHost::setRootLayer(PassRefPtr<LayerChromium> rootLayer)
318 {
319     if (m_rootLayer == rootLayer)
320         return;
321
322     if (m_rootLayer)
323         m_rootLayer->setLayerTreeHost(0);
324     m_rootLayer = rootLayer;
325     if (m_rootLayer)
326         m_rootLayer->setLayerTreeHost(this);
327     setNeedsCommit();
328 }
329
330 void CCLayerTreeHost::setViewportSize(const IntSize& viewportSize)
331 {
332     if (viewportSize == m_viewportSize)
333         return;
334
335     if (m_contentsTextureManager) {
336         m_contentsTextureManager->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(viewportSize));
337         m_contentsTextureManager->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(viewportSize));
338     }
339     m_viewportSize = viewportSize;
340     setNeedsCommit();
341 }
342
343 void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
344 {
345     if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
346         return;
347
348     m_pageScaleFactor = pageScaleFactor;
349     m_minPageScaleFactor = minPageScaleFactor;
350     m_maxPageScaleFactor = maxPageScaleFactor;
351     setNeedsCommit();
352 }
353
354 void CCLayerTreeHost::setVisible(bool visible)
355 {
356     if (m_visible == visible)
357         return;
358
359     m_visible = visible;
360
361     if (!visible && m_layerRendererInitialized) {
362         m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes(viewportSize()));
363         m_contentsTextureManager->unprotectAllTextures();
364     }
365
366     // Tells the proxy that visibility state has changed. This will in turn call
367     // CCLayerTreeHost::didBecomeInvisibleOnImplThread on the appropriate thread, for
368     // the case where !visible.
369     m_proxy->setVisible(visible);
370 }
371
372 void CCLayerTreeHost::didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl* hostImpl)
373 {
374     ASSERT(CCProxy::isImplThread());
375     if (!m_layerRendererInitialized)
376         return;
377
378     if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer)
379         contentsTextureManager()->evictAndDeleteAllTextures(hostImpl->contentsTextureAllocator());
380     else {
381         contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
382         contentsTextureManager()->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
383     }
384
385     // Ensure that the dropped tiles are propagated to the impl tree.
386     // If the frontbuffer is cached, then clobber the impl tree. Otherwise,
387     // push over the tree changes.
388     if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer) {
389         hostImpl->setRootLayer(nullptr);
390         return;
391     }
392
393     hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer()));
394
395     // We may have added an animation during the tree sync. This will cause both layer tree hosts
396     // to visit their controllers.
397     if (rootLayer()) {
398         hostImpl->setNeedsAnimateLayers();
399         m_needsAnimateLayers = true;
400     }
401 }
402
403 void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec)
404 {
405     m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec);
406 }
407
408 void CCLayerTreeHost::loseContext(int numTimes)
409 {
410     TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes);
411     m_numTimesRecreateShouldFail = numTimes - 1;
412     m_proxy->loseContext();
413 }
414
415 TextureManager* CCLayerTreeHost::contentsTextureManager() const
416 {
417     return m_contentsTextureManager.get();
418 }
419
420 void CCLayerTreeHost::composite()
421 {
422     ASSERT(!CCThreadProxy::implThread());
423     static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
424 }
425
426 bool CCLayerTreeHost::updateLayers()
427 {
428     if (!m_layerRendererInitialized) {
429         initializeLayerRenderer();
430         // If we couldn't initialize, then bail since we're returning to software mode.
431         if (!m_layerRendererInitialized)
432             return false;
433     }
434     if (m_contextLost) {
435         if (recreateContext() != RecreateSucceeded)
436             return false;
437     }
438
439     if (!rootLayer())
440         return true;
441
442     if (viewportSize().isEmpty())
443         return true;
444
445     updateLayers(rootLayer());
446     return true;
447 }
448
449 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
450 {
451     TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
452
453     if (!rootLayer->renderSurface())
454         rootLayer->createRenderSurface();
455     rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), viewportSize()));
456
457     IntRect rootClipRect(IntPoint(), viewportSize());
458     rootLayer->setClipRect(rootClipRect);
459
460     // This assert fires if updateCompositorResources wasn't called after
461     // updateLayers. Only one update can be pending at any given time.
462     ASSERT(!m_updateList.size());
463     m_updateList.append(rootLayer);
464
465     RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
466     rootRenderSurface->clearLayerList();
467
468     TransformationMatrix identityMatrix;
469     {
470         TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
471         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
472     }
473
474     // Reset partial texture update requests.
475     m_partialTextureUpdateRequests = 0;
476
477     reserveTextures();
478
479     paintLayerContents(m_updateList, PaintVisible);
480     if (!m_triggerIdlePaints)
481         return;
482
483     size_t preferredLimitBytes = TextureManager::reclaimLimitBytes(m_viewportSize);
484     size_t maxLimitBytes = TextureManager::highLimitBytes(m_viewportSize);
485     m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes);
486     if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes)
487         return;
488
489     // Idle painting should fail when we hit the preferred memory limit,
490     // otherwise it will always push us towards the maximum limit.
491     m_contentsTextureManager->setMaxMemoryLimitBytes(preferredLimitBytes);
492     // The second (idle) paint will be a no-op in layers where painting already occured above.
493     paintLayerContents(m_updateList, PaintIdle);
494     m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes);
495 }
496
497 void CCLayerTreeHost::reserveTextures()
498 {
499     // Use BackToFront since it's cheap and this isn't order-dependent.
500     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
501
502     CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
503     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
504         if (!it.representsItself() || !it->alwaysReserveTextures())
505             continue;
506         it->reserveTextures();
507     }
508 }
509
510 // static
511 void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paintType, const CCOcclusionTracker* occlusion)
512 {
513     ASSERT(layer);
514     ASSERT(PaintVisible == paintType || PaintIdle == paintType);
515     if (PaintVisible == paintType)
516         layer->paintContentsIfDirty(occlusion);
517     else
518         layer->idlePaintContentsIfDirty(occlusion);
519 }
520
521 void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType)
522 {
523     // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
524     // in code, we already know that at least something will be drawn into this render surface, so the
525     // mask and replica should be painted.
526
527     // FIXME: If the surface has a replica, it should be painted with occlusion that excludes the current target surface subtree.
528
529     if (renderSurfaceLayer->maskLayer()) {
530         renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
531         paintContentsIfDirty(renderSurfaceLayer->maskLayer(), paintType, 0);
532     }
533
534     LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
535     if (replicaLayer) {
536         paintContentsIfDirty(replicaLayer, paintType, 0);
537
538         if (replicaLayer->maskLayer()) {
539             replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
540             paintContentsIfDirty(replicaLayer->maskLayer(), paintType, 0);
541         }
542     }
543 }
544
545 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType)
546 {
547     // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
548     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
549
550     CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), viewportSize()));
551     occlusionTracker.setUsePaintTracking(true); // FIXME: Remove this after m19 branch.
552
553     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
554     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
555         if (it.representsTargetRenderSurface()) {
556             ASSERT(it->renderSurface()->drawOpacity() || it->drawOpacityIsAnimating());
557
558             occlusionTracker.finishedTargetRenderSurface(*it, it->renderSurface());
559             paintMaskAndReplicaForRenderSurface(*it, paintType);
560         } else if (it.representsItself()) {
561             ASSERT(!it->bounds().isEmpty());
562
563             occlusionTracker.enterTargetRenderSurface(it->targetRenderSurface());
564             paintContentsIfDirty(*it, paintType, &occlusionTracker);
565             occlusionTracker.markOccludedBehindLayer(*it);
566         } else
567             occlusionTracker.leaveToTargetRenderSurface(it.targetRenderSurfaceLayer()->renderSurface());
568     }
569
570     occlusionTracker.overdrawMetrics().recordMetrics(this);
571 }
572
573 void CCLayerTreeHost::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
574 {
575     // Use BackToFront since it's cheap and this isn't order-dependent.
576     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
577
578     CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
579     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
580         if (it.representsTargetRenderSurface()) {
581             ASSERT(it->renderSurface()->drawOpacity() || it->drawOpacityIsAnimating());
582             if (it->maskLayer())
583                 it->maskLayer()->updateCompositorResources(context, updater);
584
585             if (it->replicaLayer()) {
586                 it->replicaLayer()->updateCompositorResources(context, updater);
587                 if (it->replicaLayer()->maskLayer())
588                     it->replicaLayer()->maskLayer()->updateCompositorResources(context, updater);
589             }
590         } else if (it.representsItself())
591             it->updateCompositorResources(context, updater);
592     }
593 }
594
595 void CCLayerTreeHost::clearPendingUpdate()
596 {
597     for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
598         LayerChromium* layer = m_updateList[surfaceIndex].get();
599         ASSERT(layer->renderSurface());
600         layer->clearRenderSurface();
601     }
602     m_updateList.clear();
603 }
604
605 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
606 {
607     // FIXME: pushing scroll offsets to non-root layers not implemented
608     if (!info.scrolls.size())
609         return;
610
611     ASSERT(info.scrolls.size() == 1);
612     IntSize scrollDelta = info.scrolls[0].scrollDelta;
613     m_client->applyScrollAndScale(scrollDelta, info.pageScaleDelta);
614 }
615
616 void CCLayerTreeHost::startRateLimiter(GraphicsContext3D* context)
617 {
618     if (m_animating)
619         return;
620     ASSERT(context);
621     RateLimiterMap::iterator it = m_rateLimiters.find(context);
622     if (it != m_rateLimiters.end())
623         it->second->start();
624     else {
625         RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context);
626         m_rateLimiters.set(context, rateLimiter);
627         rateLimiter->start();
628     }
629 }
630
631 void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
632 {
633     RateLimiterMap::iterator it = m_rateLimiters.find(context);
634     if (it != m_rateLimiters.end()) {
635         it->second->stop();
636         m_rateLimiters.remove(it);
637     }
638 }
639
640 bool CCLayerTreeHost::requestPartialTextureUpdate()
641 {
642     if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
643         return false;
644
645     m_partialTextureUpdateRequests++;
646     return true;
647 }
648
649 void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture)
650 {
651     m_deleteTextureAfterCommitList.append(texture);
652 }
653
654 void CCLayerTreeHost::animateLayers(double monotonicTime)
655 {
656     if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayer)
657         return;
658
659     TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
660     m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime);
661 }
662
663 bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime)
664 {
665     bool subtreeNeedsAnimateLayers = false;
666     CCLayerAnimationController* currentController = current->layerAnimationController();
667     currentController->animate(monotonicTime, 0);
668
669     // If the current controller still has an active animation, we must continue animating layers.
670     if (currentController->hasActiveAnimation())
671          subtreeNeedsAnimateLayers = true;
672
673     for (size_t i = 0; i < current->children().size(); ++i) {
674         if (animateLayersRecursive(current->children()[i].get(), monotonicTime))
675             subtreeNeedsAnimateLayers = true;
676     }
677
678     return subtreeNeedsAnimateLayers;
679 }
680
681 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
682 {
683     for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
684         if (layer->id() == events[eventIndex]->layerId())
685             layer->setAnimationEvent(*events[eventIndex], wallClockTime);
686     }
687
688     for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
689         setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
690 }
691
692 } // namespace WebCore