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