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/profiler/scoped_tracker.h"
9 #include "base/trace_event/trace_event.h"
10 #include "cc/debug/benchmark_instrumentation.h"
11 #include "cc/debug/devtools_instrumentation.h"
12 #include "cc/output/context_provider.h"
13 #include "cc/output/output_surface.h"
14 #include "cc/quads/draw_quad.h"
15 #include "cc/resources/prioritized_resource_manager.h"
16 #include "cc/resources/resource_update_controller.h"
17 #include "cc/scheduler/commit_earlyout_reason.h"
18 #include "cc/trees/layer_tree_host.h"
19 #include "cc/trees/layer_tree_host_single_thread_client.h"
20 #include "cc/trees/layer_tree_impl.h"
21 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
22 #include "ui/gfx/frame_time.h"
26 scoped_ptr
<Proxy
> SingleThreadProxy::Create(
27 LayerTreeHost
* layer_tree_host
,
28 LayerTreeHostSingleThreadClient
* client
,
29 scoped_refptr
<base::SingleThreadTaskRunner
> main_task_runner
,
30 scoped_ptr
<BeginFrameSource
> external_begin_frame_source
) {
31 return make_scoped_ptr(new SingleThreadProxy(
35 external_begin_frame_source
.Pass()));
38 SingleThreadProxy::SingleThreadProxy(
39 LayerTreeHost
* layer_tree_host
,
40 LayerTreeHostSingleThreadClient
* client
,
41 scoped_refptr
<base::SingleThreadTaskRunner
> main_task_runner
,
42 scoped_ptr
<BeginFrameSource
> external_begin_frame_source
)
43 : Proxy(main_task_runner
, NULL
),
44 layer_tree_host_(layer_tree_host
),
46 timing_history_(layer_tree_host
->rendering_stats_instrumentation()),
47 next_frame_is_newly_committed_frame_(false),
49 defer_commits_(false),
50 commit_requested_(false),
51 inside_synchronous_composite_(false),
52 output_surface_creation_requested_(false),
53 external_begin_frame_source_(external_begin_frame_source
.Pass()),
55 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
56 DCHECK(Proxy::IsMainThread());
57 DCHECK(layer_tree_host
);
60 void SingleThreadProxy::Start() {
61 DebugScopedSetImplThread
impl(this);
62 layer_tree_host_impl_
= layer_tree_host_
->CreateLayerTreeHostImpl(this);
65 SingleThreadProxy::~SingleThreadProxy() {
66 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
67 DCHECK(Proxy::IsMainThread());
68 // Make sure Stop() got called or never Started.
69 DCHECK(!layer_tree_host_impl_
);
72 void SingleThreadProxy::FinishAllRendering() {
73 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
74 DCHECK(Proxy::IsMainThread());
76 DebugScopedSetImplThread
impl(this);
77 layer_tree_host_impl_
->FinishAllRendering();
81 bool SingleThreadProxy::IsStarted() const {
82 DCHECK(Proxy::IsMainThread());
83 return layer_tree_host_impl_
;
86 bool SingleThreadProxy::CommitToActiveTree() const {
87 // With SingleThreadProxy we skip the pending tree and commit directly to the
92 void SingleThreadProxy::SetLayerTreeHostClientReady() {
93 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
94 // Scheduling is controlled by the embedder in the single thread case, so
96 DCHECK(Proxy::IsMainThread());
97 DebugScopedSetImplThread
impl(this);
98 if (layer_tree_host_
->settings().single_thread_proxy_scheduler
&&
99 !scheduler_on_impl_thread_
) {
100 SchedulerSettings
scheduler_settings(
101 layer_tree_host_
->settings().ToSchedulerSettings());
102 // SingleThreadProxy should run in main thread low latency mode.
103 scheduler_settings
.main_thread_should_always_be_low_latency
= true;
104 scheduler_on_impl_thread_
=
105 Scheduler::Create(this,
107 layer_tree_host_
->id(),
108 MainThreadTaskRunner(),
109 external_begin_frame_source_
.Pass());
110 scheduler_on_impl_thread_
->SetCanStart();
111 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
115 void SingleThreadProxy::SetVisible(bool visible
) {
116 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible
);
117 DebugScopedSetImplThread
impl(this);
118 layer_tree_host_impl_
->SetVisible(visible
);
119 if (scheduler_on_impl_thread_
)
120 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
121 // Changing visibility could change ShouldComposite().
124 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle
) {
125 TRACE_EVENT1("cc", "SingleThreadProxy::SetThrottleFrameProduction",
126 "throttle", throttle
);
127 DebugScopedSetImplThread
impl(this);
128 if (scheduler_on_impl_thread_
)
129 scheduler_on_impl_thread_
->SetThrottleFrameProduction(throttle
);
132 void SingleThreadProxy::RequestNewOutputSurface() {
133 DCHECK(Proxy::IsMainThread());
134 DCHECK(layer_tree_host_
->output_surface_lost());
135 output_surface_creation_callback_
.Cancel();
136 if (output_surface_creation_requested_
)
138 output_surface_creation_requested_
= true;
139 layer_tree_host_
->RequestNewOutputSurface();
142 void SingleThreadProxy::SetOutputSurface(
143 scoped_ptr
<OutputSurface
> output_surface
) {
144 DCHECK(Proxy::IsMainThread());
145 DCHECK(layer_tree_host_
->output_surface_lost());
146 DCHECK(output_surface_creation_requested_
);
147 renderer_capabilities_for_main_thread_
= RendererCapabilities();
151 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
152 DebugScopedSetImplThread
impl(this);
153 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
154 layer_tree_host_impl_
->resource_provider());
155 success
= layer_tree_host_impl_
->InitializeRenderer(output_surface
.Pass());
159 layer_tree_host_
->DidInitializeOutputSurface();
160 if (scheduler_on_impl_thread_
)
161 scheduler_on_impl_thread_
->DidCreateAndInitializeOutputSurface();
162 else if (!inside_synchronous_composite_
)
164 output_surface_creation_requested_
= false;
166 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface,
167 // and so output_surface_creation_requested remains true.
168 layer_tree_host_
->DidFailToInitializeOutputSurface();
172 const RendererCapabilities
& SingleThreadProxy::GetRendererCapabilities() const {
173 DCHECK(Proxy::IsMainThread());
174 DCHECK(!layer_tree_host_
->output_surface_lost());
175 return renderer_capabilities_for_main_thread_
;
178 void SingleThreadProxy::SetNeedsAnimate() {
179 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
180 DCHECK(Proxy::IsMainThread());
181 client_
->ScheduleAnimation();
185 void SingleThreadProxy::SetNeedsUpdateLayers() {
186 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
187 DCHECK(Proxy::IsMainThread());
191 void SingleThreadProxy::DoAnimate() {
192 // Don't animate if there is no root layer.
193 // TODO(mithro): Both Animate and UpdateAnimationState already have a
194 // "!active_tree_->root_layer()" check?
195 if (!layer_tree_host_impl_
->active_tree()->root_layer()) {
199 layer_tree_host_impl_
->Animate(
200 layer_tree_host_impl_
->CurrentBeginFrameArgs().frame_time
);
202 // If animations are not visible, update the animation state now as it
203 // won't happen in DoComposite.
204 if (!layer_tree_host_impl_
->AnimationsAreVisible()) {
205 layer_tree_host_impl_
->UpdateAnimationState(true);
209 void SingleThreadProxy::DoCommit() {
210 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
211 DCHECK(Proxy::IsMainThread());
213 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
215 tracked_objects::ScopedTracker
tracking_profile1(
216 FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1"));
217 commit_requested_
= false;
218 layer_tree_host_
->WillCommit();
219 devtools_instrumentation::ScopedCommitTrace
commit_task(
220 layer_tree_host_
->id());
222 // Commit immediately.
224 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
226 tracked_objects::ScopedTracker
tracking_profile2(
227 FROM_HERE_WITH_EXPLICIT_FUNCTION(
228 "461509 SingleThreadProxy::DoCommit2"));
229 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
230 DebugScopedSetImplThread
impl(this);
232 // This CapturePostTasks should be destroyed before CommitComplete() is
233 // called since that goes out to the embedder, and we want the embedder
234 // to receive its callbacks before that.
235 commit_blocking_task_runner_
.reset(new BlockingTaskRunner::CapturePostTasks(
236 blocking_main_thread_task_runner()));
238 layer_tree_host_impl_
->BeginCommit();
240 if (PrioritizedResourceManager
* contents_texture_manager
=
241 layer_tree_host_
->contents_texture_manager()) {
242 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
244 tracked_objects::ScopedTracker
tracking_profile3(
245 FROM_HERE_WITH_EXPLICIT_FUNCTION(
246 "461509 SingleThreadProxy::DoCommit3"));
247 contents_texture_manager
->PushTexturePrioritiesToBackings();
249 layer_tree_host_
->BeginCommitOnImplThread(layer_tree_host_impl_
.get());
251 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
253 tracked_objects::ScopedTracker
tracking_profile4(
254 FROM_HERE_WITH_EXPLICIT_FUNCTION(
255 "461509 SingleThreadProxy::DoCommit4"));
256 scoped_ptr
<ResourceUpdateController
> update_controller
=
257 ResourceUpdateController::Create(
259 MainThreadTaskRunner(),
260 queue_for_commit_
.Pass(),
261 layer_tree_host_impl_
->resource_provider());
263 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
265 tracked_objects::ScopedTracker
tracking_profile5(
266 FROM_HERE_WITH_EXPLICIT_FUNCTION(
267 "461509 SingleThreadProxy::DoCommit5"));
268 update_controller
->Finalize();
270 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
272 tracked_objects::ScopedTracker
tracking_profile6(
273 FROM_HERE_WITH_EXPLICIT_FUNCTION(
274 "461509 SingleThreadProxy::DoCommit6"));
275 if (layer_tree_host_impl_
->EvictedUIResourcesExist())
276 layer_tree_host_
->RecreateUIResources();
278 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
280 tracked_objects::ScopedTracker
tracking_profile7(
281 FROM_HERE_WITH_EXPLICIT_FUNCTION(
282 "461509 SingleThreadProxy::DoCommit7"));
283 layer_tree_host_
->FinishCommitOnImplThread(layer_tree_host_impl_
.get());
286 // In the single-threaded case, the scale and scroll deltas should never be
287 // touched on the impl layer tree.
288 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
289 layer_tree_host_impl_
->ProcessScrollDeltas();
290 DCHECK(!scroll_info
->scrolls
.size());
291 DCHECK_EQ(1.f
, scroll_info
->page_scale_delta
);
294 if (layer_tree_host_
->settings().impl_side_painting
) {
295 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
297 tracked_objects::ScopedTracker
tracking_profile8(
298 FROM_HERE_WITH_EXPLICIT_FUNCTION(
299 "461509 SingleThreadProxy::DoCommit8"));
300 // Commit goes directly to the active tree, but we need to synchronously
301 // "activate" the tree still during commit to satisfy any potential
302 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
303 // might not be ready to draw, so DidActivateSyncTree must set
304 // the flag to force the tree to not draw until textures are ready.
305 NotifyReadyToActivate();
307 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
309 tracked_objects::ScopedTracker
tracking_profile9(
310 FROM_HERE_WITH_EXPLICIT_FUNCTION(
311 "461509 SingleThreadProxy::DoCommit9"));
317 void SingleThreadProxy::CommitComplete() {
318 DCHECK(!layer_tree_host_impl_
->pending_tree())
319 << "Activation is expected to have synchronously occurred by now.";
320 DCHECK(commit_blocking_task_runner_
);
322 // Notify commit complete on the impl side after activate to satisfy any
323 // SetNextCommitWaitsForActivation calls.
324 layer_tree_host_impl_
->CommitComplete();
326 DebugScopedSetMainThread
main(this);
327 commit_blocking_task_runner_
.reset();
328 layer_tree_host_
->CommitComplete();
329 layer_tree_host_
->DidBeginMainFrame();
330 timing_history_
.DidCommit();
332 next_frame_is_newly_committed_frame_
= true;
335 void SingleThreadProxy::SetNeedsCommit() {
336 DCHECK(Proxy::IsMainThread());
337 DebugScopedSetImplThread
impl(this);
338 client_
->ScheduleComposite();
339 if (scheduler_on_impl_thread_
)
340 scheduler_on_impl_thread_
->SetNeedsCommit();
341 commit_requested_
= true;
344 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect
& damage_rect
) {
345 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
346 DCHECK(Proxy::IsMainThread());
347 DebugScopedSetImplThread
impl(this);
348 client_
->ScheduleComposite();
349 SetNeedsRedrawRectOnImplThread(damage_rect
);
352 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
353 // Activation always forced in commit, so nothing to do.
354 DCHECK(Proxy::IsMainThread());
357 void SingleThreadProxy::SetDeferCommits(bool defer_commits
) {
358 DCHECK(Proxy::IsMainThread());
359 // Deferring commits only makes sense if there's a scheduler.
360 if (!scheduler_on_impl_thread_
)
362 if (defer_commits_
== defer_commits
)
366 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
368 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
370 defer_commits_
= defer_commits
;
371 scheduler_on_impl_thread_
->SetDeferCommits(defer_commits
);
374 bool SingleThreadProxy::CommitRequested() const {
375 DCHECK(Proxy::IsMainThread());
376 return commit_requested_
;
379 bool SingleThreadProxy::BeginMainFrameRequested() const {
380 DCHECK(Proxy::IsMainThread());
381 // If there is no scheduler, then there can be no pending begin frame,
382 // as all frames are all manually initiated by the embedder of cc.
383 if (!scheduler_on_impl_thread_
)
385 return commit_requested_
;
388 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
389 return std::numeric_limits
<size_t>::max();
392 void SingleThreadProxy::Stop() {
393 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
394 DCHECK(Proxy::IsMainThread());
396 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
397 DebugScopedSetImplThread
impl(this);
399 BlockingTaskRunner::CapturePostTasks
blocked(
400 blocking_main_thread_task_runner());
401 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
402 layer_tree_host_impl_
->resource_provider());
403 scheduler_on_impl_thread_
= nullptr;
404 layer_tree_host_impl_
= nullptr;
406 layer_tree_host_
= NULL
;
409 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw
) {
411 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw
);
412 DCHECK(Proxy::IsImplThread());
413 if (scheduler_on_impl_thread_
)
414 scheduler_on_impl_thread_
->SetCanDraw(can_draw
);
417 void SingleThreadProxy::NotifyReadyToActivate() {
418 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
419 DebugScopedSetImplThread
impl(this);
420 if (scheduler_on_impl_thread_
)
421 scheduler_on_impl_thread_
->NotifyReadyToActivate();
424 void SingleThreadProxy::NotifyReadyToDraw() {
425 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToDraw");
426 DebugScopedSetImplThread
impl(this);
427 if (scheduler_on_impl_thread_
)
428 scheduler_on_impl_thread_
->NotifyReadyToDraw();
431 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
432 client_
->ScheduleComposite();
433 if (scheduler_on_impl_thread_
)
434 scheduler_on_impl_thread_
->SetNeedsRedraw();
437 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
438 client_
->ScheduleComposite();
439 if (scheduler_on_impl_thread_
)
440 scheduler_on_impl_thread_
->SetNeedsAnimate();
443 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
444 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
445 if (scheduler_on_impl_thread_
)
446 scheduler_on_impl_thread_
->SetNeedsPrepareTiles();
449 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
450 const gfx::Rect
& damage_rect
) {
451 layer_tree_host_impl_
->SetViewportDamage(damage_rect
);
452 SetNeedsRedrawOnImplThread();
455 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
456 client_
->ScheduleComposite();
457 if (scheduler_on_impl_thread_
)
458 scheduler_on_impl_thread_
->SetNeedsCommit();
461 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
462 scoped_ptr
<AnimationEventsVector
> events
) {
464 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
465 DCHECK(Proxy::IsImplThread());
466 DebugScopedSetMainThread
main(this);
467 layer_tree_host_
->SetAnimationEvents(events
.Pass());
470 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
472 int priority_cutoff
) {
473 DCHECK(IsImplThread());
474 PrioritizedResourceManager
* contents_texture_manager
=
475 layer_tree_host_
->contents_texture_manager();
477 ResourceProvider
* resource_provider
=
478 layer_tree_host_impl_
->resource_provider();
480 if (!contents_texture_manager
|| !resource_provider
)
483 return contents_texture_manager
->ReduceMemoryOnImplThread(
484 limit_bytes
, priority_cutoff
, resource_provider
);
487 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_
; }
489 void SingleThreadProxy::DidActivateSyncTree() {
490 // Non-impl-side painting finishes commit in DoCommit. Impl-side painting
491 // defers until here to simulate SetNextCommitWaitsForActivation.
492 if (layer_tree_host_impl_
->settings().impl_side_painting
) {
493 // This is required because NotifyReadyToActivate gets called immediately
494 // after commit since single thread commits directly to the active tree.
495 if (scheduler_on_impl_thread_
)
496 scheduler_on_impl_thread_
->SetWaitForReadyToDraw();
498 // Synchronously call to CommitComplete. Resetting
499 // |commit_blocking_task_runner| would make sure all tasks posted during
500 // commit/activation before CommitComplete.
504 timing_history_
.DidActivateSyncTree();
507 void SingleThreadProxy::DidPrepareTiles() {
508 DCHECK(layer_tree_host_impl_
->settings().impl_side_painting
);
509 DCHECK(Proxy::IsImplThread());
510 if (scheduler_on_impl_thread_
)
511 scheduler_on_impl_thread_
->DidPrepareTiles();
514 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
515 layer_tree_host_
->DidCompletePageScaleAnimation();
518 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
519 DCHECK(IsImplThread());
520 renderer_capabilities_for_main_thread_
=
521 layer_tree_host_impl_
->GetRendererCapabilities().MainThreadCapabilities();
524 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
525 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
527 DebugScopedSetMainThread
main(this);
528 // This must happen before we notify the scheduler as it may try to recreate
529 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
530 layer_tree_host_
->DidLoseOutputSurface();
532 client_
->DidAbortSwapBuffers();
533 if (scheduler_on_impl_thread_
)
534 scheduler_on_impl_thread_
->DidLoseOutputSurface();
537 void SingleThreadProxy::CommitVSyncParameters(base::TimeTicks timebase
,
538 base::TimeDelta interval
) {
539 if (scheduler_on_impl_thread_
)
540 scheduler_on_impl_thread_
->CommitVSyncParameters(timebase
, interval
);
543 void SingleThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time
) {
544 if (scheduler_on_impl_thread_
)
545 scheduler_on_impl_thread_
->SetEstimatedParentDrawTime(draw_time
);
548 void SingleThreadProxy::SetMaxSwapsPendingOnImplThread(int max
) {
549 if (scheduler_on_impl_thread_
)
550 scheduler_on_impl_thread_
->SetMaxSwapsPending(max
);
553 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
554 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
555 if (scheduler_on_impl_thread_
)
556 scheduler_on_impl_thread_
->DidSwapBuffers();
557 client_
->DidPostSwapBuffers();
560 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
561 TRACE_EVENT0("cc,benchmark",
562 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
563 if (scheduler_on_impl_thread_
)
564 scheduler_on_impl_thread_
->DidSwapBuffersComplete();
565 layer_tree_host_
->DidCompleteSwapBuffers();
568 void SingleThreadProxy::OnDrawForOutputSurface() {
569 NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor.";
572 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time
) {
573 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
574 DCHECK(Proxy::IsMainThread());
575 base::AutoReset
<bool> inside_composite(&inside_synchronous_composite_
, true);
577 if (layer_tree_host_
->output_surface_lost()) {
578 RequestNewOutputSurface();
579 // RequestNewOutputSurface could have synchronously created an output
580 // surface, so check again before returning.
581 if (layer_tree_host_
->output_surface_lost())
586 BeginFrameArgs
begin_frame_args(BeginFrameArgs::Create(
587 BEGINFRAME_FROM_HERE
, frame_begin_time
, base::TimeTicks(),
588 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL
));
589 DoBeginMainFrame(begin_frame_args
);
592 DCHECK_EQ(0u, layer_tree_host_
->num_queued_swap_promises())
593 << "Commit should always succeed and transfer promises.";
597 DebugScopedSetImplThread
impl(const_cast<SingleThreadProxy
*>(this));
598 if (layer_tree_host_impl_
->settings().impl_side_painting
) {
599 layer_tree_host_impl_
->ActivateSyncTree();
600 DCHECK(!layer_tree_host_impl_
->active_tree()
601 ->needs_update_draw_properties());
602 layer_tree_host_impl_
->PrepareTiles();
603 layer_tree_host_impl_
->SynchronouslyInitializeAllTiles();
608 LayerTreeHostImpl::FrameData frame
;
609 DoComposite(frame_begin_time
, &frame
);
611 // DoComposite could abort, but because this is a synchronous composite
612 // another draw will never be scheduled, so break remaining promises.
613 layer_tree_host_impl_
->active_tree()->BreakSwapPromises(
614 SwapPromise::SWAP_FAILS
);
618 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
620 DebugScopedSetImplThread
impl(this);
621 if (layer_tree_host_impl_
->renderer()) {
622 DCHECK(!layer_tree_host_
->output_surface_lost());
623 layer_tree_host_impl_
->renderer()->DoNoOp();
628 bool SingleThreadProxy::SupportsImplScrolling() const {
632 bool SingleThreadProxy::ShouldComposite() const {
633 DCHECK(Proxy::IsImplThread());
634 return layer_tree_host_impl_
->visible() &&
635 layer_tree_host_impl_
->CanDraw();
638 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
639 if (output_surface_creation_callback_
.IsCancelled() &&
640 !output_surface_creation_requested_
) {
641 output_surface_creation_callback_
.Reset(
642 base::Bind(&SingleThreadProxy::RequestNewOutputSurface
,
643 weak_factory_
.GetWeakPtr()));
644 MainThreadTaskRunner()->PostTask(
645 FROM_HERE
, output_surface_creation_callback_
.callback());
649 DrawResult
SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time
,
650 LayerTreeHostImpl::FrameData
* frame
) {
651 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
652 DCHECK(!layer_tree_host_
->output_surface_lost());
654 DrawResult draw_result
;
657 DebugScopedSetImplThread
impl(this);
658 base::AutoReset
<bool> mark_inside(&inside_draw_
, true);
660 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
662 tracked_objects::ScopedTracker
tracking_profile1(
663 FROM_HERE_WITH_EXPLICIT_FUNCTION(
664 "461509 SingleThreadProxy::DoComposite1"));
666 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
667 // frame, so can only be used when such a frame is possible. Since
668 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
669 // CanDraw() as well.
670 if (!ShouldComposite()) {
671 return DRAW_ABORTED_CANT_DRAW
;
674 timing_history_
.DidStartDrawing();
676 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
678 tracked_objects::ScopedTracker
tracking_profile2(
679 FROM_HERE_WITH_EXPLICIT_FUNCTION(
680 "461509 SingleThreadProxy::DoComposite2"));
681 draw_result
= layer_tree_host_impl_
->PrepareToDraw(frame
);
682 draw_frame
= draw_result
== DRAW_SUCCESS
;
684 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
686 tracked_objects::ScopedTracker
tracking_profile3(
687 FROM_HERE_WITH_EXPLICIT_FUNCTION(
688 "461509 SingleThreadProxy::DoComposite3"));
689 layer_tree_host_impl_
->DrawLayers(frame
, frame_begin_time
);
691 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
693 tracked_objects::ScopedTracker
tracking_profile4(
694 FROM_HERE_WITH_EXPLICIT_FUNCTION(
695 "461509 SingleThreadProxy::DoComposite4"));
696 layer_tree_host_impl_
->DidDrawAllLayers(*frame
);
698 bool start_ready_animations
= draw_frame
;
699 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
701 tracked_objects::ScopedTracker
tracking_profile5(
702 FROM_HERE_WITH_EXPLICIT_FUNCTION(
703 "461509 SingleThreadProxy::DoComposite5"));
704 layer_tree_host_impl_
->UpdateAnimationState(start_ready_animations
);
705 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
707 tracked_objects::ScopedTracker
tracking_profile6(
708 FROM_HERE_WITH_EXPLICIT_FUNCTION(
709 "461509 SingleThreadProxy::DoComposite6"));
710 layer_tree_host_impl_
->ResetCurrentBeginFrameArgsForNextFrame();
712 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
714 tracked_objects::ScopedTracker
tracking_profile7(
715 FROM_HERE_WITH_EXPLICIT_FUNCTION(
716 "461509 SingleThreadProxy::DoComposite7"));
717 timing_history_
.DidFinishDrawing();
721 DebugScopedSetImplThread
impl(this);
723 // This CapturePostTasks should be destroyed before
724 // DidCommitAndDrawFrame() is called since that goes out to the
726 // and we want the embedder to receive its callbacks before that.
727 // NOTE: This maintains consistent ordering with the ThreadProxy since
728 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
729 // there as the main thread is not blocked, so any posted tasks inside
730 // the swap buffers will execute first.
731 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
733 BlockingTaskRunner::CapturePostTasks
blocked(
734 blocking_main_thread_task_runner());
735 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509
737 tracked_objects::ScopedTracker
tracking_profile8(
738 FROM_HERE_WITH_EXPLICIT_FUNCTION(
739 "461509 SingleThreadProxy::DoComposite8"));
740 layer_tree_host_impl_
->SwapBuffers(*frame
);
742 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is
744 tracked_objects::ScopedTracker
tracking_profile9(
745 FROM_HERE_WITH_EXPLICIT_FUNCTION(
746 "461509 SingleThreadProxy::DoComposite9"));
747 DidCommitAndDrawFrame();
752 void SingleThreadProxy::DidCommitAndDrawFrame() {
753 if (next_frame_is_newly_committed_frame_
) {
754 DebugScopedSetMainThread
main(this);
755 next_frame_is_newly_committed_frame_
= false;
756 layer_tree_host_
->DidCommitAndDrawFrame();
760 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
764 void SingleThreadProxy::SetChildrenNeedBeginFrames(
765 bool children_need_begin_frames
) {
766 scheduler_on_impl_thread_
->SetChildrenNeedBeginFrames(
767 children_need_begin_frames
);
770 void SingleThreadProxy::SetAuthoritativeVSyncInterval(
771 const base::TimeDelta
& interval
) {
772 scheduler_on_impl_thread_
->SetAuthoritativeVSyncInterval(interval
);
775 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs
& args
) {
776 layer_tree_host_impl_
->WillBeginImplFrame(args
);
779 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
780 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
781 // Although this proxy is single-threaded, it's problematic to synchronously
782 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
783 // could cause a commit to occur in between a series of SetNeedsCommit calls
784 // (i.e. property modifications) causing some to fall on one frame and some to
785 // fall on the next. Doing it asynchronously instead matches the semantics of
786 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
787 // synchronous commit.
788 MainThreadTaskRunner()->PostTask(
790 base::Bind(&SingleThreadProxy::BeginMainFrame
,
791 weak_factory_
.GetWeakPtr()));
794 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() {
795 layer_tree_host_
->BeginMainFrameNotExpectedSoon();
798 void SingleThreadProxy::BeginMainFrame() {
799 if (defer_commits_
) {
800 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
801 TRACE_EVENT_SCOPE_THREAD
);
802 BeginMainFrameAbortedOnImplThread(
803 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT
);
807 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
809 ScopedAbortRemainingSwapPromises
swap_promise_checker(layer_tree_host_
);
811 if (!layer_tree_host_
->visible()) {
812 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD
);
813 BeginMainFrameAbortedOnImplThread(
814 CommitEarlyOutReason::ABORTED_NOT_VISIBLE
);
818 if (layer_tree_host_
->output_surface_lost()) {
819 TRACE_EVENT_INSTANT0(
820 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD
);
821 BeginMainFrameAbortedOnImplThread(
822 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST
);
826 const BeginFrameArgs
& begin_frame_args
=
827 layer_tree_host_impl_
->CurrentBeginFrameArgs();
828 DoBeginMainFrame(begin_frame_args
);
831 void SingleThreadProxy::DoBeginMainFrame(
832 const BeginFrameArgs
& begin_frame_args
) {
833 layer_tree_host_
->WillBeginMainFrame();
834 layer_tree_host_
->BeginMainFrame(begin_frame_args
);
835 layer_tree_host_
->AnimateLayers(begin_frame_args
.frame_time
);
836 layer_tree_host_
->Layout();
838 if (PrioritizedResourceManager
* contents_texture_manager
=
839 layer_tree_host_
->contents_texture_manager()) {
840 contents_texture_manager
->UnlinkAndClearEvictedBackings();
841 contents_texture_manager
->SetMaxMemoryLimitBytes(
842 layer_tree_host_impl_
->memory_allocation_limit_bytes());
843 contents_texture_manager
->SetExternalPriorityCutoff(
844 layer_tree_host_impl_
->memory_allocation_priority_cutoff());
847 DCHECK(!queue_for_commit_
);
848 queue_for_commit_
= make_scoped_ptr(new ResourceUpdateQueue
);
850 layer_tree_host_
->UpdateLayers(queue_for_commit_
.get());
852 timing_history_
.DidBeginMainFrame();
854 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
855 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
857 if (scheduler_on_impl_thread_
) {
858 scheduler_on_impl_thread_
->NotifyBeginMainFrameStarted();
859 scheduler_on_impl_thread_
->NotifyReadyToCommit();
863 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
864 CommitEarlyOutReason reason
) {
865 DebugScopedSetImplThread
impl(this);
866 DCHECK(scheduler_on_impl_thread_
->CommitPending());
867 DCHECK(!layer_tree_host_impl_
->pending_tree());
869 layer_tree_host_impl_
->BeginMainFrameAborted(reason
);
870 scheduler_on_impl_thread_
->BeginMainFrameAborted(reason
);
873 DrawResult
SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
874 DebugScopedSetImplThread
impl(this);
875 LayerTreeHostImpl::FrameData frame
;
876 return DoComposite(layer_tree_host_impl_
->CurrentBeginFrameArgs().frame_time
,
880 DrawResult
SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
882 return INVALID_RESULT
;
885 void SingleThreadProxy::ScheduledActionCommit() {
886 DebugScopedSetMainThread
main(this);
890 void SingleThreadProxy::ScheduledActionAnimate() {
891 TRACE_EVENT0("cc", "ScheduledActionAnimate");
892 DebugScopedSetImplThread
impl(this);
896 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
897 DebugScopedSetImplThread
impl(this);
898 layer_tree_host_impl_
->ActivateSyncTree();
901 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
902 DebugScopedSetMainThread
main(this);
903 DCHECK(scheduler_on_impl_thread_
);
904 // If possible, create the output surface in a post task. Synchronously
905 // creating the output surface makes tests more awkward since this differs
906 // from the ThreadProxy behavior. However, sometimes there is no
908 if (Proxy::MainThreadTaskRunner()) {
909 ScheduleRequestNewOutputSurface();
911 RequestNewOutputSurface();
915 void SingleThreadProxy::ScheduledActionPrepareTiles() {
916 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
917 DCHECK(layer_tree_host_impl_
->settings().impl_side_painting
);
918 DebugScopedSetImplThread
impl(this);
919 layer_tree_host_impl_
->PrepareTiles();
922 void SingleThreadProxy::ScheduledActionInvalidateOutputSurface() {
926 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time
) {
929 base::TimeDelta
SingleThreadProxy::DrawDurationEstimate() {
930 return timing_history_
.DrawDurationEstimate();
933 base::TimeDelta
SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
934 return timing_history_
.BeginMainFrameToCommitDurationEstimate();
937 base::TimeDelta
SingleThreadProxy::CommitToActivateDurationEstimate() {
938 return timing_history_
.CommitToActivateDurationEstimate();
941 void SingleThreadProxy::DidBeginImplFrameDeadline() {
942 layer_tree_host_impl_
->ResetCurrentBeginFrameArgsForNextFrame();
945 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs
& args
) {
946 layer_tree_host_
->SendBeginFramesToChildren(args
);