[chromium] LayerRendererChromium is not getting visibility messages in single threade...
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCSingleThreadProxy.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/CCSingleThreadProxy.h"
28
29 #include "TraceEvent.h"
30 #include "cc/CCDrawQuad.h"
31 #include "cc/CCFontAtlas.h"
32 #include "cc/CCGraphicsContext.h"
33 #include "cc/CCLayerTreeHost.h"
34 #include "cc/CCTextureUpdater.h"
35 #include "cc/CCTimer.h"
36 #include <wtf/CurrentTime.h>
37
38 using namespace WTF;
39
40 namespace WebCore {
41
42 class CCSingleThreadProxyAnimationTimer : public CCTimer, CCTimerClient {
43 public:
44     static PassOwnPtr<CCSingleThreadProxyAnimationTimer> create(CCSingleThreadProxy* proxy) { return adoptPtr(new CCSingleThreadProxyAnimationTimer(proxy)); }
45
46     virtual void onTimerFired() OVERRIDE
47     {
48         if (m_proxy->m_layerRendererInitialized)
49             m_proxy->compositeImmediately();
50     }
51
52 private:
53     explicit CCSingleThreadProxyAnimationTimer(CCSingleThreadProxy* proxy)
54         : CCTimer(CCProxy::mainThread(), this)
55         , m_proxy(proxy)
56     {
57     }
58
59     CCSingleThreadProxy* m_proxy;
60 };
61
62 PassOwnPtr<CCProxy> CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost)
63 {
64     return adoptPtr(new CCSingleThreadProxy(layerTreeHost));
65 }
66
67 CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost)
68     : m_layerTreeHost(layerTreeHost)
69     , m_contextLost(false)
70     , m_compositorIdentifier(-1)
71     , m_animationTimer(CCSingleThreadProxyAnimationTimer::create(this))
72     , m_layerRendererInitialized(false)
73     , m_nextFrameIsNewlyCommittedFrame(false)
74 {
75     TRACE_EVENT("CCSingleThreadProxy::CCSingleThreadProxy", this, 0);
76     ASSERT(CCProxy::isMainThread());
77 }
78
79 void CCSingleThreadProxy::start()
80 {
81     DebugScopedSetImplThread impl;
82     m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
83 }
84
85 CCSingleThreadProxy::~CCSingleThreadProxy()
86 {
87     TRACE_EVENT("CCSingleThreadProxy::~CCSingleThreadProxy", this, 0);
88     ASSERT(CCProxy::isMainThread());
89     ASSERT(!m_layerTreeHostImpl && !m_layerTreeHost); // make sure stop() got called.
90 }
91
92 bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
93 {
94     TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0);
95     ASSERT(CCProxy::isMainThread());
96
97     if (!commitAndComposite())
98         return false;
99
100     m_layerTreeHostImpl->readback(pixels, rect);
101
102     if (m_layerTreeHostImpl->isContextLost())
103         return false;
104
105     m_layerTreeHostImpl->swapBuffers();
106     didSwapFrame();
107
108     return true;
109 }
110
111 void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration)
112 {
113     m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration);
114 }
115
116 CCGraphicsContext* CCSingleThreadProxy::context()
117 {
118     ASSERT(CCProxy::isMainThread());
119     if (m_contextBeforeInitialization)
120         return m_contextBeforeInitialization.get();
121     DebugScopedSetImplThread impl;
122     return m_layerTreeHostImpl->context();
123 }
124
125 void CCSingleThreadProxy::finishAllRendering()
126 {
127     ASSERT(CCProxy::isMainThread());
128     {
129         DebugScopedSetImplThread impl;
130         m_layerTreeHostImpl->finishAllRendering();
131     }
132 }
133
134 bool CCSingleThreadProxy::isStarted() const
135 {
136     ASSERT(CCProxy::isMainThread());
137     return m_layerTreeHostImpl;
138 }
139
140 bool CCSingleThreadProxy::initializeContext()
141 {
142     ASSERT(CCProxy::isMainThread());
143     RefPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
144     if (!context)
145         return false;
146     ASSERT(context->hasOneRef());
147     m_contextBeforeInitialization = context;
148     return true;
149 }
150
151 void CCSingleThreadProxy::setSurfaceReady()
152 {
153     // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
154 }
155
156 void CCSingleThreadProxy::setVisible(bool visible)
157 {
158     DebugScopedSetImplThread impl;
159     m_layerTreeHostImpl->setVisible(visible);
160 }
161
162 bool CCSingleThreadProxy::initializeLayerRenderer()
163 {
164     ASSERT(CCProxy::isMainThread());
165     ASSERT(m_contextBeforeInitialization);
166     {
167         DebugScopedSetImplThread impl;
168         bool ok = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitialization.release(), UnthrottledUploader);
169         if (ok) {
170             m_layerRendererInitialized = true;
171             m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities();
172         } else
173             // If we couldn't initialize the layer renderer, we shouldn't process any future animation events.
174             m_animationTimer->stop();
175
176         return ok;
177     }
178 }
179
180 bool CCSingleThreadProxy::recreateContext()
181 {
182     TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext");
183     ASSERT(CCProxy::isMainThread());
184     ASSERT(m_contextLost);
185
186     RefPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
187     if (!context)
188         return false;
189
190     ASSERT(context->hasOneRef());
191     bool initialized;
192     {
193         DebugScopedSetImplThread impl;
194         m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
195         initialized = m_layerTreeHostImpl->initializeLayerRenderer(context, UnthrottledUploader);
196         if (initialized) {
197             m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities();
198         }
199     }
200
201     if (initialized)
202         m_contextLost = false;
203
204     return initialized;
205 }
206
207 const LayerRendererCapabilities& CCSingleThreadProxy::layerRendererCapabilities() const
208 {
209     ASSERT(m_layerRendererInitialized);
210     // Note: this gets called during the commit by the "impl" thread
211     return m_layerRendererCapabilitiesForMainThread;
212 }
213
214 void CCSingleThreadProxy::loseContext()
215 {
216     ASSERT(CCProxy::isMainThread());
217     m_layerTreeHost->didLoseContext();
218     m_contextLost = true;
219 }
220
221 void CCSingleThreadProxy::setNeedsAnimate()
222 {
223     // CCThread-only feature
224     ASSERT_NOT_REACHED();
225 }
226
227 void CCSingleThreadProxy::doCommit(CCTextureUpdater& updater)
228 {
229     ASSERT(CCProxy::isMainThread());
230     // Commit immediately
231     {
232         DebugScopedSetMainThreadBlocked mainThreadBlocked;
233         DebugScopedSetImplThread impl;
234
235         m_layerTreeHostImpl->beginCommit();
236
237         m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
238
239         // CCTextureUpdater is non-blocking and will return without updating
240         // any textures if the uploader is busy. This shouldn't be a problem
241         // here as the throttled uploader isn't used in single thread mode.
242         // For correctness, loop until no more updates are pending.
243         while (updater.hasMoreUpdates())
244             updater.update(m_layerTreeHostImpl->context(), m_layerTreeHostImpl->contentsTextureAllocator(), m_layerTreeHostImpl->layerRenderer()->textureCopier(), m_layerTreeHostImpl->layerRenderer()->textureUploader(), maxPartialTextureUpdates());
245
246         m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
247
248         m_layerTreeHostImpl->commitComplete();
249
250 #if !ASSERT_DISABLED
251         // In the single-threaded case, the scroll deltas should never be
252         // touched on the impl layer tree.
253         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
254         ASSERT(!scrollInfo->scrolls.size());
255 #endif
256     }
257     m_layerTreeHost->commitComplete();
258     m_nextFrameIsNewlyCommittedFrame = true;
259 }
260
261 void CCSingleThreadProxy::setNeedsCommit()
262 {
263     ASSERT(CCProxy::isMainThread());
264     m_layerTreeHost->scheduleComposite();
265 }
266
267 void CCSingleThreadProxy::setNeedsRedraw()
268 {
269     // FIXME: Once we move render_widget scheduling into this class, we can
270     // treat redraw requests more efficiently than commitAndRedraw requests.
271     m_layerTreeHostImpl->setFullRootLayerDamage();
272     setNeedsCommit();
273 }
274
275 bool CCSingleThreadProxy::commitRequested() const
276 {
277     return false;
278 }
279
280 void CCSingleThreadProxy::didAddAnimation()
281 {
282     m_animationTimer->startOneShot(animationTimerDelay());
283 }
284
285 void CCSingleThreadProxy::stop()
286 {
287     TRACE_EVENT("CCSingleThreadProxy::stop", this, 0);
288     ASSERT(CCProxy::isMainThread());
289     {
290         DebugScopedSetMainThreadBlocked mainThreadBlocked;
291         DebugScopedSetImplThread impl;
292
293         if (!m_layerTreeHostImpl->contentsTexturesWerePurgedSinceLastCommit())
294             m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
295         m_layerTreeHostImpl.clear();
296     }
297     m_layerTreeHost = 0;
298 }
299
300 void CCSingleThreadProxy::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
301 {
302     ASSERT(isMainThread());
303     DebugScopedSetImplThread impl;
304     m_layerTreeHostImpl->setFontAtlas(fontAtlas);
305 }
306
307 void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
308 {
309     ASSERT(CCProxy::isImplThread());
310     DebugScopedSetMainThread main;
311     m_layerTreeHost->setAnimationEvents(events, wallClockTime);
312 }
313
314 // Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
315 void CCSingleThreadProxy::compositeImmediately()
316 {
317     if (commitAndComposite()) {
318         m_layerTreeHostImpl->swapBuffers();
319         didSwapFrame();
320     }
321 }
322
323 double CCSingleThreadProxy::animationTimerDelay()
324 {
325     return 1 / 60.0;
326 }
327
328 void CCSingleThreadProxy::forceSerializeOnSwapBuffers()
329 {
330     {
331         DebugScopedSetImplThread impl;
332         if (m_layerRendererInitialized)
333             m_layerTreeHostImpl->layerRenderer()->doNoOp();
334     }
335 }
336
337 bool CCSingleThreadProxy::commitAndComposite()
338 {
339     ASSERT(CCProxy::isMainThread());
340
341
342     if (!m_layerTreeHost->initializeLayerRendererIfNeeded())
343         return false;
344
345     if (m_layerTreeHostImpl->contentsTexturesWerePurgedSinceLastCommit())
346         m_layerTreeHost->evictAllContentTextures();
347
348     CCTextureUpdater updater;
349     m_layerTreeHost->updateLayers(updater, m_layerTreeHostImpl->memoryAllocationLimitBytes());
350
351     m_layerTreeHost->willCommit();
352     doCommit(updater);
353     bool result = doComposite();
354     m_layerTreeHost->didBeginFrame();
355     return result;
356 }
357
358 bool CCSingleThreadProxy::doComposite()
359 {
360     ASSERT(!m_contextLost);
361     {
362         DebugScopedSetImplThread impl;
363
364         if (!m_layerTreeHostImpl->visible())
365             return false;
366
367         double monotonicTime = monotonicallyIncreasingTime();
368         double wallClockTime = currentTime();
369         m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
370
371         // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
372         // be used when such a frame is possible. Since drawLayers() depends on the result of
373         // prepareToDraw(), it is guarded on canDraw() as well.
374         if (!m_layerTreeHostImpl->canDraw())
375             return false;
376
377         CCLayerTreeHostImpl::FrameData frame;
378         m_layerTreeHostImpl->prepareToDraw(frame);
379         m_layerTreeHostImpl->drawLayers(frame);
380         m_layerTreeHostImpl->didDrawAllLayers(frame);
381     }
382
383     if (m_layerTreeHostImpl->isContextLost()) {
384         m_contextLost = true;
385         m_layerTreeHost->didLoseContext();
386         return false;
387     }
388
389     return true;
390 }
391
392 void CCSingleThreadProxy::didSwapFrame()
393 {
394     if (m_nextFrameIsNewlyCommittedFrame) {
395         m_nextFrameIsNewlyCommittedFrame = false;
396         m_layerTreeHost->didCommitAndDrawFrame();
397     }
398 }
399
400 }