blob: 843d2e2f854697a225e17da3b0cade8805e01914 [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
[email protected]4456eee22012-10-19 18:16:385#include "cc/single_thread_proxy.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]74d9063c2013-01-18 03:14:477#include "base/auto_reset.h"
[email protected]6331a1172012-10-18 11:35:138#include "base/debug/trace_event.h"
[email protected]0a451722013-02-22 20:32:059#include "cc/context_provider.h"
[email protected]aa0a9d32012-10-24 01:58:1010#include "cc/draw_quad.h"
[email protected]d50c6862012-10-23 02:08:3111#include "cc/layer_tree_host.h"
[email protected]6f90b9e2013-01-17 23:42:0012#include "cc/layer_tree_impl.h"
[email protected]3be2171d2012-12-06 06:13:2013#include "cc/output_surface.h"
[email protected]cd98a8c32013-01-08 18:16:1714#include "cc/prioritized_resource_manager.h"
[email protected]b4da2032012-10-25 21:22:5515#include "cc/resource_update_controller.h"
[email protected]61de5812012-11-08 07:03:4416#include "cc/thread.h"
[email protected]94f206c12012-08-25 00:09:1417
[email protected]9c88e562012-09-14 22:21:3018namespace cc {
[email protected]94f206c12012-08-25 00:09:1419
[email protected]a8a049c2013-03-11 23:27:0620scoped_ptr<Proxy> SingleThreadProxy::Create(LayerTreeHost* layer_tree_host) {
21 return make_scoped_ptr(
22 new SingleThreadProxy(layer_tree_host)).PassAs<Proxy>();
[email protected]94f206c12012-08-25 00:09:1423}
24
[email protected]a8a049c2013-03-11 23:27:0625SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host)
26 : Proxy(scoped_ptr<Thread>(NULL)),
27 layer_tree_host_(layer_tree_host),
28 output_surface_lost_(false),
29 created_offscreen_context_provider(false),
30 renderer_initialized_(false),
31 next_frame_is_newly_committed_frame_(false),
32 inside_draw_(false),
33 total_commit_count_(0) {
34 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
35 DCHECK(Proxy::IsMainThread());
36 DCHECK(layer_tree_host);
[email protected]1e4c352b2013-01-10 02:05:2337
[email protected]a8a049c2013-03-11 23:27:0638 // Impl-side painting not supported without threaded compositing
39 DCHECK(!layer_tree_host->settings().implSidePainting);
[email protected]94f206c12012-08-25 00:09:1440}
41
[email protected]a8a049c2013-03-11 23:27:0642void SingleThreadProxy::Start() {
43 DebugScopedSetImplThread impl(this);
44 layer_tree_host_impl_ = layer_tree_host_->createLayerTreeHostImpl(this);
45}
46
47SingleThreadProxy::~SingleThreadProxy() {
48 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
49 DCHECK(Proxy::IsMainThread());
50 DCHECK(!layer_tree_host_impl_.get() &&
51 !layer_tree_host_); // make sure Stop() got called.
52}
53
54bool SingleThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
55 TRACE_EVENT0("cc", "SingleThreadProxy::compositeAndReadback");
56 DCHECK(Proxy::IsMainThread());
57
58 if (!CommitAndComposite())
59 return false;
60
61 {
[email protected]61de5812012-11-08 07:03:4462 DebugScopedSetImplThread impl(this);
[email protected]a8a049c2013-03-11 23:27:0663 layer_tree_host_impl_->readback(pixels, rect);
64
65 if (layer_tree_host_impl_->isContextLost())
66 return false;
67
68 layer_tree_host_impl_->swapBuffers();
69 }
70 DidSwapFrame();
71
72 return true;
[email protected]94f206c12012-08-25 00:09:1473}
74
[email protected]a8a049c2013-03-11 23:27:0675void SingleThreadProxy::StartPageScaleAnimation(gfx::Vector2d target_offset,
76 bool use_anchor,
77 float scale,
78 base::TimeDelta duration) {
79 layer_tree_host_impl_->startPageScaleAnimation(
80 target_offset, use_anchor, scale, base::TimeTicks::Now(), duration);
[email protected]94f206c12012-08-25 00:09:1481}
82
[email protected]a8a049c2013-03-11 23:27:0683void SingleThreadProxy::FinishAllRendering() {
84 DCHECK(Proxy::IsMainThread());
85 {
[email protected]61de5812012-11-08 07:03:4486 DebugScopedSetImplThread impl(this);
[email protected]a8a049c2013-03-11 23:27:0687 layer_tree_host_impl_->finishAllRendering();
88 }
[email protected]94f206c12012-08-25 00:09:1489}
90
[email protected]a8a049c2013-03-11 23:27:0691bool SingleThreadProxy::IsStarted() const {
92 DCHECK(Proxy::IsMainThread());
93 return layer_tree_host_impl_.get();
[email protected]94f206c12012-08-25 00:09:1494}
95
[email protected]a8a049c2013-03-11 23:27:0696bool SingleThreadProxy::InitializeOutputSurface() {
97 DCHECK(Proxy::IsMainThread());
98 scoped_ptr<OutputSurface> outputSurface =
99 layer_tree_host_->createOutputSurface();
100 if (!outputSurface.get())
101 return false;
102 output_surface_before_initialization_ = outputSurface.Pass();
103 return true;
104}
[email protected]94f206c12012-08-25 00:09:14105
[email protected]a8a049c2013-03-11 23:27:06106void SingleThreadProxy::SetSurfaceReady() {
107 // Scheduling is controlled by the embedder in the single thread case, so
108 // nothing to do.
109}
110
111void SingleThreadProxy::SetVisible(bool visible) {
112 DebugScopedSetImplThread impl(this);
113 layer_tree_host_impl_->setVisible(visible);
114}
115
116bool SingleThreadProxy::InitializeRenderer() {
117 DCHECK(Proxy::IsMainThread());
118 DCHECK(output_surface_before_initialization_.get());
119 {
120 DebugScopedSetImplThread impl(this);
121 bool ok = layer_tree_host_impl_->initializeRenderer(
122 output_surface_before_initialization_.Pass());
123 if (ok) {
124 renderer_initialized_ = true;
125 renderer_capabilities_for_main_thread_ =
126 layer_tree_host_impl_->rendererCapabilities();
[email protected]0a451722013-02-22 20:32:05127 }
[email protected]94f206c12012-08-25 00:09:14128
[email protected]a8a049c2013-03-11 23:27:06129 return ok;
130 }
131}
132
133bool SingleThreadProxy::RecreateOutputSurface() {
134 TRACE_EVENT0("cc", "SingleThreadProxy::recreateContext");
135 DCHECK(Proxy::IsMainThread());
136 DCHECK(output_surface_lost_);
137
138 scoped_ptr<OutputSurface> outputSurface =
139 layer_tree_host_->createOutputSurface();
140 if (!outputSurface.get())
141 return false;
142 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
143 if (created_offscreen_context_provider) {
144 offscreen_context_provider =
145 layer_tree_host_->client()->OffscreenContextProviderForMainThread();
146 if (!offscreen_context_provider->InitializeOnMainThread())
147 return false;
148 }
149
150 bool initialized;
151 {
152 DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
153 DebugScopedSetImplThread impl(this);
154 layer_tree_host_->deleteContentsTexturesOnImplThread(
155 layer_tree_host_impl_->resourceProvider());
156 initialized =
157 layer_tree_host_impl_->initializeRenderer(outputSurface.Pass());
158 if (initialized) {
159 renderer_capabilities_for_main_thread_ =
160 layer_tree_host_impl_->rendererCapabilities();
161 layer_tree_host_impl_->resourceProvider()
162 ->SetOffscreenContextProvider(offscreen_context_provider);
163 } else if (offscreen_context_provider) {
164 offscreen_context_provider->VerifyContexts();
[email protected]94f206c12012-08-25 00:09:14165 }
[email protected]a8a049c2013-03-11 23:27:06166 }
[email protected]94f206c12012-08-25 00:09:14167
[email protected]a8a049c2013-03-11 23:27:06168 if (initialized)
169 output_surface_lost_ = false;
[email protected]94f206c12012-08-25 00:09:14170
[email protected]a8a049c2013-03-11 23:27:06171 return initialized;
[email protected]94f206c12012-08-25 00:09:14172}
173
[email protected]a8a049c2013-03-11 23:27:06174void SingleThreadProxy::GetRenderingStats(RenderingStats* stats) {
175 stats->totalCommitTime = total_commit_time_;
176 stats->totalCommitCount = total_commit_count_;
177 layer_tree_host_impl_->renderingStats(stats);
[email protected]94f206c12012-08-25 00:09:14178}
179
[email protected]a8a049c2013-03-11 23:27:06180const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
181 DCHECK(renderer_initialized_);
182 // Note: this gets called during the commit by the "impl" thread.
183 return renderer_capabilities_for_main_thread_;
[email protected]94f206c12012-08-25 00:09:14184}
185
[email protected]a8a049c2013-03-11 23:27:06186void SingleThreadProxy::SetNeedsAnimate() {
187 // Thread-only feature.
188 NOTREACHED();
[email protected]94f206c12012-08-25 00:09:14189}
190
[email protected]a8a049c2013-03-11 23:27:06191void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
192 DCHECK(Proxy::IsMainThread());
193 // Commit immediately.
194 {
195 DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
196 DebugScopedSetImplThread impl(this);
[email protected]94f206c12012-08-25 00:09:14197
[email protected]a8a049c2013-03-11 23:27:06198 base::TimeTicks startTime = base::TimeTicks::HighResNow();
199 layer_tree_host_impl_->beginCommit();
[email protected]94f206c12012-08-25 00:09:14200
[email protected]a8a049c2013-03-11 23:27:06201 layer_tree_host_->contentsTextureManager()->
202 pushTexturePrioritiesToBackings();
203 layer_tree_host_->beginCommitOnImplThread(layer_tree_host_impl_.get());
[email protected]94f206c12012-08-25 00:09:14204
[email protected]a8a049c2013-03-11 23:27:06205 scoped_ptr<ResourceUpdateController> updateController =
206 ResourceUpdateController::Create(
207 NULL,
208 Proxy::MainThread(),
209 queue.Pass(),
210 layer_tree_host_impl_->resourceProvider());
211 updateController->Finalize();
[email protected]94f206c12012-08-25 00:09:14212
[email protected]a8a049c2013-03-11 23:27:06213 layer_tree_host_->finishCommitOnImplThread(layer_tree_host_impl_.get());
[email protected]94f206c12012-08-25 00:09:14214
[email protected]a8a049c2013-03-11 23:27:06215 layer_tree_host_impl_->commitComplete();
[email protected]94f206c12012-08-25 00:09:14216
[email protected]1d993172012-10-18 18:15:04217#ifndef NDEBUG
[email protected]a8a049c2013-03-11 23:27:06218 // In the single-threaded case, the scroll deltas should never be
219 // touched on the impl layer tree.
220 scoped_ptr<ScrollAndScaleSet> scrollInfo =
221 layer_tree_host_impl_->processScrollDeltas();
222 DCHECK(!scrollInfo->scrolls.size());
[email protected]94f206c12012-08-25 00:09:14223#endif
[email protected]8b9af6b2012-09-27 00:36:36224
[email protected]a8a049c2013-03-11 23:27:06225 base::TimeTicks endTime = base::TimeTicks::HighResNow();
226 total_commit_time_ += endTime - startTime;
227 total_commit_count_++;
228 }
229 layer_tree_host_->commitComplete();
230 next_frame_is_newly_committed_frame_ = true;
[email protected]94f206c12012-08-25 00:09:14231}
232
[email protected]a8a049c2013-03-11 23:27:06233void SingleThreadProxy::SetNeedsCommit() {
234 DCHECK(Proxy::IsMainThread());
235 layer_tree_host_->scheduleComposite();
[email protected]94f206c12012-08-25 00:09:14236}
237
[email protected]a8a049c2013-03-11 23:27:06238void SingleThreadProxy::SetNeedsRedraw() {
239 // FIXME: Once we move render_widget scheduling into this class, we can
240 // treat redraw requests more efficiently than commitAndRedraw requests.
241 layer_tree_host_impl_->SetFullRootLayerDamage();
242 SetNeedsCommit();
[email protected]94f206c12012-08-25 00:09:14243}
244
[email protected]a8a049c2013-03-11 23:27:06245void SingleThreadProxy::onHasPendingTreeStateChanged(bool have_pending_tree) {
246 // Thread-only feature.
247 NOTREACHED();
[email protected]2e7ca422012-12-20 02:57:27248}
249
[email protected]a8a049c2013-03-11 23:27:06250void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
251 // Thread-only feature.
252 NOTREACHED();
[email protected]6b16679e2012-10-27 00:44:28253}
254
[email protected]a8a049c2013-03-11 23:27:06255bool SingleThreadProxy::CommitRequested() const { return false; }
256
257size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
258 return std::numeric_limits<size_t>::max();
259}
260
261void SingleThreadProxy::Stop() {
262 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
263 DCHECK(Proxy::IsMainThread());
264 {
265 DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
266 DebugScopedSetImplThread impl(this);
267
268 layer_tree_host_->deleteContentsTexturesOnImplThread(
269 layer_tree_host_impl_->resourceProvider());
270 layer_tree_host_impl_.reset();
271 }
272 layer_tree_host_ = 0;
273}
274
275void SingleThreadProxy::setNeedsRedrawOnImplThread() {
276 layer_tree_host_->scheduleComposite();
277}
278
279void SingleThreadProxy::didUploadVisibleHighResolutionTileOnImplThread() {
280 // Impl-side painting only.
281 NOTREACHED();
282}
283
284void SingleThreadProxy::setNeedsCommitOnImplThread() {
285 layer_tree_host_->scheduleComposite();
286}
287
288void SingleThreadProxy::setNeedsManageTilesOnImplThread() {
289 layer_tree_host_->scheduleComposite();
290}
291
292void SingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(
293 scoped_ptr<AnimationEventsVector> events,
294 base::Time wall_clock_time) {
295 DCHECK(Proxy::IsImplThread());
296 DebugScopedSetMainThread main(this);
297 layer_tree_host_->setAnimationEvents(events.Pass(), wall_clock_time);
298}
299
300bool SingleThreadProxy::reduceContentsTextureMemoryOnImplThread(
301 size_t limit_bytes,
302 int priority_cutoff) {
303 DCHECK(IsImplThread());
304 if (!layer_tree_host_->contentsTextureManager())
[email protected]94f206c12012-08-25 00:09:14305 return false;
[email protected]a8a049c2013-03-11 23:27:06306
307 return layer_tree_host_->contentsTextureManager()->reduceMemoryOnImplThread(
308 limit_bytes, priority_cutoff, layer_tree_host_impl_->resourceProvider());
[email protected]94f206c12012-08-25 00:09:14309}
310
[email protected]a8a049c2013-03-11 23:27:06311void SingleThreadProxy::reduceWastedContentsTextureMemoryOnImplThread() {
312 // Impl-side painting only.
313 NOTREACHED();
[email protected]493067512012-09-19 23:34:10314}
315
[email protected]a8a049c2013-03-11 23:27:06316void SingleThreadProxy::sendManagedMemoryStats() {
317 DCHECK(Proxy::IsImplThread());
318 if (!layer_tree_host_impl_.get())
319 return;
320 if (!layer_tree_host_->contentsTextureManager())
321 return;
[email protected]94f206c12012-08-25 00:09:14322
[email protected]a8a049c2013-03-11 23:27:06323 layer_tree_host_impl_->sendManagedMemoryStats(
324 layer_tree_host_->contentsTextureManager()->memoryVisibleBytes(),
325 layer_tree_host_->contentsTextureManager()->memoryVisibleAndNearbyBytes(),
326 layer_tree_host_->contentsTextureManager()->memoryUseBytes());
[email protected]94f206c12012-08-25 00:09:14327}
328
[email protected]a8a049c2013-03-11 23:27:06329bool SingleThreadProxy::isInsideDraw() { return inside_draw_; }
330
331void SingleThreadProxy::didLoseOutputSurfaceOnImplThread() {
332 // Cause a commit so we can notice the lost context.
333 setNeedsCommitOnImplThread();
[email protected]493067512012-09-19 23:34:10334}
335
[email protected]a8a049c2013-03-11 23:27:06336// Called by the legacy scheduling path (e.g. where render_widget does the
337// scheduling)
338void SingleThreadProxy::CompositeImmediately() {
339 if (CommitAndComposite()) {
340 layer_tree_host_impl_->swapBuffers();
341 DidSwapFrame();
342 }
[email protected]74d9063c2013-01-18 03:14:47343}
344
[email protected]a8a049c2013-03-11 23:27:06345scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
346 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
347 {
348 // The following line casts away const modifiers because it is just
349 // setting debug state. We still want the AsValue() function and its
350 // call chain to be const throughout.
351 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
352
353 state->Set("layer_tree_host_impl",
354 layer_tree_host_impl_->asValue().release());
355 }
356 return state.PassAs<base::Value>();
[email protected]493067512012-09-19 23:34:10357}
358
[email protected]a8a049c2013-03-11 23:27:06359void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
360 {
361 DebugScopedSetImplThread impl(this);
362 if (renderer_initialized_)
363 layer_tree_host_impl_->renderer()->DoNoOp();
364 }
[email protected]8947cbe2012-11-28 05:27:43365}
366
[email protected]a8a049c2013-03-11 23:27:06367void SingleThreadProxy::onSwapBuffersCompleteOnImplThread() { NOTREACHED(); }
[email protected]94f206c12012-08-25 00:09:14368
[email protected]a8a049c2013-03-11 23:27:06369bool SingleThreadProxy::CommitAndComposite() {
370 DCHECK(Proxy::IsMainThread());
[email protected]b1969fa2012-10-17 20:16:29371
[email protected]a8a049c2013-03-11 23:27:06372 if (!layer_tree_host_->initializeRendererIfNeeded())
[email protected]16288a42012-12-17 23:31:05373 return false;
[email protected]a8a049c2013-03-11 23:27:06374
375 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
376 if (renderer_capabilities_for_main_thread_.usingOffscreenContext3d &&
377 layer_tree_host_->needsOffscreenContext()) {
378 offscreen_context_provider =
379 layer_tree_host_->client()->OffscreenContextProviderForMainThread();
380 if (offscreen_context_provider->InitializeOnMainThread())
381 created_offscreen_context_provider = true;
382 else
383 offscreen_context_provider = NULL;
384 }
385
386 layer_tree_host_->contentsTextureManager()->unlinkAndClearEvictedBackings();
387
388 scoped_ptr<ResourceUpdateQueue> queue =
389 make_scoped_ptr(new ResourceUpdateQueue);
390 layer_tree_host_->updateLayers(
391 *(queue.get()), layer_tree_host_impl_->memoryAllocationLimitBytes());
392
393 layer_tree_host_->willCommit();
394 DoCommit(queue.Pass());
395 bool result = DoComposite(offscreen_context_provider);
396 layer_tree_host_->didBeginFrame();
397 return result;
[email protected]16288a42012-12-17 23:31:05398}
399
[email protected]a8a049c2013-03-11 23:27:06400bool SingleThreadProxy::DoComposite(
401 scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
402 DCHECK(!output_surface_lost_);
403 {
404 DebugScopedSetImplThread impl(this);
405 base::AutoReset<bool> mark_inside(&inside_draw_, true);
406
407 layer_tree_host_impl_->resourceProvider()->
408 SetOffscreenContextProvider(offscreen_context_provider);
409
410 if (!layer_tree_host_impl_->visible())
411 return false;
412
413 layer_tree_host_impl_->animate(base::TimeTicks::Now(), base::Time::Now());
414
415 // We guard prepareToDraw() with canDraw() because it always returns a valid
416 // frame, so can only be used when such a frame is possible. Since
417 // drawLayers() depends on the result of prepareToDraw(), it is guarded on
418 // canDraw() as well.
419 if (!layer_tree_host_impl_->canDraw())
420 return false;
421
422 LayerTreeHostImpl::FrameData frame;
423 layer_tree_host_impl_->prepareToDraw(frame);
424 layer_tree_host_impl_->drawLayers(frame);
425 layer_tree_host_impl_->didDrawAllLayers(frame);
426 output_surface_lost_ = layer_tree_host_impl_->isContextLost();
427
428 layer_tree_host_impl_->beginNextFrame();
429 }
430
431 if (output_surface_lost_) {
432 cc::ContextProvider* offscreen_contexts = layer_tree_host_impl_->
433 resourceProvider()->offscreen_context_provider();
434 if (offscreen_contexts)
435 offscreen_contexts->VerifyContexts();
436 layer_tree_host_->didLoseOutputSurface();
437 return false;
438 }
439
440 return true;
441}
442
443void SingleThreadProxy::DidSwapFrame() {
444 if (next_frame_is_newly_committed_frame_) {
445 next_frame_is_newly_committed_frame_ = false;
446 layer_tree_host_->didCommitAndDrawFrame();
447 }
448}
449
450bool SingleThreadProxy::CommitPendingForTesting() { return false; }
451
452skia::RefPtr<SkPicture> SingleThreadProxy::CapturePicture() {
453 // Impl-side painting only.
454 NOTREACHED();
455 return skia::RefPtr<SkPicture>();
[email protected]b9dcf43a2013-01-09 00:15:29456}
457
[email protected]bc5e77c2012-11-05 20:00:49458} // namespace cc