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 "cc/single_thread_proxy.h"
9 #include "base/debug/trace_event.h"
10 #include "cc/draw_quad.h"
11 #include "cc/graphics_context.h"
12 #include "cc/layer_tree_host.h"
13 #include "cc/resource_update_controller.h"
14 #include "cc/thread.h"
18 scoped_ptr
<Proxy
> SingleThreadProxy::create(LayerTreeHost
* layerTreeHost
)
20 return make_scoped_ptr(new SingleThreadProxy(layerTreeHost
)).PassAs
<Proxy
>();
23 SingleThreadProxy::SingleThreadProxy(LayerTreeHost
* layerTreeHost
)
24 : Proxy(scoped_ptr
<Thread
>(NULL
))
25 , m_layerTreeHost(layerTreeHost
)
26 , m_contextLost(false)
27 , m_rendererInitialized(false)
28 , m_nextFrameIsNewlyCommittedFrame(false)
29 , m_totalCommitCount(0)
31 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
32 DCHECK(Proxy::isMainThread());
35 void SingleThreadProxy::start()
37 DebugScopedSetImplThread
impl(this);
38 m_layerTreeHostImpl
= m_layerTreeHost
->createLayerTreeHostImpl(this);
41 SingleThreadProxy::~SingleThreadProxy()
43 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
44 DCHECK(Proxy::isMainThread());
45 DCHECK(!m_layerTreeHostImpl
.get() && !m_layerTreeHost
); // make sure stop() got called.
48 bool SingleThreadProxy::compositeAndReadback(void *pixels
, const gfx::Rect
& rect
)
50 TRACE_EVENT0("cc", "SingleThreadProxy::compositeAndReadback");
51 DCHECK(Proxy::isMainThread());
53 if (!commitAndComposite())
56 m_layerTreeHostImpl
->readback(pixels
, rect
);
58 if (m_layerTreeHostImpl
->isContextLost())
61 m_layerTreeHostImpl
->swapBuffers();
67 void SingleThreadProxy::startPageScaleAnimation(gfx::Vector2d targetOffset
, bool useAnchor
, float scale
, base::TimeDelta duration
)
69 m_layerTreeHostImpl
->startPageScaleAnimation(targetOffset
, useAnchor
, scale
, base::TimeTicks::Now(), duration
);
72 void SingleThreadProxy::finishAllRendering()
74 DCHECK(Proxy::isMainThread());
76 DebugScopedSetImplThread
impl(this);
77 m_layerTreeHostImpl
->finishAllRendering();
81 bool SingleThreadProxy::isStarted() const
83 DCHECK(Proxy::isMainThread());
84 return m_layerTreeHostImpl
.get();
87 bool SingleThreadProxy::initializeContext()
89 DCHECK(Proxy::isMainThread());
90 scoped_ptr
<GraphicsContext
> context
= m_layerTreeHost
->createContext();
93 m_contextBeforeInitialization
= context
.Pass();
97 void SingleThreadProxy::setSurfaceReady()
99 // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
102 void SingleThreadProxy::setVisible(bool visible
)
104 DebugScopedSetImplThread
impl(this);
105 m_layerTreeHostImpl
->setVisible(visible
);
108 bool SingleThreadProxy::initializeRenderer()
110 DCHECK(Proxy::isMainThread());
111 DCHECK(m_contextBeforeInitialization
.get());
113 DebugScopedSetImplThread
impl(this);
114 bool ok
= m_layerTreeHostImpl
->initializeRenderer(m_contextBeforeInitialization
.Pass());
116 m_rendererInitialized
= true;
117 m_RendererCapabilitiesForMainThread
= m_layerTreeHostImpl
->rendererCapabilities();
124 bool SingleThreadProxy::recreateContext()
126 TRACE_EVENT0("cc", "SingleThreadProxy::recreateContext");
127 DCHECK(Proxy::isMainThread());
128 DCHECK(m_contextLost
);
130 scoped_ptr
<GraphicsContext
> context
= m_layerTreeHost
->createContext();
136 DebugScopedSetMainThreadBlocked
mainThreadBlocked(this);
137 DebugScopedSetImplThread
impl(this);
138 if (!m_layerTreeHostImpl
->contentsTexturesPurged())
139 m_layerTreeHost
->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl
->resourceProvider());
140 initialized
= m_layerTreeHostImpl
->initializeRenderer(context
.Pass());
142 m_RendererCapabilitiesForMainThread
= m_layerTreeHostImpl
->rendererCapabilities();
147 m_contextLost
= false;
152 void SingleThreadProxy::renderingStats(RenderingStats
* stats
)
154 stats
->totalCommitTimeInSeconds
= m_totalCommitTime
.InSecondsF();
155 stats
->totalCommitCount
= m_totalCommitCount
;
156 m_layerTreeHostImpl
->renderingStats(stats
);
159 const RendererCapabilities
& SingleThreadProxy::rendererCapabilities() const
161 DCHECK(m_rendererInitialized
);
162 // Note: this gets called during the commit by the "impl" thread
163 return m_RendererCapabilitiesForMainThread
;
166 void SingleThreadProxy::loseContext()
168 DCHECK(Proxy::isMainThread());
169 m_layerTreeHost
->didLoseContext();
170 m_contextLost
= true;
173 void SingleThreadProxy::setNeedsAnimate()
175 // Thread-only feature
179 void SingleThreadProxy::doCommit(scoped_ptr
<ResourceUpdateQueue
> queue
)
181 DCHECK(Proxy::isMainThread());
182 // Commit immediately
184 DebugScopedSetMainThreadBlocked
mainThreadBlocked(this);
185 DebugScopedSetImplThread
impl(this);
187 base::TimeTicks startTime
= base::TimeTicks::HighResNow();
188 m_layerTreeHostImpl
->beginCommit();
190 m_layerTreeHost
->contentsTextureManager()->pushTexturePrioritiesToBackings();
191 m_layerTreeHost
->beginCommitOnImplThread(m_layerTreeHostImpl
.get());
193 scoped_ptr
<ResourceUpdateController
> updateController
=
194 ResourceUpdateController::create(
198 m_layerTreeHostImpl
->resourceProvider(),
200 updateController
->finalize();
202 m_layerTreeHost
->finishCommitOnImplThread(m_layerTreeHostImpl
.get());
204 m_layerTreeHostImpl
->commitComplete();
207 // In the single-threaded case, the scroll deltas should never be
208 // touched on the impl layer tree.
209 scoped_ptr
<ScrollAndScaleSet
> scrollInfo
= m_layerTreeHostImpl
->processScrollDeltas();
210 DCHECK(!scrollInfo
->scrolls
.size());
213 base::TimeTicks endTime
= base::TimeTicks::HighResNow();
214 m_totalCommitTime
+= endTime
- startTime
;
215 m_totalCommitCount
++;
217 m_layerTreeHost
->commitComplete();
218 m_nextFrameIsNewlyCommittedFrame
= true;
221 void SingleThreadProxy::setNeedsCommit()
223 DCHECK(Proxy::isMainThread());
224 m_layerTreeHost
->scheduleComposite();
227 void SingleThreadProxy::setNeedsRedraw()
229 // FIXME: Once we move render_widget scheduling into this class, we can
230 // treat redraw requests more efficiently than commitAndRedraw requests.
231 m_layerTreeHostImpl
->setFullRootLayerDamage();
235 void SingleThreadProxy::setDeferCommits(bool deferCommits
)
237 // Thread-only feature.
241 bool SingleThreadProxy::commitRequested() const
246 void SingleThreadProxy::didAddAnimation()
250 size_t SingleThreadProxy::maxPartialTextureUpdates() const
252 return std::numeric_limits
<size_t>::max();
255 void SingleThreadProxy::stop()
257 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
258 DCHECK(Proxy::isMainThread());
260 DebugScopedSetMainThreadBlocked
mainThreadBlocked(this);
261 DebugScopedSetImplThread
impl(this);
263 if (!m_layerTreeHostImpl
->contentsTexturesPurged())
264 m_layerTreeHost
->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl
->resourceProvider());
265 m_layerTreeHostImpl
.reset();
270 void SingleThreadProxy::setNeedsRedrawOnImplThread()
272 m_layerTreeHost
->scheduleComposite();
275 void SingleThreadProxy::setNeedsCommitOnImplThread()
277 m_layerTreeHost
->scheduleComposite();
280 void SingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr
<AnimationEventsVector
> events
, base::Time wallClockTime
)
282 DCHECK(Proxy::isImplThread());
283 DebugScopedSetMainThread
main(this);
284 m_layerTreeHost
->setAnimationEvents(events
.Pass(), wallClockTime
);
287 bool SingleThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes
, int priorityCutoff
)
289 DCHECK(isImplThread());
290 if (!m_layerTreeHost
->contentsTextureManager())
293 return m_layerTreeHost
->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes
, priorityCutoff
, m_layerTreeHostImpl
->resourceProvider());
296 void SingleThreadProxy::sendManagedMemoryStats()
298 DCHECK(Proxy::isImplThread());
299 if (!m_layerTreeHostImpl
.get())
301 if (!m_layerTreeHostImpl
->renderer())
303 if (!m_layerTreeHost
->contentsTextureManager())
306 m_layerTreeHostImpl
->renderer()->sendManagedMemoryStats(
307 m_layerTreeHost
->contentsTextureManager()->memoryVisibleBytes(),
308 m_layerTreeHost
->contentsTextureManager()->memoryVisibleAndNearbyBytes(),
309 m_layerTreeHost
->contentsTextureManager()->memoryUseBytes());
312 // Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
313 void SingleThreadProxy::compositeImmediately()
315 if (commitAndComposite()) {
316 m_layerTreeHostImpl
->swapBuffers();
321 void SingleThreadProxy::forceSerializeOnSwapBuffers()
324 DebugScopedSetImplThread
impl(this);
325 if (m_rendererInitialized
)
326 m_layerTreeHostImpl
->renderer()->doNoOp();
330 void SingleThreadProxy::onSwapBuffersCompleteOnImplThread()
335 bool SingleThreadProxy::commitAndComposite()
337 DCHECK(Proxy::isMainThread());
339 if (!m_layerTreeHost
->initializeRendererIfNeeded())
342 // Unlink any texture backings that were deleted
343 PrioritizedResourceManager::BackingList evictedContentsTexturesBackings
;
345 DebugScopedSetImplThread
impl(this);
346 m_layerTreeHost
->contentsTextureManager()->getEvictedBackings(evictedContentsTexturesBackings
);
348 m_layerTreeHost
->contentsTextureManager()->unlinkEvictedBackings(evictedContentsTexturesBackings
);
350 scoped_ptr
<ResourceUpdateQueue
> queue
= make_scoped_ptr(new ResourceUpdateQueue
);
351 m_layerTreeHost
->updateLayers(*(queue
.get()), m_layerTreeHostImpl
->memoryAllocationLimitBytes());
353 if (m_layerTreeHostImpl
->contentsTexturesPurged())
354 m_layerTreeHostImpl
->resetContentsTexturesPurged();
356 m_layerTreeHost
->willCommit();
357 doCommit(queue
.Pass());
358 bool result
= doComposite();
359 m_layerTreeHost
->didBeginFrame();
363 bool SingleThreadProxy::doComposite()
365 DCHECK(!m_contextLost
);
367 DebugScopedSetImplThread
impl(this);
369 if (!m_layerTreeHostImpl
->visible())
372 m_layerTreeHostImpl
->animate(base::TimeTicks::Now(), base::Time::Now());
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())
380 LayerTreeHostImpl::FrameData frame
;
381 m_layerTreeHostImpl
->prepareToDraw(frame
);
382 m_layerTreeHostImpl
->drawLayers(frame
);
383 m_layerTreeHostImpl
->didDrawAllLayers(frame
);
386 if (m_layerTreeHostImpl
->isContextLost()) {
387 m_contextLost
= true;
388 m_layerTreeHost
->didLoseContext();
395 void SingleThreadProxy::didSwapFrame()
397 if (m_nextFrameIsNewlyCommittedFrame
) {
398 m_nextFrameIsNewlyCommittedFrame
= false;
399 m_layerTreeHost
->didCommitAndDrawFrame();