Support HTTP/2 drafts 14 and 15 simultaneously.
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blobf15c7ec269256105167466e691e5d94d306d60a4
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 scoped_ptr<BeginFrameSource> external_begin_frame_source) {
28 return make_scoped_ptr(new SingleThreadProxy(
29 layer_tree_host,
30 client,
31 main_task_runner,
32 external_begin_frame_source.Pass()));
35 SingleThreadProxy::SingleThreadProxy(
36 LayerTreeHost* layer_tree_host,
37 LayerTreeHostSingleThreadClient* client,
38 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
39 scoped_ptr<BeginFrameSource> external_begin_frame_source)
40 : Proxy(main_task_runner, NULL),
41 layer_tree_host_(layer_tree_host),
42 client_(client),
43 timing_history_(layer_tree_host->rendering_stats_instrumentation()),
44 next_frame_is_newly_committed_frame_(false),
45 inside_draw_(false),
46 defer_commits_(false),
47 commit_was_deferred_(false),
48 commit_requested_(false),
49 inside_synchronous_composite_(false),
50 output_surface_creation_requested_(false),
51 external_begin_frame_source_(external_begin_frame_source.Pass()),
52 weak_factory_(this) {
53 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
54 DCHECK(Proxy::IsMainThread());
55 DCHECK(layer_tree_host);
58 void SingleThreadProxy::Start() {
59 DebugScopedSetImplThread impl(this);
60 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
63 SingleThreadProxy::~SingleThreadProxy() {
64 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
65 DCHECK(Proxy::IsMainThread());
66 // Make sure Stop() got called or never Started.
67 DCHECK(!layer_tree_host_impl_);
70 void SingleThreadProxy::FinishAllRendering() {
71 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
72 DCHECK(Proxy::IsMainThread());
74 DebugScopedSetImplThread impl(this);
75 layer_tree_host_impl_->FinishAllRendering();
79 bool SingleThreadProxy::IsStarted() const {
80 DCHECK(Proxy::IsMainThread());
81 return layer_tree_host_impl_;
84 void SingleThreadProxy::SetLayerTreeHostClientReady() {
85 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
86 // Scheduling is controlled by the embedder in the single thread case, so
87 // nothing to do.
88 DCHECK(Proxy::IsMainThread());
89 DebugScopedSetImplThread impl(this);
90 if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
91 !scheduler_on_impl_thread_) {
92 SchedulerSettings scheduler_settings(layer_tree_host_->settings());
93 scheduler_on_impl_thread_ =
94 Scheduler::Create(this,
95 scheduler_settings,
96 layer_tree_host_->id(),
97 MainThreadTaskRunner(),
98 base::PowerMonitor::Get(),
99 external_begin_frame_source_.Pass());
100 scheduler_on_impl_thread_->SetCanStart();
101 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
105 void SingleThreadProxy::SetVisible(bool visible) {
106 TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
107 DebugScopedSetImplThread impl(this);
108 layer_tree_host_impl_->SetVisible(visible);
109 if (scheduler_on_impl_thread_)
110 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
111 // Changing visibility could change ShouldComposite().
114 void SingleThreadProxy::RequestNewOutputSurface() {
115 DCHECK(Proxy::IsMainThread());
116 DCHECK(layer_tree_host_->output_surface_lost());
117 output_surface_creation_callback_.Cancel();
118 if (output_surface_creation_requested_)
119 return;
120 output_surface_creation_requested_ = true;
121 layer_tree_host_->RequestNewOutputSurface();
124 void SingleThreadProxy::SetOutputSurface(
125 scoped_ptr<OutputSurface> output_surface) {
126 DCHECK(Proxy::IsMainThread());
127 DCHECK(layer_tree_host_->output_surface_lost());
128 output_surface_creation_requested_ = false;
129 renderer_capabilities_for_main_thread_ = RendererCapabilities();
131 bool success = !!output_surface;
132 if (success) {
133 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
134 DebugScopedSetImplThread impl(this);
135 layer_tree_host_->DeleteContentsTexturesOnImplThread(
136 layer_tree_host_impl_->resource_provider());
137 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
140 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
142 if (success) {
143 if (scheduler_on_impl_thread_)
144 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
145 else if (!inside_synchronous_composite_)
146 SetNeedsCommit();
147 } else if (Proxy::MainThreadTaskRunner()) {
148 ScheduleRequestNewOutputSurface();
152 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
153 DCHECK(Proxy::IsMainThread());
154 DCHECK(!layer_tree_host_->output_surface_lost());
155 return renderer_capabilities_for_main_thread_;
158 void SingleThreadProxy::SetNeedsAnimate() {
159 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
160 DCHECK(Proxy::IsMainThread());
161 client_->ScheduleAnimation();
162 SetNeedsCommit();
165 void SingleThreadProxy::SetNeedsUpdateLayers() {
166 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
167 DCHECK(Proxy::IsMainThread());
168 SetNeedsCommit();
171 void SingleThreadProxy::DoAnimate() {
172 // Don't animate if there is no root layer.
173 // TODO(mithro): Both Animate and UpdateAnimationState already have a
174 // "!active_tree_->root_layer()" check?
175 if (!layer_tree_host_impl_->active_tree()->root_layer()) {
176 return;
179 layer_tree_host_impl_->Animate(
180 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
182 // If animations are not visible, update the animation state now as it
183 // won't happen in DoComposite.
184 if (!layer_tree_host_impl_->AnimationsAreVisible()) {
185 layer_tree_host_impl_->UpdateAnimationState(true);
189 void SingleThreadProxy::DoCommit() {
190 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
191 DCHECK(Proxy::IsMainThread());
193 commit_requested_ = false;
194 layer_tree_host_->WillCommit();
196 // Commit immediately.
198 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
199 DebugScopedSetImplThread impl(this);
201 // This CapturePostTasks should be destroyed before CommitComplete() is
202 // called since that goes out to the embedder, and we want the embedder
203 // to receive its callbacks before that.
204 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks(
205 blocking_main_thread_task_runner()));
207 layer_tree_host_impl_->BeginCommit();
209 if (PrioritizedResourceManager* contents_texture_manager =
210 layer_tree_host_->contents_texture_manager()) {
211 contents_texture_manager->PushTexturePrioritiesToBackings();
213 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
215 scoped_ptr<ResourceUpdateController> update_controller =
216 ResourceUpdateController::Create(
217 NULL,
218 MainThreadTaskRunner(),
219 queue_for_commit_.Pass(),
220 layer_tree_host_impl_->resource_provider());
221 update_controller->Finalize();
223 if (layer_tree_host_impl_->EvictedUIResourcesExist())
224 layer_tree_host_->RecreateUIResources();
226 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
228 layer_tree_host_impl_->CommitComplete();
230 #if DCHECK_IS_ON
231 // In the single-threaded case, the scale and scroll deltas should never be
232 // touched on the impl layer tree.
233 scoped_ptr<ScrollAndScaleSet> scroll_info =
234 layer_tree_host_impl_->ProcessScrollDeltas();
235 DCHECK(!scroll_info->scrolls.size());
236 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
237 #endif
240 if (layer_tree_host_->settings().impl_side_painting) {
241 // TODO(enne): just commit directly to the active tree.
243 // Synchronously activate during commit to satisfy any potential
244 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
245 // might not be ready to draw, so DidActivateSyncTree must set
246 // the flag to force the tree to not draw until textures are ready.
247 NotifyReadyToActivate();
248 } else {
249 CommitComplete();
253 void SingleThreadProxy::CommitComplete() {
254 DCHECK(!layer_tree_host_impl_->pending_tree())
255 << "Activation is expected to have synchronously occurred by now.";
256 DCHECK(commit_blocking_task_runner_);
258 DebugScopedSetMainThread main(this);
259 commit_blocking_task_runner_.reset();
260 layer_tree_host_->CommitComplete();
261 layer_tree_host_->DidBeginMainFrame();
262 timing_history_.DidCommit();
264 next_frame_is_newly_committed_frame_ = true;
267 void SingleThreadProxy::SetNeedsCommit() {
268 DCHECK(Proxy::IsMainThread());
269 DebugScopedSetImplThread impl(this);
270 client_->ScheduleComposite();
271 if (scheduler_on_impl_thread_)
272 scheduler_on_impl_thread_->SetNeedsCommit();
273 commit_requested_ = true;
276 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
277 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
278 DCHECK(Proxy::IsMainThread());
279 DebugScopedSetImplThread impl(this);
280 client_->ScheduleComposite();
281 SetNeedsRedrawRectOnImplThread(damage_rect);
284 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
285 // Activation always forced in commit, so nothing to do.
286 DCHECK(Proxy::IsMainThread());
289 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
290 DCHECK(Proxy::IsMainThread());
291 // Deferring commits only makes sense if there's a scheduler.
292 if (!scheduler_on_impl_thread_)
293 return;
294 if (defer_commits_ == defer_commits)
295 return;
297 if (defer_commits)
298 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
299 else
300 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
302 defer_commits_ = defer_commits;
303 if (!defer_commits_ && commit_was_deferred_) {
304 commit_was_deferred_ = false;
305 BeginMainFrame();
309 bool SingleThreadProxy::CommitRequested() const {
310 DCHECK(Proxy::IsMainThread());
311 return commit_requested_;
314 bool SingleThreadProxy::BeginMainFrameRequested() const {
315 DCHECK(Proxy::IsMainThread());
316 // If there is no scheduler, then there can be no pending begin frame,
317 // as all frames are all manually initiated by the embedder of cc.
318 if (!scheduler_on_impl_thread_)
319 return false;
320 return commit_requested_;
323 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
324 return std::numeric_limits<size_t>::max();
327 void SingleThreadProxy::Stop() {
328 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
329 DCHECK(Proxy::IsMainThread());
331 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
332 DebugScopedSetImplThread impl(this);
334 BlockingTaskRunner::CapturePostTasks blocked(
335 blocking_main_thread_task_runner());
336 layer_tree_host_->DeleteContentsTexturesOnImplThread(
337 layer_tree_host_impl_->resource_provider());
338 scheduler_on_impl_thread_ = nullptr;
339 layer_tree_host_impl_ = nullptr;
341 layer_tree_host_ = NULL;
344 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
345 TRACE_EVENT1(
346 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
347 DCHECK(Proxy::IsImplThread());
348 if (scheduler_on_impl_thread_)
349 scheduler_on_impl_thread_->SetCanDraw(can_draw);
352 void SingleThreadProxy::NotifyReadyToActivate() {
353 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
354 DebugScopedSetImplThread impl(this);
355 if (scheduler_on_impl_thread_)
356 scheduler_on_impl_thread_->NotifyReadyToActivate();
359 void SingleThreadProxy::NotifyReadyToDraw() {
362 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
363 client_->ScheduleComposite();
364 if (scheduler_on_impl_thread_)
365 scheduler_on_impl_thread_->SetNeedsRedraw();
368 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
369 client_->ScheduleComposite();
370 if (scheduler_on_impl_thread_)
371 scheduler_on_impl_thread_->SetNeedsAnimate();
374 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
375 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsManageTilesOnImplThread");
376 if (scheduler_on_impl_thread_)
377 scheduler_on_impl_thread_->SetNeedsManageTiles();
380 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
381 const gfx::Rect& damage_rect) {
382 layer_tree_host_impl_->SetViewportDamage(damage_rect);
383 SetNeedsRedrawOnImplThread();
386 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
387 TRACE_EVENT0("cc", "SingleThreadProxy::DidInitializeVisibleTileOnImplThread");
388 if (scheduler_on_impl_thread_)
389 scheduler_on_impl_thread_->SetNeedsRedraw();
392 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
393 client_->ScheduleComposite();
394 if (scheduler_on_impl_thread_)
395 scheduler_on_impl_thread_->SetNeedsCommit();
398 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
399 scoped_ptr<AnimationEventsVector> events) {
400 TRACE_EVENT0(
401 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
402 DCHECK(Proxy::IsImplThread());
403 DebugScopedSetMainThread main(this);
404 layer_tree_host_->SetAnimationEvents(events.Pass());
407 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
408 size_t limit_bytes,
409 int priority_cutoff) {
410 DCHECK(IsImplThread());
411 PrioritizedResourceManager* contents_texture_manager =
412 layer_tree_host_->contents_texture_manager();
414 ResourceProvider* resource_provider =
415 layer_tree_host_impl_->resource_provider();
417 if (!contents_texture_manager || !resource_provider)
418 return false;
420 return contents_texture_manager->ReduceMemoryOnImplThread(
421 limit_bytes, priority_cutoff, resource_provider);
424 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
426 void SingleThreadProxy::DidActivateSyncTree() {
427 // Non-impl-side painting finishes commit in DoCommit. Impl-side painting
428 // defers until here to simulate SetNextCommitWaitsForActivation.
429 if (layer_tree_host_impl_->settings().impl_side_painting) {
430 // This is required because NotifyReadyToActivate gets called when
431 // the pending tree is not actually ready in the SingleThreadProxy.
432 layer_tree_host_impl_->SetRequiresHighResToDraw();
434 // Since activation could cause tasks to run, post CommitComplete
435 // separately so that it runs after these tasks. This is the loose
436 // equivalent of blocking commit until activation and also running
437 // all tasks posted during commit/activation before CommitComplete.
438 MainThreadTaskRunner()->PostTask(
439 FROM_HERE,
440 base::Bind(&SingleThreadProxy::CommitComplete,
441 weak_factory_.GetWeakPtr()));
444 timing_history_.DidActivateSyncTree();
447 void SingleThreadProxy::DidManageTiles() {
448 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
449 DCHECK(Proxy::IsImplThread());
450 if (scheduler_on_impl_thread_)
451 scheduler_on_impl_thread_->DidManageTiles();
454 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
455 DCHECK(IsImplThread());
456 renderer_capabilities_for_main_thread_ =
457 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
460 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
461 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
463 DebugScopedSetMainThread main(this);
464 // This must happen before we notify the scheduler as it may try to recreate
465 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
466 layer_tree_host_->DidLoseOutputSurface();
468 client_->DidAbortSwapBuffers();
469 if (scheduler_on_impl_thread_)
470 scheduler_on_impl_thread_->DidLoseOutputSurface();
473 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
474 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
475 if (scheduler_on_impl_thread_)
476 scheduler_on_impl_thread_->DidSwapBuffers();
477 client_->DidPostSwapBuffers();
480 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
481 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
482 if (scheduler_on_impl_thread_)
483 scheduler_on_impl_thread_->DidSwapBuffersComplete();
484 layer_tree_host_->DidCompleteSwapBuffers();
487 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
488 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
489 DCHECK(Proxy::IsMainThread());
490 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
492 if (layer_tree_host_->output_surface_lost()) {
493 RequestNewOutputSurface();
494 // RequestNewOutputSurface could have synchronously created an output
495 // surface, so check again before returning.
496 if (layer_tree_host_->output_surface_lost())
497 return;
501 BeginFrameArgs begin_frame_args(
502 BeginFrameArgs::Create(frame_begin_time,
503 base::TimeTicks(),
504 BeginFrameArgs::DefaultInterval()));
505 DoBeginMainFrame(begin_frame_args);
506 DoCommit();
508 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises())
509 << "Commit should always succeed and transfer promises.";
513 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
514 if (layer_tree_host_impl_->settings().impl_side_painting) {
515 layer_tree_host_impl_->ActivateSyncTree();
516 layer_tree_host_impl_->active_tree()->UpdateDrawProperties();
517 layer_tree_host_impl_->ManageTiles();
518 layer_tree_host_impl_->SynchronouslyInitializeAllTiles();
521 DoAnimate();
523 LayerTreeHostImpl::FrameData frame;
524 DoComposite(frame_begin_time, &frame);
526 // DoComposite could abort, but because this is a synchronous composite
527 // another draw will never be scheduled, so break remaining promises.
528 layer_tree_host_impl_->active_tree()->BreakSwapPromises(
529 SwapPromise::SWAP_FAILS);
533 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
534 // The following line casts away const modifiers because it is just
535 // setting debug state. We still want the AsValue() function and its
536 // call chain to be const throughout.
537 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
539 state->BeginDictionary("layer_tree_host_impl");
540 layer_tree_host_impl_->AsValueInto(state);
541 state->EndDictionary();
544 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
546 DebugScopedSetImplThread impl(this);
547 if (layer_tree_host_impl_->renderer()) {
548 DCHECK(!layer_tree_host_->output_surface_lost());
549 layer_tree_host_impl_->renderer()->DoNoOp();
554 bool SingleThreadProxy::SupportsImplScrolling() const {
555 return false;
558 bool SingleThreadProxy::ShouldComposite() const {
559 DCHECK(Proxy::IsImplThread());
560 return layer_tree_host_impl_->visible() &&
561 layer_tree_host_impl_->CanDraw();
564 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
565 if (output_surface_creation_callback_.IsCancelled() &&
566 !output_surface_creation_requested_) {
567 output_surface_creation_callback_.Reset(
568 base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
569 weak_factory_.GetWeakPtr()));
570 MainThreadTaskRunner()->PostTask(
571 FROM_HERE, output_surface_creation_callback_.callback());
575 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
576 LayerTreeHostImpl::FrameData* frame) {
577 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
578 DCHECK(!layer_tree_host_->output_surface_lost());
580 DrawResult draw_result;
581 bool draw_frame;
583 DebugScopedSetImplThread impl(this);
584 base::AutoReset<bool> mark_inside(&inside_draw_, true);
586 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
587 // frame, so can only be used when such a frame is possible. Since
588 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
589 // CanDraw() as well.
590 if (!ShouldComposite()) {
591 return DRAW_ABORTED_CANT_DRAW;
594 timing_history_.DidStartDrawing();
596 draw_result = layer_tree_host_impl_->PrepareToDraw(frame);
597 draw_frame = draw_result == DRAW_SUCCESS;
598 if (draw_frame)
599 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
600 layer_tree_host_impl_->DidDrawAllLayers(*frame);
602 bool start_ready_animations = draw_frame;
603 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
604 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
606 timing_history_.DidFinishDrawing();
609 if (draw_frame) {
610 DebugScopedSetImplThread impl(this);
612 // This CapturePostTasks should be destroyed before
613 // DidCommitAndDrawFrame() is called since that goes out to the
614 // embedder,
615 // and we want the embedder to receive its callbacks before that.
616 // NOTE: This maintains consistent ordering with the ThreadProxy since
617 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
618 // there as the main thread is not blocked, so any posted tasks inside
619 // the swap buffers will execute first.
620 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
622 BlockingTaskRunner::CapturePostTasks blocked(
623 blocking_main_thread_task_runner());
624 layer_tree_host_impl_->SwapBuffers(*frame);
626 DidCommitAndDrawFrame();
628 return draw_result;
631 void SingleThreadProxy::DidCommitAndDrawFrame() {
632 if (next_frame_is_newly_committed_frame_) {
633 DebugScopedSetMainThread main(this);
634 next_frame_is_newly_committed_frame_ = false;
635 layer_tree_host_->DidCommitAndDrawFrame();
639 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
640 return false;
643 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
644 layer_tree_host_impl_->WillBeginImplFrame(args);
647 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
648 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
649 // Although this proxy is single-threaded, it's problematic to synchronously
650 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
651 // could cause a commit to occur in between a series of SetNeedsCommit calls
652 // (i.e. property modifications) causing some to fall on one frame and some to
653 // fall on the next. Doing it asynchronously instead matches the semantics of
654 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
655 // synchronous commit.
656 MainThreadTaskRunner()->PostTask(
657 FROM_HERE,
658 base::Bind(&SingleThreadProxy::BeginMainFrame,
659 weak_factory_.GetWeakPtr()));
662 void SingleThreadProxy::BeginMainFrame() {
663 if (defer_commits_) {
664 DCHECK(!commit_was_deferred_);
665 commit_was_deferred_ = true;
666 layer_tree_host_->DidDeferCommit();
667 return;
670 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
671 // commit.
672 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
674 if (!layer_tree_host_->visible()) {
675 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
676 BeginMainFrameAbortedOnImplThread();
677 return;
680 if (layer_tree_host_->output_surface_lost()) {
681 TRACE_EVENT_INSTANT0(
682 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
683 BeginMainFrameAbortedOnImplThread();
684 return;
687 const BeginFrameArgs& begin_frame_args =
688 layer_tree_host_impl_->CurrentBeginFrameArgs();
689 DoBeginMainFrame(begin_frame_args);
692 void SingleThreadProxy::DoBeginMainFrame(
693 const BeginFrameArgs& begin_frame_args) {
694 layer_tree_host_->WillBeginMainFrame();
695 layer_tree_host_->BeginMainFrame(begin_frame_args);
696 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
697 layer_tree_host_->Layout();
699 if (PrioritizedResourceManager* contents_texture_manager =
700 layer_tree_host_->contents_texture_manager()) {
701 contents_texture_manager->UnlinkAndClearEvictedBackings();
702 contents_texture_manager->SetMaxMemoryLimitBytes(
703 layer_tree_host_impl_->memory_allocation_limit_bytes());
704 contents_texture_manager->SetExternalPriorityCutoff(
705 layer_tree_host_impl_->memory_allocation_priority_cutoff());
708 DCHECK(!queue_for_commit_);
709 queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue);
711 layer_tree_host_->UpdateLayers(queue_for_commit_.get());
713 timing_history_.DidBeginMainFrame();
715 if (scheduler_on_impl_thread_) {
716 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
717 scheduler_on_impl_thread_->NotifyReadyToCommit();
721 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread() {
722 DebugScopedSetImplThread impl(this);
723 DCHECK(scheduler_on_impl_thread_->CommitPending());
724 DCHECK(!layer_tree_host_impl_->pending_tree());
726 // TODO(enne): SingleThreadProxy does not support cancelling commits yet so
727 // did_handle is always false.
728 bool did_handle = false;
729 layer_tree_host_impl_->BeginMainFrameAborted(did_handle);
730 scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle);
733 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
734 DebugScopedSetImplThread impl(this);
735 LayerTreeHostImpl::FrameData frame;
736 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
737 &frame);
740 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
741 NOTREACHED();
742 return INVALID_RESULT;
745 void SingleThreadProxy::ScheduledActionCommit() {
746 DebugScopedSetMainThread main(this);
747 DoCommit();
750 void SingleThreadProxy::ScheduledActionAnimate() {
751 TRACE_EVENT0("cc", "ScheduledActionAnimate");
752 DebugScopedSetImplThread impl(this);
753 DoAnimate();
756 void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() {
757 DebugScopedSetImplThread impl(this);
758 layer_tree_host_impl_->UpdateVisibleTiles();
761 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
762 DebugScopedSetImplThread impl(this);
763 layer_tree_host_impl_->ActivateSyncTree();
766 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
767 DebugScopedSetMainThread main(this);
768 DCHECK(scheduler_on_impl_thread_);
769 // If possible, create the output surface in a post task. Synchronously
770 // creating the output surface makes tests more awkward since this differs
771 // from the ThreadProxy behavior. However, sometimes there is no
772 // task runner.
773 if (Proxy::MainThreadTaskRunner()) {
774 ScheduleRequestNewOutputSurface();
775 } else {
776 RequestNewOutputSurface();
780 void SingleThreadProxy::ScheduledActionManageTiles() {
781 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionManageTiles");
782 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
783 DebugScopedSetImplThread impl(this);
784 layer_tree_host_impl_->ManageTiles();
787 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
790 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
791 return timing_history_.DrawDurationEstimate();
794 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
795 return timing_history_.BeginMainFrameToCommitDurationEstimate();
798 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
799 return timing_history_.CommitToActivateDurationEstimate();
802 void SingleThreadProxy::DidBeginImplFrameDeadline() {
803 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
806 } // namespace cc