blob: cc7d538201cc9907b2a15303aeab96a57a884d3e [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// 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.
4
5#include "config.h"
6
7#include "CCSingleThreadProxy.h"
8
9#include "CCDrawQuad.h"
10#include "CCGraphicsContext.h"
11#include "CCLayerTreeHost.h"
12#include "CCTextureUpdateController.h"
13#include "CCTimer.h"
14#include "TraceEvent.h"
15#include <wtf/CurrentTime.h>
16
17using namespace WTF;
18
[email protected]9c88e562012-09-14 22:21:3019namespace cc {
[email protected]94f206c12012-08-25 00:09:1420
21PassOwnPtr<CCProxy> CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost)
22{
23 return adoptPtr(new CCSingleThreadProxy(layerTreeHost));
24}
25
26CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost)
27 : m_layerTreeHost(layerTreeHost)
28 , m_contextLost(false)
[email protected]94f206c12012-08-25 00:09:1429 , m_rendererInitialized(false)
30 , m_nextFrameIsNewlyCommittedFrame(false)
[email protected]8b9af6b2012-09-27 00:36:3631 , m_totalCommitCount(0)
[email protected]94f206c12012-08-25 00:09:1432{
33 TRACE_EVENT0("cc", "CCSingleThreadProxy::CCSingleThreadProxy");
34 ASSERT(CCProxy::isMainThread());
35}
36
37void CCSingleThreadProxy::start()
38{
39 DebugScopedSetImplThread impl;
40 m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
41}
42
43CCSingleThreadProxy::~CCSingleThreadProxy()
44{
45 TRACE_EVENT0("cc", "CCSingleThreadProxy::~CCSingleThreadProxy");
46 ASSERT(CCProxy::isMainThread());
47 ASSERT(!m_layerTreeHostImpl && !m_layerTreeHost); // make sure stop() got called.
48}
49
50bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
51{
52 TRACE_EVENT0("cc", "CCSingleThreadProxy::compositeAndReadback");
53 ASSERT(CCProxy::isMainThread());
54
55 if (!commitAndComposite())
56 return false;
57
58 m_layerTreeHostImpl->readback(pixels, rect);
59
60 if (m_layerTreeHostImpl->isContextLost())
61 return false;
62
63 m_layerTreeHostImpl->swapBuffers();
64 didSwapFrame();
65
66 return true;
67}
68
69void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration)
70{
71 m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration);
72}
73
74void CCSingleThreadProxy::finishAllRendering()
75{
76 ASSERT(CCProxy::isMainThread());
77 {
78 DebugScopedSetImplThread impl;
79 m_layerTreeHostImpl->finishAllRendering();
80 }
81}
82
83bool CCSingleThreadProxy::isStarted() const
84{
85 ASSERT(CCProxy::isMainThread());
86 return m_layerTreeHostImpl;
87}
88
89bool CCSingleThreadProxy::initializeContext()
90{
91 ASSERT(CCProxy::isMainThread());
92 OwnPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
93 if (!context)
94 return false;
95 m_contextBeforeInitialization = context.release();
96 return true;
97}
98
99void CCSingleThreadProxy::setSurfaceReady()
100{
101 // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
102}
103
104void CCSingleThreadProxy::setVisible(bool visible)
105{
106 DebugScopedSetImplThread impl;
107 m_layerTreeHostImpl->setVisible(visible);
108}
109
110bool CCSingleThreadProxy::initializeRenderer()
111{
112 ASSERT(CCProxy::isMainThread());
113 ASSERT(m_contextBeforeInitialization);
114 {
115 DebugScopedSetImplThread impl;
[email protected]673788a2012-09-22 22:22:10116 bool ok = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitialization.release());
[email protected]94f206c12012-08-25 00:09:14117 if (ok) {
118 m_rendererInitialized = true;
119 m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities();
120 }
121
122 return ok;
123 }
124}
125
126bool CCSingleThreadProxy::recreateContext()
127{
128 TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext");
129 ASSERT(CCProxy::isMainThread());
130 ASSERT(m_contextLost);
131
132 OwnPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
133 if (!context)
134 return false;
135
136 bool initialized;
137 {
[email protected]d74ca3b2012-09-12 23:11:12138 DebugScopedSetMainThreadBlocked mainThreadBlocked;
[email protected]94f206c12012-08-25 00:09:14139 DebugScopedSetImplThread impl;
140 if (!m_layerTreeHostImpl->contentsTexturesPurged())
141 m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider());
[email protected]673788a2012-09-22 22:22:10142 initialized = m_layerTreeHostImpl->initializeRenderer(context.release());
[email protected]94f206c12012-08-25 00:09:14143 if (initialized) {
144 m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities();
145 }
146 }
147
148 if (initialized)
149 m_contextLost = false;
150
151 return initialized;
152}
153
[email protected]8b9af6b2012-09-27 00:36:36154void CCSingleThreadProxy::renderingStats(CCRenderingStats* stats)
[email protected]94f206c12012-08-25 00:09:14155{
[email protected]8b9af6b2012-09-27 00:36:36156 stats->totalCommitTimeInSeconds = m_totalCommitTime.InSecondsF();
157 stats->totalCommitCount = m_totalCommitCount;
[email protected]94f206c12012-08-25 00:09:14158 m_layerTreeHostImpl->renderingStats(stats);
159}
160
161const RendererCapabilities& CCSingleThreadProxy::rendererCapabilities() const
162{
163 ASSERT(m_rendererInitialized);
164 // Note: this gets called during the commit by the "impl" thread
165 return m_RendererCapabilitiesForMainThread;
166}
167
168void CCSingleThreadProxy::loseContext()
169{
170 ASSERT(CCProxy::isMainThread());
171 m_layerTreeHost->didLoseContext();
172 m_contextLost = true;
173}
174
175void CCSingleThreadProxy::setNeedsAnimate()
176{
177 // CCThread-only feature
178 ASSERT_NOT_REACHED();
179}
180
[email protected]f961b792012-09-20 07:27:33181void CCSingleThreadProxy::doCommit(PassOwnPtr<CCTextureUpdateQueue> queue)
[email protected]94f206c12012-08-25 00:09:14182{
183 ASSERT(CCProxy::isMainThread());
184 // Commit immediately
185 {
186 DebugScopedSetMainThreadBlocked mainThreadBlocked;
187 DebugScopedSetImplThread impl;
188
[email protected]8b9af6b2012-09-27 00:36:36189 base::TimeTicks startTime = base::TimeTicks::HighResNow();
[email protected]94f206c12012-08-25 00:09:14190 m_layerTreeHostImpl->beginCommit();
191
192 m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
193
[email protected]f961b792012-09-20 07:27:33194 OwnPtr<CCTextureUpdateController> updateController =
195 CCTextureUpdateController::create(
196 NULL,
197 CCProxy::mainThread(),
198 queue,
199 m_layerTreeHostImpl->resourceProvider(),
200 m_layerTreeHostImpl->resourceProvider()->textureUploader());
201 updateController->finalize();
[email protected]94f206c12012-08-25 00:09:14202
203 m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
204
205 m_layerTreeHostImpl->commitComplete();
206
207#if !ASSERT_DISABLED
208 // In the single-threaded case, the scroll deltas should never be
209 // touched on the impl layer tree.
210 OwnPtr<CCScrollAndScaleSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
211 ASSERT(!scrollInfo->scrolls.size());
212#endif
[email protected]8b9af6b2012-09-27 00:36:36213
214 base::TimeTicks endTime = base::TimeTicks::HighResNow();
215 m_totalCommitTime += endTime - startTime;
216 m_totalCommitCount++;
[email protected]94f206c12012-08-25 00:09:14217 }
218 m_layerTreeHost->commitComplete();
219 m_nextFrameIsNewlyCommittedFrame = true;
220}
221
222void CCSingleThreadProxy::setNeedsCommit()
223{
224 ASSERT(CCProxy::isMainThread());
225 m_layerTreeHost->scheduleComposite();
226}
227
228void CCSingleThreadProxy::setNeedsRedraw()
229{
230 // FIXME: Once we move render_widget scheduling into this class, we can
231 // treat redraw requests more efficiently than commitAndRedraw requests.
232 m_layerTreeHostImpl->setFullRootLayerDamage();
233 setNeedsCommit();
234}
235
236bool CCSingleThreadProxy::commitRequested() const
237{
238 return false;
239}
240
241void CCSingleThreadProxy::didAddAnimation()
242{
243}
244
[email protected]493067512012-09-19 23:34:10245size_t CCSingleThreadProxy::maxPartialTextureUpdates() const
246{
247 return std::numeric_limits<size_t>::max();
248}
249
[email protected]94f206c12012-08-25 00:09:14250void CCSingleThreadProxy::stop()
251{
252 TRACE_EVENT0("cc", "CCSingleThreadProxy::stop");
253 ASSERT(CCProxy::isMainThread());
254 {
255 DebugScopedSetMainThreadBlocked mainThreadBlocked;
256 DebugScopedSetImplThread impl;
257
258 if (!m_layerTreeHostImpl->contentsTexturesPurged())
259 m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider());
260 m_layerTreeHostImpl.clear();
261 }
262 m_layerTreeHost = 0;
263}
264
[email protected]493067512012-09-19 23:34:10265void CCSingleThreadProxy::setNeedsRedrawOnImplThread()
266{
267 m_layerTreeHost->scheduleComposite();
268}
269
270void CCSingleThreadProxy::setNeedsCommitOnImplThread()
271{
272 m_layerTreeHost->scheduleComposite();
273}
274
[email protected]94f206c12012-08-25 00:09:14275void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
276{
277 ASSERT(CCProxy::isImplThread());
278 DebugScopedSetMainThread main;
279 m_layerTreeHost->setAnimationEvents(events, wallClockTime);
280}
281
[email protected]e1fc8b32012-09-18 20:29:09282void CCSingleThreadProxy::releaseContentsTexturesOnImplThread()
283{
284 ASSERT(isImplThread());
285 m_layerTreeHost->reduceContentsTexturesMemoryOnImplThread(0, m_layerTreeHostImpl->resourceProvider());
286}
287
[email protected]94f206c12012-08-25 00:09:14288// Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
289void CCSingleThreadProxy::compositeImmediately()
290{
291 if (commitAndComposite()) {
292 m_layerTreeHostImpl->swapBuffers();
293 didSwapFrame();
294 }
295}
296
297void CCSingleThreadProxy::forceSerializeOnSwapBuffers()
298{
299 {
300 DebugScopedSetImplThread impl;
301 if (m_rendererInitialized)
302 m_layerTreeHostImpl->renderer()->doNoOp();
303 }
304}
305
[email protected]493067512012-09-19 23:34:10306void CCSingleThreadProxy::onSwapBuffersCompleteOnImplThread()
307{
308 ASSERT_NOT_REACHED();
309}
310
[email protected]94f206c12012-08-25 00:09:14311bool CCSingleThreadProxy::commitAndComposite()
312{
313 ASSERT(CCProxy::isMainThread());
314
[email protected]94f206c12012-08-25 00:09:14315 if (!m_layerTreeHost->initializeRendererIfNeeded())
316 return false;
317
[email protected]e1fc8b32012-09-18 20:29:09318 // Unlink any texture backings that were deleted
319 CCPrioritizedTextureManager::BackingVector evictedContentsTexturesBackings;
320 {
321 DebugScopedSetImplThread implThread;
322 m_layerTreeHost->getEvictedContentTexturesBackings(evictedContentsTexturesBackings);
323 }
324 m_layerTreeHost->unlinkEvictedContentTexturesBackings(evictedContentsTexturesBackings);
325 {
[email protected]d74ca3b2012-09-12 23:11:12326 DebugScopedSetImplThreadAndMainThreadBlocked implAndMainBlocked;
[email protected]e1fc8b32012-09-18 20:29:09327 m_layerTreeHost->deleteEvictedContentTexturesBackings();
[email protected]d74ca3b2012-09-12 23:11:12328 }
[email protected]94f206c12012-08-25 00:09:14329
[email protected]f961b792012-09-20 07:27:33330 OwnPtr<CCTextureUpdateQueue> queue = adoptPtr(new CCTextureUpdateQueue);
331 m_layerTreeHost->updateLayers(*(queue.get()), m_layerTreeHostImpl->memoryAllocationLimitBytes());
[email protected]e1fc8b32012-09-18 20:29:09332
333 if (m_layerTreeHostImpl->contentsTexturesPurged())
334 m_layerTreeHostImpl->resetContentsTexturesPurged();
[email protected]94f206c12012-08-25 00:09:14335
336 m_layerTreeHost->willCommit();
[email protected]f961b792012-09-20 07:27:33337 doCommit(queue.release());
[email protected]94f206c12012-08-25 00:09:14338 bool result = doComposite();
339 m_layerTreeHost->didBeginFrame();
340 return result;
341}
342
343bool CCSingleThreadProxy::doComposite()
344{
345 ASSERT(!m_contextLost);
346 {
347 DebugScopedSetImplThread impl;
348
349 if (!m_layerTreeHostImpl->visible())
350 return false;
351
352 double monotonicTime = monotonicallyIncreasingTime();
353 double wallClockTime = currentTime();
354 m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
355
356 // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
357 // be used when such a frame is possible. Since drawLayers() depends on the result of
358 // prepareToDraw(), it is guarded on canDraw() as well.
359 if (!m_layerTreeHostImpl->canDraw())
360 return false;
361
362 CCLayerTreeHostImpl::FrameData frame;
363 m_layerTreeHostImpl->prepareToDraw(frame);
364 m_layerTreeHostImpl->drawLayers(frame);
365 m_layerTreeHostImpl->didDrawAllLayers(frame);
366 }
367
368 if (m_layerTreeHostImpl->isContextLost()) {
369 m_contextLost = true;
370 m_layerTreeHost->didLoseContext();
371 return false;
372 }
373
374 return true;
375}
376
377void CCSingleThreadProxy::didSwapFrame()
378{
379 if (m_nextFrameIsNewlyCommittedFrame) {
380 m_nextFrameIsNewlyCommittedFrame = false;
381 m_layerTreeHost->didCommitAndDrawFrame();
382 }
383}
384
385}