1 // Copyright 2015 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/proxy_impl.h"
6 
7 #include <string.h>
8 
9 #include <algorithm>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/auto_reset.h"
15 #include "base/bind.h"
16 #include "base/trace_event/trace_event.h"
17 #include "base/trace_event/traced_value.h"
18 #include "cc/base/devtools_instrumentation.h"
19 #include "cc/base/features.h"
20 #include "cc/benchmarks/benchmark_instrumentation.h"
21 #include "cc/input/browser_controls_offset_manager.h"
22 #include "cc/metrics/compositor_timing_history.h"
23 #include "cc/paint/paint_worklet_layer_painter.h"
24 #include "cc/trees/compositor_commit_data.h"
25 #include "cc/trees/layer_tree_frame_sink.h"
26 #include "cc/trees/layer_tree_host.h"
27 #include "cc/trees/layer_tree_impl.h"
28 #include "cc/trees/mutator_host.h"
29 #include "cc/trees/proxy_main.h"
30 #include "cc/trees/render_frame_metadata_observer.h"
31 #include "cc/trees/task_runner_provider.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 #include "gpu/command_buffer/client/gles2_interface.h"
36 #include "services/metrics/public/cpp/ukm_recorder.h"
37 
38 namespace cc {
39 
40 namespace {
41 
42 // Measured in seconds.
43 constexpr auto kSmoothnessTakesPriorityExpirationDelay =
44     base::TimeDelta::FromMilliseconds(250);
45 
46 }  // namespace
47 
48 // Ensures that a CompletionEvent is always signaled.
49 class ScopedCompletionEvent {
50  public:
ScopedCompletionEvent(CompletionEvent * event)51   explicit ScopedCompletionEvent(CompletionEvent* event) : event_(event) {}
52   ScopedCompletionEvent(const ScopedCompletionEvent&) = delete;
~ScopedCompletionEvent()53   ~ScopedCompletionEvent() { event_->Signal(); }
54 
55   ScopedCompletionEvent& operator=(const ScopedCompletionEvent&) = delete;
56 
57  private:
58   CompletionEvent* const event_;
59 };
60 
ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,LayerTreeHost * layer_tree_host,TaskRunnerProvider * task_runner_provider)61 ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
62                      LayerTreeHost* layer_tree_host,
63                      TaskRunnerProvider* task_runner_provider)
64     : layer_tree_host_id_(layer_tree_host->GetId()),
65       commit_completion_waits_for_activation_(false),
66       next_frame_is_newly_committed_frame_(false),
67       inside_draw_(false),
68       task_runner_provider_(task_runner_provider),
69       smoothness_priority_expiration_notifier_(
70           task_runner_provider->ImplThreadTaskRunner(),
71           base::BindRepeating(&ProxyImpl::RenewTreePriority,
72                               base::Unretained(this)),
73           kSmoothnessTakesPriorityExpirationDelay),
74       proxy_main_weak_ptr_(proxy_main_weak_ptr) {
75   TRACE_EVENT0("cc", "ProxyImpl::ProxyImpl");
76   DCHECK(IsImplThread());
77   DCHECK(IsMainThreadBlocked());
78 
79   host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this);
80   const LayerTreeSettings& settings = layer_tree_host->GetSettings();
81   send_compositor_frame_ack_ = settings.send_compositor_frame_ack;
82   last_raster_priority_ = SAME_PRIORITY_FOR_BOTH_TREES;
83 
84   SchedulerSettings scheduler_settings(settings.ToSchedulerSettings());
85 
86   std::unique_ptr<CompositorTimingHistory> compositor_timing_history(
87       new CompositorTimingHistory(
88           scheduler_settings.using_synchronous_renderer_compositor,
89           CompositorTimingHistory::RENDERER_UMA,
90           layer_tree_host->rendering_stats_instrumentation(),
91           host_impl_->compositor_frame_reporting_controller()));
92   scheduler_.reset(new Scheduler(this, scheduler_settings, layer_tree_host_id_,
93                                  task_runner_provider_->ImplThreadTaskRunner(),
94                                  std::move(compositor_timing_history)));
95 
96   DCHECK_EQ(scheduler_->visible(), host_impl_->visible());
97 }
98 
BlockedMainCommitOnly()99 ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly()
100     : layer_tree_host(nullptr) {}
101 
102 ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() = default;
103 
~ProxyImpl()104 ProxyImpl::~ProxyImpl() {
105   TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl");
106   DCHECK(IsImplThread());
107   DCHECK(IsMainThreadBlocked());
108 
109   // Prevent the scheduler from performing actions while we're in an
110   // inconsistent state.
111   scheduler_->Stop();
112   // Take away the LayerTreeFrameSink before destroying things so it doesn't
113   // try to call into its client mid-shutdown.
114   host_impl_->ReleaseLayerTreeFrameSink();
115 
116   // It is important to destroy LTHI before the Scheduler since it can make
117   // callbacks that access it during destruction cleanup.
118   host_impl_ = nullptr;
119   scheduler_ = nullptr;
120 
121   // We need to explicitly shutdown the notifier to destroy any weakptrs it is
122   // holding while still on the compositor thread. This also ensures any
123   // callbacks holding a ProxyImpl pointer are cancelled.
124   smoothness_priority_expiration_notifier_.Shutdown();
125 }
126 
InitializeMutatorOnImpl(std::unique_ptr<LayerTreeMutator> mutator)127 void ProxyImpl::InitializeMutatorOnImpl(
128     std::unique_ptr<LayerTreeMutator> mutator) {
129   TRACE_EVENT0("cc", "ProxyImpl::InitializeMutatorOnImpl");
130   DCHECK(IsImplThread());
131   host_impl_->SetLayerTreeMutator(std::move(mutator));
132 }
133 
InitializePaintWorkletLayerPainterOnImpl(std::unique_ptr<PaintWorkletLayerPainter> painter)134 void ProxyImpl::InitializePaintWorkletLayerPainterOnImpl(
135     std::unique_ptr<PaintWorkletLayerPainter> painter) {
136   TRACE_EVENT0("cc", "ProxyImpl::InitializePaintWorkletLayerPainterOnImpl");
137   DCHECK(IsImplThread());
138   host_impl_->SetPaintWorkletLayerPainter(std::move(painter));
139 }
140 
UpdateBrowserControlsStateOnImpl(BrowserControlsState constraints,BrowserControlsState current,bool animate)141 void ProxyImpl::UpdateBrowserControlsStateOnImpl(
142     BrowserControlsState constraints,
143     BrowserControlsState current,
144     bool animate) {
145   DCHECK(IsImplThread());
146   host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
147       constraints, current, animate);
148 }
149 
InitializeLayerTreeFrameSinkOnImpl(LayerTreeFrameSink * layer_tree_frame_sink,base::WeakPtr<ProxyMain> proxy_main_frame_sink_bound_weak_ptr)150 void ProxyImpl::InitializeLayerTreeFrameSinkOnImpl(
151     LayerTreeFrameSink* layer_tree_frame_sink,
152     base::WeakPtr<ProxyMain> proxy_main_frame_sink_bound_weak_ptr) {
153   TRACE_EVENT0("cc", "ProxyImpl::InitializeLayerTreeFrameSinkOnImplThread");
154   DCHECK(IsImplThread());
155 
156   proxy_main_frame_sink_bound_weak_ptr_ = proxy_main_frame_sink_bound_weak_ptr;
157 
158   LayerTreeHostImpl* host_impl = host_impl_.get();
159   bool success = host_impl->InitializeFrameSink(layer_tree_frame_sink);
160   MainThreadTaskRunner()->PostTask(
161       FROM_HERE, base::BindOnce(&ProxyMain::DidInitializeLayerTreeFrameSink,
162                                 proxy_main_weak_ptr_, success));
163   if (success)
164     scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
165 }
166 
SetDeferBeginMainFrameOnImpl(bool defer_begin_main_frame) const167 void ProxyImpl::SetDeferBeginMainFrameOnImpl(
168     bool defer_begin_main_frame) const {
169   DCHECK(IsImplThread());
170   scheduler_->SetDeferBeginMainFrame(defer_begin_main_frame);
171 }
172 
SetNeedsRedrawOnImpl(const gfx::Rect & damage_rect)173 void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
174   DCHECK(IsImplThread());
175   host_impl_->SetViewportDamage(damage_rect);
176   SetNeedsRedrawOnImplThread();
177 }
178 
SetNeedsCommitOnImpl()179 void ProxyImpl::SetNeedsCommitOnImpl() {
180   DCHECK(IsImplThread());
181   SetNeedsCommitOnImplThread();
182 }
183 
BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason,base::TimeTicks main_thread_start_time,std::vector<std::unique_ptr<SwapPromise>> swap_promises)184 void ProxyImpl::BeginMainFrameAbortedOnImpl(
185     CommitEarlyOutReason reason,
186     base::TimeTicks main_thread_start_time,
187     std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
188   TRACE_EVENT1("cc", "ProxyImpl::BeginMainFrameAbortedOnImplThread", "reason",
189                CommitEarlyOutReasonToString(reason));
190   DCHECK(IsImplThread());
191   DCHECK(scheduler_->CommitPending());
192 
193   host_impl_->BeginMainFrameAborted(
194       reason, std::move(swap_promises),
195       scheduler_->last_dispatched_begin_main_frame_args());
196   scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
197   scheduler_->BeginMainFrameAborted(reason);
198 }
199 
SetVisibleOnImpl(bool visible)200 void ProxyImpl::SetVisibleOnImpl(bool visible) {
201   TRACE_EVENT1("cc", "ProxyImpl::SetVisibleOnImplThread", "visible", visible);
202   DCHECK(IsImplThread());
203   host_impl_->SetVisible(visible);
204   scheduler_->SetVisible(visible);
205 }
206 
ReleaseLayerTreeFrameSinkOnImpl(CompletionEvent * completion)207 void ProxyImpl::ReleaseLayerTreeFrameSinkOnImpl(CompletionEvent* completion) {
208   DCHECK(IsImplThread());
209 
210   // Unlike DidLoseLayerTreeFrameSinkOnImplThread, we don't need to call
211   // LayerTreeHost::DidLoseLayerTreeFrameSink since it already knows.
212   scheduler_->DidLoseLayerTreeFrameSink();
213   host_impl_->ReleaseLayerTreeFrameSink();
214   completion->Signal();
215 }
216 
FinishGLOnImpl(CompletionEvent * completion)217 void ProxyImpl::FinishGLOnImpl(CompletionEvent* completion) {
218   TRACE_EVENT0("cc", "ProxyImpl::FinishGLOnImplThread");
219   DCHECK(IsImplThread());
220   if (host_impl_->layer_tree_frame_sink()) {
221     viz::ContextProvider* context_provider =
222         host_impl_->layer_tree_frame_sink()->context_provider();
223     if (context_provider)
224       context_provider->ContextGL()->Finish();
225   }
226   completion->Signal();
227 }
228 
MainFrameWillHappenOnImplForTesting(CompletionEvent * completion,bool * main_frame_will_happen)229 void ProxyImpl::MainFrameWillHappenOnImplForTesting(
230     CompletionEvent* completion,
231     bool* main_frame_will_happen) {
232   DCHECK(IsImplThread());
233   if (host_impl_->layer_tree_frame_sink()) {
234     *main_frame_will_happen = scheduler_->MainFrameForTestingWillHappen();
235   } else {
236     *main_frame_will_happen = false;
237   }
238   completion->Signal();
239 }
240 
RequestBeginMainFrameNotExpected(bool new_state)241 void ProxyImpl::RequestBeginMainFrameNotExpected(bool new_state) {
242   DCHECK(IsImplThread());
243   DCHECK(scheduler_);
244   TRACE_EVENT1("cc", "ProxyImpl::RequestBeginMainFrameNotExpected", "new_state",
245                new_state);
246   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(new_state);
247 }
248 
IsInSynchronousComposite() const249 bool ProxyImpl::IsInSynchronousComposite() const {
250   return false;
251 }
252 
NotifyReadyToCommitOnImpl(CompletionEvent * completion,LayerTreeHost * layer_tree_host,base::TimeTicks main_thread_start_time,const viz::BeginFrameArgs & commit_args,bool hold_commit_for_activation)253 void ProxyImpl::NotifyReadyToCommitOnImpl(
254     CompletionEvent* completion,
255     LayerTreeHost* layer_tree_host,
256     base::TimeTicks main_thread_start_time,
257     const viz::BeginFrameArgs& commit_args,
258     bool hold_commit_for_activation) {
259   TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToCommitOnImpl");
260   DCHECK(!commit_completion_event_);
261   DCHECK(IsImplThread() && IsMainThreadBlocked());
262   DCHECK(scheduler_);
263   DCHECK(scheduler_->CommitPending());
264 
265   if (!host_impl_) {
266     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree",
267                          TRACE_EVENT_SCOPE_THREAD);
268     completion->Signal();
269     return;
270   }
271 
272   // Ideally, we should inform to impl thread when BeginMainFrame is started.
273   // But, we can avoid a PostTask in here.
274   scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
275 
276   auto begin_main_frame_metrics = layer_tree_host->begin_main_frame_metrics();
277   host_impl_->ReadyToCommit(commit_args, begin_main_frame_metrics.get());
278 
279   commit_completion_event_ =
280       std::make_unique<ScopedCompletionEvent>(completion);
281   commit_completion_waits_for_activation_ = hold_commit_for_activation;
282 
283   DCHECK(!blocked_main_commit().layer_tree_host);
284   blocked_main_commit().layer_tree_host = layer_tree_host;
285 
286   // Inform the layer tree host that the commit has started, so that metrics
287   // can determine how long we waited for thread synchronization.
288   layer_tree_host->SetImplCommitStartTime(base::TimeTicks::Now());
289 
290   // Extract metrics data from the layer tree host and send them to the
291   // scheduler to pass them to the compositor_timing_history object.
292   scheduler_->NotifyReadyToCommit(std::move(begin_main_frame_metrics));
293 }
294 
DidLoseLayerTreeFrameSinkOnImplThread()295 void ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread() {
296   TRACE_EVENT0("cc", "ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread");
297   DCHECK(IsImplThread());
298   MainThreadTaskRunner()->PostTask(
299       FROM_HERE, base::BindOnce(&ProxyMain::DidLoseLayerTreeFrameSink,
300                                 proxy_main_weak_ptr_));
301   scheduler_->DidLoseLayerTreeFrameSink();
302 }
303 
SetBeginFrameSource(viz::BeginFrameSource * source)304 void ProxyImpl::SetBeginFrameSource(viz::BeginFrameSource* source) {
305   // During shutdown, destroying the LayerTreeFrameSink may unset the
306   // viz::BeginFrameSource.
307   if (scheduler_) {
308     // TODO(enne): this overrides any preexisting begin frame source.  Those
309     // other sources will eventually be removed and this will be the only path.
310     scheduler_->SetBeginFrameSource(source);
311   }
312 }
313 
DidReceiveCompositorFrameAckOnImplThread()314 void ProxyImpl::DidReceiveCompositorFrameAckOnImplThread() {
315   TRACE_EVENT0("cc,benchmark",
316                "ProxyImpl::DidReceiveCompositorFrameAckOnImplThread");
317   DCHECK(IsImplThread());
318   scheduler_->DidReceiveCompositorFrameAck();
319   if (send_compositor_frame_ack_) {
320     MainThreadTaskRunner()->PostTask(
321         FROM_HERE, base::BindOnce(&ProxyMain::DidReceiveCompositorFrameAck,
322                                   proxy_main_frame_sink_bound_weak_ptr_));
323   }
324 }
325 
OnCanDrawStateChanged(bool can_draw)326 void ProxyImpl::OnCanDrawStateChanged(bool can_draw) {
327   TRACE_EVENT1("cc", "ProxyImpl::OnCanDrawStateChanged", "can_draw", can_draw);
328   DCHECK(IsImplThread());
329   scheduler_->SetCanDraw(can_draw);
330 }
331 
NotifyReadyToActivate()332 void ProxyImpl::NotifyReadyToActivate() {
333   TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToActivate");
334   DCHECK(IsImplThread());
335   scheduler_->NotifyReadyToActivate();
336 }
337 
NotifyReadyToDraw()338 void ProxyImpl::NotifyReadyToDraw() {
339   TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToDraw");
340   DCHECK(IsImplThread());
341   scheduler_->NotifyReadyToDraw();
342 }
343 
SetNeedsRedrawOnImplThread()344 void ProxyImpl::SetNeedsRedrawOnImplThread() {
345   TRACE_EVENT0("cc", "ProxyImpl::SetNeedsRedrawOnImplThread");
346   DCHECK(IsImplThread());
347   scheduler_->SetNeedsRedraw();
348 }
349 
SetNeedsOneBeginImplFrameOnImplThread()350 void ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread() {
351   TRACE_EVENT0("cc", "ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread");
352   DCHECK(IsImplThread());
353   scheduler_->SetNeedsOneBeginImplFrame();
354 }
355 
SetNeedsPrepareTilesOnImplThread()356 void ProxyImpl::SetNeedsPrepareTilesOnImplThread() {
357   DCHECK(IsImplThread());
358   scheduler_->SetNeedsPrepareTiles();
359 }
360 
SetNeedsCommitOnImplThread()361 void ProxyImpl::SetNeedsCommitOnImplThread() {
362   TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
363   DCHECK(IsImplThread());
364   scheduler_->SetNeedsBeginMainFrame();
365 }
366 
SetVideoNeedsBeginFrames(bool needs_begin_frames)367 void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
368   TRACE_EVENT1("cc", "ProxyImpl::SetVideoNeedsBeginFrames",
369                "needs_begin_frames", needs_begin_frames);
370   DCHECK(IsImplThread());
371   // In tests the layer tree is destroyed after the scheduler is.
372   if (scheduler_)
373     scheduler_->SetVideoNeedsBeginFrames(needs_begin_frames);
374 }
375 
HasCustomPropertyAnimations() const376 bool ProxyImpl::HasCustomPropertyAnimations() const {
377   return host_impl_->mutator_host()->HasCustomPropertyAnimations();
378 }
379 
IsInsideDraw()380 bool ProxyImpl::IsInsideDraw() {
381   return inside_draw_;
382 }
383 
IsBeginMainFrameExpected()384 bool ProxyImpl::IsBeginMainFrameExpected() {
385   // Check whether the main-thread has requested for updates. If main-thread has
386   // not responded to a previously dispatched BeginMainFrame, then assume that
387   // main-thread would want to produce an update for the current frame too.
388   return scheduler_->needs_begin_main_frame() ||
389          scheduler_->IsBeginMainFrameSent();
390 }
391 
RenewTreePriority()392 void ProxyImpl::RenewTreePriority() {
393   DCHECK(IsImplThread());
394 
395   bool scroll_type_considered_interaction = false;
396   bool non_scroll_interaction_in_progress =
397       host_impl_->IsPinchGestureActive() ||
398       host_impl_->page_scale_animation_active();
399 
400   ActivelyScrollingType actively_scrolling_type =
401       host_impl_->GetActivelyScrollingType();
402 
403   switch (actively_scrolling_type) {
404     case ActivelyScrollingType::kNone:
405       break;
406     case ActivelyScrollingType::kPrecise:
407       scroll_type_considered_interaction = true;
408       break;
409     case ActivelyScrollingType::kAnimated:
410       scroll_type_considered_interaction = base::FeatureList::IsEnabled(
411           features::kSchedulerSmoothnessForAnimatedScrolls);
412   }
413 
414   bool user_interaction_in_progress =
415       non_scroll_interaction_in_progress || scroll_type_considered_interaction;
416 
417   if (host_impl_->ukm_manager()) {
418     host_impl_->ukm_manager()->SetUserInteractionInProgress(
419         user_interaction_in_progress);
420   }
421 
422   // Schedule expiration if smoothness currently takes priority.
423   if (user_interaction_in_progress)
424     smoothness_priority_expiration_notifier_.Schedule();
425 
426   // We use the same priority for both trees by default.
427   TreePriority scheduler_tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
428   TreePriority raster_tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
429 
430   // Smoothness takes priority if we have an expiration for it scheduled.
431   if (smoothness_priority_expiration_notifier_.HasPendingNotification()) {
432     scheduler_tree_priority = SMOOTHNESS_TAKES_PRIORITY;
433     if (non_scroll_interaction_in_progress ||
434         actively_scrolling_type == ActivelyScrollingType::kPrecise ||
435         last_raster_priority_ == SMOOTHNESS_TAKES_PRIORITY)
436       raster_tree_priority = SMOOTHNESS_TAKES_PRIORITY;
437   }
438 
439   last_raster_priority_ = raster_tree_priority;
440 
441   // New content always takes priority when ui resources have been evicted.
442   if (host_impl_->active_tree()->GetDeviceViewport().size().IsEmpty() ||
443       host_impl_->EvictedUIResourcesExist()) {
444     // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
445     // tree might be freed. We need to set RequiresHighResToDraw to ensure that
446     // high res tiles will be required to activate pending tree.
447     host_impl_->SetRequiresHighResToDraw();
448     scheduler_tree_priority = raster_tree_priority = NEW_CONTENT_TAKES_PRIORITY;
449   }
450 
451   host_impl_->SetTreePriority(raster_tree_priority);
452 
453   // Only put the scheduler in impl latency prioritization mode if we don't
454   // have a scroll listener. This gives the scroll listener a better chance of
455   // handling scroll updates within the same frame. The tree itself is still
456   // kept in prefer smoothness mode to allow checkerboarding.
457   ScrollHandlerState scroll_handler_state =
458       host_impl_->ScrollAffectsScrollHandler()
459           ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
460           : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
461   scheduler_->SetTreePrioritiesAndScrollState(scheduler_tree_priority,
462                                               scroll_handler_state);
463 }
464 
PostDelayedAnimationTaskOnImplThread(base::OnceClosure task,base::TimeDelta delay)465 void ProxyImpl::PostDelayedAnimationTaskOnImplThread(base::OnceClosure task,
466                                                      base::TimeDelta delay) {
467   DCHECK(IsImplThread());
468   task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(
469       FROM_HERE, std::move(task), delay);
470 }
471 
DidActivateSyncTree()472 void ProxyImpl::DidActivateSyncTree() {
473   TRACE_EVENT0("cc", "ProxyImpl::DidActivateSyncTreeOnImplThread");
474   DCHECK(IsImplThread());
475 
476   if (activation_completion_event_) {
477     TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
478                          TRACE_EVENT_SCOPE_THREAD);
479     activation_completion_event_ = nullptr;
480   }
481 }
482 
WillPrepareTiles()483 void ProxyImpl::WillPrepareTiles() {
484   DCHECK(IsImplThread());
485   scheduler_->WillPrepareTiles();
486 }
487 
DidPrepareTiles()488 void ProxyImpl::DidPrepareTiles() {
489   DCHECK(IsImplThread());
490   scheduler_->DidPrepareTiles();
491 }
492 
DidCompletePageScaleAnimationOnImplThread()493 void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() {
494   DCHECK(IsImplThread());
495   MainThreadTaskRunner()->PostTask(
496       FROM_HERE, base::BindOnce(&ProxyMain::DidCompletePageScaleAnimation,
497                                 proxy_main_weak_ptr_));
498 }
499 
OnDrawForLayerTreeFrameSink(bool resourceless_software_draw,bool skip_draw)500 void ProxyImpl::OnDrawForLayerTreeFrameSink(bool resourceless_software_draw,
501                                             bool skip_draw) {
502   DCHECK(IsImplThread());
503   scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw,
504                                           skip_draw);
505 }
506 
NeedsImplSideInvalidation(bool needs_first_draw_on_activation)507 void ProxyImpl::NeedsImplSideInvalidation(bool needs_first_draw_on_activation) {
508   DCHECK(IsImplThread());
509   scheduler_->SetNeedsImplSideInvalidation(needs_first_draw_on_activation);
510 }
511 
NotifyImageDecodeRequestFinished()512 void ProxyImpl::NotifyImageDecodeRequestFinished() {
513   DCHECK(IsImplThread());
514   SetNeedsCommitOnImplThread();
515 }
516 
DidPresentCompositorFrameOnImplThread(uint32_t frame_token,std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,const viz::FrameTimingDetails & details)517 void ProxyImpl::DidPresentCompositorFrameOnImplThread(
518     uint32_t frame_token,
519     std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
520     const viz::FrameTimingDetails& details) {
521   MainThreadTaskRunner()->PostTask(
522       FROM_HERE,
523       base::BindOnce(&ProxyMain::DidPresentCompositorFrame,
524                      proxy_main_weak_ptr_, frame_token, std::move(callbacks),
525                      details.presentation_feedback));
526   if (scheduler_)
527     scheduler_->DidPresentCompositorFrame(frame_token, details);
528 }
529 
NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state,ElementListType element_list_type)530 void ProxyImpl::NotifyAnimationWorkletStateChange(
531     AnimationWorkletMutationState state,
532     ElementListType element_list_type) {
533   DCHECK(IsImplThread());
534   Scheduler::AnimationWorkletState animation_worklet_state =
535       (state == AnimationWorkletMutationState::STARTED)
536           ? Scheduler::AnimationWorkletState::PROCESSING
537           : Scheduler::AnimationWorkletState::IDLE;
538   Scheduler::TreeType tree_type = (element_list_type == ElementListType::ACTIVE)
539                                       ? Scheduler::TreeType::ACTIVE
540                                       : Scheduler::TreeType::PENDING;
541   scheduler_->NotifyAnimationWorkletStateChange(animation_worklet_state,
542                                                 tree_type);
543 }
544 
NotifyPaintWorkletStateChange(Scheduler::PaintWorkletState state)545 void ProxyImpl::NotifyPaintWorkletStateChange(
546     Scheduler::PaintWorkletState state) {
547   DCHECK(IsImplThread());
548   scheduler_->NotifyPaintWorkletStateChange(state);
549 }
550 
NotifyThroughputTrackerResults(CustomTrackerResults results)551 void ProxyImpl::NotifyThroughputTrackerResults(CustomTrackerResults results) {
552   DCHECK(IsImplThread());
553   MainThreadTaskRunner()->PostTask(
554       FROM_HERE, base::BindOnce(&ProxyMain::NotifyThroughputTrackerResults,
555                                 proxy_main_weak_ptr_, std::move(results)));
556 }
557 
DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay,base::TimeTicks first_scroll_timestamp)558 void ProxyImpl::DidObserveFirstScrollDelay(
559     base::TimeDelta first_scroll_delay,
560     base::TimeTicks first_scroll_timestamp) {
561   DCHECK(IsImplThread());
562   MainThreadTaskRunner()->PostTask(
563       FROM_HERE, base::BindOnce(&ProxyMain::DidObserveFirstScrollDelay,
564                                 proxy_main_weak_ptr_, first_scroll_delay,
565                                 first_scroll_timestamp));
566 }
567 
WillBeginImplFrame(const viz::BeginFrameArgs & args)568 bool ProxyImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
569   DCHECK(IsImplThread());
570   return host_impl_->WillBeginImplFrame(args);
571 }
572 
DidFinishImplFrame(const viz::BeginFrameArgs & last_activated_args)573 void ProxyImpl::DidFinishImplFrame(
574     const viz::BeginFrameArgs& last_activated_args) {
575   DCHECK(IsImplThread());
576   host_impl_->DidFinishImplFrame(last_activated_args);
577 }
578 
DidNotProduceFrame(const viz::BeginFrameAck & ack,FrameSkippedReason reason)579 void ProxyImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack,
580                                    FrameSkippedReason reason) {
581   DCHECK(IsImplThread());
582   host_impl_->DidNotProduceFrame(ack, reason);
583 }
584 
WillNotReceiveBeginFrame()585 void ProxyImpl::WillNotReceiveBeginFrame() {
586   DCHECK(IsImplThread());
587   host_impl_->DidNotNeedBeginFrame();
588 }
589 
ScheduledActionSendBeginMainFrame(const viz::BeginFrameArgs & args)590 void ProxyImpl::ScheduledActionSendBeginMainFrame(
591     const viz::BeginFrameArgs& args) {
592   DCHECK(IsImplThread());
593   benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
594       benchmark_instrumentation::kSendBeginFrame,
595       args.frame_id.sequence_number);
596   std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
597       new BeginMainFrameAndCommitState);
598   begin_main_frame_state->begin_frame_args = args;
599   begin_main_frame_state->commit_data = host_impl_->ProcessCompositorDeltas();
600   begin_main_frame_state->completed_image_decode_requests =
601       host_impl_->TakeCompletedImageDecodeRequests();
602   begin_main_frame_state->mutator_events = host_impl_->TakeMutatorEvents();
603   begin_main_frame_state->active_sequence_trackers =
604       host_impl_->FrameSequenceTrackerActiveTypes();
605   begin_main_frame_state->evicted_ui_resources =
606       host_impl_->EvictedUIResourcesExist();
607   host_impl_->WillSendBeginMainFrame();
608   MainThreadTaskRunner()->PostTask(
609       FROM_HERE,
610       base::BindOnce(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_,
611                      std::move(begin_main_frame_state)));
612   host_impl_->DidSendBeginMainFrame(args);
613   devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_);
614 }
615 
ScheduledActionDrawIfPossible()616 DrawResult ProxyImpl::ScheduledActionDrawIfPossible() {
617   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDraw");
618   DCHECK(IsImplThread());
619 
620   // The scheduler should never generate this call when it can't draw.
621   DCHECK(host_impl_->CanDraw());
622 
623   bool forced_draw = false;
624   return DrawInternal(forced_draw);
625 }
626 
ScheduledActionDrawForced()627 DrawResult ProxyImpl::ScheduledActionDrawForced() {
628   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawForced");
629   DCHECK(IsImplThread());
630   bool forced_draw = true;
631   return DrawInternal(forced_draw);
632 }
633 
ScheduledActionCommit()634 void ProxyImpl::ScheduledActionCommit() {
635   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionCommit");
636   DCHECK(IsImplThread());
637   DCHECK(IsMainThreadBlocked());
638   DCHECK(commit_completion_event_);
639 
640   // Relax the cross-thread access restriction to non-thread-safe RefCount.
641   // It's safe since the main thread is blocked while a main-thread-bound
642   // compositor stuff are accessed from the impl thread.
643   base::ScopedAllowCrossThreadRefCountAccess
644       allow_cross_thread_ref_count_access;
645 
646   host_impl_->BeginCommit();
647   blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
648       host_impl_.get());
649 
650   // Remove the LayerTreeHost reference before the completion event is signaled
651   // and cleared. This is necessary since blocked_main_commit() allows access
652   // only while we have the completion event to ensure the main thread is
653   // blocked for a commit.
654   blocked_main_commit().layer_tree_host = nullptr;
655 
656   if (commit_completion_waits_for_activation_) {
657     // For some layer types in impl-side painting, the commit is held until the
658     // sync tree is activated.  It's also possible that the sync tree has
659     // already activated if there was no work to be done.
660     TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
661     commit_completion_waits_for_activation_ = false;
662     activation_completion_event_ = std::move(commit_completion_event_);
663   }
664   commit_completion_event_ = nullptr;
665 
666   scheduler_->DidCommit();
667 
668   // Delay this step until afer the main thread has been released as it's
669   // often a good bit of work to update the tree and prepare the new frame.
670   host_impl_->CommitComplete();
671 
672   next_frame_is_newly_committed_frame_ = true;
673 }
674 
ScheduledActionActivateSyncTree()675 void ProxyImpl::ScheduledActionActivateSyncTree() {
676   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionActivateSyncTree");
677   DCHECK(IsImplThread());
678   host_impl_->ActivateSyncTree();
679 }
680 
ScheduledActionBeginLayerTreeFrameSinkCreation()681 void ProxyImpl::ScheduledActionBeginLayerTreeFrameSinkCreation() {
682   TRACE_EVENT0("cc",
683                "ProxyImpl::ScheduledActionBeginLayerTreeFrameSinkCreation");
684   DCHECK(IsImplThread());
685   MainThreadTaskRunner()->PostTask(
686       FROM_HERE, base::BindOnce(&ProxyMain::RequestNewLayerTreeFrameSink,
687                                 proxy_main_weak_ptr_));
688 }
689 
ScheduledActionPrepareTiles()690 void ProxyImpl::ScheduledActionPrepareTiles() {
691   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPrepareTiles");
692   DCHECK(IsImplThread());
693   host_impl_->PrepareTiles();
694 }
695 
ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw)696 void ProxyImpl::ScheduledActionInvalidateLayerTreeFrameSink(bool needs_redraw) {
697   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionInvalidateLayerTreeFrameSink");
698   DCHECK(IsImplThread());
699   host_impl_->InvalidateLayerTreeFrameSink(needs_redraw);
700 }
701 
ScheduledActionPerformImplSideInvalidation()702 void ProxyImpl::ScheduledActionPerformImplSideInvalidation() {
703   TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPerformImplSideInvalidation");
704   DCHECK(IsImplThread());
705   host_impl_->InvalidateContentOnImplSide();
706 }
707 
SendBeginMainFrameNotExpectedSoon()708 void ProxyImpl::SendBeginMainFrameNotExpectedSoon() {
709   DCHECK(IsImplThread());
710   MainThreadTaskRunner()->PostTask(
711       FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrameNotExpectedSoon,
712                                 proxy_main_weak_ptr_));
713 }
714 
ScheduledActionBeginMainFrameNotExpectedUntil(base::TimeTicks time)715 void ProxyImpl::ScheduledActionBeginMainFrameNotExpectedUntil(
716     base::TimeTicks time) {
717   DCHECK(IsImplThread());
718   MainThreadTaskRunner()->PostTask(
719       FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrameNotExpectedUntil,
720                                 proxy_main_weak_ptr_, time));
721 }
722 
DrawInternal(bool forced_draw)723 DrawResult ProxyImpl::DrawInternal(bool forced_draw) {
724   DCHECK(IsImplThread());
725   DCHECK(host_impl_.get());
726 
727   base::AutoReset<bool> mark_inside(&inside_draw_, true);
728 
729   // This method is called on a forced draw, regardless of whether we are able
730   // to produce a frame, as the calling site on main thread is blocked until its
731   // request completes, and we signal completion here. If CanDraw() is false, we
732   // will indicate success=false to the caller, but we must still signal
733   // completion to avoid deadlock.
734 
735   // We guard PrepareToDraw() with CanDraw() because it always returns a valid
736   // frame, so can only be used when such a frame is possible. Since
737   // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
738   // CanDraw() as well.
739 
740   LayerTreeHostImpl::FrameData frame;
741   frame.begin_frame_ack = scheduler_->CurrentBeginFrameAckForActiveTree();
742   frame.origin_begin_main_frame_args =
743       scheduler_->last_activate_origin_frame_args();
744   bool draw_frame = false;
745 
746   DrawResult result;
747   if (host_impl_->CanDraw()) {
748     result = host_impl_->PrepareToDraw(&frame);
749     draw_frame = forced_draw || result == DRAW_SUCCESS;
750   } else {
751     result = DRAW_ABORTED_CANT_DRAW;
752   }
753 
754   if (draw_frame) {
755     if (host_impl_->DrawLayers(&frame)) {
756       DCHECK_NE(frame.frame_token, 0u);
757       // Drawing implies we submitted a frame to the LayerTreeFrameSink.
758       scheduler_->DidSubmitCompositorFrame(frame.frame_token,
759                                            host_impl_->TakeEventsMetrics());
760     }
761     result = DRAW_SUCCESS;
762   } else {
763     DCHECK_NE(DRAW_SUCCESS, result);
764   }
765 
766   host_impl_->DidDrawAllLayers(frame);
767 
768   bool start_ready_animations = draw_frame;
769   host_impl_->UpdateAnimationState(start_ready_animations);
770 
771   // Tell the main thread that the newly-commited frame was drawn.
772   if (next_frame_is_newly_committed_frame_) {
773     next_frame_is_newly_committed_frame_ = false;
774     MainThreadTaskRunner()->PostTask(
775         FROM_HERE, base::BindOnce(&ProxyMain::DidCommitAndDrawFrame,
776                                   proxy_main_weak_ptr_));
777   }
778 
779   // The tile visibility/priority of the pending tree needs to be updated so
780   // that it doesn't get activated before the raster is complete. But this needs
781   // to happen after the draw, off of the critical path to draw.
782   if (host_impl_->pending_tree())
783     host_impl_->pending_tree()->UpdateDrawProperties();
784 
785   DCHECK_NE(INVALID_RESULT, result);
786   return result;
787 }
788 
IsImplThread() const789 bool ProxyImpl::IsImplThread() const {
790   return task_runner_provider_->IsImplThread();
791 }
792 
IsMainThreadBlocked() const793 bool ProxyImpl::IsMainThreadBlocked() const {
794   return task_runner_provider_->IsMainThreadBlocked();
795 }
796 
blocked_main_commit()797 ProxyImpl::BlockedMainCommitOnly& ProxyImpl::blocked_main_commit() {
798   DCHECK(IsMainThreadBlocked() && commit_completion_event_);
799   return main_thread_blocked_commit_vars_unsafe_;
800 }
801 
MainThreadTaskRunner()802 base::SingleThreadTaskRunner* ProxyImpl::MainThreadTaskRunner() {
803   return task_runner_provider_->MainThreadTaskRunner();
804 }
805 
SetSourceURL(ukm::SourceId source_id,const GURL & url)806 void ProxyImpl::SetSourceURL(ukm::SourceId source_id, const GURL& url) {
807   DCHECK(IsImplThread());
808   host_impl_->SetActiveURL(url, source_id);
809 }
810 
SetUkmSmoothnessDestination(base::WritableSharedMemoryMapping ukm_smoothness_data)811 void ProxyImpl::SetUkmSmoothnessDestination(
812     base::WritableSharedMemoryMapping ukm_smoothness_data) {
813   DCHECK(IsImplThread());
814   host_impl_->SetUkmSmoothnessDestination(std::move(ukm_smoothness_data));
815 }
816 
ClearHistory()817 void ProxyImpl::ClearHistory() {
818   DCHECK(IsImplThread());
819   DCHECK(IsMainThreadBlocked());
820   scheduler_->ClearHistory();
821 }
822 
SetRenderFrameObserver(std::unique_ptr<RenderFrameMetadataObserver> observer)823 void ProxyImpl::SetRenderFrameObserver(
824     std::unique_ptr<RenderFrameMetadataObserver> observer) {
825   host_impl_->SetRenderFrameObserver(std::move(observer));
826 }
827 
SetEnableFrameRateThrottling(bool enable_frame_rate_throttling)828 void ProxyImpl::SetEnableFrameRateThrottling(
829     bool enable_frame_rate_throttling) {
830   host_impl_->SetEnableFrameRateThrottling(enable_frame_rate_throttling);
831 }
832 
833 }  // namespace cc
834