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 |