Unreviewed, rolling out r110929.
[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 Region& occludedScreenSpace)
503 {
504     ASSERT(layer);
505     ASSERT(PaintVisible == paintType || PaintIdle == paintType);
506     if (PaintVisible == paintType)
507         layer->paintContentsIfDirty(occludedScreenSpace);
508     else
509         layer->idlePaintContentsIfDirty(occludedScreenSpace);
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     Region noOcclusion;
520
521     if (renderSurfaceLayer->maskLayer()) {
522         renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
523         paintContentsIfDirty(renderSurfaceLayer->maskLayer(), paintType, noOcclusion);
524     }
525
526     LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
527     if (replicaLayer) {
528         paintContentsIfDirty(replicaLayer, paintType, noOcclusion);
529
530         if (replicaLayer->maskLayer()) {
531             replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
532             paintContentsIfDirty(replicaLayer->maskLayer(), paintType, noOcclusion);
533         }
534     }
535 }
536
537 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType)
538 {
539     // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
540     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
541
542     CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), viewportSize()));
543     occlusionTracker.setUsePaintTracking(false); // FIXME: Remove this to turn on paint tracking for paint culling
544
545     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
546     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
547         if (it.representsTargetRenderSurface()) {
548             ASSERT(it->renderSurface()->drawOpacity());
549
550             occlusionTracker.finishedTargetRenderSurface(*it, it->renderSurface());
551             paintMaskAndReplicaForRenderSurface(*it, paintType);
552         } else if (it.representsItself()) {
553             ASSERT(!it->bounds().isEmpty());
554
555             occlusionTracker.enterTargetRenderSurface(it->targetRenderSurface());
556             paintContentsIfDirty(*it, paintType, occlusionTracker.currentOcclusionInScreenSpace());
557             occlusionTracker.markOccludedBehindLayer(*it);
558         } else
559             occlusionTracker.leaveToTargetRenderSurface(it.targetRenderSurfaceLayer()->renderSurface());
560     }
561 }
562
563 void CCLayerTreeHost::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
564 {
565     // Use BackToFront since it's cheap and this isn't order-dependent.
566     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
567
568     CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
569     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
570         if (it.representsTargetRenderSurface()) {
571             ASSERT(it->renderSurface()->drawOpacity());
572             if (it->maskLayer())
573                 it->maskLayer()->updateCompositorResources(context, updater);
574
575             if (it->replicaLayer()) {
576                 it->replicaLayer()->updateCompositorResources(context, updater);
577                 if (it->replicaLayer()->maskLayer())
578                     it->replicaLayer()->maskLayer()->updateCompositorResources(context, updater);
579             }
580         } else if (it.representsItself())
581             it->updateCompositorResources(context, updater);
582     }
583 }
584
585 void CCLayerTreeHost::clearPendingUpdate()
586 {
587     for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
588         LayerChromium* layer = m_updateList[surfaceIndex].get();
589         ASSERT(layer->renderSurface());
590         layer->clearRenderSurface();
591     }
592     m_updateList.clear();
593 }
594
595 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
596 {
597     // FIXME: pushing scroll offsets to non-root layers not implemented
598     if (!info.scrolls.size())
599         return;
600
601     ASSERT(info.scrolls.size() == 1);
602     IntSize scrollDelta = info.scrolls[0].scrollDelta;
603     m_client->applyScrollAndScale(scrollDelta, info.pageScaleDelta);
604 }
605
606 void CCLayerTreeHost::startRateLimiter(GraphicsContext3D* context)
607 {
608     if (m_animating)
609         return;
610     ASSERT(context);
611     RateLimiterMap::iterator it = m_rateLimiters.find(context);
612     if (it != m_rateLimiters.end())
613         it->second->start();
614     else {
615         RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context);
616         m_rateLimiters.set(context, rateLimiter);
617         rateLimiter->start();
618     }
619 }
620
621 void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
622 {
623     RateLimiterMap::iterator it = m_rateLimiters.find(context);
624     if (it != m_rateLimiters.end()) {
625         it->second->stop();
626         m_rateLimiters.remove(it);
627     }
628 }
629
630 bool CCLayerTreeHost::requestPartialTextureUpdate()
631 {
632     if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
633         return false;
634
635     m_partialTextureUpdateRequests++;
636     return true;
637 }
638
639 void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture)
640 {
641     m_deleteTextureAfterCommitList.append(texture);
642 }
643
644 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
645 {
646     for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
647         if (layer->id() == events[eventIndex]->layerId())
648             layer->setAnimationEvent(*events[eventIndex], wallClockTime);
649     }
650
651     for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
652         setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
653 }
654
655 } // namespace WebCore