Mechanical rename of tracing includes for /cc
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blob488bba48a445c84c966349def4a8340cfa25ac8d
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/trace_event/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/scheduler/commit_earlyout_reason.h"
16 #include "cc/trees/layer_tree_host.h"
17 #include "cc/trees/layer_tree_host_single_thread_client.h"
18 #include "cc/trees/layer_tree_impl.h"
19 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
20 #include "ui/gfx/frame_time.h"
22 namespace cc {
24 scoped_ptr<Proxy> SingleThreadProxy::Create(
25 LayerTreeHost* layer_tree_host,
26 LayerTreeHostSingleThreadClient* client,
27 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
28 scoped_ptr<BeginFrameSource> external_begin_frame_source) {
29 return make_scoped_ptr(new SingleThreadProxy(
30 layer_tree_host,
31 client,
32 main_task_runner,
33 external_begin_frame_source.Pass()));
36 SingleThreadProxy::SingleThreadProxy(
37 LayerTreeHost* layer_tree_host,
38 LayerTreeHostSingleThreadClient* client,
39 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
40 scoped_ptr<BeginFrameSource> external_begin_frame_source)
41 : Proxy(main_task_runner, NULL),
42 layer_tree_host_(layer_tree_host),
43 client_(client),
44 timing_history_(layer_tree_host->rendering_stats_instrumentation()),
45 next_frame_is_newly_committed_frame_(false),
46 inside_draw_(false),
47 defer_commits_(false),
48 commit_was_deferred_(false),
49 commit_requested_(false),
50 inside_synchronous_composite_(false),
51 output_surface_creation_requested_(false),
52 external_begin_frame_source_(external_begin_frame_source.Pass()),
53 weak_factory_(this) {
54 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
55 DCHECK(Proxy::IsMainThread());
56 DCHECK(layer_tree_host);
59 void SingleThreadProxy::Start() {
60 DebugScopedSetImplThread impl(this);
61 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
64 SingleThreadProxy::~SingleThreadProxy() {
65 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
66 DCHECK(Proxy::IsMainThread());
67 // Make sure Stop() got called or never Started.
68 DCHECK(!layer_tree_host_impl_);
71 void SingleThreadProxy::FinishAllRendering() {
72 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
73 DCHECK(Proxy::IsMainThread());
75 DebugScopedSetImplThread impl(this);
76 layer_tree_host_impl_->FinishAllRendering();
80 bool SingleThreadProxy::IsStarted() const {
81 DCHECK(Proxy::IsMainThread());
82 return layer_tree_host_impl_;
85 void SingleThreadProxy::SetLayerTreeHostClientReady() {
86 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
87 // Scheduling is controlled by the embedder in the single thread case, so
88 // nothing to do.
89 DCHECK(Proxy::IsMainThread());
90 DebugScopedSetImplThread impl(this);
91 if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
92 !scheduler_on_impl_thread_) {
93 SchedulerSettings scheduler_settings(layer_tree_host_->settings());
94 scheduler_settings.main_thread_should_always_be_low_latency = true;
95 scheduler_on_impl_thread_ =
96 Scheduler::Create(this,
97 scheduler_settings,
98 layer_tree_host_->id(),
99 MainThreadTaskRunner(),
100 base::PowerMonitor::Get(),
101 external_begin_frame_source_.Pass());
102 scheduler_on_impl_thread_->SetCanStart();
103 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
107 void SingleThreadProxy::SetVisible(bool visible) {
108 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
109 DebugScopedSetImplThread impl(this);
110 layer_tree_host_impl_->SetVisible(visible);
111 if (scheduler_on_impl_thread_)
112 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
113 // Changing visibility could change ShouldComposite().
116 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) {
117 TRACE_EVENT1("cc", "SingleThreadProxy::SetThrottleFrameProduction",
118 "throttle", throttle);
119 DebugScopedSetImplThread impl(this);
120 if (scheduler_on_impl_thread_)
121 scheduler_on_impl_thread_->SetThrottleFrameProduction(throttle);
124 void SingleThreadProxy::RequestNewOutputSurface() {
125 DCHECK(Proxy::IsMainThread());
126 DCHECK(layer_tree_host_->output_surface_lost());
127 output_surface_creation_callback_.Cancel();
128 if (output_surface_creation_requested_)
129 return;
130 output_surface_creation_requested_ = true;
131 layer_tree_host_->RequestNewOutputSurface();
134 void SingleThreadProxy::SetOutputSurface(
135 scoped_ptr<OutputSurface> output_surface) {
136 DCHECK(Proxy::IsMainThread());
137 DCHECK(layer_tree_host_->output_surface_lost());
138 DCHECK(output_surface_creation_requested_);
139 renderer_capabilities_for_main_thread_ = RendererCapabilities();
141 bool success;
143 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
144 DebugScopedSetImplThread impl(this);
145 layer_tree_host_->DeleteContentsTexturesOnImplThread(
146 layer_tree_host_impl_->resource_provider());
147 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
150 if (success) {
151 layer_tree_host_->DidInitializeOutputSurface();
152 if (scheduler_on_impl_thread_)
153 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
154 else if (!inside_synchronous_composite_)
155 SetNeedsCommit();
156 output_surface_creation_requested_ = false;
157 } else {
158 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface,
159 // and so output_surface_creation_requested remains true.
160 layer_tree_host_->DidFailToInitializeOutputSurface();
164 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
165 DCHECK(Proxy::IsMainThread());
166 DCHECK(!layer_tree_host_->output_surface_lost());
167 return renderer_capabilities_for_main_thread_;
170 void SingleThreadProxy::SetNeedsAnimate() {
171 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
172 DCHECK(Proxy::IsMainThread());
173 client_->ScheduleAnimation();
174 SetNeedsCommit();
177 void SingleThreadProxy::SetNeedsUpdateLayers() {
178 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
179 DCHECK(Proxy::IsMainThread());
180 SetNeedsCommit();
183 void SingleThreadProxy::DoAnimate() {
184 // Don't animate if there is no root layer.
185 // TODO(mithro): Both Animate and UpdateAnimationState already have a
186 // "!active_tree_->root_layer()" check?
187 if (!layer_tree_host_impl_->active_tree()->root_layer()) {
188 return;
191 layer_tree_host_impl_->Animate(
192 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
194 // If animations are not visible, update the animation state now as it
195 // won't happen in DoComposite.
196 if (!layer_tree_host_impl_->AnimationsAreVisible()) {
197 layer_tree_host_impl_->UpdateAnimationState(true);
201 void SingleThreadProxy::DoCommit() {
202 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
203 DCHECK(Proxy::IsMainThread());
205 commit_requested_ = false;
206 layer_tree_host_->WillCommit();
208 // Commit immediately.
210 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
211 DebugScopedSetImplThread impl(this);
213 // This CapturePostTasks should be destroyed before CommitComplete() is
214 // called since that goes out to the embedder, and we want the embedder
215 // to receive its callbacks before that.
216 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks(
217 blocking_main_thread_task_runner()));
219 layer_tree_host_impl_->BeginCommit();
221 if (PrioritizedResourceManager* contents_texture_manager =
222 layer_tree_host_->contents_texture_manager()) {
223 contents_texture_manager->PushTexturePrioritiesToBackings();
225 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
227 scoped_ptr<ResourceUpdateController> update_controller =
228 ResourceUpdateController::Create(
229 NULL,
230 MainThreadTaskRunner(),
231 queue_for_commit_.Pass(),
232 layer_tree_host_impl_->resource_provider());
233 update_controller->Finalize();
235 if (layer_tree_host_impl_->EvictedUIResourcesExist())
236 layer_tree_host_->RecreateUIResources();
238 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
240 layer_tree_host_impl_->CommitComplete();
242 #if DCHECK_IS_ON()
243 // In the single-threaded case, the scale and scroll deltas should never be
244 // touched on the impl layer tree.
245 scoped_ptr<ScrollAndScaleSet> scroll_info =
246 layer_tree_host_impl_->ProcessScrollDeltas();
247 DCHECK(!scroll_info->scrolls.size());
248 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
249 #endif
252 if (layer_tree_host_->settings().impl_side_painting) {
253 // TODO(enne): just commit directly to the active tree.
255 // Synchronously activate during commit to satisfy any potential
256 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
257 // might not be ready to draw, so DidActivateSyncTree must set
258 // the flag to force the tree to not draw until textures are ready.
259 NotifyReadyToActivate();
260 } else {
261 CommitComplete();
265 void SingleThreadProxy::CommitComplete() {
266 DCHECK(!layer_tree_host_impl_->pending_tree())
267 << "Activation is expected to have synchronously occurred by now.";
268 DCHECK(commit_blocking_task_runner_);
270 DebugScopedSetMainThread main(this);
271 commit_blocking_task_runner_.reset();
272 layer_tree_host_->CommitComplete();
273 layer_tree_host_->DidBeginMainFrame();
274 timing_history_.DidCommit();
276 next_frame_is_newly_committed_frame_ = true;
279 void SingleThreadProxy::SetNeedsCommit() {
280 DCHECK(Proxy::IsMainThread());
281 DebugScopedSetImplThread impl(this);
282 client_->ScheduleComposite();
283 if (scheduler_on_impl_thread_)
284 scheduler_on_impl_thread_->SetNeedsCommit();
285 commit_requested_ = true;
288 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
289 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
290 DCHECK(Proxy::IsMainThread());
291 DebugScopedSetImplThread impl(this);
292 client_->ScheduleComposite();
293 SetNeedsRedrawRectOnImplThread(damage_rect);
296 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
297 // Activation always forced in commit, so nothing to do.
298 DCHECK(Proxy::IsMainThread());
301 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
302 DCHECK(Proxy::IsMainThread());
303 // Deferring commits only makes sense if there's a scheduler.
304 if (!scheduler_on_impl_thread_)
305 return;
306 if (defer_commits_ == defer_commits)
307 return;
309 if (defer_commits)
310 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
311 else
312 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
314 defer_commits_ = defer_commits;
315 if (!defer_commits_ && commit_was_deferred_) {
316 commit_was_deferred_ = false;
317 BeginMainFrame();
321 bool SingleThreadProxy::CommitRequested() const {
322 DCHECK(Proxy::IsMainThread());
323 return commit_requested_;
326 bool SingleThreadProxy::BeginMainFrameRequested() const {
327 DCHECK(Proxy::IsMainThread());
328 // If there is no scheduler, then there can be no pending begin frame,
329 // as all frames are all manually initiated by the embedder of cc.
330 if (!scheduler_on_impl_thread_)
331 return false;
332 return commit_requested_;
335 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
336 return std::numeric_limits<size_t>::max();
339 void SingleThreadProxy::Stop() {
340 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
341 DCHECK(Proxy::IsMainThread());
343 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
344 DebugScopedSetImplThread impl(this);
346 BlockingTaskRunner::CapturePostTasks blocked(
347 blocking_main_thread_task_runner());
348 layer_tree_host_->DeleteContentsTexturesOnImplThread(
349 layer_tree_host_impl_->resource_provider());
350 scheduler_on_impl_thread_ = nullptr;
351 layer_tree_host_impl_ = nullptr;
353 layer_tree_host_ = NULL;
356 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
357 TRACE_EVENT1(
358 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
359 DCHECK(Proxy::IsImplThread());
360 if (scheduler_on_impl_thread_)
361 scheduler_on_impl_thread_->SetCanDraw(can_draw);
364 void SingleThreadProxy::NotifyReadyToActivate() {
365 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
366 DebugScopedSetImplThread impl(this);
367 if (scheduler_on_impl_thread_)
368 scheduler_on_impl_thread_->NotifyReadyToActivate();
371 void SingleThreadProxy::NotifyReadyToDraw() {
374 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
375 client_->ScheduleComposite();
376 if (scheduler_on_impl_thread_)
377 scheduler_on_impl_thread_->SetNeedsRedraw();
380 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
381 client_->ScheduleComposite();
382 if (scheduler_on_impl_thread_)
383 scheduler_on_impl_thread_->SetNeedsAnimate();
386 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
387 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
388 if (scheduler_on_impl_thread_)
389 scheduler_on_impl_thread_->SetNeedsPrepareTiles();
392 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
393 const gfx::Rect& damage_rect) {
394 layer_tree_host_impl_->SetViewportDamage(damage_rect);
395 SetNeedsRedrawOnImplThread();
398 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
399 client_->ScheduleComposite();
400 if (scheduler_on_impl_thread_)
401 scheduler_on_impl_thread_->SetNeedsCommit();
404 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
405 scoped_ptr<AnimationEventsVector> events) {
406 TRACE_EVENT0(
407 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
408 DCHECK(Proxy::IsImplThread());
409 DebugScopedSetMainThread main(this);
410 layer_tree_host_->SetAnimationEvents(events.Pass());
413 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
414 size_t limit_bytes,
415 int priority_cutoff) {
416 DCHECK(IsImplThread());
417 PrioritizedResourceManager* contents_texture_manager =
418 layer_tree_host_->contents_texture_manager();
420 ResourceProvider* resource_provider =
421 layer_tree_host_impl_->resource_provider();
423 if (!contents_texture_manager || !resource_provider)
424 return false;
426 return contents_texture_manager->ReduceMemoryOnImplThread(
427 limit_bytes, priority_cutoff, resource_provider);
430 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
432 void SingleThreadProxy::DidActivateSyncTree() {
433 // Non-impl-side painting finishes commit in DoCommit. Impl-side painting
434 // defers until here to simulate SetNextCommitWaitsForActivation.
435 if (layer_tree_host_impl_->settings().impl_side_painting) {
436 // This is required because NotifyReadyToActivate gets called when
437 // the pending tree is not actually ready in the SingleThreadProxy.
438 layer_tree_host_impl_->SetRequiresHighResToDraw();
440 CommitComplete();
443 timing_history_.DidActivateSyncTree();
446 void SingleThreadProxy::DidPrepareTiles() {
447 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
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::DidSwapBuffersOnImplThread() {
483 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
484 if (scheduler_on_impl_thread_)
485 scheduler_on_impl_thread_->DidSwapBuffers();
486 client_->DidPostSwapBuffers();
489 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
490 TRACE_EVENT0("cc,benchmark",
491 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
492 if (scheduler_on_impl_thread_)
493 scheduler_on_impl_thread_->DidSwapBuffersComplete();
494 layer_tree_host_->DidCompleteSwapBuffers();
497 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
498 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
499 DCHECK(Proxy::IsMainThread());
500 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
502 if (layer_tree_host_->output_surface_lost()) {
503 RequestNewOutputSurface();
504 // RequestNewOutputSurface could have synchronously created an output
505 // surface, so check again before returning.
506 if (layer_tree_host_->output_surface_lost())
507 return;
511 BeginFrameArgs begin_frame_args(BeginFrameArgs::Create(
512 BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(),
513 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::SYNCHRONOUS));
514 DoBeginMainFrame(begin_frame_args);
515 DoCommit();
517 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
518 << "Commit should always succeed and transfer promises.";
522 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
523 if (layer_tree_host_impl_->settings().impl_side_painting) {
524 layer_tree_host_impl_->ActivateSyncTree();
525 layer_tree_host_impl_->active_tree()->UpdateDrawProperties();
526 layer_tree_host_impl_->PrepareTiles();
527 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
530 DoAnimate();
532 LayerTreeHostImpl::FrameData frame;
533 DoComposite(frame_begin_time, &frame);
535 // DoComposite could abort, but because this is a synchronous composite
536 // another draw will never be scheduled, so break remaining promises.
537 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
538 SwapPromise::SWAP_FAILS);
542 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
543 // The following line casts away const modifiers because it is just
544 // setting debug state. We still want the AsValue() function and its
545 // call chain to be const throughout.
546 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
548 state->BeginDictionary("layer_tree_host_impl");
549 layer_tree_host_impl_->AsValueInto(state);
550 state->EndDictionary();
553 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
555 DebugScopedSetImplThread impl(this);
556 if (layer_tree_host_impl_->renderer()) {
557 DCHECK(!layer_tree_host_->output_surface_lost());
558 layer_tree_host_impl_->renderer()->DoNoOp();
563 bool SingleThreadProxy::SupportsImplScrolling() const {
564 return false;
567 bool SingleThreadProxy::ShouldComposite() const {
568 DCHECK(Proxy::IsImplThread());
569 return layer_tree_host_impl_->visible() &&
570 layer_tree_host_impl_->CanDraw();
573 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
574 if (output_surface_creation_callback_.IsCancelled() &&
575 !output_surface_creation_requested_) {
576 output_surface_creation_callback_.Reset(
577 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
578 weak_factory_.GetWeakPtr()));
579 MainThreadTaskRunner()->PostTask(
580 FROM_HERE, output_surface_creation_callback_.callback());
584 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
585 LayerTreeHostImpl::FrameData* frame) {
586 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
587 DCHECK(!layer_tree_host_->output_surface_lost());
589 DrawResult draw_result;
590 bool draw_frame;
592 DebugScopedSetImplThread impl(this);
593 base::AutoReset<bool> mark_inside(&inside_draw_, true);
595 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
596 // frame, so can only be used when such a frame is possible. Since
597 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
598 // CanDraw() as well.
599 if (!ShouldComposite()) {
600 return DRAW_ABORTED_CANT_DRAW;
603 timing_history_.DidStartDrawing();
605 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
606 draw_frame = draw_result == DRAW_SUCCESS;
607 if (draw_frame)
608 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
609 layer_tree_host_impl_->DidDrawAllLayers(*frame);
611 bool start_ready_animations = draw_frame;
612 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
613 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
615 timing_history_.DidFinishDrawing();
618 if (draw_frame) {
619 DebugScopedSetImplThread impl(this);
621 // This CapturePostTasks should be destroyed before
622 // DidCommitAndDrawFrame() is called since that goes out to the
623 // embedder,
624 // and we want the embedder to receive its callbacks before that.
625 // NOTE: This maintains consistent ordering with the ThreadProxy since
626 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
627 // there as the main thread is not blocked, so any posted tasks inside
628 // the swap buffers will execute first.
629 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
631 BlockingTaskRunner::CapturePostTasks blocked(
632 blocking_main_thread_task_runner());
633 layer_tree_host_impl_->SwapBuffers(*frame);
635 DidCommitAndDrawFrame();
637 return draw_result;
640 void SingleThreadProxy::DidCommitAndDrawFrame() {
641 if (next_frame_is_newly_committed_frame_) {
642 DebugScopedSetMainThread main(this);
643 next_frame_is_newly_committed_frame_ = false;
644 layer_tree_host_->DidCommitAndDrawFrame();
648 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
649 return false;
652 void SingleThreadProxy::SetChildrenNeedBeginFrames(
653 bool children_need_begin_frames) {
654 scheduler_on_impl_thread_->SetChildrenNeedBeginFrames(
655 children_need_begin_frames);
658 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
659 layer_tree_host_impl_->WillBeginImplFrame(args);
662 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
663 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
664 // Although this proxy is single-threaded, it's problematic to synchronously
665 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
666 // could cause a commit to occur in between a series of SetNeedsCommit calls
667 // (i.e. property modifications) causing some to fall on one frame and some to
668 // fall on the next. Doing it asynchronously instead matches the semantics of
669 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
670 // synchronous commit.
671 MainThreadTaskRunner()->PostTask(
672 FROM_HERE,
673 base::Bind(&SingleThreadProxy::BeginMainFrame,
674 weak_factory_.GetWeakPtr()));
677 void SingleThreadProxy::BeginMainFrame() {
678 if (defer_commits_) {
679 DCHECK(!commit_was_deferred_);
680 commit_was_deferred_ = true;
681 layer_tree_host_->DidDeferCommit();
682 return;
685 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
686 // commit.
687 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
689 if (!layer_tree_host_->visible()) {
690 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
691 BeginMainFrameAbortedOnImplThread(
692 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
693 return;
696 if (layer_tree_host_->output_surface_lost()) {
697 TRACE_EVENT_INSTANT0(
698 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
699 BeginMainFrameAbortedOnImplThread(
700 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
701 return;
704 const BeginFrameArgs& begin_frame_args =
705 layer_tree_host_impl_->CurrentBeginFrameArgs();
706 DoBeginMainFrame(begin_frame_args);
709 void SingleThreadProxy::DoBeginMainFrame(
710 const BeginFrameArgs& begin_frame_args) {
711 layer_tree_host_->WillBeginMainFrame();
712 layer_tree_host_->BeginMainFrame(begin_frame_args);
713 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
714 layer_tree_host_->Layout();
716 if (PrioritizedResourceManager* contents_texture_manager =
717 layer_tree_host_->contents_texture_manager()) {
718 contents_texture_manager->UnlinkAndClearEvictedBackings();
719 contents_texture_manager->SetMaxMemoryLimitBytes(
720 layer_tree_host_impl_->memory_allocation_limit_bytes());
721 contents_texture_manager->SetExternalPriorityCutoff(
722 layer_tree_host_impl_->memory_allocation_priority_cutoff());
725 DCHECK(!queue_for_commit_);
726 queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue);
728 layer_tree_host_->UpdateLayers(queue_for_commit_.get());
730 timing_history_.DidBeginMainFrame();
732 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
733 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
734 // thread_proxy.cc
735 if (scheduler_on_impl_thread_) {
736 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
737 scheduler_on_impl_thread_->NotifyReadyToCommit();
741 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
742 CommitEarlyOutReason reason) {
743 DebugScopedSetImplThread impl(this);
744 DCHECK(scheduler_on_impl_thread_->CommitPending());
745 DCHECK(!layer_tree_host_impl_->pending_tree());
747 layer_tree_host_impl_->BeginMainFrameAborted(reason);
748 scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
751 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
752 DebugScopedSetImplThread impl(this);
753 LayerTreeHostImpl::FrameData frame;
754 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
755 &frame);
758 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
759 NOTREACHED();
760 return INVALID_RESULT;
763 void SingleThreadProxy::ScheduledActionCommit() {
764 DebugScopedSetMainThread main(this);
765 DoCommit();
768 void SingleThreadProxy::ScheduledActionAnimate() {
769 TRACE_EVENT0("cc", "ScheduledActionAnimate");
770 DebugScopedSetImplThread impl(this);
771 DoAnimate();
774 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
775 DebugScopedSetImplThread impl(this);
776 layer_tree_host_impl_->ActivateSyncTree();
779 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
780 DebugScopedSetMainThread main(this);
781 DCHECK(scheduler_on_impl_thread_);
782 // If possible, create the output surface in a post task. Synchronously
783 // creating the output surface makes tests more awkward since this differs
784 // from the ThreadProxy behavior. However, sometimes there is no
785 // task runner.
786 if (Proxy::MainThreadTaskRunner()) {
787 ScheduleRequestNewOutputSurface();
788 } else {
789 RequestNewOutputSurface();
793 void SingleThreadProxy::ScheduledActionPrepareTiles() {
794 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
795 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
796 DebugScopedSetImplThread impl(this);
797 layer_tree_host_impl_->PrepareTiles();
800 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
803 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
804 return timing_history_.DrawDurationEstimate();
807 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
808 return timing_history_.BeginMainFrameToCommitDurationEstimate();
811 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
812 return timing_history_.CommitToActivateDurationEstimate();
815 void SingleThreadProxy::DidBeginImplFrameDeadline() {
816 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
819 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
820 layer_tree_host_->SendBeginFramesToChildren(args);
823 } // namespace cc