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