Roll src/third_party/skia d32087a:1052f51
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blobbcda921ff86dc86bf20feb23499c812330c2107d
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/scheduler/commit_earlyout_reason.h"
16 #include "cc/scheduler/compositor_timing_history.h"
17 #include "cc/scheduler/scheduler.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"
23 namespace cc {
25 scoped_ptr<Proxy> SingleThreadProxy::Create(
26 LayerTreeHost* layer_tree_host,
27 LayerTreeHostSingleThreadClient* client,
28 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
29 scoped_ptr<BeginFrameSource> external_begin_frame_source) {
30 return make_scoped_ptr(new SingleThreadProxy(
31 layer_tree_host,
32 client,
33 main_task_runner,
34 external_begin_frame_source.Pass()));
37 SingleThreadProxy::SingleThreadProxy(
38 LayerTreeHost* layer_tree_host,
39 LayerTreeHostSingleThreadClient* client,
40 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
41 scoped_ptr<BeginFrameSource> external_begin_frame_source)
42 : Proxy(main_task_runner, NULL),
43 layer_tree_host_(layer_tree_host),
44 client_(client),
45 external_begin_frame_source_(external_begin_frame_source.Pass()),
46 next_frame_is_newly_committed_frame_(false),
47 #if DCHECK_IS_ON()
48 inside_impl_frame_(false),
49 #endif
50 inside_draw_(false),
51 defer_commits_(false),
52 animate_requested_(false),
53 commit_requested_(false),
54 inside_synchronous_composite_(false),
55 output_surface_creation_requested_(false),
56 weak_factory_(this) {
57 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
58 DCHECK(Proxy::IsMainThread());
59 DCHECK(layer_tree_host);
61 if (layer_tree_host->settings().single_thread_proxy_scheduler &&
62 !scheduler_on_impl_thread_) {
63 SchedulerSettings scheduler_settings(
64 layer_tree_host->settings().ToSchedulerSettings());
65 scheduler_settings.commit_to_active_tree = CommitToActiveTree();
67 scoped_ptr<CompositorTimingHistory> compositor_timing_history(
68 new CompositorTimingHistory(
69 CompositorTimingHistory::BROWSER_UMA,
70 layer_tree_host->rendering_stats_instrumentation()));
72 scheduler_on_impl_thread_ = Scheduler::Create(
73 this, scheduler_settings, layer_tree_host_->id(),
74 MainThreadTaskRunner(), external_begin_frame_source_.get(),
75 compositor_timing_history.Pass());
79 void SingleThreadProxy::Start() {
80 DebugScopedSetImplThread impl(this);
81 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
84 SingleThreadProxy::~SingleThreadProxy() {
85 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
86 DCHECK(Proxy::IsMainThread());
87 // Make sure Stop() got called or never Started.
88 DCHECK(!layer_tree_host_impl_);
91 void SingleThreadProxy::FinishAllRendering() {
92 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
93 DCHECK(Proxy::IsMainThread());
95 DebugScopedSetImplThread impl(this);
96 layer_tree_host_impl_->FinishAllRendering();
100 bool SingleThreadProxy::IsStarted() const {
101 DCHECK(Proxy::IsMainThread());
102 return layer_tree_host_impl_;
105 bool SingleThreadProxy::CommitToActiveTree() const {
106 // With SingleThreadProxy we skip the pending tree and commit directly to the
107 // active tree.
108 return true;
111 void SingleThreadProxy::SetLayerTreeHostClientReady() {
112 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
113 // Scheduling is controlled by the embedder in the single thread case, so
114 // nothing to do.
115 DCHECK(Proxy::IsMainThread());
116 DebugScopedSetImplThread impl(this);
117 if (scheduler_on_impl_thread_) {
118 scheduler_on_impl_thread_->SetCanStart();
119 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
123 void SingleThreadProxy::SetVisible(bool visible) {
124 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
125 DebugScopedSetImplThread impl(this);
127 layer_tree_host_impl_->SetVisible(visible);
129 if (scheduler_on_impl_thread_)
130 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
131 // Changing visibility could change ShouldComposite().
134 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) {
135 TRACE_EVENT1("cc", "SingleThreadProxy::SetThrottleFrameProduction",
136 "throttle", throttle);
137 DebugScopedSetImplThread impl(this);
138 if (scheduler_on_impl_thread_)
139 scheduler_on_impl_thread_->SetThrottleFrameProduction(throttle);
142 void SingleThreadProxy::RequestNewOutputSurface() {
143 DCHECK(Proxy::IsMainThread());
144 DCHECK(layer_tree_host_->output_surface_lost());
145 output_surface_creation_callback_.Cancel();
146 if (output_surface_creation_requested_)
147 return;
148 output_surface_creation_requested_ = true;
149 layer_tree_host_->RequestNewOutputSurface();
152 scoped_ptr<OutputSurface> SingleThreadProxy::ReleaseOutputSurface() {
153 if (scheduler_on_impl_thread_)
154 scheduler_on_impl_thread_->DidLoseOutputSurface();
155 return layer_tree_host_impl_->ReleaseOutputSurface();
158 void SingleThreadProxy::SetOutputSurface(
159 scoped_ptr<OutputSurface> output_surface) {
160 DCHECK(Proxy::IsMainThread());
161 DCHECK(layer_tree_host_->output_surface_lost());
162 DCHECK(output_surface_creation_requested_);
163 renderer_capabilities_for_main_thread_ = RendererCapabilities();
165 bool success;
167 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
168 DebugScopedSetImplThread impl(this);
169 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
172 if (success) {
173 layer_tree_host_->DidInitializeOutputSurface();
174 if (scheduler_on_impl_thread_)
175 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
176 else if (!inside_synchronous_composite_)
177 SetNeedsCommit();
178 output_surface_creation_requested_ = false;
179 } else {
180 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface,
181 // and so output_surface_creation_requested remains true.
182 layer_tree_host_->DidFailToInitializeOutputSurface();
186 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
187 DCHECK(Proxy::IsMainThread());
188 DCHECK(!layer_tree_host_->output_surface_lost());
189 return renderer_capabilities_for_main_thread_;
192 void SingleThreadProxy::SetNeedsAnimate() {
193 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
194 DCHECK(Proxy::IsMainThread());
195 client_->ScheduleAnimation();
196 if (animate_requested_)
197 return;
198 animate_requested_ = true;
199 DebugScopedSetImplThread impl(this);
200 if (scheduler_on_impl_thread_)
201 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
204 void SingleThreadProxy::SetNeedsUpdateLayers() {
205 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
206 DCHECK(Proxy::IsMainThread());
207 SetNeedsCommit();
210 void SingleThreadProxy::DoCommit() {
211 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
212 DCHECK(Proxy::IsMainThread());
214 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
215 // fixed.
216 tracked_objects::ScopedTracker tracking_profile1(
217 FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1"));
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 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
241 // is fixed.
242 tracked_objects::ScopedTracker tracking_profile6(
243 FROM_HERE_WITH_EXPLICIT_FUNCTION(
244 "461509 SingleThreadProxy::DoCommit6"));
245 if (layer_tree_host_impl_->EvictedUIResourcesExist())
246 layer_tree_host_->RecreateUIResources();
248 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
249 // is fixed.
250 tracked_objects::ScopedTracker tracking_profile7(
251 FROM_HERE_WITH_EXPLICIT_FUNCTION(
252 "461509 SingleThreadProxy::DoCommit7"));
253 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
255 #if DCHECK_IS_ON()
256 // In the single-threaded case, the scale and scroll deltas should never be
257 // touched on the impl layer tree.
258 scoped_ptr<ScrollAndScaleSet> scroll_info =
259 layer_tree_host_impl_->ProcessScrollDeltas();
260 DCHECK(!scroll_info->scrolls.size());
261 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
262 #endif
264 if (scheduler_on_impl_thread_)
265 scheduler_on_impl_thread_->DidCommit();
267 layer_tree_host_impl_->CommitComplete();
269 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
270 // is fixed.
271 tracked_objects::ScopedTracker tracking_profile8(
272 FROM_HERE_WITH_EXPLICIT_FUNCTION(
273 "461509 SingleThreadProxy::DoCommit8"));
274 // Commit goes directly to the active tree, but we need to synchronously
275 // "activate" the tree still during commit to satisfy any potential
276 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
277 // might not be ready to draw, so DidActivateSyncTree must set
278 // the flag to force the tree to not draw until textures are ready.
279 NotifyReadyToActivate();
283 void SingleThreadProxy::CommitComplete() {
284 // Commit complete happens on the main side after activate to satisfy any
285 // SetNextCommitWaitsForActivation calls.
286 DCHECK(!layer_tree_host_impl_->pending_tree())
287 << "Activation is expected to have synchronously occurred by now.";
288 DCHECK(commit_blocking_task_runner_);
290 DebugScopedSetMainThread main(this);
291 commit_blocking_task_runner_.reset();
292 layer_tree_host_->CommitComplete();
293 layer_tree_host_->DidBeginMainFrame();
295 next_frame_is_newly_committed_frame_ = true;
298 void SingleThreadProxy::SetNeedsCommit() {
299 DCHECK(Proxy::IsMainThread());
300 client_->ScheduleComposite();
301 if (commit_requested_)
302 return;
303 commit_requested_ = true;
304 DebugScopedSetImplThread impl(this);
305 if (scheduler_on_impl_thread_)
306 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
309 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
310 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
311 DCHECK(Proxy::IsMainThread());
312 DebugScopedSetImplThread impl(this);
313 client_->ScheduleComposite();
314 SetNeedsRedrawRectOnImplThread(damage_rect);
317 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
318 // Activation always forced in commit, so nothing to do.
319 DCHECK(Proxy::IsMainThread());
322 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
323 DCHECK(Proxy::IsMainThread());
324 // Deferring commits only makes sense if there's a scheduler.
325 if (!scheduler_on_impl_thread_)
326 return;
327 if (defer_commits_ == defer_commits)
328 return;
330 if (defer_commits)
331 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
332 else
333 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
335 defer_commits_ = defer_commits;
336 scheduler_on_impl_thread_->SetDeferCommits(defer_commits);
339 bool SingleThreadProxy::CommitRequested() const {
340 DCHECK(Proxy::IsMainThread());
341 return commit_requested_;
344 bool SingleThreadProxy::BeginMainFrameRequested() const {
345 DCHECK(Proxy::IsMainThread());
346 // If there is no scheduler, then there can be no pending begin frame,
347 // as all frames are all manually initiated by the embedder of cc.
348 if (!scheduler_on_impl_thread_)
349 return false;
350 return commit_requested_;
353 void SingleThreadProxy::Stop() {
354 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
355 DCHECK(Proxy::IsMainThread());
357 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
358 DebugScopedSetImplThread impl(this);
360 BlockingTaskRunner::CapturePostTasks blocked(
361 blocking_main_thread_task_runner());
362 scheduler_on_impl_thread_ = nullptr;
363 layer_tree_host_impl_ = nullptr;
365 layer_tree_host_ = NULL;
368 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
369 TRACE_EVENT1(
370 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
371 DCHECK(Proxy::IsImplThread());
372 if (scheduler_on_impl_thread_)
373 scheduler_on_impl_thread_->SetCanDraw(can_draw);
376 void SingleThreadProxy::NotifyReadyToActivate() {
377 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
378 DebugScopedSetImplThread impl(this);
379 if (scheduler_on_impl_thread_)
380 scheduler_on_impl_thread_->NotifyReadyToActivate();
383 void SingleThreadProxy::NotifyReadyToDraw() {
384 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToDraw");
385 DebugScopedSetImplThread impl(this);
386 if (scheduler_on_impl_thread_)
387 scheduler_on_impl_thread_->NotifyReadyToDraw();
390 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
391 client_->ScheduleComposite();
392 if (scheduler_on_impl_thread_)
393 scheduler_on_impl_thread_->SetNeedsRedraw();
396 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
397 client_->ScheduleComposite();
398 if (scheduler_on_impl_thread_)
399 scheduler_on_impl_thread_->SetNeedsAnimate();
402 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
403 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
404 if (scheduler_on_impl_thread_)
405 scheduler_on_impl_thread_->SetNeedsPrepareTiles();
408 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
409 const gfx::Rect& damage_rect) {
410 layer_tree_host_impl_->SetViewportDamage(damage_rect);
411 SetNeedsRedrawOnImplThread();
414 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
415 client_->ScheduleComposite();
416 if (scheduler_on_impl_thread_)
417 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
420 void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
421 TRACE_EVENT1("cc", "SingleThreadProxy::SetVideoNeedsBeginFrames",
422 "needs_begin_frames", needs_begin_frames);
423 // In tests the layer tree is destroyed after the scheduler is.
424 if (scheduler_on_impl_thread_)
425 scheduler_on_impl_thread_->SetVideoNeedsBeginFrames(needs_begin_frames);
428 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
429 scoped_ptr<AnimationEventsVector> events) {
430 TRACE_EVENT0(
431 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
432 DCHECK(Proxy::IsImplThread());
433 DebugScopedSetMainThread main(this);
434 layer_tree_host_->SetAnimationEvents(events.Pass());
437 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
439 void SingleThreadProxy::DidActivateSyncTree() {
440 // Synchronously call to CommitComplete. Resetting
441 // |commit_blocking_task_runner| would make sure all tasks posted during
442 // commit/activation before CommitComplete.
443 CommitComplete();
446 void SingleThreadProxy::WillPrepareTiles() {
447 DCHECK(Proxy::IsImplThread());
448 if (scheduler_on_impl_thread_)
449 scheduler_on_impl_thread_->WillPrepareTiles();
452 void SingleThreadProxy::DidPrepareTiles() {
453 DCHECK(Proxy::IsImplThread());
454 if (scheduler_on_impl_thread_)
455 scheduler_on_impl_thread_->DidPrepareTiles();
458 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
459 layer_tree_host_->DidCompletePageScaleAnimation();
462 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
463 DCHECK(IsImplThread());
464 renderer_capabilities_for_main_thread_ =
465 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
468 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
469 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
471 DebugScopedSetMainThread main(this);
472 // This must happen before we notify the scheduler as it may try to recreate
473 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
474 layer_tree_host_->DidLoseOutputSurface();
476 client_->DidAbortSwapBuffers();
477 if (scheduler_on_impl_thread_)
478 scheduler_on_impl_thread_->DidLoseOutputSurface();
481 void SingleThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
482 base::TimeDelta interval) {
483 if (scheduler_on_impl_thread_)
484 scheduler_on_impl_thread_->CommitVSyncParameters(timebase, interval);
487 void SingleThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
488 if (scheduler_on_impl_thread_)
489 scheduler_on_impl_thread_->SetEstimatedParentDrawTime(draw_time);
492 void SingleThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
493 if (scheduler_on_impl_thread_)
494 scheduler_on_impl_thread_->SetMaxSwapsPending(max);
497 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
498 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
499 if (scheduler_on_impl_thread_)
500 scheduler_on_impl_thread_->DidSwapBuffers();
501 client_->DidPostSwapBuffers();
504 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
505 TRACE_EVENT0("cc,benchmark",
506 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
507 if (scheduler_on_impl_thread_)
508 scheduler_on_impl_thread_->DidSwapBuffersComplete();
509 layer_tree_host_->DidCompleteSwapBuffers();
512 void SingleThreadProxy::OnDrawForOutputSurface() {
513 NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor.";
516 void SingleThreadProxy::PostFrameTimingEventsOnImplThread(
517 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
518 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
519 layer_tree_host_->RecordFrameTimingEvents(composite_events.Pass(),
520 main_frame_events.Pass());
523 void SingleThreadProxy::LayoutAndUpdateLayers() {
524 if (layer_tree_host_->output_surface_lost()) {
525 RequestNewOutputSurface();
526 // RequestNewOutputSurface could have synchronously created an output
527 // surface, so check again before returning.
528 if (layer_tree_host_->output_surface_lost())
529 return;
532 layer_tree_host_->Layout();
533 layer_tree_host_->UpdateLayers();
536 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
537 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
538 DCHECK(Proxy::IsMainThread());
539 #if DCHECK_IS_ON()
540 DCHECK(!inside_impl_frame_);
541 #endif
542 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
544 if (layer_tree_host_->output_surface_lost()) {
545 RequestNewOutputSurface();
546 // RequestNewOutputSurface could have synchronously created an output
547 // surface, so check again before returning.
548 if (layer_tree_host_->output_surface_lost())
549 return;
552 BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
553 BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(),
554 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL));
556 // Start the impl frame.
558 DebugScopedSetImplThread impl(this);
559 WillBeginImplFrame(begin_frame_args);
562 // Run the "main thread" and get it to commit.
564 #if DCHECK_IS_ON()
565 DCHECK(inside_impl_frame_);
566 #endif
567 DoBeginMainFrame(begin_frame_args);
568 DoCommit();
570 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
571 << "Commit should always succeed and transfer promises.";
574 // Finish the impl frame.
576 DebugScopedSetImplThread impl(this);
577 layer_tree_host_impl_->ActivateSyncTree();
578 DCHECK(
579 !layer_tree_host_impl_->active_tree()->needs_update_draw_properties());
580 layer_tree_host_impl_->PrepareTiles();
581 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
583 // TODO(danakj): Don't do this last... we prepared the wrong things. D:
584 layer_tree_host_impl_->Animate();
586 LayerTreeHostImpl::FrameData frame;
587 DoComposite(&frame);
589 // DoComposite could abort, but because this is a synchronous composite
590 // another draw will never be scheduled, so break remaining promises.
591 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
592 SwapPromise::SWAP_FAILS);
594 DidFinishImplFrame();
598 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
600 DebugScopedSetImplThread impl(this);
601 if (layer_tree_host_impl_->renderer()) {
602 DCHECK(!layer_tree_host_->output_surface_lost());
603 layer_tree_host_impl_->renderer()->DoNoOp();
608 bool SingleThreadProxy::SupportsImplScrolling() const {
609 return false;
612 bool SingleThreadProxy::ShouldComposite() const {
613 DCHECK(Proxy::IsImplThread());
614 return layer_tree_host_impl_->visible() &&
615 layer_tree_host_impl_->CanDraw();
618 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
619 if (output_surface_creation_callback_.IsCancelled() &&
620 !output_surface_creation_requested_) {
621 output_surface_creation_callback_.Reset(
622 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
623 weak_factory_.GetWeakPtr()));
624 MainThreadTaskRunner()->PostTask(
625 FROM_HERE, output_surface_creation_callback_.callback());
629 DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) {
630 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
631 DCHECK(!layer_tree_host_->output_surface_lost());
633 DrawResult draw_result;
634 bool draw_frame;
636 DebugScopedSetImplThread impl(this);
637 base::AutoReset<bool> mark_inside(&inside_draw_, true);
639 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
640 // is fixed.
641 tracked_objects::ScopedTracker tracking_profile1(
642 FROM_HERE_WITH_EXPLICIT_FUNCTION(
643 "461509 SingleThreadProxy::DoComposite1"));
645 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
646 // frame, so can only be used when such a frame is possible. Since
647 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
648 // CanDraw() as well.
649 if (!ShouldComposite()) {
650 return DRAW_ABORTED_CANT_DRAW;
653 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
654 // is fixed.
655 tracked_objects::ScopedTracker tracking_profile2(
656 FROM_HERE_WITH_EXPLICIT_FUNCTION(
657 "461509 SingleThreadProxy::DoComposite2"));
658 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
659 draw_frame = draw_result == DRAW_SUCCESS;
660 if (draw_frame) {
661 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
662 // is fixed.
663 tracked_objects::ScopedTracker tracking_profile3(
664 FROM_HERE_WITH_EXPLICIT_FUNCTION(
665 "461509 SingleThreadProxy::DoComposite3"));
666 layer_tree_host_impl_->DrawLayers(frame);
668 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
669 // is fixed.
670 tracked_objects::ScopedTracker tracking_profile4(
671 FROM_HERE_WITH_EXPLICIT_FUNCTION(
672 "461509 SingleThreadProxy::DoComposite4"));
673 layer_tree_host_impl_->DidDrawAllLayers(*frame);
675 bool start_ready_animations = draw_frame;
676 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
677 // is fixed.
678 tracked_objects::ScopedTracker tracking_profile5(
679 FROM_HERE_WITH_EXPLICIT_FUNCTION(
680 "461509 SingleThreadProxy::DoComposite5"));
681 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
683 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
684 // is fixed.
685 tracked_objects::ScopedTracker tracking_profile7(
686 FROM_HERE_WITH_EXPLICIT_FUNCTION(
687 "461509 SingleThreadProxy::DoComposite7"));
690 if (draw_frame) {
691 DebugScopedSetImplThread impl(this);
693 // This CapturePostTasks should be destroyed before
694 // DidCommitAndDrawFrame() is called since that goes out to the
695 // embedder,
696 // and we want the embedder to receive its callbacks before that.
697 // NOTE: This maintains consistent ordering with the ThreadProxy since
698 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
699 // there as the main thread is not blocked, so any posted tasks inside
700 // the swap buffers will execute first.
701 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
703 BlockingTaskRunner::CapturePostTasks blocked(
704 blocking_main_thread_task_runner());
705 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
706 // is fixed.
707 tracked_objects::ScopedTracker tracking_profile8(
708 FROM_HERE_WITH_EXPLICIT_FUNCTION(
709 "461509 SingleThreadProxy::DoComposite8"));
710 layer_tree_host_impl_->SwapBuffers(*frame);
712 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
713 // fixed.
714 tracked_objects::ScopedTracker tracking_profile9(
715 FROM_HERE_WITH_EXPLICIT_FUNCTION(
716 "461509 SingleThreadProxy::DoComposite9"));
717 DidCommitAndDrawFrame();
719 return draw_result;
722 void SingleThreadProxy::DidCommitAndDrawFrame() {
723 if (next_frame_is_newly_committed_frame_) {
724 DebugScopedSetMainThread main(this);
725 next_frame_is_newly_committed_frame_ = false;
726 layer_tree_host_->DidCommitAndDrawFrame();
730 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
731 if (layer_tree_host_->output_surface_lost())
732 return false;
733 if (!scheduler_on_impl_thread_)
734 return false;
735 return scheduler_on_impl_thread_->MainFrameForTestingWillHappen();
738 void SingleThreadProxy::SetChildrenNeedBeginFrames(
739 bool children_need_begin_frames) {
740 scheduler_on_impl_thread_->SetChildrenNeedBeginFrames(
741 children_need_begin_frames);
744 void SingleThreadProxy::SetAuthoritativeVSyncInterval(
745 const base::TimeDelta& interval) {
746 scheduler_on_impl_thread_->SetAuthoritativeVSyncInterval(interval);
749 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
750 #if DCHECK_IS_ON()
751 DCHECK(!inside_impl_frame_)
752 << "WillBeginImplFrame called while already inside an impl frame!";
753 inside_impl_frame_ = true;
754 #endif
755 layer_tree_host_impl_->WillBeginImplFrame(args);
758 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
759 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
760 // Although this proxy is single-threaded, it's problematic to synchronously
761 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
762 // could cause a commit to occur in between a series of SetNeedsCommit calls
763 // (i.e. property modifications) causing some to fall on one frame and some to
764 // fall on the next. Doing it asynchronously instead matches the semantics of
765 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
766 // synchronous commit.
767 #if DCHECK_IS_ON()
768 DCHECK(inside_impl_frame_)
769 << "BeginMainFrame should only be sent inside a BeginImplFrame";
770 #endif
771 const BeginFrameArgs& begin_frame_args =
772 layer_tree_host_impl_->CurrentBeginFrameArgs();
774 MainThreadTaskRunner()->PostTask(
775 FROM_HERE, base::Bind(&SingleThreadProxy::BeginMainFrame,
776 weak_factory_.GetWeakPtr(), begin_frame_args));
779 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() {
780 layer_tree_host_->BeginMainFrameNotExpectedSoon();
783 void SingleThreadProxy::BeginMainFrame(const BeginFrameArgs& begin_frame_args) {
784 commit_requested_ = false;
785 animate_requested_ = false;
787 if (defer_commits_) {
788 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
789 TRACE_EVENT_SCOPE_THREAD);
790 BeginMainFrameAbortedOnImplThread(
791 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
792 return;
795 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
796 // commit.
797 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
799 if (!layer_tree_host_->visible()) {
800 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
801 BeginMainFrameAbortedOnImplThread(
802 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
803 return;
806 if (layer_tree_host_->output_surface_lost()) {
807 TRACE_EVENT_INSTANT0(
808 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
809 BeginMainFrameAbortedOnImplThread(
810 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
811 return;
814 // Prevent new commits from being requested inside DoBeginMainFrame.
815 // Note: We do not want to prevent SetNeedsAnimate from requesting
816 // a commit here.
817 commit_requested_ = true;
819 DoBeginMainFrame(begin_frame_args);
822 void SingleThreadProxy::DoBeginMainFrame(
823 const BeginFrameArgs& begin_frame_args) {
824 layer_tree_host_->WillBeginMainFrame();
825 layer_tree_host_->BeginMainFrame(begin_frame_args);
826 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
827 layer_tree_host_->Layout();
829 // New commits requested inside UpdateLayers should be respected.
830 commit_requested_ = false;
832 layer_tree_host_->UpdateLayers();
834 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
835 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
836 // thread_proxy.cc
837 if (scheduler_on_impl_thread_) {
838 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
839 scheduler_on_impl_thread_->NotifyReadyToCommit();
843 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
844 CommitEarlyOutReason reason) {
845 DebugScopedSetImplThread impl(this);
846 DCHECK(scheduler_on_impl_thread_->CommitPending());
847 DCHECK(!layer_tree_host_impl_->pending_tree());
849 layer_tree_host_impl_->BeginMainFrameAborted(reason);
850 scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
853 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
854 DebugScopedSetImplThread impl(this);
855 LayerTreeHostImpl::FrameData frame;
856 return DoComposite(&frame);
859 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
860 NOTREACHED();
861 return INVALID_RESULT;
864 void SingleThreadProxy::ScheduledActionCommit() {
865 DebugScopedSetMainThread main(this);
866 DoCommit();
869 void SingleThreadProxy::ScheduledActionAnimate() {
870 TRACE_EVENT0("cc", "ScheduledActionAnimate");
871 DebugScopedSetImplThread impl(this);
872 layer_tree_host_impl_->Animate();
875 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
876 DebugScopedSetImplThread impl(this);
877 layer_tree_host_impl_->ActivateSyncTree();
880 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
881 DebugScopedSetMainThread main(this);
882 DCHECK(scheduler_on_impl_thread_);
883 // If possible, create the output surface in a post task. Synchronously
884 // creating the output surface makes tests more awkward since this differs
885 // from the ThreadProxy behavior. However, sometimes there is no
886 // task runner.
887 if (Proxy::MainThreadTaskRunner()) {
888 ScheduleRequestNewOutputSurface();
889 } else {
890 RequestNewOutputSurface();
894 void SingleThreadProxy::ScheduledActionPrepareTiles() {
895 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
896 DebugScopedSetImplThread impl(this);
897 layer_tree_host_impl_->PrepareTiles();
900 void SingleThreadProxy::ScheduledActionInvalidateOutputSurface() {
901 NOTREACHED();
904 void SingleThreadProxy::DidFinishImplFrame() {
905 layer_tree_host_impl_->DidFinishImplFrame();
906 #if DCHECK_IS_ON()
907 DCHECK(inside_impl_frame_)
908 << "DidFinishImplFrame called while not inside an impl frame!";
909 inside_impl_frame_ = false;
910 #endif
913 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
914 layer_tree_host_->SendBeginFramesToChildren(args);
917 } // namespace cc