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.
5 #include "cc/single_thread_proxy.h"
7 #include "base/debug/trace_event.h"
8 #include "cc/draw_quad.h"
9 #include "cc/graphics_context.h"
10 #include "cc/layer_tree_host.h"
11 #include "cc/resource_update_controller.h"
12 #include "cc/thread.h"
16 scoped_ptr
<Proxy
> SingleThreadProxy::create(LayerTreeHost
* layerTreeHost
)
18 return make_scoped_ptr(new SingleThreadProxy(layerTreeHost
)).PassAs
<Proxy
>();
21 SingleThreadProxy::SingleThreadProxy(LayerTreeHost
* layerTreeHost
)
22 : Proxy(scoped_ptr
<Thread
>(NULL
))
23 , m_layerTreeHost(layerTreeHost
)
24 , m_contextLost(false)
25 , m_rendererInitialized(false)
26 , m_nextFrameIsNewlyCommittedFrame(false)
27 , m_totalCommitCount(0)
29 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
30 DCHECK(Proxy::isMainThread());
33 void SingleThreadProxy::start()
35 DebugScopedSetImplThread
impl(this);
36 m_layerTreeHostImpl
= m_layerTreeHost
->createLayerTreeHostImpl(this);
39 SingleThreadProxy::~SingleThreadProxy()
41 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
42 DCHECK(Proxy::isMainThread());
43 DCHECK(!m_layerTreeHostImpl
.get() && !m_layerTreeHost
); // make sure stop() got called.
46 bool SingleThreadProxy::compositeAndReadback(void *pixels
, const gfx::Rect
& rect
)
48 TRACE_EVENT0("cc", "SingleThreadProxy::compositeAndReadback");
49 DCHECK(Proxy::isMainThread());
51 if (!commitAndComposite())
54 m_layerTreeHostImpl
->readback(pixels
, rect
);
56 if (m_layerTreeHostImpl
->isContextLost())
59 m_layerTreeHostImpl
->swapBuffers();
65 void SingleThreadProxy::startPageScaleAnimation(gfx::Vector2d targetOffset
, bool useAnchor
, float scale
, base::TimeDelta duration
)
67 m_layerTreeHostImpl
->startPageScaleAnimation(targetOffset
, useAnchor
, scale
, base::TimeTicks::Now(), duration
);
70 void SingleThreadProxy::finishAllRendering()
72 DCHECK(Proxy::isMainThread());
74 DebugScopedSetImplThread
impl(this);
75 m_layerTreeHostImpl
->finishAllRendering();
79 bool SingleThreadProxy::isStarted() const
81 DCHECK(Proxy::isMainThread());
82 return m_layerTreeHostImpl
.get();
85 bool SingleThreadProxy::initializeContext()
87 DCHECK(Proxy::isMainThread());
88 scoped_ptr
<GraphicsContext
> context
= m_layerTreeHost
->createContext();
91 m_contextBeforeInitialization
= context
.Pass();
95 void SingleThreadProxy::setSurfaceReady()
97 // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
100 void SingleThreadProxy::setVisible(bool visible
)
102 DebugScopedSetImplThread
impl(this);
103 m_layerTreeHostImpl
->setVisible(visible
);
106 bool SingleThreadProxy::initializeRenderer()
108 DCHECK(Proxy::isMainThread());
109 DCHECK(m_contextBeforeInitialization
.get());
111 DebugScopedSetImplThread
impl(this);
112 bool ok
= m_layerTreeHostImpl
->initializeRenderer(m_contextBeforeInitialization
.Pass());
114 m_rendererInitialized
= true;
115 m_RendererCapabilitiesForMainThread
= m_layerTreeHostImpl
->rendererCapabilities();
122 bool SingleThreadProxy::recreateContext()
124 TRACE_EVENT0("cc", "SingleThreadProxy::recreateContext");
125 DCHECK(Proxy::isMainThread());
126 DCHECK(m_contextLost
);
128 scoped_ptr
<GraphicsContext
> context
= m_layerTreeHost
->createContext();
134 DebugScopedSetMainThreadBlocked
mainThreadBlocked(this);
135 DebugScopedSetImplThread
impl(this);
136 if (!m_layerTreeHostImpl
->contentsTexturesPurged())
137 m_layerTreeHost
->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl
->resourceProvider());
138 initialized
= m_layerTreeHostImpl
->initializeRenderer(context
.Pass());
140 m_RendererCapabilitiesForMainThread
= m_layerTreeHostImpl
->rendererCapabilities();
145 m_contextLost
= false;
150 void SingleThreadProxy::renderingStats(RenderingStats
* stats
)
152 stats
->totalCommitTimeInSeconds
= m_totalCommitTime
.InSecondsF();
153 stats
->totalCommitCount
= m_totalCommitCount
;
154 m_layerTreeHostImpl
->renderingStats(stats
);
157 const RendererCapabilities
& SingleThreadProxy::rendererCapabilities() const
159 DCHECK(m_rendererInitialized
);
160 // Note: this gets called during the commit by the "impl" thread
161 return m_RendererCapabilitiesForMainThread
;
164 void SingleThreadProxy::loseContext()
166 DCHECK(Proxy::isMainThread());
167 m_layerTreeHost
->didLoseContext();
168 m_contextLost
= true;
171 void SingleThreadProxy::setNeedsAnimate()
173 // Thread-only feature
177 void SingleThreadProxy::doCommit(scoped_ptr
<ResourceUpdateQueue
> queue
)
179 DCHECK(Proxy::isMainThread());
180 // Commit immediately
182 DebugScopedSetMainThreadBlocked
mainThreadBlocked(this);
183 DebugScopedSetImplThread
impl(this);
185 base::TimeTicks startTime
= base::TimeTicks::HighResNow();
186 m_layerTreeHostImpl
->beginCommit();
188 m_layerTreeHost
->contentsTextureManager()->pushTexturePrioritiesToBackings();
189 m_layerTreeHost
->beginCommitOnImplThread(m_layerTreeHostImpl
.get());
191 scoped_ptr
<ResourceUpdateController
> updateController
=
192 ResourceUpdateController::create(
196 m_layerTreeHostImpl
->resourceProvider(),
198 updateController
->finalize();
200 m_layerTreeHost
->finishCommitOnImplThread(m_layerTreeHostImpl
.get());
202 m_layerTreeHostImpl
->commitComplete();
205 // In the single-threaded case, the scroll deltas should never be
206 // touched on the impl layer tree.
207 scoped_ptr
<ScrollAndScaleSet
> scrollInfo
= m_layerTreeHostImpl
->processScrollDeltas();
208 DCHECK(!scrollInfo
->scrolls
.size());
211 base::TimeTicks endTime
= base::TimeTicks::HighResNow();
212 m_totalCommitTime
+= endTime
- startTime
;
213 m_totalCommitCount
++;
215 m_layerTreeHost
->commitComplete();
216 m_nextFrameIsNewlyCommittedFrame
= true;
219 void SingleThreadProxy::setNeedsCommit()
221 DCHECK(Proxy::isMainThread());
222 m_layerTreeHost
->scheduleComposite();
225 void SingleThreadProxy::setNeedsRedraw()
227 // FIXME: Once we move render_widget scheduling into this class, we can
228 // treat redraw requests more efficiently than commitAndRedraw requests.
229 m_layerTreeHostImpl
->setFullRootLayerDamage();
233 void SingleThreadProxy::setDeferCommits(bool deferCommits
)
235 // Thread-only feature.
239 bool SingleThreadProxy::commitRequested() const
244 void SingleThreadProxy::didAddAnimation()
248 size_t SingleThreadProxy::maxPartialTextureUpdates() const
250 return std::numeric_limits
<size_t>::max();
253 void SingleThreadProxy::stop()
255 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
256 DCHECK(Proxy::isMainThread());
258 DebugScopedSetMainThreadBlocked
mainThreadBlocked(this);
259 DebugScopedSetImplThread
impl(this);
261 if (!m_layerTreeHostImpl
->contentsTexturesPurged())
262 m_layerTreeHost
->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl
->resourceProvider());
263 m_layerTreeHostImpl
.reset();
268 void SingleThreadProxy::setNeedsRedrawOnImplThread()
270 m_layerTreeHost
->scheduleComposite();
273 void SingleThreadProxy::setNeedsCommitOnImplThread()
275 m_layerTreeHost
->scheduleComposite();
278 void SingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr
<AnimationEventsVector
> events
, base::Time wallClockTime
)
280 DCHECK(Proxy::isImplThread());
281 DebugScopedSetMainThread
main(this);
282 m_layerTreeHost
->setAnimationEvents(events
.Pass(), wallClockTime
);
285 bool SingleThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes
, int priorityCutoff
)
287 DCHECK(isImplThread());
288 if (!m_layerTreeHost
->contentsTextureManager())
291 return m_layerTreeHost
->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes
, priorityCutoff
, m_layerTreeHostImpl
->resourceProvider());
294 void SingleThreadProxy::sendManagedMemoryStats()
296 DCHECK(Proxy::isImplThread());
297 if (!m_layerTreeHostImpl
.get())
299 if (!m_layerTreeHostImpl
->renderer())
301 if (!m_layerTreeHost
->contentsTextureManager())
304 m_layerTreeHostImpl
->renderer()->sendManagedMemoryStats(
305 m_layerTreeHost
->contentsTextureManager()->memoryVisibleBytes(),
306 m_layerTreeHost
->contentsTextureManager()->memoryVisibleAndNearbyBytes(),
307 m_layerTreeHost
->contentsTextureManager()->memoryUseBytes());
310 // Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
311 void SingleThreadProxy::compositeImmediately()
313 if (commitAndComposite()) {
314 m_layerTreeHostImpl
->swapBuffers();
319 void SingleThreadProxy::forceSerializeOnSwapBuffers()
322 DebugScopedSetImplThread
impl(this);
323 if (m_rendererInitialized
)
324 m_layerTreeHostImpl
->renderer()->doNoOp();
328 void SingleThreadProxy::onSwapBuffersCompleteOnImplThread()
333 bool SingleThreadProxy::commitAndComposite()
335 DCHECK(Proxy::isMainThread());
337 if (!m_layerTreeHost
->initializeRendererIfNeeded())
340 // Unlink any texture backings that were deleted
341 PrioritizedResourceManager::BackingList evictedContentsTexturesBackings
;
343 DebugScopedSetImplThread
impl(this);
344 m_layerTreeHost
->contentsTextureManager()->getEvictedBackings(evictedContentsTexturesBackings
);
346 m_layerTreeHost
->contentsTextureManager()->unlinkEvictedBackings(evictedContentsTexturesBackings
);
348 scoped_ptr
<ResourceUpdateQueue
> queue
= make_scoped_ptr(new ResourceUpdateQueue
);
349 m_layerTreeHost
->updateLayers(*(queue
.get()), m_layerTreeHostImpl
->memoryAllocationLimitBytes());
351 if (m_layerTreeHostImpl
->contentsTexturesPurged())
352 m_layerTreeHostImpl
->resetContentsTexturesPurged();
354 m_layerTreeHost
->willCommit();
355 doCommit(queue
.Pass());
356 bool result
= doComposite();
357 m_layerTreeHost
->didBeginFrame();
361 bool SingleThreadProxy::doComposite()
363 DCHECK(!m_contextLost
);
365 DebugScopedSetImplThread
impl(this);
367 if (!m_layerTreeHostImpl
->visible())
370 m_layerTreeHostImpl
->animate(base::TimeTicks::Now(), base::Time::Now());
372 // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
373 // be used when such a frame is possible. Since drawLayers() depends on the result of
374 // prepareToDraw(), it is guarded on canDraw() as well.
375 if (!m_layerTreeHostImpl
->canDraw())
378 LayerTreeHostImpl::FrameData frame
;
379 m_layerTreeHostImpl
->prepareToDraw(frame
);
380 m_layerTreeHostImpl
->drawLayers(frame
);
381 m_layerTreeHostImpl
->didDrawAllLayers(frame
);
384 if (m_layerTreeHostImpl
->isContextLost()) {
385 m_contextLost
= true;
386 m_layerTreeHost
->didLoseContext();
393 void SingleThreadProxy::didSwapFrame()
395 if (m_nextFrameIsNewlyCommittedFrame
) {
396 m_nextFrameIsNewlyCommittedFrame
= false;
397 m_layerTreeHost
->didCommitAndDrawFrame();