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/debug/trace_event.h"
9 #include "cc/debug/benchmark_instrumentation.h"
10 #include "cc/output/context_provider.h"
11 #include "cc/output/output_surface.h"
12 #include "cc/quads/draw_quad.h"
13 #include "cc/resources/prioritized_resource_manager.h"
14 #include "cc/resources/resource_update_controller.h"
15 #include "cc/trees/layer_tree_host.h"
16 #include "cc/trees/layer_tree_host_single_thread_client.h"
17 #include "cc/trees/layer_tree_impl.h"
18 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
19 #include "ui/gfx/frame_time.h"
23 scoped_ptr<Proxy> SingleThreadProxy::Create(
24 LayerTreeHost* layer_tree_host,
25 LayerTreeHostSingleThreadClient* client,
26 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
27 return make_scoped_ptr(
28 new SingleThreadProxy(layer_tree_host, client, main_task_runner));
31 SingleThreadProxy::SingleThreadProxy(
32 LayerTreeHost* layer_tree_host,
33 LayerTreeHostSingleThreadClient* client,
34 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
35 : Proxy(main_task_runner, NULL),
36 layer_tree_host_(layer_tree_host),
38 timing_history_(layer_tree_host->rendering_stats_instrumentation()),
39 next_frame_is_newly_committed_frame_(false),
41 defer_commits_(false),
42 commit_was_deferred_(false),
43 commit_requested_(false),
44 inside_synchronous_composite_(false),
45 output_surface_creation_requested_(false),
47 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
48 DCHECK(Proxy::IsMainThread());
49 DCHECK(layer_tree_host);
52 void SingleThreadProxy::Start() {
53 DebugScopedSetImplThread impl(this);
54 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
57 SingleThreadProxy::~SingleThreadProxy() {
58 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
59 DCHECK(Proxy::IsMainThread());
60 // Make sure Stop() got called or never Started.
61 DCHECK(!layer_tree_host_impl_);
64 void SingleThreadProxy::FinishAllRendering() {
65 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
66 DCHECK(Proxy::IsMainThread());
68 DebugScopedSetImplThread impl(this);
69 layer_tree_host_impl_->FinishAllRendering();
73 bool SingleThreadProxy::IsStarted() const {
74 DCHECK(Proxy::IsMainThread());
75 return layer_tree_host_impl_;
78 void SingleThreadProxy::SetLayerTreeHostClientReady() {
79 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
80 // Scheduling is controlled by the embedder in the single thread case, so
82 DCHECK(Proxy::IsMainThread());
83 DebugScopedSetImplThread impl(this);
84 if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
85 !scheduler_on_impl_thread_) {
86 SchedulerSettings scheduler_settings(layer_tree_host_->settings());
87 scheduler_on_impl_thread_ = Scheduler::Create(this,
89 layer_tree_host_->id(),
90 MainThreadTaskRunner(),
91 base::PowerMonitor::Get());
92 scheduler_on_impl_thread_->SetCanStart();
93 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
97 void SingleThreadProxy::SetVisible(bool visible) {
98 TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
99 DebugScopedSetImplThread impl(this);
100 layer_tree_host_impl_->SetVisible(visible);
101 if (scheduler_on_impl_thread_)
102 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
103 // Changing visibility could change ShouldComposite().
104 UpdateBackgroundAnimateTicking();
107 void SingleThreadProxy::RequestNewOutputSurface() {
108 DCHECK(Proxy::IsMainThread());
109 DCHECK(layer_tree_host_->output_surface_lost());
110 output_surface_creation_callback_.Cancel();
111 if (output_surface_creation_requested_)
113 output_surface_creation_requested_ = true;
114 layer_tree_host_->RequestNewOutputSurface();
117 void SingleThreadProxy::SetOutputSurface(
118 scoped_ptr<OutputSurface> output_surface) {
119 DCHECK(Proxy::IsMainThread());
120 DCHECK(layer_tree_host_->output_surface_lost());
121 output_surface_creation_requested_ = false;
122 renderer_capabilities_for_main_thread_ = RendererCapabilities();
124 bool success = !!output_surface;
126 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
127 DebugScopedSetImplThread impl(this);
128 layer_tree_host_->DeleteContentsTexturesOnImplThread(
129 layer_tree_host_impl_->resource_provider());
130 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
133 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
136 if (scheduler_on_impl_thread_)
137 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
138 else if (!inside_synchronous_composite_)
140 } else if (Proxy::MainThreadTaskRunner()) {
141 ScheduleRequestNewOutputSurface();
145 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
146 DCHECK(Proxy::IsMainThread());
147 DCHECK(!layer_tree_host_->output_surface_lost());
148 return renderer_capabilities_for_main_thread_;
151 void SingleThreadProxy::SetNeedsAnimate() {
152 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
153 DCHECK(Proxy::IsMainThread());
154 client_->ScheduleAnimation();
158 void SingleThreadProxy::SetNeedsUpdateLayers() {
159 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
160 DCHECK(Proxy::IsMainThread());
164 void SingleThreadProxy::DoCommit() {
165 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
166 DCHECK(Proxy::IsMainThread());
168 commit_requested_ = false;
169 layer_tree_host_->WillCommit();
171 // Commit immediately.
173 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
174 DebugScopedSetImplThread impl(this);
176 // This CapturePostTasks should be destroyed before CommitComplete() is
177 // called since that goes out to the embedder, and we want the embedder
178 // to receive its callbacks before that.
179 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks(
180 blocking_main_thread_task_runner()));
182 layer_tree_host_impl_->BeginCommit();
184 if (PrioritizedResourceManager* contents_texture_manager =
185 layer_tree_host_->contents_texture_manager()) {
186 contents_texture_manager->PushTexturePrioritiesToBackings();
188 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
190 scoped_ptr<ResourceUpdateController> update_controller =
191 ResourceUpdateController::Create(
193 MainThreadTaskRunner(),
194 queue_for_commit_.Pass(),
195 layer_tree_host_impl_->resource_provider());
196 update_controller->Finalize();
198 if (layer_tree_host_impl_->EvictedUIResourcesExist())
199 layer_tree_host_->RecreateUIResources();
201 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
203 layer_tree_host_impl_->CommitComplete();
205 UpdateBackgroundAnimateTicking();
208 // In the single-threaded case, the scale and scroll deltas should never be
209 // touched on the impl layer tree.
210 scoped_ptr<ScrollAndScaleSet> scroll_info =
211 layer_tree_host_impl_->ProcessScrollDeltas();
212 DCHECK(!scroll_info->scrolls.size());
213 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
216 RenderingStatsInstrumentation* stats_instrumentation =
217 layer_tree_host_->rendering_stats_instrumentation();
218 benchmark_instrumentation::IssueMainThreadRenderingStatsEvent(
219 stats_instrumentation->main_thread_rendering_stats());
220 stats_instrumentation->AccumulateAndClearMainThreadStats();
223 if (layer_tree_host_->settings().impl_side_painting) {
224 // TODO(enne): just commit directly to the active tree.
226 // Synchronously activate during commit to satisfy any potential
227 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
228 // might not be ready to draw, so DidActivateSyncTree must set
229 // the flag to force the tree to not draw until textures are ready.
230 NotifyReadyToActivate();
236 void SingleThreadProxy::CommitComplete() {
237 DCHECK(!layer_tree_host_impl_->pending_tree())
238 << "Activation is expected to have synchronously occurred by now.";
239 DCHECK(commit_blocking_task_runner_);
241 DebugScopedSetMainThread main(this);
242 commit_blocking_task_runner_.reset();
243 layer_tree_host_->CommitComplete();
244 layer_tree_host_->DidBeginMainFrame();
245 timing_history_.DidCommit();
247 next_frame_is_newly_committed_frame_ = true;
250 void SingleThreadProxy::SetNeedsCommit() {
251 DCHECK(Proxy::IsMainThread());
252 DebugScopedSetImplThread impl(this);
253 client_->ScheduleComposite();
254 if (scheduler_on_impl_thread_)
255 scheduler_on_impl_thread_->SetNeedsCommit();
256 commit_requested_ = true;
259 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
260 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
261 DCHECK(Proxy::IsMainThread());
262 DebugScopedSetImplThread impl(this);
263 client_->ScheduleComposite();
264 SetNeedsRedrawRectOnImplThread(damage_rect);
267 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
268 // Activation always forced in commit, so nothing to do.
269 DCHECK(Proxy::IsMainThread());
272 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
273 DCHECK(Proxy::IsMainThread());
274 // Deferring commits only makes sense if there's a scheduler.
275 if (!scheduler_on_impl_thread_)
277 if (defer_commits_ == defer_commits)
281 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
283 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
285 defer_commits_ = defer_commits;
286 if (!defer_commits_ && commit_was_deferred_) {
287 commit_was_deferred_ = false;
292 bool SingleThreadProxy::CommitRequested() const {
293 DCHECK(Proxy::IsMainThread());
294 return commit_requested_;
297 bool SingleThreadProxy::BeginMainFrameRequested() const {
298 DCHECK(Proxy::IsMainThread());
299 // If there is no scheduler, then there can be no pending begin frame,
300 // as all frames are all manually initiated by the embedder of cc.
301 if (!scheduler_on_impl_thread_)
303 return commit_requested_;
306 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
307 return std::numeric_limits<size_t>::max();
310 void SingleThreadProxy::Stop() {
311 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
312 DCHECK(Proxy::IsMainThread());
314 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
315 DebugScopedSetImplThread impl(this);
317 BlockingTaskRunner::CapturePostTasks blocked(
318 blocking_main_thread_task_runner());
319 layer_tree_host_->DeleteContentsTexturesOnImplThread(
320 layer_tree_host_impl_->resource_provider());
321 scheduler_on_impl_thread_ = nullptr;
322 layer_tree_host_impl_ = nullptr;
324 layer_tree_host_ = NULL;
327 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
329 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
330 DCHECK(Proxy::IsImplThread());
331 UpdateBackgroundAnimateTicking();
332 if (scheduler_on_impl_thread_)
333 scheduler_on_impl_thread_->SetCanDraw(can_draw);
336 void SingleThreadProxy::NotifyReadyToActivate() {
337 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
338 DebugScopedSetImplThread impl(this);
339 if (scheduler_on_impl_thread_)
340 scheduler_on_impl_thread_->NotifyReadyToActivate();
343 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
344 client_->ScheduleComposite();
345 if (scheduler_on_impl_thread_)
346 scheduler_on_impl_thread_->SetNeedsRedraw();
349 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
350 SetNeedsRedrawOnImplThread();
353 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
354 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsManageTilesOnImplThread");
355 if (scheduler_on_impl_thread_)
356 scheduler_on_impl_thread_->SetNeedsManageTiles();
359 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
360 const gfx::Rect& damage_rect) {
361 layer_tree_host_impl_->SetViewportDamage(damage_rect);
362 SetNeedsRedrawOnImplThread();
365 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
366 TRACE_EVENT0("cc", "SingleThreadProxy::DidInitializeVisibleTileOnImplThread");
367 if (scheduler_on_impl_thread_)
368 scheduler_on_impl_thread_->SetNeedsRedraw();
371 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
372 client_->ScheduleComposite();
373 if (scheduler_on_impl_thread_)
374 scheduler_on_impl_thread_->SetNeedsCommit();
377 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
378 scoped_ptr<AnimationEventsVector> events) {
380 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
381 DCHECK(Proxy::IsImplThread());
382 DebugScopedSetMainThread main(this);
383 layer_tree_host_->SetAnimationEvents(events.Pass());
386 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
388 int priority_cutoff) {
389 DCHECK(IsImplThread());
390 PrioritizedResourceManager* contents_texture_manager =
391 layer_tree_host_->contents_texture_manager();
393 ResourceProvider* resource_provider =
394 layer_tree_host_impl_->resource_provider();
396 if (!contents_texture_manager || !resource_provider)
399 return contents_texture_manager->ReduceMemoryOnImplThread(
400 limit_bytes, priority_cutoff, resource_provider);
403 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
405 void SingleThreadProxy::DidActivateSyncTree() {
406 // Non-impl-side painting finishes commit in DoCommit. Impl-side painting
407 // defers until here to simulate SetNextCommitWaitsForActivation.
408 if (layer_tree_host_impl_->settings().impl_side_painting) {
409 // This is required because NotifyReadyToActivate gets called when
410 // the pending tree is not actually ready in the SingleThreadProxy.
411 layer_tree_host_impl_->SetRequiresHighResToDraw();
413 // Since activation could cause tasks to run, post CommitComplete
414 // separately so that it runs after these tasks. This is the loose
415 // equivalent of blocking commit until activation and also running
416 // all tasks posted during commit/activation before CommitComplete.
417 MainThreadTaskRunner()->PostTask(
419 base::Bind(&SingleThreadProxy::CommitComplete,
420 weak_factory_.GetWeakPtr()));
423 UpdateBackgroundAnimateTicking();
424 timing_history_.DidActivateSyncTree();
427 void SingleThreadProxy::DidManageTiles() {
428 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
429 DCHECK(Proxy::IsImplThread());
430 if (scheduler_on_impl_thread_)
431 scheduler_on_impl_thread_->DidManageTiles();
434 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
435 DCHECK(IsImplThread());
436 renderer_capabilities_for_main_thread_ =
437 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
440 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
441 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
443 DebugScopedSetMainThread main(this);
444 // This must happen before we notify the scheduler as it may try to recreate
445 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
446 layer_tree_host_->DidLoseOutputSurface();
448 client_->DidAbortSwapBuffers();
449 if (scheduler_on_impl_thread_)
450 scheduler_on_impl_thread_->DidLoseOutputSurface();
453 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
454 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
455 if (scheduler_on_impl_thread_)
456 scheduler_on_impl_thread_->DidSwapBuffers();
457 client_->DidPostSwapBuffers();
460 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
461 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
462 if (scheduler_on_impl_thread_)
463 scheduler_on_impl_thread_->DidSwapBuffersComplete();
464 layer_tree_host_->DidCompleteSwapBuffers();
467 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
468 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
469 DCHECK(Proxy::IsMainThread());
470 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
472 if (layer_tree_host_->output_surface_lost()) {
473 RequestNewOutputSurface();
474 // RequestNewOutputSurface could have synchronously created an output
475 // surface, so check again before returning.
476 if (layer_tree_host_->output_surface_lost())
481 BeginFrameArgs begin_frame_args(
482 BeginFrameArgs::Create(frame_begin_time,
484 BeginFrameArgs::DefaultInterval()));
485 DoBeginMainFrame(begin_frame_args);
488 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
489 << "Commit should always succeed and transfer promises.";
493 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
494 if (layer_tree_host_impl_->settings().impl_side_painting) {
495 layer_tree_host_impl_->ActivateSyncTree();
496 layer_tree_host_impl_->active_tree()->UpdateDrawProperties();
497 layer_tree_host_impl_->ManageTiles();
498 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
501 LayerTreeHostImpl::FrameData frame;
502 DoComposite(frame_begin_time, &frame);
504 // DoComposite could abort, but because this is a synchronous composite
505 // another draw will never be scheduled, so break remaining promises.
506 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
507 SwapPromise::SWAP_FAILS);
511 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
512 // The following line casts away const modifiers because it is just
513 // setting debug state. We still want the AsValue() function and its
514 // call chain to be const throughout.
515 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
517 state->BeginDictionary("layer_tree_host_impl");
518 layer_tree_host_impl_->AsValueInto(state);
519 state->EndDictionary();
522 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
524 DebugScopedSetImplThread impl(this);
525 if (layer_tree_host_impl_->renderer()) {
526 DCHECK(!layer_tree_host_->output_surface_lost());
527 layer_tree_host_impl_->renderer()->DoNoOp();
532 bool SingleThreadProxy::SupportsImplScrolling() const {
536 bool SingleThreadProxy::ShouldComposite() const {
537 DCHECK(Proxy::IsImplThread());
538 return layer_tree_host_impl_->visible() &&
539 layer_tree_host_impl_->CanDraw();
542 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
543 DCHECK(Proxy::IsImplThread());
544 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
545 !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
548 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
549 if (output_surface_creation_callback_.IsCancelled() &&
550 !output_surface_creation_requested_) {
551 output_surface_creation_callback_.Reset(
552 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
553 weak_factory_.GetWeakPtr()));
554 MainThreadTaskRunner()->PostTask(
555 FROM_HERE, output_surface_creation_callback_.callback());
559 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
560 LayerTreeHostImpl::FrameData* frame) {
561 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
562 DCHECK(!layer_tree_host_->output_surface_lost());
564 DrawResult draw_result;
567 DebugScopedSetImplThread impl(this);
568 base::AutoReset<bool> mark_inside(&inside_draw_, true);
570 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
571 // frame, so can only be used when such a frame is possible. Since
572 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
573 // CanDraw() as well.
574 if (!ShouldComposite()) {
575 UpdateBackgroundAnimateTicking();
576 return DRAW_ABORTED_CANT_DRAW;
579 timing_history_.DidStartDrawing();
581 layer_tree_host_impl_->Animate(
582 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
583 UpdateBackgroundAnimateTicking();
585 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
586 draw_frame = draw_result == DRAW_SUCCESS;
588 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
589 layer_tree_host_impl_->DidDrawAllLayers(*frame);
591 bool start_ready_animations = draw_frame;
592 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
593 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
595 timing_history_.DidFinishDrawing();
599 DebugScopedSetImplThread impl(this);
601 // This CapturePostTasks should be destroyed before
602 // DidCommitAndDrawFrame() is called since that goes out to the
604 // and we want the embedder to receive its callbacks before that.
605 // NOTE: This maintains consistent ordering with the ThreadProxy since
606 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
607 // there as the main thread is not blocked, so any posted tasks inside
608 // the swap buffers will execute first.
609 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
611 BlockingTaskRunner::CapturePostTasks blocked(
612 blocking_main_thread_task_runner());
613 layer_tree_host_impl_->SwapBuffers(*frame);
615 DidCommitAndDrawFrame();
620 void SingleThreadProxy::DidCommitAndDrawFrame() {
621 if (next_frame_is_newly_committed_frame_) {
622 DebugScopedSetMainThread main(this);
623 next_frame_is_newly_committed_frame_ = false;
624 layer_tree_host_->DidCommitAndDrawFrame();
628 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
632 BeginFrameSource* SingleThreadProxy::ExternalBeginFrameSource() {
633 return layer_tree_host_impl_.get();
636 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
637 layer_tree_host_impl_->WillBeginImplFrame(args);
640 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
641 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
642 // Although this proxy is single-threaded, it's problematic to synchronously
643 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
644 // could cause a commit to occur in between a series of SetNeedsCommit calls
645 // (i.e. property modifications) causing some to fall on one frame and some to
646 // fall on the next. Doing it asynchronously instead matches the semantics of
647 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
648 // synchronous commit.
649 MainThreadTaskRunner()->PostTask(
651 base::Bind(&SingleThreadProxy::BeginMainFrame,
652 weak_factory_.GetWeakPtr()));
655 void SingleThreadProxy::BeginMainFrame() {
656 if (defer_commits_) {
657 DCHECK(!commit_was_deferred_);
658 commit_was_deferred_ = true;
659 layer_tree_host_->DidDeferCommit();
663 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
665 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
667 if (!layer_tree_host_->visible()) {
668 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
669 BeginMainFrameAbortedOnImplThread();
673 if (layer_tree_host_->output_surface_lost()) {
674 TRACE_EVENT_INSTANT0(
675 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
676 BeginMainFrameAbortedOnImplThread();
680 const BeginFrameArgs& begin_frame_args =
681 layer_tree_host_impl_->CurrentBeginFrameArgs();
682 DoBeginMainFrame(begin_frame_args);
685 void SingleThreadProxy::DoBeginMainFrame(
686 const BeginFrameArgs& begin_frame_args) {
687 layer_tree_host_->WillBeginMainFrame();
688 layer_tree_host_->BeginMainFrame(begin_frame_args);
689 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
690 layer_tree_host_->Layout();
692 if (PrioritizedResourceManager* contents_texture_manager =
693 layer_tree_host_->contents_texture_manager()) {
694 contents_texture_manager->UnlinkAndClearEvictedBackings();
695 contents_texture_manager->SetMaxMemoryLimitBytes(
696 layer_tree_host_impl_->memory_allocation_limit_bytes());
697 contents_texture_manager->SetExternalPriorityCutoff(
698 layer_tree_host_impl_->memory_allocation_priority_cutoff());
701 DCHECK(!queue_for_commit_);
702 queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue);
704 layer_tree_host_->UpdateLayers(queue_for_commit_.get());
706 timing_history_.DidBeginMainFrame();
708 if (scheduler_on_impl_thread_) {
709 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
710 scheduler_on_impl_thread_->NotifyReadyToCommit();
714 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread() {
715 DebugScopedSetImplThread impl(this);
716 DCHECK(scheduler_on_impl_thread_->CommitPending());
717 DCHECK(!layer_tree_host_impl_->pending_tree());
719 // TODO(enne): SingleThreadProxy does not support cancelling commits yet so
720 // did_handle is always false.
721 bool did_handle = false;
722 layer_tree_host_impl_->BeginMainFrameAborted(did_handle);
723 scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle);
726 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
727 DebugScopedSetImplThread impl(this);
728 LayerTreeHostImpl::FrameData frame;
729 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
733 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
735 return INVALID_RESULT;
738 void SingleThreadProxy::ScheduledActionCommit() {
739 DebugScopedSetMainThread main(this);
743 void SingleThreadProxy::ScheduledActionAnimate() {
744 TRACE_EVENT0("cc", "ScheduledActionAnimate");
745 layer_tree_host_impl_->Animate(
746 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
749 void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() {
750 DebugScopedSetImplThread impl(this);
751 layer_tree_host_impl_->UpdateVisibleTiles();
754 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
755 DebugScopedSetImplThread impl(this);
756 layer_tree_host_impl_->ActivateSyncTree();
759 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
760 DebugScopedSetMainThread main(this);
761 DCHECK(scheduler_on_impl_thread_);
762 // If possible, create the output surface in a post task. Synchronously
763 // creating the output surface makes tests more awkward since this differs
764 // from the ThreadProxy behavior. However, sometimes there is no
766 if (Proxy::MainThreadTaskRunner()) {
767 ScheduleRequestNewOutputSurface();
769 RequestNewOutputSurface();
773 void SingleThreadProxy::ScheduledActionManageTiles() {
774 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionManageTiles");
775 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
776 DebugScopedSetImplThread impl(this);
777 layer_tree_host_impl_->ManageTiles();
780 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
783 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
784 return timing_history_.DrawDurationEstimate();
787 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
788 return timing_history_.BeginMainFrameToCommitDurationEstimate();
791 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
792 return timing_history_.CommitToActivateDurationEstimate();
795 void SingleThreadProxy::DidBeginImplFrameDeadline() {
796 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();