[chromium] Apply sent deltas on finishCommit
[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
144     // Synchronize trees, if one exists at all...
145     if (rootLayer())
146         hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer()));
147     else
148         hostImpl->setRootLayer(0);
149
150     hostImpl->setSourceFrameNumber(frameNumber());
151     hostImpl->setHaveWheelEventHandlers(m_haveWheelEventHandlers);
152     hostImpl->setZoomAnimatorTransform(m_zoomAnimatorTransform);
153     hostImpl->setViewport(viewportSize());
154     hostImpl->setPageScaleFactorAndLimits(pageScale(), m_minPageScale, m_maxPageScale);
155
156     m_frameNumber++;
157 }
158
159 void CCLayerTreeHost::commitComplete()
160 {
161     clearPendingUpdate();
162     m_contentsTextureManager->unprotectAllTextures();
163 }
164
165 PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createLayerTreeHostContext3D()
166 {
167     return m_client->createLayerTreeHostContext3D();
168 }
169
170 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
171 {
172     return CCLayerTreeHostImpl::create(m_settings, client);
173 }
174
175 void CCLayerTreeHost::didRecreateGraphicsContext(bool success)
176 {
177     if (rootLayer())
178         rootLayer()->cleanupResourcesRecursive();
179     m_client->didRecreateGraphicsContext(success);
180 }
181
182 // Temporary hack until WebViewImpl context creation gets simplified
183 GraphicsContext3D* CCLayerTreeHost::context()
184 {
185     ASSERT(!CCProxy::hasImplThread());
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::setZoomAnimatorTransform(const TransformationMatrix& zoom)
205 {
206     bool zoomChanged = m_zoomAnimatorTransform != zoom;
207
208     m_zoomAnimatorTransform = zoom;
209
210     if (zoomChanged)
211         setNeedsCommit();
212 }
213
214 void CCLayerTreeHost::setNeedsAnimate()
215 {
216     ASSERT(CCProxy::hasImplThread());
217     m_proxy->setNeedsAnimate();
218 }
219
220 void CCLayerTreeHost::setNeedsCommit()
221 {
222     if (CCThreadProxy::implThread()) {
223         TRACE_EVENT("CCLayerTreeHost::setNeedsCommit", this, 0);
224         m_proxy->setNeedsCommit();
225     } else
226         m_client->scheduleComposite();
227 }
228
229 void CCLayerTreeHost::setNeedsRedraw()
230 {
231     if (CCThreadProxy::implThread())
232         m_proxy->setNeedsRedraw();
233     else
234         m_client->scheduleComposite();
235 }
236
237 void CCLayerTreeHost::setViewport(const IntSize& viewportSize)
238 {
239     contentsTextureManager()->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(viewportSize));
240     contentsTextureManager()->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(viewportSize));
241     m_viewportSize = viewportSize;
242     setNeedsCommit();
243 }
244
245 void CCLayerTreeHost::setPageScale(float pageScale)
246 {
247     if (pageScale == m_pageScale)
248         return;
249
250     m_pageScale = pageScale;
251     setNeedsCommit();
252 }
253
254 void CCLayerTreeHost::setPageScaleFactorLimits(float minScale, float maxScale)
255 {
256     if (minScale == m_minPageScale && maxScale == m_maxPageScale)
257         return;
258
259     m_minPageScale = minScale;
260     m_maxPageScale = maxScale;
261     setNeedsCommit();
262 }
263
264 void CCLayerTreeHost::setVisible(bool visible)
265 {
266     if (m_visible == visible)
267         return;
268
269     m_visible = visible;
270     if (!visible) {
271         m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes(viewportSize()));
272         m_contentsTextureManager->unprotectAllTextures();
273     }
274
275     // Tells the proxy that visibility state has changed. This will in turn call
276     // CCLayerTreeHost::didBecomeInvisibleOnImplThread on the appropriate thread, for
277     // the case where !visible.
278     m_proxy->setVisible(visible);
279 }
280
281 void CCLayerTreeHost::didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl* hostImpl)
282 {
283     ASSERT(CCProxy::isImplThread());
284     if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer)
285         contentsTextureManager()->evictAndDeleteAllTextures(hostImpl->contentsTextureAllocator());
286     else {
287         contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize()));
288         contentsTextureManager()->deleteEvictedTextures(hostImpl->contentsTextureAllocator());
289     }
290 }
291
292 void CCLayerTreeHost::setHaveWheelEventHandlers(bool haveWheelEventHandlers)
293 {
294     if (m_haveWheelEventHandlers == haveWheelEventHandlers)
295         return;
296     m_haveWheelEventHandlers = haveWheelEventHandlers;
297     m_proxy->setNeedsCommit();
298 }
299
300
301 void CCLayerTreeHost::loseCompositorContext(int numTimes)
302 {
303     m_proxy->loseCompositorContext(numTimes);
304 }
305
306 TextureManager* CCLayerTreeHost::contentsTextureManager() const
307 {
308     return m_contentsTextureManager.get();
309 }
310
311 void CCLayerTreeHost::composite()
312 {
313     ASSERT(!CCThreadProxy::implThread());
314     static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately();
315 }
316
317 void CCLayerTreeHost::updateLayers()
318 {
319     if (!rootLayer())
320         return;
321
322     if (viewportSize().isEmpty())
323         return;
324
325     updateLayers(rootLayer());
326 }
327
328 void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer)
329 {
330     TRACE_EVENT("CCLayerTreeHost::updateLayers", this, 0);
331
332     if (!rootLayer->renderSurface())
333         rootLayer->createRenderSurface();
334     rootLayer->renderSurface()->setContentRect(IntRect(IntPoint(0, 0), viewportSize()));
335
336     IntRect rootClipRect(IntPoint(), viewportSize());
337     rootLayer->setClipRect(rootClipRect);
338
339     // This assert fires if updateCompositorResources wasn't called after
340     // updateLayers. Only one update can be pending at any given time.
341     ASSERT(!m_updateList.size());
342     m_updateList.append(rootLayer);
343
344     RenderSurfaceChromium* rootRenderSurface = rootLayer->renderSurface();
345     rootRenderSurface->clearLayerList();
346
347     TransformationMatrix identityMatrix;
348     {
349         TRACE_EVENT("CCLayerTreeHost::updateLayers::calcDrawEtc", this, 0);
350         CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
351     }
352
353     paintLayerContents(m_updateList);
354 }
355
356 void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderSurfaceLayer)
357 {
358     // Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
359     // in code, we already know that at least something will be drawn into this render surface, so the
360     // mask and replica should be painted.
361
362     if (renderSurfaceLayer->maskLayer()) {
363         renderSurfaceLayer->maskLayer()->setLayerTreeHost(this);
364         renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
365         renderSurfaceLayer->maskLayer()->paintContentsIfDirty();
366     }
367
368     LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
369     if (replicaLayer) {
370
371         replicaLayer->setLayerTreeHost(this);
372         replicaLayer->paintContentsIfDirty();
373
374         if (replicaLayer->maskLayer()) {
375             replicaLayer->maskLayer()->setLayerTreeHost(this);
376             replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
377             replicaLayer->maskLayer()->paintContentsIfDirty();
378         }
379     }
380 }
381
382 void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList)
383 {
384     for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
385         LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
386         RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
387         ASSERT(renderSurface);
388         ASSERT(renderSurface->drawOpacity());
389
390         renderSurfaceLayer->setLayerTreeHost(this);
391         paintMaskAndReplicaForRenderSurface(renderSurfaceLayer);
392
393         const LayerList& layerList = renderSurface->layerList();
394         for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
395             LayerChromium* layer = layerList[layerIndex].get();
396
397             // Layers that start a new render surface will be painted when the render
398             // surface's list is processed.
399             if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<LayerChromium>(layer, renderSurfaceLayer->id()))
400                 continue;
401
402             layer->setLayerTreeHost(this);
403
404             ASSERT(layer->opacity());
405             ASSERT(!layer->bounds().isEmpty());
406
407             layer->paintContentsIfDirty();
408         }
409     }
410 }
411
412 void CCLayerTreeHost::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
413 {
414     for (int surfaceIndex = m_updateList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
415         LayerChromium* renderSurfaceLayer = m_updateList[surfaceIndex].get();
416         RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
417         ASSERT(renderSurface);
418         ASSERT(renderSurface->drawOpacity());
419
420         if (renderSurfaceLayer->maskLayer())
421             renderSurfaceLayer->maskLayer()->updateCompositorResources(context, updater);
422
423         if (renderSurfaceLayer->replicaLayer()) {
424             renderSurfaceLayer->replicaLayer()->updateCompositorResources(context, updater);
425             
426             if (renderSurfaceLayer->replicaLayer()->maskLayer())
427                 renderSurfaceLayer->replicaLayer()->maskLayer()->updateCompositorResources(context, updater);
428         }
429         
430         const LayerList& layerList = renderSurface->layerList();
431         for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
432             LayerChromium* layer = layerList[layerIndex].get();
433
434             if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<LayerChromium>(layer, renderSurfaceLayer->id()))
435                 continue;
436
437             layer->updateCompositorResources(context, updater);
438         }
439     }
440 }
441
442 void CCLayerTreeHost::clearPendingUpdate()
443 {
444     for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
445         LayerChromium* layer = m_updateList[surfaceIndex].get();
446         ASSERT(layer->renderSurface());
447         layer->clearRenderSurface();
448     }
449     m_updateList.clear();
450 }
451
452 void CCLayerTreeHost::applyScrollAndScale(const CCScrollAndScaleSet& info)
453 {
454     // FIXME: pushing scroll offsets to non-root layers not implemented
455     if (!info.scrolls.size())
456         return;
457
458     ASSERT(info.scrolls.size() == 1);
459     IntSize scrollDelta = info.scrolls[0].scrollDelta;
460     m_client->applyScrollAndScale(scrollDelta, info.pageScaleDelta);
461 }
462
463 void CCLayerTreeHost::startRateLimiter(GraphicsContext3D* context)
464 {
465     if (animating())
466         return;
467     ASSERT(context);
468     RateLimiterMap::iterator it = m_rateLimiters.find(context);
469     if (it != m_rateLimiters.end())
470         it->second->start();
471     else {
472         RefPtr<RateLimiter> rateLimiter = RateLimiter::create(context);
473         m_rateLimiters.set(context, rateLimiter);
474         rateLimiter->start();
475     }
476 }
477
478 void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context)
479 {
480     RateLimiterMap::iterator it = m_rateLimiters.find(context);
481     if (it != m_rateLimiters.end()) {
482         it->second->stop();
483         m_rateLimiters.remove(it);
484     }
485 }
486
487 }