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 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())
483 BeginFrameArgs
begin_frame_args(
484 BeginFrameArgs::Create(frame_begin_time
,
486 BeginFrameArgs::DefaultInterval()));
487 DoBeginMainFrame(begin_frame_args
);
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 {
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
;
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
;
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();
594 DebugScopedSetImplThread
impl(this);
596 // This CapturePostTasks should be destroyed before
597 // DidCommitAndDrawFrame() is called since that goes out to the
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();
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() {
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(
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();
658 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
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();
668 if (layer_tree_host_
->output_surface_lost()) {
669 TRACE_EVENT_INSTANT0(
670 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD
);
671 BeginMainFrameAbortedOnImplThread();
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
,
728 DrawResult
SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
730 return INVALID_RESULT
;
733 void SingleThreadProxy::ScheduledActionCommit() {
734 DebugScopedSetMainThread
main(this);
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
761 if (Proxy::MainThreadTaskRunner()) {
762 ScheduleRequestNewOutputSurface();
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();