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.
4
5 #include "cc/trees/single_thread_proxy.h"
6
7 #include "base/auto_reset.h"
8 #include "base/bind.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/trace_event/trace_event.h"
11 #include "cc/base/devtools_instrumentation.h"
12 #include "cc/benchmarks/benchmark_instrumentation.h"
13 #include "cc/input/browser_controls_offset_manager.h"
14 #include "cc/metrics/compositor_timing_history.h"
15 #include "cc/paint/paint_worklet_layer_painter.h"
16 #include "cc/resources/ui_resource_manager.h"
17 #include "cc/scheduler/commit_earlyout_reason.h"
18 #include "cc/scheduler/scheduler.h"
19 #include "cc/trees/latency_info_swap_promise.h"
20 #include "cc/trees/layer_tree_frame_sink.h"
21 #include "cc/trees/layer_tree_host.h"
22 #include "cc/trees/layer_tree_host_single_thread_client.h"
23 #include "cc/trees/layer_tree_impl.h"
24 #include "cc/trees/mutator_host.h"
25 #include "cc/trees/render_frame_metadata_observer.h"
26 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
27 #include "cc/trees/scroll_and_scale_set.h"
28 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
29 #include "components/viz/common/frame_timing_details.h"
30 #include "components/viz/common/gpu/context_provider.h"
31
32 namespace cc {
33
Create(LayerTreeHost * layer_tree_host,LayerTreeHostSingleThreadClient * client,TaskRunnerProvider * task_runner_provider)34 std::unique_ptr<Proxy> SingleThreadProxy::Create(
35 LayerTreeHost* layer_tree_host,
36 LayerTreeHostSingleThreadClient* client,
37 TaskRunnerProvider* task_runner_provider) {
38 return base::WrapUnique(
39 new SingleThreadProxy(layer_tree_host, client, task_runner_provider));
40 }
41
SingleThreadProxy(LayerTreeHost * layer_tree_host,LayerTreeHostSingleThreadClient * client,TaskRunnerProvider * task_runner_provider)42 SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
43 LayerTreeHostSingleThreadClient* client,
44 TaskRunnerProvider* task_runner_provider)
45 : layer_tree_host_(layer_tree_host),
46 single_thread_client_(client),
47 task_runner_provider_(task_runner_provider),
48 next_frame_is_newly_committed_frame_(false),
49 #if DCHECK_IS_ON()
50 inside_impl_frame_(false),
51 #endif
52 inside_draw_(false),
53 defer_main_frame_update_(false),
54 defer_commits_(false),
55 animate_requested_(false),
56 commit_requested_(false),
57 inside_synchronous_composite_(false),
58 needs_impl_frame_(false),
59 layer_tree_frame_sink_creation_requested_(false),
60 layer_tree_frame_sink_lost_(true) {
61 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
62 DCHECK(task_runner_provider_);
63 DCHECK(task_runner_provider_->IsMainThread());
64 DCHECK(layer_tree_host);
65 }
66
Start()67 void SingleThreadProxy::Start() {
68 DebugScopedSetImplThread impl(task_runner_provider_);
69
70 const LayerTreeSettings& settings = layer_tree_host_->GetSettings();
71 DCHECK(settings.single_thread_proxy_scheduler ||
72 !settings.enable_checker_imaging)
73 << "Checker-imaging is not supported in synchronous single threaded mode";
74 host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
75 if (settings.single_thread_proxy_scheduler && !scheduler_on_impl_thread_) {
76 SchedulerSettings scheduler_settings(settings.ToSchedulerSettings());
77 scheduler_settings.commit_to_active_tree = true;
78
79 std::unique_ptr<CompositorTimingHistory> compositor_timing_history(
80 new CompositorTimingHistory(
81 scheduler_settings.using_synchronous_renderer_compositor,
82 CompositorTimingHistory::BROWSER_UMA,
83 layer_tree_host_->rendering_stats_instrumentation(),
84 host_impl_->compositor_frame_reporting_controller()));
85 scheduler_on_impl_thread_.reset(
86 new Scheduler(this, scheduler_settings, layer_tree_host_->GetId(),
87 task_runner_provider_->MainThreadTaskRunner(),
88 std::move(compositor_timing_history)));
89 }
90 }
91
~SingleThreadProxy()92 SingleThreadProxy::~SingleThreadProxy() {
93 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
94 DCHECK(task_runner_provider_->IsMainThread());
95 // Make sure Stop() got called or never Started.
96 DCHECK(!host_impl_);
97 }
98
IsStarted() const99 bool SingleThreadProxy::IsStarted() const {
100 DCHECK(task_runner_provider_->IsMainThread());
101 return !!host_impl_;
102 }
103
SetVisible(bool visible)104 void SingleThreadProxy::SetVisible(bool visible) {
105 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible);
106 DebugScopedSetImplThread impl(task_runner_provider_);
107
108 host_impl_->SetVisible(visible);
109
110 if (scheduler_on_impl_thread_)
111 scheduler_on_impl_thread_->SetVisible(host_impl_->visible());
112 }
113
RequestNewLayerTreeFrameSink()114 void SingleThreadProxy::RequestNewLayerTreeFrameSink() {
115 DCHECK(task_runner_provider_->IsMainThread());
116 layer_tree_frame_sink_creation_callback_.Cancel();
117 if (layer_tree_frame_sink_creation_requested_)
118 return;
119 layer_tree_frame_sink_creation_requested_ = true;
120 layer_tree_host_->RequestNewLayerTreeFrameSink();
121 }
122
ReleaseLayerTreeFrameSink()123 void SingleThreadProxy::ReleaseLayerTreeFrameSink() {
124 layer_tree_frame_sink_lost_ = true;
125 frame_sink_bound_weak_factory_.InvalidateWeakPtrs();
126 if (scheduler_on_impl_thread_)
127 scheduler_on_impl_thread_->DidLoseLayerTreeFrameSink();
128 return host_impl_->ReleaseLayerTreeFrameSink();
129 }
130
SetLayerTreeFrameSink(LayerTreeFrameSink * layer_tree_frame_sink)131 void SingleThreadProxy::SetLayerTreeFrameSink(
132 LayerTreeFrameSink* layer_tree_frame_sink) {
133 DCHECK(task_runner_provider_->IsMainThread());
134 DCHECK(layer_tree_frame_sink_creation_requested_);
135
136 bool success;
137 {
138 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
139 DebugScopedSetImplThread impl(task_runner_provider_);
140 success = host_impl_->InitializeFrameSink(layer_tree_frame_sink);
141 }
142
143 if (success) {
144 frame_sink_bound_weak_ptr_ = frame_sink_bound_weak_factory_.GetWeakPtr();
145 layer_tree_host_->DidInitializeLayerTreeFrameSink();
146 if (scheduler_on_impl_thread_)
147 scheduler_on_impl_thread_->DidCreateAndInitializeLayerTreeFrameSink();
148 else if (!inside_synchronous_composite_)
149 SetNeedsCommit();
150 layer_tree_frame_sink_creation_requested_ = false;
151 layer_tree_frame_sink_lost_ = false;
152 } else {
153 // DidFailToInitializeLayerTreeFrameSink is treated as a
154 // RequestNewLayerTreeFrameSink, and so
155 // layer_tree_frame_sink_creation_requested remains true.
156 layer_tree_host_->DidFailToInitializeLayerTreeFrameSink();
157 }
158 }
159
SetNeedsAnimate()160 void SingleThreadProxy::SetNeedsAnimate() {
161 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
162 DCHECK(task_runner_provider_->IsMainThread());
163 if (animate_requested_)
164 return;
165 animate_requested_ = true;
166 DebugScopedSetImplThread impl(task_runner_provider_);
167 if (scheduler_on_impl_thread_)
168 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
169 }
170
SetNeedsUpdateLayers()171 void SingleThreadProxy::SetNeedsUpdateLayers() {
172 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
173 DCHECK(task_runner_provider_->IsMainThread());
174 SetNeedsCommit();
175 }
176
DoCommit(const viz::BeginFrameArgs & commit_args)177 void SingleThreadProxy::DoCommit(const viz::BeginFrameArgs& commit_args) {
178 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
179 DCHECK(task_runner_provider_->IsMainThread());
180
181 layer_tree_host_->WillCommit();
182 devtools_instrumentation::ScopedCommitTrace commit_task(
183 layer_tree_host_->GetId());
184
185 // Commit immediately.
186 {
187 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
188 DebugScopedSetImplThread impl(task_runner_provider_);
189
190 host_impl_->ReadyToCommit(commit_args);
191 host_impl_->BeginCommit();
192
193 if (host_impl_->EvictedUIResourcesExist())
194 layer_tree_host_->GetUIResourceManager()->RecreateUIResources();
195
196 layer_tree_host_->FinishCommitOnImplThread(host_impl_.get());
197
198 if (scheduler_on_impl_thread_) {
199 scheduler_on_impl_thread_->DidCommit();
200 }
201
202 IssueImageDecodeFinishedCallbacks();
203 host_impl_->CommitComplete();
204
205 // Commit goes directly to the active tree, but we need to synchronously
206 // "activate" the tree still during commit to satisfy any potential
207 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
208 // might not be ready to draw, so DidActivateSyncTree must set
209 // the flag to force the tree to not draw until textures are ready.
210 NotifyReadyToActivate();
211 }
212 }
213
IssueImageDecodeFinishedCallbacks()214 void SingleThreadProxy::IssueImageDecodeFinishedCallbacks() {
215 DCHECK(task_runner_provider_->IsImplThread());
216
217 layer_tree_host_->ImageDecodesFinished(
218 host_impl_->TakeCompletedImageDecodeRequests());
219 }
220
CommitComplete()221 void SingleThreadProxy::CommitComplete() {
222 // Commit complete happens on the main side after activate to satisfy any
223 // SetNextCommitWaitsForActivation calls.
224 DCHECK(!host_impl_->pending_tree())
225 << "Activation is expected to have synchronously occurred by now.";
226
227 DebugScopedSetMainThread main(task_runner_provider_);
228 layer_tree_host_->CommitComplete();
229 layer_tree_host_->DidBeginMainFrame();
230
231 next_frame_is_newly_committed_frame_ = true;
232 }
233
SetNeedsCommit()234 void SingleThreadProxy::SetNeedsCommit() {
235 DCHECK(task_runner_provider_->IsMainThread());
236 single_thread_client_->RequestScheduleComposite();
237 if (commit_requested_)
238 return;
239 commit_requested_ = true;
240 DebugScopedSetImplThread impl(task_runner_provider_);
241 if (scheduler_on_impl_thread_)
242 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
243 }
244
SetNeedsRedraw(const gfx::Rect & damage_rect)245 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
246 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
247 DCHECK(task_runner_provider_->IsMainThread());
248 DebugScopedSetImplThread impl(task_runner_provider_);
249 host_impl_->SetViewportDamage(damage_rect);
250 SetNeedsRedrawOnImplThread();
251 }
252
SetNextCommitWaitsForActivation()253 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
254 // Activation always forced in commit, so nothing to do.
255 DCHECK(task_runner_provider_->IsMainThread());
256 }
257
RequestedAnimatePending()258 bool SingleThreadProxy::RequestedAnimatePending() {
259 return animate_requested_ || commit_requested_ || needs_impl_frame_;
260 }
261
SetDeferMainFrameUpdate(bool defer_main_frame_update)262 void SingleThreadProxy::SetDeferMainFrameUpdate(bool defer_main_frame_update) {
263 DCHECK(task_runner_provider_->IsMainThread());
264 // Deferring main frame updates only makes sense if there's a scheduler.
265 if (!scheduler_on_impl_thread_)
266 return;
267 if (defer_main_frame_update_ == defer_main_frame_update)
268 return;
269
270 if (defer_main_frame_update) {
271 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
272 "cc", "SingleThreadProxy::SetDeferMainFrameUpdate",
273 TRACE_ID_LOCAL(this));
274 } else {
275 TRACE_EVENT_NESTABLE_ASYNC_END0(
276 "cc", "SingleThreadProxy::SetDeferMainFrameUpdate",
277 TRACE_ID_LOCAL(this));
278 }
279
280 defer_main_frame_update_ = defer_main_frame_update;
281
282 // Notify dependent systems that the deferral status has changed.
283 layer_tree_host_->OnDeferMainFrameUpdatesChanged(defer_main_frame_update_);
284
285 // The scheduler needs to know that it should not issue BeginMainFrame.
286 scheduler_on_impl_thread_->SetDeferBeginMainFrame(defer_main_frame_update_);
287 }
288
StartDeferringCommits(base::TimeDelta timeout)289 void SingleThreadProxy::StartDeferringCommits(base::TimeDelta timeout) {
290 DCHECK(task_runner_provider_->IsMainThread());
291
292 // Do nothing if already deferring. The timeout remains as it was from when
293 // we most recently began deferring.
294 if (defer_commits_)
295 return;
296
297 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits",
298 TRACE_ID_LOCAL(this));
299
300 defer_commits_ = true;
301 commits_restart_time_ = base::TimeTicks::Now() + timeout;
302
303 // Notify dependent systems that the deferral status has changed.
304 layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
305 }
306
StopDeferringCommits(PaintHoldingCommitTrigger trigger)307 void SingleThreadProxy::StopDeferringCommits(
308 PaintHoldingCommitTrigger trigger) {
309 if (!defer_commits_)
310 return;
311 defer_commits_ = false;
312 commits_restart_time_ = base::TimeTicks();
313 UMA_HISTOGRAM_ENUMERATION("PaintHolding.CommitTrigger2", trigger);
314 TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits",
315 TRACE_ID_LOCAL(this));
316
317 // Notify dependent systems that the deferral status has changed.
318 layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
319 }
320
CommitRequested() const321 bool SingleThreadProxy::CommitRequested() const {
322 DCHECK(task_runner_provider_->IsMainThread());
323 return commit_requested_;
324 }
325
Stop()326 void SingleThreadProxy::Stop() {
327 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
328 DCHECK(task_runner_provider_->IsMainThread());
329 {
330 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
331 DebugScopedSetImplThread impl(task_runner_provider_);
332
333 // Prevent the scheduler from performing actions while we're in an
334 // inconsistent state.
335 if (scheduler_on_impl_thread_)
336 scheduler_on_impl_thread_->Stop();
337 // Take away the LayerTreeFrameSink before destroying things so it doesn't
338 // try to call into its client mid-shutdown.
339 host_impl_->ReleaseLayerTreeFrameSink();
340
341 // It is important to destroy LTHI before the Scheduler since it can make
342 // callbacks that access it during destruction cleanup.
343 host_impl_ = nullptr;
344 scheduler_on_impl_thread_ = nullptr;
345 }
346 layer_tree_host_ = nullptr;
347 }
348
SetMutator(std::unique_ptr<LayerTreeMutator> mutator)349 void SingleThreadProxy::SetMutator(std::unique_ptr<LayerTreeMutator> mutator) {
350 DCHECK(task_runner_provider_->IsMainThread());
351 DebugScopedSetImplThread impl(task_runner_provider_);
352 host_impl_->SetLayerTreeMutator(std::move(mutator));
353 }
354
SetPaintWorkletLayerPainter(std::unique_ptr<PaintWorkletLayerPainter> painter)355 void SingleThreadProxy::SetPaintWorkletLayerPainter(
356 std::unique_ptr<PaintWorkletLayerPainter> painter) {
357 NOTREACHED();
358 }
359
OnCanDrawStateChanged(bool can_draw)360 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
361 TRACE_EVENT1("cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw",
362 can_draw);
363 DCHECK(task_runner_provider_->IsImplThread());
364 if (scheduler_on_impl_thread_)
365 scheduler_on_impl_thread_->SetCanDraw(can_draw);
366 }
367
NotifyReadyToActivate()368 void SingleThreadProxy::NotifyReadyToActivate() {
369 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate");
370 DebugScopedSetImplThread impl(task_runner_provider_);
371 if (scheduler_on_impl_thread_)
372 scheduler_on_impl_thread_->NotifyReadyToActivate();
373 }
374
NotifyReadyToDraw()375 void SingleThreadProxy::NotifyReadyToDraw() {
376 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToDraw");
377 DebugScopedSetImplThread impl(task_runner_provider_);
378 if (scheduler_on_impl_thread_)
379 scheduler_on_impl_thread_->NotifyReadyToDraw();
380 }
381
SetNeedsRedrawOnImplThread()382 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
383 single_thread_client_->RequestScheduleComposite();
384 if (scheduler_on_impl_thread_)
385 scheduler_on_impl_thread_->SetNeedsRedraw();
386 }
387
SetNeedsOneBeginImplFrameOnImplThread()388 void SingleThreadProxy::SetNeedsOneBeginImplFrameOnImplThread() {
389 TRACE_EVENT0("cc",
390 "SingleThreadProxy::SetNeedsOneBeginImplFrameOnImplThread");
391 single_thread_client_->RequestScheduleComposite();
392 if (scheduler_on_impl_thread_)
393 scheduler_on_impl_thread_->SetNeedsOneBeginImplFrame();
394 needs_impl_frame_ = true;
395 }
396
SetNeedsPrepareTilesOnImplThread()397 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
398 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread");
399 if (scheduler_on_impl_thread_)
400 scheduler_on_impl_thread_->SetNeedsPrepareTiles();
401 }
402
SetNeedsCommitOnImplThread()403 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
404 single_thread_client_->RequestScheduleComposite();
405 if (scheduler_on_impl_thread_)
406 scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
407 commit_requested_ = true;
408 }
409
SetVideoNeedsBeginFrames(bool needs_begin_frames)410 void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
411 TRACE_EVENT1("cc", "SingleThreadProxy::SetVideoNeedsBeginFrames",
412 "needs_begin_frames", needs_begin_frames);
413 // In tests the layer tree is destroyed after the scheduler is.
414 if (scheduler_on_impl_thread_)
415 scheduler_on_impl_thread_->SetVideoNeedsBeginFrames(needs_begin_frames);
416 }
417
CompositedAnimationsCount() const418 size_t SingleThreadProxy::CompositedAnimationsCount() const {
419 return 0;
420 }
421
MainThreadAnimationsCount() const422 size_t SingleThreadProxy::MainThreadAnimationsCount() const {
423 return 0;
424 }
425
HasCustomPropertyAnimations() const426 bool SingleThreadProxy::HasCustomPropertyAnimations() const {
427 return false;
428 }
429
CurrentFrameHadRAF() const430 bool SingleThreadProxy::CurrentFrameHadRAF() const {
431 return false;
432 }
433
NextFrameHasPendingRAF() const434 bool SingleThreadProxy::NextFrameHasPendingRAF() const {
435 return false;
436 }
437
IsInsideDraw()438 bool SingleThreadProxy::IsInsideDraw() {
439 return inside_draw_;
440 }
441
IsBeginMainFrameExpected()442 bool SingleThreadProxy::IsBeginMainFrameExpected() {
443 return true;
444 }
445
DidActivateSyncTree()446 void SingleThreadProxy::DidActivateSyncTree() {
447 CommitComplete();
448 }
449
WillPrepareTiles()450 void SingleThreadProxy::WillPrepareTiles() {
451 DCHECK(task_runner_provider_->IsImplThread());
452 if (scheduler_on_impl_thread_)
453 scheduler_on_impl_thread_->WillPrepareTiles();
454 }
455
DidPrepareTiles()456 void SingleThreadProxy::DidPrepareTiles() {
457 DCHECK(task_runner_provider_->IsImplThread());
458 if (scheduler_on_impl_thread_)
459 scheduler_on_impl_thread_->DidPrepareTiles();
460 }
461
DidCompletePageScaleAnimationOnImplThread()462 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
463 layer_tree_host_->DidCompletePageScaleAnimation();
464 }
465
DidLoseLayerTreeFrameSinkOnImplThread()466 void SingleThreadProxy::DidLoseLayerTreeFrameSinkOnImplThread() {
467 TRACE_EVENT0("cc",
468 "SingleThreadProxy::DidLoseLayerTreeFrameSinkOnImplThread");
469 {
470 DebugScopedSetMainThread main(task_runner_provider_);
471 // This must happen before we notify the scheduler as it may try to recreate
472 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
473 layer_tree_host_->DidLoseLayerTreeFrameSink();
474 }
475 single_thread_client_->DidLoseLayerTreeFrameSink();
476 if (scheduler_on_impl_thread_)
477 scheduler_on_impl_thread_->DidLoseLayerTreeFrameSink();
478 layer_tree_frame_sink_lost_ = true;
479 }
480
SetBeginFrameSource(viz::BeginFrameSource * source)481 void SingleThreadProxy::SetBeginFrameSource(viz::BeginFrameSource* source) {
482 if (scheduler_on_impl_thread_)
483 scheduler_on_impl_thread_->SetBeginFrameSource(source);
484 }
485
DidReceiveCompositorFrameAckOnImplThread()486 void SingleThreadProxy::DidReceiveCompositorFrameAckOnImplThread() {
487 TRACE_EVENT0("cc,benchmark",
488 "SingleThreadProxy::DidReceiveCompositorFrameAckOnImplThread");
489 if (scheduler_on_impl_thread_)
490 scheduler_on_impl_thread_->DidReceiveCompositorFrameAck();
491 if (layer_tree_host_->GetSettings().send_compositor_frame_ack) {
492 // We do a PostTask here because freeing resources in some cases (such as in
493 // TextureLayer) is PostTasked and we want to make sure ack is received
494 // after resources are returned.
495 task_runner_provider_->MainThreadTaskRunner()->PostTask(
496 FROM_HERE,
497 base::BindOnce(&SingleThreadProxy::DidReceiveCompositorFrameAck,
498 frame_sink_bound_weak_ptr_));
499 }
500 }
501
OnDrawForLayerTreeFrameSink(bool resourceless_software_draw,bool skip_draw)502 void SingleThreadProxy::OnDrawForLayerTreeFrameSink(
503 bool resourceless_software_draw,
504 bool skip_draw) {
505 NOTREACHED() << "Implemented by ThreadProxy for synchronous compositor.";
506 }
507
NeedsImplSideInvalidation(bool needs_first_draw_on_activation)508 void SingleThreadProxy::NeedsImplSideInvalidation(
509 bool needs_first_draw_on_activation) {
510 if (scheduler_on_impl_thread_) {
511 scheduler_on_impl_thread_->SetNeedsImplSideInvalidation(
512 needs_first_draw_on_activation);
513 }
514 }
515
NotifyImageDecodeRequestFinished()516 void SingleThreadProxy::NotifyImageDecodeRequestFinished() {
517 // If we don't have a scheduler, then just issue the callbacks here.
518 // Otherwise, schedule a commit.
519 if (!scheduler_on_impl_thread_) {
520 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
521 DebugScopedSetImplThread impl(task_runner_provider_);
522
523 IssueImageDecodeFinishedCallbacks();
524 return;
525 }
526 SetNeedsCommitOnImplThread();
527 }
528
DidPresentCompositorFrameOnImplThread(uint32_t frame_token,std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,const viz::FrameTimingDetails & details)529 void SingleThreadProxy::DidPresentCompositorFrameOnImplThread(
530 uint32_t frame_token,
531 std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
532 const viz::FrameTimingDetails& details) {
533 layer_tree_host_->DidPresentCompositorFrame(frame_token, std::move(callbacks),
534 details.presentation_feedback);
535
536 if (scheduler_on_impl_thread_) {
537 scheduler_on_impl_thread_->DidPresentCompositorFrame(frame_token, details);
538 }
539 }
540
NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state,ElementListType element_list_type)541 void SingleThreadProxy::NotifyAnimationWorkletStateChange(
542 AnimationWorkletMutationState state,
543 ElementListType element_list_type) {
544 layer_tree_host_->NotifyAnimationWorkletStateChange(state, element_list_type);
545 }
546
NotifyPaintWorkletStateChange(Scheduler::PaintWorkletState state)547 void SingleThreadProxy::NotifyPaintWorkletStateChange(
548 Scheduler::PaintWorkletState state) {
549 // Off-Thread PaintWorklet is only supported on the threaded compositor.
550 NOTREACHED();
551 }
552
RequestBeginMainFrameNotExpected(bool new_state)553 void SingleThreadProxy::RequestBeginMainFrameNotExpected(bool new_state) {
554 if (scheduler_on_impl_thread_) {
555 scheduler_on_impl_thread_->SetMainThreadWantsBeginMainFrameNotExpected(
556 new_state);
557 }
558 }
559
CompositeImmediately(base::TimeTicks frame_begin_time,bool raster)560 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time,
561 bool raster) {
562 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately");
563 DCHECK(task_runner_provider_->IsMainThread());
564 #if DCHECK_IS_ON()
565 DCHECK(!inside_impl_frame_);
566 #endif
567 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
568
569 if (layer_tree_frame_sink_lost_) {
570 RequestNewLayerTreeFrameSink();
571 // RequestNewLayerTreeFrameSink could have synchronously created an output
572 // surface, so check again before returning.
573 if (layer_tree_frame_sink_lost_)
574 return;
575 }
576
577 viz::BeginFrameArgs begin_frame_args(viz::BeginFrameArgs::Create(
578 BEGINFRAME_FROM_HERE, viz::BeginFrameArgs::kManualSourceId,
579 begin_frame_sequence_number_++, frame_begin_time, base::TimeTicks(),
580 viz::BeginFrameArgs::DefaultInterval(), viz::BeginFrameArgs::NORMAL));
581
582 // Start the impl frame.
583 {
584 DebugScopedSetImplThread impl(task_runner_provider_);
585 WillBeginImplFrame(begin_frame_args);
586 }
587
588 // Run the "main thread" and get it to commit.
589 {
590 #if DCHECK_IS_ON()
591 DCHECK(inside_impl_frame_);
592 #endif
593 animate_requested_ = false;
594 needs_impl_frame_ = false;
595 // Prevent new commits from being requested inside DoBeginMainFrame.
596 // Note: We do not want to prevent SetNeedsAnimate from requesting
597 // a commit here.
598 commit_requested_ = true;
599 DoBeginMainFrame(begin_frame_args);
600 commit_requested_ = false;
601 DoPainting();
602 DoCommit(begin_frame_args);
603
604 DCHECK_EQ(
605 0u,
606 layer_tree_host_->GetSwapPromiseManager()->num_queued_swap_promises())
607 << "Commit should always succeed and transfer promises.";
608 }
609
610 // Finish the impl frame.
611 {
612 DebugScopedSetImplThread impl(task_runner_provider_);
613 host_impl_->ActivateSyncTree();
614 if (raster) {
615 host_impl_->PrepareTiles();
616 host_impl_->SynchronouslyInitializeAllTiles();
617 }
618
619 // TODO(danakj): Don't do this last... we prepared the wrong things. D:
620 host_impl_->Animate();
621
622 if (raster) {
623 LayerTreeHostImpl::FrameData frame;
624 frame.begin_frame_ack = viz::BeginFrameAck(begin_frame_args, true);
625 frame.origin_begin_main_frame_args = begin_frame_args;
626 DoComposite(&frame);
627 }
628
629 // DoComposite could abort, but because this is a synchronous composite
630 // another draw will never be scheduled, so break remaining promises.
631 host_impl_->active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS);
632
633 DidFinishImplFrame();
634 }
635 }
636
SupportsImplScrolling() const637 bool SingleThreadProxy::SupportsImplScrolling() const {
638 return false;
639 }
640
ShouldComposite() const641 bool SingleThreadProxy::ShouldComposite() const {
642 DCHECK(task_runner_provider_->IsImplThread());
643 return host_impl_->visible() && host_impl_->CanDraw();
644 }
645
ScheduleRequestNewLayerTreeFrameSink()646 void SingleThreadProxy::ScheduleRequestNewLayerTreeFrameSink() {
647 if (layer_tree_frame_sink_creation_callback_.IsCancelled() &&
648 !layer_tree_frame_sink_creation_requested_) {
649 layer_tree_frame_sink_creation_callback_.Reset(
650 base::BindOnce(&SingleThreadProxy::RequestNewLayerTreeFrameSink,
651 weak_factory_.GetWeakPtr()));
652 task_runner_provider_->MainThreadTaskRunner()->PostTask(
653 FROM_HERE, layer_tree_frame_sink_creation_callback_.callback());
654 }
655 }
656
DoComposite(LayerTreeHostImpl::FrameData * frame)657 DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) {
658 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
659
660 DrawResult draw_result;
661 bool draw_frame;
662 {
663 DebugScopedSetImplThread impl(task_runner_provider_);
664 base::AutoReset<bool> mark_inside(&inside_draw_, true);
665
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;
672 }
673
674 // This CapturePostTasks should be destroyed before
675 // DidCommitAndDrawFrame() is called since that goes out to the
676 // embedder, and we want the embedder to receive its callbacks before that.
677 // NOTE: This maintains consistent ordering with the ThreadProxy since
678 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
679 // there as the main thread is not blocked, so any posted tasks inside
680 // the swap buffers will execute first.
681 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
682
683 draw_result = host_impl_->PrepareToDraw(frame);
684 draw_frame = draw_result == DRAW_SUCCESS;
685 if (draw_frame) {
686 if (host_impl_->DrawLayers(frame)) {
687 if (scheduler_on_impl_thread_) {
688 // Drawing implies we submitted a frame to the LayerTreeFrameSink.
689 scheduler_on_impl_thread_->DidSubmitCompositorFrame(
690 frame->frame_token, host_impl_->TakeEventsMetrics());
691 }
692 single_thread_client_->DidSubmitCompositorFrame();
693 }
694 }
695 host_impl_->DidDrawAllLayers(*frame);
696
697 bool start_ready_animations = draw_frame;
698 host_impl_->UpdateAnimationState(start_ready_animations);
699 }
700 DidCommitAndDrawFrame();
701
702 return draw_result;
703 }
704
DidCommitAndDrawFrame()705 void SingleThreadProxy::DidCommitAndDrawFrame() {
706 if (next_frame_is_newly_committed_frame_) {
707 DebugScopedSetMainThread main(task_runner_provider_);
708 next_frame_is_newly_committed_frame_ = false;
709 layer_tree_host_->DidCommitAndDrawFrame();
710 }
711 }
712
MainFrameWillHappenForTesting()713 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
714 if (!scheduler_on_impl_thread_)
715 return false;
716 return scheduler_on_impl_thread_->MainFrameForTestingWillHappen();
717 }
718
ClearHistory()719 void SingleThreadProxy::ClearHistory() {
720 DCHECK(task_runner_provider_->IsImplThread());
721 if (scheduler_on_impl_thread_)
722 scheduler_on_impl_thread_->ClearHistory();
723 }
724
SetRenderFrameObserver(std::unique_ptr<RenderFrameMetadataObserver> observer)725 void SingleThreadProxy::SetRenderFrameObserver(
726 std::unique_ptr<RenderFrameMetadataObserver> observer) {
727 host_impl_->SetRenderFrameObserver(std::move(observer));
728 }
729
UpdateBrowserControlsState(BrowserControlsState constraints,BrowserControlsState current,bool animate)730 void SingleThreadProxy::UpdateBrowserControlsState(
731 BrowserControlsState constraints,
732 BrowserControlsState current,
733 bool animate) {
734 host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
735 constraints, current, animate);
736 }
737
WillBeginImplFrame(const viz::BeginFrameArgs & args)738 bool SingleThreadProxy::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
739 DebugScopedSetImplThread impl(task_runner_provider_);
740 #if DCHECK_IS_ON()
741 DCHECK(!inside_impl_frame_)
742 << "WillBeginImplFrame called while already inside an impl frame!";
743 inside_impl_frame_ = true;
744 #endif
745 return host_impl_->WillBeginImplFrame(args);
746 }
747
ScheduledActionSendBeginMainFrame(const viz::BeginFrameArgs & begin_frame_args)748 void SingleThreadProxy::ScheduledActionSendBeginMainFrame(
749 const viz::BeginFrameArgs& begin_frame_args) {
750 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
751 #if DCHECK_IS_ON()
752 // Although this proxy is single-threaded, it's problematic to synchronously
753 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This
754 // could cause a commit to occur in between a series of SetNeedsCommit calls
755 // (i.e. property modifications) causing some to fall on one frame and some to
756 // fall on the next. Doing it asynchronously instead matches the semantics of
757 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
758 // synchronous commit.
759 DCHECK(inside_impl_frame_)
760 << "BeginMainFrame should only be sent inside a BeginImplFrame";
761 #endif
762
763 host_impl_->WillSendBeginMainFrame();
764 task_runner_provider_->MainThreadTaskRunner()->PostTask(
765 FROM_HERE, base::BindOnce(&SingleThreadProxy::BeginMainFrame,
766 weak_factory_.GetWeakPtr(), begin_frame_args));
767 host_impl_->DidSendBeginMainFrame(begin_frame_args);
768 }
769
FrameIntervalUpdated(base::TimeDelta interval)770 void SingleThreadProxy::FrameIntervalUpdated(base::TimeDelta interval) {
771 DebugScopedSetMainThread main(task_runner_provider_);
772 single_thread_client_->FrameIntervalUpdated(interval);
773 }
774
SendBeginMainFrameNotExpectedSoon()775 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() {
776 layer_tree_host_->BeginMainFrameNotExpectedSoon();
777 }
778
ScheduledActionBeginMainFrameNotExpectedUntil(base::TimeTicks time)779 void SingleThreadProxy::ScheduledActionBeginMainFrameNotExpectedUntil(
780 base::TimeTicks time) {
781 layer_tree_host_->BeginMainFrameNotExpectedUntil(time);
782 }
783
BeginMainFrame(const viz::BeginFrameArgs & begin_frame_args)784 void SingleThreadProxy::BeginMainFrame(
785 const viz::BeginFrameArgs& begin_frame_args) {
786 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous
787 // commit.
788 ScopedAbortRemainingSwapPromises swap_promise_checker(
789 layer_tree_host_->GetSwapPromiseManager());
790
791 if (scheduler_on_impl_thread_) {
792 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted(
793 base::TimeTicks::Now());
794 }
795
796 commit_requested_ = false;
797 needs_impl_frame_ = false;
798 animate_requested_ = false;
799
800 if (defer_main_frame_update_) {
801 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferBeginMainFrame",
802 TRACE_EVENT_SCOPE_THREAD);
803 BeginMainFrameAbortedOnImplThread(
804 CommitEarlyOutReason::ABORTED_DEFERRED_MAIN_FRAME_UPDATE);
805 return;
806 }
807
808 if (!layer_tree_host_->IsVisible()) {
809 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
810 BeginMainFrameAbortedOnImplThread(
811 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
812 return;
813 }
814
815 // Prevent new commits from being requested inside DoBeginMainFrame.
816 // Note: We do not want to prevent SetNeedsAnimate from requesting
817 // a commit here.
818 commit_requested_ = true;
819
820 // Check now if we should stop deferring commits. Do this before
821 // DoBeginMainFrame because the latter updates scroll offsets, which
822 // we should avoid if deferring commits.
823 if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_)
824 StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout);
825
826 DoBeginMainFrame(begin_frame_args);
827
828 // New commits requested inside UpdateLayers should be respected.
829 commit_requested_ = false;
830
831 // At this point the main frame may have deferred commits to avoid committing
832 // right now.
833 if (defer_main_frame_update_ || defer_commits_ ||
834 begin_frame_args.animate_only) {
835 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame",
836 TRACE_EVENT_SCOPE_THREAD);
837 BeginMainFrameAbortedOnImplThread(
838 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
839 layer_tree_host_->DidBeginMainFrame();
840 return;
841 }
842
843 DoPainting();
844 }
845
DoBeginMainFrame(const viz::BeginFrameArgs & begin_frame_args)846 void SingleThreadProxy::DoBeginMainFrame(
847 const viz::BeginFrameArgs& begin_frame_args) {
848 // Only update scroll deltas if we are going to commit the frame, otherwise
849 // scroll offsets get confused.
850 if (!defer_commits_) {
851 // The impl-side scroll deltas may be manipulated directly via the
852 // InputHandler on the UI thread and the scale deltas may change when they
853 // are clamped on the impl thread.
854 std::unique_ptr<ScrollAndScaleSet> scroll_info =
855 host_impl_->ProcessScrollDeltas();
856 layer_tree_host_->ApplyScrollAndScale(scroll_info.get());
857 }
858 layer_tree_host_->ApplyMutatorEvents(host_impl_->TakeMutatorEvents());
859 layer_tree_host_->WillBeginMainFrame();
860 layer_tree_host_->BeginMainFrame(begin_frame_args);
861 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
862 layer_tree_host_->RequestMainFrameUpdate(false /* record_cc_metrics */);
863 }
864
DoPainting()865 void SingleThreadProxy::DoPainting() {
866 layer_tree_host_->UpdateLayers();
867
868 // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
869 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside
870 // thread_proxy.cc
871 if (scheduler_on_impl_thread_) {
872 scheduler_on_impl_thread_->NotifyReadyToCommit(
873 layer_tree_host_->begin_main_frame_metrics());
874 }
875 }
876
BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason)877 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread(
878 CommitEarlyOutReason reason) {
879 DebugScopedSetImplThread impl(task_runner_provider_);
880 DCHECK(scheduler_on_impl_thread_->CommitPending());
881 DCHECK(!host_impl_->pending_tree());
882
883 std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
884 host_impl_->BeginMainFrameAborted(
885 reason, std::move(empty_swap_promises),
886 scheduler_on_impl_thread_->last_dispatched_begin_main_frame_args());
887 scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
888 }
889
ScheduledActionDrawIfPossible()890 DrawResult SingleThreadProxy::ScheduledActionDrawIfPossible() {
891 DebugScopedSetImplThread impl(task_runner_provider_);
892 LayerTreeHostImpl::FrameData frame;
893 frame.begin_frame_ack =
894 scheduler_on_impl_thread_->CurrentBeginFrameAckForActiveTree();
895 frame.origin_begin_main_frame_args =
896 scheduler_on_impl_thread_->last_activate_origin_frame_args();
897 return DoComposite(&frame);
898 }
899
ScheduledActionDrawForced()900 DrawResult SingleThreadProxy::ScheduledActionDrawForced() {
901 NOTREACHED();
902 return INVALID_RESULT;
903 }
904
ScheduledActionCommit()905 void SingleThreadProxy::ScheduledActionCommit() {
906 DebugScopedSetMainThread main(task_runner_provider_);
907 DoCommit(scheduler_on_impl_thread_->last_dispatched_begin_main_frame_args());
908 }
909
ScheduledActionActivateSyncTree()910 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
911 DebugScopedSetImplThread impl(task_runner_provider_);
912 host_impl_->ActivateSyncTree();
913 }
914
ScheduledActionBeginLayerTreeFrameSinkCreation()915 void SingleThreadProxy::ScheduledActionBeginLayerTreeFrameSinkCreation() {
916 DebugScopedSetMainThread main(task_runner_provider_);
917 DCHECK(scheduler_on_impl_thread_);
918 // If possible, create the output surface in a post task. Synchronously
919 // creating the output surface makes tests more awkward since this differs
920 // from the ThreadProxy behavior. However, sometimes there is no
921 // task runner.
922 if (task_runner_provider_->MainThreadTaskRunner()) {
923 ScheduleRequestNewLayerTreeFrameSink();
924 } else {
925 RequestNewLayerTreeFrameSink();
926 }
927 }
928
ScheduledActionPrepareTiles()929 void SingleThreadProxy::ScheduledActionPrepareTiles() {
930 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles");
931 DebugScopedSetImplThread impl(task_runner_provider_);
932 host_impl_->PrepareTiles();
933 }
934
ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw)935 void SingleThreadProxy::ScheduledActionInvalidateLayerTreeFrameSink(
936 bool needs_redraw) {
937 // This is an Android WebView codepath, which only uses multi-thread
938 // compositor. So this should not occur in single-thread mode.
939 NOTREACHED() << "Android Webview use-case, so multi-thread only";
940 }
941
ScheduledActionPerformImplSideInvalidation()942 void SingleThreadProxy::ScheduledActionPerformImplSideInvalidation() {
943 DCHECK(scheduler_on_impl_thread_);
944
945 DebugScopedSetImplThread impl(task_runner_provider_);
946 host_impl_->InvalidateContentOnImplSide();
947
948 // Invalidations go directly to the active tree, so we synchronously call
949 // NotifyReadyToActivate to update the scheduler and LTHI state correctly.
950 // Since in single-threaded mode the scheduler will wait for a ready to draw
951 // signal from LTHI, the draw will remain blocked till the invalidated tiles
952 // are ready.
953 NotifyReadyToActivate();
954 }
955
DidFinishImplFrame()956 void SingleThreadProxy::DidFinishImplFrame() {
957 host_impl_->DidFinishImplFrame(
958 scheduler_on_impl_thread_->last_activate_origin_frame_args());
959 #if DCHECK_IS_ON()
960 DCHECK(inside_impl_frame_)
961 << "DidFinishImplFrame called while not inside an impl frame!";
962 inside_impl_frame_ = false;
963 #endif
964 }
965
DidNotProduceFrame(const viz::BeginFrameAck & ack,FrameSkippedReason reason)966 void SingleThreadProxy::DidNotProduceFrame(const viz::BeginFrameAck& ack,
967 FrameSkippedReason reason) {
968 DebugScopedSetImplThread impl(task_runner_provider_);
969 host_impl_->DidNotProduceFrame(ack, reason);
970 }
971
WillNotReceiveBeginFrame()972 void SingleThreadProxy::WillNotReceiveBeginFrame() {
973 host_impl_->DidNotNeedBeginFrame();
974 }
975
DidReceiveCompositorFrameAck()976 void SingleThreadProxy::DidReceiveCompositorFrameAck() {
977 layer_tree_host_->DidReceiveCompositorFrameAck();
978 }
979
980 } // namespace cc
981