Don't consider a Bluetooth adapter present until it has an address.
[chromium-blink-merge.git] / cc / CCLayerTreeHost.cpp
blob50f227a0d6d476350331fc74787b3e6fefaf34a3
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "config.h"
7 #include "CCLayerTreeHost.h"
9 #include "CCFontAtlas.h"
10 #include "CCGraphicsContext.h"
11 #include "CCHeadsUpDisplayLayerImpl.h"
12 #include "CCLayerAnimationController.h"
13 #include "CCLayerIterator.h"
14 #include "CCLayerTreeHostClient.h"
15 #include "CCLayerTreeHostCommon.h"
16 #include "CCLayerTreeHostImpl.h"
17 #include "CCOcclusionTracker.h"
18 #include "CCOverdrawMetrics.h"
19 #include "CCSettings.h"
20 #include "CCSingleThreadProxy.h"
21 #include "CCThreadProxy.h"
22 #include "HeadsUpDisplayLayerChromium.h"
23 #include "LayerChromium.h"
24 #include "Region.h"
25 #include "TraceEvent.h"
26 #include "TreeSynchronizer.h"
28 using namespace std;
29 using WebKit::WebTransformationMatrix;
31 namespace {
32 static int numLayerTreeInstances;
35 namespace WebCore {
37 bool CCLayerTreeHost::s_needsFilterContext = false;
39 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
41 return numLayerTreeInstances > 0;
44 PassOwnPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings)
46 OwnPtr<CCLayerTreeHost> layerTreeHost = adoptPtr(new CCLayerTreeHost(client, settings));
47 if (!layerTreeHost->initialize())
48 return nullptr;
49 return layerTreeHost.release();
52 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTreeSettings& settings)
53 : m_animating(false)
54 , m_needsAnimateLayers(false)
55 , m_client(client)
56 , m_commitNumber(0)
57 , m_renderingStats()
58 , m_rendererInitialized(false)
59 , m_contextLost(false)
60 , m_numTimesRecreateShouldFail(0)
61 , m_numFailedRecreateAttempts(0)
62 , m_settings(settings)
63 , m_deviceScaleFactor(1)
64 , m_visible(true)
65 , m_pageScaleFactor(1)
66 , m_minPageScaleFactor(1)
67 , m_maxPageScaleFactor(1)
68 , m_triggerIdleUpdates(true)
69 , m_backgroundColor(SK_ColorWHITE)
70 , m_hasTransparentBackground(false)
71 , m_partialTextureUpdateRequests(0)
73 ASSERT(CCProxy::isMainThread());
74 numLayerTreeInstances++;
77 bool CCLayerTreeHost::initialize()
79 TRACE_EVENT0("cc", "CCLayerTreeHost::initialize");
81 if (CCProxy::hasImplThread())
82 m_proxy = CCThreadProxy::create(this);
83 else
84 m_proxy = CCSingleThreadProxy::create(this);
85 m_proxy->start();
87 return m_proxy->initializeContext();
90 CCLayerTreeHost::~CCLayerTreeHost()
92 if (m_rootLayer)
93 m_rootLayer->setLayerTreeHost(0);
94 ASSERT(CCProxy::isMainThread());
95 TRACE_EVENT0("cc", "CCLayerTreeHost::~CCLayerTreeHost");
96 ASSERT(m_proxy);
97 m_proxy->stop();
98 m_proxy.clear();
99 numLayerTreeInstances--;
100 RateLimiterMap::iterator it = m_rateLimiters.begin();
101 if (it != m_rateLimiters.end())
102 it->second->stop();
105 void CCLayerTreeHost::setSurfaceReady()
107 m_proxy->setSurfaceReady();
110 void CCLayerTreeHost::initializeRenderer()
112 TRACE_EVENT0("cc", "CCLayerTreeHost::initializeRenderer");
113 if (!m_proxy->initializeRenderer()) {
114 // Uh oh, better tell the client that we can't do anything with this context.
115 m_client->didRecreateOutputSurface(false);
116 return;
119 // Update m_settings based on capabilities that we got back from the renderer.
120 m_settings.acceleratePainting = m_proxy->rendererCapabilities().usingAcceleratedPainting;
122 // Update m_settings based on partial update capability.
123 m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates());
125 m_contentsTextureManager = CCPrioritizedTextureManager::create(0, m_proxy->rendererCapabilities().maxTextureSize, CCRenderer::ContentPool);
126 m_surfaceMemoryPlaceholder = m_contentsTextureManager->createTexture(IntSize(), GraphicsContext3D::RGBA);
128 m_rendererInitialized = true;
130 m_settings.defaultTileSize = IntSize(min(m_settings.defaultTileSize.width(), m_proxy->rendererCapabilities().maxTextureSize),
131 min(m_settings.defaultTileSize.height(), m_proxy->rendererCapabilities().maxTextureSize));
132 m_settings.maxUntiledLayerSize = IntSize(min(m_settings.maxUntiledLayerSize.width(), m_proxy->rendererCapabilities().maxTextureSize),
133 min(m_settings.maxUntiledLayerSize.height(), m_proxy->rendererCapabilities().maxTextureSize));
136 CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext()
138 TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext");
139 ASSERT(m_contextLost);
141 bool recreated = false;
142 if (!m_numTimesRecreateShouldFail)
143 recreated = m_proxy->recreateContext();
144 else
145 m_numTimesRecreateShouldFail--;
147 if (recreated) {
148 m_client->didRecreateOutputSurface(true);
149 m_contextLost = false;
150 return RecreateSucceeded;
153 // Tolerate a certain number of recreation failures to work around races
154 // in the context-lost machinery.
155 m_numFailedRecreateAttempts++;
156 if (m_numFailedRecreateAttempts < 5) {
157 // FIXME: The single thread does not self-schedule context
158 // recreation. So force another recreation attempt to happen by requesting
159 // another commit.
160 if (!CCProxy::hasImplThread())
161 setNeedsCommit();
162 return RecreateFailedButTryAgain;
165 // We have tried too many times to recreate the context. Tell the host to fall
166 // back to software rendering.
167 m_client->didRecreateOutputSurface(false);
168 return RecreateFailedAndGaveUp;
171 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(CCResourceProvider* resourceProvider)
173 ASSERT(CCProxy::isImplThread());
174 if (m_rendererInitialized)
175 m_contentsTextureManager->clearAllMemory(resourceProvider);
178 void CCLayerTreeHost::acquireLayerTextures()
180 ASSERT(CCProxy::isMainThread());
181 m_proxy->acquireLayerTextures();
184 void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime)
186 m_animating = true;
187 m_client->animate(monotonicFrameBeginTime);
188 animateLayers(monotonicFrameBeginTime);
189 m_animating = false;
191 m_renderingStats.numAnimationFrames++;
194 void CCLayerTreeHost::layout()
196 m_client->layout();
199 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
201 ASSERT(CCProxy::isImplThread());
202 TRACE_EVENT0("cc", "CCLayerTreeHost::commitTo");
204 m_contentsTextureManager->reduceMemory(hostImpl->resourceProvider());
207 // This function commits the CCLayerTreeHost to an impl tree. When modifying
208 // this function, keep in mind that the function *runs* on the impl thread! Any
209 // code that is logically a main thread operation, e.g. deletion of a LayerChromium,
210 // should be delayed until the CCLayerTreeHost::commitComplete, which will run
211 // after the commit, but on the main thread.
212 void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
214 ASSERT(CCProxy::isImplThread());
216 hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->detachLayerTree(), hostImpl));
218 if (m_rootLayer && m_hudLayer)
219 hostImpl->setHudLayer(static_cast<CCHeadsUpDisplayLayerImpl*>(CCLayerTreeHostCommon::findLayerInSubtree(hostImpl->rootLayer(), m_hudLayer->id())));
220 else
221 hostImpl->setHudLayer(0);
223 // We may have added an animation during the tree sync. This will cause both layer tree hosts
224 // to visit their controllers.
225 if (rootLayer() && m_needsAnimateLayers)
226 hostImpl->setNeedsAnimateLayers();
228 hostImpl->setSourceFrameNumber(commitNumber());
229 hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize());
230 hostImpl->setDeviceScaleFactor(deviceScaleFactor());
231 hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
232 hostImpl->setBackgroundColor(m_backgroundColor);
233 hostImpl->setHasTransparentBackground(m_hasTransparentBackground);
235 m_commitNumber++;
238 void CCLayerTreeHost::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
240 m_fontAtlas = fontAtlas;
241 setNeedsCommit();
244 void CCLayerTreeHost::willCommit()
246 m_client->willCommit();
247 if (m_rootLayer && m_settings.showDebugInfo()) {
248 if (!m_hudLayer)
249 m_hudLayer = HeadsUpDisplayLayerChromium::create();
251 if (m_fontAtlas)
252 m_hudLayer->setFontAtlas(m_fontAtlas.release());
254 if (!m_hudLayer->parent())
255 m_rootLayer->addChild(m_hudLayer);
259 void CCLayerTreeHost::commitComplete()
261 m_deleteTextureAfterCommitList.clear();
262 m_client->didCommit();
265 PassOwnPtr<CCGraphicsContext> CCLayerTreeHost::createContext()
267 return m_client->createOutputSurface();
270 PassOwnPtr<CCInputHandler> CCLayerTreeHost::createInputHandler()
272 return m_client->createInputHandler();
275 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
277 return CCLayerTreeHostImpl::create(m_settings, client);
280 void CCLayerTreeHost::didLoseContext()
282 TRACE_EVENT0("cc", "CCLayerTreeHost::didLoseContext");
283 ASSERT(CCProxy::isMainThread());
284 m_contextLost = true;
285 m_numFailedRecreateAttempts = 0;
286 setNeedsCommit();
289 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
291 m_triggerIdleUpdates = false;
292 bool ret = m_proxy->compositeAndReadback(pixels, rect);
293 m_triggerIdleUpdates = true;
294 return ret;
297 void CCLayerTreeHost::finishAllRendering()
299 if (!m_rendererInitialized)
300 return;
301 m_proxy->finishAllRendering();
304 void CCLayerTreeHost::renderingStats(CCRenderingStats& stats) const
306 stats = m_renderingStats;
307 m_proxy->implSideRenderingStats(stats);
310 const RendererCapabilities& CCLayerTreeHost::rendererCapabilities() const
312 return m_proxy->rendererCapabilities();
315 void CCLayerTreeHost::setNeedsAnimate()
317 ASSERT(CCProxy::hasImplThread());
318 m_proxy->setNeedsAnimate();
321 void CCLayerTreeHost::setNeedsCommit()
323 m_proxy->setNeedsCommit();
326 void CCLayerTreeHost::setNeedsRedraw()
328 m_proxy->setNeedsRedraw();
329 if (!CCThreadProxy::implThread())
330 m_client->scheduleComposite();
333 bool CCLayerTreeHost::commitRequested() const
335 return m_proxy->commitRequested();
338 void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
340 ASSERT(CCThreadProxy::isMainThread());
341 setAnimationEventsRecursive(*events, m_rootLayer.get(), wallClockTime);
344 void CCLayerTreeHost::didAddAnimation()
346 m_needsAnimateLayers = true;
347 m_proxy->didAddAnimation();
350 void CCLayerTreeHost::setRootLayer(PassRefPtr<LayerChromium> rootLayer)
352 if (m_rootLayer == rootLayer)
353 return;
355 if (m_rootLayer)
356 m_rootLayer->setLayerTreeHost(0);
357 m_rootLayer = rootLayer;
358 if (m_rootLayer)
359 m_rootLayer->setLayerTreeHost(this);
361 if (m_hudLayer)
362 m_hudLayer->removeFromParent();
364 setNeedsCommit();
367 void CCLayerTreeHost::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize)
369 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
370 return;
372 m_layoutViewportSize = layoutViewportSize;
373 m_deviceViewportSize = deviceViewportSize;
375 setNeedsCommit();
378 void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
380 if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
381 return;
383 m_pageScaleFactor = pageScaleFactor;
384 m_minPageScaleFactor = minPageScaleFactor;
385 m_maxPageScaleFactor = maxPageScaleFactor;
386 setNeedsCommit();
389 void CCLayerTreeHost::setVisible(bool visible)
391 if (m_visible == visible)
392 return;
393 m_visible = visible;
394 m_proxy->setVisible(visible);
397 void CCLayerTreeHost::evictAllContentTextures()
399 ASSERT(CCProxy::isMainThread());
400 ASSERT(m_contentsTextureManager.get());
401 m_contentsTextureManager->allBackingTexturesWereDeleted();
404 void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec)
406 m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec);
409 void CCLayerTreeHost::loseContext(int numTimes)
411 TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes);
412 m_numTimesRecreateShouldFail = numTimes - 1;
413 m_proxy->loseContext();
416 CCPrioritizedTextureManager* CCLayerTreeHost::contentsTextureManager() const
418 return m_contentsTextureManager.get();
421 void CCLayerTreeHost::composite()
423 ASSERT(!CCThreadProxy::implThread());
424 static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
427 void CCLayerTreeHost::scheduleComposite()
429 m_client->scheduleComposite();
432 bool CCLayerTreeHost::initializeRendererIfNeeded()
434 if (!m_rendererInitialized) {
435 initializeRenderer();
436 // If we couldn't initialize, then bail since we're returning to software mode.
437 if (!m_rendererInitialized)
438 return false;
440 if (m_contextLost) {
441 if (recreateContext() != RecreateSucceeded)
442 return false;
444 return true;
447 void CCLayerTreeHost::updateLayers(CCTextureUpdateQueue& queue, size_t memoryAllocationLimitBytes)
449 ASSERT(m_rendererInitialized);
450 ASSERT(memoryAllocationLimitBytes);
452 if (!rootLayer())
453 return;
455 if (layoutViewportSize().isEmpty())
456 return;
458 m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes);
460 updateLayers(rootLayer(), queue);
463 static void setScale(LayerChromium* layer, float deviceScaleFactor, float pageScaleFactor)
465 if (layer->boundsContainPageScale())
466 layer->setContentsScale(deviceScaleFactor);
467 else
468 layer->setContentsScale(deviceScaleFactor * pageScaleFactor);
471 static void updateLayerScale(LayerChromium* layer, float deviceScaleFactor, float pageScaleFactor)
473 setScale(layer, deviceScaleFactor, pageScaleFactor);
475 LayerChromium* maskLayer = layer->maskLayer();
476 if (maskLayer)
477 setScale(maskLayer, deviceScaleFactor, pageScaleFactor);
479 LayerChromium* replicaMaskLayer = layer->replicaLayer() ? layer->replicaLayer()->maskLayer() : 0;
480 if (replicaMaskLayer)
481 setScale(replicaMaskLayer, deviceScaleFactor, pageScaleFactor);
483 const Vector<RefPtr<LayerChromium> >& children = layer->children();
484 for (unsigned int i = 0; i < children.size(); ++i)
485 updateLayerScale(children[i].get(), deviceScaleFactor, pageScaleFactor);
488 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdateQueue& queue)
490 TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers");
492 updateLayerScale(rootLayer, m_deviceScaleFactor, m_pageScaleFactor);
494 LayerList updateList;
497 TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc");
498 CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, rendererCapabilities().maxTextureSize, updateList);
499 CCLayerTreeHostCommon::calculateVisibleRects(updateList);
502 // Reset partial texture update requests.
503 m_partialTextureUpdateRequests = 0;
505 bool needMoreUpdates = paintLayerContents(updateList, queue);
506 if (m_triggerIdleUpdates && needMoreUpdates)
507 setNeedsCommit();
509 for (size_t i = 0; i < updateList.size(); ++i)
510 updateList[i]->clearRenderSurface();
513 void CCLayerTreeHost::setPrioritiesForSurfaces(size_t surfaceMemoryBytes)
515 // Surfaces have a place holder for their memory since they are managed
516 // independantly but should still be tracked and reduce other memory usage.
517 m_surfaceMemoryPlaceholder->setTextureManager(m_contentsTextureManager.get());
518 m_surfaceMemoryPlaceholder->setRequestPriority(CCPriorityCalculator::renderSurfacePriority());
519 m_surfaceMemoryPlaceholder->setToSelfManagedMemoryPlaceholder(surfaceMemoryBytes);
522 void CCLayerTreeHost::setPrioritiesForLayers(const LayerList& updateList)
524 // Use BackToFront since it's cheap and this isn't order-dependent.
525 typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
527 CCPriorityCalculator calculator;
528 CCLayerIteratorType end = CCLayerIteratorType::end(&updateList);
529 for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) {
530 if (it.representsItself())
531 it->setTexturePriorities(calculator);
532 else if (it.representsTargetRenderSurface()) {
533 if (it->maskLayer())
534 it->maskLayer()->setTexturePriorities(calculator);
535 if (it->replicaLayer() && it->replicaLayer()->maskLayer())
536 it->replicaLayer()->maskLayer()->setTexturePriorities(calculator);
541 void CCLayerTreeHost::prioritizeTextures(const LayerList& renderSurfaceLayerList, CCOverdrawMetrics& metrics)
543 m_contentsTextureManager->clearPriorities();
545 size_t memoryForRenderSurfacesMetric = calculateMemoryForRenderSurfaces(renderSurfaceLayerList);
547 setPrioritiesForLayers(renderSurfaceLayerList);
548 setPrioritiesForSurfaces(memoryForRenderSurfacesMetric);
550 metrics.didUseContentsTextureMemoryBytes(m_contentsTextureManager->memoryAboveCutoffBytes());
551 metrics.didUseRenderSurfaceTextureMemoryBytes(memoryForRenderSurfacesMetric);
553 m_contentsTextureManager->prioritizeTextures();
556 size_t CCLayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList& updateList)
558 size_t readbackBytes = 0;
559 size_t maxBackgroundTextureBytes = 0;
560 size_t contentsTextureBytes = 0;
562 // Start iteration at 1 to skip the root surface as it does not have a texture cost.
563 for (size_t i = 1; i < updateList.size(); ++i) {
564 LayerChromium* renderSurfaceLayer = updateList[i].get();
565 RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
567 size_t bytes = CCTexture::memorySizeBytes(renderSurface->contentRect().size(), GraphicsContext3D::RGBA);
568 contentsTextureBytes += bytes;
570 if (renderSurfaceLayer->backgroundFilters().isEmpty())
571 continue;
573 if (bytes > maxBackgroundTextureBytes)
574 maxBackgroundTextureBytes = bytes;
575 if (!readbackBytes)
576 readbackBytes = CCTexture::memorySizeBytes(m_deviceViewportSize, GraphicsContext3D::RGBA);
578 return readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes;
581 bool CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, CCTextureUpdateQueue& queue)
583 // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
584 // in code, we already know that at least something will be drawn into this render surface, so the
585 // mask and replica should be painted.
587 bool needMoreUpdates = false;
588 LayerChromium* maskLayer = renderSurfaceLayer->maskLayer();
589 if (maskLayer) {
590 maskLayer->update(queue, 0, m_renderingStats);
591 needMoreUpdates |= maskLayer->needMoreUpdates();
594 LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0;
595 if (replicaMaskLayer) {
596 replicaMaskLayer->update(queue, 0, m_renderingStats);
597 needMoreUpdates |= replicaMaskLayer->needMoreUpdates();
599 return needMoreUpdates;
602 bool CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, CCTextureUpdateQueue& queue)
604 // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
605 typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
607 bool needMoreUpdates = false;
608 bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
609 CCOcclusionTracker occlusionTracker(m_rootLayer->renderSurface()->contentRect(), recordMetricsForFrame);
610 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
612 prioritizeTextures(renderSurfaceLayerList, occlusionTracker.overdrawMetrics());
614 CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
615 for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
616 occlusionTracker.enterLayer(it);
618 if (it.representsTargetRenderSurface()) {
619 ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating());
620 needMoreUpdates |= paintMasksForRenderSurface(*it, queue);
621 } else if (it.representsItself()) {
622 ASSERT(!it->bounds().isEmpty());
623 it->update(queue, &occlusionTracker, m_renderingStats);
624 needMoreUpdates |= it->needMoreUpdates();
627 occlusionTracker.leaveLayer(it);
630 occlusionTracker.overdrawMetrics().recordMetrics(this);
632 return needMoreUpdates;
635 static LayerChromium* findFirstScrollableLayer(LayerChromium* layer)
637 if (!layer)
638 return 0;
640 if (layer->scrollable())
641 return layer;
643 for (size_t i = 0; i < layer->children().size(); ++i) {
644 LayerChromium* found = findFirstScrollableLayer(layer->children()[i].get());
645 if (found)
646 return found;
649 return 0;
652 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
654 if (!m_rootLayer)
655 return;
657 LayerChromium* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get());
658 IntSize rootScrollDelta;
660 for (size_t i = 0; i < info.scrolls.size(); ++i) {
661 LayerChromium* layer = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), info.scrolls[i].layerId);
662 if (!layer)
663 continue;
664 if (layer == rootScrollLayer)
665 rootScrollDelta += info.scrolls[i].scrollDelta;
666 else
667 layer->setScrollPosition(layer->scrollPosition() + info.scrolls[i].scrollDelta);
669 if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1)
670 m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta);
673 void CCLayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D* context)
675 if (m_animating)
676 return;
678 ASSERT(context);
679 RateLimiterMap::iterator it = m_rateLimiters.find(context);
680 if (it != m_rateLimiters.end())
681 it->second->start();
682 else {
683 RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context, this);
684 m_rateLimiters.set(context, rateLimiter);
685 rateLimiter->start();
689 void CCLayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D* context)
691 RateLimiterMap::iterator it = m_rateLimiters.find(context);
692 if (it != m_rateLimiters.end()) {
693 it->second->stop();
694 m_rateLimiters.remove(it);
698 void CCLayerTreeHost::rateLimit()
700 // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing
701 // context, and therefore for the SwapBuffers.
702 m_proxy->forceSerializeOnSwapBuffers();
705 bool CCLayerTreeHost::bufferedUpdates()
707 return m_settings.maxPartialTextureUpdates != numeric_limits<size_t>::max();
710 bool CCLayerTreeHost::requestPartialTextureUpdate()
712 if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
713 return false;
715 m_partialTextureUpdateRequests++;
716 return true;
719 void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<CCPrioritizedTexture> texture)
721 m_deleteTextureAfterCommitList.append(texture);
724 void CCLayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor)
726 if (deviceScaleFactor == m_deviceScaleFactor)
727 return;
728 m_deviceScaleFactor = deviceScaleFactor;
730 setNeedsCommit();
733 void CCLayerTreeHost::animateLayers(double monotonicTime)
735 if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers)
736 return;
738 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
739 m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime);
742 bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime)
744 if (!current)
745 return false;
747 bool subtreeNeedsAnimateLayers = false;
748 CCLayerAnimationController* currentController = current->layerAnimationController();
749 currentController->animate(monotonicTime, 0);
751 // If the current controller still has an active animation, we must continue animating layers.
752 if (currentController->hasActiveAnimation())
753 subtreeNeedsAnimateLayers = true;
755 for (size_t i = 0; i < current->children().size(); ++i) {
756 if (animateLayersRecursive(current->children()[i].get(), monotonicTime))
757 subtreeNeedsAnimateLayers = true;
760 return subtreeNeedsAnimateLayers;
763 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
765 if (!layer)
766 return;
768 for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
769 if (layer->id() == events[eventIndex].layerId) {
770 if (events[eventIndex].type == CCAnimationEvent::Started)
771 layer->notifyAnimationStarted(events[eventIndex], wallClockTime);
772 else
773 layer->notifyAnimationFinished(wallClockTime);
777 for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
778 setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
781 } // namespace WebCore