blob: 3b331deecc9fd3b46095b93eb24c1c09c727afbf [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)
31{
32 TRACE_EVENT0("cc", "CCSingleThreadProxy::CCSingleThreadProxy");
33 ASSERT(CCProxy::isMainThread());
34}
35
36void CCSingleThreadProxy::start()
37{
38 DebugScopedSetImplThread impl;
39 m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
40}
41
42CCSingleThreadProxy::~CCSingleThreadProxy()
43{
44 TRACE_EVENT0("cc", "CCSingleThreadProxy::~CCSingleThreadProxy");
45 ASSERT(CCProxy::isMainThread());
46 ASSERT(!m_layerTreeHostImpl && !m_layerTreeHost); // make sure stop() got called.
47}
48
49bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
50{
51 TRACE_EVENT0("cc", "CCSingleThreadProxy::compositeAndReadback");
52 ASSERT(CCProxy::isMainThread());
53
54 if (!commitAndComposite())
55 return false;
56
57 m_layerTreeHostImpl->readback(pixels, rect);
58
59 if (m_layerTreeHostImpl->isContextLost())
60 return false;
61
62 m_layerTreeHostImpl->swapBuffers();
63 didSwapFrame();
64
65 return true;
66}
67
68void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration)
69{
70 m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration);
71}
72
73void CCSingleThreadProxy::finishAllRendering()
74{
75 ASSERT(CCProxy::isMainThread());
76 {
77 DebugScopedSetImplThread impl;
78 m_layerTreeHostImpl->finishAllRendering();
79 }
80}
81
82bool CCSingleThreadProxy::isStarted() const
83{
84 ASSERT(CCProxy::isMainThread());
85 return m_layerTreeHostImpl;
86}
87
88bool CCSingleThreadProxy::initializeContext()
89{
90 ASSERT(CCProxy::isMainThread());
91 OwnPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
92 if (!context)
93 return false;
94 m_contextBeforeInitialization = context.release();
95 return true;
96}
97
98void CCSingleThreadProxy::setSurfaceReady()
99{
100 // Scheduling is controlled by the embedder in the single thread case, so nothing to do.
101}
102
103void CCSingleThreadProxy::setVisible(bool visible)
104{
105 DebugScopedSetImplThread impl;
106 m_layerTreeHostImpl->setVisible(visible);
107}
108
109bool CCSingleThreadProxy::initializeRenderer()
110{
111 ASSERT(CCProxy::isMainThread());
112 ASSERT(m_contextBeforeInitialization);
113 {
114 DebugScopedSetImplThread impl;
115 bool ok = m_layerTreeHostImpl->initializeRenderer(m_contextBeforeInitialization.release(), UnthrottledUploader);
116 if (ok) {
117 m_rendererInitialized = true;
118 m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities();
119 }
120
121 return ok;
122 }
123}
124
125bool CCSingleThreadProxy::recreateContext()
126{
127 TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext");
128 ASSERT(CCProxy::isMainThread());
129 ASSERT(m_contextLost);
130
131 OwnPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
132 if (!context)
133 return false;
134
135 bool initialized;
136 {
[email protected]d74ca3b2012-09-12 23:11:12137 DebugScopedSetMainThreadBlocked mainThreadBlocked;
[email protected]94f206c12012-08-25 00:09:14138 DebugScopedSetImplThread impl;
139 if (!m_layerTreeHostImpl->contentsTexturesPurged())
140 m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider());
141 initialized = m_layerTreeHostImpl->initializeRenderer(context.release(), UnthrottledUploader);
142 if (initialized) {
143 m_RendererCapabilitiesForMainThread = m_layerTreeHostImpl->rendererCapabilities();
144 }
145 }
146
147 if (initialized)
148 m_contextLost = false;
149
150 return initialized;
151}
152
153void CCSingleThreadProxy::implSideRenderingStats(CCRenderingStats& stats)
154{
155 m_layerTreeHostImpl->renderingStats(stats);
156}
157
158const RendererCapabilities& CCSingleThreadProxy::rendererCapabilities() const
159{
160 ASSERT(m_rendererInitialized);
161 // Note: this gets called during the commit by the "impl" thread
162 return m_RendererCapabilitiesForMainThread;
163}
164
165void CCSingleThreadProxy::loseContext()
166{
167 ASSERT(CCProxy::isMainThread());
168 m_layerTreeHost->didLoseContext();
169 m_contextLost = true;
170}
171
172void CCSingleThreadProxy::setNeedsAnimate()
173{
174 // CCThread-only feature
175 ASSERT_NOT_REACHED();
176}
177
178void CCSingleThreadProxy::doCommit(CCTextureUpdateQueue& queue)
179{
180 ASSERT(CCProxy::isMainThread());
181 // Commit immediately
182 {
183 DebugScopedSetMainThreadBlocked mainThreadBlocked;
184 DebugScopedSetImplThread impl;
185
186 m_layerTreeHostImpl->beginCommit();
187
188 m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
189
[email protected]cc11ff32012-09-18 14:46:15190 CCTextureUpdateController::updateTextures(m_layerTreeHostImpl->resourceProvider(), m_layerTreeHostImpl->resourceProvider()->textureUploader(), &queue);
[email protected]94f206c12012-08-25 00:09:14191
192 m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
193
194 m_layerTreeHostImpl->commitComplete();
195
196#if !ASSERT_DISABLED
197 // In the single-threaded case, the scroll deltas should never be
198 // touched on the impl layer tree.
199 OwnPtr<CCScrollAndScaleSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
200 ASSERT(!scrollInfo->scrolls.size());
201#endif
202 }
203 m_layerTreeHost->commitComplete();
204 m_nextFrameIsNewlyCommittedFrame = true;
205}
206
207void CCSingleThreadProxy::setNeedsCommit()
208{
209 ASSERT(CCProxy::isMainThread());
210 m_layerTreeHost->scheduleComposite();
211}
212
213void CCSingleThreadProxy::setNeedsRedraw()
214{
215 // FIXME: Once we move render_widget scheduling into this class, we can
216 // treat redraw requests more efficiently than commitAndRedraw requests.
217 m_layerTreeHostImpl->setFullRootLayerDamage();
218 setNeedsCommit();
219}
220
221bool CCSingleThreadProxy::commitRequested() const
222{
223 return false;
224}
225
226void CCSingleThreadProxy::didAddAnimation()
227{
228}
229
[email protected]493067512012-09-19 23:34:10230size_t CCSingleThreadProxy::maxPartialTextureUpdates() const
231{
232 return std::numeric_limits<size_t>::max();
233}
234
[email protected]94f206c12012-08-25 00:09:14235void CCSingleThreadProxy::stop()
236{
237 TRACE_EVENT0("cc", "CCSingleThreadProxy::stop");
238 ASSERT(CCProxy::isMainThread());
239 {
240 DebugScopedSetMainThreadBlocked mainThreadBlocked;
241 DebugScopedSetImplThread impl;
242
243 if (!m_layerTreeHostImpl->contentsTexturesPurged())
244 m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->resourceProvider());
245 m_layerTreeHostImpl.clear();
246 }
247 m_layerTreeHost = 0;
248}
249
[email protected]493067512012-09-19 23:34:10250void CCSingleThreadProxy::setNeedsRedrawOnImplThread()
251{
252 m_layerTreeHost->scheduleComposite();
253}
254
255void CCSingleThreadProxy::setNeedsCommitOnImplThread()
256{
257 m_layerTreeHost->scheduleComposite();
258}
259
[email protected]94f206c12012-08-25 00:09:14260void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
261{
262 ASSERT(CCProxy::isImplThread());
263 DebugScopedSetMainThread main;
264 m_layerTreeHost->setAnimationEvents(events, wallClockTime);
265}
266
[email protected]e1fc8b32012-09-18 20:29:09267void CCSingleThreadProxy::releaseContentsTexturesOnImplThread()
268{
269 ASSERT(isImplThread());
270 m_layerTreeHost->reduceContentsTexturesMemoryOnImplThread(0, m_layerTreeHostImpl->resourceProvider());
271}
272
[email protected]94f206c12012-08-25 00:09:14273// Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
274void CCSingleThreadProxy::compositeImmediately()
275{
276 if (commitAndComposite()) {
277 m_layerTreeHostImpl->swapBuffers();
278 didSwapFrame();
279 }
280}
281
282void CCSingleThreadProxy::forceSerializeOnSwapBuffers()
283{
284 {
285 DebugScopedSetImplThread impl;
286 if (m_rendererInitialized)
287 m_layerTreeHostImpl->renderer()->doNoOp();
288 }
289}
290
[email protected]493067512012-09-19 23:34:10291void CCSingleThreadProxy::onSwapBuffersCompleteOnImplThread()
292{
293 ASSERT_NOT_REACHED();
294}
295
[email protected]94f206c12012-08-25 00:09:14296bool CCSingleThreadProxy::commitAndComposite()
297{
298 ASSERT(CCProxy::isMainThread());
299
[email protected]94f206c12012-08-25 00:09:14300 if (!m_layerTreeHost->initializeRendererIfNeeded())
301 return false;
302
[email protected]e1fc8b32012-09-18 20:29:09303 // Unlink any texture backings that were deleted
304 CCPrioritizedTextureManager::BackingVector evictedContentsTexturesBackings;
305 {
306 DebugScopedSetImplThread implThread;
307 m_layerTreeHost->getEvictedContentTexturesBackings(evictedContentsTexturesBackings);
308 }
309 m_layerTreeHost->unlinkEvictedContentTexturesBackings(evictedContentsTexturesBackings);
310 {
[email protected]d74ca3b2012-09-12 23:11:12311 DebugScopedSetImplThreadAndMainThreadBlocked implAndMainBlocked;
[email protected]e1fc8b32012-09-18 20:29:09312 m_layerTreeHost->deleteEvictedContentTexturesBackings();
[email protected]d74ca3b2012-09-12 23:11:12313 }
[email protected]94f206c12012-08-25 00:09:14314
315 CCTextureUpdateQueue queue;
316 m_layerTreeHost->updateLayers(queue, m_layerTreeHostImpl->memoryAllocationLimitBytes());
[email protected]e1fc8b32012-09-18 20:29:09317
318 if (m_layerTreeHostImpl->contentsTexturesPurged())
319 m_layerTreeHostImpl->resetContentsTexturesPurged();
[email protected]94f206c12012-08-25 00:09:14320
321 m_layerTreeHost->willCommit();
322 doCommit(queue);
323 bool result = doComposite();
324 m_layerTreeHost->didBeginFrame();
325 return result;
326}
327
328bool CCSingleThreadProxy::doComposite()
329{
330 ASSERT(!m_contextLost);
331 {
332 DebugScopedSetImplThread impl;
333
334 if (!m_layerTreeHostImpl->visible())
335 return false;
336
337 double monotonicTime = monotonicallyIncreasingTime();
338 double wallClockTime = currentTime();
339 m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
340
341 // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
342 // be used when such a frame is possible. Since drawLayers() depends on the result of
343 // prepareToDraw(), it is guarded on canDraw() as well.
344 if (!m_layerTreeHostImpl->canDraw())
345 return false;
346
347 CCLayerTreeHostImpl::FrameData frame;
348 m_layerTreeHostImpl->prepareToDraw(frame);
349 m_layerTreeHostImpl->drawLayers(frame);
350 m_layerTreeHostImpl->didDrawAllLayers(frame);
351 }
352
353 if (m_layerTreeHostImpl->isContextLost()) {
354 m_contextLost = true;
355 m_layerTreeHost->didLoseContext();
356 return false;
357 }
358
359 return true;
360}
361
362void CCSingleThreadProxy::didSwapFrame()
363{
364 if (m_nextFrameIsNewlyCommittedFrame) {
365 m_nextFrameIsNewlyCommittedFrame = false;
366 m_layerTreeHost->didCommitAndDrawFrame();
367 }
368}
369
370}