| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "config.h" | |
| 6 | |
| 7 #include "CCLayerTreeHost.h" | |
| 8 | |
| 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" | |
| 27 | |
| 28 using namespace std; | |
| 29 using WebKit::WebTransformationMatrix; | |
| 30 | |
| 31 namespace { | |
| 32 static int numLayerTreeInstances; | |
| 33 } | |
| 34 | |
| 35 namespace cc { | |
| 36 | |
| 37 bool CCLayerTreeHost::s_needsFilterContext = false; | |
| 38 | |
| 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) | |
| 50 , refreshRate(0) | |
| 51 , maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) | |
| 52 , defaultTileSize(IntSize(256, 256)) | |
| 53 , maxUntiledLayerSize(IntSize(512, 512)) | |
| 54 , minimumOcclusionTrackingSize(IntSize(160, 160)) | |
| 55 { | |
| 56 } | |
| 57 | |
| 58 CCLayerTreeSettings::~CCLayerTreeSettings() | |
| 59 { | |
| 60 } | |
| 61 | |
| 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) | |
| 72 , maxTextureSize(0) | |
| 73 { | |
| 74 } | |
| 75 | |
| 76 RendererCapabilities::~RendererCapabilities() | |
| 77 { | |
| 78 } | |
| 79 | |
| 80 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists() | |
| 81 { | |
| 82 return numLayerTreeInstances > 0; | |
| 83 } | |
| 84 | |
| 85 scoped_ptr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* clien
t, const CCLayerTreeSettings& settings) | |
| 86 { | |
| 87 scoped_ptr<CCLayerTreeHost> layerTreeHost(new CCLayerTreeHost(client, settin
gs)); | |
| 88 if (!layerTreeHost->initialize()) | |
| 89 return scoped_ptr<CCLayerTreeHost>(); | |
| 90 return layerTreeHost.Pass(); | |
| 91 } | |
| 92 | |
| 93 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCLayerTre
eSettings& settings) | |
| 94 : m_animating(false) | |
| 95 , m_needsAnimateLayers(false) | |
| 96 , m_client(client) | |
| 97 , m_commitNumber(0) | |
| 98 , m_renderingStats() | |
| 99 , m_rendererInitialized(false) | |
| 100 , m_contextLost(false) | |
| 101 , m_numTimesRecreateShouldFail(0) | |
| 102 , m_numFailedRecreateAttempts(0) | |
| 103 , m_settings(settings) | |
| 104 , m_deviceScaleFactor(1) | |
| 105 , m_visible(true) | |
| 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) | |
| 113 { | |
| 114 ASSERT(CCProxy::isMainThread()); | |
| 115 numLayerTreeInstances++; | |
| 116 } | |
| 117 | |
| 118 bool CCLayerTreeHost::initialize() | |
| 119 { | |
| 120 TRACE_EVENT0("cc", "CCLayerTreeHost::initialize"); | |
| 121 | |
| 122 if (CCProxy::hasImplThread()) | |
| 123 m_proxy = CCThreadProxy::create(this); | |
| 124 else | |
| 125 m_proxy = CCSingleThreadProxy::create(this); | |
| 126 m_proxy->start(); | |
| 127 | |
| 128 return m_proxy->initializeContext(); | |
| 129 } | |
| 130 | |
| 131 CCLayerTreeHost::~CCLayerTreeHost() | |
| 132 { | |
| 133 if (m_rootLayer) | |
| 134 m_rootLayer->setLayerTreeHost(0); | |
| 135 ASSERT(CCProxy::isMainThread()); | |
| 136 TRACE_EVENT0("cc", "CCLayerTreeHost::~CCLayerTreeHost"); | |
| 137 ASSERT(m_proxy.get()); | |
| 138 m_proxy->stop(); | |
| 139 m_proxy.reset(); | |
| 140 numLayerTreeInstances--; | |
| 141 RateLimiterMap::iterator it = m_rateLimiters.begin(); | |
| 142 if (it != m_rateLimiters.end()) | |
| 143 it->second->stop(); | |
| 144 } | |
| 145 | |
| 146 void CCLayerTreeHost::setSurfaceReady() | |
| 147 { | |
| 148 m_proxy->setSurfaceReady(); | |
| 149 } | |
| 150 | |
| 151 void CCLayerTreeHost::initializeRenderer() | |
| 152 { | |
| 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 con
text. | |
| 156 m_client->didRecreateOutputSurface(false); | |
| 157 return; | |
| 158 } | |
| 159 | |
| 160 // Update m_settings based on capabilities that we got back from the rendere
r. | |
| 161 m_settings.acceleratePainting = m_proxy->rendererCapabilities().usingAcceler
atedPainting; | |
| 162 | |
| 163 // Update m_settings based on partial update capability. | |
| 164 m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdate
s, m_proxy->maxPartialTextureUpdates()); | |
| 165 | |
| 166 m_contentsTextureManager = CCPrioritizedTextureManager::create(0, m_proxy->r
endererCapabilities().maxTextureSize, CCRenderer::ContentPool); | |
| 167 m_surfaceMemoryPlaceholder = m_contentsTextureManager->createTexture(IntSize
(), GraphicsContext3D::RGBA); | |
| 168 | |
| 169 m_rendererInitialized = true; | |
| 170 | |
| 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)); | |
| 175 } | |
| 176 | |
| 177 CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext() | |
| 178 { | |
| 179 TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext"); | |
| 180 ASSERT(m_contextLost); | |
| 181 | |
| 182 bool recreated = false; | |
| 183 if (!m_numTimesRecreateShouldFail) | |
| 184 recreated = m_proxy->recreateContext(); | |
| 185 else | |
| 186 m_numTimesRecreateShouldFail--; | |
| 187 | |
| 188 if (recreated) { | |
| 189 m_client->didRecreateOutputSurface(true); | |
| 190 m_contextLost = false; | |
| 191 return RecreateSucceeded; | |
| 192 } | |
| 193 | |
| 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 requesti
ng | |
| 200 // another commit. | |
| 201 if (!CCProxy::hasImplThread()) | |
| 202 setNeedsCommit(); | |
| 203 return RecreateFailedButTryAgain; | |
| 204 } | |
| 205 | |
| 206 // We have tried too many times to recreate the context. Tell the host to fa
ll | |
| 207 // back to software rendering. | |
| 208 m_client->didRecreateOutputSurface(false); | |
| 209 return RecreateFailedAndGaveUp; | |
| 210 } | |
| 211 | |
| 212 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(CCResourceProvider* res
ourceProvider) | |
| 213 { | |
| 214 ASSERT(CCProxy::isImplThread()); | |
| 215 if (m_rendererInitialized) | |
| 216 m_contentsTextureManager->clearAllMemory(resourceProvider); | |
| 217 } | |
| 218 | |
| 219 void CCLayerTreeHost::acquireLayerTextures() | |
| 220 { | |
| 221 ASSERT(CCProxy::isMainThread()); | |
| 222 m_proxy->acquireLayerTextures(); | |
| 223 } | |
| 224 | |
| 225 void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime) | |
| 226 { | |
| 227 m_animating = true; | |
| 228 m_client->animate(monotonicFrameBeginTime); | |
| 229 animateLayers(monotonicFrameBeginTime); | |
| 230 m_animating = false; | |
| 231 | |
| 232 m_renderingStats.numAnimationFrames++; | |
| 233 } | |
| 234 | |
| 235 void CCLayerTreeHost::layout() | |
| 236 { | |
| 237 m_client->layout(); | |
| 238 } | |
| 239 | |
| 240 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) | |
| 241 { | |
| 242 ASSERT(CCProxy::isImplThread()); | |
| 243 TRACE_EVENT0("cc", "CCLayerTreeHost::commitTo"); | |
| 244 | |
| 245 m_contentsTextureManager->reduceMemory(hostImpl->resourceProvider()); | |
| 246 } | |
| 247 | |
| 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 LayerChrom
ium, | |
| 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) | |
| 254 { | |
| 255 ASSERT(CCProxy::isImplThread()); | |
| 256 | |
| 257 hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostI
mpl->detachLayerTree(), hostImpl)); | |
| 258 | |
| 259 if (m_rootLayer && m_hudLayer) | |
| 260 hostImpl->setHudLayer(static_cast<CCHeadsUpDisplayLayerImpl*>(CCLayerTre
eHostCommon::findLayerInSubtree(hostImpl->rootLayer(), m_hudLayer->id()))); | |
| 261 else | |
| 262 hostImpl->setHudLayer(0); | |
| 263 | |
| 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(); | |
| 268 | |
| 269 hostImpl->setSourceFrameNumber(commitNumber()); | |
| 270 hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize()); | |
| 271 hostImpl->setDeviceScaleFactor(deviceScaleFactor()); | |
| 272 hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFacto
r, m_maxPageScaleFactor); | |
| 273 hostImpl->setBackgroundColor(m_backgroundColor); | |
| 274 hostImpl->setHasTransparentBackground(m_hasTransparentBackground); | |
| 275 | |
| 276 m_commitNumber++; | |
| 277 } | |
| 278 | |
| 279 void CCLayerTreeHost::setFontAtlas(scoped_ptr<CCFontAtlas> fontAtlas) | |
| 280 { | |
| 281 m_fontAtlas = fontAtlas.Pass(); | |
| 282 setNeedsCommit(); | |
| 283 } | |
| 284 | |
| 285 void CCLayerTreeHost::willCommit() | |
| 286 { | |
| 287 m_client->willCommit(); | |
| 288 if (m_rootLayer && m_settings.showDebugInfo()) { | |
| 289 if (!m_hudLayer) | |
| 290 m_hudLayer = HeadsUpDisplayLayerChromium::create(); | |
| 291 | |
| 292 if (m_fontAtlas.get()) | |
| 293 m_hudLayer->setFontAtlas(m_fontAtlas.Pass()); | |
| 294 | |
| 295 if (!m_hudLayer->parent()) | |
| 296 m_rootLayer->addChild(m_hudLayer); | |
| 297 } | |
| 298 } | |
| 299 | |
| 300 void CCLayerTreeHost::commitComplete() | |
| 301 { | |
| 302 m_deleteTextureAfterCommitList.clear(); | |
| 303 m_client->didCommit(); | |
| 304 } | |
| 305 | |
| 306 scoped_ptr<CCGraphicsContext> CCLayerTreeHost::createContext() | |
| 307 { | |
| 308 return m_client->createOutputSurface(); | |
| 309 } | |
| 310 | |
| 311 scoped_ptr<CCInputHandler> CCLayerTreeHost::createInputHandler() | |
| 312 { | |
| 313 return m_client->createInputHandler(); | |
| 314 } | |
| 315 | |
| 316 scoped_ptr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayer
TreeHostImplClient* client) | |
| 317 { | |
| 318 return CCLayerTreeHostImpl::create(m_settings, client); | |
| 319 } | |
| 320 | |
| 321 void CCLayerTreeHost::didLoseContext() | |
| 322 { | |
| 323 TRACE_EVENT0("cc", "CCLayerTreeHost::didLoseContext"); | |
| 324 ASSERT(CCProxy::isMainThread()); | |
| 325 m_contextLost = true; | |
| 326 m_numFailedRecreateAttempts = 0; | |
| 327 setNeedsCommit(); | |
| 328 } | |
| 329 | |
| 330 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) | |
| 331 { | |
| 332 m_triggerIdleUpdates = false; | |
| 333 bool ret = m_proxy->compositeAndReadback(pixels, rect); | |
| 334 m_triggerIdleUpdates = true; | |
| 335 return ret; | |
| 336 } | |
| 337 | |
| 338 void CCLayerTreeHost::finishAllRendering() | |
| 339 { | |
| 340 if (!m_rendererInitialized) | |
| 341 return; | |
| 342 m_proxy->finishAllRendering(); | |
| 343 } | |
| 344 | |
| 345 void CCLayerTreeHost::renderingStats(CCRenderingStats* stats) const | |
| 346 { | |
| 347 *stats = m_renderingStats; | |
| 348 m_proxy->renderingStats(stats); | |
| 349 } | |
| 350 | |
| 351 const RendererCapabilities& CCLayerTreeHost::rendererCapabilities() const | |
| 352 { | |
| 353 return m_proxy->rendererCapabilities(); | |
| 354 } | |
| 355 | |
| 356 void CCLayerTreeHost::setNeedsAnimate() | |
| 357 { | |
| 358 ASSERT(CCProxy::hasImplThread()); | |
| 359 m_proxy->setNeedsAnimate(); | |
| 360 } | |
| 361 | |
| 362 void CCLayerTreeHost::setNeedsCommit() | |
| 363 { | |
| 364 m_proxy->setNeedsCommit(); | |
| 365 } | |
| 366 | |
| 367 void CCLayerTreeHost::setNeedsRedraw() | |
| 368 { | |
| 369 m_proxy->setNeedsRedraw(); | |
| 370 if (!CCThreadProxy::implThread()) | |
| 371 m_client->scheduleComposite(); | |
| 372 } | |
| 373 | |
| 374 bool CCLayerTreeHost::commitRequested() const | |
| 375 { | |
| 376 return m_proxy->commitRequested(); | |
| 377 } | |
| 378 | |
| 379 void CCLayerTreeHost::setAnimationEvents(scoped_ptr<CCAnimationEventsVector> eve
nts, double wallClockTime) | |
| 380 { | |
| 381 ASSERT(CCThreadProxy::isMainThread()); | |
| 382 setAnimationEventsRecursive(*events.get(), m_rootLayer.get(), wallClockTime)
; | |
| 383 } | |
| 384 | |
| 385 void CCLayerTreeHost::didAddAnimation() | |
| 386 { | |
| 387 m_needsAnimateLayers = true; | |
| 388 m_proxy->didAddAnimation(); | |
| 389 } | |
| 390 | |
| 391 void CCLayerTreeHost::setRootLayer(scoped_refptr<LayerChromium> rootLayer) | |
| 392 { | |
| 393 if (m_rootLayer == rootLayer) | |
| 394 return; | |
| 395 | |
| 396 if (m_rootLayer) | |
| 397 m_rootLayer->setLayerTreeHost(0); | |
| 398 m_rootLayer = rootLayer; | |
| 399 if (m_rootLayer) | |
| 400 m_rootLayer->setLayerTreeHost(this); | |
| 401 | |
| 402 if (m_hudLayer) | |
| 403 m_hudLayer->removeFromParent(); | |
| 404 | |
| 405 setNeedsCommit(); | |
| 406 } | |
| 407 | |
| 408 void CCLayerTreeHost::setViewportSize(const IntSize& layoutViewportSize, const I
ntSize& deviceViewportSize) | |
| 409 { | |
| 410 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_de
viceViewportSize) | |
| 411 return; | |
| 412 | |
| 413 m_layoutViewportSize = layoutViewportSize; | |
| 414 m_deviceViewportSize = deviceViewportSize; | |
| 415 | |
| 416 setNeedsCommit(); | |
| 417 } | |
| 418 | |
| 419 void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float m
inPageScaleFactor, float maxPageScaleFactor) | |
| 420 { | |
| 421 if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageS
caleFactor && maxPageScaleFactor == m_maxPageScaleFactor) | |
| 422 return; | |
| 423 | |
| 424 m_pageScaleFactor = pageScaleFactor; | |
| 425 m_minPageScaleFactor = minPageScaleFactor; | |
| 426 m_maxPageScaleFactor = maxPageScaleFactor; | |
| 427 setNeedsCommit(); | |
| 428 } | |
| 429 | |
| 430 void CCLayerTreeHost::setVisible(bool visible) | |
| 431 { | |
| 432 if (m_visible == visible) | |
| 433 return; | |
| 434 m_visible = visible; | |
| 435 m_proxy->setVisible(visible); | |
| 436 } | |
| 437 | |
| 438 void CCLayerTreeHost::reduceContentsTexturesMemoryOnImplThread(size_t limitBytes
, CCResourceProvider* resourceProvider) | |
| 439 { | |
| 440 ASSERT(CCProxy::isImplThread()); | |
| 441 ASSERT(m_contentsTextureManager.get()); | |
| 442 m_contentsTextureManager->reduceMemoryOnImplThread(limitBytes, resourceProvi
der); | |
| 443 } | |
| 444 | |
| 445 bool CCLayerTreeHost::evictedContentsTexturesBackingsExist() const | |
| 446 { | |
| 447 ASSERT(CCProxy::isImplThread()); | |
| 448 ASSERT(m_contentsTextureManager.get()); | |
| 449 return m_contentsTextureManager->evictedBackingsExist(); | |
| 450 } | |
| 451 | |
| 452 void CCLayerTreeHost::getEvictedContentTexturesBackings(CCPrioritizedTextureMana
ger::BackingVector& evictedBackings) | |
| 453 { | |
| 454 ASSERT(CCProxy::isImplThread()); | |
| 455 evictedBackings.clear(); | |
| 456 if (m_rendererInitialized) | |
| 457 m_contentsTextureManager->getEvictedBackings(evictedBackings); | |
| 458 } | |
| 459 | |
| 460 void CCLayerTreeHost::unlinkEvictedContentTexturesBackings(const CCPrioritizedTe
xtureManager::BackingVector& evictedBackings) | |
| 461 { | |
| 462 ASSERT(CCProxy::isMainThread()); | |
| 463 ASSERT(m_contentsTextureManager.get()); | |
| 464 m_contentsTextureManager->unlinkEvictedBackings(evictedBackings); | |
| 465 } | |
| 466 | |
| 467 bool CCLayerTreeHost::deleteEvictedContentTexturesBackings() | |
| 468 { | |
| 469 ASSERT(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked()); | |
| 470 ASSERT(m_contentsTextureManager.get()); | |
| 471 return m_contentsTextureManager->deleteEvictedBackings(); | |
| 472 } | |
| 473 | |
| 474 void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, boo
l useAnchor, float scale, double durationSec) | |
| 475 { | |
| 476 m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationS
ec); | |
| 477 } | |
| 478 | |
| 479 void CCLayerTreeHost::loseContext(int numTimes) | |
| 480 { | |
| 481 TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", num
Times); | |
| 482 m_numTimesRecreateShouldFail = numTimes - 1; | |
| 483 m_proxy->loseContext(); | |
| 484 } | |
| 485 | |
| 486 CCPrioritizedTextureManager* CCLayerTreeHost::contentsTextureManager() const | |
| 487 { | |
| 488 return m_contentsTextureManager.get(); | |
| 489 } | |
| 490 | |
| 491 void CCLayerTreeHost::composite() | |
| 492 { | |
| 493 ASSERT(!CCThreadProxy::implThread()); | |
| 494 static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately(); | |
| 495 } | |
| 496 | |
| 497 void CCLayerTreeHost::scheduleComposite() | |
| 498 { | |
| 499 m_client->scheduleComposite(); | |
| 500 } | |
| 501 | |
| 502 bool CCLayerTreeHost::initializeRendererIfNeeded() | |
| 503 { | |
| 504 if (!m_rendererInitialized) { | |
| 505 initializeRenderer(); | |
| 506 // If we couldn't initialize, then bail since we're returning to softwar
e mode. | |
| 507 if (!m_rendererInitialized) | |
| 508 return false; | |
| 509 } | |
| 510 if (m_contextLost) { | |
| 511 if (recreateContext() != RecreateSucceeded) | |
| 512 return false; | |
| 513 } | |
| 514 return true; | |
| 515 } | |
| 516 | |
| 517 void CCLayerTreeHost::updateLayers(CCTextureUpdateQueue& queue, size_t memoryAll
ocationLimitBytes) | |
| 518 { | |
| 519 ASSERT(m_rendererInitialized); | |
| 520 ASSERT(memoryAllocationLimitBytes); | |
| 521 | |
| 522 if (!rootLayer()) | |
| 523 return; | |
| 524 | |
| 525 if (layoutViewportSize().isEmpty()) | |
| 526 return; | |
| 527 | |
| 528 m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes)
; | |
| 529 | |
| 530 updateLayers(rootLayer(), queue); | |
| 531 } | |
| 532 | |
| 533 static void setScale(LayerChromium* layer, float deviceScaleFactor, float pageSc
aleFactor) | |
| 534 { | |
| 535 if (layer->boundsContainPageScale()) | |
| 536 layer->setContentsScale(deviceScaleFactor); | |
| 537 else | |
| 538 layer->setContentsScale(deviceScaleFactor * pageScaleFactor); | |
| 539 } | |
| 540 | |
| 541 static LayerChromium* findFirstScrollableLayer(LayerChromium* layer) | |
| 542 { | |
| 543 if (!layer) | |
| 544 return 0; | |
| 545 | |
| 546 if (layer->scrollable()) | |
| 547 return layer; | |
| 548 | |
| 549 for (size_t i = 0; i < layer->children().size(); ++i) { | |
| 550 LayerChromium* found = findFirstScrollableLayer(layer->children()[i].get
()); | |
| 551 if (found) | |
| 552 return found; | |
| 553 } | |
| 554 | |
| 555 return 0; | |
| 556 } | |
| 557 | |
| 558 static void updateLayerScale(LayerChromium* layer, float deviceScaleFactor, floa
t pageScaleFactor) | |
| 559 { | |
| 560 setScale(layer, deviceScaleFactor, pageScaleFactor); | |
| 561 | |
| 562 LayerChromium* maskLayer = layer->maskLayer(); | |
| 563 if (maskLayer) | |
| 564 setScale(maskLayer, deviceScaleFactor, pageScaleFactor); | |
| 565 | |
| 566 LayerChromium* replicaMaskLayer = layer->replicaLayer() ? layer->replicaLaye
r()->maskLayer() : 0; | |
| 567 if (replicaMaskLayer) | |
| 568 setScale(replicaMaskLayer, deviceScaleFactor, pageScaleFactor); | |
| 569 | |
| 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); | |
| 573 } | |
| 574 | |
| 575 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdateQueu
e& queue) | |
| 576 { | |
| 577 TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers"); | |
| 578 | |
| 579 updateLayerScale(rootLayer, m_deviceScaleFactor, m_pageScaleFactor); | |
| 580 | |
| 581 LayerList updateList; | |
| 582 | |
| 583 { | |
| 584 if (CCSettings::pageScalePinchZoomEnabled()) { | |
| 585 LayerChromium* rootScroll = findFirstScrollableLayer(rootLayer); | |
| 586 if (rootScroll) | |
| 587 rootScroll->setImplTransform(m_implTransform); | |
| 588 } | |
| 589 | |
| 590 TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc"); | |
| 591 CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewport
Size(), m_deviceScaleFactor, rendererCapabilities().maxTextureSize, updateList); | |
| 592 } | |
| 593 | |
| 594 // Reset partial texture update requests. | |
| 595 m_partialTextureUpdateRequests = 0; | |
| 596 | |
| 597 bool needMoreUpdates = paintLayerContents(updateList, queue); | |
| 598 if (m_triggerIdleUpdates && needMoreUpdates) | |
| 599 setNeedsCommit(); | |
| 600 | |
| 601 for (size_t i = 0; i < updateList.size(); ++i) | |
| 602 updateList[i]->clearRenderSurface(); | |
| 603 } | |
| 604 | |
| 605 void CCLayerTreeHost::setPrioritiesForSurfaces(size_t surfaceMemoryBytes) | |
| 606 { | |
| 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::renderS
urfacePriority()); | |
| 611 m_surfaceMemoryPlaceholder->setToSelfManagedMemoryPlaceholder(surfaceMemoryB
ytes); | |
| 612 } | |
| 613 | |
| 614 void CCLayerTreeHost::setPrioritiesForLayers(const LayerList& updateList) | |
| 615 { | |
| 616 // Use BackToFront since it's cheap and this isn't order-dependent. | |
| 617 typedef CCLayerIterator<LayerChromium, LayerList, RenderSurfaceChromium, CCL
ayerIteratorActions::BackToFront> CCLayerIteratorType; | |
| 618 | |
| 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()) { | |
| 625 if (it->maskLayer()) | |
| 626 it->maskLayer()->setTexturePriorities(calculator); | |
| 627 if (it->replicaLayer() && it->replicaLayer()->maskLayer()) | |
| 628 it->replicaLayer()->maskLayer()->setTexturePriorities(calculator
); | |
| 629 } | |
| 630 } | |
| 631 } | |
| 632 | |
| 633 void CCLayerTreeHost::prioritizeTextures(const LayerList& renderSurfaceLayerList
, CCOverdrawMetrics& metrics) | |
| 634 { | |
| 635 m_contentsTextureManager->clearPriorities(); | |
| 636 | |
| 637 size_t memoryForRenderSurfacesMetric = calculateMemoryForRenderSurfaces(rend
erSurfaceLayerList); | |
| 638 | |
| 639 setPrioritiesForLayers(renderSurfaceLayerList); | |
| 640 setPrioritiesForSurfaces(memoryForRenderSurfacesMetric); | |
| 641 | |
| 642 metrics.didUseContentsTextureMemoryBytes(m_contentsTextureManager->memoryAbo
veCutoffBytes()); | |
| 643 metrics.didUseRenderSurfaceTextureMemoryBytes(memoryForRenderSurfacesMetric)
; | |
| 644 | |
| 645 m_contentsTextureManager->prioritizeTextures(); | |
| 646 } | |
| 647 | |
| 648 size_t CCLayerTreeHost::calculateMemoryForRenderSurfaces(const LayerList& update
List) | |
| 649 { | |
| 650 size_t readbackBytes = 0; | |
| 651 size_t maxBackgroundTextureBytes = 0; | |
| 652 size_t contentsTextureBytes = 0; | |
| 653 | |
| 654 // Start iteration at 1 to skip the root surface as it does not have a textu
re cost. | |
| 655 for (size_t i = 1; i < updateList.size(); ++i) { | |
| 656 LayerChromium* renderSurfaceLayer = updateList[i].get(); | |
| 657 RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface
(); | |
| 658 | |
| 659 size_t bytes = CCTexture::memorySizeBytes(renderSurface->contentRect().s
ize(), GraphicsContext3D::RGBA); | |
| 660 contentsTextureBytes += bytes; | |
| 661 | |
| 662 if (renderSurfaceLayer->backgroundFilters().isEmpty()) | |
| 663 continue; | |
| 664 | |
| 665 if (bytes > maxBackgroundTextureBytes) | |
| 666 maxBackgroundTextureBytes = bytes; | |
| 667 if (!readbackBytes) | |
| 668 readbackBytes = CCTexture::memorySizeBytes(m_deviceViewportSize, Gra
phicsContext3D::RGBA); | |
| 669 } | |
| 670 return readbackBytes + maxBackgroundTextureBytes + contentsTextureBytes; | |
| 671 } | |
| 672 | |
| 673 bool CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLay
er, CCTextureUpdateQueue& queue) | |
| 674 { | |
| 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. | |
| 678 | |
| 679 bool needMoreUpdates = false; | |
| 680 LayerChromium* maskLayer = renderSurfaceLayer->maskLayer(); | |
| 681 if (maskLayer) { | |
| 682 maskLayer->update(queue, 0, m_renderingStats); | |
| 683 needMoreUpdates |= maskLayer->needMoreUpdates(); | |
| 684 } | |
| 685 | |
| 686 LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? rende
rSurfaceLayer->replicaLayer()->maskLayer() : 0; | |
| 687 if (replicaMaskLayer) { | |
| 688 replicaMaskLayer->update(queue, 0, m_renderingStats); | |
| 689 needMoreUpdates |= replicaMaskLayer->needMoreUpdates(); | |
| 690 } | |
| 691 return needMoreUpdates; | |
| 692 } | |
| 693 | |
| 694 bool CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList
, CCTextureUpdateQueue& queue) | |
| 695 { | |
| 696 // Use FrontToBack to allow for testing occlusion and performing culling dur
ing the tree walk. | |
| 697 typedef CCLayerIterator<LayerChromium, LayerList, RenderSurfaceChromium, CCL
ayerIteratorActions::FrontToBack> CCLayerIteratorType; | |
| 698 | |
| 699 bool needMoreUpdates = false; | |
| 700 bool recordMetricsForFrame = true; // FIXME: In the future, disable this whe
n about:tracing is off. | |
| 701 CCOcclusionTracker occlusionTracker(m_rootLayer->renderSurface()->contentRec
t(), recordMetricsForFrame); | |
| 702 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingS
ize); | |
| 703 | |
| 704 prioritizeTextures(renderSurfaceLayerList, occlusionTracker.overdrawMetrics(
)); | |
| 705 | |
| 706 CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); | |
| 707 for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayer
List); it != end; ++it) { | |
| 708 occlusionTracker.enterLayer(it); | |
| 709 | |
| 710 if (it.representsTargetRenderSurface()) { | |
| 711 ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->dr
awOpacityIsAnimating()); | |
| 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(); | |
| 717 } | |
| 718 | |
| 719 occlusionTracker.leaveLayer(it); | |
| 720 } | |
| 721 | |
| 722 occlusionTracker.overdrawMetrics().recordMetrics(this); | |
| 723 | |
| 724 return needMoreUpdates; | |
| 725 } | |
| 726 | |
| 727 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info) | |
| 728 { | |
| 729 if (!m_rootLayer) | |
| 730 return; | |
| 731 | |
| 732 LayerChromium* rootScrollLayer = findFirstScrollableLayer(m_rootLayer.get())
; | |
| 733 IntSize rootScrollDelta; | |
| 734 | |
| 735 for (size_t i = 0; i < info.scrolls.size(); ++i) { | |
| 736 LayerChromium* layer = CCLayerTreeHostCommon::findLayerInSubtree(m_rootL
ayer.get(), info.scrolls[i].layerId); | |
| 737 if (!layer) | |
| 738 continue; | |
| 739 if (layer == rootScrollLayer) | |
| 740 rootScrollDelta += info.scrolls[i].scrollDelta; | |
| 741 else | |
| 742 layer->setScrollPosition(layer->scrollPosition() + info.scrolls[i].s
crollDelta); | |
| 743 } | |
| 744 if (!rootScrollDelta.isZero() || info.pageScaleDelta != 1) | |
| 745 m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta); | |
| 746 } | |
| 747 | |
| 748 void CCLayerTreeHost::setImplTransform(const WebKit::WebTransformationMatrix& tr
ansform) | |
| 749 { | |
| 750 m_implTransform = transform; | |
| 751 } | |
| 752 | |
| 753 void CCLayerTreeHost::startRateLimiter(WebKit::WebGraphicsContext3D* context) | |
| 754 { | |
| 755 if (m_animating) | |
| 756 return; | |
| 757 | |
| 758 ASSERT(context); | |
| 759 RateLimiterMap::iterator it = m_rateLimiters.find(context); | |
| 760 if (it != m_rateLimiters.end()) | |
| 761 it->second->start(); | |
| 762 else { | |
| 763 scoped_refptr<RateLimiter> rateLimiter = RateLimiter::create(context, th
is); | |
| 764 m_rateLimiters[context] = rateLimiter; | |
| 765 rateLimiter->start(); | |
| 766 } | |
| 767 } | |
| 768 | |
| 769 void CCLayerTreeHost::stopRateLimiter(WebKit::WebGraphicsContext3D* context) | |
| 770 { | |
| 771 RateLimiterMap::iterator it = m_rateLimiters.find(context); | |
| 772 if (it != m_rateLimiters.end()) { | |
| 773 it->second->stop(); | |
| 774 m_rateLimiters.erase(it); | |
| 775 } | |
| 776 } | |
| 777 | |
| 778 void CCLayerTreeHost::rateLimit() | |
| 779 { | |
| 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(); | |
| 783 } | |
| 784 | |
| 785 bool CCLayerTreeHost::bufferedUpdates() | |
| 786 { | |
| 787 return m_settings.maxPartialTextureUpdates != numeric_limits<size_t>::max(); | |
| 788 } | |
| 789 | |
| 790 bool CCLayerTreeHost::requestPartialTextureUpdate() | |
| 791 { | |
| 792 if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates) | |
| 793 return false; | |
| 794 | |
| 795 m_partialTextureUpdateRequests++; | |
| 796 return true; | |
| 797 } | |
| 798 | |
| 799 void CCLayerTreeHost::deleteTextureAfterCommit(scoped_ptr<CCPrioritizedTexture>
texture) | |
| 800 { | |
| 801 m_deleteTextureAfterCommitList.append(texture.Pass()); | |
| 802 } | |
| 803 | |
| 804 void CCLayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor) | |
| 805 { | |
| 806 if (deviceScaleFactor == m_deviceScaleFactor) | |
| 807 return; | |
| 808 m_deviceScaleFactor = deviceScaleFactor; | |
| 809 | |
| 810 setNeedsCommit(); | |
| 811 } | |
| 812 | |
| 813 void CCLayerTreeHost::animateLayers(double monotonicTime) | |
| 814 { | |
| 815 if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers) | |
| 816 return; | |
| 817 | |
| 818 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers"); | |
| 819 m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTi
me); | |
| 820 } | |
| 821 | |
| 822 bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double mono
tonicTime) | |
| 823 { | |
| 824 if (!current) | |
| 825 return false; | |
| 826 | |
| 827 bool subtreeNeedsAnimateLayers = false; | |
| 828 CCLayerAnimationController* currentController = current->layerAnimationContr
oller(); | |
| 829 currentController->animate(monotonicTime, 0); | |
| 830 | |
| 831 // If the current controller still has an active animation, we must continue
animating layers. | |
| 832 if (currentController->hasActiveAnimation()) | |
| 833 subtreeNeedsAnimateLayers = true; | |
| 834 | |
| 835 for (size_t i = 0; i < current->children().size(); ++i) { | |
| 836 if (animateLayersRecursive(current->children()[i].get(), monotonicTime)) | |
| 837 subtreeNeedsAnimateLayers = true; | |
| 838 } | |
| 839 | |
| 840 return subtreeNeedsAnimateLayers; | |
| 841 } | |
| 842 | |
| 843 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector&
events, LayerChromium* layer, double wallClockTime) | |
| 844 { | |
| 845 if (!layer) | |
| 846 return; | |
| 847 | |
| 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)
; | |
| 852 else | |
| 853 layer->notifyAnimationFinished(wallClockTime); | |
| 854 } | |
| 855 } | |
| 856 | |
| 857 for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIn
dex) | |
| 858 setAnimationEventsRecursive(events, layer->children()[childIndex].get(),
wallClockTime); | |
| 859 } | |
| 860 | |
| 861 } // namespace cc | |
| OLD | NEW |