a257b411ab9f4c4d6acebfe7a753bf19dab832c8
[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 WebCore {
41
42 PassRefPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
43 {
44     RefPtr<CCLayerTreeHost> layerTreeHost = adoptRef(new CCLayerTreeHost(client, rootLayer, settings));
45     if (!layerTreeHost->initialize())
46         return 0;
47     return layerTreeHost;
48 }
49
50 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
51     : m_animating(false)
52     , m_client(client)
53     , m_frameNumber(0)
54     , m_rootLayer(rootLayer)
55     , m_settings(settings)
56     , m_zoomAnimatorScale(1)
57     , m_visible(true)
58 {
59 }
60
61 bool CCLayerTreeHost::initialize()
62 {
63     if (m_settings.enableCompositorThread) {
64         // Accelerated Painting is not supported in threaded mode. Turn it off.
65         m_settings.acceleratePainting = false;
66         m_proxy = CCThreadProxy::create(this);
67     } else
68         m_proxy = CCSingleThreadProxy::create(this);
69     m_proxy->start();
70
71     if (!m_proxy->initializeLayerRenderer())
72         return false;
73
74     // Update m_settings based on capabilities that we got back from the renderer.
75     m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
76
77     // We changed the root layer. Tell the proxy a commit is needed.
78     m_proxy->setNeedsCommitAndRedraw();
79
80     m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(), m_proxy->layerRendererCapabilities().maxTextureSize);
81     return true;
82 }
83
84 CCLayerTreeHost::~CCLayerTreeHost()
85 {
86     ASSERT(CCProxy::isMainThread());
87     TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0);
88     m_proxy->stop();
89     m_proxy.clear();
90     clearPendingUpdate();
91     ASSERT(!m_contentsTextureManager || !m_contentsTextureManager->currentMemoryUseBytes());
92     m_contentsTextureManager.clear();
93 }
94
95 void CCLayerTreeHost::deleteContentsTextures(GraphicsContext3D* context)
96 {
97     ASSERT(CCProxy::isImplThread());
98     if (m_contentsTextureManager)
99         m_contentsTextureManager->evictAndDeleteAllTextures(context);
100 }
101
102 void CCLayerTreeHost::animateAndLayout(double frameBeginTime)
103 {
104     m_animating = true;
105     m_client->animateAndLayout(frameBeginTime);
106     m_animating = false;
107 }
108
109 void CCLayerTreeHost::commitTo(CCLayerTreeHostImpl* hostImpl)
110 {
111     ASSERT(CCProxy::isImplThread());
112     TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0);
113     hostImpl->setSourceFrameNumber(frameNumber());
114
115     // FIXME: Temporary diagnostic for crbug 96719. This shouldn't happen.
116     if (!contentsTextureManager())
117         CRASH();
118
119     contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes());
120     contentsTextureManager()->deleteEvictedTextures(hostImpl->context());
121
122     updateCompositorResources(m_updateList, hostImpl->context());
123     clearPendingUpdate();
124
125     hostImpl->setVisible(m_visible);
126     hostImpl->setZoomAnimatorScale(m_zoomAnimatorScale);
127     hostImpl->setViewport(viewportSize());
128
129     hostImpl->layerRenderer()->setContentsTextureMemoryUseBytes(m_contentsTextureManager->currentMemoryUseBytes());
130     m_contentsTextureManager->unprotectAllTextures();
131
132     // Synchronize trees, if one exists at all...
133     if (rootLayer())
134         hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer()));
135     else
136         hostImpl->setRootLayer(0);
137
138     m_frameNumber++;
139 }
140
141 PassOwnPtr<CCThread> CCLayerTreeHost::createCompositorThread()
142 {
143     return m_client->createCompositorThread();
144 }
145
146 PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createLayerTreeHostContext3D()
147 {
148     return m_client->createLayerTreeHostContext3D();
149 }
150
151 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl()
152 {
153     return CCLayerTreeHostImpl::create(m_settings);
154 }
155
156 void CCLayerTreeHost::didRecreateGraphicsContext(bool success)
157 {
158     m_contentsTextureManager->evictAndDeleteAllTextures(0);
159
160     if (rootLayer())
161         rootLayer()->cleanupResourcesRecursive();
162     m_client->didRecreateGraphicsContext(success);
163 }
164
165 #if !USE(THREADED_COMPOSITING)
166 void CCLayerTreeHost::scheduleComposite()
167 {
168     m_client->scheduleComposite();
169 }
170 #endif
171
172 // Temporary hack until WebViewImpl context creation gets simplified
173 GraphicsContext3D* CCLayerTreeHost::context()
174 {
175     ASSERT(!m_settings.enableCompositorThread);
176     return m_proxy->context();
177 }
178
179 bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
180 {
181     return m_proxy->compositeAndReadback(pixels, rect);
182 }
183
184 void CCLayerTreeHost::finishAllRendering()
185 {
186     m_proxy->finishAllRendering();
187 }
188
189 const LayerRendererCapabilities& CCLayerTreeHost::layerRendererCapabilities() const
190 {
191     return m_proxy->layerRendererCapabilities();
192 }
193
194 void CCLayerTreeHost::setZoomAnimatorScale(double zoom)
195 {
196     bool zoomChanged = m_zoomAnimatorScale != zoom;
197
198     m_zoomAnimatorScale = zoom;
199
200     if (zoomChanged)
201         setNeedsCommitAndRedraw();
202 }
203
204 void CCLayerTreeHost::setNeedsCommitAndRedraw()
205 {
206 #if USE(THREADED_COMPOSITING)
207     TRACE_EVENT("CCLayerTreeHost::setNeedsRedraw", this, 0);
208     m_proxy->setNeedsCommitAndRedraw();
209 #else
210     m_client->scheduleComposite();
211 #endif
212 }
213
214 void CCLayerTreeHost::setNeedsRedraw()
215 {
216 #if USE(THREADED_COMPOSITING)
217     TRACE_EVENT("CCLayerTreeHost::setNeedsRedraw", this, 0);
218     m_proxy->setNeedsRedraw();
219 #else
220     m_client->scheduleComposite();
221 #endif
222 }
223
224 void CCLayerTreeHost::setViewport(const IntSize& viewportSize)
225 {
226     m_viewportSize = viewportSize;
227     setNeedsCommitAndRedraw();
228 }
229
230 void CCLayerTreeHost::setVisible(bool visible)
231 {
232     m_visible = visible;
233     if (visible)
234         m_proxy->setNeedsCommitAndRedraw();
235     else {
236         m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes());
237         m_contentsTextureManager->unprotectAllTextures();
238         m_proxy->setNeedsCommit();
239     }
240 }
241
242 void CCLayerTreeHost::loseCompositorContext(int numTimes)
243 {
244     m_proxy->loseCompositorContext(numTimes);
245 }
246
247 TextureManager* CCLayerTreeHost::contentsTextureManager() const
248 {
249     return m_contentsTextureManager.get();
250 }
251
252 #if !USE(THREADED_COMPOSITING)
253 void CCLayerTreeHost::composite()
254 {
255     ASSERT(!m_settings.enableCompositorThread);
256     static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
257 }
258 #endif // !USE(THREADED_COMPOSITING)
259
260 void CCLayerTreeHost::updateLayers()
261 {
262     if (!rootLayer())
263         return;
264
265     if (viewportSize().isEmpty())
266         return;
267
268     updateLayers(rootLayer());
269 }
270
271 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
272 {
273     TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
274
275     if (!rootLayer->renderSurface())
276         rootLayer->createRenderSurface();
277     rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), viewportSize()));
278
279     IntRect rootScissorRect(IntPoint(), viewportSize());
280     rootLayer->setScissorRect(rootScissorRect);
281
282     // This assert fires if updateCompositorResources wasn't called after
283     // updateLayers. Only one update can be pending at any given time.
284     ASSERT(!m_updateList.size());
285     m_updateList.append(rootLayer);
286
287     RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
288     rootRenderSurface->clearLayerList();
289
290     TransformationMatrix zoomMatrix;
291     zoomMatrix.scale3d(m_zoomAnimatorScale, m_zoomAnimatorScale, 1);
292     {
293         TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
294         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, zoomMatrix, zoomMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
295     }
296
297     paintLayerContents(m_updateList);
298 }
299
300 static void paintContentsIfDirty(LayerChromium* layer, const IntRect& visibleLayerRect)
301 {
302     if (layer->drawsContent()) {
303         layer->setVisibleLayerRect(visibleLayerRect);
304         layer->paintContentsIfDirty();
305     }
306 }
307
308 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList)
309 {
310     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
311         LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
312         RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
313         ASSERT(renderSurface);
314
315         renderSurfaceLayer->setLayerTreeHost(this);
316
317         // Render surfaces whose drawable area has zero width or height
318         // will have no layers associated with them and should be skipped.
319         if (!renderSurface->layerList().size())
320             continue;
321
322         if (!renderSurface->drawOpacity())
323             continue;
324
325         const LayerList& layerList = renderSurface->layerList();
326         ASSERT(layerList.size());
327         for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
328             LayerChromium* layer = layerList[layerIndex].get();
329
330             // Layers that start a new render surface will be painted when the render
331             // surface's list is processed.
332             if (layer->renderSurface() && layer->renderSurface() != renderSurface)
333                 continue;
334
335             layer->setLayerTreeHost(this);
336
337             if (!layer->opacity())
338                 continue;
339
340             if (layer->maskLayer())
341                 layer->maskLayer()->setLayerTreeHost(this);
342             if (layer->replicaLayer()) {
343                 layer->replicaLayer()->setLayerTreeHost(this);
344                 if (layer->replicaLayer()->maskLayer())
345                     layer->replicaLayer()->maskLayer()->setLayerTreeHost(this);
346             }
347
348             if (layer->bounds().isEmpty())
349                 continue;
350
351             IntRect defaultContentRect = IntRect(rootLayer()->scrollPosition(), viewportSize());
352
353             IntRect targetSurfaceRect = layer->targetRenderSurface() ? layer->targetRenderSurface()->contentRect() : defaultContentRect;
354             if (layer->usesLayerScissor())
355                 targetSurfaceRect.intersect(layer->scissorRect());
356             IntRect visibleLayerRect = CCLayerTreeHostCommon::calculateVisibleLayerRect(targetSurfaceRect, layer->bounds(), layer->contentBounds(), layer->drawTransform());
357
358             visibleLayerRect.move(toSize(layer->scrollPosition()));
359             paintContentsIfDirty(layer, visibleLayerRect);
360
361             if (LayerChromium* maskLayer = layer->maskLayer())
362                 paintContentsIfDirty(maskLayer, IntRect(IntPoint(), maskLayer->contentBounds()));
363
364             if (LayerChromium* replicaLayer = layer->replicaLayer()) {
365                 paintContentsIfDirty(replicaLayer, visibleLayerRect);
366
367                 if (LayerChromium* replicaMaskLayer = replicaLayer->maskLayer())
368                     paintContentsIfDirty(replicaMaskLayer, IntRect(IntPoint(), replicaMaskLayer->contentBounds()));
369             }
370         }
371     }
372 }
373
374 void CCLayerTreeHost::updateCompositorResources(const LayerList& renderSurfaceLayerList, GraphicsContext3D* context)
375 {
376     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
377         LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
378         RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
379         ASSERT(renderSurface);
380
381         if (!renderSurface->layerList().size() || !renderSurface->drawOpacity())
382             continue;
383
384         const LayerList& layerList = renderSurface->layerList();
385         ASSERT(layerList.size());
386         for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
387             LayerChromium* layer = layerList[layerIndex].get();
388             if (layer->renderSurface() && layer->renderSurface() != renderSurface)
389                 continue;
390
391             updateCompositorResources(layer, context);
392         }
393     }
394 }
395
396 void CCLayerTreeHost::updateCompositorResources(LayerChromium* layer, GraphicsContext3D* context)
397 {
398     if (layer->bounds().isEmpty())
399         return;
400
401     if (!layer->opacity())
402         return;
403
404     if (layer->maskLayer())
405         updateCompositorResources(layer->maskLayer(), context);
406     if (layer->replicaLayer())
407         updateCompositorResources(layer->replicaLayer(), context);
408
409     if (layer->drawsContent())
410         layer->updateCompositorResources(context);
411 }
412
413 void CCLayerTreeHost::clearPendingUpdate()
414 {
415     for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
416         LayerChromium* layer = m_updateList[surfaceIndex].get();
417         ASSERT(layer->renderSurface());
418         layer->clearRenderSurface();
419     }
420     m_updateList.clear();
421 }
422
423 }