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