14cdf1c0808b351c4d0ac26a87c60b3ba5ae043e
[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 bool CCSingleThreadProxy::initializeLayerRenderer()
157 {
158     ASSERT(CCProxy::isMainThread());
159     ASSERT(m_contextBeforeInitialization);
160     {
161         DebugScopedSetImplThread impl;
162         bool ok = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitialization.release(), UnthrottledUploader);
163         if (ok) {
164             m_layerRendererInitialized = true;
165             m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities();
166         } else
167             // If we couldn't initialize the layer renderer, we shouldn't process any future animation events.
168             m_animationTimer->stop();
169
170         return ok;
171     }
172 }
173
174 bool CCSingleThreadProxy::recreateContext()
175 {
176     TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext");
177     ASSERT(CCProxy::isMainThread());
178     ASSERT(m_contextLost);
179
180     RefPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
181     if (!context)
182         return false;
183
184     ASSERT(context->hasOneRef());
185     bool initialized;
186     {
187         DebugScopedSetImplThread impl;
188         m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
189         initialized = m_layerTreeHostImpl->initializeLayerRenderer(context, UnthrottledUploader);
190         if (initialized) {
191             m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities();
192         }
193     }
194
195     if (initialized)
196         m_contextLost = false;
197
198     return initialized;
199 }
200
201 const LayerRendererCapabilities& CCSingleThreadProxy::layerRendererCapabilities() const
202 {
203     ASSERT(m_layerRendererInitialized);
204     // Note: this gets called during the commit by the "impl" thread
205     return m_layerRendererCapabilitiesForMainThread;
206 }
207
208 void CCSingleThreadProxy::loseContext()
209 {
210     ASSERT(CCProxy::isMainThread());
211     m_layerTreeHost->didLoseContext();
212     m_contextLost = true;
213 }
214
215 void CCSingleThreadProxy::setNeedsAnimate()
216 {
217     // CCThread-only feature
218     ASSERT_NOT_REACHED();
219 }
220
221 void CCSingleThreadProxy::doCommit(CCTextureUpdater& updater)
222 {
223     ASSERT(CCProxy::isMainThread());
224     // Commit immediately
225     {
226         DebugScopedSetMainThreadBlocked mainThreadBlocked;
227         DebugScopedSetImplThread impl;
228
229         m_layerTreeHostImpl->beginCommit();
230
231         m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
232
233         // CCTextureUpdater is non-blocking and will return without updating
234         // any textures if the uploader is busy. This shouldn't be a problem
235         // here as the throttled uploader isn't used in single thread mode.
236         // For correctness, loop until no more updates are pending.
237         while (updater.hasMoreUpdates())
238             updater.update(m_layerTreeHostImpl->context(), m_layerTreeHostImpl->contentsTextureAllocator(), m_layerTreeHostImpl->layerRenderer()->textureCopier(), m_layerTreeHostImpl->layerRenderer()->textureUploader(), maxPartialTextureUpdates());
239
240         m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
241
242         m_layerTreeHostImpl->commitComplete();
243
244 #if !ASSERT_DISABLED
245         // In the single-threaded case, the scroll deltas should never be
246         // touched on the impl layer tree.
247         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
248         ASSERT(!scrollInfo->scrolls.size());
249 #endif
250     }
251     m_layerTreeHost->commitComplete();
252     m_nextFrameIsNewlyCommittedFrame = true;
253 }
254
255 void CCSingleThreadProxy::setNeedsCommit()
256 {
257     ASSERT(CCProxy::isMainThread());
258     m_layerTreeHost->scheduleComposite();
259 }
260
261 void CCSingleThreadProxy::setNeedsForcedCommit()
262 {
263     // This proxy doesn't block commits when not visible so use a normal commit.
264     setNeedsCommit();
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         m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
294         m_layerTreeHostImpl.clear();
295     }
296     m_layerTreeHost = 0;
297 }
298
299 void CCSingleThreadProxy::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
300 {
301     ASSERT(isMainThread());
302     DebugScopedSetImplThread impl;
303     m_layerTreeHostImpl->setFontAtlas(fontAtlas);
304 }
305
306 void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
307 {
308     ASSERT(CCProxy::isImplThread());
309     DebugScopedSetMainThread main;
310     m_layerTreeHost->setAnimationEvents(events, wallClockTime);
311 }
312
313 void CCSingleThreadProxy::postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t bytes)
314 {
315     ASSERT(CCProxy::isImplThread());
316     DebugScopedSetMainThread main;
317     ASSERT(m_layerTreeHost);
318     m_layerTreeHost->setContentsMemoryAllocationLimitBytes(bytes);
319 }
320
321 // Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
322 void CCSingleThreadProxy::compositeImmediately()
323 {
324     if (commitAndComposite()) {
325         m_layerTreeHostImpl->swapBuffers();
326         didSwapFrame();
327     }
328 }
329
330 double CCSingleThreadProxy::animationTimerDelay()
331 {
332     return 1 / 60.0;
333 }
334
335 void CCSingleThreadProxy::forceSerializeOnSwapBuffers()
336 {
337     {
338         DebugScopedSetImplThread impl;
339         if (m_layerRendererInitialized)
340             m_layerTreeHostImpl->layerRenderer()->doNoOp();
341     }
342 }
343
344 bool CCSingleThreadProxy::commitAndComposite()
345 {
346     ASSERT(CCProxy::isMainThread());
347
348     if (!m_layerTreeHost->initializeLayerRendererIfNeeded())
349         return false;
350
351     CCTextureUpdater updater;
352     m_layerTreeHost->updateLayers(updater);
353
354     m_layerTreeHost->willCommit();
355     doCommit(updater);
356     bool result = doComposite();
357     m_layerTreeHost->didBeginFrame();
358     return result;
359 }
360
361 bool CCSingleThreadProxy::doComposite()
362 {
363     ASSERT(!m_contextLost);
364     {
365         DebugScopedSetImplThread impl;
366
367         if (!m_layerTreeHostImpl->visible())
368             return false;
369
370         double monotonicTime = monotonicallyIncreasingTime();
371         double wallClockTime = currentTime();
372         m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
373
374         // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
375         // be used when such a frame is possible. Since drawLayers() depends on the result of
376         // prepareToDraw(), it is guarded on canDraw() as well.
377         if (!m_layerTreeHostImpl->canDraw())
378             return false;
379
380         CCLayerTreeHostImpl::FrameData frame;
381         m_layerTreeHostImpl->prepareToDraw(frame);
382         m_layerTreeHostImpl->drawLayers(frame);
383         m_layerTreeHostImpl->didDrawAllLayers(frame);
384     }
385
386     if (m_layerTreeHostImpl->isContextLost()) {
387         m_contextLost = true;
388         m_layerTreeHost->didLoseContext();
389         return false;
390     }
391
392     return true;
393 }
394
395 void CCSingleThreadProxy::didSwapFrame()
396 {
397     if (m_nextFrameIsNewlyCommittedFrame) {
398         m_nextFrameIsNewlyCommittedFrame = false;
399         m_layerTreeHost->didCommitAndDrawFrame();
400     }
401 }
402
403 }