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