1 // Copyright (c) 2012 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 "ui/compositor/compositor.h"
6 
7 #include <stddef.h>
8 #include <algorithm>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "base/system/sys_info.h"
20 #include "base/trace_event/trace_event.h"
21 #include "build/build_config.h"
22 #include "cc/animation/animation_host.h"
23 #include "cc/animation/animation_id_provider.h"
24 #include "cc/animation/animation_timeline.h"
25 #include "cc/base/features.h"
26 #include "cc/base/switches.h"
27 #include "cc/input/input_handler.h"
28 #include "cc/layers/layer.h"
29 #include "cc/metrics/begin_main_frame_metrics.h"
30 #include "cc/metrics/frame_sequence_tracker.h"
31 #include "cc/trees/layer_tree_host.h"
32 #include "cc/trees/layer_tree_settings.h"
33 #include "components/viz/common/features.h"
34 #include "components/viz/common/frame_sinks/begin_frame_args.h"
35 #include "components/viz/common/frame_sinks/begin_frame_source.h"
36 #include "components/viz/common/gpu/context_provider.h"
37 #include "components/viz/common/resources/resource_format.h"
38 #include "components/viz/common/resources/resource_settings.h"
39 #include "components/viz/common/switches.h"
40 #include "components/viz/host/host_frame_sink_manager.h"
41 #include "components/viz/host/renderer_settings_creation.h"
42 #include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
43 #include "services/viz/privileged/mojom/compositing/external_begin_frame_controller.mojom.h"
44 #include "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom.h"
45 #include "third_party/skia/include/core/SkBitmap.h"
46 #include "ui/base/ui_base_features.h"
47 #include "ui/base/ui_base_switches.h"
48 #include "ui/compositor/compositor_observer.h"
49 #include "ui/compositor/compositor_switches.h"
50 #include "ui/compositor/layer.h"
51 #include "ui/compositor/layer_animator_collection.h"
52 #include "ui/compositor/overscroll/scroll_input_handler.h"
53 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
54 #include "ui/display/display_switches.h"
55 #include "ui/gfx/icc_profile.h"
56 #include "ui/gfx/switches.h"
57 #include "ui/gl/gl_switches.h"
58 
59 #if defined(OS_WIN)
60 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
61 #endif
62 
63 namespace ui {
64 
65 // Used to hold on to IssueExternalBeginFrame arguments if
66 // |external_begin_frame_controller_| isn't ready yet.
67 struct PendingBeginFrameArgs {
PendingBeginFrameArgsui::PendingBeginFrameArgs68   PendingBeginFrameArgs(
69       const viz::BeginFrameArgs& args,
70       bool force,
71       base::OnceCallback<void(const viz::BeginFrameAck&)> callback)
72       : args(args), force(force), callback(std::move(callback)) {}
73 
74   viz::BeginFrameArgs args;
75   bool force;
76   base::OnceCallback<void(const viz::BeginFrameAck&)> callback;
77 };
78 
Compositor(const viz::FrameSinkId & frame_sink_id,ui::ContextFactory * context_factory,scoped_refptr<base::SingleThreadTaskRunner> task_runner,bool enable_pixel_canvas,bool use_external_begin_frame_control,bool force_software_compositor)79 Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
80                        ui::ContextFactory* context_factory,
81                        scoped_refptr<base::SingleThreadTaskRunner> task_runner,
82                        bool enable_pixel_canvas,
83                        bool use_external_begin_frame_control,
84                        bool force_software_compositor)
85     : context_factory_(context_factory),
86       frame_sink_id_(frame_sink_id),
87       task_runner_(task_runner),
88       use_external_begin_frame_control_(use_external_begin_frame_control),
89       force_software_compositor_(force_software_compositor),
90       layer_animator_collection_(this),
91       is_pixel_canvas_(enable_pixel_canvas),
92       lock_manager_(task_runner) {
93   DCHECK(context_factory_);
94   auto* host_frame_sink_manager = context_factory_->GetHostFrameSinkManager();
95   host_frame_sink_manager->RegisterFrameSinkId(
96       frame_sink_id_, this, viz::ReportFirstSurfaceActivation::kNo);
97   host_frame_sink_manager->SetFrameSinkDebugLabel(frame_sink_id_, "Compositor");
98   root_web_layer_ = cc::Layer::Create();
99 
100   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
101 
102   cc::LayerTreeSettings settings;
103 
104   // This will ensure PictureLayers always can have LCD text, to match the
105   // previous behaviour with ContentLayers, where LCD-not-allowed notifications
106   // were ignored.
107   settings.layers_always_allowed_lcd_text = true;
108   // Use occlusion to allow more overlapping windows to take less memory.
109   settings.use_occlusion_for_tile_prioritization = true;
110   settings.main_frame_before_activation_enabled = false;
111 
112   // Disable edge anti-aliasing in order to increase support for HW overlays.
113   settings.enable_edge_anti_aliasing = false;
114 
115   // GPU rasterization in the UI compositor is controlled by a feature.
116   settings.gpu_rasterization_disabled =
117       !features::IsUiGpuRasterizationEnabled();
118 
119   if (command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders)) {
120     std::string layer_borders_string = command_line->GetSwitchValueASCII(
121         cc::switches::kUIShowCompositedLayerBorders);
122     std::vector<base::StringPiece> entries = base::SplitStringPiece(
123         layer_borders_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
124     if (entries.empty()) {
125       settings.initial_debug_state.show_debug_borders.set();
126     } else {
127       for (const auto& entry : entries) {
128         const struct {
129           const char* name;
130           cc::DebugBorderType type;
131         } kBorders[] = {{cc::switches::kCompositedRenderPassBorders,
132                          cc::DebugBorderType::RENDERPASS},
133                         {cc::switches::kCompositedSurfaceBorders,
134                          cc::DebugBorderType::SURFACE},
135                         {cc::switches::kCompositedLayerBorders,
136                          cc::DebugBorderType::LAYER}};
137         for (const auto& border : kBorders) {
138           if (border.name == entry) {
139             settings.initial_debug_state.show_debug_borders.set(border.type);
140             break;
141           }
142         }
143       }
144     }
145   }
146   settings.initial_debug_state.show_fps_counter =
147       command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
148   settings.initial_debug_state.show_layer_animation_bounds_rects =
149       command_line->HasSwitch(cc::switches::kUIShowLayerAnimationBounds);
150   settings.initial_debug_state.show_paint_rects =
151       command_line->HasSwitch(switches::kUIShowPaintRects);
152   settings.initial_debug_state.show_property_changed_rects =
153       command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects);
154   settings.initial_debug_state.show_surface_damage_rects =
155       command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects);
156   settings.initial_debug_state.show_screen_space_rects =
157       command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects);
158 
159   settings.initial_debug_state.SetRecordRenderingStats(
160       command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
161 
162   settings.use_zero_copy = IsUIZeroCopyEnabled();
163 
164   settings.use_layer_lists =
165       command_line->HasSwitch(cc::switches::kUIEnableLayerLists);
166 
167   // UI compositor always uses partial raster if not using zero-copy. Zero copy
168   // doesn't currently support partial raster.
169   settings.use_partial_raster = !settings.use_zero_copy;
170 
171   settings.use_rgba_4444 =
172       command_line->HasSwitch(switches::kUIEnableRGBA4444Textures);
173 
174 #if defined(OS_APPLE)
175   // Using CoreAnimation to composite requires using GpuMemoryBuffers, which
176   // require zero copy.
177   settings.resource_settings.use_gpu_memory_buffer_resources =
178       settings.use_zero_copy;
179   settings.enable_elastic_overscroll = true;
180 #endif
181 
182   settings.memory_policy.bytes_limit_when_visible = 512 * 1024 * 1024;
183 
184   // Used to configure ui compositor memory limit for chromeos devices.
185   // See crbug.com/923141.
186   if (command_line->HasSwitch(
187           switches::kUiCompositorMemoryLimitWhenVisibleMB)) {
188     std::string value_str = command_line->GetSwitchValueASCII(
189         switches::kUiCompositorMemoryLimitWhenVisibleMB);
190     unsigned value_in_mb;
191     if (base::StringToUint(value_str, &value_in_mb)) {
192       settings.memory_policy.bytes_limit_when_visible =
193           1024 * 1024 * value_in_mb;
194     }
195   }
196 
197   settings.memory_policy.priority_cutoff_when_visible =
198       gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
199 
200   settings.disallow_non_exact_resource_reuse =
201       command_line->HasSwitch(switches::kDisallowNonExactResourceReuse);
202 
203   settings.enable_impl_latency_recovery =
204       features::IsImplLatencyRecoveryEnabled();
205   settings.enable_main_latency_recovery =
206       features::IsMainLatencyRecoveryEnabled();
207 
208   if (command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)) {
209     settings.wait_for_all_pipeline_stages_before_draw = true;
210     settings.enable_impl_latency_recovery = false;
211     settings.enable_main_latency_recovery = false;
212   }
213 
214   if (base::FeatureList::IsEnabled(
215           features::kCompositorThreadedScrollbarScrolling)) {
216     settings.compositor_threaded_scrollbar_scrolling = true;
217   }
218 
219   if (base::FeatureList::IsEnabled(features::kPercentBasedScrolling)) {
220     settings.percent_based_scrolling = true;
221   }
222 
223 #if DCHECK_IS_ON()
224   if (command_line->HasSwitch(cc::switches::kLogOnUIDoubleBackgroundBlur))
225     settings.log_on_ui_double_background_blur = true;
226 #endif
227 
228   animation_host_ = cc::AnimationHost::CreateMainInstance();
229 
230   cc::LayerTreeHost::InitParams params;
231   params.client = this;
232   params.task_graph_runner = context_factory_->GetTaskGraphRunner();
233   params.settings = &settings;
234   params.main_task_runner = task_runner_;
235   params.mutator_host = animation_host_.get();
236   host_ = cc::LayerTreeHost::CreateSingleThreaded(this, std::move(params));
237 
238   const base::WeakPtr<cc::CompositorDelegateForInput>& compositor_delegate =
239       host_->GetDelegateForInput();
240   if (base::FeatureList::IsEnabled(features::kUiCompositorScrollWithLayers) &&
241       compositor_delegate) {
242     input_handler_weak_ = cc::InputHandler::Create(*compositor_delegate);
243     scroll_input_handler_.reset(new ScrollInputHandler(input_handler_weak_));
244   }
245 
246   animation_timeline_ =
247       cc::AnimationTimeline::Create(cc::AnimationIdProvider::NextTimelineId());
248   animation_host_->AddAnimationTimeline(animation_timeline_.get());
249 
250   host_->SetRootLayer(root_web_layer_);
251 
252   // This shouldn't be done in the constructor in order to match Widget.
253   // See: http://crbug.com/956264.
254   host_->SetVisible(true);
255 
256   if (command_line->HasSwitch(switches::kUISlowAnimations)) {
257     slow_animations_ = std::make_unique<ScopedAnimationDurationScaleMode>(
258         ScopedAnimationDurationScaleMode::SLOW_DURATION);
259   }
260 }
261 
~Compositor()262 Compositor::~Compositor() {
263   TRACE_EVENT0("shutdown,viz", "Compositor::destructor");
264 
265   for (auto& observer : observer_list_)
266     observer.OnCompositingShuttingDown(this);
267 
268   for (auto& observer : animation_observer_list_)
269     observer.OnCompositingShuttingDown(this);
270 
271   if (root_layer_)
272     root_layer_->ResetCompositor();
273 
274   if (animation_timeline_)
275     animation_host_->RemoveAnimationTimeline(animation_timeline_.get());
276 
277   // Stop all outstanding draws before telling the ContextFactory to tear
278   // down any contexts that the |host_| may rely upon.
279   host_.reset();
280 
281   context_factory_->RemoveCompositor(this);
282   auto* host_frame_sink_manager = context_factory_->GetHostFrameSinkManager();
283   for (auto& client : child_frame_sinks_) {
284     DCHECK(client.is_valid());
285     host_frame_sink_manager->UnregisterFrameSinkHierarchy(frame_sink_id_,
286                                                           client);
287   }
288   host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_);
289 }
290 
AddChildFrameSink(const viz::FrameSinkId & frame_sink_id)291 void Compositor::AddChildFrameSink(const viz::FrameSinkId& frame_sink_id) {
292   context_factory_->GetHostFrameSinkManager()->RegisterFrameSinkHierarchy(
293       frame_sink_id_, frame_sink_id);
294 
295   child_frame_sinks_.insert(frame_sink_id);
296 }
297 
RemoveChildFrameSink(const viz::FrameSinkId & frame_sink_id)298 void Compositor::RemoveChildFrameSink(const viz::FrameSinkId& frame_sink_id) {
299   auto it = child_frame_sinks_.find(frame_sink_id);
300   DCHECK(it != child_frame_sinks_.end());
301   DCHECK(it->is_valid());
302   context_factory_->GetHostFrameSinkManager()->UnregisterFrameSinkHierarchy(
303       frame_sink_id_, *it);
304   child_frame_sinks_.erase(it);
305 }
306 
SetLayerTreeFrameSink(std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink,viz::mojom::DisplayPrivate * display_private)307 void Compositor::SetLayerTreeFrameSink(
308     std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink,
309     viz::mojom::DisplayPrivate* display_private) {
310   layer_tree_frame_sink_requested_ = false;
311   display_private_ = display_private;
312   host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
313   // Display properties are reset when the output surface is lost, so update it
314   // to match the Compositor's.
315   if (display_private_) {
316     disabled_swap_until_resize_ = false;
317     display_private_->Resize(size());
318     display_private_->SetDisplayVisible(host_->IsVisible());
319     display_private_->SetDisplayColorSpaces(display_color_spaces_);
320     display_private_->SetDisplayColorMatrix(
321         gfx::Transform(display_color_matrix_));
322     display_private_->SetOutputIsSecure(output_is_secure_);
323     if (has_vsync_params_)
324       display_private_->SetDisplayVSyncParameters(vsync_timebase_,
325                                                   vsync_interval_);
326   }
327 }
328 
SetExternalBeginFrameController(viz::mojom::ExternalBeginFrameController * external_begin_frame_controller)329 void Compositor::SetExternalBeginFrameController(
330     viz::mojom::ExternalBeginFrameController* external_begin_frame_controller) {
331   DCHECK(use_external_begin_frame_control());
332   external_begin_frame_controller_ = external_begin_frame_controller;
333   if (pending_begin_frame_args_) {
334     external_begin_frame_controller_->IssueExternalBeginFrame(
335         pending_begin_frame_args_->args, pending_begin_frame_args_->force,
336         std::move(pending_begin_frame_args_->callback));
337     pending_begin_frame_args_.reset();
338   }
339 }
340 
OnChildResizing()341 void Compositor::OnChildResizing() {
342   for (auto& observer : observer_list_)
343     observer.OnCompositingChildResizing(this);
344 }
345 
ScheduleDraw()346 void Compositor::ScheduleDraw() {
347   host_->SetNeedsCommit();
348 }
349 
SetRootLayer(Layer * root_layer)350 void Compositor::SetRootLayer(Layer* root_layer) {
351   if (root_layer_ == root_layer)
352     return;
353   if (root_layer_)
354     root_layer_->ResetCompositor();
355   root_layer_ = root_layer;
356   root_web_layer_->RemoveAllChildren();
357   if (root_layer_)
358     root_layer_->SetCompositor(this, root_web_layer_);
359 }
360 
GetAnimationTimeline() const361 cc::AnimationTimeline* Compositor::GetAnimationTimeline() const {
362   return animation_timeline_.get();
363 }
364 
SetDisplayColorMatrix(const SkMatrix44 & matrix)365 void Compositor::SetDisplayColorMatrix(const SkMatrix44& matrix) {
366   display_color_matrix_ = matrix;
367   if (display_private_)
368     display_private_->SetDisplayColorMatrix(gfx::Transform(matrix));
369 }
370 
ScheduleFullRedraw()371 void Compositor::ScheduleFullRedraw() {
372   // TODO(enne): Some callers (mac) call this function expecting that it
373   // will also commit.  This should probably just redraw the screen
374   // from damage and not commit.  ScheduleDraw/ScheduleRedraw need
375   // better names.
376   host_->SetNeedsRedrawRect(host_->device_viewport_rect());
377   host_->SetNeedsCommit();
378 }
379 
ScheduleRedrawRect(const gfx::Rect & damage_rect)380 void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
381   // TODO(enne): Make this not commit.  See ScheduleFullRedraw.
382   host_->SetNeedsRedrawRect(damage_rect);
383   host_->SetNeedsCommit();
384 }
385 
386 #if defined(OS_WIN)
SetShouldDisableSwapUntilResize(bool should)387 void Compositor::SetShouldDisableSwapUntilResize(bool should) {
388   should_disable_swap_until_resize_ = should;
389 }
390 
DisableSwapUntilResize()391 void Compositor::DisableSwapUntilResize() {
392   if (should_disable_swap_until_resize_ && display_private_) {
393     // Browser needs to block for Viz to receive and process this message.
394     // Otherwise when we return from WM_WINDOWPOSCHANGING message handler and
395     // receive a WM_WINDOWPOSCHANGED the resize is finalized and any swaps of
396     // wrong size by Viz can cause the swapped content to get scaled.
397     // TODO(crbug.com/859168): Investigate nonblocking ways for solving.
398     TRACE_EVENT0("viz", "Blocked UI for DisableSwapUntilResize");
399     mojo::SyncCallRestrictions::ScopedAllowSyncCall scoped_allow_sync_call;
400     display_private_->DisableSwapUntilResize();
401     disabled_swap_until_resize_ = true;
402   }
403 }
404 
ReenableSwap()405 void Compositor::ReenableSwap() {
406   if (should_disable_swap_until_resize_ && display_private_)
407     display_private_->Resize(size_);
408 }
409 #endif
410 
SetScaleAndSize(float scale,const gfx::Size & size_in_pixel,const viz::LocalSurfaceId & local_surface_id)411 void Compositor::SetScaleAndSize(float scale,
412                                  const gfx::Size& size_in_pixel,
413                                  const viz::LocalSurfaceId& local_surface_id) {
414   DCHECK_GT(scale, 0);
415   bool device_scale_factor_changed = device_scale_factor_ != scale;
416   device_scale_factor_ = scale;
417 
418 #if DCHECK_IS_ON()
419   if (size_ != size_in_pixel && local_surface_id.is_valid()) {
420     // A new LocalSurfaceId must be set when the compositor size changes.
421     DCHECK_NE(local_surface_id, host_->local_surface_id_from_parent());
422     DCHECK_NE(local_surface_id, host_->local_surface_id_from_parent());
423   }
424 #endif  // DECHECK_IS_ON()
425 
426   if (!size_in_pixel.IsEmpty()) {
427     bool size_changed = size_ != size_in_pixel;
428     size_ = size_in_pixel;
429     host_->SetViewportRectAndScale(gfx::Rect(size_in_pixel), scale,
430                                    local_surface_id);
431     root_web_layer_->SetBounds(size_in_pixel);
432     if (display_private_ && (size_changed || disabled_swap_until_resize_)) {
433       display_private_->Resize(size_in_pixel);
434       disabled_swap_until_resize_ = false;
435     }
436   }
437   if (device_scale_factor_changed) {
438     if (is_pixel_canvas())
439       host_->SetRecordingScaleFactor(scale);
440     if (root_layer_)
441       root_layer_->OnDeviceScaleFactorChanged(scale);
442   }
443 }
444 
SetDisplayColorSpaces(const gfx::DisplayColorSpaces & display_color_spaces)445 void Compositor::SetDisplayColorSpaces(
446     const gfx::DisplayColorSpaces& display_color_spaces) {
447   if (display_color_spaces_ == display_color_spaces)
448     return;
449   display_color_spaces_ = display_color_spaces;
450 
451   host_->SetDisplayColorSpaces(display_color_spaces_);
452 
453   // Always force the ui::Compositor to re-draw all layers, because damage
454   // tracking bugs result in black flashes.
455   // https://crbug.com/804430
456   // TODO(ccameron): Remove this when the above bug is fixed.
457   host_->SetNeedsDisplayOnAllLayers();
458 
459   // Color space is reset when the output surface is lost, so this must also be
460   // updated then.
461   if (display_private_)
462     display_private_->SetDisplayColorSpaces(display_color_spaces_);
463 }
464 
SetDisplayTransformHint(gfx::OverlayTransform hint)465 void Compositor::SetDisplayTransformHint(gfx::OverlayTransform hint) {
466   host_->set_display_transform_hint(hint);
467 }
468 
SetBackgroundColor(SkColor color)469 void Compositor::SetBackgroundColor(SkColor color) {
470   host_->set_background_color(color);
471   ScheduleDraw();
472 }
473 
SetVisible(bool visible)474 void Compositor::SetVisible(bool visible) {
475   host_->SetVisible(visible);
476   // Visibility is reset when the output surface is lost, so this must also be
477   // updated then.
478   if (display_private_)
479     display_private_->SetDisplayVisible(visible);
480 }
481 
IsVisible()482 bool Compositor::IsVisible() {
483   return host_->IsVisible();
484 }
485 
486 // TODO(bokan): These calls should be delegated through the
487 // scroll_input_handler_ so that we don't have to keep a pointer to the
488 // cc::InputHandler in this class.
ScrollLayerTo(cc::ElementId element_id,const gfx::ScrollOffset & offset)489 bool Compositor::ScrollLayerTo(cc::ElementId element_id,
490                                const gfx::ScrollOffset& offset) {
491   return input_handler_weak_ &&
492          input_handler_weak_->ScrollLayerTo(element_id, offset);
493 }
494 
GetScrollOffsetForLayer(cc::ElementId element_id,gfx::ScrollOffset * offset) const495 bool Compositor::GetScrollOffsetForLayer(cc::ElementId element_id,
496                                          gfx::ScrollOffset* offset) const {
497   return input_handler_weak_ &&
498          input_handler_weak_->GetScrollOffsetForLayer(element_id, offset);
499 }
500 
SetDisplayVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)501 void Compositor::SetDisplayVSyncParameters(base::TimeTicks timebase,
502                                            base::TimeDelta interval) {
503   static bool is_frame_rate_limit_disabled =
504       base::CommandLine::ForCurrentProcess()->HasSwitch(
505           switches::kDisableFrameRateLimit);
506   if (is_frame_rate_limit_disabled)
507     return;
508 
509   if (interval.is_zero()) {
510     // TODO(brianderson): We should not be receiving 0 intervals.
511     interval = viz::BeginFrameArgs::DefaultInterval();
512   }
513   DCHECK_GT(interval.InMillisecondsF(), 0);
514 
515   // This is called at high frequenty on macOS, so early-out of redundant
516   // updates here.
517   if (vsync_timebase_ == timebase && vsync_interval_ == interval)
518     return;
519 
520   if (interval != vsync_interval_)
521     has_vsync_params_ = true;
522 
523   vsync_timebase_ = timebase;
524   vsync_interval_ = interval;
525   if (display_private_)
526     display_private_->SetDisplayVSyncParameters(timebase, interval);
527 }
528 
AddVSyncParameterObserver(mojo::PendingRemote<viz::mojom::VSyncParameterObserver> observer)529 void Compositor::AddVSyncParameterObserver(
530     mojo::PendingRemote<viz::mojom::VSyncParameterObserver> observer) {
531   if (display_private_)
532     display_private_->AddVSyncParameterObserver(std::move(observer));
533 }
534 
SetAcceleratedWidget(gfx::AcceleratedWidget widget)535 void Compositor::SetAcceleratedWidget(gfx::AcceleratedWidget widget) {
536   // This function should only get called once.
537   DCHECK(!widget_valid_);
538   widget_ = widget;
539   widget_valid_ = true;
540   if (layer_tree_frame_sink_requested_) {
541     context_factory_->CreateLayerTreeFrameSink(
542         context_creation_weak_ptr_factory_.GetWeakPtr());
543   }
544 }
545 
ReleaseAcceleratedWidget()546 gfx::AcceleratedWidget Compositor::ReleaseAcceleratedWidget() {
547   DCHECK(!IsVisible());
548   host_->ReleaseLayerTreeFrameSink();
549   display_private_ = nullptr;
550   external_begin_frame_controller_ = nullptr;
551   context_factory_->RemoveCompositor(this);
552   context_creation_weak_ptr_factory_.InvalidateWeakPtrs();
553   widget_valid_ = false;
554   gfx::AcceleratedWidget widget = widget_;
555   widget_ = gfx::kNullAcceleratedWidget;
556   return widget;
557 }
558 
widget() const559 gfx::AcceleratedWidget Compositor::widget() const {
560   DCHECK(widget_valid_);
561   return widget_;
562 }
563 
AddObserver(CompositorObserver * observer)564 void Compositor::AddObserver(CompositorObserver* observer) {
565   observer_list_.AddObserver(observer);
566 }
567 
RemoveObserver(CompositorObserver * observer)568 void Compositor::RemoveObserver(CompositorObserver* observer) {
569   observer_list_.RemoveObserver(observer);
570 }
571 
HasObserver(const CompositorObserver * observer) const572 bool Compositor::HasObserver(const CompositorObserver* observer) const {
573   return observer_list_.HasObserver(observer);
574 }
575 
AddAnimationObserver(CompositorAnimationObserver * observer)576 void Compositor::AddAnimationObserver(CompositorAnimationObserver* observer) {
577   animation_observer_list_.AddObserver(observer);
578   host_->SetNeedsAnimate();
579 }
580 
RemoveAnimationObserver(CompositorAnimationObserver * observer)581 void Compositor::RemoveAnimationObserver(
582     CompositorAnimationObserver* observer) {
583   animation_observer_list_.RemoveObserver(observer);
584 }
585 
HasAnimationObserver(const CompositorAnimationObserver * observer) const586 bool Compositor::HasAnimationObserver(
587     const CompositorAnimationObserver* observer) const {
588   return animation_observer_list_.HasObserver(observer);
589 }
590 
IssueExternalBeginFrame(const viz::BeginFrameArgs & args,bool force,base::OnceCallback<void (const viz::BeginFrameAck &)> callback)591 void Compositor::IssueExternalBeginFrame(
592     const viz::BeginFrameArgs& args,
593     bool force,
594     base::OnceCallback<void(const viz::BeginFrameAck&)> callback) {
595   if (!external_begin_frame_controller_) {
596     // IssueExternalBeginFrame() shouldn't be called again before the previous
597     // begin frame is acknowledged.
598     DCHECK(!pending_begin_frame_args_);
599     pending_begin_frame_args_ = std::make_unique<PendingBeginFrameArgs>(
600         args, force, std::move(callback));
601     return;
602   }
603   external_begin_frame_controller_->IssueExternalBeginFrame(
604       args, force, std::move(callback));
605 }
606 
RequestNewThroughputTracker()607 ThroughputTracker Compositor::RequestNewThroughputTracker() {
608   return ThroughputTracker(next_throughput_tracker_id_++,
609                            weak_ptr_factory_.GetWeakPtr());
610 }
611 
DidUpdateLayers()612 void Compositor::DidUpdateLayers() {
613   // Dump property trees and layers if run with:
614   //   --vmodule=*ui/compositor*=3
615   VLOG(3) << "After updating layers:\n"
616           << "property trees:\n"
617           << host_->property_trees()->ToString() << "\n"
618           << "cc::Layers:\n"
619           << host_->LayersAsString();
620 }
621 
BeginMainFrame(const viz::BeginFrameArgs & args)622 void Compositor::BeginMainFrame(const viz::BeginFrameArgs& args) {
623   DCHECK(!IsLocked());
624   for (auto& observer : animation_observer_list_)
625     observer.OnAnimationStep(args.frame_time);
626   if (animation_observer_list_.might_have_observers())
627     host_->SetNeedsAnimate();
628 }
629 
BeginMainFrameNotExpectedSoon()630 void Compositor::BeginMainFrameNotExpectedSoon() {
631 }
632 
BeginMainFrameNotExpectedUntil(base::TimeTicks time)633 void Compositor::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {}
634 
SendDamagedRectsRecursive(ui::Layer * layer)635 static void SendDamagedRectsRecursive(ui::Layer* layer) {
636   layer->SendDamagedRects();
637   for (auto* child : layer->children())
638     SendDamagedRectsRecursive(child);
639 }
640 
UpdateLayerTreeHost()641 void Compositor::UpdateLayerTreeHost() {
642   if (!root_layer())
643     return;
644   SendDamagedRectsRecursive(root_layer());
645 }
646 
RequestNewLayerTreeFrameSink()647 void Compositor::RequestNewLayerTreeFrameSink() {
648   DCHECK(!layer_tree_frame_sink_requested_);
649   layer_tree_frame_sink_requested_ = true;
650   if (widget_valid_) {
651     context_factory_->CreateLayerTreeFrameSink(
652         context_creation_weak_ptr_factory_.GetWeakPtr());
653   }
654 }
655 
DidFailToInitializeLayerTreeFrameSink()656 void Compositor::DidFailToInitializeLayerTreeFrameSink() {
657   task_runner_->PostTask(
658       FROM_HERE,
659       base::BindOnce(&Compositor::RequestNewLayerTreeFrameSink,
660                      context_creation_weak_ptr_factory_.GetWeakPtr()));
661 }
662 
DidCommit(base::TimeTicks)663 void Compositor::DidCommit(base::TimeTicks) {
664   DCHECK(!IsLocked());
665   for (auto& observer : observer_list_)
666     observer.OnCompositingDidCommit(this);
667 }
668 
669 std::unique_ptr<cc::BeginMainFrameMetrics>
GetBeginMainFrameMetrics()670 Compositor::GetBeginMainFrameMetrics() {
671   return nullptr;
672 }
673 
NotifyThroughputTrackerResults(cc::CustomTrackerResults results)674 void Compositor::NotifyThroughputTrackerResults(
675     cc::CustomTrackerResults results) {
676   for (auto& pair : results)
677     ReportMetricsForTracker(pair.first, std::move(pair.second));
678 }
679 
DidReceiveCompositorFrameAck()680 void Compositor::DidReceiveCompositorFrameAck() {
681   ++activated_frame_count_;
682   for (auto& observer : observer_list_)
683     observer.OnCompositingEnded(this);
684 }
685 
DidPresentCompositorFrame(uint32_t frame_token,const gfx::PresentationFeedback & feedback)686 void Compositor::DidPresentCompositorFrame(
687     uint32_t frame_token,
688     const gfx::PresentationFeedback& feedback) {
689   TRACE_EVENT_MARK_WITH_TIMESTAMP1("cc,benchmark", "FramePresented",
690                                    feedback.timestamp, "environment",
691                                    "browser");
692   for (auto& observer : observer_list_)
693     observer.OnDidPresentCompositorFrame(frame_token, feedback);
694 }
695 
DidSubmitCompositorFrame()696 void Compositor::DidSubmitCompositorFrame() {
697   base::TimeTicks start_time = base::TimeTicks::Now();
698   for (auto& observer : observer_list_)
699     observer.OnCompositingStarted(this, start_time);
700 }
701 
FrameIntervalUpdated(base::TimeDelta interval)702 void Compositor::FrameIntervalUpdated(base::TimeDelta interval) {
703   refresh_rate_ = interval.ToHz();
704 }
705 
OnFirstSurfaceActivation(const viz::SurfaceInfo & surface_info)706 void Compositor::OnFirstSurfaceActivation(
707     const viz::SurfaceInfo& surface_info) {
708   NOTREACHED();
709 }
710 
OnFrameTokenChanged(uint32_t frame_token)711 void Compositor::OnFrameTokenChanged(uint32_t frame_token) {
712   // TODO(yiyix, fsamuel): Implement frame token propagation for Compositor.
713   NOTREACHED();
714 }
715 
StartThroughputTracker(TrackerId tracker_id,ThroughputTrackerHost::ReportCallback callback)716 void Compositor::StartThroughputTracker(
717     TrackerId tracker_id,
718     ThroughputTrackerHost::ReportCallback callback) {
719   DCHECK(!base::Contains(throughput_tracker_map_, tracker_id));
720   throughput_tracker_map_[tracker_id] = std::move(callback);
721   animation_host_->StartThroughputTracking(tracker_id);
722 }
723 
StopThroughtputTracker(TrackerId tracker_id)724 void Compositor::StopThroughtputTracker(TrackerId tracker_id) {
725   DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
726   animation_host_->StopThroughputTracking(tracker_id);
727 }
728 
CancelThroughtputTracker(TrackerId tracker_id)729 void Compositor::CancelThroughtputTracker(TrackerId tracker_id) {
730   DCHECK(base::Contains(throughput_tracker_map_, tracker_id));
731   StopThroughtputTracker(tracker_id);
732   throughput_tracker_map_.erase(tracker_id);
733 }
734 
735 #if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_BSD)
OnCompleteSwapWithNewSize(const gfx::Size & size)736 void Compositor::OnCompleteSwapWithNewSize(const gfx::Size& size) {
737   for (auto& observer : observer_list_)
738     observer.OnCompositingCompleteSwapWithNewSize(this, size);
739 }
740 #endif
741 
SetOutputIsSecure(bool output_is_secure)742 void Compositor::SetOutputIsSecure(bool output_is_secure) {
743   output_is_secure_ = output_is_secure;
744   if (display_private_)
745     display_private_->SetOutputIsSecure(output_is_secure);
746 }
747 
GetLayerTreeDebugState() const748 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const {
749   return host_->GetDebugState();
750 }
751 
SetLayerTreeDebugState(const cc::LayerTreeDebugState & debug_state)752 void Compositor::SetLayerTreeDebugState(
753     const cc::LayerTreeDebugState& debug_state) {
754   host_->SetDebugState(debug_state);
755 }
756 
RequestPresentationTimeForNextFrame(PresentationTimeCallback callback)757 void Compositor::RequestPresentationTimeForNextFrame(
758     PresentationTimeCallback callback) {
759   host_->RequestPresentationTimeForNextFrame(std::move(callback));
760 }
761 
ReportMetricsForTracker(int tracker_id,const cc::FrameSequenceMetrics::CustomReportData & data)762 void Compositor::ReportMetricsForTracker(
763     int tracker_id,
764     const cc::FrameSequenceMetrics::CustomReportData& data) {
765   auto it = throughput_tracker_map_.find(tracker_id);
766   if (it == throughput_tracker_map_.end())
767     return;
768 
769   std::move(it->second).Run(data);
770   throughput_tracker_map_.erase(it);
771 }
772 
SetDelegatedInkPointRenderer(mojo::PendingReceiver<viz::mojom::DelegatedInkPointRenderer> receiver)773 void Compositor::SetDelegatedInkPointRenderer(
774     mojo::PendingReceiver<viz::mojom::DelegatedInkPointRenderer> receiver) {
775   if (display_private_)
776     display_private_->SetDelegatedInkPointRenderer(std::move(receiver));
777 }
778 
779 }  // namespace ui
780