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