Landing Recent QUIC changes until 8/19/2015 17:00 UTC.
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blob8193758812327d2bd2408cdedd8c5fa6a9335665
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 void SingleThreadProxy::SetOutputSurface(
153 scoped_ptr<OutputSurface> output_surface) {
154 DCHECK(Proxy::IsMainThread());
155 DCHECK(layer_tree_host_->output_surface_lost());
156 DCHECK(output_surface_creation_requested_);
157 renderer_capabilities_for_main_thread_ = RendererCapabilities();
159 bool success;
161 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
162 DebugScopedSetImplThread impl(this);
163 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
166 if (success) {
167 layer_tree_host_->DidInitializeOutputSurface();
168 if (scheduler_on_impl_thread_)
169 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
170 else if (!inside_synchronous_composite_)
171 SetNeedsCommit();
172 output_surface_creation_requested_ = false;
173 } else {
174 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface,
175 // and so output_surface_creation_requested remains true.
176 layer_tree_host_->DidFailToInitializeOutputSurface();
180 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
181 DCHECK(Proxy::IsMainThread());
182 DCHECK(!layer_tree_host_->output_surface_lost());
183 return renderer_capabilities_for_main_thread_;
186 void SingleThreadProxy::SetNeedsAnimate() {
187 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
188 DCHECK(Proxy::IsMainThread());
189 client_->ScheduleAnimation();
190 if (animate_requested_)
191 return;
192 animate_requested_ = true;
193 DebugScopedSetImplThread impl(this);
194 if (scheduler_on_impl_thread_)
195 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
198 void SingleThreadProxy::SetNeedsUpdateLayers() {
199 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
200 DCHECK(Proxy::IsMainThread());
201 SetNeedsCommit();
204 void SingleThreadProxy::DoCommit() {
205 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
206 DCHECK(Proxy::IsMainThread());
208 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
209 // fixed.
210 tracked_objects::ScopedTracker tracking_profile1(
211 FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1"));
212 layer_tree_host_->WillCommit();
213 devtools_instrumentation::ScopedCommitTrace commit_task(
214 layer_tree_host_->id());
216 // Commit immediately.
218 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
219 // is fixed.
220 tracked_objects::ScopedTracker tracking_profile2(
221 FROM_HERE_WITH_EXPLICIT_FUNCTION(
222 "461509 SingleThreadProxy::DoCommit2"));
223 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
224 DebugScopedSetImplThread impl(this);
226 // This CapturePostTasks should be destroyed before CommitComplete() is
227 // called since that goes out to the embedder, and we want the embedder
228 // to receive its callbacks before that.
229 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks(
230 blocking_main_thread_task_runner()));
232 layer_tree_host_impl_->BeginCommit();
233 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
235 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
236 // is fixed.
237 tracked_objects::ScopedTracker tracking_profile6(
238 FROM_HERE_WITH_EXPLICIT_FUNCTION(
239 "461509 SingleThreadProxy::DoCommit6"));
240 if (layer_tree_host_impl_->EvictedUIResourcesExist())
241 layer_tree_host_->RecreateUIResources();
243 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
244 // is fixed.
245 tracked_objects::ScopedTracker tracking_profile7(
246 FROM_HERE_WITH_EXPLICIT_FUNCTION(
247 "461509 SingleThreadProxy::DoCommit7"));
248 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
250 #if DCHECK_IS_ON()
251 // In the single-threaded case, the scale and scroll deltas should never be
252 // touched on the impl layer tree.
253 scoped_ptr<ScrollAndScaleSet> scroll_info =
254 layer_tree_host_impl_->ProcessScrollDeltas();
255 DCHECK(!scroll_info->scrolls.size());
256 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
257 #endif
259 if (scheduler_on_impl_thread_)
260 scheduler_on_impl_thread_->DidCommit();
262 layer_tree_host_impl_->CommitComplete();
264 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
265 // is fixed.
266 tracked_objects::ScopedTracker tracking_profile8(
267 FROM_HERE_WITH_EXPLICIT_FUNCTION(
268 "461509 SingleThreadProxy::DoCommit8"));
269 // Commit goes directly to the active tree, but we need to synchronously
270 // "activate" the tree still during commit to satisfy any potential
271 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
272 // might not be ready to draw, so DidActivateSyncTree must set
273 // the flag to force the tree to not draw until textures are ready.
274 NotifyReadyToActivate();
278 void SingleThreadProxy::CommitComplete() {
279 // Commit complete happens on the main side after activate to satisfy any
280 // SetNextCommitWaitsForActivation calls.
281 DCHECK(!layer_tree_host_impl_->pending_tree())
282 << "Activation is expected to have synchronously occurred by now.";
283 DCHECK(commit_blocking_task_runner_);
285 DebugScopedSetMainThread main(this);
286 commit_blocking_task_runner_.reset();
287 layer_tree_host_->CommitComplete();
288 layer_tree_host_->DidBeginMainFrame();
290 next_frame_is_newly_committed_frame_ = true;
293 void SingleThreadProxy::SetNeedsCommit() {
294 DCHECK(Proxy::IsMainThread());
295 client_->ScheduleComposite();
296 if (commit_requested_)
297 return;
298 commit_requested_ = true;
299 DebugScopedSetImplThread impl(this);
300 if (scheduler_on_impl_thread_)
301 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
304 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
305 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
306 DCHECK(Proxy::IsMainThread());
307 DebugScopedSetImplThread impl(this);
308 client_->ScheduleComposite();
309 SetNeedsRedrawRectOnImplThread(damage_rect);
312 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
313 // Activation always forced in commit, so nothing to do.
314 DCHECK(Proxy::IsMainThread());
317 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
318 DCHECK(Proxy::IsMainThread());
319 // Deferring commits only makes sense if there's a scheduler.
320 if (!scheduler_on_impl_thread_)
321 return;
322 if (defer_commits_ == defer_commits)
323 return;
325 if (defer_commits)
326 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
327 else
328 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
330 defer_commits_ = defer_commits;
331 scheduler_on_impl_thread_->SetDeferCommits(defer_commits);
334 bool SingleThreadProxy::CommitRequested() const {
335 DCHECK(Proxy::IsMainThread());
336 return commit_requested_;
339 bool SingleThreadProxy::BeginMainFrameRequested() const {
340 DCHECK(Proxy::IsMainThread());
341 // If there is no scheduler, then there can be no pending begin frame,
342 // as all frames are all manually initiated by the embedder of cc.
343 if (!scheduler_on_impl_thread_)
344 return false;
345 return commit_requested_;
348 void SingleThreadProxy::Stop() {
349 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
350 DCHECK(Proxy::IsMainThread());
352 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
353 DebugScopedSetImplThread impl(this);
355 BlockingTaskRunner::CapturePostTasks blocked(
356 blocking_main_thread_task_runner());
357 scheduler_on_impl_thread_ = nullptr;
358 layer_tree_host_impl_ = nullptr;
360 layer_tree_host_ = NULL;
363 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
364 TRACE_EVENT1(
365 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
366 DCHECK(Proxy::IsImplThread());
367 if (scheduler_on_impl_thread_)
368 scheduler_on_impl_thread_->SetCanDraw(can_draw);
371 void SingleThreadProxy::NotifyReadyToActivate() {
372 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
373 DebugScopedSetImplThread impl(this);
374 if (scheduler_on_impl_thread_)
375 scheduler_on_impl_thread_->NotifyReadyToActivate();
378 void SingleThreadProxy::NotifyReadyToDraw() {
379 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToDraw");
380 DebugScopedSetImplThread impl(this);
381 if (scheduler_on_impl_thread_)
382 scheduler_on_impl_thread_->NotifyReadyToDraw();
385 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
386 client_->ScheduleComposite();
387 if (scheduler_on_impl_thread_)
388 scheduler_on_impl_thread_->SetNeedsRedraw();
391 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
392 client_->ScheduleComposite();
393 if (scheduler_on_impl_thread_)
394 scheduler_on_impl_thread_->SetNeedsAnimate();
397 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
398 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
399 if (scheduler_on_impl_thread_)
400 scheduler_on_impl_thread_->SetNeedsPrepareTiles();
403 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
404 const gfx::Rect& damage_rect) {
405 layer_tree_host_impl_->SetViewportDamage(damage_rect);
406 SetNeedsRedrawOnImplThread();
409 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
410 client_->ScheduleComposite();
411 if (scheduler_on_impl_thread_)
412 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
415 void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
416 TRACE_EVENT1("cc", "SingleThreadProxy::SetVideoNeedsBeginFrames",
417 "needs_begin_frames", needs_begin_frames);
418 // In tests the layer tree is destroyed after the scheduler is.
419 if (scheduler_on_impl_thread_)
420 scheduler_on_impl_thread_->SetVideoNeedsBeginFrames(needs_begin_frames);
423 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
424 scoped_ptr<AnimationEventsVector> events) {
425 TRACE_EVENT0(
426 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
427 DCHECK(Proxy::IsImplThread());
428 DebugScopedSetMainThread main(this);
429 layer_tree_host_->SetAnimationEvents(events.Pass());
432 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
434 void SingleThreadProxy::DidActivateSyncTree() {
435 // Synchronously call to CommitComplete. Resetting
436 // |commit_blocking_task_runner| would make sure all tasks posted during
437 // commit/activation before CommitComplete.
438 CommitComplete();
441 void SingleThreadProxy::WillPrepareTiles() {
442 DCHECK(Proxy::IsImplThread());
443 if (scheduler_on_impl_thread_)
444 scheduler_on_impl_thread_->WillPrepareTiles();
447 void SingleThreadProxy::DidPrepareTiles() {
448 DCHECK(Proxy::IsImplThread());
449 if (scheduler_on_impl_thread_)
450 scheduler_on_impl_thread_->DidPrepareTiles();
453 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
454 layer_tree_host_->DidCompletePageScaleAnimation();
457 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
458 DCHECK(IsImplThread());
459 renderer_capabilities_for_main_thread_ =
460 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
463 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
464 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
466 DebugScopedSetMainThread main(this);
467 // This must happen before we notify the scheduler as it may try to recreate
468 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
469 layer_tree_host_->DidLoseOutputSurface();
471 client_->DidAbortSwapBuffers();
472 if (scheduler_on_impl_thread_)
473 scheduler_on_impl_thread_->DidLoseOutputSurface();
476 void SingleThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
477 base::TimeDelta interval) {
478 if (scheduler_on_impl_thread_)
479 scheduler_on_impl_thread_->CommitVSyncParameters(timebase, interval);
482 void SingleThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
483 if (scheduler_on_impl_thread_)
484 scheduler_on_impl_thread_->SetEstimatedParentDrawTime(draw_time);
487 void SingleThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
488 if (scheduler_on_impl_thread_)
489 scheduler_on_impl_thread_->SetMaxSwapsPending(max);
492 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
493 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
494 if (scheduler_on_impl_thread_)
495 scheduler_on_impl_thread_->DidSwapBuffers();
496 client_->DidPostSwapBuffers();
499 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
500 TRACE_EVENT0("cc,benchmark",
501 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
502 if (scheduler_on_impl_thread_)
503 scheduler_on_impl_thread_->DidSwapBuffersComplete();
504 layer_tree_host_->DidCompleteSwapBuffers();
507 void SingleThreadProxy::OnDrawForOutputSurface() {
508 NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor.";
511 void SingleThreadProxy::PostFrameTimingEventsOnImplThread(
512 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
513 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
514 layer_tree_host_->RecordFrameTimingEvents(composite_events.Pass(),
515 main_frame_events.Pass());
518 void SingleThreadProxy::LayoutAndUpdateLayers() {
519 if (layer_tree_host_->output_surface_lost()) {
520 RequestNewOutputSurface();
521 // RequestNewOutputSurface could have synchronously created an output
522 // surface, so check again before returning.
523 if (layer_tree_host_->output_surface_lost())
524 return;
527 layer_tree_host_->Layout();
528 layer_tree_host_->UpdateLayers();
531 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
532 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
533 DCHECK(Proxy::IsMainThread());
534 #if DCHECK_IS_ON()
535 DCHECK(!inside_impl_frame_);
536 #endif
537 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
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 BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
548 BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(),
549 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL));
551 // Start the impl frame.
553 DebugScopedSetImplThread impl(this);
554 WillBeginImplFrame(begin_frame_args);
557 // Run the "main thread" and get it to commit.
559 #if DCHECK_IS_ON()
560 DCHECK(inside_impl_frame_);
561 #endif
562 DoBeginMainFrame(begin_frame_args);
563 DoCommit();
565 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
566 << "Commit should always succeed and transfer promises.";
569 // Finish the impl frame.
571 DebugScopedSetImplThread impl(this);
572 layer_tree_host_impl_->ActivateSyncTree();
573 DCHECK(
574 !layer_tree_host_impl_->active_tree()->needs_update_draw_properties());
575 layer_tree_host_impl_->PrepareTiles();
576 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
578 // TODO(danakj): Don't do this last... we prepared the wrong things. D:
579 layer_tree_host_impl_->Animate();
581 LayerTreeHostImpl::FrameData frame;
582 DoComposite(&frame);
584 // DoComposite could abort, but because this is a synchronous composite
585 // another draw will never be scheduled, so break remaining promises.
586 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
587 SwapPromise::SWAP_FAILS);
589 DidFinishImplFrame();
593 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
595 DebugScopedSetImplThread impl(this);
596 if (layer_tree_host_impl_->renderer()) {
597 DCHECK(!layer_tree_host_->output_surface_lost());
598 layer_tree_host_impl_->renderer()->DoNoOp();
603 bool SingleThreadProxy::SupportsImplScrolling() const {
604 return false;
607 bool SingleThreadProxy::ShouldComposite() const {
608 DCHECK(Proxy::IsImplThread());
609 return layer_tree_host_impl_->visible() &&
610 layer_tree_host_impl_->CanDraw();
613 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
614 if (output_surface_creation_callback_.IsCancelled() &&
615 !output_surface_creation_requested_) {
616 output_surface_creation_callback_.Reset(
617 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
618 weak_factory_.GetWeakPtr()));
619 MainThreadTaskRunner()->PostTask(
620 FROM_HERE, output_surface_creation_callback_.callback());
624 DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) {
625 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
626 DCHECK(!layer_tree_host_->output_surface_lost());
628 DrawResult draw_result;
629 bool draw_frame;
631 DebugScopedSetImplThread impl(this);
632 base::AutoReset<bool> mark_inside(&inside_draw_, true);
634 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
635 // is fixed.
636 tracked_objects::ScopedTracker tracking_profile1(
637 FROM_HERE_WITH_EXPLICIT_FUNCTION(
638 "461509 SingleThreadProxy::DoComposite1"));
640 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
641 // frame, so can only be used when such a frame is possible. Since
642 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
643 // CanDraw() as well.
644 if (!ShouldComposite()) {
645 return DRAW_ABORTED_CANT_DRAW;
648 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
649 // is fixed.
650 tracked_objects::ScopedTracker tracking_profile2(
651 FROM_HERE_WITH_EXPLICIT_FUNCTION(
652 "461509 SingleThreadProxy::DoComposite2"));
653 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
654 draw_frame = draw_result == DRAW_SUCCESS;
655 if (draw_frame) {
656 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
657 // is fixed.
658 tracked_objects::ScopedTracker tracking_profile3(
659 FROM_HERE_WITH_EXPLICIT_FUNCTION(
660 "461509 SingleThreadProxy::DoComposite3"));
661 layer_tree_host_impl_->DrawLayers(frame);
663 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
664 // is fixed.
665 tracked_objects::ScopedTracker tracking_profile4(
666 FROM_HERE_WITH_EXPLICIT_FUNCTION(
667 "461509 SingleThreadProxy::DoComposite4"));
668 layer_tree_host_impl_->DidDrawAllLayers(*frame);
670 bool start_ready_animations = draw_frame;
671 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
672 // is fixed.
673 tracked_objects::ScopedTracker tracking_profile5(
674 FROM_HERE_WITH_EXPLICIT_FUNCTION(
675 "461509 SingleThreadProxy::DoComposite5"));
676 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
678 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
679 // is fixed.
680 tracked_objects::ScopedTracker tracking_profile7(
681 FROM_HERE_WITH_EXPLICIT_FUNCTION(
682 "461509 SingleThreadProxy::DoComposite7"));
685 if (draw_frame) {
686 DebugScopedSetImplThread impl(this);
688 // This CapturePostTasks should be destroyed before
689 // DidCommitAndDrawFrame() is called since that goes out to the
690 // embedder,
691 // and we want the embedder to receive its callbacks before that.
692 // NOTE: This maintains consistent ordering with the ThreadProxy since
693 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
694 // there as the main thread is not blocked, so any posted tasks inside
695 // the swap buffers will execute first.
696 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
698 BlockingTaskRunner::CapturePostTasks blocked(
699 blocking_main_thread_task_runner());
700 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
701 // is fixed.
702 tracked_objects::ScopedTracker tracking_profile8(
703 FROM_HERE_WITH_EXPLICIT_FUNCTION(
704 "461509 SingleThreadProxy::DoComposite8"));
705 layer_tree_host_impl_->SwapBuffers(*frame);
707 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
708 // fixed.
709 tracked_objects::ScopedTracker tracking_profile9(
710 FROM_HERE_WITH_EXPLICIT_FUNCTION(
711 "461509 SingleThreadProxy::DoComposite9"));
712 DidCommitAndDrawFrame();
714 return draw_result;
717 void SingleThreadProxy::DidCommitAndDrawFrame() {
718 if (next_frame_is_newly_committed_frame_) {
719 DebugScopedSetMainThread main(this);
720 next_frame_is_newly_committed_frame_ = false;
721 layer_tree_host_->DidCommitAndDrawFrame();
725 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
726 if (layer_tree_host_->output_surface_lost())
727 return false;
728 if (!scheduler_on_impl_thread_)
729 return false;
730 return scheduler_on_impl_thread_->MainFrameForTestingWillHappen();
733 void SingleThreadProxy::SetChildrenNeedBeginFrames(
734 bool children_need_begin_frames) {
735 scheduler_on_impl_thread_->SetChildrenNeedBeginFrames(
736 children_need_begin_frames);
739 void SingleThreadProxy::SetAuthoritativeVSyncInterval(
740 const base::TimeDelta& interval) {
741 scheduler_on_impl_thread_->SetAuthoritativeVSyncInterval(interval);
744 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
745 #if DCHECK_IS_ON()
746 DCHECK(!inside_impl_frame_)
747 << "WillBeginImplFrame called while already inside an impl frame!";
748 inside_impl_frame_ = true;
749 #endif
750 layer_tree_host_impl_->WillBeginImplFrame(args);
753 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
754 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
755 // Although this proxy is single-threaded, it's problematic to synchronously
756 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
757 // could cause a commit to occur in between a series of SetNeedsCommit calls
758 // (i.e. property modifications) causing some to fall on one frame and some to
759 // fall on the next. Doing it asynchronously instead matches the semantics of
760 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
761 // synchronous commit.
762 #if DCHECK_IS_ON()
763 DCHECK(inside_impl_frame_)
764 << "BeginMainFrame should only be sent inside a BeginImplFrame";
765 #endif
766 const BeginFrameArgs& begin_frame_args =
767 layer_tree_host_impl_->CurrentBeginFrameArgs();
769 MainThreadTaskRunner()->PostTask(
770 FROM_HERE, base::Bind(&SingleThreadProxy::BeginMainFrame,
771 weak_factory_.GetWeakPtr(), begin_frame_args));
774 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() {
775 layer_tree_host_->BeginMainFrameNotExpectedSoon();
778 void SingleThreadProxy::BeginMainFrame(const BeginFrameArgs& begin_frame_args) {
779 commit_requested_ = false;
780 animate_requested_ = false;
782 if (defer_commits_) {
783 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
784 TRACE_EVENT_SCOPE_THREAD);
785 BeginMainFrameAbortedOnImplThread(
786 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
787 return;
790 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
791 // commit.
792 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
794 if (!layer_tree_host_->visible()) {
795 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
796 BeginMainFrameAbortedOnImplThread(
797 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
798 return;
801 if (layer_tree_host_->output_surface_lost()) {
802 TRACE_EVENT_INSTANT0(
803 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
804 BeginMainFrameAbortedOnImplThread(
805 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
806 return;
809 // Prevent new commits from being requested inside DoBeginMainFrame.
810 // Note: We do not want to prevent SetNeedsAnimate from requesting
811 // a commit here.
812 commit_requested_ = true;
814 DoBeginMainFrame(begin_frame_args);
817 void SingleThreadProxy::DoBeginMainFrame(
818 const BeginFrameArgs& begin_frame_args) {
819 layer_tree_host_->WillBeginMainFrame();
820 layer_tree_host_->BeginMainFrame(begin_frame_args);
821 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
822 layer_tree_host_->Layout();
824 // New commits requested inside UpdateLayers should be respected.
825 commit_requested_ = false;
827 layer_tree_host_->UpdateLayers();
829 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
830 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
831 // thread_proxy.cc
832 if (scheduler_on_impl_thread_) {
833 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
834 scheduler_on_impl_thread_->NotifyReadyToCommit();
838 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
839 CommitEarlyOutReason reason) {
840 DebugScopedSetImplThread impl(this);
841 DCHECK(scheduler_on_impl_thread_->CommitPending());
842 DCHECK(!layer_tree_host_impl_->pending_tree());
844 layer_tree_host_impl_->BeginMainFrameAborted(reason);
845 scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
848 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
849 DebugScopedSetImplThread impl(this);
850 LayerTreeHostImpl::FrameData frame;
851 return DoComposite(&frame);
854 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
855 NOTREACHED();
856 return INVALID_RESULT;
859 void SingleThreadProxy::ScheduledActionCommit() {
860 DebugScopedSetMainThread main(this);
861 DoCommit();
864 void SingleThreadProxy::ScheduledActionAnimate() {
865 TRACE_EVENT0("cc", "ScheduledActionAnimate");
866 DebugScopedSetImplThread impl(this);
867 layer_tree_host_impl_->Animate();
870 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
871 DebugScopedSetImplThread impl(this);
872 layer_tree_host_impl_->ActivateSyncTree();
875 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
876 DebugScopedSetMainThread main(this);
877 DCHECK(scheduler_on_impl_thread_);
878 // If possible, create the output surface in a post task. Synchronously
879 // creating the output surface makes tests more awkward since this differs
880 // from the ThreadProxy behavior. However, sometimes there is no
881 // task runner.
882 if (Proxy::MainThreadTaskRunner()) {
883 ScheduleRequestNewOutputSurface();
884 } else {
885 RequestNewOutputSurface();
889 void SingleThreadProxy::ScheduledActionPrepareTiles() {
890 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
891 DebugScopedSetImplThread impl(this);
892 layer_tree_host_impl_->PrepareTiles();
895 void SingleThreadProxy::ScheduledActionInvalidateOutputSurface() {
896 NOTREACHED();
899 void SingleThreadProxy::DidFinishImplFrame() {
900 layer_tree_host_impl_->DidFinishImplFrame();
901 #if DCHECK_IS_ON()
902 DCHECK(inside_impl_frame_)
903 << "DidFinishImplFrame called while not inside an impl frame!";
904 inside_impl_frame_ = false;
905 #endif
908 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
909 layer_tree_host_->SendBeginFramesToChildren(args);
912 } // namespace cc