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