27c1704e722386beda7d09bb5a774a05379f4187
[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 "TraceEvent.h"
33 #include "TreeSynchronizer.h"
34 #include "cc/CCLayerTreeHostCommon.h"
35 #include "cc/CCLayerTreeHostImpl.h"
36 #include "cc/CCSingleThreadProxy.h"
37 #include "cc/CCThread.h"
38 #include "cc/CCThreadProxy.h"
39
40 namespace {
41 static int numLayerTreeInstances;
42 }
43
44 namespace WebCore {
45
46 bool CCLayerTreeHost::anyLayerTreeHostInstanceExists()
47 {
48     return numLayerTreeInstances > 0;
49 }
50
51 PassRefPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCSettings& settings)
52 {
53     RefPtr<CCLayerTreeHost> layerTreeHost = adoptRef(new CCLayerTreeHost(client, settings));
54     if (!layerTreeHost->initialize())
55         return 0;
56     return layerTreeHost;
57 }
58
59 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings& settings)
60     : m_compositorIdentifier(-1)
61     , m_animating(false)
62     , m_client(client)
63     , m_frameNumber(0)
64     , m_settings(settings)
65     , m_visible(true)
66     , m_haveWheelEventHandlers(false)
67     , m_pageScale(1)
68     , m_minPageScale(1)
69     , m_maxPageScale(1)
70 {
71     ASSERT(CCProxy::isMainThread());
72     numLayerTreeInstances++;
73 }
74
75 bool CCLayerTreeHost::initialize()
76 {
77     TRACE_EVENT("CCLayerTreeHost::initialize", this, 0);
78     if (CCProxy::hasImplThread()) {
79         // The HUD does not work in threaded mode. Turn it off.
80         m_settings.showFPSCounter = false;
81         m_settings.showPlatformLayerTree = false;
82
83         m_proxy = CCThreadProxy::create(this);
84     } else
85         m_proxy = CCSingleThreadProxy::create(this);
86     m_proxy->start();
87
88     if (!m_proxy->initializeLayerRenderer())
89         return false;
90
91     m_compositorIdentifier = m_proxy->compositorIdentifier();
92
93     // Update m_settings based on capabilities that we got back from the renderer.
94     m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
95
96     m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
97                                                       TextureManager::reclaimLimitBytes(viewportSize()),
98                                                       m_proxy->layerRendererCapabilities().maxTextureSize);
99     return true;
100 }
101
102 CCLayerTreeHost::~CCLayerTreeHost()
103 {
104     ASSERT(CCProxy::isMainThread());
105     TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0);
106     m_proxy->stop();
107     m_proxy.clear();
108     clearPendingUpdate();
109     numLayerTreeInstances--;
110 }
111
112 void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator)
113 {
114     ASSERT(CCProxy::isImplThread());
115     if (m_contentsTextureManager)
116         m_contentsTextureManager->evictAndDeleteAllTextures(allocator);
117 }
118
119 void CCLayerTreeHost::animateAndLayout(double frameBeginTime)
120 {
121     m_animating = true;
122     m_client->animateAndLayout(frameBeginTime);
123     m_animating = false;
124 }
125
126 void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
127 {
128     ASSERT(CCProxy::isImplThread());
129     TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0);
130
131     contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
132     contentsTextureManager()->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
133 }
134
135 // This function commits the CCLayerTreeHost to an impl tree. When modifying
136 // this function, keep in mind that the function *runs* on the impl thread! Any
137 // code that is logically a main thread operation, e.g. deletion of a LayerChromium,
138 // should be delayed until the CCLayerTreeHost::commitComplete, which will run
139 // after the commit, but on the main thread.
140 void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl)
141 {
142     ASSERT(CCProxy::isImplThread());
143     hostImpl->setSourceFrameNumber(frameNumber());
144     hostImpl->setHaveWheelEventHandlers(m_haveWheelEventHandlers);
145     hostImpl->setZoomAnimatorTransform(m_zoomAnimatorTransform);
146     hostImpl->setViewport(viewportSize());
147     hostImpl->setPageScaleFactorAndLimits(pageScale(), m_minPageScale, m_maxPageScale);
148
149     // Synchronize trees, if one exists at all...
150     if (rootLayer())
151         hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer()));
152     else
153         hostImpl->setRootLayer(0);
154
155     m_frameNumber++;
156 }
157
158 void CCLayerTreeHost::commitComplete()
159 {
160     clearPendingUpdate();
161     m_contentsTextureManager->unprotectAllTextures();
162 }
163
164 PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createLayerTreeHostContext3D()
165 {
166     return m_client->createLayerTreeHostContext3D();
167 }
168
169 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
170 {
171     return CCLayerTreeHostImpl::create(m_settings, client);
172 }
173
174 void CCLayerTreeHost::didRecreateGraphicsContext(bool success)
175 {
176     if (rootLayer())
177         rootLayer()->cleanupResourcesRecursive();
178     m_client->didRecreateGraphicsContext(success);
179 }
180
181 // Temporary hack until WebViewImpl context creation gets simplified
182 GraphicsContext3D* CCLayerTreeHost::context()
183 {
184     ASSERT(!CCProxy::hasImplThread());
185     return m_proxy->context();
186 }
187
188 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
189 {
190     return m_proxy->compositeAndReadback(pixels, rect);
191 }
192
193 void CCLayerTreeHost::finishAllRendering()
194 {
195     m_proxy->finishAllRendering();
196 }
197
198 const LayerRendererCapabilities& CCLayerTreeHost::layerRendererCapabilities() const
199 {
200     return m_proxy->layerRendererCapabilities();
201 }
202
203 void CCLayerTreeHost::setZoomAnimatorTransform(const TransformationMatrix& zoom)
204 {
205     bool zoomChanged = m_zoomAnimatorTransform != zoom;
206
207     m_zoomAnimatorTransform = zoom;
208
209     if (zoomChanged)
210         setNeedsCommit();
211 }
212
213 void CCLayerTreeHost::setNeedsAnimate()
214 {
215     ASSERT(CCProxy::hasImplThread());
216     m_proxy->setNeedsAnimate();
217 }
218
219 void CCLayerTreeHost::setNeedsCommit()
220 {
221     if (CCThreadProxy::implThread()) {
222         TRACE_EVENT("CCLayerTreeHost::setNeedsCommit", this, 0);
223         m_proxy->setNeedsCommit();
224     } else
225         m_client->scheduleComposite();
226 }
227
228 void CCLayerTreeHost::setNeedsRedraw()
229 {
230     if (CCThreadProxy::implThread())
231         m_proxy->setNeedsRedraw();
232     else
233         m_client->scheduleComposite();
234 }
235
236 void CCLayerTreeHost::setViewport(const IntSize& viewportSize)
237 {
238     contentsTextureManager()->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(viewportSize));
239     contentsTextureManager()->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(viewportSize));
240     m_viewportSize = viewportSize;
241     setNeedsCommit();
242 }
243
244 void CCLayerTreeHost::setPageScale(float pageScale)
245 {
246     if (pageScale == m_pageScale)
247         return;
248
249     m_pageScale = pageScale;
250     setNeedsCommit();
251 }
252
253 void CCLayerTreeHost::setPageScaleFactorLimits(float minScale, float maxScale)
254 {
255     if (minScale == m_minPageScale && maxScale == m_maxPageScale)
256         return;
257
258     m_minPageScale = minScale;
259     m_maxPageScale = maxScale;
260     setNeedsCommit();
261 }
262
263 void CCLayerTreeHost::setVisible(bool visible)
264 {
265     if (m_visible == visible)
266         return;
267
268     m_visible = visible;
269     if (!visible) {
270         m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes(viewportSize()));
271         m_contentsTextureManager->unprotectAllTextures();
272     }
273
274     // Tells the proxy that visibility state has changed. This will in turn call
275     // CCLayerTreeHost::didBecomeInvisibleOnImplThread on the appropriate thread, for
276     // the case where !visible.
277     m_proxy->setVisible(visible);
278 }
279
280 void CCLayerTreeHost::didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl* hostImpl)
281 {
282     ASSERT(CCProxy::isImplThread());
283     if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer)
284         contentsTextureManager()->evictAndDeleteAllTextures(hostImpl->contentsTextureAllocator());
285     else {
286         contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
287         contentsTextureManager()->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
288     }
289 }
290
291 void CCLayerTreeHost::setHaveWheelEventHandlers(bool haveWheelEventHandlers)
292 {
293     if (m_haveWheelEventHandlers == haveWheelEventHandlers)
294         return;
295     m_haveWheelEventHandlers = haveWheelEventHandlers;
296     m_proxy->setNeedsCommit();
297 }
298
299
300 void CCLayerTreeHost::loseCompositorContext(int numTimes)
301 {
302     m_proxy->loseCompositorContext(numTimes);
303 }
304
305 TextureManager* CCLayerTreeHost::contentsTextureManager() const
306 {
307     return m_contentsTextureManager.get();
308 }
309
310 void CCLayerTreeHost::composite()
311 {
312     ASSERT(!CCThreadProxy::implThread());
313     static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
314 }
315
316 void CCLayerTreeHost::updateLayers()
317 {
318     if (!rootLayer())
319         return;
320
321     if (viewportSize().isEmpty())
322         return;
323
324     updateLayers(rootLayer());
325 }
326
327 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
328 {
329     TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
330
331     if (!rootLayer->renderSurface())
332         rootLayer->createRenderSurface();
333     rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), viewportSize()));
334
335     IntRect rootClipRect(IntPoint(), viewportSize());
336     rootLayer->setClipRect(rootClipRect);
337
338     // This assert fires if updateCompositorResources wasn't called after
339     // updateLayers. Only one update can be pending at any given time.
340     ASSERT(!m_updateList.size());
341     m_updateList.append(rootLayer);
342
343     RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
344     rootRenderSurface->clearLayerList();
345
346     TransformationMatrix identityMatrix;
347     {
348         TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
349         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
350     }
351
352     paintLayerContents(m_updateList);
353 }
354
355 void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderSurfaceLayer)
356 {
357     // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
358     // in code, we already know that at least something will be drawn into this render surface, so the
359     // mask and replica should be painted.
360
361     if (renderSurfaceLayer->maskLayer()) {
362         renderSurfaceLayer->maskLayer()->setLayerTreeHost(this);
363         renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
364         renderSurfaceLayer->maskLayer()->paintContentsIfDirty();
365     }
366
367     LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
368     if (replicaLayer) {
369
370         replicaLayer->setLayerTreeHost(this);
371         replicaLayer->paintContentsIfDirty();
372
373         if (replicaLayer->maskLayer()) {
374             replicaLayer->maskLayer()->setLayerTreeHost(this);
375             replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
376             replicaLayer->maskLayer()->paintContentsIfDirty();
377         }
378     }
379 }
380
381 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList)
382 {
383     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
384         LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
385         RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
386         ASSERT(renderSurface);
387         ASSERT(renderSurface->drawOpacity());
388
389         renderSurfaceLayer->setLayerTreeHost(this);
390         paintMaskAndReplicaForRenderSurface(renderSurfaceLayer);
391
392         const LayerList& layerList = renderSurface->layerList();
393         for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
394             LayerChromium* layer = layerList[layerIndex].get();
395
396             // Layers that start a new render surface will be painted when the render
397             // surface's list is processed.
398             if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<LayerChromium>(layer, renderSurfaceLayer->id()))
399                 continue;
400
401             layer->setLayerTreeHost(this);
402
403             ASSERT(layer->opacity());
404             ASSERT(!layer->bounds().isEmpty());
405
406             layer->paintContentsIfDirty();
407         }
408     }
409 }
410
411 void CCLayerTreeHost::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
412 {
413     for (int surfaceIndex = m_updateList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
414         LayerChromium* renderSurfaceLayer = m_updateList[surfaceIndex].get();
415         RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
416         ASSERT(renderSurface);
417         ASSERT(renderSurface->drawOpacity());
418
419         if (renderSurfaceLayer->maskLayer())
420             renderSurfaceLayer->maskLayer()->updateCompositorResources(context, updater);
421
422         if (renderSurfaceLayer->replicaLayer()) {
423             renderSurfaceLayer->replicaLayer()->updateCompositorResources(context, updater);
424             
425             if (renderSurfaceLayer->replicaLayer()->maskLayer())
426                 renderSurfaceLayer->replicaLayer()->maskLayer()->updateCompositorResources(context, updater);
427         }
428         
429         const LayerList& layerList = renderSurface->layerList();
430         for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
431             LayerChromium* layer = layerList[layerIndex].get();
432
433             if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<LayerChromium>(layer, renderSurfaceLayer->id()))
434                 continue;
435
436             layer->updateCompositorResources(context, updater);
437         }
438     }
439 }
440
441 void CCLayerTreeHost::clearPendingUpdate()
442 {
443     for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
444         LayerChromium* layer = m_updateList[surfaceIndex].get();
445         ASSERT(layer->renderSurface());
446         layer->clearRenderSurface();
447     }
448     m_updateList.clear();
449 }
450
451 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
452 {
453     // FIXME: pushing scroll offsets to non-root layers not implemented
454     if (!info.scrolls.size())
455         return;
456
457     ASSERT(info.scrolls.size() == 1);
458     IntSize scrollDelta = info.scrolls[0].scrollDelta;
459     m_client->applyScrollAndScale(scrollDelta, info.pageScaleDelta);
460 }
461
462 void CCLayerTreeHost::startRateLimiter(GraphicsContext3D* context)
463 {
464     if (animating())
465         return;
466     ASSERT(context);
467     RateLimiterMap::iterator it = m_rateLimiters.find(context);
468     if (it != m_rateLimiters.end())
469         it->second->start();
470     else {
471         RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context);
472         m_rateLimiters.set(context, rateLimiter);
473         rateLimiter->start();
474     }
475 }
476
477 void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
478 {
479     RateLimiterMap::iterator it = m_rateLimiters.find(context);
480     if (it != m_rateLimiters.end()) {
481         it->second->stop();
482         m_rateLimiters.remove(it);
483     }
484 }
485
486 }