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