Disable blink_perf.events on x64.
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blobc25ed4d1dbb6d5f48337e29594a8044f09eab369
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/trees/single_thread_proxy.h"
7 #include "base/auto_reset.h"
8 #include "base/profiler/scoped_tracker.h"
9 #include "base/trace_event/trace_event.h"
10 #include "cc/debug/benchmark_instrumentation.h"
11 #include "cc/debug/devtools_instrumentation.h"
12 #include "cc/output/context_provider.h"
13 #include "cc/output/output_surface.h"
14 #include "cc/quads/draw_quad.h"
15 #include "cc/resources/prioritized_resource_manager.h"
16 #include "cc/resources/resource_update_controller.h"
17 #include "cc/scheduler/commit_earlyout_reason.h"
18 #include "cc/trees/layer_tree_host.h"
19 #include "cc/trees/layer_tree_host_single_thread_client.h"
20 #include "cc/trees/layer_tree_impl.h"
21 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
22 #include "ui/gfx/frame_time.h"
24 namespace cc {
26 scoped_ptr<Proxy> SingleThreadProxy::Create(
27 LayerTreeHost* layer_tree_host,
28 LayerTreeHostSingleThreadClient* client,
29 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
30 scoped_ptr<BeginFrameSource> external_begin_frame_source) {
31 return make_scoped_ptr(new SingleThreadProxy(
32 layer_tree_host,
33 client,
34 main_task_runner,
35 external_begin_frame_source.Pass()));
38 SingleThreadProxy::SingleThreadProxy(
39 LayerTreeHost* layer_tree_host,
40 LayerTreeHostSingleThreadClient* client,
41 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
42 scoped_ptr<BeginFrameSource> external_begin_frame_source)
43 : Proxy(main_task_runner, NULL),
44 layer_tree_host_(layer_tree_host),
45 client_(client),
46 timing_history_(layer_tree_host->rendering_stats_instrumentation()),
47 next_frame_is_newly_committed_frame_(false),
48 inside_draw_(false),
49 defer_commits_(false),
50 commit_requested_(false),
51 inside_synchronous_composite_(false),
52 output_surface_creation_requested_(false),
53 external_begin_frame_source_(external_begin_frame_source.Pass()),
54 weak_factory_(this) {
55 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
56 DCHECK(Proxy::IsMainThread());
57 DCHECK(layer_tree_host);
60 void SingleThreadProxy::Start() {
61 DebugScopedSetImplThread impl(this);
62 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
65 SingleThreadProxy::~SingleThreadProxy() {
66 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
67 DCHECK(Proxy::IsMainThread());
68 // Make sure Stop() got called or never Started.
69 DCHECK(!layer_tree_host_impl_);
72 void SingleThreadProxy::FinishAllRendering() {
73 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
74 DCHECK(Proxy::IsMainThread());
76 DebugScopedSetImplThread impl(this);
77 layer_tree_host_impl_->FinishAllRendering();
81 bool SingleThreadProxy::IsStarted() const {
82 DCHECK(Proxy::IsMainThread());
83 return layer_tree_host_impl_;
86 bool SingleThreadProxy::CommitToActiveTree() const {
87 // With SingleThreadProxy we skip the pending tree and commit directly to the
88 // active tree.
89 return true;
92 void SingleThreadProxy::SetLayerTreeHostClientReady() {
93 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
94 // Scheduling is controlled by the embedder in the single thread case, so
95 // nothing to do.
96 DCHECK(Proxy::IsMainThread());
97 DebugScopedSetImplThread impl(this);
98 if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
99 !scheduler_on_impl_thread_) {
100 SchedulerSettings scheduler_settings(
101 layer_tree_host_->settings().ToSchedulerSettings());
102 // SingleThreadProxy should run in main thread low latency mode.
103 scheduler_settings.main_thread_should_always_be_low_latency = true;
104 scheduler_on_impl_thread_ =
105 Scheduler::Create(this,
106 scheduler_settings,
107 layer_tree_host_->id(),
108 MainThreadTaskRunner(),
109 external_begin_frame_source_.Pass());
110 scheduler_on_impl_thread_->SetCanStart();
111 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
115 void SingleThreadProxy::SetVisible(bool visible) {
116 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
117 DebugScopedSetImplThread impl(this);
118 layer_tree_host_impl_->SetVisible(visible);
119 if (scheduler_on_impl_thread_)
120 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
121 // Changing visibility could change ShouldComposite().
124 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) {
125 TRACE_EVENT1("cc", "SingleThreadProxy::SetThrottleFrameProduction",
126 "throttle", throttle);
127 DebugScopedSetImplThread impl(this);
128 if (scheduler_on_impl_thread_)
129 scheduler_on_impl_thread_->SetThrottleFrameProduction(throttle);
132 void SingleThreadProxy::RequestNewOutputSurface() {
133 DCHECK(Proxy::IsMainThread());
134 DCHECK(layer_tree_host_->output_surface_lost());
135 output_surface_creation_callback_.Cancel();
136 if (output_surface_creation_requested_)
137 return;
138 output_surface_creation_requested_ = true;
139 layer_tree_host_->RequestNewOutputSurface();
142 void SingleThreadProxy::SetOutputSurface(
143 scoped_ptr<OutputSurface> output_surface) {
144 DCHECK(Proxy::IsMainThread());
145 DCHECK(layer_tree_host_->output_surface_lost());
146 DCHECK(output_surface_creation_requested_);
147 renderer_capabilities_for_main_thread_ = RendererCapabilities();
149 bool success;
151 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
152 DebugScopedSetImplThread impl(this);
153 layer_tree_host_->DeleteContentsTexturesOnImplThread(
154 layer_tree_host_impl_->resource_provider());
155 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
158 if (success) {
159 layer_tree_host_->DidInitializeOutputSurface();
160 if (scheduler_on_impl_thread_)
161 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
162 else if (!inside_synchronous_composite_)
163 SetNeedsCommit();
164 output_surface_creation_requested_ = false;
165 } else {
166 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface,
167 // and so output_surface_creation_requested remains true.
168 layer_tree_host_->DidFailToInitializeOutputSurface();
172 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
173 DCHECK(Proxy::IsMainThread());
174 DCHECK(!layer_tree_host_->output_surface_lost());
175 return renderer_capabilities_for_main_thread_;
178 void SingleThreadProxy::SetNeedsAnimate() {
179 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
180 DCHECK(Proxy::IsMainThread());
181 client_->ScheduleAnimation();
182 SetNeedsCommit();
185 void SingleThreadProxy::SetNeedsUpdateLayers() {
186 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
187 DCHECK(Proxy::IsMainThread());
188 SetNeedsCommit();
191 void SingleThreadProxy::DoAnimate() {
192 // Don't animate if there is no root layer.
193 // TODO(mithro): Both Animate and UpdateAnimationState already have a
194 // "!active_tree_->root_layer()" check?
195 if (!layer_tree_host_impl_->active_tree()->root_layer()) {
196 return;
199 layer_tree_host_impl_->Animate(
200 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
202 // If animations are not visible, update the animation state now as it
203 // won't happen in DoComposite.
204 if (!layer_tree_host_impl_->AnimationsAreVisible()) {
205 layer_tree_host_impl_->UpdateAnimationState(true);
209 void SingleThreadProxy::DoCommit() {
210 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
211 DCHECK(Proxy::IsMainThread());
213 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
214 // fixed.
215 tracked_objects::ScopedTracker tracking_profile1(
216 FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1"));
217 commit_requested_ = false;
218 layer_tree_host_->WillCommit();
219 devtools_instrumentation::ScopedCommitTrace commit_task(
220 layer_tree_host_->id());
222 // Commit immediately.
224 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
225 // is fixed.
226 tracked_objects::ScopedTracker tracking_profile2(
227 FROM_HERE_WITH_EXPLICIT_FUNCTION(
228 "461509 SingleThreadProxy::DoCommit2"));
229 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
230 DebugScopedSetImplThread impl(this);
232 // This CapturePostTasks should be destroyed before CommitComplete() is
233 // called since that goes out to the embedder, and we want the embedder
234 // to receive its callbacks before that.
235 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks(
236 blocking_main_thread_task_runner()));
238 layer_tree_host_impl_->BeginCommit();
240 if (PrioritizedResourceManager* contents_texture_manager =
241 layer_tree_host_->contents_texture_manager()) {
242 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
243 // is fixed.
244 tracked_objects::ScopedTracker tracking_profile3(
245 FROM_HERE_WITH_EXPLICIT_FUNCTION(
246 "461509 SingleThreadProxy::DoCommit3"));
247 contents_texture_manager->PushTexturePrioritiesToBackings();
249 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
251 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
252 // is fixed.
253 tracked_objects::ScopedTracker tracking_profile4(
254 FROM_HERE_WITH_EXPLICIT_FUNCTION(
255 "461509 SingleThreadProxy::DoCommit4"));
256 scoped_ptr<ResourceUpdateController> update_controller =
257 ResourceUpdateController::Create(
258 NULL,
259 MainThreadTaskRunner(),
260 queue_for_commit_.Pass(),
261 layer_tree_host_impl_->resource_provider());
263 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
264 // is fixed.
265 tracked_objects::ScopedTracker tracking_profile5(
266 FROM_HERE_WITH_EXPLICIT_FUNCTION(
267 "461509 SingleThreadProxy::DoCommit5"));
268 update_controller->Finalize();
270 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
271 // is fixed.
272 tracked_objects::ScopedTracker tracking_profile6(
273 FROM_HERE_WITH_EXPLICIT_FUNCTION(
274 "461509 SingleThreadProxy::DoCommit6"));
275 if (layer_tree_host_impl_->EvictedUIResourcesExist())
276 layer_tree_host_->RecreateUIResources();
278 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
279 // is fixed.
280 tracked_objects::ScopedTracker tracking_profile7(
281 FROM_HERE_WITH_EXPLICIT_FUNCTION(
282 "461509 SingleThreadProxy::DoCommit7"));
283 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
285 #if DCHECK_IS_ON()
286 // In the single-threaded case, the scale and scroll deltas should never be
287 // touched on the impl layer tree.
288 scoped_ptr<ScrollAndScaleSet> scroll_info =
289 layer_tree_host_impl_->ProcessScrollDeltas();
290 DCHECK(!scroll_info->scrolls.size());
291 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
292 #endif
294 if (layer_tree_host_->settings().impl_side_painting) {
295 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
296 // is fixed.
297 tracked_objects::ScopedTracker tracking_profile8(
298 FROM_HERE_WITH_EXPLICIT_FUNCTION(
299 "461509 SingleThreadProxy::DoCommit8"));
300 // Commit goes directly to the active tree, but we need to synchronously
301 // "activate" the tree still during commit to satisfy any potential
302 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
303 // might not be ready to draw, so DidActivateSyncTree must set
304 // the flag to force the tree to not draw until textures are ready.
305 NotifyReadyToActivate();
306 } else {
307 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
308 // is fixed.
309 tracked_objects::ScopedTracker tracking_profile9(
310 FROM_HERE_WITH_EXPLICIT_FUNCTION(
311 "461509 SingleThreadProxy::DoCommit9"));
312 CommitComplete();
317 void SingleThreadProxy::CommitComplete() {
318 DCHECK(!layer_tree_host_impl_->pending_tree())
319 << "Activation is expected to have synchronously occurred by now.";
320 DCHECK(commit_blocking_task_runner_);
322 // Notify commit complete on the impl side after activate to satisfy any
323 // SetNextCommitWaitsForActivation calls.
324 layer_tree_host_impl_->CommitComplete();
326 DebugScopedSetMainThread main(this);
327 commit_blocking_task_runner_.reset();
328 layer_tree_host_->CommitComplete();
329 layer_tree_host_->DidBeginMainFrame();
330 timing_history_.DidCommit();
332 next_frame_is_newly_committed_frame_ = true;
335 void SingleThreadProxy::SetNeedsCommit() {
336 DCHECK(Proxy::IsMainThread());
337 DebugScopedSetImplThread impl(this);
338 client_->ScheduleComposite();
339 if (scheduler_on_impl_thread_)
340 scheduler_on_impl_thread_->SetNeedsCommit();
341 commit_requested_ = true;
344 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
345 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
346 DCHECK(Proxy::IsMainThread());
347 DebugScopedSetImplThread impl(this);
348 client_->ScheduleComposite();
349 SetNeedsRedrawRectOnImplThread(damage_rect);
352 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
353 // Activation always forced in commit, so nothing to do.
354 DCHECK(Proxy::IsMainThread());
357 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
358 DCHECK(Proxy::IsMainThread());
359 // Deferring commits only makes sense if there's a scheduler.
360 if (!scheduler_on_impl_thread_)
361 return;
362 if (defer_commits_ == defer_commits)
363 return;
365 if (defer_commits)
366 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
367 else
368 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
370 defer_commits_ = defer_commits;
371 scheduler_on_impl_thread_->SetDeferCommits(defer_commits);
374 bool SingleThreadProxy::CommitRequested() const {
375 DCHECK(Proxy::IsMainThread());
376 return commit_requested_;
379 bool SingleThreadProxy::BeginMainFrameRequested() const {
380 DCHECK(Proxy::IsMainThread());
381 // If there is no scheduler, then there can be no pending begin frame,
382 // as all frames are all manually initiated by the embedder of cc.
383 if (!scheduler_on_impl_thread_)
384 return false;
385 return commit_requested_;
388 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
389 return std::numeric_limits<size_t>::max();
392 void SingleThreadProxy::Stop() {
393 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
394 DCHECK(Proxy::IsMainThread());
396 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
397 DebugScopedSetImplThread impl(this);
399 BlockingTaskRunner::CapturePostTasks blocked(
400 blocking_main_thread_task_runner());
401 layer_tree_host_->DeleteContentsTexturesOnImplThread(
402 layer_tree_host_impl_->resource_provider());
403 scheduler_on_impl_thread_ = nullptr;
404 layer_tree_host_impl_ = nullptr;
406 layer_tree_host_ = NULL;
409 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
410 TRACE_EVENT1(
411 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
412 DCHECK(Proxy::IsImplThread());
413 if (scheduler_on_impl_thread_)
414 scheduler_on_impl_thread_->SetCanDraw(can_draw);
417 void SingleThreadProxy::NotifyReadyToActivate() {
418 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
419 DebugScopedSetImplThread impl(this);
420 if (scheduler_on_impl_thread_)
421 scheduler_on_impl_thread_->NotifyReadyToActivate();
424 void SingleThreadProxy::NotifyReadyToDraw() {
425 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToDraw");
426 DebugScopedSetImplThread impl(this);
427 if (scheduler_on_impl_thread_)
428 scheduler_on_impl_thread_->NotifyReadyToDraw();
431 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
432 client_->ScheduleComposite();
433 if (scheduler_on_impl_thread_)
434 scheduler_on_impl_thread_->SetNeedsRedraw();
437 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
438 client_->ScheduleComposite();
439 if (scheduler_on_impl_thread_)
440 scheduler_on_impl_thread_->SetNeedsAnimate();
443 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
444 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
445 if (scheduler_on_impl_thread_)
446 scheduler_on_impl_thread_->SetNeedsPrepareTiles();
449 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
450 const gfx::Rect& damage_rect) {
451 layer_tree_host_impl_->SetViewportDamage(damage_rect);
452 SetNeedsRedrawOnImplThread();
455 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
456 client_->ScheduleComposite();
457 if (scheduler_on_impl_thread_)
458 scheduler_on_impl_thread_->SetNeedsCommit();
461 void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
462 TRACE_EVENT1("cc", "SingleThreadProxy::SetVideoNeedsBeginFrames",
463 "needs_begin_frames", needs_begin_frames);
464 // In tests the layer tree is destroyed after the scheduler is.
465 if (scheduler_on_impl_thread_)
466 scheduler_on_impl_thread_->SetVideoNeedsBeginFrames(needs_begin_frames);
469 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
470 scoped_ptr<AnimationEventsVector> events) {
471 TRACE_EVENT0(
472 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
473 DCHECK(Proxy::IsImplThread());
474 DebugScopedSetMainThread main(this);
475 layer_tree_host_->SetAnimationEvents(events.Pass());
478 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
479 size_t limit_bytes,
480 int priority_cutoff) {
481 DCHECK(IsImplThread());
482 PrioritizedResourceManager* contents_texture_manager =
483 layer_tree_host_->contents_texture_manager();
485 ResourceProvider* resource_provider =
486 layer_tree_host_impl_->resource_provider();
488 if (!contents_texture_manager || !resource_provider)
489 return false;
491 return contents_texture_manager->ReduceMemoryOnImplThread(
492 limit_bytes, priority_cutoff, resource_provider);
495 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
497 void SingleThreadProxy::DidActivateSyncTree() {
498 // Non-impl-side painting finishes commit in DoCommit. Impl-side painting
499 // defers until here to simulate SetNextCommitWaitsForActivation.
500 if (layer_tree_host_impl_->settings().impl_side_painting) {
501 // This is required because NotifyReadyToActivate gets called immediately
502 // after commit since single thread commits directly to the active tree.
503 if (scheduler_on_impl_thread_)
504 scheduler_on_impl_thread_->SetWaitForReadyToDraw();
506 // Synchronously call to CommitComplete. Resetting
507 // |commit_blocking_task_runner| would make sure all tasks posted during
508 // commit/activation before CommitComplete.
509 CommitComplete();
512 timing_history_.DidActivateSyncTree();
515 void SingleThreadProxy::DidPrepareTiles() {
516 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
517 DCHECK(Proxy::IsImplThread());
518 if (scheduler_on_impl_thread_)
519 scheduler_on_impl_thread_->DidPrepareTiles();
522 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
523 layer_tree_host_->DidCompletePageScaleAnimation();
526 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
527 DCHECK(IsImplThread());
528 renderer_capabilities_for_main_thread_ =
529 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
532 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
533 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
535 DebugScopedSetMainThread main(this);
536 // This must happen before we notify the scheduler as it may try to recreate
537 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
538 layer_tree_host_->DidLoseOutputSurface();
540 client_->DidAbortSwapBuffers();
541 if (scheduler_on_impl_thread_)
542 scheduler_on_impl_thread_->DidLoseOutputSurface();
545 void SingleThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
546 base::TimeDelta interval) {
547 if (scheduler_on_impl_thread_)
548 scheduler_on_impl_thread_->CommitVSyncParameters(timebase, interval);
551 void SingleThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
552 if (scheduler_on_impl_thread_)
553 scheduler_on_impl_thread_->SetEstimatedParentDrawTime(draw_time);
556 void SingleThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
557 if (scheduler_on_impl_thread_)
558 scheduler_on_impl_thread_->SetMaxSwapsPending(max);
561 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
562 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
563 if (scheduler_on_impl_thread_)
564 scheduler_on_impl_thread_->DidSwapBuffers();
565 client_->DidPostSwapBuffers();
568 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
569 TRACE_EVENT0("cc,benchmark",
570 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
571 if (scheduler_on_impl_thread_)
572 scheduler_on_impl_thread_->DidSwapBuffersComplete();
573 layer_tree_host_->DidCompleteSwapBuffers();
576 void SingleThreadProxy::OnDrawForOutputSurface() {
577 NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor.";
580 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
581 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
582 DCHECK(Proxy::IsMainThread());
583 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
585 if (layer_tree_host_->output_surface_lost()) {
586 RequestNewOutputSurface();
587 // RequestNewOutputSurface could have synchronously created an output
588 // surface, so check again before returning.
589 if (layer_tree_host_->output_surface_lost())
590 return;
594 BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
595 BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(),
596 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL));
597 DoBeginMainFrame(begin_frame_args);
598 DoCommit();
600 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
601 << "Commit should always succeed and transfer promises.";
605 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
606 if (layer_tree_host_impl_->settings().impl_side_painting) {
607 layer_tree_host_impl_->ActivateSyncTree();
608 DCHECK(!layer_tree_host_impl_->active_tree()
609 ->needs_update_draw_properties());
610 layer_tree_host_impl_->PrepareTiles();
611 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
614 DoAnimate();
616 LayerTreeHostImpl::FrameData frame;
617 DoComposite(frame_begin_time, &frame);
619 // DoComposite could abort, but because this is a synchronous composite
620 // another draw will never be scheduled, so break remaining promises.
621 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
622 SwapPromise::SWAP_FAILS);
626 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
628 DebugScopedSetImplThread impl(this);
629 if (layer_tree_host_impl_->renderer()) {
630 DCHECK(!layer_tree_host_->output_surface_lost());
631 layer_tree_host_impl_->renderer()->DoNoOp();
636 bool SingleThreadProxy::SupportsImplScrolling() const {
637 return false;
640 bool SingleThreadProxy::ShouldComposite() const {
641 DCHECK(Proxy::IsImplThread());
642 return layer_tree_host_impl_->visible() &&
643 layer_tree_host_impl_->CanDraw();
646 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
647 if (output_surface_creation_callback_.IsCancelled() &&
648 !output_surface_creation_requested_) {
649 output_surface_creation_callback_.Reset(
650 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
651 weak_factory_.GetWeakPtr()));
652 MainThreadTaskRunner()->PostTask(
653 FROM_HERE, output_surface_creation_callback_.callback());
657 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
658 LayerTreeHostImpl::FrameData* frame) {
659 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
660 DCHECK(!layer_tree_host_->output_surface_lost());
662 DrawResult draw_result;
663 bool draw_frame;
665 DebugScopedSetImplThread impl(this);
666 base::AutoReset<bool> mark_inside(&inside_draw_, true);
668 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
669 // is fixed.
670 tracked_objects::ScopedTracker tracking_profile1(
671 FROM_HERE_WITH_EXPLICIT_FUNCTION(
672 "461509 SingleThreadProxy::DoComposite1"));
674 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
675 // frame, so can only be used when such a frame is possible. Since
676 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
677 // CanDraw() as well.
678 if (!ShouldComposite()) {
679 return DRAW_ABORTED_CANT_DRAW;
682 timing_history_.DidStartDrawing();
684 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
685 // is fixed.
686 tracked_objects::ScopedTracker tracking_profile2(
687 FROM_HERE_WITH_EXPLICIT_FUNCTION(
688 "461509 SingleThreadProxy::DoComposite2"));
689 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
690 draw_frame = draw_result == DRAW_SUCCESS;
691 if (draw_frame) {
692 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
693 // is fixed.
694 tracked_objects::ScopedTracker tracking_profile3(
695 FROM_HERE_WITH_EXPLICIT_FUNCTION(
696 "461509 SingleThreadProxy::DoComposite3"));
697 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
699 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
700 // is fixed.
701 tracked_objects::ScopedTracker tracking_profile4(
702 FROM_HERE_WITH_EXPLICIT_FUNCTION(
703 "461509 SingleThreadProxy::DoComposite4"));
704 layer_tree_host_impl_->DidDrawAllLayers(*frame);
706 bool start_ready_animations = draw_frame;
707 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
708 // is fixed.
709 tracked_objects::ScopedTracker tracking_profile5(
710 FROM_HERE_WITH_EXPLICIT_FUNCTION(
711 "461509 SingleThreadProxy::DoComposite5"));
712 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
713 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
714 // is fixed.
715 tracked_objects::ScopedTracker tracking_profile6(
716 FROM_HERE_WITH_EXPLICIT_FUNCTION(
717 "461509 SingleThreadProxy::DoComposite6"));
718 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
720 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
721 // is fixed.
722 tracked_objects::ScopedTracker tracking_profile7(
723 FROM_HERE_WITH_EXPLICIT_FUNCTION(
724 "461509 SingleThreadProxy::DoComposite7"));
725 timing_history_.DidFinishDrawing();
728 if (draw_frame) {
729 DebugScopedSetImplThread impl(this);
731 // This CapturePostTasks should be destroyed before
732 // DidCommitAndDrawFrame() is called since that goes out to the
733 // embedder,
734 // and we want the embedder to receive its callbacks before that.
735 // NOTE: This maintains consistent ordering with the ThreadProxy since
736 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
737 // there as the main thread is not blocked, so any posted tasks inside
738 // the swap buffers will execute first.
739 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
741 BlockingTaskRunner::CapturePostTasks blocked(
742 blocking_main_thread_task_runner());
743 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
744 // is fixed.
745 tracked_objects::ScopedTracker tracking_profile8(
746 FROM_HERE_WITH_EXPLICIT_FUNCTION(
747 "461509 SingleThreadProxy::DoComposite8"));
748 layer_tree_host_impl_->SwapBuffers(*frame);
750 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
751 // fixed.
752 tracked_objects::ScopedTracker tracking_profile9(
753 FROM_HERE_WITH_EXPLICIT_FUNCTION(
754 "461509 SingleThreadProxy::DoComposite9"));
755 DidCommitAndDrawFrame();
757 return draw_result;
760 void SingleThreadProxy::DidCommitAndDrawFrame() {
761 if (next_frame_is_newly_committed_frame_) {
762 DebugScopedSetMainThread main(this);
763 next_frame_is_newly_committed_frame_ = false;
764 layer_tree_host_->DidCommitAndDrawFrame();
768 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
769 return false;
772 void SingleThreadProxy::SetChildrenNeedBeginFrames(
773 bool children_need_begin_frames) {
774 scheduler_on_impl_thread_->SetChildrenNeedBeginFrames(
775 children_need_begin_frames);
778 void SingleThreadProxy::SetAuthoritativeVSyncInterval(
779 const base::TimeDelta& interval) {
780 scheduler_on_impl_thread_->SetAuthoritativeVSyncInterval(interval);
783 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
784 layer_tree_host_impl_->WillBeginImplFrame(args);
787 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
788 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
789 // Although this proxy is single-threaded, it's problematic to synchronously
790 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
791 // could cause a commit to occur in between a series of SetNeedsCommit calls
792 // (i.e. property modifications) causing some to fall on one frame and some to
793 // fall on the next. Doing it asynchronously instead matches the semantics of
794 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
795 // synchronous commit.
796 MainThreadTaskRunner()->PostTask(
797 FROM_HERE,
798 base::Bind(&SingleThreadProxy::BeginMainFrame,
799 weak_factory_.GetWeakPtr()));
802 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() {
803 layer_tree_host_->BeginMainFrameNotExpectedSoon();
806 void SingleThreadProxy::BeginMainFrame() {
807 if (defer_commits_) {
808 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
809 TRACE_EVENT_SCOPE_THREAD);
810 BeginMainFrameAbortedOnImplThread(
811 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
812 return;
815 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
816 // commit.
817 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
819 if (!layer_tree_host_->visible()) {
820 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
821 BeginMainFrameAbortedOnImplThread(
822 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
823 return;
826 if (layer_tree_host_->output_surface_lost()) {
827 TRACE_EVENT_INSTANT0(
828 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
829 BeginMainFrameAbortedOnImplThread(
830 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
831 return;
834 const BeginFrameArgs& begin_frame_args =
835 layer_tree_host_impl_->CurrentBeginFrameArgs();
836 DoBeginMainFrame(begin_frame_args);
839 void SingleThreadProxy::DoBeginMainFrame(
840 const BeginFrameArgs& begin_frame_args) {
841 layer_tree_host_->WillBeginMainFrame();
842 layer_tree_host_->BeginMainFrame(begin_frame_args);
843 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
844 layer_tree_host_->Layout();
846 if (PrioritizedResourceManager* contents_texture_manager =
847 layer_tree_host_->contents_texture_manager()) {
848 contents_texture_manager->UnlinkAndClearEvictedBackings();
849 contents_texture_manager->SetMaxMemoryLimitBytes(
850 layer_tree_host_impl_->memory_allocation_limit_bytes());
851 contents_texture_manager->SetExternalPriorityCutoff(
852 layer_tree_host_impl_->memory_allocation_priority_cutoff());
855 DCHECK(!queue_for_commit_);
856 queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue);
858 layer_tree_host_->UpdateLayers(queue_for_commit_.get());
860 timing_history_.DidBeginMainFrame();
862 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
863 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
864 // thread_proxy.cc
865 if (scheduler_on_impl_thread_) {
866 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
867 scheduler_on_impl_thread_->NotifyReadyToCommit();
871 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
872 CommitEarlyOutReason reason) {
873 DebugScopedSetImplThread impl(this);
874 DCHECK(scheduler_on_impl_thread_->CommitPending());
875 DCHECK(!layer_tree_host_impl_->pending_tree());
877 layer_tree_host_impl_->BeginMainFrameAborted(reason);
878 scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
881 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
882 DebugScopedSetImplThread impl(this);
883 LayerTreeHostImpl::FrameData frame;
884 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
885 &frame);
888 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
889 NOTREACHED();
890 return INVALID_RESULT;
893 void SingleThreadProxy::ScheduledActionCommit() {
894 DebugScopedSetMainThread main(this);
895 DoCommit();
898 void SingleThreadProxy::ScheduledActionAnimate() {
899 TRACE_EVENT0("cc", "ScheduledActionAnimate");
900 DebugScopedSetImplThread impl(this);
901 DoAnimate();
904 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
905 DebugScopedSetImplThread impl(this);
906 layer_tree_host_impl_->ActivateSyncTree();
909 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
910 DebugScopedSetMainThread main(this);
911 DCHECK(scheduler_on_impl_thread_);
912 // If possible, create the output surface in a post task. Synchronously
913 // creating the output surface makes tests more awkward since this differs
914 // from the ThreadProxy behavior. However, sometimes there is no
915 // task runner.
916 if (Proxy::MainThreadTaskRunner()) {
917 ScheduleRequestNewOutputSurface();
918 } else {
919 RequestNewOutputSurface();
923 void SingleThreadProxy::ScheduledActionPrepareTiles() {
924 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
925 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
926 DebugScopedSetImplThread impl(this);
927 layer_tree_host_impl_->PrepareTiles();
930 void SingleThreadProxy::ScheduledActionInvalidateOutputSurface() {
931 NOTREACHED();
934 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
937 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
938 return timing_history_.DrawDurationEstimate();
941 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
942 return timing_history_.BeginMainFrameToCommitDurationEstimate();
945 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
946 return timing_history_.CommitToActivateDurationEstimate();
949 void SingleThreadProxy::DidBeginImplFrameDeadline() {
950 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
953 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
954 layer_tree_host_->SendBeginFramesToChildren(args);
957 } // namespace cc