fa0eb64c365b18de0d969fc83e9b4835a386934a
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCLayerTreeHost.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCLayerTreeHost.h"
28
29 #include "LayerChromium.h"
30 #include "LayerPainterChromium.h"
31 #include "LayerRendererChromium.h"
32 #include "Region.h"
33 #include "TraceEvent.h"
34 #include "TreeSynchronizer.h"
35 #include "cc/CCFontAtlas.h"
36 #include "cc/CCLayerAnimationController.h"
37 #include "cc/CCLayerIterator.h"
38 #include "cc/CCLayerTreeHostCommon.h"
39 #include "cc/CCLayerTreeHostImpl.h"
40 #include "cc/CCOcclusionTracker.h"
41 #include "cc/CCSingleThreadProxy.h"
42 #include "cc/CCThread.h"
43 #include "cc/CCThreadProxy.h"
44
45 using namespace std;
46 using WebKit::WebTransformationMatrix;
47
48 namespace {
49 static int numLayerTreeInstances;
50 }
51
52 namespace WebCore {
53
54 bool CCLayerTreeHost::s_needsFilterContext = false;
55
56 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
57 {
58     return numLayerTreeInstances > 0;
59 }
60
61 PassOwnPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCSettings& settings)
62 {
63     OwnPtr<CCLayerTreeHost> layerTreeHost = adoptPtr(new CCLayerTreeHost(client, settings));
64     if (!layerTreeHost->initialize())
65         return nullptr;
66     return layerTreeHost.release();
67 }
68
69 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings& settings)
70     : m_compositorIdentifier(-1)
71     , m_animating(false)
72     , m_needsAnimateLayers(false)
73     , m_client(client)
74     , m_frameNumber(0)
75     , m_frameIsForDisplay(false)
76     , m_layerRendererInitialized(false)
77     , m_contextLost(false)
78     , m_numTimesRecreateShouldFail(0)
79     , m_numFailedRecreateAttempts(0)
80     , m_settings(settings)
81     , m_visible(true)
82     , m_memoryAllocationBytes(0)
83     , m_memoryAllocationIsForDisplay(false)
84     , m_pageScaleFactor(1)
85     , m_minPageScaleFactor(1)
86     , m_maxPageScaleFactor(1)
87     , m_triggerIdlePaints(true)
88     , m_backgroundColor(Color::white)
89     , m_partialTextureUpdateRequests(0)
90 {
91     ASSERT(CCProxy::isMainThread());
92     numLayerTreeInstances++;
93 }
94
95 bool CCLayerTreeHost::initialize()
96 {
97     TRACE_EVENT("CCLayerTreeHost::initialize", this, 0);
98
99     if (CCProxy::hasImplThread())
100         m_proxy = CCThreadProxy::create(this);
101     else
102         m_proxy = CCSingleThreadProxy::create(this);
103     m_proxy->start();
104
105     if (!m_proxy->initializeContext())
106         return false;
107
108     // Only allocate the font atlas if we have reason to use the heads-up display.
109     if (m_settings.showFPSCounter || m_settings.showPlatformLayerTree) {
110         TRACE_EVENT0("cc", "CCLayerTreeHost::initialize::initializeFontAtlas");
111         OwnPtr<CCFontAtlas> fontAtlas(CCFontAtlas::create());
112         fontAtlas->initialize();
113         m_proxy->setFontAtlas(fontAtlas.release());
114     }
115
116     m_compositorIdentifier = m_proxy->compositorIdentifier();
117     return true;
118 }
119
120 CCLayerTreeHost::~CCLayerTreeHost()
121 {
122     ASSERT(CCProxy::isMainThread());
123     TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0);
124     ASSERT(m_proxy);
125     m_proxy->stop();
126     m_proxy.clear();
127     numLayerTreeInstances--;
128 }
129
130 void CCLayerTreeHost::setSurfaceReady()
131 {
132     m_proxy->setSurfaceReady();
133 }
134
135 void CCLayerTreeHost::initializeLayerRenderer()
136 {
137     TRACE_EVENT("CCLayerTreeHost::initializeLayerRenderer", this, 0);
138     if (!m_proxy->initializeLayerRenderer()) {
139         // Uh oh, better tell the client that we can't do anything with this context.
140         m_client->didRecreateContext(false);
141         return;
142     }
143
144     // Update m_settings based on capabilities that we got back from the renderer.
145     m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
146
147     // Update m_settings based on partial update capability.
148     m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates());
149
150     m_contentsTextureManager = TextureManager::create(0, 0, m_proxy->layerRendererCapabilities().maxTextureSize);
151
152     // FIXME: This is the same as setContentsMemoryAllocationLimitBytes, but
153     // we're in the middle of a commit here and don't want to force another.
154     m_memoryAllocationBytes = TextureManager::highLimitBytes(deviceViewportSize());
155     m_memoryAllocationIsForDisplay = true;
156
157     m_layerRendererInitialized = true;
158
159     m_settings.defaultTileSize = IntSize(min(m_settings.defaultTileSize.width(), m_proxy->layerRendererCapabilities().maxTextureSize),
160                                          min(m_settings.defaultTileSize.height(), m_proxy->layerRendererCapabilities().maxTextureSize));
161     m_settings.maxUntiledLayerSize = IntSize(min(m_settings.maxUntiledLayerSize.width(), m_proxy->layerRendererCapabilities().maxTextureSize),
162                                              min(m_settings.maxUntiledLayerSize.height(), m_proxy->layerRendererCapabilities().maxTextureSize));
163 }
164
165 CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext()
166 {
167     TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext");
168     ASSERT(m_contextLost);
169
170     bool recreated = false;
171     if (!m_numTimesRecreateShouldFail)
172         recreated = m_proxy->recreateContext();
173     else
174         m_numTimesRecreateShouldFail--;
175
176     if (recreated) {
177         m_client->didRecreateContext(true);
178         m_contextLost = false;
179         return RecreateSucceeded;
180     }
181
182     // Tolerate a certain number of recreation failures to work around races
183     // in the context-lost machinery.
184     m_numFailedRecreateAttempts++;
185     if (m_numFailedRecreateAttempts < 5) {
186         // FIXME: The single thread does not self-schedule context
187         // recreation. So force another recreation attempt to happen by requesting
188         // another commit.
189         if (!CCProxy::hasImplThread())
190             setNeedsCommit();
191         return RecreateFailedButTryAgain;
192     }
193
194     // We have tried too many times to recreate the context. Tell the host to fall
195     // back to software rendering.
196     m_client->didRecreateContext(false);
197     return RecreateFailedAndGaveUp;
198 }
199
200 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator)
201 {
202     ASSERT(CCProxy::isImplThread());
203     if (m_layerRendererInitialized)
204         m_contentsTextureManager->evictAndDeleteAllTextures(allocator);
205 }
206
207 void CCLayerTreeHost::acquireLayerTextures()
208 {
209     ASSERT(CCProxy::isMainThread());
210     m_proxy->acquireLayerTextures();
211 }
212
213 void CCLayerTreeHost::updateAnimations(double monotonicFrameBeginTime)
214 {
215     m_animating = true;
216     m_client->updateAnimations(monotonicFrameBeginTime);
217     animateLayers(monotonicFrameBeginTime);
218     m_animating = false;
219 }
220
221 void CCLayerTreeHost::layout()
222 {
223     m_client->layout();
224 }
225
226 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
227 {
228     ASSERT(CCProxy::isImplThread());
229     TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0);
230
231     m_contentsTextureManager->reduceMemoryToLimit(m_contentsTextureManager->preferredMemoryLimitBytes());
232     m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
233 }
234
235 // This function commits the CCLayerTreeHost to an impl tree. When modifying
236 // this function, keep in mind that the function *runs* on the impl thread! Any
237 // code that is logically a main thread operation, e.g. deletion of a LayerChromium,
238 // should be delayed until the CCLayerTreeHost::commitComplete, which will run
239 // after the commit, but on the main thread.
240 void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
241 {
242     ASSERT(CCProxy::isImplThread());
243
244     hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer(), hostImpl));
245
246     // We may have added an animation during the tree sync. This will cause both layer tree hosts
247     // to visit their controllers.
248     if (rootLayer() && m_needsAnimateLayers)
249         hostImpl->setNeedsAnimateLayers();
250
251     hostImpl->setSourceFrameNumber(frameNumber());
252     hostImpl->setViewportSize(viewportSize());
253     hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor);
254     hostImpl->setBackgroundColor(m_backgroundColor);
255     hostImpl->setVisible(m_visible);
256     hostImpl->setSourceFrameCanBeDrawn(m_frameIsForDisplay);
257
258     m_frameNumber++;
259 }
260
261 void CCLayerTreeHost::commitComplete()
262 {
263     m_deleteTextureAfterCommitList.clear();
264     m_contentsTextureManager->unprotectAllTextures();
265     m_client->didCommit();
266 }
267
268 PassRefPtr<CCGraphicsContext> CCLayerTreeHost::createContext()
269 {
270     RefPtr<CCGraphicsContext> context;
271     if (settings().forceSoftwareCompositing)
272         return CCGraphicsContext::create2D();
273     return CCGraphicsContext::create3D(m_client->createContext3D());
274 }
275
276 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
277 {
278     return CCLayerTreeHostImpl::create(m_settings, client);
279 }
280
281 void CCLayerTreeHost::didLoseContext()
282 {
283     TRACE_EVENT("CCLayerTreeHost::didLoseContext", 0, this);
284     ASSERT(CCProxy::isMainThread());
285     m_contextLost = true;
286     m_numFailedRecreateAttempts = 0;
287     setNeedsCommit();
288 }
289
290 // Temporary hack until WebViewImpl context creation gets simplified
291 CCGraphicsContext* CCLayerTreeHost::context()
292 {
293     return m_proxy->context();
294 }
295
296 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
297 {
298     if (!m_layerRendererInitialized) {
299         initializeLayerRenderer();
300         if (!m_layerRendererInitialized)
301             return false;
302     }
303     if (m_contextLost) {
304         if (recreateContext() != RecreateSucceeded)
305             return false;
306     }
307     m_triggerIdlePaints = false;
308     bool ret = m_proxy->compositeAndReadback(pixels, rect);
309     m_triggerIdlePaints = true;
310     return ret;
311 }
312
313 void CCLayerTreeHost::finishAllRendering()
314 {
315     if (!m_layerRendererInitialized)
316         return;
317     m_proxy->finishAllRendering();
318 }
319
320 const LayerRendererCapabilities& CCLayerTreeHost::layerRendererCapabilities() const
321 {
322     return m_proxy->layerRendererCapabilities();
323 }
324
325 void CCLayerTreeHost::setNeedsAnimate()
326 {
327     ASSERT(CCProxy::hasImplThread());
328     m_proxy->setNeedsAnimate();
329 }
330
331 void CCLayerTreeHost::setNeedsCommit()
332 {
333     m_proxy->setNeedsCommit();
334 }
335
336 void CCLayerTreeHost::setNeedsForcedCommit()
337 {
338     m_proxy->setNeedsForcedCommit();
339 }
340
341 void CCLayerTreeHost::setNeedsRedraw()
342 {
343     m_proxy->setNeedsRedraw();
344     if (!CCThreadProxy::implThread())
345         m_client->scheduleComposite();
346 }
347
348 bool CCLayerTreeHost::commitRequested() const
349 {
350     return m_proxy->commitRequested();
351 }
352
353 void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
354 {
355     ASSERT(CCThreadProxy::isMainThread());
356     setAnimationEventsRecursive(*events, m_rootLayer.get(), wallClockTime);
357 }
358
359 void CCLayerTreeHost::didAddAnimation()
360 {
361     m_needsAnimateLayers = true;
362     m_proxy->didAddAnimation();
363 }
364
365 void CCLayerTreeHost::setRootLayer(PassRefPtr<LayerChromium> rootLayer)
366 {
367     if (m_rootLayer == rootLayer)
368         return;
369
370     if (m_rootLayer)
371         m_rootLayer->setLayerTreeHost(0);
372     m_rootLayer = rootLayer;
373     if (m_rootLayer)
374         m_rootLayer->setLayerTreeHost(this);
375     setNeedsCommit();
376 }
377
378 void CCLayerTreeHost::setViewportSize(const IntSize& viewportSize)
379 {
380     if (viewportSize == m_viewportSize)
381         return;
382
383     m_viewportSize = viewportSize;
384
385     m_deviceViewportSize = viewportSize;
386     m_deviceViewportSize.scale(m_settings.deviceScaleFactor);
387
388     setNeedsCommit();
389 }
390
391 void CCLayerTreeHost::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
392 {
393     if (pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
394         return;
395
396     m_pageScaleFactor = pageScaleFactor;
397     m_minPageScaleFactor = minPageScaleFactor;
398     m_maxPageScaleFactor = maxPageScaleFactor;
399     setNeedsCommit();
400 }
401
402 void CCLayerTreeHost::setVisible(bool visible)
403 {
404     if (m_visible == visible)
405         return;
406
407     m_visible = visible;
408
409     // FIXME: Remove this stuff, it is here just for the m20 merge.
410     if (!m_visible && m_layerRendererInitialized) {
411         if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer)
412             setContentsMemoryAllocationLimitBytes(0);
413         else
414             setContentsMemoryAllocationLimitBytes(m_contentsTextureManager->preferredMemoryLimitBytes());
415     }
416
417     setNeedsForcedCommit();
418 }
419
420 void CCLayerTreeHost::setContentsMemoryAllocationLimitBytes(size_t bytes)
421 {
422     ASSERT(CCProxy::isMainThread());
423     if (m_memoryAllocationBytes == bytes)
424         return;
425
426     m_memoryAllocationBytes = bytes;
427     m_memoryAllocationIsForDisplay = bytes;
428
429     // When not visible, force a commit so that we change our memory allocation
430     // and evict/delete any textures if we are being requested to.
431     if (!m_visible)
432         setNeedsForcedCommit();
433     else
434         setNeedsCommit();
435 }
436
437 void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec)
438 {
439     m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec);
440 }
441
442 void CCLayerTreeHost::loseContext(int numTimes)
443 {
444     TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes);
445     m_numTimesRecreateShouldFail = numTimes - 1;
446     m_proxy->loseContext();
447 }
448
449 TextureManager* CCLayerTreeHost::contentsTextureManager() const
450 {
451     return m_contentsTextureManager.get();
452 }
453
454 void CCLayerTreeHost::composite()
455 {
456     ASSERT(!CCThreadProxy::implThread());
457     static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
458 }
459
460 void CCLayerTreeHost::scheduleComposite()
461 {
462     m_client->scheduleComposite();
463 }
464
465 bool CCLayerTreeHost::updateLayers(CCTextureUpdater& updater)
466 {
467     if (!m_layerRendererInitialized) {
468         initializeLayerRenderer();
469         // If we couldn't initialize, then bail since we're returning to software mode.
470         if (!m_layerRendererInitialized)
471             return false;
472     }
473     if (m_contextLost) {
474         if (recreateContext() != RecreateSucceeded)
475             return false;
476     }
477
478     // The visible state and memory allocation are set independently and in
479     // arbitrary order, so do not change the memory allocation used for the
480     // current commit until both values match intentions.
481     // FIXME: These two states should be combined into a single action so we
482     // need a single commit to change visible state, and this can be removed.
483     bool memoryAllocationStateMatchesVisibility = m_visible == m_memoryAllocationIsForDisplay;
484     if (memoryAllocationStateMatchesVisibility) {
485         m_contentsTextureManager->setMemoryAllocationLimitBytes(m_memoryAllocationBytes);
486         m_frameIsForDisplay = m_memoryAllocationIsForDisplay;
487     }
488
489     if (!rootLayer())
490         return true;
491
492     if (viewportSize().isEmpty())
493         return true;
494
495     updateLayers(rootLayer(), updater);
496     return true;
497 }
498
499 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdater& updater)
500 {
501     TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
502
503     if (!rootLayer->renderSurface())
504         rootLayer->createRenderSurface();
505     rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), deviceViewportSize()));
506
507     IntRect rootClipRect(IntPoint(), deviceViewportSize());
508     rootLayer->setClipRect(rootClipRect);
509
510     LayerList updateList;
511     updateList.append(rootLayer);
512
513     RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
514     rootRenderSurface->clearLayerList();
515
516     {
517         TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
518         WebTransformationMatrix identityMatrix;
519         WebTransformationMatrix deviceScaleTransform;
520         deviceScaleTransform.scale(m_settings.deviceScaleFactor);
521         CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
522
523         FloatRect rootScissorRect(FloatPoint(0, 0), viewportSize());
524         CCLayerTreeHostCommon::calculateVisibleAndScissorRects(updateList, rootScissorRect);
525     }
526
527     // Reset partial texture update requests.
528     m_partialTextureUpdateRequests = 0;
529
530     reserveTextures(updateList);
531
532     paintLayerContents(updateList, PaintVisible, updater);
533     if (!m_triggerIdlePaints)
534         return;
535
536     size_t preferredLimitBytes = m_contentsTextureManager->preferredMemoryLimitBytes();
537     size_t maxLimitBytes = m_contentsTextureManager->maxMemoryLimitBytes();
538     m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes);
539     if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes)
540         return;
541
542     // Idle painting should fail when we hit the preferred memory limit,
543     // otherwise it will always push us towards the maximum limit.
544     m_contentsTextureManager->setMaxMemoryLimitBytes(preferredLimitBytes);
545     // The second (idle) paint will be a no-op in layers where painting already occured above.
546     paintLayerContents(updateList, PaintIdle, updater);
547     m_contentsTextureManager->setMaxMemoryLimitBytes(maxLimitBytes);
548
549     for (size_t i = 0; i < updateList.size(); ++i)
550         updateList[i]->clearRenderSurface();
551 }
552
553 void CCLayerTreeHost::reserveTextures(const LayerList& updateList)
554 {
555     // Use BackToFront since it's cheap and this isn't order-dependent.
556     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
557
558     CCLayerIteratorType end = CCLayerIteratorType::end(&updateList);
559     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&updateList); it != end; ++it) {
560         if (!it.representsItself() || !it->alwaysReserveTextures())
561             continue;
562         it->reserveTextures();
563     }
564 }
565
566 // static
567 void CCLayerTreeHost::update(LayerChromium* layer, PaintType paintType, CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
568 {
569     ASSERT(layer);
570     ASSERT(PaintVisible == paintType || PaintIdle == paintType);
571     if (PaintVisible == paintType)
572         layer->update(updater, occlusion);
573     else
574         layer->idleUpdate(updater, occlusion);
575 }
576
577 void CCLayerTreeHost::paintMasksForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType, CCTextureUpdater& updater)
578 {
579     // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
580     // in code, we already know that at least something will be drawn into this render surface, so the
581     // mask and replica should be painted.
582
583     LayerChromium* maskLayer = renderSurfaceLayer->maskLayer();
584     if (maskLayer) {
585         maskLayer->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
586         update(maskLayer, paintType, updater, 0);
587     }
588
589     LayerChromium* replicaMaskLayer = renderSurfaceLayer->replicaLayer() ? renderSurfaceLayer->replicaLayer()->maskLayer() : 0;
590     if (replicaMaskLayer) {
591         replicaMaskLayer->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
592         update(replicaMaskLayer, paintType, updater, 0);
593     }
594 }
595
596 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType, CCTextureUpdater& updater)
597 {
598     // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk.
599     typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
600
601     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
602     CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), deviceViewportSize()), recordMetricsForFrame);
603     occlusionTracker.setMinimumTrackingSize(CCOcclusionTracker::preferredMinimumTrackingSize());
604
605     CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
606     for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
607         occlusionTracker.enterLayer(it);
608
609         if (it.representsTargetRenderSurface()) {
610             ASSERT(it->renderSurface()->drawOpacity() || it->renderSurface()->drawOpacityIsAnimating());
611             paintMasksForRenderSurface(*it, paintType, updater);
612         } else if (it.representsItself()) {
613             ASSERT(!it->bounds().isEmpty());
614             update(*it, paintType, updater, &occlusionTracker);
615         }
616
617         occlusionTracker.leaveLayer(it);
618     }
619
620     occlusionTracker.overdrawMetrics().recordMetrics(this);
621 }
622
623 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
624 {
625     // FIXME: pushing scroll offsets to non-root layers not implemented
626     if (!info.scrolls.size())
627         return;
628
629     ASSERT(info.scrolls.size() == 1);
630     IntSize scrollDelta = info.scrolls[0].scrollDelta;
631     m_client->applyScrollAndScale(scrollDelta, info.pageScaleDelta);
632 }
633
634 void CCLayerTreeHost::startRateLimiter(GraphicsContext3D* context)
635 {
636     if (m_animating)
637         return;
638     ASSERT(context);
639     RateLimiterMap::iterator it = m_rateLimiters.find(context);
640     if (it != m_rateLimiters.end())
641         it->second->start();
642     else {
643         RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context, this);
644         m_rateLimiters.set(context, rateLimiter);
645         rateLimiter->start();
646     }
647 }
648
649 void CCLayerTreeHost::rateLimit()
650 {
651     // Force a no-op command on the compositor context, so that any ratelimiting commands will wait for the compositing
652     // context, and therefore for the SwapBuffers.
653     m_proxy->forceSerializeOnSwapBuffers();
654 }
655
656 void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
657 {
658     RateLimiterMap::iterator it = m_rateLimiters.find(context);
659     if (it != m_rateLimiters.end()) {
660         it->second->stop();
661         m_rateLimiters.remove(it);
662     }
663 }
664
665 bool CCLayerTreeHost::bufferedUpdates()
666 {
667     return m_settings.maxPartialTextureUpdates != numeric_limits<size_t>::max();
668 }
669
670 bool CCLayerTreeHost::requestPartialTextureUpdate()
671 {
672     if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
673         return false;
674
675     m_partialTextureUpdateRequests++;
676     return true;
677 }
678
679 void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture)
680 {
681     m_deleteTextureAfterCommitList.append(texture);
682 }
683
684 void CCLayerTreeHost::animateLayers(double monotonicTime)
685 {
686     if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers)
687         return;
688
689     TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
690     m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime);
691 }
692
693 bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime)
694 {
695     if (!current)
696         return false;
697
698     bool subtreeNeedsAnimateLayers = false;
699     CCLayerAnimationController* currentController = current->layerAnimationController();
700     currentController->animate(monotonicTime, 0);
701
702     // If the current controller still has an active animation, we must continue animating layers.
703     if (currentController->hasActiveAnimation())
704          subtreeNeedsAnimateLayers = true;
705
706     for (size_t i = 0; i < current->children().size(); ++i) {
707         if (animateLayersRecursive(current->children()[i].get(), monotonicTime))
708             subtreeNeedsAnimateLayers = true;
709     }
710
711     return subtreeNeedsAnimateLayers;
712 }
713
714 void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
715 {
716     if (!layer)
717         return;
718
719     for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
720         if (layer->id() == events[eventIndex].layerId) {
721             if (events[eventIndex].type == CCAnimationEvent::Started)
722                 layer->notifyAnimationStarted(events[eventIndex], wallClockTime);
723             else
724                 layer->notifyAnimationFinished(wallClockTime);
725         }
726     }
727
728     for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
729         setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
730 }
731
732 } // namespace WebCore