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