1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "CCSingleThreadProxy.h"
9 #include "CCDrawQuad.h"
10 #include "CCGraphicsContext.h"
11 #include "CCLayerTreeHost.h"
12 #include "CCTextureUpdateController.h"
14 #include "TraceEvent.h"
15 #include <wtf/CurrentTime.h>
21 PassOwnPtr
<CCProxy
> CCSingleThreadProxy::create(CCLayerTreeHost
* layerTreeHost
)
23 return adoptPtr(new CCSingleThreadProxy(layerTreeHost
));
26 CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost
* layerTreeHost
)
27 : m_layerTreeHost(layerTreeHost
)
28 , m_contextLost(false)
29 , m_rendererInitialized(false)
30 , m_nextFrameIsNewlyCommittedFrame(false)
32 TRACE_EVENT0("cc", "CCSingleThreadProxy::CCSingleThreadProxy");
33 ASSERT(CCProxy::isMainThread());
36 void CCSingleThreadProxy::start()
38 DebugScopedSetImplThread impl
;
39 m_layerTreeHostImpl
= m_layerTreeHost
->createLayerTreeHostImpl(this);
42 CCSingleThreadProxy::~CCSingleThreadProxy()
44 TRACE_EVENT0("cc", "CCSingleThreadProxy::~CCSingleThreadProxy");
45 ASSERT(CCProxy::isMainThread());
46 ASSERT(!m_layerTreeHostImpl
&& !m_layerTreeHost
); // make sure stop() got called.
49 bool CCSingleThreadProxy::compositeAndReadback(void *pixels
, const IntRect
& rect
)
51 TRACE_EVENT0("cc", "CCSingleThreadProxy::compositeAndReadback");
52 ASSERT(CCProxy::isMainThread());
54 if (!commitAndComposite())
57 m_layerTreeHostImpl
->readback(pixels
, rect
);
59 if (m_layerTreeHostImpl
->isContextLost())
62 m_layerTreeHostImpl
->swapBuffers();
68 void CCSingleThreadProxy::startPageScaleAnimation(const IntSize
& targetPosition
, bool useAnchor
, float scale
, double duration
)
70 m_layerTreeHostImpl
->startPageScaleAnimation(targetPosition
, useAnchor
, scale
, monotonicallyIncreasingTime(), duration
);
73 void CCSingleThreadProxy::finishAllRendering()
75 ASSERT(CCProxy::isMainThread());
77 DebugScopedSetImplThread impl
;
78 m_layerTreeHostImpl
->finishAllRendering();
82 bool CCSingleThreadProxy::isStarted() const
84 ASSERT(CCProxy::isMainThread());
85 return m_layerTreeHostImpl
;
88 bool CCSingleThreadProxy::initializeContext()
90 ASSERT(CCProxy::isMainThread());
91 OwnPtr
<CCGraphicsContext
> context
= m_layerTreeHost
->createContext();
94 m_contextBeforeInitialization
= context
.release();
98 void CCSingleThreadProxy::setSurfaceReady()
100 // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
103 void CCSingleThreadProxy::setVisible(bool visible
)
105 DebugScopedSetImplThread impl
;
106 m_layerTreeHostImpl
->setVisible(visible
);
109 bool CCSingleThreadProxy::initializeRenderer()
111 ASSERT(CCProxy::isMainThread());
112 ASSERT(m_contextBeforeInitialization
);
114 DebugScopedSetImplThread impl
;
115 bool ok
= m_layerTreeHostImpl
->initializeRenderer(m_contextBeforeInitialization
.release(), UnthrottledUploader
);
117 m_rendererInitialized
= true;
118 m_RendererCapabilitiesForMainThread
= m_layerTreeHostImpl
->rendererCapabilities();
125 bool CCSingleThreadProxy::recreateContext()
127 TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext");
128 ASSERT(CCProxy::isMainThread());
129 ASSERT(m_contextLost
);
131 OwnPtr
<CCGraphicsContext
> context
= m_layerTreeHost
->createContext();
137 DebugScopedSetMainThreadBlocked mainThreadBlocked
;
138 DebugScopedSetImplThread impl
;
139 if (!m_layerTreeHostImpl
->contentsTexturesPurged())
140 m_layerTreeHost
->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl
->resourceProvider());
141 initialized
= m_layerTreeHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
143 m_RendererCapabilitiesForMainThread
= m_layerTreeHostImpl
->rendererCapabilities();
148 m_contextLost
= false;
153 void CCSingleThreadProxy::implSideRenderingStats(CCRenderingStats
& stats
)
155 m_layerTreeHostImpl
->renderingStats(stats
);
158 const RendererCapabilities
& CCSingleThreadProxy::rendererCapabilities() const
160 ASSERT(m_rendererInitialized
);
161 // Note: this gets called during the commit by the "impl" thread
162 return m_RendererCapabilitiesForMainThread
;
165 void CCSingleThreadProxy::loseContext()
167 ASSERT(CCProxy::isMainThread());
168 m_layerTreeHost
->didLoseContext();
169 m_contextLost
= true;
172 void CCSingleThreadProxy::setNeedsAnimate()
174 // CCThread-only feature
175 ASSERT_NOT_REACHED();
178 void CCSingleThreadProxy::doCommit(CCTextureUpdateQueue
& queue
)
180 ASSERT(CCProxy::isMainThread());
181 // Commit immediately
183 DebugScopedSetMainThreadBlocked mainThreadBlocked
;
184 DebugScopedSetImplThread impl
;
186 m_layerTreeHostImpl
->beginCommit();
188 m_layerTreeHost
->beginCommitOnImplThread(m_layerTreeHostImpl
.get());
190 // CCTextureUpdateController::updateTextures is non-blocking and will
191 // return without updating any textures if the uploader is busy. This
192 // shouldn't be a problem here as the throttled uploader isn't used in
193 // single thread mode. For correctness, loop until no more updates are
195 while (queue
.hasMoreUpdates())
196 CCTextureUpdateController::updateTextures(m_layerTreeHostImpl
->resourceProvider(), m_layerTreeHostImpl
->renderer()->textureCopier(), m_layerTreeHostImpl
->renderer()->textureUploader(), &queue
, maxPartialTextureUpdates());
198 m_layerTreeHost
->finishCommitOnImplThread(m_layerTreeHostImpl
.get());
200 m_layerTreeHostImpl
->commitComplete();
203 // In the single-threaded case, the scroll deltas should never be
204 // touched on the impl layer tree.
205 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_layerTreeHostImpl
->processScrollDeltas();
206 ASSERT(!scrollInfo
->scrolls
.size());
209 m_layerTreeHost
->commitComplete();
210 m_nextFrameIsNewlyCommittedFrame
= true;
213 void CCSingleThreadProxy::setNeedsCommit()
215 ASSERT(CCProxy::isMainThread());
216 m_layerTreeHost
->scheduleComposite();
219 void CCSingleThreadProxy::setNeedsRedraw()
221 // FIXME: Once we move render_widget scheduling into this class, we can
222 // treat redraw requests more efficiently than commitAndRedraw requests.
223 m_layerTreeHostImpl
->setFullRootLayerDamage();
227 bool CCSingleThreadProxy::commitRequested() const
232 void CCSingleThreadProxy::didAddAnimation()
236 void CCSingleThreadProxy::stop()
238 TRACE_EVENT0("cc", "CCSingleThreadProxy::stop");
239 ASSERT(CCProxy::isMainThread());
241 DebugScopedSetMainThreadBlocked mainThreadBlocked
;
242 DebugScopedSetImplThread impl
;
244 if (!m_layerTreeHostImpl
->contentsTexturesPurged())
245 m_layerTreeHost
->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl
->resourceProvider());
246 m_layerTreeHostImpl
.clear();
251 void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr
<CCAnimationEventsVector
> events
, double wallClockTime
)
253 ASSERT(CCProxy::isImplThread());
254 DebugScopedSetMainThread main
;
255 m_layerTreeHost
->setAnimationEvents(events
, wallClockTime
);
258 // Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
259 void CCSingleThreadProxy::compositeImmediately()
261 if (commitAndComposite()) {
262 m_layerTreeHostImpl
->swapBuffers();
267 void CCSingleThreadProxy::forceSerializeOnSwapBuffers()
270 DebugScopedSetImplThread impl
;
271 if (m_rendererInitialized
)
272 m_layerTreeHostImpl
->renderer()->doNoOp();
276 bool CCSingleThreadProxy::commitAndComposite()
278 ASSERT(CCProxy::isMainThread());
280 if (!m_layerTreeHost
->initializeRendererIfNeeded())
283 if (m_layerTreeHostImpl
->contentsTexturesPurged()) {
284 m_layerTreeHost
->unlinkAllContentTextures();
285 DebugScopedSetImplThreadAndMainThreadBlocked implAndMainBlocked
;
286 m_layerTreeHost
->deleteUnlinkedTextures();
289 CCTextureUpdateQueue queue
;
290 m_layerTreeHost
->updateLayers(queue
, m_layerTreeHostImpl
->memoryAllocationLimitBytes());
291 m_layerTreeHostImpl
->resetContentsTexturesPurged();
293 m_layerTreeHost
->willCommit();
295 bool result
= doComposite();
296 m_layerTreeHost
->didBeginFrame();
300 bool CCSingleThreadProxy::doComposite()
302 ASSERT(!m_contextLost
);
304 DebugScopedSetImplThread impl
;
306 if (!m_layerTreeHostImpl
->visible())
309 double monotonicTime
= monotonicallyIncreasingTime();
310 double wallClockTime
= currentTime();
311 m_layerTreeHostImpl
->animate(monotonicTime
, wallClockTime
);
313 // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
314 // be used when such a frame is possible. Since drawLayers() depends on the result of
315 // prepareToDraw(), it is guarded on canDraw() as well.
316 if (!m_layerTreeHostImpl
->canDraw())
319 CCLayerTreeHostImpl::FrameData frame
;
320 m_layerTreeHostImpl
->prepareToDraw(frame
);
321 m_layerTreeHostImpl
->drawLayers(frame
);
322 m_layerTreeHostImpl
->didDrawAllLayers(frame
);
325 if (m_layerTreeHostImpl
->isContextLost()) {
326 m_contextLost
= true;
327 m_layerTreeHost
->didLoseContext();
334 void CCSingleThreadProxy::didSwapFrame()
336 if (m_nextFrameIsNewlyCommittedFrame
) {
337 m_nextFrameIsNewlyCommittedFrame
= false;
338 m_layerTreeHost
->didCommitAndDrawFrame();