Preserve viewport scrolling layer when a fling starts
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blobb6d120b48053a54c3cfbf34b9646b6db407968f8
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 layer_tree_host->rendering_stats_instrumentation()));
71 scheduler_on_impl_thread_ = Scheduler::Create(
72 this, scheduler_settings, layer_tree_host_->id(),
73 MainThreadTaskRunner(), external_begin_frame_source_.get(),
74 compositor_timing_history.Pass());
78 void SingleThreadProxy::Start() {
79 DebugScopedSetImplThread impl(this);
80 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
83 SingleThreadProxy::~SingleThreadProxy() {
84 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
85 DCHECK(Proxy::IsMainThread());
86 // Make sure Stop() got called or never Started.
87 DCHECK(!layer_tree_host_impl_);
90 void SingleThreadProxy::FinishAllRendering() {
91 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
92 DCHECK(Proxy::IsMainThread());
94 DebugScopedSetImplThread impl(this);
95 layer_tree_host_impl_->FinishAllRendering();
99 bool SingleThreadProxy::IsStarted() const {
100 DCHECK(Proxy::IsMainThread());
101 return layer_tree_host_impl_;
104 bool SingleThreadProxy::CommitToActiveTree() const {
105 // With SingleThreadProxy we skip the pending tree and commit directly to the
106 // active tree.
107 return true;
110 void SingleThreadProxy::SetLayerTreeHostClientReady() {
111 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
112 // Scheduling is controlled by the embedder in the single thread case, so
113 // nothing to do.
114 DCHECK(Proxy::IsMainThread());
115 DebugScopedSetImplThread impl(this);
116 if (scheduler_on_impl_thread_) {
117 scheduler_on_impl_thread_->SetCanStart();
118 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
122 void SingleThreadProxy::SetVisible(bool visible) {
123 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
124 DebugScopedSetImplThread impl(this);
125 layer_tree_host_impl_->SetVisible(visible);
126 if (scheduler_on_impl_thread_)
127 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
128 // Changing visibility could change ShouldComposite().
131 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) {
132 TRACE_EVENT1("cc", "SingleThreadProxy::SetThrottleFrameProduction",
133 "throttle", throttle);
134 DebugScopedSetImplThread impl(this);
135 if (scheduler_on_impl_thread_)
136 scheduler_on_impl_thread_->SetThrottleFrameProduction(throttle);
139 void SingleThreadProxy::RequestNewOutputSurface() {
140 DCHECK(Proxy::IsMainThread());
141 DCHECK(layer_tree_host_->output_surface_lost());
142 output_surface_creation_callback_.Cancel();
143 if (output_surface_creation_requested_)
144 return;
145 output_surface_creation_requested_ = true;
146 layer_tree_host_->RequestNewOutputSurface();
149 void SingleThreadProxy::SetOutputSurface(
150 scoped_ptr<OutputSurface> output_surface) {
151 DCHECK(Proxy::IsMainThread());
152 DCHECK(layer_tree_host_->output_surface_lost());
153 DCHECK(output_surface_creation_requested_);
154 renderer_capabilities_for_main_thread_ = RendererCapabilities();
156 bool success;
158 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
159 DebugScopedSetImplThread impl(this);
160 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
163 if (success) {
164 layer_tree_host_->DidInitializeOutputSurface();
165 if (scheduler_on_impl_thread_)
166 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
167 else if (!inside_synchronous_composite_)
168 SetNeedsCommit();
169 output_surface_creation_requested_ = false;
170 } else {
171 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface,
172 // and so output_surface_creation_requested remains true.
173 layer_tree_host_->DidFailToInitializeOutputSurface();
177 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
178 DCHECK(Proxy::IsMainThread());
179 DCHECK(!layer_tree_host_->output_surface_lost());
180 return renderer_capabilities_for_main_thread_;
183 void SingleThreadProxy::SetNeedsAnimate() {
184 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
185 DCHECK(Proxy::IsMainThread());
186 client_->ScheduleAnimation();
187 if (animate_requested_)
188 return;
189 animate_requested_ = true;
190 DebugScopedSetImplThread impl(this);
191 if (scheduler_on_impl_thread_)
192 scheduler_on_impl_thread_->SetNeedsCommit();
195 void SingleThreadProxy::SetNeedsUpdateLayers() {
196 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
197 DCHECK(Proxy::IsMainThread());
198 SetNeedsCommit();
201 void SingleThreadProxy::DoAnimate() {
202 // Don't animate if there is no root layer.
203 // TODO(mithro): Both Animate and UpdateAnimationState already have a
204 // "!active_tree_->root_layer()" check?
205 if (!layer_tree_host_impl_->active_tree()->root_layer()) {
206 return;
209 layer_tree_host_impl_->Animate(
210 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
212 // If animations are not visible, update the animation state now as it
213 // won't happen in DoComposite.
214 if (!layer_tree_host_impl_->AnimationsAreVisible()) {
215 layer_tree_host_impl_->UpdateAnimationState(true);
219 void SingleThreadProxy::DoCommit() {
220 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
221 DCHECK(Proxy::IsMainThread());
223 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
224 // fixed.
225 tracked_objects::ScopedTracker tracking_profile1(
226 FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1"));
227 layer_tree_host_->WillCommit();
228 devtools_instrumentation::ScopedCommitTrace commit_task(
229 layer_tree_host_->id());
231 // Commit immediately.
233 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
234 // is fixed.
235 tracked_objects::ScopedTracker tracking_profile2(
236 FROM_HERE_WITH_EXPLICIT_FUNCTION(
237 "461509 SingleThreadProxy::DoCommit2"));
238 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
239 DebugScopedSetImplThread impl(this);
241 // This CapturePostTasks should be destroyed before CommitComplete() is
242 // called since that goes out to the embedder, and we want the embedder
243 // to receive its callbacks before that.
244 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks(
245 blocking_main_thread_task_runner()));
247 layer_tree_host_impl_->BeginCommit();
248 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
250 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
251 // is fixed.
252 tracked_objects::ScopedTracker tracking_profile6(
253 FROM_HERE_WITH_EXPLICIT_FUNCTION(
254 "461509 SingleThreadProxy::DoCommit6"));
255 if (layer_tree_host_impl_->EvictedUIResourcesExist())
256 layer_tree_host_->RecreateUIResources();
258 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
259 // is fixed.
260 tracked_objects::ScopedTracker tracking_profile7(
261 FROM_HERE_WITH_EXPLICIT_FUNCTION(
262 "461509 SingleThreadProxy::DoCommit7"));
263 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
265 #if DCHECK_IS_ON()
266 // In the single-threaded case, the scale and scroll deltas should never be
267 // touched on the impl layer tree.
268 scoped_ptr<ScrollAndScaleSet> scroll_info =
269 layer_tree_host_impl_->ProcessScrollDeltas();
270 DCHECK(!scroll_info->scrolls.size());
271 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
272 #endif
274 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
275 // is fixed.
276 tracked_objects::ScopedTracker tracking_profile8(
277 FROM_HERE_WITH_EXPLICIT_FUNCTION(
278 "461509 SingleThreadProxy::DoCommit8"));
279 // Commit goes directly to the active tree, but we need to synchronously
280 // "activate" the tree still during commit to satisfy any potential
281 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
282 // might not be ready to draw, so DidActivateSyncTree must set
283 // the flag to force the tree to not draw until textures are ready.
284 NotifyReadyToActivate();
288 void SingleThreadProxy::CommitComplete() {
289 DCHECK(!layer_tree_host_impl_->pending_tree())
290 << "Activation is expected to have synchronously occurred by now.";
291 DCHECK(commit_blocking_task_runner_);
293 if (scheduler_on_impl_thread_)
294 scheduler_on_impl_thread_->DidCommit();
296 // Notify commit complete on the impl side after activate to satisfy any
297 // SetNextCommitWaitsForActivation calls.
298 layer_tree_host_impl_->CommitComplete();
300 DebugScopedSetMainThread main(this);
301 commit_blocking_task_runner_.reset();
302 layer_tree_host_->CommitComplete();
303 layer_tree_host_->DidBeginMainFrame();
305 next_frame_is_newly_committed_frame_ = true;
308 void SingleThreadProxy::SetNeedsCommit() {
309 DCHECK(Proxy::IsMainThread());
310 client_->ScheduleComposite();
311 if (commit_requested_)
312 return;
313 commit_requested_ = true;
314 DebugScopedSetImplThread impl(this);
315 if (scheduler_on_impl_thread_)
316 scheduler_on_impl_thread_->SetNeedsCommit();
319 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
320 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
321 DCHECK(Proxy::IsMainThread());
322 DebugScopedSetImplThread impl(this);
323 client_->ScheduleComposite();
324 SetNeedsRedrawRectOnImplThread(damage_rect);
327 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
328 // Activation always forced in commit, so nothing to do.
329 DCHECK(Proxy::IsMainThread());
332 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
333 DCHECK(Proxy::IsMainThread());
334 // Deferring commits only makes sense if there's a scheduler.
335 if (!scheduler_on_impl_thread_)
336 return;
337 if (defer_commits_ == defer_commits)
338 return;
340 if (defer_commits)
341 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
342 else
343 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
345 defer_commits_ = defer_commits;
346 scheduler_on_impl_thread_->SetDeferCommits(defer_commits);
349 bool SingleThreadProxy::CommitRequested() const {
350 DCHECK(Proxy::IsMainThread());
351 return commit_requested_;
354 bool SingleThreadProxy::BeginMainFrameRequested() const {
355 DCHECK(Proxy::IsMainThread());
356 // If there is no scheduler, then there can be no pending begin frame,
357 // as all frames are all manually initiated by the embedder of cc.
358 if (!scheduler_on_impl_thread_)
359 return false;
360 return commit_requested_;
363 void SingleThreadProxy::Stop() {
364 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
365 DCHECK(Proxy::IsMainThread());
367 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
368 DebugScopedSetImplThread impl(this);
370 BlockingTaskRunner::CapturePostTasks blocked(
371 blocking_main_thread_task_runner());
372 scheduler_on_impl_thread_ = nullptr;
373 layer_tree_host_impl_ = nullptr;
375 layer_tree_host_ = NULL;
378 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
379 TRACE_EVENT1(
380 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
381 DCHECK(Proxy::IsImplThread());
382 if (scheduler_on_impl_thread_)
383 scheduler_on_impl_thread_->SetCanDraw(can_draw);
386 void SingleThreadProxy::NotifyReadyToActivate() {
387 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
388 DebugScopedSetImplThread impl(this);
389 if (scheduler_on_impl_thread_)
390 scheduler_on_impl_thread_->NotifyReadyToActivate();
393 void SingleThreadProxy::NotifyReadyToDraw() {
394 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToDraw");
395 DebugScopedSetImplThread impl(this);
396 if (scheduler_on_impl_thread_)
397 scheduler_on_impl_thread_->NotifyReadyToDraw();
400 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
401 client_->ScheduleComposite();
402 if (scheduler_on_impl_thread_)
403 scheduler_on_impl_thread_->SetNeedsRedraw();
406 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
407 client_->ScheduleComposite();
408 if (scheduler_on_impl_thread_)
409 scheduler_on_impl_thread_->SetNeedsAnimate();
412 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
413 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
414 if (scheduler_on_impl_thread_)
415 scheduler_on_impl_thread_->SetNeedsPrepareTiles();
418 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
419 const gfx::Rect& damage_rect) {
420 layer_tree_host_impl_->SetViewportDamage(damage_rect);
421 SetNeedsRedrawOnImplThread();
424 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
425 client_->ScheduleComposite();
426 if (scheduler_on_impl_thread_)
427 scheduler_on_impl_thread_->SetNeedsCommit();
430 void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
431 TRACE_EVENT1("cc", "SingleThreadProxy::SetVideoNeedsBeginFrames",
432 "needs_begin_frames", needs_begin_frames);
433 // In tests the layer tree is destroyed after the scheduler is.
434 if (scheduler_on_impl_thread_)
435 scheduler_on_impl_thread_->SetVideoNeedsBeginFrames(needs_begin_frames);
438 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
439 scoped_ptr<AnimationEventsVector> events) {
440 TRACE_EVENT0(
441 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
442 DCHECK(Proxy::IsImplThread());
443 DebugScopedSetMainThread main(this);
444 layer_tree_host_->SetAnimationEvents(events.Pass());
447 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
449 void SingleThreadProxy::DidActivateSyncTree() {
450 // This is required because NotifyReadyToActivate gets called immediately
451 // after commit since single thread commits directly to the active tree.
452 if (scheduler_on_impl_thread_)
453 scheduler_on_impl_thread_->SetWaitForReadyToDraw();
455 // Synchronously call to CommitComplete. Resetting
456 // |commit_blocking_task_runner| would make sure all tasks posted during
457 // commit/activation before CommitComplete.
458 CommitComplete();
461 void SingleThreadProxy::WillPrepareTiles() {
462 DCHECK(Proxy::IsImplThread());
463 if (scheduler_on_impl_thread_)
464 scheduler_on_impl_thread_->WillPrepareTiles();
467 void SingleThreadProxy::DidPrepareTiles() {
468 DCHECK(Proxy::IsImplThread());
469 if (scheduler_on_impl_thread_)
470 scheduler_on_impl_thread_->DidPrepareTiles();
473 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
474 layer_tree_host_->DidCompletePageScaleAnimation();
477 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
478 DCHECK(IsImplThread());
479 renderer_capabilities_for_main_thread_ =
480 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
483 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
484 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
486 DebugScopedSetMainThread main(this);
487 // This must happen before we notify the scheduler as it may try to recreate
488 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
489 layer_tree_host_->DidLoseOutputSurface();
491 client_->DidAbortSwapBuffers();
492 if (scheduler_on_impl_thread_)
493 scheduler_on_impl_thread_->DidLoseOutputSurface();
496 void SingleThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
497 base::TimeDelta interval) {
498 if (scheduler_on_impl_thread_)
499 scheduler_on_impl_thread_->CommitVSyncParameters(timebase, interval);
502 void SingleThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
503 if (scheduler_on_impl_thread_)
504 scheduler_on_impl_thread_->SetEstimatedParentDrawTime(draw_time);
507 void SingleThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
508 if (scheduler_on_impl_thread_)
509 scheduler_on_impl_thread_->SetMaxSwapsPending(max);
512 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
513 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
514 if (scheduler_on_impl_thread_)
515 scheduler_on_impl_thread_->DidSwapBuffers();
516 client_->DidPostSwapBuffers();
519 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
520 TRACE_EVENT0("cc,benchmark",
521 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
522 if (scheduler_on_impl_thread_)
523 scheduler_on_impl_thread_->DidSwapBuffersComplete();
524 layer_tree_host_->DidCompleteSwapBuffers();
527 void SingleThreadProxy::OnDrawForOutputSurface() {
528 NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor.";
531 void SingleThreadProxy::PostFrameTimingEventsOnImplThread(
532 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
533 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
534 layer_tree_host_->RecordFrameTimingEvents(composite_events.Pass(),
535 main_frame_events.Pass());
538 void SingleThreadProxy::LayoutAndUpdateLayers() {
539 if (layer_tree_host_->output_surface_lost()) {
540 RequestNewOutputSurface();
541 // RequestNewOutputSurface could have synchronously created an output
542 // surface, so check again before returning.
543 if (layer_tree_host_->output_surface_lost())
544 return;
547 layer_tree_host_->Layout();
548 layer_tree_host_->UpdateLayers();
551 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
552 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
553 DCHECK(Proxy::IsMainThread());
554 #if DCHECK_IS_ON()
555 DCHECK(!inside_impl_frame_);
556 #endif
557 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
559 if (layer_tree_host_->output_surface_lost()) {
560 RequestNewOutputSurface();
561 // RequestNewOutputSurface could have synchronously created an output
562 // surface, so check again before returning.
563 if (layer_tree_host_->output_surface_lost())
564 return;
567 BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
568 BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(),
569 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL));
571 // Start the impl frame.
573 DebugScopedSetImplThread impl(this);
574 WillBeginImplFrame(begin_frame_args);
577 // Run the "main thread" and get it to commit.
579 #if DCHECK_IS_ON()
580 DCHECK(inside_impl_frame_);
581 #endif
582 DoBeginMainFrame(begin_frame_args);
583 DoCommit();
585 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
586 << "Commit should always succeed and transfer promises.";
589 // Finish the impl frame.
591 DebugScopedSetImplThread impl(this);
592 layer_tree_host_impl_->ActivateSyncTree();
593 DCHECK(
594 !layer_tree_host_impl_->active_tree()->needs_update_draw_properties());
595 layer_tree_host_impl_->PrepareTiles();
596 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
598 DoAnimate();
600 LayerTreeHostImpl::FrameData frame;
601 DoComposite(&frame);
603 // DoComposite could abort, but because this is a synchronous composite
604 // another draw will never be scheduled, so break remaining promises.
605 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
606 SwapPromise::SWAP_FAILS);
608 DidFinishImplFrame();
612 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
614 DebugScopedSetImplThread impl(this);
615 if (layer_tree_host_impl_->renderer()) {
616 DCHECK(!layer_tree_host_->output_surface_lost());
617 layer_tree_host_impl_->renderer()->DoNoOp();
622 bool SingleThreadProxy::SupportsImplScrolling() const {
623 return false;
626 bool SingleThreadProxy::ShouldComposite() const {
627 DCHECK(Proxy::IsImplThread());
628 return layer_tree_host_impl_->visible() &&
629 layer_tree_host_impl_->CanDraw();
632 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
633 if (output_surface_creation_callback_.IsCancelled() &&
634 !output_surface_creation_requested_) {
635 output_surface_creation_callback_.Reset(
636 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
637 weak_factory_.GetWeakPtr()));
638 MainThreadTaskRunner()->PostTask(
639 FROM_HERE, output_surface_creation_callback_.callback());
643 DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) {
644 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
645 DCHECK(!layer_tree_host_->output_surface_lost());
647 DrawResult draw_result;
648 bool draw_frame;
650 DebugScopedSetImplThread impl(this);
651 base::AutoReset<bool> mark_inside(&inside_draw_, true);
653 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
654 // is fixed.
655 tracked_objects::ScopedTracker tracking_profile1(
656 FROM_HERE_WITH_EXPLICIT_FUNCTION(
657 "461509 SingleThreadProxy::DoComposite1"));
659 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
660 // frame, so can only be used when such a frame is possible. Since
661 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
662 // CanDraw() as well.
663 if (!ShouldComposite()) {
664 return DRAW_ABORTED_CANT_DRAW;
667 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
668 // is fixed.
669 tracked_objects::ScopedTracker tracking_profile2(
670 FROM_HERE_WITH_EXPLICIT_FUNCTION(
671 "461509 SingleThreadProxy::DoComposite2"));
672 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
673 draw_frame = draw_result == DRAW_SUCCESS;
674 if (draw_frame) {
675 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
676 // is fixed.
677 tracked_objects::ScopedTracker tracking_profile3(
678 FROM_HERE_WITH_EXPLICIT_FUNCTION(
679 "461509 SingleThreadProxy::DoComposite3"));
680 layer_tree_host_impl_->DrawLayers(frame);
682 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
683 // is fixed.
684 tracked_objects::ScopedTracker tracking_profile4(
685 FROM_HERE_WITH_EXPLICIT_FUNCTION(
686 "461509 SingleThreadProxy::DoComposite4"));
687 layer_tree_host_impl_->DidDrawAllLayers(*frame);
689 bool start_ready_animations = draw_frame;
690 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
691 // is fixed.
692 tracked_objects::ScopedTracker tracking_profile5(
693 FROM_HERE_WITH_EXPLICIT_FUNCTION(
694 "461509 SingleThreadProxy::DoComposite5"));
695 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
697 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
698 // is fixed.
699 tracked_objects::ScopedTracker tracking_profile7(
700 FROM_HERE_WITH_EXPLICIT_FUNCTION(
701 "461509 SingleThreadProxy::DoComposite7"));
704 if (draw_frame) {
705 DebugScopedSetImplThread impl(this);
707 // This CapturePostTasks should be destroyed before
708 // DidCommitAndDrawFrame() is called since that goes out to the
709 // embedder,
710 // and we want the embedder to receive its callbacks before that.
711 // NOTE: This maintains consistent ordering with the ThreadProxy since
712 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
713 // there as the main thread is not blocked, so any posted tasks inside
714 // the swap buffers will execute first.
715 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
717 BlockingTaskRunner::CapturePostTasks blocked(
718 blocking_main_thread_task_runner());
719 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
720 // is fixed.
721 tracked_objects::ScopedTracker tracking_profile8(
722 FROM_HERE_WITH_EXPLICIT_FUNCTION(
723 "461509 SingleThreadProxy::DoComposite8"));
724 layer_tree_host_impl_->SwapBuffers(*frame);
726 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
727 // fixed.
728 tracked_objects::ScopedTracker tracking_profile9(
729 FROM_HERE_WITH_EXPLICIT_FUNCTION(
730 "461509 SingleThreadProxy::DoComposite9"));
731 DidCommitAndDrawFrame();
733 return draw_result;
736 void SingleThreadProxy::DidCommitAndDrawFrame() {
737 if (next_frame_is_newly_committed_frame_) {
738 DebugScopedSetMainThread main(this);
739 next_frame_is_newly_committed_frame_ = false;
740 layer_tree_host_->DidCommitAndDrawFrame();
744 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
745 if (layer_tree_host_->output_surface_lost())
746 return false;
747 if (!scheduler_on_impl_thread_)
748 return false;
749 return scheduler_on_impl_thread_->MainFrameForTestingWillHappen();
752 void SingleThreadProxy::SetChildrenNeedBeginFrames(
753 bool children_need_begin_frames) {
754 scheduler_on_impl_thread_->SetChildrenNeedBeginFrames(
755 children_need_begin_frames);
758 void SingleThreadProxy::SetAuthoritativeVSyncInterval(
759 const base::TimeDelta& interval) {
760 scheduler_on_impl_thread_->SetAuthoritativeVSyncInterval(interval);
763 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
764 #if DCHECK_IS_ON()
765 DCHECK(!inside_impl_frame_)
766 << "WillBeginImplFrame called while already inside an impl frame!";
767 inside_impl_frame_ = true;
768 #endif
769 layer_tree_host_impl_->WillBeginImplFrame(args);
772 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
773 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
774 // Although this proxy is single-threaded, it's problematic to synchronously
775 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
776 // could cause a commit to occur in between a series of SetNeedsCommit calls
777 // (i.e. property modifications) causing some to fall on one frame and some to
778 // fall on the next. Doing it asynchronously instead matches the semantics of
779 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
780 // synchronous commit.
781 #if DCHECK_IS_ON()
782 DCHECK(inside_impl_frame_)
783 << "BeginMainFrame should only be sent inside a BeginImplFrame";
784 #endif
785 const BeginFrameArgs& begin_frame_args =
786 layer_tree_host_impl_->CurrentBeginFrameArgs();
788 MainThreadTaskRunner()->PostTask(
789 FROM_HERE, base::Bind(&SingleThreadProxy::BeginMainFrame,
790 weak_factory_.GetWeakPtr(), begin_frame_args));
793 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() {
794 layer_tree_host_->BeginMainFrameNotExpectedSoon();
797 void SingleThreadProxy::BeginMainFrame(const BeginFrameArgs& begin_frame_args) {
798 commit_requested_ = false;
799 animate_requested_ = false;
801 if (defer_commits_) {
802 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
803 TRACE_EVENT_SCOPE_THREAD);
804 BeginMainFrameAbortedOnImplThread(
805 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
806 return;
809 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
810 // commit.
811 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
813 if (!layer_tree_host_->visible()) {
814 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
815 BeginMainFrameAbortedOnImplThread(
816 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
817 return;
820 if (layer_tree_host_->output_surface_lost()) {
821 TRACE_EVENT_INSTANT0(
822 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
823 BeginMainFrameAbortedOnImplThread(
824 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
825 return;
828 // Prevent new commits from being requested inside DoBeginMainFrame.
829 // Note: We do not want to prevent SetNeedsAnimate from requesting
830 // a commit here.
831 commit_requested_ = true;
833 DoBeginMainFrame(begin_frame_args);
836 void SingleThreadProxy::DoBeginMainFrame(
837 const BeginFrameArgs& begin_frame_args) {
838 layer_tree_host_->WillBeginMainFrame();
839 layer_tree_host_->BeginMainFrame(begin_frame_args);
840 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
841 layer_tree_host_->Layout();
843 // New commits requested inside UpdateLayers should be respected.
844 commit_requested_ = false;
846 layer_tree_host_->UpdateLayers();
848 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
849 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
850 // thread_proxy.cc
851 if (scheduler_on_impl_thread_) {
852 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
853 scheduler_on_impl_thread_->NotifyReadyToCommit();
857 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
858 CommitEarlyOutReason reason) {
859 DebugScopedSetImplThread impl(this);
860 DCHECK(scheduler_on_impl_thread_->CommitPending());
861 DCHECK(!layer_tree_host_impl_->pending_tree());
863 layer_tree_host_impl_->BeginMainFrameAborted(reason);
864 scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
867 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
868 DebugScopedSetImplThread impl(this);
869 LayerTreeHostImpl::FrameData frame;
870 return DoComposite(&frame);
873 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
874 NOTREACHED();
875 return INVALID_RESULT;
878 void SingleThreadProxy::ScheduledActionCommit() {
879 DebugScopedSetMainThread main(this);
880 DoCommit();
883 void SingleThreadProxy::ScheduledActionAnimate() {
884 TRACE_EVENT0("cc", "ScheduledActionAnimate");
885 DebugScopedSetImplThread impl(this);
886 DoAnimate();
889 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
890 DebugScopedSetImplThread impl(this);
891 layer_tree_host_impl_->ActivateSyncTree();
894 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
895 DebugScopedSetMainThread main(this);
896 DCHECK(scheduler_on_impl_thread_);
897 // If possible, create the output surface in a post task. Synchronously
898 // creating the output surface makes tests more awkward since this differs
899 // from the ThreadProxy behavior. However, sometimes there is no
900 // task runner.
901 if (Proxy::MainThreadTaskRunner()) {
902 ScheduleRequestNewOutputSurface();
903 } else {
904 RequestNewOutputSurface();
908 void SingleThreadProxy::ScheduledActionPrepareTiles() {
909 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
910 DebugScopedSetImplThread impl(this);
911 layer_tree_host_impl_->PrepareTiles();
914 void SingleThreadProxy::ScheduledActionInvalidateOutputSurface() {
915 NOTREACHED();
918 void SingleThreadProxy::DidFinishImplFrame() {
919 layer_tree_host_impl_->DidFinishImplFrame();
920 #if DCHECK_IS_ON()
921 DCHECK(inside_impl_frame_)
922 << "DidFinishImplFrame called while not inside an impl frame!";
923 inside_impl_frame_ = false;
924 #endif
927 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
928 layer_tree_host_->SendBeginFramesToChildren(args);
931 } // namespace cc