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.
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"
25 #include "TraceEvent.h"
26 #include "TreeSynchronizer.h"
29 using WebKit::WebTransformationMatrix
;
32 static int numLayerTreeInstances
;
37 bool CCLayerTreeHost::s_needsFilterContext
= false;
39 CCLayerTreeSettings::CCLayerTreeSettings()
40 : acceleratePainting(false)
41 , showFPSCounter(false)
42 , showPlatformLayerTree(false)
43 , showPaintRects(false)
44 , showPropertyChangedRects(false)
45 , showSurfaceDamageRects(false)
46 , showScreenSpaceRects(false)
47 , showReplicaScreenSpaceRects(false)
48 , showOccludingRects(false)
49 , renderVSyncEnabled(true)
51 , maxPartialTextureUpdates(std::numeric_limits
<size_t>::max())
52 , defaultTileSize(IntSize(256, 256))
53 , maxUntiledLayerSize(IntSize(512, 512))
54 , minimumOcclusionTrackingSize(IntSize(160, 160))
58 CCLayerTreeSettings::~CCLayerTreeSettings()
62 RendererCapabilities::RendererCapabilities()
63 : bestTextureFormat(0)
64 , contextHasCachedFrontBuffer(false)
65 , usingPartialSwap(false)
66 , usingAcceleratedPainting(false)
67 , usingSetVisibility(false)
68 , usingSwapCompleteCallback(false)
69 , usingGpuMemoryManager(false)
70 , usingDiscardFramebuffer(false)
71 , usingEglImage(false)
76 RendererCapabilities::~RendererCapabilities()
80 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
82 return numLayerTreeInstances
> 0;
85 scoped_ptr
<CCLayerTreeHost
> CCLayerTreeHost::create(CCLayerTreeHostClient
* client
, const CCLayerTreeSettings
& settings
)
87 scoped_ptr
<CCLayerTreeHost
> layerTreeHost(new CCLayerTreeHost(client
, settings
));
88 if (!layerTreeHost
->initialize())
89 return scoped_ptr
<CCLayerTreeHost
>();
90 return layerTreeHost
.Pass();
93 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient
* client
, const CCLayerTreeSettings
& settings
)
95 , m_needsAnimateLayers(false)
99 , m_rendererInitialized(false)
100 , m_contextLost(false)
101 , m_numTimesRecreateShouldFail(0)
102 , m_numFailedRecreateAttempts(0)
103 , m_settings(settings
)
104 , m_deviceScaleFactor(1)
106 , m_pageScaleFactor(1)
107 , m_minPageScaleFactor(1)
108 , m_maxPageScaleFactor(1)
109 , m_triggerIdleUpdates(true)
110 , m_backgroundColor(SK_ColorWHITE
)
111 , m_hasTransparentBackground(false)
112 , m_partialTextureUpdateRequests(0)
114 ASSERT(CCProxy::isMainThread());
115 numLayerTreeInstances
++;
118 bool CCLayerTreeHost::initialize()
120 TRACE_EVENT0("cc", "CCLayerTreeHost::initialize");
122 if (CCProxy::hasImplThread())
123 m_proxy
= CCThreadProxy::create(this);
125 m_proxy
= CCSingleThreadProxy::create(this);
128 return m_proxy
->initializeContext();
131 CCLayerTreeHost::~CCLayerTreeHost()
134 m_rootLayer
->setLayerTreeHost(0);
135 ASSERT(CCProxy::isMainThread());
136 TRACE_EVENT0("cc", "CCLayerTreeHost::~CCLayerTreeHost");
137 ASSERT(m_proxy
.get());
140 numLayerTreeInstances
--;
141 RateLimiterMap::iterator it
= m_rateLimiters
.begin();
142 if (it
!= m_rateLimiters
.end())
146 void CCLayerTreeHost::setSurfaceReady()
148 m_proxy
->setSurfaceReady();
151 void CCLayerTreeHost::initializeRenderer()
153 TRACE_EVENT0("cc", "CCLayerTreeHost::initializeRenderer");
154 if (!m_proxy
->initializeRenderer()) {
155 // Uh oh, better tell the client that we can't do anything with this context.
156 m_client
->didRecreateOutputSurface(false);
160 // Update m_settings based on capabilities that we got back from the renderer.
161 m_settings
.acceleratePainting
= m_proxy
->rendererCapabilities().usingAcceleratedPainting
;
163 // Update m_settings based on partial update capability.
164 m_settings
.maxPartialTextureUpdates
= min(m_settings
.maxPartialTextureUpdates
, m_proxy
->maxPartialTextureUpdates());
166 m_contentsTextureManager
= CCPrioritizedTextureManager::create(0, m_proxy
->rendererCapabilities().maxTextureSize
, CCRenderer::ContentPool
);
167 m_surfaceMemoryPlaceholder
= m_contentsTextureManager
->createTexture(IntSize(), GraphicsContext3D::RGBA
);
169 m_rendererInitialized
= true;
171 m_settings
.defaultTileSize
= IntSize(min(m_settings
.defaultTileSize
.width(), m_proxy
->rendererCapabilities().maxTextureSize
),
172 min(m_settings
.defaultTileSize
.height(), m_proxy
->rendererCapabilities().maxTextureSize
));
173 m_settings
.maxUntiledLayerSize
= IntSize(min(m_settings
.maxUntiledLayerSize
.width(), m_proxy
->rendererCapabilities().maxTextureSize
),
174 min(m_settings
.maxUntiledLayerSize
.height(), m_proxy
->rendererCapabilities().maxTextureSize
));
177 CCLayerTreeHost::RecreateResult
CCLayerTreeHost::recreateContext()
179 TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext");
180 ASSERT(m_contextLost
);
182 bool recreated
= false;
183 if (!m_numTimesRecreateShouldFail
)
184 recreated
= m_proxy
->recreateContext();
186 m_numTimesRecreateShouldFail
--;
189 m_client
->didRecreateOutputSurface(true);
190 m_contextLost
= false;
191 return RecreateSucceeded
;
194 // Tolerate a certain number of recreation failures to work around races
195 // in the context-lost machinery.
196 m_numFailedRecreateAttempts
++;
197 if (m_numFailedRecreateAttempts
< 5) {
198 // FIXME: The single thread does not self-schedule context
199 // recreation. So force another recreation attempt to happen by requesting
201 if (!CCProxy::hasImplThread())
203 return RecreateFailedButTryAgain
;
206 // We have tried too many times to recreate the context. Tell the host to fall
207 // back to software rendering.
208 m_client
->didRecreateOutputSurface(false);
209 return RecreateFailedAndGaveUp
;
212 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(CCResourceProvider
* resourceProvider
)
214 ASSERT(CCProxy::isImplThread());
215 if (m_rendererInitialized
)
216 m_contentsTextureManager
->clearAllMemory(resourceProvider
);
219 void CCLayerTreeHost::acquireLayerTextures()
221 ASSERT(CCProxy::isMainThread());
222 m_proxy
->acquireLayerTextures();
225 void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime
)
228 m_client
->animate(monotonicFrameBeginTime
);
229 animateLayers(monotonicFrameBeginTime
);
232 m_renderingStats
.numAnimationFrames
++;
235 void CCLayerTreeHost::layout()
240 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl
* hostImpl
)
242 ASSERT(CCProxy::isImplThread());
243 TRACE_EVENT0("cc", "CCLayerTreeHost::commitTo");
245 m_contentsTextureManager
->reduceMemory(hostImpl
->resourceProvider());
248 // This function commits the CCLayerTreeHost to an impl tree. When modifying
249 // this function, keep in mind that the function *runs* on the impl thread! Any
250 // code that is logically a main thread operation, e.g. deletion of a LayerChromium,
251 // should be delayed until the CCLayerTreeHost::commitComplete, which will run
252 // after the commit, but on the main thread.
253 void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl
* hostImpl
)
255 ASSERT(CCProxy::isImplThread());
257 hostImpl
->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl
->detachLayerTree(), hostImpl
));
259 if (m_rootLayer
&& m_hudLayer
)
260 hostImpl
->setHudLayer(static_cast<CCHeadsUpDisplayLayerImpl
*>(CCLayerTreeHostCommon::findLayerInSubtree(hostImpl
->rootLayer(), m_hudLayer
->id())));
262 hostImpl
->setHudLayer(0);
264 // We may have added an animation during the tree sync. This will cause both layer tree hosts
265 // to visit their controllers.
266 if (rootLayer() && m_needsAnimateLayers
)
267 hostImpl
->setNeedsAnimateLayers();
269 hostImpl
->setSourceFrameNumber(commitNumber());
270 hostImpl
->setViewportSize(layoutViewportSize(), deviceViewportSize());
271 hostImpl
->setDeviceScaleFactor(deviceScaleFactor());
272 hostImpl
->setPageScaleFactorAndLimits(m_pageScaleFactor
, m_minPageScaleFactor
, m_maxPageScaleFactor
);
273 hostImpl
->setBackgroundColor(m_backgroundColor
);
274 hostImpl
->setHasTransparentBackground(m_hasTransparentBackground
);
279 void CCLayerTreeHost::setFontAtlas(scoped_ptr
<CCFontAtlas
> fontAtlas
)
281 m_fontAtlas
= fontAtlas
.Pass();
285 void CCLayerTreeHost::willCommit()
287 m_client
->willCommit();
288 if (m_rootLayer
&& m_settings
.showDebugInfo()) {
290 m_hudLayer
= HeadsUpDisplayLayerChromium::create();
292 if (m_fontAtlas
.get())
293 m_hudLayer
->setFontAtlas(m_fontAtlas
.Pass());
295 if (!m_hudLayer
->parent())
296 m_rootLayer
->addChild(m_hudLayer
);
300 void CCLayerTreeHost::commitComplete()
302 m_deleteTextureAfterCommitList
.clear();
303 m_client
->didCommit();
306 scoped_ptr
<CCGraphicsContext
> CCLayerTreeHost::createContext()
308 return m_client
->createOutputSurface();
311 scoped_ptr
<CCInputHandler
> CCLayerTreeHost::createInputHandler()
313 return m_client
->createInputHandler();
316 scoped_ptr
<CCLayerTreeHostImpl
> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient
* client
)
318 return CCLayerTreeHostImpl::create(m_settings
, client
);
321 void CCLayerTreeHost::didLoseContext()
323 TRACE_EVENT0("cc", "CCLayerTreeHost::didLoseContext");
324 ASSERT(CCProxy::isMainThread());
325 m_contextLost
= true;
326 m_numFailedRecreateAttempts
= 0;
330 bool CCLayerTreeHost::compositeAndReadback(void *pixels
, const IntRect
& rect
)
332 m_triggerIdleUpdates
= false;
333 bool ret
= m_proxy
->compositeAndReadback(pixels
, rect
);
334 m_triggerIdleUpdates
= true;
338 void CCLayerTreeHost::finishAllRendering()
340 if (!m_rendererInitialized
)
342 m_proxy
->finishAllRendering();
345 void CCLayerTreeHost::renderingStats(CCRenderingStats
* stats
) const
347 *stats
= m_renderingStats
;
348 m_proxy
->renderingStats(stats
);
351 const RendererCapabilities
& CCLayerTreeHost::rendererCapabilities() const
353 return m_proxy
->rendererCapabilities();
356 void CCLayerTreeHost::setNeedsAnimate()
358 ASSERT(CCProxy::hasImplThread());
359 m_proxy
->setNeedsAnimate();
362 void CCLayerTreeHost::setNeedsCommit()
364 m_proxy
->setNeedsCommit();
367 void CCLayerTreeHost::setNeedsRedraw()
369 m_proxy
->setNeedsRedraw();
370 if (!CCThreadProxy::implThread())
371 m_client
->scheduleComposite();
374 bool CCLayerTreeHost::commitRequested() const
376 return m_proxy
->commitRequested();
379 void CCLayerTreeHost::setAnimationEvents(scoped_ptr
<CCAnimationEventsVector
> events
, double wallClockTime
)
381 ASSERT(CCThreadProxy::isMainThread());
382 setAnimationEventsRecursive(*events
.get(), m_rootLayer
.get(), wallClockTime
);
385 void CCLayerTreeHost::didAddAnimation()
387 m_needsAnimateLayers
= true;
388 m_proxy
->didAddAnimation();
391 void CCLayerTreeHost::setRootLayer(scoped_refptr
<LayerChromium
> rootLayer
)
393 if (m_rootLayer
== rootLayer
)
397 m_rootLayer
->setLayerTreeHost(0);
398 m_rootLayer
= rootLayer
;
400 m_rootLayer
->setLayerTreeHost(this);
403 m_hudLayer
->removeFromParent();
408 void CCLayerTreeHost::setViewportSize(const IntSize
& layoutViewportSize
, const IntSize
& deviceViewportSize
)
410 if (layoutViewportSize
== m_layoutViewportSize
&& deviceViewportSize
== m_deviceViewportSize
)
413 m_layoutViewportSize
= layoutViewportSize
;
414 m_deviceViewportSize
= deviceViewportSize
;
419 void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor
, float minPageScaleFactor
, float maxPageScaleFactor
)
421 if (pageScaleFactor
== m_pageScaleFactor
&& minPageScaleFactor
== m_minPageScaleFactor
&& maxPageScaleFactor
== m_maxPageScaleFactor
)
424 m_pageScaleFactor
= pageScaleFactor
;
425 m_minPageScaleFactor
= minPageScaleFactor
;
426 m_maxPageScaleFactor
= maxPageScaleFactor
;
430 void CCLayerTreeHost::setVisible(bool visible
)
432 if (m_visible
== visible
)
435 m_proxy
->setVisible(visible
);
438 void CCLayerTreeHost::reduceContentsTexturesMemoryOnImplThread(size_t limitBytes
, CCResourceProvider
* resourceProvider
)
440 ASSERT(CCProxy::isImplThread());
441 ASSERT(m_contentsTextureManager
.get());
442 m_contentsTextureManager
->reduceMemoryOnImplThread(limitBytes
, resourceProvider
);
445 bool CCLayerTreeHost::evictedContentsTexturesBackingsExist() const
447 ASSERT(CCProxy::isImplThread());
448 ASSERT(m_contentsTextureManager
.get());
449 return m_contentsTextureManager
->evictedBackingsExist();
452 void CCLayerTreeHost::getEvictedContentTexturesBackings(CCPrioritizedTextureManager::BackingVector
& evictedBackings
)
454 ASSERT(CCProxy::isImplThread());
455 evictedBackings
.clear();
456 if (m_rendererInitialized
)
457 m_contentsTextureManager
->getEvictedBackings(evictedBackings
);
460 void CCLayerTreeHost::unlinkEvictedContentTexturesBackings(const CCPrioritizedTextureManager::BackingVector
& evictedBackings
)
462 ASSERT(CCProxy::isMainThread());
463 ASSERT(m_contentsTextureManager
.get());
464 m_contentsTextureManager
->unlinkEvictedBackings(evictedBackings
);
467 bool CCLayerTreeHost::deleteEvictedContentTexturesBackings()
469 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked());
470 ASSERT(m_contentsTextureManager
.get());
471 return m_contentsTextureManager
->deleteEvictedBackings();
474 void CCLayerTreeHost::startPageScaleAnimation(const IntSize
& targetPosition
, bool useAnchor
, float scale
, double durationSec
)
476 m_proxy
->startPageScaleAnimation(targetPosition
, useAnchor
, scale
, durationSec
);
479 void CCLayerTreeHost::loseContext(int numTimes
)
481 TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes
);
482 m_numTimesRecreateShouldFail
= numTimes
- 1;
483 m_proxy
->loseContext();
486 CCPrioritizedTextureManager
* CCLayerTreeHost::contentsTextureManager() const
488 return m_contentsTextureManager
.get();
491 void CCLayerTreeHost::composite()
493 ASSERT(!CCThreadProxy::implThread());
494 static_cast<CCSingleThreadProxy
*>(m_proxy
.get())->compositeImmediately();
497 void CCLayerTreeHost::scheduleComposite()
499 m_client
->scheduleComposite();
502 bool CCLayerTreeHost::initializeRendererIfNeeded()
504 if (!m_rendererInitialized
) {
505 initializeRenderer();
506 // If we couldn't initialize, then bail since we're returning to software mode.
507 if (!m_rendererInitialized
)
511 if (recreateContext() != RecreateSucceeded
)
517 void CCLayerTreeHost::updateLayers(CCTextureUpdateQueue
& queue
, size_t memoryAllocationLimitBytes
)
519 ASSERT(m_rendererInitialized
);
520 ASSERT(memoryAllocationLimitBytes
);
525 if (layoutViewportSize().isEmpty())
528 m_contentsTextureManager
->setMaxMemoryLimitBytes(memoryAllocationLimitBytes
);
530 updateLayers(rootLayer(), queue
);
533 static void setScale(LayerChromium
* layer
, float deviceScaleFactor
, float pageScaleFactor
)
535 if (layer
->boundsContainPageScale())
536 layer
->setContentsScale(deviceScaleFactor
);
538 layer
->setContentsScale(deviceScaleFactor
* pageScaleFactor
);
541 static LayerChromium
* findFirstScrollableLayer(LayerChromium
* layer
)
546 if (layer
->scrollable())
549 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
550 LayerChromium
* found
= findFirstScrollableLayer(layer
->children()[i
].get());
558 static void updateLayerScale(LayerChromium
* layer
, float deviceScaleFactor
, float pageScaleFactor
)
560 setScale(layer
, deviceScaleFactor
, pageScaleFactor
);
562 LayerChromium
* maskLayer
= layer
->maskLayer();
564 setScale(maskLayer
, deviceScaleFactor
, pageScaleFactor
);
566 LayerChromium
* replicaMaskLayer
= layer
->replicaLayer() ? layer
->replicaLayer()->maskLayer() : 0;
567 if (replicaMaskLayer
)
568 setScale(replicaMaskLayer
, deviceScaleFactor
, pageScaleFactor
);
570 const std::vector
<scoped_refptr
<LayerChromium
> >& children
= layer
->children();
571 for (unsigned int i
= 0; i
< children
.size(); ++i
)
572 updateLayerScale(children
[i
].get(), deviceScaleFactor
, pageScaleFactor
);
575 void CCLayerTreeHost::updateLayers(LayerChromium
* rootLayer
, CCTextureUpdateQueue
& queue
)
577 TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers");
579 updateLayerScale(rootLayer
, m_deviceScaleFactor
, m_pageScaleFactor
);
581 LayerList updateList
;
584 if (CCSettings::pageScalePinchZoomEnabled()) {
585 LayerChromium
* rootScroll
= findFirstScrollableLayer(rootLayer
);
587 rootScroll
->setImplTransform(m_implTransform
);
590 TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc");
591 CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer
, deviceViewportSize(), m_deviceScaleFactor
, rendererCapabilities().maxTextureSize
, updateList
);
594 // Reset partial texture update requests.
595 m_partialTextureUpdateRequests
= 0;
597 bool needMoreUpdates
= paintLayerContents(updateList
, queue
);
598 if (m_triggerIdleUpdates
&& needMoreUpdates
)
601 for (size_t i
= 0; i
< updateList
.size(); ++i
)
602 updateList
[i
]->clearRenderSurface();
605 void CCLayerTreeHost::setPrioritiesForSurfaces(size_t surfaceMemoryBytes
)
607 // Surfaces have a place holder for their memory since they are managed
608 // independantly but should still be tracked and reduce other memory usage.
609 m_surfaceMemoryPlaceholder
->setTextureManager(m_contentsTextureManager
.get());
610 m_surfaceMemoryPlaceholder
->setRequestPriority(CCPriorityCalculator::renderSurfacePriority());
611 m_surfaceMemoryPlaceholder
->setToSelfManagedMemoryPlaceholder(surfaceMemoryBytes
);
614 void CCLayerTreeHost::setPrioritiesForLayers(const LayerList
& updateList
)
616 // Use BackToFront since it's cheap and this isn't order-dependent.
617 typedef CCLayerIterator
<LayerChromium
, LayerList
, RenderSurfaceChromium
, CCLayerIteratorActions::BackToFront
> CCLayerIteratorType
;
619 CCPriorityCalculator calculator
;
620 CCLayerIteratorType end
= CCLayerIteratorType::end(&updateList
);
621 for (CCLayerIteratorType it
= CCLayerIteratorType::begin(&updateList
); it
!= end
; ++it
) {
622 if (it
.representsItself())
623 it
->setTexturePriorities(calculator
);
624 else if (it
.representsTargetRenderSurface()) {
626 it
->maskLayer()->setTexturePriorities(calculator
);
627 if (it
->replicaLayer() && it
->replicaLayer()->maskLayer())
628 it
->replicaLayer()->maskLayer()->setTexturePriorities(calculator
);
633 void CCLayerTreeHost::prioritizeTextures(const LayerList
& renderSurfaceLayerList
, CCOverdrawMetrics
& metrics
)
635 m_contentsTextureManager
->clearPriorities();
637 size_t memoryForRenderSurfacesMetric
= calculateMemoryForRenderSurfaces(renderSurfaceLayerList
);
639 setPrioritiesForLayers(renderSurfaceLayerList
);
640 setPrioritiesForSurfaces(memoryForRenderSurfacesMetric
);
642 metrics
.didUseContentsTextureMemoryBytes(m_contentsTextureManager
->memoryAboveCutoffBytes());
643 metrics
.didUseRenderSurfaceTextureMemoryBytes(memoryForRenderSurfacesMetric
);
645 m_contentsTextureManager
->prioritizeTextures();
648 size_t CCLayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList
& updateList
)
650 size_t readbackBytes
= 0;
651 size_t maxBackgroundTextureBytes
= 0;
652 size_t contentsTextureBytes
= 0;
654 // Start iteration at 1 to skip the root surface as it does not have a texture cost.
655 for (size_t i
= 1; i
< updateList
.size(); ++i
) {
656 LayerChromium
* renderSurfaceLayer
= updateList
[i
].get();
657 RenderSurfaceChromium
* renderSurface
= renderSurfaceLayer
->renderSurface();
659 size_t bytes
= CCTexture::memorySizeBytes(renderSurface
->contentRect().size(), GraphicsContext3D::RGBA
);
660 contentsTextureBytes
+= bytes
;
662 if (renderSurfaceLayer
->backgroundFilters().isEmpty())
665 if (bytes
> maxBackgroundTextureBytes
)
666 maxBackgroundTextureBytes
= bytes
;
668 readbackBytes
= CCTexture::memorySizeBytes(m_deviceViewportSize
, GraphicsContext3D::RGBA
);
670 return readbackBytes
+ maxBackgroundTextureBytes
+ contentsTextureBytes
;
673 bool CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium
* renderSurfaceLayer
, CCTextureUpdateQueue
& queue
)
675 // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
676 // in code, we already know that at least something will be drawn into this render surface, so the
677 // mask and replica should be painted.
679 bool needMoreUpdates
= false;
680 LayerChromium
* maskLayer
= renderSurfaceLayer
->maskLayer();
682 maskLayer
->update(queue
, 0, m_renderingStats
);
683 needMoreUpdates
|= maskLayer
->needMoreUpdates();
686 LayerChromium
* replicaMaskLayer
= renderSurfaceLayer
->replicaLayer() ? renderSurfaceLayer
->replicaLayer()->maskLayer() : 0;
687 if (replicaMaskLayer
) {
688 replicaMaskLayer
->update(queue
, 0, m_renderingStats
);
689 needMoreUpdates
|= replicaMaskLayer
->needMoreUpdates();
691 return needMoreUpdates
;
694 bool CCLayerTreeHost::paintLayerContents(const LayerList
& renderSurfaceLayerList
, CCTextureUpdateQueue
& queue
)
696 // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
697 typedef CCLayerIterator
<LayerChromium
, LayerList
, RenderSurfaceChromium
, CCLayerIteratorActions::FrontToBack
> CCLayerIteratorType
;
699 bool needMoreUpdates
= false;
700 bool recordMetricsForFrame
= true; // FIXME: In the future, disable this when about:tracing is off.
701 CCOcclusionTracker
occlusionTracker(m_rootLayer
->renderSurface()->contentRect(), recordMetricsForFrame
);
702 occlusionTracker
.setMinimumTrackingSize(m_settings
.minimumOcclusionTrackingSize
);
704 prioritizeTextures(renderSurfaceLayerList
, occlusionTracker
.overdrawMetrics());
706 CCLayerIteratorType end
= CCLayerIteratorType::end(&renderSurfaceLayerList
);
707 for (CCLayerIteratorType it
= CCLayerIteratorType::begin(&renderSurfaceLayerList
); it
!= end
; ++it
) {
708 occlusionTracker
.enterLayer(it
);
710 if (it
.representsTargetRenderSurface()) {
711 ASSERT(it
->renderSurface()->drawOpacity() || it
->renderSurface()->drawOpacityIsAnimating());
712 needMoreUpdates
|= paintMasksForRenderSurface(*it
, queue
);
713 } else if (it
.representsItself()) {
714 ASSERT(!it
->bounds().isEmpty());
715 it
->update(queue
, &occlusionTracker
, m_renderingStats
);
716 needMoreUpdates
|= it
->needMoreUpdates();
719 occlusionTracker
.leaveLayer(it
);
722 occlusionTracker
.overdrawMetrics().recordMetrics(this);
724 return needMoreUpdates
;
727 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet
& info
)
732 LayerChromium
* rootScrollLayer
= findFirstScrollableLayer(m_rootLayer
.get());
733 IntSize rootScrollDelta
;
735 for (size_t i
= 0; i
< info
.scrolls
.size(); ++i
) {
736 LayerChromium
* layer
= CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayer
.get(), info
.scrolls
[i
].layerId
);
739 if (layer
== rootScrollLayer
)
740 rootScrollDelta
+= info
.scrolls
[i
].scrollDelta
;
742 layer
->setScrollPosition(layer
->scrollPosition() + info
.scrolls
[i
].scrollDelta
);
744 if (!rootScrollDelta
.isZero() || info
.pageScaleDelta
!= 1)
745 m_client
->applyScrollAndScale(rootScrollDelta
, info
.pageScaleDelta
);
748 void CCLayerTreeHost::setImplTransform(const WebKit::WebTransformationMatrix
& transform
)
750 m_implTransform
= transform
;
753 void CCLayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D
* context
)
759 RateLimiterMap::iterator it
= m_rateLimiters
.find(context
);
760 if (it
!= m_rateLimiters
.end())
763 scoped_refptr
<RateLimiter
> rateLimiter
= RateLimiter::create(context
, this);
764 m_rateLimiters
[context
] = rateLimiter
;
765 rateLimiter
->start();
769 void CCLayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D
* context
)
771 RateLimiterMap::iterator it
= m_rateLimiters
.find(context
);
772 if (it
!= m_rateLimiters
.end()) {
774 m_rateLimiters
.erase(it
);
778 void CCLayerTreeHost::rateLimit()
780 // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing
781 // context, and therefore for the SwapBuffers.
782 m_proxy
->forceSerializeOnSwapBuffers();
785 bool CCLayerTreeHost::bufferedUpdates()
787 return m_settings
.maxPartialTextureUpdates
!= numeric_limits
<size_t>::max();
790 bool CCLayerTreeHost::requestPartialTextureUpdate()
792 if (m_partialTextureUpdateRequests
>= m_settings
.maxPartialTextureUpdates
)
795 m_partialTextureUpdateRequests
++;
799 void CCLayerTreeHost::deleteTextureAfterCommit(scoped_ptr
<CCPrioritizedTexture
> texture
)
801 m_deleteTextureAfterCommitList
.append(texture
.Pass());
804 void CCLayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor
)
806 if (deviceScaleFactor
== m_deviceScaleFactor
)
808 m_deviceScaleFactor
= deviceScaleFactor
;
813 void CCLayerTreeHost::animateLayers(double monotonicTime
)
815 if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers
)
818 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
819 m_needsAnimateLayers
= animateLayersRecursive(m_rootLayer
.get(), monotonicTime
);
822 bool CCLayerTreeHost::animateLayersRecursive(LayerChromium
* current
, double monotonicTime
)
827 bool subtreeNeedsAnimateLayers
= false;
828 CCLayerAnimationController
* currentController
= current
->layerAnimationController();
829 currentController
->animate(monotonicTime
, 0);
831 // If the current controller still has an active animation, we must continue animating layers.
832 if (currentController
->hasActiveAnimation())
833 subtreeNeedsAnimateLayers
= true;
835 for (size_t i
= 0; i
< current
->children().size(); ++i
) {
836 if (animateLayersRecursive(current
->children()[i
].get(), monotonicTime
))
837 subtreeNeedsAnimateLayers
= true;
840 return subtreeNeedsAnimateLayers
;
843 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector
& events
, LayerChromium
* layer
, double wallClockTime
)
848 for (size_t eventIndex
= 0; eventIndex
< events
.size(); ++eventIndex
) {
849 if (layer
->id() == events
[eventIndex
].layerId
) {
850 if (events
[eventIndex
].type
== CCAnimationEvent::Started
)
851 layer
->notifyAnimationStarted(events
[eventIndex
], wallClockTime
);
853 layer
->notifyAnimationFinished(wallClockTime
);
857 for (size_t childIndex
= 0; childIndex
< layer
->children().size(); ++childIndex
)
858 setAnimationEventsRecursive(events
, layer
->children()[childIndex
].get(), wallClockTime
);