Update Smart lock strings in chrome://settings.
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blob344dfb97f66df586e94ef01a0717426831627db9
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"
21 namespace cc {
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),
37 client_(client),
38 timing_history_(layer_tree_host->rendering_stats_instrumentation()),
39 next_frame_is_newly_committed_frame_(false),
40 inside_draw_(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),
46 weak_factory_(this) {
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
81 // nothing to do.
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,
88 scheduler_settings,
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_)
112 return;
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;
125 if (success) {
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);
135 if (success) {
136 if (scheduler_on_impl_thread_)
137 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
138 else if (!inside_synchronous_composite_)
139 SetNeedsCommit();
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();
155 SetNeedsCommit();
158 void SingleThreadProxy::SetNeedsUpdateLayers() {
159 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
160 DCHECK(Proxy::IsMainThread());
161 SetNeedsCommit();
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(
192 NULL,
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();
207 #if DCHECK_IS_ON
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);
214 #endif
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();
231 } else {
232 CommitComplete();
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_)
276 return;
277 if (defer_commits_ == defer_commits)
278 return;
280 if (defer_commits)
281 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
282 else
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;
288 BeginMainFrame();
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_)
302 return false;
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) {
328 TRACE_EVENT1(
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) {
379 TRACE_EVENT0(
380 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
381 DCHECK(Proxy::IsImplThread());
382 DebugScopedSetMainThread main(this);
383 layer_tree_host_->SetAnimationEvents(events.Pass());
386 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
387 size_t limit_bytes,
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)
397 return false;
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(
418 FROM_HERE,
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 DCHECK(!layer_tree_host_impl_->settings().impl_side_painting)
471 << "Impl-side painting and synchronous compositing are not supported.";
472 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
474 if (layer_tree_host_->output_surface_lost()) {
475 RequestNewOutputSurface();
476 // RequestNewOutputSurface could have synchronously created an output
477 // surface, so check again before returning.
478 if (layer_tree_host_->output_surface_lost())
479 return;
483 BeginFrameArgs begin_frame_args(
484 BeginFrameArgs::Create(frame_begin_time,
485 base::TimeTicks(),
486 BeginFrameArgs::DefaultInterval()));
487 DoBeginMainFrame(begin_frame_args);
488 DoCommit();
490 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
491 << "Commit should always succeed and transfer promises.";
495 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
496 LayerTreeHostImpl::FrameData frame;
497 DoComposite(frame_begin_time, &frame);
499 // DoComposite could abort, but because this is a synchronous composite
500 // another draw will never be scheduled, so break remaining promises.
501 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
502 SwapPromise::SWAP_FAILS);
506 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
507 // The following line casts away const modifiers because it is just
508 // setting debug state. We still want the AsValue() function and its
509 // call chain to be const throughout.
510 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
512 state->BeginDictionary("layer_tree_host_impl");
513 layer_tree_host_impl_->AsValueInto(state);
514 state->EndDictionary();
517 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
519 DebugScopedSetImplThread impl(this);
520 if (layer_tree_host_impl_->renderer()) {
521 DCHECK(!layer_tree_host_->output_surface_lost());
522 layer_tree_host_impl_->renderer()->DoNoOp();
527 bool SingleThreadProxy::SupportsImplScrolling() const {
528 return false;
531 bool SingleThreadProxy::ShouldComposite() const {
532 DCHECK(Proxy::IsImplThread());
533 return layer_tree_host_impl_->visible() &&
534 layer_tree_host_impl_->CanDraw();
537 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
538 DCHECK(Proxy::IsImplThread());
539 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
540 !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
543 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
544 if (output_surface_creation_callback_.IsCancelled() &&
545 !output_surface_creation_requested_) {
546 output_surface_creation_callback_.Reset(
547 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
548 weak_factory_.GetWeakPtr()));
549 MainThreadTaskRunner()->PostTask(
550 FROM_HERE, output_surface_creation_callback_.callback());
554 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
555 LayerTreeHostImpl::FrameData* frame) {
556 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
557 DCHECK(!layer_tree_host_->output_surface_lost());
559 DrawResult draw_result;
560 bool draw_frame;
562 DebugScopedSetImplThread impl(this);
563 base::AutoReset<bool> mark_inside(&inside_draw_, true);
565 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
566 // frame, so can only be used when such a frame is possible. Since
567 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
568 // CanDraw() as well.
569 if (!ShouldComposite()) {
570 UpdateBackgroundAnimateTicking();
571 return DRAW_ABORTED_CANT_DRAW;
574 timing_history_.DidStartDrawing();
576 layer_tree_host_impl_->Animate(
577 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
578 UpdateBackgroundAnimateTicking();
580 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
581 draw_frame = draw_result == DRAW_SUCCESS;
582 if (draw_frame)
583 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
584 layer_tree_host_impl_->DidDrawAllLayers(*frame);
586 bool start_ready_animations = draw_frame;
587 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
588 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
590 timing_history_.DidFinishDrawing();
593 if (draw_frame) {
594 DebugScopedSetImplThread impl(this);
596 // This CapturePostTasks should be destroyed before
597 // DidCommitAndDrawFrame() is called since that goes out to the
598 // embedder,
599 // and we want the embedder to receive its callbacks before that.
600 // NOTE: This maintains consistent ordering with the ThreadProxy since
601 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
602 // there as the main thread is not blocked, so any posted tasks inside
603 // the swap buffers will execute first.
604 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
606 BlockingTaskRunner::CapturePostTasks blocked(
607 blocking_main_thread_task_runner());
608 layer_tree_host_impl_->SwapBuffers(*frame);
610 DidCommitAndDrawFrame();
612 return draw_result;
615 void SingleThreadProxy::DidCommitAndDrawFrame() {
616 if (next_frame_is_newly_committed_frame_) {
617 DebugScopedSetMainThread main(this);
618 next_frame_is_newly_committed_frame_ = false;
619 layer_tree_host_->DidCommitAndDrawFrame();
623 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
624 return false;
627 BeginFrameSource* SingleThreadProxy::ExternalBeginFrameSource() {
628 return layer_tree_host_impl_.get();
631 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
632 layer_tree_host_impl_->WillBeginImplFrame(args);
635 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
636 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
637 // Although this proxy is single-threaded, it's problematic to synchronously
638 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
639 // could cause a commit to occur in between a series of SetNeedsCommit calls
640 // (i.e. property modifications) causing some to fall on one frame and some to
641 // fall on the next. Doing it asynchronously instead matches the semantics of
642 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
643 // synchronous commit.
644 MainThreadTaskRunner()->PostTask(
645 FROM_HERE,
646 base::Bind(&SingleThreadProxy::BeginMainFrame,
647 weak_factory_.GetWeakPtr()));
650 void SingleThreadProxy::BeginMainFrame() {
651 if (defer_commits_) {
652 DCHECK(!commit_was_deferred_);
653 commit_was_deferred_ = true;
654 layer_tree_host_->DidDeferCommit();
655 return;
658 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
659 // commit.
660 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
662 if (!layer_tree_host_->visible()) {
663 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
664 BeginMainFrameAbortedOnImplThread();
665 return;
668 if (layer_tree_host_->output_surface_lost()) {
669 TRACE_EVENT_INSTANT0(
670 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
671 BeginMainFrameAbortedOnImplThread();
672 return;
675 const BeginFrameArgs& begin_frame_args =
676 layer_tree_host_impl_->CurrentBeginFrameArgs();
677 DoBeginMainFrame(begin_frame_args);
680 void SingleThreadProxy::DoBeginMainFrame(
681 const BeginFrameArgs& begin_frame_args) {
682 layer_tree_host_->WillBeginMainFrame();
683 layer_tree_host_->BeginMainFrame(begin_frame_args);
684 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
685 layer_tree_host_->Layout();
687 if (PrioritizedResourceManager* contents_texture_manager =
688 layer_tree_host_->contents_texture_manager()) {
689 contents_texture_manager->UnlinkAndClearEvictedBackings();
690 contents_texture_manager->SetMaxMemoryLimitBytes(
691 layer_tree_host_impl_->memory_allocation_limit_bytes());
692 contents_texture_manager->SetExternalPriorityCutoff(
693 layer_tree_host_impl_->memory_allocation_priority_cutoff());
696 DCHECK(!queue_for_commit_);
697 queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue);
699 layer_tree_host_->UpdateLayers(queue_for_commit_.get());
701 timing_history_.DidBeginMainFrame();
703 if (scheduler_on_impl_thread_) {
704 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
705 scheduler_on_impl_thread_->NotifyReadyToCommit();
709 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread() {
710 DebugScopedSetImplThread impl(this);
711 DCHECK(scheduler_on_impl_thread_->CommitPending());
712 DCHECK(!layer_tree_host_impl_->pending_tree());
714 // TODO(enne): SingleThreadProxy does not support cancelling commits yet so
715 // did_handle is always false.
716 bool did_handle = false;
717 layer_tree_host_impl_->BeginMainFrameAborted(did_handle);
718 scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle);
721 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
722 DebugScopedSetImplThread impl(this);
723 LayerTreeHostImpl::FrameData frame;
724 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
725 &frame);
728 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
729 NOTREACHED();
730 return INVALID_RESULT;
733 void SingleThreadProxy::ScheduledActionCommit() {
734 DebugScopedSetMainThread main(this);
735 DoCommit();
738 void SingleThreadProxy::ScheduledActionAnimate() {
739 TRACE_EVENT0("cc", "ScheduledActionAnimate");
740 layer_tree_host_impl_->Animate(
741 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
744 void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() {
745 DebugScopedSetImplThread impl(this);
746 layer_tree_host_impl_->UpdateVisibleTiles();
749 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
750 DebugScopedSetImplThread impl(this);
751 layer_tree_host_impl_->ActivateSyncTree();
754 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
755 DebugScopedSetMainThread main(this);
756 DCHECK(scheduler_on_impl_thread_);
757 // If possible, create the output surface in a post task. Synchronously
758 // creating the output surface makes tests more awkward since this differs
759 // from the ThreadProxy behavior. However, sometimes there is no
760 // task runner.
761 if (Proxy::MainThreadTaskRunner()) {
762 ScheduleRequestNewOutputSurface();
763 } else {
764 RequestNewOutputSurface();
768 void SingleThreadProxy::ScheduledActionManageTiles() {
769 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionManageTiles");
770 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
771 DebugScopedSetImplThread impl(this);
772 layer_tree_host_impl_->ManageTiles();
775 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
778 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
779 return timing_history_.DrawDurationEstimate();
782 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
783 return timing_history_.BeginMainFrameToCommitDurationEstimate();
786 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
787 return timing_history_.CommitToActivateDurationEstimate();
790 void SingleThreadProxy::DidBeginImplFrameDeadline() {
791 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
794 } // namespace cc