1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/trees/layer_tree_host_impl.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <limits>
12 #include <list>
13 #include <string>
14
15 #include "base/auto_reset.h"
16 #include "base/bind.h"
17 #include "base/command_line.h"
18 #include "base/compiler_specific.h"
19 #include "base/containers/adapters.h"
20 #include "base/containers/flat_map.h"
21 #include "base/debug/crash_logging.h"
22 #include "base/debug/dump_without_crashing.h"
23 #include "base/location.h"
24 #include "base/logging.h"
25 #include "base/memory/ptr_util.h"
26 #include "base/memory/read_only_shared_memory_region.h"
27 #include "base/metrics/histogram.h"
28 #include "base/numerics/safe_conversions.h"
29 #include "base/stl_util.h"
30 #include "base/strings/stringprintf.h"
31 #include "base/system/sys_info.h"
32 #include "base/trace_event/traced_value.h"
33 #include "build/build_config.h"
34 #include "cc/base/devtools_instrumentation.h"
35 #include "cc/base/features.h"
36 #include "cc/base/histograms.h"
37 #include "cc/base/math_util.h"
38 #include "cc/base/switches.h"
39 #include "cc/benchmarks/benchmark_instrumentation.h"
40 #include "cc/debug/rendering_stats_instrumentation.h"
41 #include "cc/input/browser_controls_offset_manager.h"
42 #include "cc/input/main_thread_scrolling_reason.h"
43 #include "cc/input/page_scale_animation.h"
44 #include "cc/input/scroll_elasticity_helper.h"
45 #include "cc/input/scroll_state.h"
46 #include "cc/input/scroll_utils.h"
47 #include "cc/input/scrollbar.h"
48 #include "cc/input/scrollbar_animation_controller.h"
49 #include "cc/input/scroller_size_metrics.h"
50 #include "cc/input/snap_selection_strategy.h"
51 #include "cc/layers/append_quads_data.h"
52 #include "cc/layers/effect_tree_layer_list_iterator.h"
53 #include "cc/layers/heads_up_display_layer_impl.h"
54 #include "cc/layers/layer_impl.h"
55 #include "cc/layers/painted_scrollbar_layer_impl.h"
56 #include "cc/layers/render_surface_impl.h"
57 #include "cc/layers/scrollbar_layer_impl_base.h"
58 #include "cc/layers/surface_layer_impl.h"
59 #include "cc/layers/viewport.h"
60 #include "cc/metrics/compositor_frame_reporting_controller.h"
61 #include "cc/metrics/frame_sequence_metrics.h"
62 #include "cc/metrics/lcd_text_metrics_reporter.h"
63 #include "cc/metrics/ukm_smoothness_data.h"
64 #include "cc/paint/display_item_list.h"
65 #include "cc/paint/paint_worklet_job.h"
66 #include "cc/paint/paint_worklet_layer_painter.h"
67 #include "cc/raster/bitmap_raster_buffer_provider.h"
68 #include "cc/raster/gpu_raster_buffer_provider.h"
69 #include "cc/raster/one_copy_raster_buffer_provider.h"
70 #include "cc/raster/raster_buffer_provider.h"
71 #include "cc/raster/synchronous_task_graph_runner.h"
72 #include "cc/raster/zero_copy_raster_buffer_provider.h"
73 #include "cc/resources/memory_history.h"
74 #include "cc/resources/resource_pool.h"
75 #include "cc/resources/ui_resource_bitmap.h"
76 #include "cc/tiles/eviction_tile_priority_queue.h"
77 #include "cc/tiles/frame_viewer_instrumentation.h"
78 #include "cc/tiles/gpu_image_decode_cache.h"
79 #include "cc/tiles/picture_layer_tiling.h"
80 #include "cc/tiles/raster_tile_priority_queue.h"
81 #include "cc/tiles/software_image_decode_cache.h"
82 #include "cc/trees/clip_node.h"
83 #include "cc/trees/compositor_commit_data.h"
84 #include "cc/trees/damage_tracker.h"
85 #include "cc/trees/debug_rect_history.h"
86 #include "cc/trees/draw_property_utils.h"
87 #include "cc/trees/effect_node.h"
88 #include "cc/trees/image_animation_controller.h"
89 #include "cc/trees/latency_info_swap_promise_monitor.h"
90 #include "cc/trees/layer_tree_frame_sink.h"
91 #include "cc/trees/layer_tree_impl.h"
92 #include "cc/trees/mutator_host.h"
93 #include "cc/trees/presentation_time_callback_buffer.h"
94 #include "cc/trees/render_frame_metadata.h"
95 #include "cc/trees/render_frame_metadata_observer.h"
96 #include "cc/trees/scroll_node.h"
97 #include "cc/trees/single_thread_proxy.h"
98 #include "cc/trees/transform_node.h"
99 #include "cc/trees/tree_synchronizer.h"
100 #include "components/viz/common/features.h"
101 #include "components/viz/common/frame_sinks/copy_output_request.h"
102 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
103 #include "components/viz/common/frame_timing_details.h"
104 #include "components/viz/common/hit_test/hit_test_region_list.h"
105 #include "components/viz/common/quads/compositor_frame.h"
106 #include "components/viz/common/quads/compositor_frame_metadata.h"
107 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
108 #include "components/viz/common/quads/frame_deadline.h"
109 #include "components/viz/common/quads/shared_quad_state.h"
110 #include "components/viz/common/quads/solid_color_draw_quad.h"
111 #include "components/viz/common/quads/texture_draw_quad.h"
112 #include "components/viz/common/resources/bitmap_allocation.h"
113 #include "components/viz/common/resources/platform_color.h"
114 #include "components/viz/common/resources/resource_sizes.h"
115 #include "components/viz/common/traced_value.h"
116 #include "gpu/GLES2/gl2extchromium.h"
117 #include "gpu/command_buffer/client/context_support.h"
118 #include "gpu/command_buffer/client/gles2_interface.h"
119 #include "gpu/command_buffer/client/raster_interface.h"
120 #include "gpu/command_buffer/client/shared_image_interface.h"
121 #include "gpu/command_buffer/common/shared_image_usage.h"
122 #include "services/metrics/public/cpp/ukm_recorder.h"
123 #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.h"
124 #include "third_party/skia/include/gpu/GrDirectContext.h"
125 #include "ui/events/types/scroll_input_type.h"
126 #include "ui/gfx/display_color_spaces.h"
127 #include "ui/gfx/geometry/point_conversions.h"
128 #include "ui/gfx/geometry/rect_conversions.h"
129 #include "ui/gfx/geometry/scroll_offset.h"
130 #include "ui/gfx/geometry/size_conversions.h"
131 #include "ui/gfx/geometry/vector2d_conversions.h"
132 #include "ui/gfx/geometry/vector2d_f.h"
133 #include "ui/gfx/skia_util.h"
134
135 using ScrollThread = cc::InputHandler::ScrollThread;
136
137 namespace cc {
138 namespace {
139
140 // Used to accommodate finite precision when comparing scaled viewport and
141 // content widths. While this value may seem large, width=device-width on an N7
142 // V1 saw errors of ~0.065 between computed window and content widths.
143 const float kMobileViewportWidthEpsilon = 0.15f;
144
145 // In BuildHitTestData we iterate all layers to find all layers that overlap
146 // OOPIFs, but when the number of layers is greater than
147 // |kAssumeOverlapThreshold|, it can be inefficient to accumulate layer bounds
148 // for overlap checking. As a result, we are conservative and make OOPIFs
149 // kHitTestAsk after the threshold is reached.
150 const size_t kAssumeOverlapThreshold = 100;
151
152 // gfx::DisplayColorSpaces stores up to 3 different color spaces. This should be
153 // updated to match any size changes in DisplayColorSpaces.
154 constexpr size_t kContainsSrgbCacheSize = 3;
155 static_assert(kContainsSrgbCacheSize ==
156 gfx::DisplayColorSpaces::kConfigCount / 2,
157 "sRGB cache must match the size of DisplayColorSpaces");
158
HasFixedPageScale(LayerTreeImpl * active_tree)159 bool HasFixedPageScale(LayerTreeImpl* active_tree) {
160 return active_tree->min_page_scale_factor() ==
161 active_tree->max_page_scale_factor();
162 }
163
HasMobileViewport(LayerTreeImpl * active_tree)164 bool HasMobileViewport(LayerTreeImpl* active_tree) {
165 float window_width_dip = active_tree->current_page_scale_factor() *
166 active_tree->ScrollableViewportSize().width();
167 float content_width_css = active_tree->ScrollableSize().width();
168 return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
169 }
170
IsMobileOptimized(LayerTreeImpl * active_tree)171 bool IsMobileOptimized(LayerTreeImpl* active_tree) {
172 bool has_mobile_viewport = HasMobileViewport(active_tree);
173 bool has_fixed_page_scale = HasFixedPageScale(active_tree);
174 return has_fixed_page_scale || has_mobile_viewport;
175 }
176
TileRasterBufferFormat(const LayerTreeSettings & settings,viz::ContextProvider * context_provider,bool use_gpu_rasterization)177 viz::ResourceFormat TileRasterBufferFormat(
178 const LayerTreeSettings& settings,
179 viz::ContextProvider* context_provider,
180 bool use_gpu_rasterization) {
181 // Software compositing always uses the native skia RGBA N32 format, but we
182 // just call it RGBA_8888 everywhere even though it can be BGRA ordering,
183 // because we don't need to communicate the actual ordering as the code all
184 // assumes the native skia format.
185 if (!context_provider)
186 return viz::RGBA_8888;
187
188 // RGBA4444 overrides the defaults if specified, but only for gpu compositing.
189 // It is always supported on platforms where it is specified.
190 if (settings.use_rgba_4444)
191 return viz::RGBA_4444;
192 // Otherwise we use BGRA textures if we can but it depends on the context
193 // capabilities, and we have different preferences when rastering to textures
194 // vs uploading textures.
195 const gpu::Capabilities& caps = context_provider->ContextCapabilities();
196 if (use_gpu_rasterization)
197 return viz::PlatformColor::BestSupportedRenderBufferFormat(caps);
198 return viz::PlatformColor::BestSupportedTextureFormat(caps);
199 }
200
DidVisibilityChange(LayerTreeHostImpl * id,bool visible)201 void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
202 if (visible) {
203 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
204 "cc,benchmark", "LayerTreeHostImpl::SetVisible", TRACE_ID_LOCAL(id),
205 "LayerTreeHostImpl", id);
206 return;
207 }
208
209 TRACE_EVENT_NESTABLE_ASYNC_END0(
210 "cc,benchmark", "LayerTreeHostImpl::SetVisible", TRACE_ID_LOCAL(id));
211 }
212
PopulateMetadataContentColorUsage(const LayerTreeHostImpl::FrameData * frame,viz::CompositorFrameMetadata * metadata)213 void PopulateMetadataContentColorUsage(
214 const LayerTreeHostImpl::FrameData* frame,
215 viz::CompositorFrameMetadata* metadata) {
216 metadata->content_color_usage = gfx::ContentColorUsage::kSRGB;
217 for (const LayerImpl* layer : frame->will_draw_layers) {
218 metadata->content_color_usage =
219 std::max(metadata->content_color_usage, layer->GetContentColorUsage());
220 }
221 }
222
223 // Registers callbacks, as needed, to track First Scroll Latency.
ApplyFirstScrollTracking(const ui::LatencyInfo * latency,uint32_t frame_token,LayerTreeHostImpl * impl)224 void ApplyFirstScrollTracking(const ui::LatencyInfo* latency,
225 uint32_t frame_token,
226 LayerTreeHostImpl* impl) {
227 base::TimeTicks creation_timestamp;
228 // If |latency| isn't tracking a scroll, we don't need to do extra
229 // first-scroll tracking.
230 auto scroll_update_started =
231 ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT;
232 auto scroll_update_continued =
233 ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT;
234 if (!latency->FindLatency(scroll_update_started, &creation_timestamp) &&
235 !latency->FindLatency(scroll_update_continued, &creation_timestamp)) {
236 return;
237 }
238
239 // Construct a callback that, given presentation feedback, will report the
240 // time span between the scroll input-event creation and the
241 // presentation timestamp.
242 LayerTreeHost::PresentationTimeCallback presentation_callback =
243 base::BindOnce(
244 [](base::TimeTicks event_creation,
245 LayerTreeHostImpl* layer_tree_host_impl,
246 const gfx::PresentationFeedback& feedback) {
247 layer_tree_host_impl->DidObserveScrollDelay(
248 feedback.timestamp - event_creation, event_creation);
249 },
250 creation_timestamp, impl);
251
252 // Tell the |LayerTreeHostImpl| to run our callback with the presentation
253 // feedback corresponding to the given |frame_token|.
254 impl->RegisterCompositorPresentationTimeCallback(
255 frame_token, std::move(presentation_callback));
256 }
257
258 // These values are persisted to logs. Entries should not be renumbered and
259 // numeric values should never be reused.
260 enum class SourceIdConsistency : int {
261 kConsistent = 0,
262 kContainsInvalid = 1,
263 kNonUnique = 2,
264 kInvalidAndNonUnique = 3,
265 kMaxValue = kInvalidAndNonUnique,
266 };
267
RecordSourceIdConsistency(bool all_valid,bool all_unique)268 void RecordSourceIdConsistency(bool all_valid, bool all_unique) {
269 SourceIdConsistency consistency =
270 all_unique ? (all_valid ? SourceIdConsistency::kConsistent
271 : SourceIdConsistency::kContainsInvalid)
272 : (all_valid ? SourceIdConsistency::kNonUnique
273 : SourceIdConsistency::kInvalidAndNonUnique);
274
275 // TODO(crbug.com/1062764): we're sometimes seeing unexpected values for the
276 // ukm::SourceId. We'll use this histogram to track how often it happens so
277 // we can properly (de-)prioritize a fix.
278 UMA_HISTOGRAM_ENUMERATION("Event.LatencyInfo.Debug.SourceIdConsistency",
279 consistency);
280 }
281
282 } // namespace
283
284 DEFINE_SCOPED_UMA_HISTOGRAM_TIMER(PendingTreeRasterDurationHistogramTimer,
285 "Scheduling.%s.PendingTreeRasterDuration")
286
DidUpdateScrollAnimationCurve()287 void LayerTreeHostImpl::DidUpdateScrollAnimationCurve() {
288 // Because we updated the animation target, notify the SwapPromiseMonitor
289 // to tell it that something happened that will cause a swap in the future.
290 // This will happen within the scope of the dispatch of a gesture scroll
291 // update input event. If we don't notify during the handling of the input
292 // event, the LatencyInfo associated with the input event will not be
293 // added as a swap promise and we won't get any swap results.
294 NotifySwapPromiseMonitorsOfSetNeedsRedraw();
295 events_metrics_manager_.SaveActiveEventMetrics();
296 }
297
AccumulateScrollDeltaForTracing(const gfx::Vector2dF & delta)298 void LayerTreeHostImpl::AccumulateScrollDeltaForTracing(
299 const gfx::Vector2dF& delta) {
300 scroll_accumulated_this_frame_ += delta;
301 }
302
DidStartPinchZoom()303 void LayerTreeHostImpl::DidStartPinchZoom() {
304 client_->RenewTreePriority();
305 frame_trackers_.StartSequence(FrameSequenceTrackerType::kPinchZoom);
306 }
307
DidEndPinchZoom()308 void LayerTreeHostImpl::DidEndPinchZoom() {
309 // When a pinch ends, we may be displaying content cached at incorrect scales,
310 // so updating draw properties and drawing will ensure we are using the right
311 // scales that we want when we're not inside a pinch.
312 active_tree_->set_needs_update_draw_properties();
313 SetNeedsRedraw();
314 frame_trackers_.StopSequence(FrameSequenceTrackerType::kPinchZoom);
315 }
316
DidUpdatePinchZoom()317 void LayerTreeHostImpl::DidUpdatePinchZoom() {
318 SetNeedsRedraw();
319 client_->RenewTreePriority();
320 }
321
DidStartScroll()322 void LayerTreeHostImpl::DidStartScroll() {
323 scroll_affects_scroll_handler_ = active_tree()->have_scroll_event_handlers();
324 client_->RenewTreePriority();
325 }
326
DidEndScroll()327 void LayerTreeHostImpl::DidEndScroll() {
328 scroll_affects_scroll_handler_ = false;
329 }
330
DidMouseLeave()331 void LayerTreeHostImpl::DidMouseLeave() {
332 for (auto& pair : scrollbar_animation_controllers_)
333 pair.second->DidMouseLeave();
334 }
335
SetNeedsFullViewportRedraw()336 void LayerTreeHostImpl::SetNeedsFullViewportRedraw() {
337 // TODO(bokan): Do these really need to be manually called? (Rather than
338 // damage/redraw being set from scroll offset changes).
339 SetFullViewportDamage();
340 SetNeedsRedraw();
341 }
342
IsInHighLatencyMode() const343 bool LayerTreeHostImpl::IsInHighLatencyMode() const {
344 return impl_thread_phase_ == ImplThreadPhase::IDLE;
345 }
346
GetSettings() const347 const LayerTreeSettings& LayerTreeHostImpl::GetSettings() const {
348 return settings();
349 }
350
GetImplDeprecated()351 LayerTreeHostImpl& LayerTreeHostImpl::GetImplDeprecated() {
352 return *this;
353 }
354
GetImplDeprecated() const355 const LayerTreeHostImpl& LayerTreeHostImpl::GetImplDeprecated() const {
356 return *this;
357 }
358
359 LayerTreeHostImpl::FrameData::FrameData() = default;
360 LayerTreeHostImpl::FrameData::~FrameData() = default;
361 LayerTreeHostImpl::UIResourceData::UIResourceData() = default;
362 LayerTreeHostImpl::UIResourceData::~UIResourceData() = default;
363 LayerTreeHostImpl::UIResourceData::UIResourceData(UIResourceData&&) noexcept =
364 default;
365 LayerTreeHostImpl::UIResourceData& LayerTreeHostImpl::UIResourceData::operator=(
366 UIResourceData&&) = default;
367
Create(const LayerTreeSettings & settings,LayerTreeHostImplClient * client,TaskRunnerProvider * task_runner_provider,RenderingStatsInstrumentation * rendering_stats_instrumentation,TaskGraphRunner * task_graph_runner,std::unique_ptr<MutatorHost> mutator_host,RasterDarkModeFilter * dark_mode_filter,int id,scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner,LayerTreeHostSchedulingClient * scheduling_client)368 std::unique_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
369 const LayerTreeSettings& settings,
370 LayerTreeHostImplClient* client,
371 TaskRunnerProvider* task_runner_provider,
372 RenderingStatsInstrumentation* rendering_stats_instrumentation,
373 TaskGraphRunner* task_graph_runner,
374 std::unique_ptr<MutatorHost> mutator_host,
375 RasterDarkModeFilter* dark_mode_filter,
376 int id,
377 scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner,
378 LayerTreeHostSchedulingClient* scheduling_client) {
379 return base::WrapUnique(new LayerTreeHostImpl(
380 settings, client, task_runner_provider, rendering_stats_instrumentation,
381 task_graph_runner, std::move(mutator_host), dark_mode_filter, id,
382 std::move(image_worker_task_runner), scheduling_client));
383 }
384
LayerTreeHostImpl(const LayerTreeSettings & settings,LayerTreeHostImplClient * client,TaskRunnerProvider * task_runner_provider,RenderingStatsInstrumentation * rendering_stats_instrumentation,TaskGraphRunner * task_graph_runner,std::unique_ptr<MutatorHost> mutator_host,RasterDarkModeFilter * dark_mode_filter,int id,scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner,LayerTreeHostSchedulingClient * scheduling_client)385 LayerTreeHostImpl::LayerTreeHostImpl(
386 const LayerTreeSettings& settings,
387 LayerTreeHostImplClient* client,
388 TaskRunnerProvider* task_runner_provider,
389 RenderingStatsInstrumentation* rendering_stats_instrumentation,
390 TaskGraphRunner* task_graph_runner,
391 std::unique_ptr<MutatorHost> mutator_host,
392 RasterDarkModeFilter* dark_mode_filter,
393 int id,
394 scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner,
395 LayerTreeHostSchedulingClient* scheduling_client)
396 : client_(client),
397 scheduling_client_(scheduling_client),
398 task_runner_provider_(task_runner_provider),
399 current_begin_frame_tracker_(FROM_HERE),
400 compositor_frame_reporting_controller_(
401 std::make_unique<CompositorFrameReportingController>(
402 /*should_report_metrics=*/!settings.single_thread_proxy_scheduler,
403 id)),
404 settings_(settings),
405 is_synchronous_single_threaded_(!task_runner_provider->HasImplThread() &&
406 !settings_.single_thread_proxy_scheduler),
407 cached_managed_memory_policy_(settings.memory_policy),
408 // Must be initialized after is_synchronous_single_threaded_ and
409 // task_runner_provider_.
410 tile_manager_(this,
411 GetTaskRunner(),
412 std::move(image_worker_task_runner),
413 is_synchronous_single_threaded_
414 ? std::numeric_limits<size_t>::max()
415 : settings.scheduled_raster_task_limit,
416 settings.ToTileManagerSettings()),
417 memory_history_(MemoryHistory::Create()),
418 debug_rect_history_(DebugRectHistory::Create()),
419 mutator_host_(std::move(mutator_host)),
420 dark_mode_filter_(dark_mode_filter),
421 rendering_stats_instrumentation_(rendering_stats_instrumentation),
422 micro_benchmark_controller_(this),
423 task_graph_runner_(task_graph_runner),
424 id_(id),
425 consecutive_frame_with_damage_count_(settings.damaged_frame_limit),
426 // It is safe to use base::Unretained here since we will outlive the
427 // ImageAnimationController.
428 image_animation_controller_(GetTaskRunner(),
429 this,
430 settings_.enable_image_animation_resync),
431 paint_image_generator_client_id_(PaintImage::GetNextGeneratorClientId()),
432 frame_trackers_(settings.single_thread_proxy_scheduler,
433 compositor_frame_reporting_controller_.get()),
434 lcd_text_metrics_reporter_(LCDTextMetricsReporter::CreateIfNeeded(this)),
435 frame_rate_estimator_(GetTaskRunner()),
436 contains_srgb_cache_(kContainsSrgbCacheSize) {
437 DCHECK(mutator_host_);
438 mutator_host_->SetMutatorHostClient(this);
439 mutator_events_ = mutator_host_->CreateEvents();
440
441 DCHECK(task_runner_provider_->IsImplThread());
442 DidVisibilityChange(this, visible_);
443
444 // LTHI always has an active tree.
445 active_tree_ = std::make_unique<LayerTreeImpl>(
446 this, new SyncedProperty<ScaleGroup>, new SyncedBrowserControls,
447 new SyncedBrowserControls, new SyncedElasticOverscroll);
448 active_tree_->property_trees()->is_active = true;
449
450 viewport_ = Viewport::Create(this);
451
452 TRACE_EVENT_OBJECT_CREATED_WITH_ID(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
453 "cc::LayerTreeHostImpl", id_);
454
455 browser_controls_offset_manager_ = BrowserControlsOffsetManager::Create(
456 this, settings.top_controls_show_threshold,
457 settings.top_controls_hide_threshold);
458
459 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
460 switches::kDisableLayerTreeHostMemoryPressure)) {
461 memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
462 FROM_HERE, base::BindRepeating(&LayerTreeHostImpl::OnMemoryPressure,
463 base::Unretained(this)));
464 }
465
466 SetDebugState(settings.initial_debug_state);
467 compositor_frame_reporting_controller_->SetDroppedFrameCounter(
468 &dropped_frame_counter_);
469
470 dropped_frame_counter_.set_total_counter(&total_frame_counter_);
471 frame_trackers_.set_custom_tracker_results_added_callback(
472 base::BindRepeating(&LayerTreeHostImpl::NotifyThroughputTrackerResults,
473 weak_factory_.GetWeakPtr()));
474 }
475
~LayerTreeHostImpl()476 LayerTreeHostImpl::~LayerTreeHostImpl() {
477 DCHECK(task_runner_provider_->IsImplThread());
478 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
479 TRACE_EVENT_OBJECT_DELETED_WITH_ID(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
480 "cc::LayerTreeHostImpl", id_);
481
482 // The frame sink is released before shutdown, which takes down
483 // all the resource and raster structures.
484 DCHECK(!layer_tree_frame_sink_);
485 DCHECK(!resource_pool_);
486 DCHECK(!image_decode_cache_);
487 DCHECK(!single_thread_synchronous_task_graph_runner_);
488
489 if (input_delegate_)
490 input_delegate_->WillShutdown();
491
492 // The layer trees must be destroyed before the LayerTreeHost. Also, if they
493 // are holding onto any resources, destroying them will release them, before
494 // we mark any leftover resources as lost.
495 if (recycle_tree_)
496 recycle_tree_->Shutdown();
497 if (pending_tree_)
498 pending_tree_->Shutdown();
499 active_tree_->Shutdown();
500 recycle_tree_ = nullptr;
501 pending_tree_ = nullptr;
502 active_tree_ = nullptr;
503
504 // All resources should already be removed, so lose anything still exported.
505 resource_provider_.ShutdownAndReleaseAllResources();
506
507 mutator_host_->ClearMutators();
508 mutator_host_->SetMutatorHostClient(nullptr);
509
510 // Clear the UKM Manager so that we do not try to report when the
511 // UKM System has shut down.
512 compositor_frame_reporting_controller_->SetUkmManager(nullptr);
513 compositor_frame_reporting_controller_ = nullptr;
514 }
515
GetInputHandler()516 ThreadedInputHandler& LayerTreeHostImpl::GetInputHandler() {
517 DCHECK(input_delegate_) << "Requested InputHandler when one wasn't bound. "
518 "Call BindToInputHandler to bind to one";
519 return static_cast<ThreadedInputHandler&>(*input_delegate_.get());
520 }
521
GetInputHandler() const522 const ThreadedInputHandler& LayerTreeHostImpl::GetInputHandler() const {
523 DCHECK(input_delegate_) << "Requested InputHandler when one wasn't bound. "
524 "Call BindToInputHandler to bind to one";
525 return static_cast<const ThreadedInputHandler&>(*input_delegate_.get());
526 }
527
WillSendBeginMainFrame()528 void LayerTreeHostImpl::WillSendBeginMainFrame() {
529 if (scheduling_client_)
530 scheduling_client_->DidScheduleBeginMainFrame();
531 }
532
DidSendBeginMainFrame(const viz::BeginFrameArgs & args)533 void LayerTreeHostImpl::DidSendBeginMainFrame(const viz::BeginFrameArgs& args) {
534 frame_trackers_.NotifyBeginMainFrame(args);
535 }
536
BeginMainFrameAborted(CommitEarlyOutReason reason,std::vector<std::unique_ptr<SwapPromise>> swap_promises,const viz::BeginFrameArgs & args)537 void LayerTreeHostImpl::BeginMainFrameAborted(
538 CommitEarlyOutReason reason,
539 std::vector<std::unique_ptr<SwapPromise>> swap_promises,
540 const viz::BeginFrameArgs& args) {
541 if (reason == CommitEarlyOutReason::ABORTED_NOT_VISIBLE ||
542 reason == CommitEarlyOutReason::FINISHED_NO_UPDATES) {
543 frame_trackers_.NotifyMainFrameCausedNoDamage(args);
544 } else {
545 frame_trackers_.NotifyMainFrameProcessed(args);
546 }
547
548 // If the begin frame data was handled, then scroll and scale set was applied
549 // by the main thread, so the active tree needs to be updated as if these sent
550 // values were applied and committed.
551 if (CommitEarlyOutHandledCommit(reason)) {
552 active_tree_->ApplySentScrollAndScaleDeltasFromAbortedCommit();
553 if (pending_tree_) {
554 pending_tree_->AppendSwapPromises(std::move(swap_promises));
555 } else {
556 for (const auto& swap_promise : swap_promises)
557 swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE);
558 }
559 }
560 }
561
ReadyToCommit(const viz::BeginFrameArgs & commit_args,const BeginMainFrameMetrics * begin_main_frame_metrics)562 void LayerTreeHostImpl::ReadyToCommit(
563 const viz::BeginFrameArgs& commit_args,
564 const BeginMainFrameMetrics* begin_main_frame_metrics) {
565 frame_trackers_.NotifyMainFrameProcessed(commit_args);
566 if (!is_measuring_smoothness_ && begin_main_frame_metrics &&
567 begin_main_frame_metrics->should_measure_smoothness) {
568 is_measuring_smoothness_ = true;
569 total_frame_counter_.Reset();
570 dropped_frame_counter_.OnFcpReceived();
571 }
572 }
573
BeginCommit()574 void LayerTreeHostImpl::BeginCommit() {
575 TRACE_EVENT0("cc", "LayerTreeHostImpl::BeginCommit");
576
577 if (!CommitToActiveTree())
578 CreatePendingTree();
579 }
580
CommitComplete()581 void LayerTreeHostImpl::CommitComplete() {
582 TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete");
583
584 if (input_delegate_)
585 input_delegate_->DidCommit();
586
587 if (CommitToActiveTree()) {
588 active_tree_->HandleScrollbarShowRequestsFromMain();
589
590 // Property tree nodes have been updated by the commit. Update elements
591 // available on active tree to start/stop ticking animations.
592 UpdateElements(ElementListType::ACTIVE);
593
594 // We have to activate animations here or "IsActive()" is true on the layers
595 // but the animations aren't activated yet so they get ignored by
596 // UpdateDrawProperties.
597 ActivateAnimations();
598 }
599
600 // We clear the entries that were never mutated by CC animations from the last
601 // commit until now. Moreover, we reset the values of input properties and
602 // relies on the fact that CC animation will mutate those values when pending
603 // tree is animated below.
604 // With that, when CC finishes animating an input property, the value of that
605 // property stays at finish state until a commit kicks in, which is consistent
606 // with current composited animations.
607 paint_worklet_tracker_.ClearUnusedInputProperties();
608
609 // Start animations before UpdateDrawProperties and PrepareTiles, as they can
610 // change the results. When doing commit to the active tree, this must happen
611 // after ActivateAnimations() in order for this ticking to be propogated
612 // to layers on the active tree.
613 if (CommitToActiveTree())
614 Animate();
615 else
616 AnimatePendingTreeAfterCommit();
617
618 UpdateSyncTreeAfterCommitOrImplSideInvalidation();
619 micro_benchmark_controller_.DidCompleteCommit();
620
621 if (mutator_host_->CurrentFrameHadRAF())
622 frame_trackers_.StartSequence(FrameSequenceTrackerType::kRAF);
623 if (mutator_host_->HasCanvasInvalidation())
624 frame_trackers_.StartSequence(FrameSequenceTrackerType::kCanvasAnimation);
625 if (mutator_host_->HasJSAnimation())
626 frame_trackers_.StartSequence(FrameSequenceTrackerType::kJSAnimation);
627
628 if (mutator_host_->MainThreadAnimationsCount() > 0) {
629 frame_trackers_.StartSequence(
630 FrameSequenceTrackerType::kMainThreadAnimation);
631 }
632
633 for (const auto& info : mutator_host_->TakePendingThroughputTrackerInfos()) {
634 const MutatorHost::TrackedAnimationSequenceId sequence_id = info.id;
635 const bool start = info.start;
636 if (start)
637 frame_trackers_.StartCustomSequence(sequence_id);
638 else
639 frame_trackers_.StopCustomSequence(sequence_id);
640 }
641 }
642
UpdateSyncTreeAfterCommitOrImplSideInvalidation()643 void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() {
644 // LayerTreeHost may have changed the GPU rasterization flags state, which
645 // may require an update of the tree resources.
646 UpdateTreeResourcesForGpuRasterizationIfNeeded();
647 sync_tree()->set_needs_update_draw_properties();
648
649 // We need an update immediately post-commit to have the opportunity to create
650 // tilings.
651 // We can avoid updating the ImageAnimationController during this
652 // DrawProperties update since it will be done when we animate the controller
653 // below.
654 bool update_image_animation_controller = false;
655 sync_tree()->UpdateDrawProperties(update_image_animation_controller);
656
657 // Defer invalidating images until UpdateDrawProperties is performed since
658 // that updates whether an image should be animated based on its visibility
659 // and the updated data for the image from the main frame.
660 PaintImageIdFlatSet images_to_invalidate =
661 tile_manager_.TakeImagesToInvalidateOnSyncTree();
662 if (ukm_manager_)
663 ukm_manager_->AddCheckerboardedImages(images_to_invalidate.size());
664
665 const auto& animated_images =
666 image_animation_controller_.AnimateForSyncTree(CurrentBeginFrameArgs());
667 images_to_invalidate.insert(animated_images.begin(), animated_images.end());
668
669 // Invalidate cached PaintRecords for worklets whose input properties were
670 // mutated since the last pending tree. We keep requesting invalidations until
671 // the animation is ticking on impl thread. Note that this works since the
672 // animation starts ticking on the pending tree
673 // (AnimatePendingTreeAfterCommit) which committed this animation timeline.
674 // After this the animation may only tick on the active tree for impl-side
675 // invalidations (since AnimatePendingTreeAfterCommit is not done for pending
676 // trees created by impl-side invalidations). But we ensure here that we
677 // request another invalidation if an input property was mutated on the active
678 // tree.
679 if (paint_worklet_tracker_.InvalidatePaintWorkletsOnPendingTree()) {
680 client_->NeedsImplSideInvalidation(
681 true /* needs_first_draw_on_activation */);
682 }
683 PaintImageIdFlatSet dirty_paint_worklet_ids;
684 PaintWorkletJobMap dirty_paint_worklets =
685 GatherDirtyPaintWorklets(&dirty_paint_worklet_ids);
686 images_to_invalidate.insert(dirty_paint_worklet_ids.begin(),
687 dirty_paint_worklet_ids.end());
688
689 sync_tree()->InvalidateRegionForImages(images_to_invalidate);
690
691 // Note that it is important to push the state for checkerboarded and animated
692 // images prior to PrepareTiles here when committing to the active tree. This
693 // is because new tiles on the active tree depend on tree specific state
694 // cached in these components, which must be pushed to active before preparing
695 // tiles for the updated active tree.
696 if (CommitToActiveTree())
697 ActivateStateForImages();
698
699 if (!paint_worklet_painter_) {
700 // Blink should not send us any PaintWorklet inputs until we have a painter
701 // registered.
702 DCHECK(sync_tree()->picture_layers_with_paint_worklets().empty());
703 pending_tree_fully_painted_ = true;
704 NotifyPendingTreeFullyPainted();
705 return;
706 }
707
708 if (!dirty_paint_worklets.size()) {
709 pending_tree_fully_painted_ = true;
710 NotifyPendingTreeFullyPainted();
711 return;
712 }
713
714 client_->NotifyPaintWorkletStateChange(
715 Scheduler::PaintWorkletState::PROCESSING);
716 auto done_callback = base::BindOnce(
717 &LayerTreeHostImpl::OnPaintWorkletResultsReady, base::Unretained(this));
718 paint_worklet_painter_->DispatchWorklets(std::move(dirty_paint_worklets),
719 std::move(done_callback));
720 }
721
GatherDirtyPaintWorklets(PaintImageIdFlatSet * dirty_paint_worklet_ids) const722 PaintWorkletJobMap LayerTreeHostImpl::GatherDirtyPaintWorklets(
723 PaintImageIdFlatSet* dirty_paint_worklet_ids) const {
724 PaintWorkletJobMap dirty_paint_worklets;
725 for (PictureLayerImpl* layer :
726 sync_tree()->picture_layers_with_paint_worklets()) {
727 for (const auto& entry : layer->GetPaintWorkletRecordMap()) {
728 const scoped_refptr<const PaintWorkletInput>& input = entry.first;
729 const PaintImage::Id& paint_image_id = entry.second.first;
730 const sk_sp<PaintRecord>& record = entry.second.second;
731 // If we already have a record we can reuse it and so the
732 // PaintWorkletInput isn't dirty.
733 if (record)
734 continue;
735
736 // Mark this PaintWorklet as needing invalidation.
737 dirty_paint_worklet_ids->insert(paint_image_id);
738
739 // Create an entry in the appropriate PaintWorkletJobVector for this dirty
740 // PaintWorklet.
741 int worklet_id = input->WorkletId();
742 auto& job_vector = dirty_paint_worklets[worklet_id];
743 if (!job_vector)
744 job_vector = base::MakeRefCounted<PaintWorkletJobVector>();
745
746 PaintWorkletJob::AnimatedPropertyValues animated_property_values;
747 for (const auto& element : input->GetPropertyKeys()) {
748 // We should not have multiple property ids with the same name.
749 DCHECK(!animated_property_values.contains(element.first));
750 const PaintWorkletInput::PropertyValue& animated_property_value =
751 paint_worklet_tracker_.GetPropertyAnimationValue(element);
752 // No value indicates that the input property was not mutated by CC
753 // animation.
754 if (animated_property_value.has_value()) {
755 animated_property_values.emplace(element.first,
756 animated_property_value);
757 }
758 }
759
760 job_vector->data.emplace_back(layer->id(), input,
761 std::move(animated_property_values));
762 }
763 }
764 return dirty_paint_worklets;
765 }
766
OnPaintWorkletResultsReady(PaintWorkletJobMap results)767 void LayerTreeHostImpl::OnPaintWorkletResultsReady(PaintWorkletJobMap results) {
768 #if DCHECK_IS_ON()
769 // Nothing else should have painted the PaintWorklets while we were waiting,
770 // and the results should have painted every PaintWorklet, so these should be
771 // the same.
772 PaintImageIdFlatSet dirty_paint_worklet_ids;
773 DCHECK_EQ(results.size(),
774 GatherDirtyPaintWorklets(&dirty_paint_worklet_ids).size());
775 #endif
776
777 for (const auto& entry : results) {
778 for (const PaintWorkletJob& job : entry.second->data) {
779 LayerImpl* layer_impl =
780 pending_tree_->FindPendingTreeLayerById(job.layer_id());
781 // Painting the pending tree occurs asynchronously but stalls the pending
782 // tree pipeline, so nothing should have changed while we were doing that.
783 DCHECK(layer_impl);
784 static_cast<PictureLayerImpl*>(layer_impl)
785 ->SetPaintWorkletRecord(job.input(), job.output());
786 }
787 }
788
789 // While the pending tree is being painted by PaintWorklets, we restrict the
790 // tiles the TileManager is able to see. This may cause the TileManager to
791 // believe that it has finished rastering all the necessary tiles. When we
792 // finish painting the tree and release all the tiles, we need to mark the
793 // tile priorities as dirty so that the TileManager logic properly re-runs.
794 tile_priorities_dirty_ = true;
795
796 // Set the painted state before calling the scheduler, to ensure any callback
797 // running as a result sees the correct painted state.
798 pending_tree_fully_painted_ = true;
799 client_->NotifyPaintWorkletStateChange(Scheduler::PaintWorkletState::IDLE);
800
801 // The pending tree may have been force activated from the signal to the
802 // scheduler above, in which case there is no longer a tree to paint.
803 if (pending_tree_)
804 NotifyPendingTreeFullyPainted();
805 }
806
NotifyPendingTreeFullyPainted()807 void LayerTreeHostImpl::NotifyPendingTreeFullyPainted() {
808 // The pending tree must be fully painted at this point.
809 DCHECK(pending_tree_fully_painted_);
810
811 // Nobody should claim the pending tree is fully painted if there is an
812 // ongoing dispatch.
813 DCHECK(!paint_worklet_painter_ ||
814 !paint_worklet_painter_->HasOngoingDispatch());
815
816 // Start working on newly created tiles immediately if needed.
817 // TODO(vmpstr): Investigate always having PrepareTiles issue
818 // NotifyReadyToActivate, instead of handling it here.
819 bool did_prepare_tiles = PrepareTiles();
820 if (!did_prepare_tiles) {
821 NotifyReadyToActivate();
822
823 // Ensure we get ReadyToDraw signal even when PrepareTiles not run. This
824 // is important for SingleThreadProxy and impl-side painting case. For
825 // STP, we commit to active tree and RequiresHighResToDraw, and set
826 // Scheduler to wait for ReadyToDraw signal to avoid Checkerboard.
827 if (CommitToActiveTree())
828 NotifyReadyToDraw();
829 } else if (!CommitToActiveTree()) {
830 DCHECK(!pending_tree_raster_duration_timer_);
831 pending_tree_raster_duration_timer_ =
832 std::make_unique<PendingTreeRasterDurationHistogramTimer>();
833 }
834 }
835
CanDraw() const836 bool LayerTreeHostImpl::CanDraw() const {
837 // Note: If you are changing this function or any other function that might
838 // affect the result of CanDraw, make sure to call
839 // client_->OnCanDrawStateChanged in the proper places and update the
840 // NotifyIfCanDrawChanged test.
841
842 if (!layer_tree_frame_sink_) {
843 TRACE_EVENT_INSTANT0("cc",
844 "LayerTreeHostImpl::CanDraw no LayerTreeFrameSink",
845 TRACE_EVENT_SCOPE_THREAD);
846 return false;
847 }
848
849 // TODO(boliu): Make draws without layers work and move this below
850 // |resourceless_software_draw_| check. Tracked in crbug.com/264967.
851 if (active_tree_->LayerListIsEmpty()) {
852 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no root layer",
853 TRACE_EVENT_SCOPE_THREAD);
854 return false;
855 }
856
857 if (resourceless_software_draw_)
858 return true;
859
860 if (active_tree_->GetDeviceViewport().IsEmpty()) {
861 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport",
862 TRACE_EVENT_SCOPE_THREAD);
863 return false;
864 }
865 if (EvictedUIResourcesExist()) {
866 TRACE_EVENT_INSTANT0(
867 "cc", "LayerTreeHostImpl::CanDraw UI resources evicted not recreated",
868 TRACE_EVENT_SCOPE_THREAD);
869 return false;
870 }
871 return true;
872 }
873
AnimatePendingTreeAfterCommit()874 void LayerTreeHostImpl::AnimatePendingTreeAfterCommit() {
875 // Animate the pending tree layer animations to put them at initial positions
876 // and starting state. There is no need to run other animations on pending
877 // tree because they depend on user inputs so the state is identical to what
878 // the active tree has.
879 AnimateLayers(CurrentBeginFrameArgs().frame_time, /* is_active_tree */ false);
880 }
881
Animate()882 void LayerTreeHostImpl::Animate() {
883 AnimateInternal();
884 }
885
AnimateInternal()886 void LayerTreeHostImpl::AnimateInternal() {
887 DCHECK(task_runner_provider_->IsImplThread());
888 base::TimeTicks monotonic_time = CurrentBeginFrameArgs().frame_time;
889
890 // mithro(TODO): Enable these checks.
891 // DCHECK(!current_begin_frame_tracker_.HasFinished());
892 // DCHECK(monotonic_time == current_begin_frame_tracker_.Current().frame_time)
893 // << "Called animate with unknown frame time!?";
894
895 bool did_animate = false;
896
897 // TODO(bokan): This should return did_animate, see TODO in
898 // ElasticOverscrollController::Animate. crbug.com/551138.
899 if (input_delegate_)
900 input_delegate_->TickAnimations(monotonic_time);
901
902 did_animate |= AnimatePageScale(monotonic_time);
903 did_animate |= AnimateLayers(monotonic_time, /* is_active_tree */ true);
904 did_animate |= AnimateScrollbars(monotonic_time);
905 did_animate |= AnimateBrowserControls(monotonic_time);
906
907 if (did_animate) {
908 // Animating stuff can change the root scroll offset, so inform the
909 // synchronous input handler.
910 if (input_delegate_)
911 input_delegate_->RootLayerStateMayHaveChanged();
912
913 // If the tree changed, then we want to draw at the end of the current
914 // frame.
915 SetNeedsRedraw();
916 }
917 }
918
PrepareTiles()919 bool LayerTreeHostImpl::PrepareTiles() {
920 if (!tile_priorities_dirty_)
921 return false;
922
923 client_->WillPrepareTiles();
924 bool did_prepare_tiles = tile_manager_.PrepareTiles(global_tile_state_);
925 if (did_prepare_tiles)
926 tile_priorities_dirty_ = false;
927 client_->DidPrepareTiles();
928 return did_prepare_tiles;
929 }
930
StartPageScaleAnimation(const gfx::Vector2d & target_offset,bool anchor_point,float page_scale,base::TimeDelta duration)931 void LayerTreeHostImpl::StartPageScaleAnimation(
932 const gfx::Vector2d& target_offset,
933 bool anchor_point,
934 float page_scale,
935 base::TimeDelta duration) {
936 // Temporary crash logging for https://crbug.com/845097.
937 static bool has_dumped_without_crashing = false;
938 if (settings().is_layer_tree_for_subframe && !has_dumped_without_crashing) {
939 has_dumped_without_crashing = true;
940 static auto* psf_oopif_animation_error =
941 base::debug::AllocateCrashKeyString("psf_oopif_animation_error",
942 base::debug::CrashKeySize::Size32);
943 base::debug::SetCrashKeyString(
944 psf_oopif_animation_error,
945 base::StringPrintf("%p", InnerViewportScrollNode()));
946 base::debug::DumpWithoutCrashing();
947 }
948
949 if (!InnerViewportScrollNode())
950 return;
951
952 gfx::ScrollOffset scroll_total = active_tree_->TotalScrollOffset();
953 gfx::SizeF scrollable_size = active_tree_->ScrollableSize();
954 gfx::SizeF viewport_size(
955 active_tree_->InnerViewportScrollNode()->container_bounds);
956
957 // TODO(miletus) : Pass in ScrollOffset.
958 page_scale_animation_ =
959 PageScaleAnimation::Create(ScrollOffsetToVector2dF(scroll_total),
960 active_tree_->current_page_scale_factor(),
961 viewport_size, scrollable_size);
962
963 if (anchor_point) {
964 gfx::Vector2dF anchor(target_offset);
965 page_scale_animation_->ZoomWithAnchor(anchor, page_scale,
966 duration.InSecondsF());
967 } else {
968 gfx::Vector2dF scaled_target_offset = target_offset;
969 page_scale_animation_->ZoomTo(scaled_target_offset, page_scale,
970 duration.InSecondsF());
971 }
972
973 SetNeedsOneBeginImplFrame();
974 client_->SetNeedsCommitOnImplThread();
975 client_->RenewTreePriority();
976 }
977
SetNeedsAnimateInput()978 void LayerTreeHostImpl::SetNeedsAnimateInput() {
979 SetNeedsOneBeginImplFrame();
980 }
981
982 std::unique_ptr<SwapPromiseMonitor>
CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo * latency)983 LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor(
984 ui::LatencyInfo* latency) {
985 return base::WrapUnique(new LatencyInfoSwapPromiseMonitor(latency, this));
986 }
987
988 std::unique_ptr<EventsMetricsManager::ScopedMonitor>
GetScopedEventMetricsMonitor(EventsMetricsManager::ScopedMonitor::DoneCallback done_callback)989 LayerTreeHostImpl::GetScopedEventMetricsMonitor(
990 EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) {
991 return events_metrics_manager_.GetScopedMonitor(std::move(done_callback));
992 }
993
NotifyInputEvent()994 void LayerTreeHostImpl::NotifyInputEvent() {
995 frame_rate_estimator_.NotifyInputEvent();
996 }
997
QueueSwapPromiseForMainThreadScrollUpdate(std::unique_ptr<SwapPromise> swap_promise)998 void LayerTreeHostImpl::QueueSwapPromiseForMainThreadScrollUpdate(
999 std::unique_ptr<SwapPromise> swap_promise) {
1000 swap_promises_for_main_thread_scroll_update_.push_back(
1001 std::move(swap_promise));
1002 }
1003
AsValueInto(base::trace_event::TracedValue * value) const1004 void LayerTreeHostImpl::FrameData::AsValueInto(
1005 base::trace_event::TracedValue* value) const {
1006 value->SetBoolean("has_no_damage", has_no_damage);
1007
1008 // Quad data can be quite large, so only dump render passes if we are
1009 // logging verbosely or viz.quads tracing category is enabled.
1010 bool quads_enabled = VLOG_IS_ON(3);
1011 if (!quads_enabled) {
1012 TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("viz.quads"),
1013 &quads_enabled);
1014 }
1015 if (quads_enabled) {
1016 value->BeginArray("render_passes");
1017 for (size_t i = 0; i < render_passes.size(); ++i) {
1018 value->BeginDictionary();
1019 render_passes[i]->AsValueInto(value);
1020 value->EndDictionary();
1021 }
1022 value->EndArray();
1023 }
1024 }
1025
ToString() const1026 std::string LayerTreeHostImpl::FrameData::ToString() const {
1027 base::trace_event::TracedValueJSON value;
1028 AsValueInto(&value);
1029 return value.ToFormattedJSON();
1030 }
1031
GetDrawMode() const1032 DrawMode LayerTreeHostImpl::GetDrawMode() const {
1033 if (resourceless_software_draw_) {
1034 return DRAW_MODE_RESOURCELESS_SOFTWARE;
1035 } else if (layer_tree_frame_sink_->context_provider()) {
1036 return DRAW_MODE_HARDWARE;
1037 } else {
1038 return DRAW_MODE_SOFTWARE;
1039 }
1040 }
1041
AppendQuadsToFillScreen(viz::CompositorRenderPass * target_render_pass,const RenderSurfaceImpl * root_render_surface,SkColor screen_background_color,const Region & fill_region)1042 static void AppendQuadsToFillScreen(
1043 viz::CompositorRenderPass* target_render_pass,
1044 const RenderSurfaceImpl* root_render_surface,
1045 SkColor screen_background_color,
1046 const Region& fill_region) {
1047 if (!root_render_surface || !SkColorGetA(screen_background_color))
1048 return;
1049 if (fill_region.IsEmpty())
1050 return;
1051
1052 // Manually create the quad state for the gutter quads, as the root layer
1053 // doesn't have any bounds and so can't generate this itself.
1054 // TODO(danakj): Make the gutter quads generated by the solid color layer
1055 // (make it smarter about generating quads to fill unoccluded areas).
1056
1057 gfx::Rect root_target_rect = root_render_surface->content_rect();
1058 float opacity = 1.f;
1059 int sorting_context_id = 0;
1060 bool are_contents_opaque = SkColorGetA(screen_background_color) == 0xFF;
1061 viz::SharedQuadState* shared_quad_state =
1062 target_render_pass->CreateAndAppendSharedQuadState();
1063 shared_quad_state->SetAll(gfx::Transform(), root_target_rect,
1064 root_target_rect, gfx::MaskFilterInfo(),
1065 root_target_rect, false, are_contents_opaque,
1066 opacity, SkBlendMode::kSrcOver, sorting_context_id);
1067
1068 for (gfx::Rect screen_space_rect : fill_region) {
1069 gfx::Rect visible_screen_space_rect = screen_space_rect;
1070 // Skip the quad culler and just append the quads directly to avoid
1071 // occlusion checks.
1072 auto* quad =
1073 target_render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
1074 quad->SetNew(shared_quad_state, screen_space_rect,
1075 visible_screen_space_rect, screen_background_color, false);
1076 }
1077 }
1078
FindRenderPassById(const viz::CompositorRenderPassList & list,viz::CompositorRenderPassId id)1079 static viz::CompositorRenderPass* FindRenderPassById(
1080 const viz::CompositorRenderPassList& list,
1081 viz::CompositorRenderPassId id) {
1082 auto it =
1083 std::find_if(list.begin(), list.end(),
1084 [id](const std::unique_ptr<viz::CompositorRenderPass>& p) {
1085 return p->id == id;
1086 });
1087 return it == list.end() ? nullptr : it->get();
1088 }
1089
HasDamage() const1090 bool LayerTreeHostImpl::HasDamage() const {
1091 DCHECK(!active_tree()->needs_update_draw_properties());
1092 DCHECK(CanDraw());
1093
1094 // When touch handle visibility changes there is no visible damage
1095 // because touch handles are composited in the browser. However we
1096 // still want the browser to be notified that the handles changed
1097 // through the |ViewHostMsg_SwapCompositorFrame| IPC so we keep
1098 // track of handle visibility changes here.
1099 if (active_tree()->HandleVisibilityChanged())
1100 return true;
1101
1102 if (!viewport_damage_rect_.IsEmpty())
1103 return true;
1104
1105 // If the set of referenced surfaces has changed then we must submit a new
1106 // CompositorFrame to update surface references.
1107 if (last_draw_referenced_surfaces_ != active_tree()->SurfaceRanges())
1108 return true;
1109
1110 // If we have a new LocalSurfaceId, we must always submit a CompositorFrame
1111 // because the parent is blocking on us.
1112 if (last_draw_local_surface_id_ !=
1113 child_local_surface_id_allocator_.GetCurrentLocalSurfaceId()) {
1114 return true;
1115 }
1116
1117 const LayerTreeImpl* active_tree = active_tree_.get();
1118
1119 // If the root render surface has no visible damage, then don't generate a
1120 // frame at all.
1121 const RenderSurfaceImpl* root_surface = active_tree->RootRenderSurface();
1122 bool root_surface_has_visible_damage =
1123 root_surface->GetDamageRect().Intersects(root_surface->content_rect());
1124 bool hud_wants_to_draw_ = active_tree->hud_layer() &&
1125 active_tree->hud_layer()->IsAnimatingHUDContents();
1126
1127 return root_surface_has_visible_damage ||
1128 active_tree_->property_trees()->effect_tree.HasCopyRequests() ||
1129 hud_wants_to_draw_;
1130 }
1131
CalculateRenderPasses(FrameData * frame)1132 DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
1133 DCHECK(frame->render_passes.empty());
1134 DCHECK(CanDraw());
1135 DCHECK(!active_tree_->LayerListIsEmpty());
1136
1137 // For now, we use damage tracking to compute a global scissor. To do this, we
1138 // must compute all damage tracking before drawing anything, so that we know
1139 // the root damage rect. The root damage rect is then used to scissor each
1140 // surface.
1141 DamageTracker::UpdateDamageTracking(active_tree_.get());
1142
1143 if (HasDamage()) {
1144 consecutive_frame_with_damage_count_++;
1145 } else {
1146 TRACE_EVENT0("cc",
1147 "LayerTreeHostImpl::CalculateRenderPasses::EmptyDamageRect");
1148 frame->has_no_damage = true;
1149 DCHECK(!resourceless_software_draw_);
1150 consecutive_frame_with_damage_count_ = 0;
1151 return DRAW_SUCCESS;
1152 }
1153
1154 TRACE_EVENT_BEGIN2("cc,benchmark", "LayerTreeHostImpl::CalculateRenderPasses",
1155 "render_surface_list.size()",
1156 static_cast<uint64_t>(frame->render_surface_list->size()),
1157 "RequiresHighResToDraw", RequiresHighResToDraw());
1158
1159 // HandleVisibilityChanged contributed to the above damage check, so reset it
1160 // now that we're going to draw.
1161 // TODO(jamwalla): only call this if we are sure the frame draws. Tracked in
1162 // crbug.com/805673.
1163 active_tree_->ResetHandleVisibilityChanged();
1164
1165 // Create the render passes in dependency order.
1166 size_t render_surface_list_size = frame->render_surface_list->size();
1167 for (size_t i = 0; i < render_surface_list_size; ++i) {
1168 size_t surface_index = render_surface_list_size - 1 - i;
1169 RenderSurfaceImpl* render_surface =
1170 (*frame->render_surface_list)[surface_index];
1171
1172 bool is_root_surface =
1173 render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId;
1174 bool should_draw_into_render_pass =
1175 is_root_surface || render_surface->contributes_to_drawn_surface() ||
1176 render_surface->HasCopyRequest() ||
1177 render_surface->ShouldCacheRenderSurface();
1178 if (should_draw_into_render_pass)
1179 frame->render_passes.push_back(render_surface->CreateRenderPass());
1180 }
1181
1182 // Damage rects for non-root passes aren't meaningful, so set them to be
1183 // equal to the output rect.
1184 for (size_t i = 0; i + 1 < frame->render_passes.size(); ++i) {
1185 viz::CompositorRenderPass* pass = frame->render_passes[i].get();
1186 pass->damage_rect = pass->output_rect;
1187 }
1188
1189 // When we are displaying the HUD, change the root damage rect to cover the
1190 // entire root surface. This will disable partial-swap/scissor optimizations
1191 // that would prevent the HUD from updating, since the HUD does not cause
1192 // damage itself, to prevent it from messing with damage visualizations. Since
1193 // damage visualizations are done off the LayerImpls and RenderSurfaceImpls,
1194 // changing the RenderPass does not affect them.
1195 if (active_tree_->hud_layer()) {
1196 viz::CompositorRenderPass* root_pass = frame->render_passes.back().get();
1197 root_pass->damage_rect = root_pass->output_rect;
1198 }
1199
1200 // Grab this region here before iterating layers. Taking copy requests from
1201 // the layers while constructing the render passes will dirty the render
1202 // surface layer list and this unoccluded region, flipping the dirty bit to
1203 // true, and making us able to query for it without doing
1204 // UpdateDrawProperties again. The value inside the Region is not actually
1205 // changed until UpdateDrawProperties happens, so a reference to it is safe.
1206 const Region& unoccluded_screen_space_region =
1207 active_tree_->UnoccludedScreenSpaceRegion();
1208
1209 // Typically when we are missing a texture and use a checkerboard quad, we
1210 // still draw the frame. However when the layer being checkerboarded is moving
1211 // due to an impl-animation, we drop the frame to avoid flashing due to the
1212 // texture suddenly appearing in the future.
1213 DrawResult draw_result = DRAW_SUCCESS;
1214
1215 const DrawMode draw_mode = GetDrawMode();
1216
1217 int num_missing_tiles = 0;
1218 int num_incomplete_tiles = 0;
1219 int64_t checkerboarded_no_recording_content_area = 0;
1220 int64_t checkerboarded_needs_raster_content_area = 0;
1221 int64_t total_visible_area = 0;
1222 bool have_copy_request =
1223 active_tree()->property_trees()->effect_tree.HasCopyRequests();
1224 bool have_missing_animated_tiles = false;
1225 int num_of_layers_with_videos = 0;
1226
1227 // Advance our de-jelly state. This is a no-op if de-jelly is not active.
1228 de_jelly_state_.AdvanceFrame(active_tree_.get());
1229
1230 for (EffectTreeLayerListIterator it(active_tree());
1231 it.state() != EffectTreeLayerListIterator::State::END; ++it) {
1232 auto target_render_pass_id = it.target_render_surface()->render_pass_id();
1233 viz::CompositorRenderPass* target_render_pass =
1234 FindRenderPassById(frame->render_passes, target_render_pass_id);
1235
1236 AppendQuadsData append_quads_data;
1237
1238 if (it.state() == EffectTreeLayerListIterator::State::TARGET_SURFACE) {
1239 RenderSurfaceImpl* render_surface = it.target_render_surface();
1240 if (render_surface->HasCopyRequest()) {
1241 active_tree()
1242 ->property_trees()
1243 ->effect_tree.TakeCopyRequestsAndTransformToSurface(
1244 render_surface->EffectTreeIndex(),
1245 &target_render_pass->copy_requests);
1246 }
1247 } else if (it.state() ==
1248 EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) {
1249 RenderSurfaceImpl* render_surface = it.current_render_surface();
1250 if (render_surface->contributes_to_drawn_surface()) {
1251 render_surface->AppendQuads(draw_mode, target_render_pass,
1252 &append_quads_data);
1253 if (settings_.allow_de_jelly_effect) {
1254 de_jelly_state_.UpdateSharedQuadState(
1255 active_tree_.get(), render_surface->TransformTreeIndex(),
1256 target_render_pass);
1257 }
1258 }
1259 } else if (it.state() == EffectTreeLayerListIterator::State::LAYER) {
1260 LayerImpl* layer = it.current_layer();
1261 if (layer->WillDraw(draw_mode, &resource_provider_)) {
1262 DCHECK_EQ(active_tree_.get(), layer->layer_tree_impl());
1263
1264 frame->will_draw_layers.push_back(layer);
1265 if (layer->may_contain_video()) {
1266 num_of_layers_with_videos++;
1267 frame->may_contain_video = true;
1268 }
1269
1270 layer->AppendQuads(target_render_pass, &append_quads_data);
1271 if (settings_.allow_de_jelly_effect) {
1272 de_jelly_state_.UpdateSharedQuadState(active_tree_.get(),
1273 layer->transform_tree_index(),
1274 target_render_pass);
1275 }
1276 }
1277
1278 rendering_stats_instrumentation_->AddVisibleContentArea(
1279 append_quads_data.visible_layer_area);
1280 rendering_stats_instrumentation_->AddApproximatedVisibleContentArea(
1281 append_quads_data.approximated_visible_content_area);
1282 rendering_stats_instrumentation_->AddCheckerboardedVisibleContentArea(
1283 append_quads_data.checkerboarded_visible_content_area);
1284 rendering_stats_instrumentation_->AddCheckerboardedNoRecordingContentArea(
1285 append_quads_data.checkerboarded_no_recording_content_area);
1286 rendering_stats_instrumentation_->AddCheckerboardedNeedsRasterContentArea(
1287 append_quads_data.checkerboarded_needs_raster_content_area);
1288
1289 num_missing_tiles += append_quads_data.num_missing_tiles;
1290 num_incomplete_tiles += append_quads_data.num_incomplete_tiles;
1291 checkerboarded_no_recording_content_area +=
1292 append_quads_data.checkerboarded_no_recording_content_area;
1293 checkerboarded_needs_raster_content_area +=
1294 append_quads_data.checkerboarded_needs_raster_content_area;
1295 total_visible_area += append_quads_data.visible_layer_area;
1296 if (append_quads_data.num_missing_tiles > 0) {
1297 have_missing_animated_tiles |=
1298 layer->screen_space_transform_is_animating();
1299 }
1300 }
1301 frame->activation_dependencies.insert(
1302 frame->activation_dependencies.end(),
1303 append_quads_data.activation_dependencies.begin(),
1304 append_quads_data.activation_dependencies.end());
1305 if (append_quads_data.deadline_in_frames) {
1306 if (!frame->deadline_in_frames) {
1307 frame->deadline_in_frames = append_quads_data.deadline_in_frames;
1308 } else {
1309 frame->deadline_in_frames = std::max(
1310 *frame->deadline_in_frames, *append_quads_data.deadline_in_frames);
1311 }
1312 }
1313 frame->use_default_lower_bound_deadline |=
1314 append_quads_data.use_default_lower_bound_deadline;
1315 }
1316
1317 // If CommitToActiveTree() is true, then we wait to draw until
1318 // NotifyReadyToDraw. That means we're in as good shape as is possible now,
1319 // so there's no reason to stop the draw now (and this is not supported by
1320 // SingleThreadProxy).
1321 if (have_missing_animated_tiles && !CommitToActiveTree())
1322 draw_result = DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
1323
1324 // When we require high res to draw, abort the draw (almost) always. This does
1325 // not cause the scheduler to do a main frame, instead it will continue to try
1326 // drawing until we finally complete, so the copy request will not be lost.
1327 // TODO(weiliangc): Remove RequiresHighResToDraw. crbug.com/469175
1328 if (num_incomplete_tiles || num_missing_tiles) {
1329 if (RequiresHighResToDraw())
1330 draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
1331 }
1332
1333 // Only enable frame rate estimation if it would help lower the composition
1334 // rate for videos.
1335 const bool enable_frame_rate_estimation = num_of_layers_with_videos > 1;
1336 frame_rate_estimator_.SetFrameEstimationEnabled(enable_frame_rate_estimation);
1337
1338 // When doing a resourceless software draw, we don't have control over the
1339 // surface the compositor draws to, so even though the frame may not be
1340 // complete, the previous frame has already been potentially lost, so an
1341 // incomplete frame is better than nothing, so this takes highest precidence.
1342 if (resourceless_software_draw_)
1343 draw_result = DRAW_SUCCESS;
1344
1345 #if DCHECK_IS_ON()
1346 for (const auto& render_pass : frame->render_passes) {
1347 for (auto* quad : render_pass->quad_list)
1348 DCHECK(quad->shared_quad_state);
1349 }
1350 DCHECK_EQ(frame->render_passes.back()->output_rect.origin(),
1351 active_tree_->GetDeviceViewport().origin());
1352 #endif
1353 bool has_transparent_background =
1354 SkColorGetA(active_tree_->background_color()) != SK_AlphaOPAQUE;
1355 auto* root_render_surface = active_tree_->RootRenderSurface();
1356 if (root_render_surface && !has_transparent_background) {
1357 frame->render_passes.back()->has_transparent_background = false;
1358
1359 // If any tiles are missing, then fill behind the entire root render
1360 // surface. This is a workaround for this edge case, instead of tracking
1361 // individual tiles that are missing.
1362 Region fill_region = unoccluded_screen_space_region;
1363 if (num_missing_tiles > 0)
1364 fill_region = root_render_surface->content_rect();
1365
1366 AppendQuadsToFillScreen(frame->render_passes.back().get(),
1367 root_render_surface,
1368 active_tree_->background_color(), fill_region);
1369 }
1370
1371 RemoveRenderPasses(frame);
1372 // If we're making a frame to draw, it better have at least one render pass.
1373 DCHECK(!frame->render_passes.empty());
1374
1375 if (have_copy_request) {
1376 // Any copy requests left in the tree are not going to get serviced, and
1377 // should be aborted.
1378 active_tree()->property_trees()->effect_tree.ClearCopyRequests();
1379
1380 // Draw properties depend on copy requests.
1381 active_tree()->set_needs_update_draw_properties();
1382 }
1383
1384 frame->has_missing_content =
1385 num_missing_tiles > 0 || num_incomplete_tiles > 0;
1386
1387 if (ukm_manager_) {
1388 ukm_manager_->AddCheckerboardStatsForFrame(
1389 checkerboarded_no_recording_content_area +
1390 checkerboarded_needs_raster_content_area,
1391 num_missing_tiles, total_visible_area);
1392 }
1393
1394 if (active_tree_->has_ever_been_drawn()) {
1395 UMA_HISTOGRAM_COUNTS_100(
1396 "Compositing.RenderPass.AppendQuadData.NumMissingTiles",
1397 num_missing_tiles);
1398 UMA_HISTOGRAM_COUNTS_100(
1399 "Compositing.RenderPass.AppendQuadData.NumIncompleteTiles",
1400 num_incomplete_tiles);
1401 UMA_HISTOGRAM_COUNTS_1M(
1402 "Compositing.RenderPass.AppendQuadData."
1403 "CheckerboardedNoRecordingContentArea",
1404 checkerboarded_no_recording_content_area);
1405 UMA_HISTOGRAM_COUNTS_1M(
1406 "Compositing.RenderPass.AppendQuadData."
1407 "CheckerboardedNeedRasterContentArea",
1408 checkerboarded_needs_raster_content_area);
1409 }
1410
1411 TRACE_EVENT_END2("cc,benchmark", "LayerTreeHostImpl::CalculateRenderPasses",
1412 "draw_result", draw_result, "missing tiles",
1413 num_missing_tiles);
1414
1415 // Draw has to be successful to not drop the copy request layer.
1416 // When we have a copy request for a layer, we need to draw even if there
1417 // would be animating checkerboards, because failing under those conditions
1418 // triggers a new main frame, which may cause the copy request layer to be
1419 // destroyed.
1420 // TODO(weiliangc): Test copy request w/ LayerTreeFrameSink recreation. Would
1421 // trigger this DCHECK.
1422 DCHECK(!have_copy_request || draw_result == DRAW_SUCCESS);
1423
1424 // TODO(crbug.com/564832): This workaround to prevent creating unnecessarily
1425 // persistent render passes. When a copy request is made, it may force a
1426 // separate render pass for the layer, which will persist until a new commit
1427 // removes it. Force a commit after copy requests, to remove extra render
1428 // passes.
1429 if (have_copy_request)
1430 client_->SetNeedsCommitOnImplThread();
1431
1432 return draw_result;
1433 }
1434
DidAnimateScrollOffset()1435 void LayerTreeHostImpl::DidAnimateScrollOffset() {
1436 client_->SetNeedsCommitOnImplThread();
1437 client_->RenewTreePriority();
1438 }
1439
SetViewportDamage(const gfx::Rect & damage_rect)1440 void LayerTreeHostImpl::SetViewportDamage(const gfx::Rect& damage_rect) {
1441 viewport_damage_rect_.Union(damage_rect);
1442 }
1443
SetEnableFrameRateThrottling(bool enable_frame_rate_throttling)1444 void LayerTreeHostImpl::SetEnableFrameRateThrottling(
1445 bool enable_frame_rate_throttling) {
1446 enable_frame_rate_throttling_ = enable_frame_rate_throttling;
1447 }
1448
UpdateElements(ElementListType changed_list)1449 void LayerTreeHostImpl::UpdateElements(ElementListType changed_list) {
1450 mutator_host()->UpdateRegisteredElementIds(changed_list);
1451 }
1452
InvalidateContentOnImplSide()1453 void LayerTreeHostImpl::InvalidateContentOnImplSide() {
1454 DCHECK(!pending_tree_);
1455 // Invalidation should never be ran outside the impl frame for non
1456 // synchronous compositor mode. For devices that use synchronous compositor,
1457 // e.g. Android Webview, the assertion is not guaranteed because it may ask
1458 // for a frame at any time.
1459 DCHECK(impl_thread_phase_ == ImplThreadPhase::INSIDE_IMPL_FRAME ||
1460 settings_.using_synchronous_renderer_compositor);
1461
1462 if (!CommitToActiveTree())
1463 CreatePendingTree();
1464
1465 UpdateSyncTreeAfterCommitOrImplSideInvalidation();
1466 }
1467
InvalidateLayerTreeFrameSink(bool needs_redraw)1468 void LayerTreeHostImpl::InvalidateLayerTreeFrameSink(bool needs_redraw) {
1469 DCHECK(layer_tree_frame_sink());
1470
1471 layer_tree_frame_sink()->Invalidate(needs_redraw);
1472 }
1473
PrepareToDraw(FrameData * frame)1474 DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
1475 TRACE_EVENT1("cc", "LayerTreeHostImpl::PrepareToDraw", "SourceFrameNumber",
1476 active_tree_->source_frame_number());
1477 TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline",
1478 TRACE_ID_GLOBAL(CurrentBeginFrameArgs().trace_id),
1479 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
1480 "step", "GenerateRenderPass");
1481 if (input_delegate_)
1482 input_delegate_->WillDraw();
1483
1484 // |client_name| is used for various UMA histograms below.
1485 // GetClientNameForMetrics only returns one non-null value over the lifetime
1486 // of the process, so the histogram names are runtime constant.
1487 const char* client_name = GetClientNameForMetrics();
1488 if (client_name) {
1489 size_t total_gpu_memory_for_tilings_in_bytes = 0;
1490 for (const PictureLayerImpl* layer : active_tree()->picture_layers())
1491 total_gpu_memory_for_tilings_in_bytes += layer->GPUMemoryUsageInBytes();
1492
1493 UMA_HISTOGRAM_CUSTOM_COUNTS(
1494 base::StringPrintf("Compositing.%s.NumActiveLayers", client_name),
1495 base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
1496
1497 UMA_HISTOGRAM_CUSTOM_COUNTS(
1498 base::StringPrintf("Compositing.%s.NumActivePictureLayers",
1499 client_name),
1500 base::saturated_cast<int>(active_tree_->picture_layers().size()), 1,
1501 400, 20);
1502
1503 // TODO(pdr): Instead of skipping empty picture layers, maybe we should
1504 // accumulate layer->GetRasterSource()->GetMemoryUsage() above and skip
1505 // recording when the accumulated memory usage is 0.
1506 if (!active_tree()->picture_layers().empty()) {
1507 UMA_HISTOGRAM_CUSTOM_COUNTS(
1508 base::StringPrintf("Compositing.%s.GPUMemoryForTilingsInKb",
1509 client_name),
1510 base::saturated_cast<int>(total_gpu_memory_for_tilings_in_bytes /
1511 1024),
1512 1, kGPUMemoryForTilingsLargestBucketKb,
1513 kGPUMemoryForTilingsBucketCount);
1514 }
1515 }
1516
1517 // Tick worklet animations here, just before draw, to give animation worklets
1518 // as much time as possible to produce their output for this frame. Note that
1519 // an animation worklet is asked to produce its output at the beginning of the
1520 // frame along side other animations but its output arrives asynchronously so
1521 // we tick worklet animations and apply that output here instead.
1522 mutator_host_->TickWorkletAnimations();
1523
1524 bool ok = active_tree_->UpdateDrawProperties();
1525 DCHECK(ok) << "UpdateDrawProperties failed during draw";
1526
1527 // This will cause NotifyTileStateChanged() to be called for any tiles that
1528 // completed, which will add damage for visible tiles to the frame for them so
1529 // they appear as part of the current frame being drawn.
1530 tile_manager_.CheckForCompletedTasks();
1531
1532 frame->render_surface_list = &active_tree_->GetRenderSurfaceList();
1533 frame->render_passes.clear();
1534 frame->will_draw_layers.clear();
1535 frame->has_no_damage = false;
1536 frame->may_contain_video = false;
1537
1538 if (active_tree_->RootRenderSurface()) {
1539 active_tree_->RootRenderSurface()->damage_tracker()->AddDamageNextUpdate(
1540 viewport_damage_rect_);
1541 viewport_damage_rect_ = gfx::Rect();
1542 }
1543
1544 DrawResult draw_result = CalculateRenderPasses(frame);
1545
1546 // Dump render passes and draw quads if run with:
1547 // --vmodule=layer_tree_host_impl=3
1548 if (VLOG_IS_ON(3)) {
1549 VLOG(3) << "Prepare to draw ("
1550 << (client_name ? client_name : "<unknown client>") << ")\n"
1551 << frame->ToString();
1552 }
1553
1554 if (draw_result != DRAW_SUCCESS) {
1555 DCHECK(!resourceless_software_draw_);
1556 return draw_result;
1557 }
1558
1559 // If we return DRAW_SUCCESS, then we expect DrawLayers() to be called before
1560 // this function is called again.
1561 return DRAW_SUCCESS;
1562 }
1563
RemoveRenderPasses(FrameData * frame)1564 void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) {
1565 // There is always at least a root RenderPass.
1566 DCHECK_GE(frame->render_passes.size(), 1u);
1567
1568 // A set of RenderPasses that we have seen.
1569 base::flat_set<viz::CompositorRenderPassId> pass_exists;
1570 // A set of viz::RenderPassDrawQuads that we have seen (stored by the
1571 // RenderPasses they refer to).
1572 base::flat_map<viz::CompositorRenderPassId, int> pass_references;
1573
1574 // Iterate RenderPasses in draw order, removing empty render passes (except
1575 // the root RenderPass).
1576 for (size_t i = 0; i < frame->render_passes.size(); ++i) {
1577 viz::CompositorRenderPass* pass = frame->render_passes[i].get();
1578
1579 // Remove orphan viz::RenderPassDrawQuads.
1580 for (auto it = pass->quad_list.begin(); it != pass->quad_list.end();) {
1581 if (it->material != viz::DrawQuad::Material::kCompositorRenderPass) {
1582 ++it;
1583 continue;
1584 }
1585 const viz::CompositorRenderPassDrawQuad* quad =
1586 viz::CompositorRenderPassDrawQuad::MaterialCast(*it);
1587 // If the RenderPass doesn't exist, we can remove the quad.
1588 if (pass_exists.count(quad->render_pass_id)) {
1589 // Otherwise, save a reference to the RenderPass so we know there's a
1590 // quad using it.
1591 pass_references[quad->render_pass_id]++;
1592 ++it;
1593 } else {
1594 it = pass->quad_list.EraseAndInvalidateAllPointers(it);
1595 }
1596 }
1597
1598 if (i == frame->render_passes.size() - 1) {
1599 // Don't remove the root RenderPass.
1600 break;
1601 }
1602
1603 if (pass->quad_list.empty() && pass->copy_requests.empty() &&
1604 pass->filters.IsEmpty() && pass->backdrop_filters.IsEmpty()) {
1605 // Remove the pass and decrement |i| to counter the for loop's increment,
1606 // so we don't skip the next pass in the loop.
1607 frame->render_passes.erase(frame->render_passes.begin() + i);
1608 --i;
1609 continue;
1610 }
1611
1612 pass_exists.insert(pass->id);
1613 }
1614
1615 // Remove RenderPasses that are not referenced by any draw quads or copy
1616 // requests (except the root RenderPass).
1617 for (size_t i = 0; i < frame->render_passes.size() - 1; ++i) {
1618 // Iterating from the back of the list to the front, skipping over the
1619 // back-most (root) pass, in order to remove each qualified RenderPass, and
1620 // drop references to earlier RenderPasses allowing them to be removed to.
1621 viz::CompositorRenderPass* pass =
1622 frame->render_passes[frame->render_passes.size() - 2 - i].get();
1623 if (!pass->copy_requests.empty())
1624 continue;
1625 if (pass_references[pass->id])
1626 continue;
1627
1628 for (auto it = pass->quad_list.begin(); it != pass->quad_list.end(); ++it) {
1629 if (it->material != viz::DrawQuad::Material::kCompositorRenderPass)
1630 continue;
1631 const viz::CompositorRenderPassDrawQuad* quad =
1632 viz::CompositorRenderPassDrawQuad::MaterialCast(*it);
1633 pass_references[quad->render_pass_id]--;
1634 }
1635
1636 frame->render_passes.erase(frame->render_passes.end() - 2 - i);
1637 --i;
1638 }
1639 }
1640
EvictTexturesForTesting()1641 void LayerTreeHostImpl::EvictTexturesForTesting() {
1642 UpdateTileManagerMemoryPolicy(ManagedMemoryPolicy(0));
1643 }
1644
BlockNotifyReadyToActivateForTesting(bool block)1645 void LayerTreeHostImpl::BlockNotifyReadyToActivateForTesting(bool block) {
1646 NOTREACHED();
1647 }
1648
BlockImplSideInvalidationRequestsForTesting(bool block)1649 void LayerTreeHostImpl::BlockImplSideInvalidationRequestsForTesting(
1650 bool block) {
1651 NOTREACHED();
1652 }
1653
ResetTreesForTesting()1654 void LayerTreeHostImpl::ResetTreesForTesting() {
1655 if (active_tree_)
1656 active_tree_->DetachLayers();
1657 active_tree_ = std::make_unique<LayerTreeImpl>(
1658 this, active_tree()->page_scale_factor(),
1659 active_tree()->top_controls_shown_ratio(),
1660 active_tree()->bottom_controls_shown_ratio(),
1661 active_tree()->elastic_overscroll());
1662 active_tree_->property_trees()->is_active = true;
1663 active_tree_->property_trees()->clear();
1664 if (pending_tree_)
1665 pending_tree_->DetachLayers();
1666 pending_tree_ = nullptr;
1667 if (recycle_tree_)
1668 recycle_tree_->DetachLayers();
1669 recycle_tree_ = nullptr;
1670 }
1671
SourceAnimationFrameNumberForTesting() const1672 size_t LayerTreeHostImpl::SourceAnimationFrameNumberForTesting() const {
1673 return *next_frame_token_;
1674 }
1675
UpdateTileManagerMemoryPolicy(const ManagedMemoryPolicy & policy)1676 void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy(
1677 const ManagedMemoryPolicy& policy) {
1678 if (!resource_pool_)
1679 return;
1680
1681 global_tile_state_.hard_memory_limit_in_bytes = 0;
1682 global_tile_state_.soft_memory_limit_in_bytes = 0;
1683 if (visible_ && policy.bytes_limit_when_visible > 0) {
1684 global_tile_state_.hard_memory_limit_in_bytes =
1685 policy.bytes_limit_when_visible;
1686 global_tile_state_.soft_memory_limit_in_bytes =
1687 (static_cast<int64_t>(global_tile_state_.hard_memory_limit_in_bytes) *
1688 settings_.max_memory_for_prepaint_percentage) /
1689 100;
1690 }
1691 global_tile_state_.memory_limit_policy =
1692 ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy(
1693 visible_ ? policy.priority_cutoff_when_visible
1694 : gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
1695 global_tile_state_.num_resources_limit = policy.num_resources_limit;
1696
1697 if (global_tile_state_.hard_memory_limit_in_bytes > 0) {
1698 // If |global_tile_state_.hard_memory_limit_in_bytes| is greater than 0, we
1699 // consider our contexts visible. Notify the contexts here. We handle
1700 // becoming invisible in NotifyAllTileTasksComplete to avoid interrupting
1701 // running work.
1702 SetContextVisibility(true);
1703
1704 // If |global_tile_state_.hard_memory_limit_in_bytes| is greater than 0, we
1705 // allow the image decode controller to retain resources. We handle the
1706 // equal to 0 case in NotifyAllTileTasksComplete to avoid interrupting
1707 // running work.
1708 if (image_decode_cache_)
1709 image_decode_cache_->SetShouldAggressivelyFreeResources(false);
1710 } else {
1711 // When the memory policy is set to zero, its important to release any
1712 // decoded images cached by the tracker. But we can not re-checker any
1713 // images that have been displayed since the resources, if held by the
1714 // browser, may be re-used. Which is why its important to maintain the
1715 // decode policy tracking.
1716 bool can_clear_decode_policy_tracking = false;
1717 tile_manager_.ClearCheckerImageTracking(can_clear_decode_policy_tracking);
1718 }
1719
1720 DCHECK(resource_pool_);
1721 // Soft limit is used for resource pool such that memory returns to soft
1722 // limit after going over.
1723 resource_pool_->SetResourceUsageLimits(
1724 global_tile_state_.soft_memory_limit_in_bytes,
1725 global_tile_state_.num_resources_limit);
1726
1727 DidModifyTilePriorities();
1728 }
1729
DidModifyTilePriorities()1730 void LayerTreeHostImpl::DidModifyTilePriorities() {
1731 // Mark priorities as dirty and schedule a PrepareTiles().
1732 tile_priorities_dirty_ = true;
1733 tile_manager_.DidModifyTilePriorities();
1734 client_->SetNeedsPrepareTilesOnImplThread();
1735 }
1736
BuildRasterQueue(TreePriority tree_priority,RasterTilePriorityQueue::Type type)1737 std::unique_ptr<RasterTilePriorityQueue> LayerTreeHostImpl::BuildRasterQueue(
1738 TreePriority tree_priority,
1739 RasterTilePriorityQueue::Type type) {
1740 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1741 "LayerTreeHostImpl::BuildRasterQueue");
1742
1743 return RasterTilePriorityQueue::Create(
1744 active_tree_->picture_layers(),
1745 pending_tree_ && pending_tree_fully_painted_
1746 ? pending_tree_->picture_layers()
1747 : std::vector<PictureLayerImpl*>(),
1748 tree_priority, type);
1749 }
1750
1751 std::unique_ptr<EvictionTilePriorityQueue>
BuildEvictionQueue(TreePriority tree_priority)1752 LayerTreeHostImpl::BuildEvictionQueue(TreePriority tree_priority) {
1753 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1754 "LayerTreeHostImpl::BuildEvictionQueue");
1755
1756 std::unique_ptr<EvictionTilePriorityQueue> queue(
1757 new EvictionTilePriorityQueue);
1758 queue->Build(active_tree_->picture_layers(),
1759 pending_tree_ ? pending_tree_->picture_layers()
1760 : std::vector<PictureLayerImpl*>(),
1761 tree_priority);
1762 return queue;
1763 }
1764
SetIsLikelyToRequireADraw(bool is_likely_to_require_a_draw)1765 void LayerTreeHostImpl::SetIsLikelyToRequireADraw(
1766 bool is_likely_to_require_a_draw) {
1767 // Proactively tell the scheduler that we expect to draw within each vsync
1768 // until we get all the tiles ready to draw. If we happen to miss a required
1769 // for draw tile here, then we will miss telling the scheduler each frame that
1770 // we intend to draw so it may make worse scheduling decisions.
1771 is_likely_to_require_a_draw_ = is_likely_to_require_a_draw;
1772 }
1773
GetRasterColorSpace(gfx::ContentColorUsage content_color_usage) const1774 gfx::ColorSpace LayerTreeHostImpl::GetRasterColorSpace(
1775 gfx::ContentColorUsage content_color_usage) const {
1776 constexpr gfx::ColorSpace srgb = gfx::ColorSpace::CreateSRGB();
1777
1778 // If we are likely to software composite the resource, we use sRGB because
1779 // software compositing is unable to perform color conversion.
1780 if (!layer_tree_frame_sink_ || !layer_tree_frame_sink_->context_provider())
1781 return srgb;
1782
1783 if (settings_.prefer_raster_in_srgb &&
1784 content_color_usage == gfx::ContentColorUsage::kSRGB) {
1785 return srgb;
1786 }
1787
1788 // The pending tree will has the most recently updated color space, so use it.
1789 gfx::DisplayColorSpaces display_cs;
1790 if (pending_tree_)
1791 display_cs = pending_tree_->display_color_spaces();
1792 else if (active_tree_)
1793 display_cs = active_tree_->display_color_spaces();
1794
1795 auto result = display_cs.GetOutputColorSpace(gfx::ContentColorUsage::kHDR,
1796 /*needs_alpha=*/false);
1797
1798 // Always specify a color space if color correct rasterization is requested
1799 // (not specifying a color space indicates that no color conversion is
1800 // required).
1801 if (!result.IsValid())
1802 return srgb;
1803
1804 // It's expensive to rasterize in HDR, so we only want to do so when we know
1805 // we have HDR content to rasterize.
1806 if (result.IsHDR() && content_color_usage != gfx::ContentColorUsage::kHDR)
1807 return gfx::ColorSpace::CreateDisplayP3D65();
1808
1809 // The raster color space should contain sRGB to avoid artifacts during
1810 // rasterization.
1811 if (!CheckColorSpaceContainsSrgb(result))
1812 return srgb;
1813
1814 return result;
1815 }
1816
CheckColorSpaceContainsSrgb(const gfx::ColorSpace & color_space) const1817 bool LayerTreeHostImpl::CheckColorSpaceContainsSrgb(
1818 const gfx::ColorSpace& color_space) const {
1819 constexpr gfx::ColorSpace srgb = gfx::ColorSpace::CreateSRGB();
1820
1821 // Color spaces without a custom primary matrix are cheap to compute, so the
1822 // cache can be bypassed.
1823 if (color_space.GetPrimaryID() != gfx::ColorSpace::PrimaryID::CUSTOM)
1824 return color_space.Contains(srgb);
1825
1826 auto it = contains_srgb_cache_.Get(color_space);
1827 if (it != contains_srgb_cache_.end())
1828 return it->second;
1829
1830 bool result = color_space.Contains(srgb);
1831 contains_srgb_cache_.Put(color_space, result);
1832 return result;
1833 }
1834
GetSDRWhiteLevel() const1835 float LayerTreeHostImpl::GetSDRWhiteLevel() const {
1836 // If we are likely to software composite the resource, we use sRGB because
1837 // software compositing is unable to perform color conversion.
1838 if (!layer_tree_frame_sink_ || !layer_tree_frame_sink_->context_provider())
1839 return gfx::ColorSpace::kDefaultSDRWhiteLevel;
1840
1841 // The pending tree will has the most recently updated color space, so use it.
1842 if (pending_tree_)
1843 return pending_tree_->display_color_spaces().GetSDRWhiteLevel();
1844 if (active_tree_)
1845 return active_tree_->display_color_spaces().GetSDRWhiteLevel();
1846 return gfx::ColorSpace::kDefaultSDRWhiteLevel;
1847 }
1848
RequestImplSideInvalidationForCheckerImagedTiles()1849 void LayerTreeHostImpl::RequestImplSideInvalidationForCheckerImagedTiles() {
1850 // When using impl-side invalidation for checker-imaging, a pending tree does
1851 // not need to be flushed as an independent update through the pipeline.
1852 bool needs_first_draw_on_activation = false;
1853 client_->NeedsImplSideInvalidation(needs_first_draw_on_activation);
1854 }
1855
GetFrameIndexForImage(const PaintImage & paint_image,WhichTree tree) const1856 size_t LayerTreeHostImpl::GetFrameIndexForImage(const PaintImage& paint_image,
1857 WhichTree tree) const {
1858 if (!paint_image.ShouldAnimate())
1859 return PaintImage::kDefaultFrameIndex;
1860
1861 return image_animation_controller_.GetFrameIndexForImage(
1862 paint_image.stable_id(), tree);
1863 }
1864
GetMSAASampleCountForRaster(const scoped_refptr<DisplayItemList> & display_list)1865 int LayerTreeHostImpl::GetMSAASampleCountForRaster(
1866 const scoped_refptr<DisplayItemList>& display_list) {
1867 constexpr int kMinNumberOfSlowPathsForMSAA = 6;
1868 if (display_list->NumSlowPaths() < kMinNumberOfSlowPathsForMSAA)
1869 return 0;
1870
1871 if (!can_use_msaa_)
1872 return 0;
1873
1874 if (display_list->HasNonAAPaint() && !supports_disable_msaa_)
1875 return 0;
1876
1877 return RequestedMSAASampleCount();
1878 }
1879
HasPendingTree()1880 bool LayerTreeHostImpl::HasPendingTree() {
1881 return pending_tree_ != nullptr;
1882 }
1883
NotifyReadyToActivate()1884 void LayerTreeHostImpl::NotifyReadyToActivate() {
1885 // The TileManager may call this method while the pending tree is still being
1886 // painted, as it isn't aware of the ongoing paint. We shouldn't tell the
1887 // scheduler we are ready to activate in that case, as if we do it will
1888 // immediately activate once we call NotifyPaintWorkletStateChange, rather
1889 // than wait for the TileManager to actually raster the content!
1890 if (!pending_tree_fully_painted_)
1891 return;
1892 pending_tree_raster_duration_timer_.reset();
1893 client_->NotifyReadyToActivate();
1894 }
1895
NotifyReadyToDraw()1896 void LayerTreeHostImpl::NotifyReadyToDraw() {
1897 // Tiles that are ready will cause NotifyTileStateChanged() to be called so we
1898 // don't need to schedule a draw here. Just stop WillBeginImplFrame() from
1899 // causing optimistic requests to draw a frame.
1900 is_likely_to_require_a_draw_ = false;
1901
1902 client_->NotifyReadyToDraw();
1903 }
1904
NotifyAllTileTasksCompleted()1905 void LayerTreeHostImpl::NotifyAllTileTasksCompleted() {
1906 // The tile tasks started by the most recent call to PrepareTiles have
1907 // completed. Now is a good time to free resources if necessary.
1908 if (global_tile_state_.hard_memory_limit_in_bytes == 0) {
1909 // Free image decode controller resources before notifying the
1910 // contexts of visibility change. This ensures that the imaged decode
1911 // controller has released all Skia refs at the time Skia's cleanup
1912 // executes (within worker context's cleanup).
1913 if (image_decode_cache_)
1914 image_decode_cache_->SetShouldAggressivelyFreeResources(true);
1915 SetContextVisibility(false);
1916 }
1917 }
1918
NotifyTileStateChanged(const Tile * tile)1919 void LayerTreeHostImpl::NotifyTileStateChanged(const Tile* tile) {
1920 TRACE_EVENT0("cc", "LayerTreeHostImpl::NotifyTileStateChanged");
1921
1922 LayerImpl* layer_impl = nullptr;
1923
1924 // We must have a pending or active tree layer here, since the layer is
1925 // guaranteed to outlive its tiles.
1926 if (tile->tiling()->tree() == WhichTree::PENDING_TREE)
1927 layer_impl = pending_tree_->FindPendingTreeLayerById(tile->layer_id());
1928 else
1929 layer_impl = active_tree_->FindActiveTreeLayerById(tile->layer_id());
1930
1931 layer_impl->NotifyTileStateChanged(tile);
1932
1933 if (!client_->IsInsideDraw() && tile->required_for_draw()) {
1934 // The LayerImpl::NotifyTileStateChanged() should damage the layer, so this
1935 // redraw will make those tiles be displayed.
1936 SetNeedsRedraw();
1937 }
1938 }
1939
SetMemoryPolicy(const ManagedMemoryPolicy & policy)1940 void LayerTreeHostImpl::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
1941 DCHECK(task_runner_provider_->IsImplThread());
1942
1943 SetManagedMemoryPolicy(policy);
1944
1945 // This is short term solution to synchronously drop tile resources when
1946 // using synchronous compositing to avoid memory usage regression.
1947 // TODO(boliu): crbug.com/499004 to track removing this.
1948 if (!policy.bytes_limit_when_visible && resource_pool_ &&
1949 settings_.using_synchronous_renderer_compositor) {
1950 ReleaseTileResources();
1951 CleanUpTileManagerResources();
1952
1953 // Force a call to NotifyAllTileTasks completed - otherwise this logic may
1954 // be skipped if no work was enqueued at the time the tile manager was
1955 // destroyed.
1956 NotifyAllTileTasksCompleted();
1957
1958 CreateTileManagerResources();
1959 RecreateTileResources();
1960 }
1961 }
1962
SetTreeActivationCallback(base::RepeatingClosure callback)1963 void LayerTreeHostImpl::SetTreeActivationCallback(
1964 base::RepeatingClosure callback) {
1965 DCHECK(task_runner_provider_->IsImplThread());
1966 tree_activation_callback_ = std::move(callback);
1967 }
1968
SetManagedMemoryPolicy(const ManagedMemoryPolicy & policy)1969 void LayerTreeHostImpl::SetManagedMemoryPolicy(
1970 const ManagedMemoryPolicy& policy) {
1971 if (cached_managed_memory_policy_ == policy)
1972 return;
1973
1974 ManagedMemoryPolicy old_policy = ActualManagedMemoryPolicy();
1975 cached_managed_memory_policy_ = policy;
1976 ManagedMemoryPolicy actual_policy = ActualManagedMemoryPolicy();
1977
1978 if (old_policy == actual_policy)
1979 return;
1980
1981 UpdateTileManagerMemoryPolicy(actual_policy);
1982
1983 // If there is already enough memory to draw everything imaginable and the
1984 // new memory limit does not change this, then do not re-commit. Don't bother
1985 // skipping commits if this is not visible (commits don't happen when not
1986 // visible, there will almost always be a commit when this becomes visible).
1987 bool needs_commit = true;
1988 if (visible() &&
1989 actual_policy.bytes_limit_when_visible >= max_memory_needed_bytes_ &&
1990 old_policy.bytes_limit_when_visible >= max_memory_needed_bytes_ &&
1991 actual_policy.priority_cutoff_when_visible ==
1992 old_policy.priority_cutoff_when_visible) {
1993 needs_commit = false;
1994 }
1995
1996 if (needs_commit)
1997 client_->SetNeedsCommitOnImplThread();
1998 }
1999
SetExternalTilePriorityConstraints(const gfx::Rect & viewport_rect,const gfx::Transform & transform)2000 void LayerTreeHostImpl::SetExternalTilePriorityConstraints(
2001 const gfx::Rect& viewport_rect,
2002 const gfx::Transform& transform) {
2003 const bool tile_priority_params_changed =
2004 viewport_rect_for_tile_priority_ != viewport_rect;
2005 viewport_rect_for_tile_priority_ = viewport_rect;
2006
2007 if (tile_priority_params_changed) {
2008 active_tree_->set_needs_update_draw_properties();
2009 if (pending_tree_)
2010 pending_tree_->set_needs_update_draw_properties();
2011
2012 // Compositor, not LayerTreeFrameSink, is responsible for setting damage
2013 // and triggering redraw for constraint changes.
2014 SetFullViewportDamage();
2015 SetNeedsRedraw();
2016 }
2017 }
2018
DidReceiveCompositorFrameAck()2019 void LayerTreeHostImpl::DidReceiveCompositorFrameAck() {
2020 client_->DidReceiveCompositorFrameAckOnImplThread();
2021 }
2022
DidPresentCompositorFrame(uint32_t frame_token,const viz::FrameTimingDetails & details)2023 void LayerTreeHostImpl::DidPresentCompositorFrame(
2024 uint32_t frame_token,
2025 const viz::FrameTimingDetails& details) {
2026 frame_trackers_.NotifyFramePresented(frame_token,
2027 details.presentation_feedback);
2028 PresentationTimeCallbackBuffer::PendingCallbacks activated =
2029 presentation_time_callbacks_.PopPendingCallbacks(frame_token);
2030
2031 // The callbacks in |compositor_thread_callbacks| expect to be run on the
2032 // compositor thread so we'll run them now.
2033 for (LayerTreeHost::PresentationTimeCallback& callback :
2034 activated.compositor_thread_callbacks) {
2035 std::move(callback).Run(details.presentation_feedback);
2036 }
2037
2038 // Send all the main-thread callbacks to the client in one batch. The client
2039 // is in charge of posting them to the main thread.
2040 client_->DidPresentCompositorFrameOnImplThread(
2041 frame_token, std::move(activated.main_thread_callbacks), details);
2042
2043 // Send all pending lag events waiting on the frame pointed by |frame_token|.
2044 // It is posted as a task because LayerTreeHostImpl::DidPresentCompositorFrame
2045 // is in the rendering critical path (it is called by AsyncLayerTreeFrameSink
2046 // ::OnBeginFrame).
2047 GetTaskRunner()->PostTask(
2048 FROM_HERE,
2049 base::BindOnce(&LayerTreeHostImpl::LogAverageLagEvents,
2050 weak_factory_.GetWeakPtr(), frame_token, details));
2051 }
2052
LogAverageLagEvents(uint32_t frame_token,const viz::FrameTimingDetails & details)2053 void LayerTreeHostImpl::LogAverageLagEvents(
2054 uint32_t frame_token,
2055 const viz::FrameTimingDetails& details) {
2056 lag_tracking_manager_.DidPresentCompositorFrame(frame_token, details);
2057 }
2058
NotifyThroughputTrackerResults(const CustomTrackerResults & results)2059 void LayerTreeHostImpl::NotifyThroughputTrackerResults(
2060 const CustomTrackerResults& results) {
2061 client_->NotifyThroughputTrackerResults(results);
2062 }
2063
DidNotNeedBeginFrame()2064 void LayerTreeHostImpl::DidNotNeedBeginFrame() {
2065 frame_trackers_.NotifyPauseFrameProduction();
2066 if (lcd_text_metrics_reporter_)
2067 lcd_text_metrics_reporter_->NotifyPauseFrameProduction();
2068 }
2069
ReclaimResources(const std::vector<viz::ReturnedResource> & resources)2070 void LayerTreeHostImpl::ReclaimResources(
2071 const std::vector<viz::ReturnedResource>& resources) {
2072 resource_provider_.ReceiveReturnsFromParent(resources);
2073
2074 // In OOM, we now might be able to release more resources that were held
2075 // because they were exported.
2076 if (resource_pool_) {
2077 if (resource_pool_->memory_usage_bytes()) {
2078 const size_t kMegabyte = 1024 * 1024;
2079 // This is a good time to log memory usage. A chunk of work has just
2080 // completed but none of the memory used for that work has likely been
2081 // freed.
2082 std::string client_suffix;
2083 if (settings_.commit_to_active_tree) {
2084 client_suffix = "Browser";
2085 } else if (settings_.is_layer_tree_for_subframe) {
2086 client_suffix = "OOPIF";
2087 } else {
2088 client_suffix = "Renderer";
2089 }
2090 base::UmaHistogramMemoryMB(
2091 "Compositing.ResourcePoolMemoryUsage." + client_suffix,
2092 static_cast<int>(resource_pool_->memory_usage_bytes() / kMegabyte));
2093 }
2094 resource_pool_->ReduceResourceUsage();
2095 }
2096
2097 // If we're not visible, we likely released resources, so we want to
2098 // aggressively flush here to make sure those DeleteTextures make it to the
2099 // GPU process to free up the memory.
2100 if (!visible_ && layer_tree_frame_sink_->context_provider()) {
2101 auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL();
2102 gl->ShallowFlushCHROMIUM();
2103 }
2104 }
2105
OnDraw(const gfx::Transform & transform,const gfx::Rect & viewport,bool resourceless_software_draw,bool skip_draw)2106 void LayerTreeHostImpl::OnDraw(const gfx::Transform& transform,
2107 const gfx::Rect& viewport,
2108 bool resourceless_software_draw,
2109 bool skip_draw) {
2110 DCHECK(!resourceless_software_draw_);
2111 // This function is only ever called by Android WebView, in which case we
2112 // expect the device viewport to be at the origin. We never expect an
2113 // external viewport to be set otherwise.
2114 DCHECK(active_tree_->internal_device_viewport().origin().IsOrigin());
2115
2116 #if DCHECK_IS_ON()
2117 base::AutoReset<bool> reset_sync_draw(&doing_sync_draw_, true);
2118 #endif
2119
2120 if (skip_draw) {
2121 client_->OnDrawForLayerTreeFrameSink(resourceless_software_draw_, true);
2122 return;
2123 }
2124
2125 const bool transform_changed = external_transform_ != transform;
2126 const bool viewport_changed = external_viewport_ != viewport;
2127
2128 external_transform_ = transform;
2129 external_viewport_ = viewport;
2130
2131 {
2132 base::AutoReset<bool> resourceless_software_draw_reset(
2133 &resourceless_software_draw_, resourceless_software_draw);
2134
2135 // For resourceless software draw, always set full damage to ensure they
2136 // always swap. Otherwise, need to set redraw for any changes to draw
2137 // parameters.
2138 if (transform_changed || viewport_changed || resourceless_software_draw_) {
2139 SetFullViewportDamage();
2140 SetNeedsRedraw();
2141 active_tree_->set_needs_update_draw_properties();
2142 }
2143
2144 if (resourceless_software_draw)
2145 client_->OnCanDrawStateChanged(CanDraw());
2146
2147 client_->OnDrawForLayerTreeFrameSink(resourceless_software_draw_,
2148 skip_draw);
2149 }
2150
2151 if (resourceless_software_draw) {
2152 active_tree_->set_needs_update_draw_properties();
2153 client_->OnCanDrawStateChanged(CanDraw());
2154 // This draw may have reset all damage, which would lead to subsequent
2155 // incorrect hardware draw, so explicitly set damage for next hardware
2156 // draw as well.
2157 SetFullViewportDamage();
2158 }
2159 }
2160
OnCanDrawStateChangedForTree()2161 void LayerTreeHostImpl::OnCanDrawStateChangedForTree() {
2162 client_->OnCanDrawStateChanged(CanDraw());
2163 }
2164
MakeCompositorFrameMetadata()2165 viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() {
2166 viz::CompositorFrameMetadata metadata;
2167 metadata.frame_token = ++next_frame_token_;
2168 metadata.device_scale_factor = active_tree_->painted_device_scale_factor() *
2169 active_tree_->device_scale_factor();
2170
2171 metadata.page_scale_factor = active_tree_->current_page_scale_factor();
2172 metadata.scrollable_viewport_size = active_tree_->ScrollableViewportSize();
2173 metadata.root_background_color = active_tree_->background_color();
2174
2175 if (active_tree_->has_presentation_callbacks()) {
2176 presentation_time_callbacks_.RegisterMainThreadPresentationCallbacks(
2177 metadata.frame_token, active_tree_->TakePresentationCallbacks());
2178 presentation_time_callbacks_.RegisterFrameTime(
2179 metadata.frame_token, CurrentBeginFrameArgs().frame_time);
2180 }
2181
2182 if (GetDrawMode() == DRAW_MODE_RESOURCELESS_SOFTWARE) {
2183 // TODO(savella) : Change to check for ActivelyScrollingType::kNone
2184 const bool actively_scrolling =
2185 GetActivelyScrollingType() == ActivelyScrollingType::kPrecise;
2186 metadata.is_resourceless_software_draw_with_scroll_or_animation =
2187 actively_scrolling || mutator_host_->NeedsTickAnimations();
2188 }
2189
2190 const base::flat_set<viz::SurfaceRange>& referenced_surfaces =
2191 active_tree_->SurfaceRanges();
2192 for (auto& surface_range : referenced_surfaces)
2193 metadata.referenced_surfaces.push_back(surface_range);
2194
2195 if (last_draw_referenced_surfaces_ != referenced_surfaces)
2196 last_draw_referenced_surfaces_ = referenced_surfaces;
2197
2198 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
2199
2200 if (browser_controls_offset_manager_->TopControlsHeight() > 0) {
2201 metadata.top_controls_visible_height.emplace(
2202 browser_controls_offset_manager_->TopControlsHeight() *
2203 browser_controls_offset_manager_->TopControlsShownRatio());
2204 }
2205
2206 if (InnerViewportScrollNode()) {
2207 // TODO(miletus) : Change the metadata to hold ScrollOffset.
2208 metadata.root_scroll_offset =
2209 gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset());
2210 }
2211
2212 metadata.display_transform_hint = active_tree_->display_transform_hint();
2213
2214 if (std::unique_ptr<viz::DelegatedInkMetadata> delegated_ink_metadata =
2215 active_tree_->take_delegated_ink_metadata()) {
2216 delegated_ink_metadata->set_frame_time(CurrentBeginFrameArgs().frame_time);
2217 TRACE_EVENT_INSTANT1(
2218 "cc", "Delegated Ink Metadata set on compositor frame metadata",
2219 TRACE_EVENT_SCOPE_THREAD, "ink metadata",
2220 delegated_ink_metadata->ToString());
2221 metadata.delegated_ink_metadata = std::move(delegated_ink_metadata);
2222 }
2223
2224 return metadata;
2225 }
2226
MakeRenderFrameMetadata(FrameData * frame)2227 RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata(
2228 FrameData* frame) {
2229 RenderFrameMetadata metadata;
2230 metadata.root_scroll_offset =
2231 gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset());
2232
2233 metadata.root_background_color = active_tree_->background_color();
2234 metadata.is_scroll_offset_at_top = active_tree_->TotalScrollOffset().y() == 0;
2235 metadata.device_scale_factor = active_tree_->painted_device_scale_factor() *
2236 active_tree_->device_scale_factor();
2237 active_tree_->GetViewportSelection(&metadata.selection);
2238 metadata.is_mobile_optimized = IsMobileOptimized(active_tree_.get());
2239 metadata.viewport_size_in_pixels = active_tree_->GetDeviceViewport().size();
2240
2241 metadata.page_scale_factor = active_tree_->current_page_scale_factor();
2242 metadata.external_page_scale_factor =
2243 active_tree_->external_page_scale_factor();
2244
2245 metadata.top_controls_height =
2246 browser_controls_offset_manager_->TopControlsHeight();
2247 metadata.top_controls_shown_ratio =
2248 browser_controls_offset_manager_->TopControlsShownRatio();
2249 #if defined(OS_ANDROID)
2250 metadata.bottom_controls_height =
2251 browser_controls_offset_manager_->BottomControlsHeight();
2252 metadata.bottom_controls_shown_ratio =
2253 browser_controls_offset_manager_->BottomControlsShownRatio();
2254 metadata.top_controls_min_height_offset =
2255 browser_controls_offset_manager_->TopControlsMinHeightOffset();
2256 metadata.bottom_controls_min_height_offset =
2257 browser_controls_offset_manager_->BottomControlsMinHeightOffset();
2258 metadata.scrollable_viewport_size = active_tree_->ScrollableViewportSize();
2259 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
2260 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor();
2261 metadata.root_layer_size = active_tree_->ScrollableSize();
2262 if (InnerViewportScrollNode()) {
2263 DCHECK(OuterViewportScrollNode());
2264 metadata.root_overflow_y_hidden =
2265 !OuterViewportScrollNode()->user_scrollable_vertical ||
2266 !InnerViewportScrollNode()->user_scrollable_vertical;
2267 }
2268 metadata.has_transparent_background =
2269 frame->render_passes.back()->has_transparent_background;
2270 #endif
2271
2272 if (last_draw_render_frame_metadata_) {
2273 const float last_root_scroll_offset_y =
2274 last_draw_render_frame_metadata_->root_scroll_offset
2275 .value_or(gfx::Vector2dF())
2276 .y();
2277
2278 const float new_root_scroll_offset_y =
2279 metadata.root_scroll_offset.value().y();
2280
2281 if (!MathUtil::IsWithinEpsilon(last_root_scroll_offset_y,
2282 new_root_scroll_offset_y)) {
2283 viz::VerticalScrollDirection new_vertical_scroll_direction =
2284 (last_root_scroll_offset_y < new_root_scroll_offset_y)
2285 ? viz::VerticalScrollDirection::kDown
2286 : viz::VerticalScrollDirection::kUp;
2287
2288 // Changes in vertical scroll direction happen instantaneously. This being
2289 // the case, a new vertical scroll direction should only be present in the
2290 // singular metadata for the render frame in which the direction change
2291 // occurred. If the vertical scroll direction detected here matches that
2292 // which we've previously cached, then this frame is not the instant in
2293 // which the direction change occurred and is therefore not propagated.
2294 if (last_vertical_scroll_direction_ != new_vertical_scroll_direction)
2295 metadata.new_vertical_scroll_direction = new_vertical_scroll_direction;
2296 }
2297 }
2298
2299 bool allocate_new_local_surface_id =
2300 #if !defined(OS_ANDROID)
2301 last_draw_render_frame_metadata_ &&
2302 (last_draw_render_frame_metadata_->top_controls_height !=
2303 metadata.top_controls_height ||
2304 last_draw_render_frame_metadata_->top_controls_shown_ratio !=
2305 metadata.top_controls_shown_ratio);
2306 #else
2307 last_draw_render_frame_metadata_ &&
2308 (last_draw_render_frame_metadata_->top_controls_height !=
2309 metadata.top_controls_height ||
2310 last_draw_render_frame_metadata_->top_controls_shown_ratio !=
2311 metadata.top_controls_shown_ratio ||
2312 last_draw_render_frame_metadata_->bottom_controls_height !=
2313 metadata.bottom_controls_height ||
2314 last_draw_render_frame_metadata_->bottom_controls_shown_ratio !=
2315 metadata.bottom_controls_shown_ratio ||
2316 last_draw_render_frame_metadata_->selection != metadata.selection ||
2317 last_draw_render_frame_metadata_->has_transparent_background !=
2318 metadata.has_transparent_background);
2319 #endif
2320
2321 if (child_local_surface_id_allocator_.GetCurrentLocalSurfaceId().is_valid()) {
2322 if (allocate_new_local_surface_id)
2323 AllocateLocalSurfaceId();
2324 metadata.local_surface_id =
2325 child_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
2326 }
2327
2328 return metadata;
2329 }
2330
DrawLayers(FrameData * frame)2331 bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
2332 DCHECK(CanDraw());
2333 DCHECK_EQ(frame->has_no_damage, frame->render_passes.empty());
2334 ResetRequiresHighResToDraw();
2335
2336 if (frame->has_no_damage) {
2337 DCHECK(!resourceless_software_draw_);
2338
2339 frame_trackers_.NotifyImplFrameCausedNoDamage(frame->begin_frame_ack);
2340 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoDamage", TRACE_EVENT_SCOPE_THREAD);
2341 active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS);
2342 active_tree()->ResetAllChangeTracking();
2343 return false;
2344 }
2345
2346 layer_tree_frame_sink_->set_source_frame_number(
2347 active_tree_->source_frame_number());
2348
2349 auto compositor_frame = GenerateCompositorFrame(frame);
2350 const auto frame_token = compositor_frame.metadata.frame_token;
2351 frame->frame_token = frame_token;
2352 const viz::BeginFrameId begin_frame_ack_frame_id =
2353 compositor_frame.metadata.begin_frame_ack.frame_id;
2354
2355 // Collect |latency_info| information for tracking
2356 lag_tracking_manager_.CollectScrollEventsFromFrame(
2357 frame_token, compositor_frame.metadata.latency_info);
2358 layer_tree_frame_sink_->SubmitCompositorFrame(
2359 std::move(compositor_frame),
2360 /*hit_test_data_changed=*/false, debug_state_.show_hit_test_borders);
2361
2362 #if DCHECK_IS_ON()
2363 if (!doing_sync_draw_) {
2364 // The throughput computation (in |FrameSequenceTracker|) depends on the
2365 // compositor-frame submission to happen while a BeginFrameArgs is 'active'
2366 // (i.e. between calls to WillBeginImplFrame() and DidFinishImplFrame()).
2367 // Verify that this is the case.
2368 // No begin-frame is available when doing sync draws, so avoid doing this
2369 // check in that case.
2370 const auto& bfargs = current_begin_frame_tracker_.Current();
2371 DCHECK_EQ(bfargs.frame_id, begin_frame_ack_frame_id);
2372 }
2373 #endif
2374
2375 // In some cases (e.g. for android-webviews), the frame-submission happens
2376 // outside of begin-impl frame pipeline. Avoid notifying the trackers in such
2377 // cases.
2378 if (impl_thread_phase_ == ImplThreadPhase::INSIDE_IMPL_FRAME) {
2379 frame_trackers_.NotifySubmitFrame(frame_token, frame->has_missing_content,
2380 frame->begin_frame_ack,
2381 frame->origin_begin_main_frame_args);
2382 }
2383
2384 if (!mutator_host_->NextFrameHasPendingRAF())
2385 frame_trackers_.StopSequence(FrameSequenceTrackerType::kRAF);
2386 if (!mutator_host_->HasCanvasInvalidation())
2387 frame_trackers_.StopSequence(FrameSequenceTrackerType::kCanvasAnimation);
2388 if (!mutator_host_->HasJSAnimation())
2389 frame_trackers_.StopSequence(FrameSequenceTrackerType::kJSAnimation);
2390
2391 if (mutator_host_->MainThreadAnimationsCount() == 0) {
2392 frame_trackers_.StopSequence(
2393 FrameSequenceTrackerType::kMainThreadAnimation);
2394 }
2395
2396 if (lcd_text_metrics_reporter_) {
2397 lcd_text_metrics_reporter_->NotifySubmitFrame(
2398 frame->origin_begin_main_frame_args);
2399 }
2400
2401 // Clears the list of swap promises after calling DidSwap on each of them to
2402 // signal that the swap is over.
2403 active_tree()->ClearSwapPromises();
2404
2405 // The next frame should start by assuming nothing has changed, and changes
2406 // are noted as they occur.
2407 // TODO(boliu): If we did a temporary software renderer frame, propogate the
2408 // damage forward to the next frame.
2409 for (size_t i = 0; i < frame->render_surface_list->size(); i++) {
2410 auto* surface = (*frame->render_surface_list)[i];
2411 surface->damage_tracker()->DidDrawDamagedArea();
2412 }
2413 active_tree_->ResetAllChangeTracking();
2414
2415 active_tree_->set_has_ever_been_drawn(true);
2416 devtools_instrumentation::DidDrawFrame(id_);
2417 benchmark_instrumentation::IssueImplThreadRenderingStatsEvent(
2418 rendering_stats_instrumentation_->TakeImplThreadRenderingStats());
2419 return true;
2420 }
2421
GenerateCompositorFrame(FrameData * frame)2422 viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame(
2423 FrameData* frame) {
2424 TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline",
2425 TRACE_ID_GLOBAL(CurrentBeginFrameArgs().trace_id),
2426 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
2427 "step", "GenerateCompositorFrame");
2428 rendering_stats_instrumentation_->IncrementFrameCount(1);
2429
2430 memory_history_->SaveEntry(tile_manager_.memory_stats_from_last_assign());
2431
2432 if (debug_state_.ShowHudRects()) {
2433 debug_rect_history_->SaveDebugRectsForCurrentFrame(
2434 active_tree(), active_tree_->hud_layer(), *frame->render_surface_list,
2435 debug_state_);
2436 }
2437
2438 TRACE_EVENT_INSTANT2("cc", "Scroll Delta This Frame",
2439 TRACE_EVENT_SCOPE_THREAD, "x",
2440 scroll_accumulated_this_frame_.x(), "y",
2441 scroll_accumulated_this_frame_.y());
2442 scroll_accumulated_this_frame_ = gfx::Vector2dF();
2443
2444 bool is_new_trace;
2445 TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
2446 if (is_new_trace) {
2447 if (pending_tree_) {
2448 for (auto* layer : *pending_tree_)
2449 layer->DidBeginTracing();
2450 }
2451 for (auto* layer : *active_tree_)
2452 layer->DidBeginTracing();
2453 }
2454
2455 {
2456 TRACE_EVENT0("cc", "DrawLayers.FrameViewerTracing");
2457 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
2458 frame_viewer_instrumentation::CategoryLayerTree(),
2459 "cc::LayerTreeHostImpl", id_, AsValueWithFrame(frame));
2460 }
2461
2462 const DrawMode draw_mode = GetDrawMode();
2463
2464 // Because the contents of the HUD depend on everything else in the frame, the
2465 // contents of its texture are updated as the last thing before the frame is
2466 // drawn.
2467 if (active_tree_->hud_layer()) {
2468 TRACE_EVENT0("cc", "DrawLayers.UpdateHudTexture");
2469 active_tree_->hud_layer()->UpdateHudTexture(
2470 draw_mode, layer_tree_frame_sink_, &resource_provider_,
2471 // The hud uses Gpu rasterization if the device is capable, not related
2472 // to the content of the web page.
2473 gpu_rasterization_status_ != GpuRasterizationStatus::OFF_DEVICE,
2474 frame->render_passes);
2475 }
2476
2477 viz::CompositorFrameMetadata metadata = MakeCompositorFrameMetadata();
2478 PopulateMetadataContentColorUsage(frame, &metadata);
2479 metadata.may_contain_video = frame->may_contain_video;
2480 metadata.deadline = viz::FrameDeadline(
2481 CurrentBeginFrameArgs().frame_time,
2482 frame->deadline_in_frames.value_or(0u), CurrentBeginFrameArgs().interval,
2483 frame->use_default_lower_bound_deadline);
2484
2485 frame_rate_estimator_.WillDraw(CurrentBeginFrameArgs().frame_time);
2486
2487 if (settings_.force_preferred_interval_for_video ||
2488 enable_frame_rate_throttling_) {
2489 metadata.preferred_frame_interval = viz::BeginFrameArgs::MaxInterval();
2490 } else {
2491 metadata.preferred_frame_interval =
2492 frame_rate_estimator_.GetPreferredInterval();
2493 }
2494
2495 metadata.activation_dependencies = std::move(frame->activation_dependencies);
2496 active_tree()->FinishSwapPromises(&metadata);
2497 // The swap-promises should not change the frame-token.
2498 DCHECK_EQ(metadata.frame_token, *next_frame_token_);
2499
2500 if (render_frame_metadata_observer_) {
2501 last_draw_render_frame_metadata_ = MakeRenderFrameMetadata(frame);
2502 last_draw_render_frame_metadata_->has_delegated_ink_metadata =
2503 metadata.delegated_ink_metadata.get();
2504
2505 // We cache the value of any new vertical scroll direction so that we can
2506 // accurately determine when the next change in vertical scroll direction
2507 // occurs. Note that |kNull| is only used to indicate the absence of a
2508 // vertical scroll direction and should therefore be ignored.
2509 if (last_draw_render_frame_metadata_->new_vertical_scroll_direction !=
2510 viz::VerticalScrollDirection::kNull) {
2511 last_vertical_scroll_direction_ =
2512 last_draw_render_frame_metadata_->new_vertical_scroll_direction;
2513 }
2514
2515 render_frame_metadata_observer_->OnRenderFrameSubmission(
2516 *last_draw_render_frame_metadata_, &metadata,
2517 active_tree()->TakeForceSendMetadataRequest());
2518 }
2519
2520 if (!CommitToActiveTree() && !metadata.latency_info.empty()) {
2521 base::TimeTicks draw_time = base::TimeTicks::Now();
2522
2523 ukm::SourceId exemplar = metadata.latency_info.front().ukm_source_id();
2524 ApplyFirstScrollTracking(&metadata.latency_info.front(),
2525 metadata.frame_token, this);
2526 bool all_valid = true;
2527 bool all_unique = true;
2528 for (auto& latency : metadata.latency_info) {
2529 latency.AddLatencyNumberWithTimestamp(
2530 ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, draw_time);
2531 all_valid &= latency.ukm_source_id() != ukm::kInvalidSourceId;
2532 all_unique &= latency.ukm_source_id() == exemplar;
2533 }
2534
2535 RecordSourceIdConsistency(all_valid, all_unique);
2536 }
2537 ui::LatencyInfo::TraceIntermediateFlowEvents(
2538 metadata.latency_info,
2539 perfetto::protos::pbzero::ChromeLatencyInfo::STEP_SWAP_BUFFERS);
2540
2541 // Collect all resource ids in the render passes into a single array.
2542 std::vector<viz::ResourceId> resources;
2543 for (const auto& render_pass : frame->render_passes) {
2544 for (auto* quad : render_pass->quad_list) {
2545 for (viz::ResourceId resource_id : quad->resources)
2546 resources.push_back(resource_id);
2547 }
2548 }
2549
2550 DCHECK(frame->begin_frame_ack.frame_id.IsSequenceValid());
2551 metadata.begin_frame_ack = frame->begin_frame_ack;
2552
2553 viz::CompositorFrame compositor_frame;
2554 compositor_frame.metadata = std::move(metadata);
2555 resource_provider_.PrepareSendToParent(
2556 resources, &compositor_frame.resource_list,
2557 layer_tree_frame_sink_->context_provider());
2558 compositor_frame.render_pass_list = std::move(frame->render_passes);
2559
2560 // We should always have a valid LocalSurfaceId in LayerTreeImpl unless we
2561 // don't have a scheduler because without a scheduler commits are not deferred
2562 // and LayerTrees without valid LocalSurfaceId might slip through, but
2563 // single-thread-without-scheduler mode is only used in tests so it doesn't
2564 // matter.
2565 CHECK(!settings_.single_thread_proxy_scheduler ||
2566 active_tree()->local_surface_id_from_parent().is_valid());
2567 layer_tree_frame_sink_->SetLocalSurfaceId(
2568 child_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
2569
2570 last_draw_local_surface_id_ =
2571 child_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
2572 return compositor_frame;
2573 }
2574
DidDrawAllLayers(const FrameData & frame)2575 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) {
2576 // TODO(lethalantidote): LayerImpl::DidDraw can be removed when
2577 // VideoLayerImpl is removed.
2578 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i)
2579 frame.will_draw_layers[i]->DidDraw(&resource_provider_);
2580
2581 for (auto* it : video_frame_controllers_)
2582 it->DidDrawFrame();
2583 }
2584
RequestedMSAASampleCount() const2585 int LayerTreeHostImpl::RequestedMSAASampleCount() const {
2586 if (settings_.gpu_rasterization_msaa_sample_count == -1) {
2587 // On "low-end" devices use 4 samples per pixel to save memory.
2588 if (base::SysInfo::IsLowEndDevice())
2589 return 4;
2590
2591 // Use the most up-to-date version of device_scale_factor that we have.
2592 float device_scale_factor = pending_tree_
2593 ? pending_tree_->device_scale_factor()
2594 : active_tree_->device_scale_factor();
2595 return device_scale_factor >= 2.0f ? 4 : 8;
2596 }
2597
2598 return settings_.gpu_rasterization_msaa_sample_count;
2599 }
2600
GetGpuRasterizationCapabilities(bool * gpu_rasterization_enabled,bool * gpu_rasterization_supported,int * max_msaa_samples,bool * supports_disable_msaa)2601 void LayerTreeHostImpl::GetGpuRasterizationCapabilities(
2602 bool* gpu_rasterization_enabled,
2603 bool* gpu_rasterization_supported,
2604 int* max_msaa_samples,
2605 bool* supports_disable_msaa) {
2606 *gpu_rasterization_enabled = false;
2607 *gpu_rasterization_supported = false;
2608 *max_msaa_samples = 0;
2609 *supports_disable_msaa = false;
2610
2611 if (settings_.gpu_rasterization_disabled)
2612 return;
2613
2614 if (!(layer_tree_frame_sink_ && layer_tree_frame_sink_->context_provider() &&
2615 layer_tree_frame_sink_->worker_context_provider())) {
2616 return;
2617 }
2618
2619 viz::RasterContextProvider* context_provider =
2620 layer_tree_frame_sink_->worker_context_provider();
2621 viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
2622 context_provider);
2623
2624 const auto& caps = context_provider->ContextCapabilities();
2625 *gpu_rasterization_enabled = caps.gpu_rasterization;
2626 if (!*gpu_rasterization_enabled)
2627 return;
2628
2629 bool use_msaa = !caps.msaa_is_slow && !caps.avoid_stencil_buffers;
2630
2631 if (can_use_oop_rasterization_) {
2632 *gpu_rasterization_supported = true;
2633 *supports_disable_msaa = caps.multisample_compatibility;
2634 // For OOP raster, the gpu service side will disable msaa if the
2635 // requested samples are not enough. GPU raster does this same
2636 // logic below client side.
2637 if (use_msaa)
2638 *max_msaa_samples = RequestedMSAASampleCount();
2639 return;
2640 }
2641
2642 if (!context_provider->ContextSupport()->HasGrContextSupport())
2643 return;
2644
2645 // Do not check GrContext above. It is lazy-created, and we only want to
2646 // create it if it might be used.
2647 GrDirectContext* gr_context = context_provider->GrContext();
2648 *gpu_rasterization_supported = !!gr_context;
2649 if (!*gpu_rasterization_supported)
2650 return;
2651
2652 *supports_disable_msaa = caps.multisample_compatibility;
2653 if (use_msaa) {
2654 // Skia may block MSAA independently of Chrome. Query Skia for its max
2655 // supported sample count. Assume gpu compositing + gpu raster for this, as
2656 // that is what we are hoping to use.
2657 viz::ResourceFormat tile_format = TileRasterBufferFormat(
2658 settings_, layer_tree_frame_sink_->context_provider(),
2659 /*use_gpu_rasterization=*/true);
2660 SkColorType color_type = ResourceFormatToClosestSkColorType(
2661 /*gpu_compositing=*/true, tile_format);
2662 *max_msaa_samples =
2663 gr_context->maxSurfaceSampleCountForColorType(color_type);
2664 }
2665 }
2666
UpdateGpuRasterizationStatus()2667 bool LayerTreeHostImpl::UpdateGpuRasterizationStatus() {
2668 if (!need_update_gpu_rasterization_status_)
2669 return false;
2670 need_update_gpu_rasterization_status_ = false;
2671
2672 // TODO(danakj): Can we avoid having this run when there's no
2673 // LayerTreeFrameSink?
2674 // For now just early out and leave things unchanged, we'll come back here
2675 // when we get a LayerTreeFrameSink.
2676 if (!layer_tree_frame_sink_)
2677 return false;
2678
2679 int requested_msaa_samples = RequestedMSAASampleCount();
2680 int max_msaa_samples = 0;
2681 bool gpu_rasterization_enabled = false;
2682 bool gpu_rasterization_supported = false;
2683 bool supports_disable_msaa = false;
2684 GetGpuRasterizationCapabilities(&gpu_rasterization_enabled,
2685 &gpu_rasterization_supported,
2686 &max_msaa_samples, &supports_disable_msaa);
2687
2688 bool use_gpu = false;
2689 bool can_use_msaa =
2690 requested_msaa_samples > 0 && max_msaa_samples >= requested_msaa_samples;
2691
2692 if (!gpu_rasterization_enabled) {
2693 if (gpu_rasterization_supported)
2694 gpu_rasterization_status_ = GpuRasterizationStatus::OFF_FORCED;
2695 else
2696 gpu_rasterization_status_ = GpuRasterizationStatus::OFF_DEVICE;
2697 } else {
2698 use_gpu = true;
2699 gpu_rasterization_status_ = GpuRasterizationStatus::ON;
2700 }
2701
2702 if (use_gpu && !use_gpu_rasterization_) {
2703 if (!gpu_rasterization_supported) {
2704 // If GPU rasterization is unusable, e.g. if GlContext could not
2705 // be created due to losing the GL context, force use of software
2706 // raster.
2707 use_gpu = false;
2708 can_use_msaa_ = false;
2709 supports_disable_msaa_ = false;
2710 gpu_rasterization_status_ = GpuRasterizationStatus::OFF_DEVICE;
2711 }
2712 }
2713
2714 // Changes in MSAA settings require that we re-raster resources for the
2715 // settings to take effect. But we don't need to trigger any raster
2716 // invalidation in this case since these settings change only if the context
2717 // changed. In this case we already re-allocate and re-raster all resources.
2718 if (use_gpu == use_gpu_rasterization_ && can_use_msaa == can_use_msaa_ &&
2719 supports_disable_msaa == supports_disable_msaa_) {
2720 return false;
2721 }
2722
2723 use_gpu_rasterization_ = use_gpu;
2724 can_use_msaa_ = can_use_msaa;
2725 supports_disable_msaa_ = supports_disable_msaa;
2726 return true;
2727 }
2728
UpdateTreeResourcesForGpuRasterizationIfNeeded()2729 void LayerTreeHostImpl::UpdateTreeResourcesForGpuRasterizationIfNeeded() {
2730 if (!UpdateGpuRasterizationStatus())
2731 return;
2732
2733 // Clean up and replace existing tile manager with another one that uses
2734 // appropriate rasterizer. Only do this however if we already have a
2735 // resource pool, since otherwise we might not be able to create a new
2736 // one.
2737 ReleaseTileResources();
2738 if (resource_pool_) {
2739 CleanUpTileManagerResources();
2740 CreateTileManagerResources();
2741 }
2742 RecreateTileResources();
2743
2744 // We have released tilings for both active and pending tree.
2745 // We would not have any content to draw until the pending tree is activated.
2746 // Prevent the active tree from drawing until activation.
2747 // TODO(crbug.com/469175): Replace with RequiresHighResToDraw.
2748 SetRequiresHighResToDraw();
2749 }
2750
RegisterMainThreadPresentationTimeCallback(uint32_t frame_token,LayerTreeHost::PresentationTimeCallback callback)2751 void LayerTreeHostImpl::RegisterMainThreadPresentationTimeCallback(
2752 uint32_t frame_token,
2753 LayerTreeHost::PresentationTimeCallback callback) {
2754 std::vector<LayerTreeHost::PresentationTimeCallback> as_vector;
2755 as_vector.emplace_back(std::move(callback));
2756 presentation_time_callbacks_.RegisterMainThreadPresentationCallbacks(
2757 frame_token, std::move(as_vector));
2758 }
2759
RegisterCompositorPresentationTimeCallback(uint32_t frame_token,LayerTreeHost::PresentationTimeCallback callback)2760 void LayerTreeHostImpl::RegisterCompositorPresentationTimeCallback(
2761 uint32_t frame_token,
2762 LayerTreeHost::PresentationTimeCallback callback) {
2763 std::vector<LayerTreeHost::PresentationTimeCallback> as_vector;
2764 as_vector.emplace_back(std::move(callback));
2765 presentation_time_callbacks_.RegisterCompositorPresentationCallbacks(
2766 frame_token, std::move(as_vector));
2767 }
2768
WillBeginImplFrame(const viz::BeginFrameArgs & args)2769 bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
2770 impl_thread_phase_ = ImplThreadPhase::INSIDE_IMPL_FRAME;
2771 current_begin_frame_tracker_.Start(args);
2772 frame_trackers_.NotifyBeginImplFrame(args);
2773 total_frame_counter_.OnBeginFrame(args);
2774
2775 if (is_likely_to_require_a_draw_) {
2776 // Optimistically schedule a draw. This will let us expect the tile manager
2777 // to complete its work so that we can draw new tiles within the impl frame
2778 // we are beginning now.
2779 SetNeedsRedraw();
2780 }
2781
2782 if (input_delegate_)
2783 input_delegate_->WillBeginImplFrame(args);
2784
2785 Animate();
2786
2787 image_animation_controller_.WillBeginImplFrame(args);
2788
2789 for (auto* it : video_frame_controllers_)
2790 it->OnBeginFrame(args);
2791
2792 bool recent_frame_had_no_damage =
2793 consecutive_frame_with_damage_count_ < settings_.damaged_frame_limit;
2794 // Check damage early if the setting is enabled and a recent frame had no
2795 // damage. HasDamage() expects CanDraw to be true. If we can't check damage,
2796 // return true to indicate that there might be damage in this frame.
2797 if (settings_.enable_early_damage_check && recent_frame_had_no_damage &&
2798 CanDraw()) {
2799 bool ok = active_tree()->UpdateDrawProperties();
2800 DCHECK(ok);
2801 DamageTracker::UpdateDamageTracking(active_tree_.get());
2802 bool has_damage = HasDamage();
2803 // Animations are updated after we attempt to draw. If the frame is aborted,
2804 // update animations now.
2805 if (!has_damage)
2806 UpdateAnimationState(true);
2807 return has_damage;
2808 }
2809 // Assume there is damage if we cannot check for damage.
2810 return true;
2811 }
2812
DidFinishImplFrame(const viz::BeginFrameArgs & args)2813 void LayerTreeHostImpl::DidFinishImplFrame(const viz::BeginFrameArgs& args) {
2814 frame_trackers_.NotifyFrameEnd(current_begin_frame_tracker_.Current(), args);
2815 impl_thread_phase_ = ImplThreadPhase::IDLE;
2816 current_begin_frame_tracker_.Finish();
2817 }
2818
DidNotProduceFrame(const viz::BeginFrameAck & ack,FrameSkippedReason reason)2819 void LayerTreeHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack,
2820 FrameSkippedReason reason) {
2821 if (layer_tree_frame_sink_)
2822 layer_tree_frame_sink_->DidNotProduceFrame(ack);
2823
2824 // If a frame was not submitted because there was no damage, or the scheduler
2825 // hit the frame-deadline while waiting for the main-thread, notify the
2826 // trackers.
2827 if (reason != FrameSkippedReason::kRecoverLatency &&
2828 impl_thread_phase_ == ImplThreadPhase::INSIDE_IMPL_FRAME) {
2829 // It is possible that |ack| is for a 'future frame', i.e. for the next
2830 // frame from the one currently being handled by the compositor (represented
2831 // by the BeginFrameArgs instance in |current_begin_frame_tracker_|). This
2832 // can happen, for example, when a frame is skipped early for
2833 // latency-recovery, while the previous frame is still being processed.
2834 // Notify the trackers only when this is *not* the case (since the trackers
2835 // are not notified about the start of the future frame either).
2836 const auto& args = current_begin_frame_tracker_.Current();
2837 if (args.frame_id == ack.frame_id) {
2838 frame_trackers_.NotifyImplFrameCausedNoDamage(ack);
2839 }
2840 }
2841 }
2842
SynchronouslyInitializeAllTiles()2843 void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
2844 // Only valid for the single-threaded non-scheduled/synchronous case
2845 // using the zero copy raster worker pool.
2846 single_thread_synchronous_task_graph_runner_->RunUntilIdle();
2847 }
2848
GetFlagsForSurfaceLayer(const SurfaceLayerImpl * layer)2849 static uint32_t GetFlagsForSurfaceLayer(const SurfaceLayerImpl* layer) {
2850 uint32_t flags = viz::HitTestRegionFlags::kHitTestMouse |
2851 viz::HitTestRegionFlags::kHitTestTouch;
2852 if (layer->range().IsValid()) {
2853 flags |= viz::HitTestRegionFlags::kHitTestChildSurface;
2854 } else {
2855 flags |= viz::HitTestRegionFlags::kHitTestMine;
2856 }
2857 return flags;
2858 }
2859
PopulateHitTestRegion(viz::HitTestRegion * hit_test_region,const LayerImpl * layer,uint32_t flags,uint32_t async_hit_test_reasons,const gfx::Rect & rect,const viz::SurfaceId & surface_id,float device_scale_factor)2860 static void PopulateHitTestRegion(viz::HitTestRegion* hit_test_region,
2861 const LayerImpl* layer,
2862 uint32_t flags,
2863 uint32_t async_hit_test_reasons,
2864 const gfx::Rect& rect,
2865 const viz::SurfaceId& surface_id,
2866 float device_scale_factor) {
2867 hit_test_region->frame_sink_id = surface_id.frame_sink_id();
2868 hit_test_region->flags = flags;
2869 hit_test_region->async_hit_test_reasons = async_hit_test_reasons;
2870 DCHECK_EQ(!!async_hit_test_reasons,
2871 !!(flags & viz::HitTestRegionFlags::kHitTestAsk));
2872
2873 hit_test_region->rect = rect;
2874 // The transform of hit test region maps a point from parent hit test region
2875 // to the local space. This is the inverse of screen space transform. Because
2876 // hit test query wants the point in target to be in Pixel space, we
2877 // counterscale the transform here. Note that the rect is scaled by dsf, so
2878 // the point and the rect are still in the same space.
2879 gfx::Transform surface_to_root_transform = layer->ScreenSpaceTransform();
2880 surface_to_root_transform.Scale(SK_Scalar1 / device_scale_factor,
2881 SK_Scalar1 / device_scale_factor);
2882 surface_to_root_transform.FlattenTo2d();
2883 // TODO(sunxd): Avoid losing precision by not using inverse if possible.
2884 bool ok = surface_to_root_transform.GetInverse(&hit_test_region->transform);
2885 // Note: If |ok| is false, the |transform| is set to the identity before
2886 // returning, which is what we want.
2887 ALLOW_UNUSED_LOCAL(ok);
2888 }
2889
BuildHitTestData()2890 base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() {
2891 TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildHitTestData");
2892
2893 base::Optional<viz::HitTestRegionList> hit_test_region_list(base::in_place);
2894 hit_test_region_list->flags = viz::HitTestRegionFlags::kHitTestMine |
2895 viz::HitTestRegionFlags::kHitTestMouse |
2896 viz::HitTestRegionFlags::kHitTestTouch;
2897 hit_test_region_list->bounds = active_tree_->GetDeviceViewport();
2898 hit_test_region_list->transform = DrawTransform();
2899
2900 float device_scale_factor = active_tree()->device_scale_factor();
2901
2902 Region overlapping_region;
2903 size_t num_iterated_layers = 0;
2904 // If the layer tree contains more than 100 layers, we stop accumulating
2905 // layers in |overlapping_region| to save compositor frame submitting time, as
2906 // a result we do async hit test on any surface layers that
2907 bool assume_overlap = false;
2908 for (const auto* layer : base::Reversed(*active_tree())) {
2909 // Viz hit test needs to collect information for pointer-events: none OOPIFs
2910 // as well. Now Layer::HitTestable ignores pointer-events property, but this
2911 // early out will not work correctly if we integrate has_pointer_events_none
2912 // into Layer::HitTestable, so we make sure we don't skip surface layers
2913 // that draws content but has pointer-events: none property.
2914 if (!(layer->HitTestable() ||
2915 (layer->is_surface_layer() && layer->DrawsContent())))
2916 continue;
2917
2918 if (layer->is_surface_layer()) {
2919 const auto* surface_layer = static_cast<const SurfaceLayerImpl*>(layer);
2920 // If a surface layer is created not by child frame compositor or the
2921 // frame owner has pointer-events: none property, the surface layer
2922 // becomes not hit testable. We should not generate data for it.
2923 if (!surface_layer->surface_hit_testable() ||
2924 !surface_layer->range().IsValid()) {
2925 // We collect any overlapped regions that does not have pointer-events:
2926 // none.
2927 if (!surface_layer->has_pointer_events_none() && !assume_overlap) {
2928 overlapping_region.Union(MathUtil::MapEnclosingClippedRect(
2929 layer->ScreenSpaceTransform(),
2930 gfx::Rect(surface_layer->bounds())));
2931 }
2932 continue;
2933 }
2934
2935 gfx::Rect content_rect(
2936 gfx::ScaleToEnclosingRect(gfx::Rect(surface_layer->bounds()),
2937 device_scale_factor, device_scale_factor));
2938
2939 gfx::Rect layer_screen_space_rect = MathUtil::MapEnclosingClippedRect(
2940 surface_layer->ScreenSpaceTransform(),
2941 gfx::Rect(surface_layer->bounds()));
2942 auto flag = GetFlagsForSurfaceLayer(surface_layer);
2943 uint32_t async_hit_test_reasons =
2944 viz::AsyncHitTestReasons::kNotAsyncHitTest;
2945 if (surface_layer->has_pointer_events_none())
2946 flag |= viz::HitTestRegionFlags::kHitTestIgnore;
2947 if (assume_overlap ||
2948 overlapping_region.Intersects(layer_screen_space_rect)) {
2949 flag |= viz::HitTestRegionFlags::kHitTestAsk;
2950 async_hit_test_reasons |= viz::AsyncHitTestReasons::kOverlappedRegion;
2951 }
2952 bool layer_hit_test_region_is_masked =
2953 active_tree()
2954 ->property_trees()
2955 ->effect_tree.HitTestMayBeAffectedByMask(
2956 surface_layer->effect_tree_index());
2957 if (surface_layer->is_clipped() || layer_hit_test_region_is_masked) {
2958 bool layer_hit_test_region_is_rectangle =
2959 !layer_hit_test_region_is_masked &&
2960 surface_layer->ScreenSpaceTransform().Preserves2dAxisAlignment() &&
2961 active_tree()
2962 ->property_trees()
2963 ->effect_tree.ClippedHitTestRegionIsRectangle(
2964 surface_layer->effect_tree_index());
2965 content_rect =
2966 gfx::ScaleToEnclosingRect(surface_layer->visible_layer_rect(),
2967 device_scale_factor, device_scale_factor);
2968 if (!layer_hit_test_region_is_rectangle) {
2969 flag |= viz::HitTestRegionFlags::kHitTestAsk;
2970 async_hit_test_reasons |= viz::AsyncHitTestReasons::kIrregularClip;
2971 }
2972 }
2973 const auto& surface_id = surface_layer->range().end();
2974 hit_test_region_list->regions.emplace_back();
2975 PopulateHitTestRegion(&hit_test_region_list->regions.back(), layer, flag,
2976 async_hit_test_reasons, content_rect, surface_id,
2977 device_scale_factor);
2978 continue;
2979 }
2980 // TODO(sunxd): Submit all overlapping layer bounds as hit test regions.
2981 // Also investigate if we can use visible layer rect as overlapping regions.
2982 num_iterated_layers++;
2983 if (num_iterated_layers > kAssumeOverlapThreshold)
2984 assume_overlap = true;
2985 if (!assume_overlap) {
2986 overlapping_region.Union(MathUtil::MapEnclosingClippedRect(
2987 layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds())));
2988 }
2989 }
2990
2991 return hit_test_region_list;
2992 }
2993
DidLoseLayerTreeFrameSink()2994 void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() {
2995 // Check that we haven't already detected context loss because we get it via
2996 // two paths: compositor context loss on the compositor thread and worker
2997 // context loss posted from main thread to compositor thread. We do not want
2998 // to reset the context recovery state in the scheduler.
2999 if (!has_valid_layer_tree_frame_sink_)
3000 return;
3001 has_valid_layer_tree_frame_sink_ = false;
3002 client_->DidLoseLayerTreeFrameSinkOnImplThread();
3003 lag_tracking_manager_.Clear();
3004
3005 dropped_frame_counter_.ResetFrameSorter();
3006 }
3007
OnlyExpandTopControlsAtPageTop() const3008 bool LayerTreeHostImpl::OnlyExpandTopControlsAtPageTop() const {
3009 return active_tree_->only_expand_top_controls_at_page_top();
3010 }
3011
HaveRootScrollNode() const3012 bool LayerTreeHostImpl::HaveRootScrollNode() const {
3013 return InnerViewportScrollNode();
3014 }
3015
SetNeedsCommit()3016 void LayerTreeHostImpl::SetNeedsCommit() {
3017 client_->SetNeedsCommitOnImplThread();
3018 }
3019
InnerViewportScrollNode() const3020 ScrollNode* LayerTreeHostImpl::InnerViewportScrollNode() const {
3021 return active_tree_->InnerViewportScrollNode();
3022 }
3023
OuterViewportScrollNode() const3024 ScrollNode* LayerTreeHostImpl::OuterViewportScrollNode() const {
3025 return active_tree_->OuterViewportScrollNode();
3026 }
3027
CurrentlyScrollingNode()3028 ScrollNode* LayerTreeHostImpl::CurrentlyScrollingNode() {
3029 return active_tree()->CurrentlyScrollingNode();
3030 }
3031
CurrentlyScrollingNode() const3032 const ScrollNode* LayerTreeHostImpl::CurrentlyScrollingNode() const {
3033 return active_tree()->CurrentlyScrollingNode();
3034 }
3035
IsPinchGestureActive() const3036 bool LayerTreeHostImpl::IsPinchGestureActive() const {
3037 if (!input_delegate_)
3038 return false;
3039 return GetInputHandler().pinch_gesture_active();
3040 }
3041
GetActivelyScrollingType() const3042 ActivelyScrollingType LayerTreeHostImpl::GetActivelyScrollingType() const {
3043 if (!input_delegate_)
3044 return ActivelyScrollingType::kNone;
3045 return input_delegate_->GetActivelyScrollingType();
3046 }
3047
ScrollAffectsScrollHandler() const3048 bool LayerTreeHostImpl::ScrollAffectsScrollHandler() const {
3049 if (!input_delegate_)
3050 return false;
3051 return settings_.enable_synchronized_scrolling &&
3052 scroll_affects_scroll_handler_;
3053 }
3054
SetExternalPinchGestureActive(bool active)3055 void LayerTreeHostImpl::SetExternalPinchGestureActive(bool active) {
3056 DCHECK(input_delegate_ || !active);
3057 if (input_delegate_)
3058 GetInputHandler().set_external_pinch_gesture_active(active);
3059 }
3060
CreatePendingTree()3061 void LayerTreeHostImpl::CreatePendingTree() {
3062 CHECK(!pending_tree_);
3063 if (recycle_tree_) {
3064 recycle_tree_.swap(pending_tree_);
3065 } else {
3066 pending_tree_ = std::make_unique<LayerTreeImpl>(
3067 this, active_tree()->page_scale_factor(),
3068 active_tree()->top_controls_shown_ratio(),
3069 active_tree()->bottom_controls_shown_ratio(),
3070 active_tree()->elastic_overscroll());
3071 }
3072 pending_tree_fully_painted_ = false;
3073
3074 client_->OnCanDrawStateChanged(CanDraw());
3075 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "PendingTree:waiting",
3076 TRACE_ID_LOCAL(pending_tree_.get()));
3077 }
3078
PushScrollbarOpacitiesFromActiveToPending()3079 void LayerTreeHostImpl::PushScrollbarOpacitiesFromActiveToPending() {
3080 if (!active_tree())
3081 return;
3082 for (auto& pair : scrollbar_animation_controllers_) {
3083 for (auto* scrollbar : pair.second->Scrollbars()) {
3084 if (const EffectNode* source_effect_node =
3085 active_tree()
3086 ->property_trees()
3087 ->effect_tree.FindNodeFromElementId(
3088 scrollbar->element_id())) {
3089 if (EffectNode* target_effect_node =
3090 pending_tree()
3091 ->property_trees()
3092 ->effect_tree.FindNodeFromElementId(
3093 scrollbar->element_id())) {
3094 DCHECK(target_effect_node);
3095 float source_opacity = source_effect_node->opacity;
3096 float target_opacity = target_effect_node->opacity;
3097 if (source_opacity == target_opacity)
3098 continue;
3099 target_effect_node->opacity = source_opacity;
3100 pending_tree()->property_trees()->effect_tree.set_needs_update(true);
3101 }
3102 }
3103 }
3104 }
3105 }
3106
ActivateSyncTree()3107 void LayerTreeHostImpl::ActivateSyncTree() {
3108 TRACE_EVENT0("cc,benchmark", "LayerTreeHostImpl::ActivateSyncTree()");
3109 if (pending_tree_) {
3110 TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "PendingTree:waiting",
3111 TRACE_ID_LOCAL(pending_tree_.get()));
3112 active_tree_->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync);
3113
3114 // In most cases, this will be reset in NotifyReadyToActivate, since we
3115 // activate the pending tree only when its ready. But an activation may be
3116 // forced, in the case of a context loss for instance, so reset it here as
3117 // well.
3118 pending_tree_raster_duration_timer_.reset();
3119
3120 // Process any requests in the UI resource queue. The request queue is
3121 // given in LayerTreeHost::FinishCommitOnImplThread. This must take place
3122 // before the swap.
3123 pending_tree_->ProcessUIResourceRequestQueue();
3124
3125 if (pending_tree_->needs_full_tree_sync()) {
3126 TreeSynchronizer::SynchronizeTrees(pending_tree_.get(),
3127 active_tree_.get());
3128 }
3129
3130 PushScrollbarOpacitiesFromActiveToPending();
3131 pending_tree_->PushPropertyTreesTo(active_tree_.get());
3132 active_tree_->lifecycle().AdvanceTo(
3133 LayerTreeLifecycle::kSyncedPropertyTrees);
3134
3135 TreeSynchronizer::PushLayerProperties(pending_tree(), active_tree());
3136
3137 active_tree_->lifecycle().AdvanceTo(
3138 LayerTreeLifecycle::kSyncedLayerProperties);
3139
3140 pending_tree_->PushPropertiesTo(active_tree_.get());
3141 if (!pending_tree_->LayerListIsEmpty())
3142 pending_tree_->property_trees()->ResetAllChangeTracking();
3143
3144 // Property tree nodes have been updated by PushLayerProperties. Update
3145 // elements available on active tree to start/stop ticking animations.
3146 UpdateElements(ElementListType::ACTIVE);
3147
3148 active_tree_->lifecycle().AdvanceTo(LayerTreeLifecycle::kNotSyncing);
3149
3150 // Now that we've synced everything from the pending tree to the active
3151 // tree, rename the pending tree the recycle tree so we can reuse it on the
3152 // next sync.
3153 DCHECK(!recycle_tree_);
3154 pending_tree_.swap(recycle_tree_);
3155
3156 // ScrollTimelines track a scroll source (i.e. a scroll node in the scroll
3157 // tree), whose ElementId may change between the active and pending trees.
3158 // Therefore we must inform all ScrollTimelines when the pending tree is
3159 // promoted to active.
3160 mutator_host_->PromoteScrollTimelinesPendingToActive();
3161
3162 // If we commit to the active tree directly, this is already done during
3163 // commit.
3164 ActivateAnimations();
3165
3166 // Update the state for images in ImageAnimationController and TileManager
3167 // before dirtying tile priorities. Since these components cache tree
3168 // specific state, these should be updated before DidModifyTilePriorities
3169 // which can synchronously issue a PrepareTiles. Note that if we commit to
3170 // the active tree directly, this is already done during commit.
3171 ActivateStateForImages();
3172 } else {
3173 active_tree_->ProcessUIResourceRequestQueue();
3174 }
3175
3176 active_tree_->UpdateViewportContainerSizes();
3177
3178 if (InnerViewportScrollNode()) {
3179 active_tree_->property_trees()->scroll_tree.ClampScrollToMaxScrollOffset(
3180 *InnerViewportScrollNode(), active_tree_.get());
3181
3182 DCHECK(OuterViewportScrollNode());
3183 active_tree_->property_trees()->scroll_tree.ClampScrollToMaxScrollOffset(
3184 *OuterViewportScrollNode(), active_tree_.get());
3185 }
3186
3187 active_tree_->DidBecomeActive();
3188 client_->RenewTreePriority();
3189
3190 // If we have any picture layers, then by activating we also modified tile
3191 // priorities.
3192 if (!active_tree_->picture_layers().empty())
3193 DidModifyTilePriorities();
3194
3195 client_->OnCanDrawStateChanged(CanDraw());
3196 client_->DidActivateSyncTree();
3197 if (!tree_activation_callback_.is_null())
3198 tree_activation_callback_.Run();
3199
3200 std::unique_ptr<PendingPageScaleAnimation> pending_page_scale_animation =
3201 active_tree_->TakePendingPageScaleAnimation();
3202 if (pending_page_scale_animation) {
3203 StartPageScaleAnimation(pending_page_scale_animation->target_offset,
3204 pending_page_scale_animation->use_anchor,
3205 pending_page_scale_animation->scale,
3206 pending_page_scale_animation->duration);
3207 }
3208
3209 if (input_delegate_)
3210 input_delegate_->DidActivatePendingTree();
3211
3212 // Update the child's LocalSurfaceId.
3213 if (active_tree()->local_surface_id_from_parent().is_valid()) {
3214 child_local_surface_id_allocator_.UpdateFromParent(
3215 active_tree()->local_surface_id_from_parent());
3216 if (active_tree()->TakeNewLocalSurfaceIdRequest())
3217 AllocateLocalSurfaceId();
3218 }
3219
3220 // Dump property trees and layers if run with:
3221 // --vmodule=layer_tree_host_impl=3
3222 if (VLOG_IS_ON(3)) {
3223 const char* client_name = GetClientNameForMetrics();
3224 if (!client_name)
3225 client_name = "<unknown client>";
3226 VLOG(3) << "After activating (" << client_name
3227 << ") sync tree, the active tree:"
3228 << "\nproperty_trees:\n"
3229 << active_tree_->property_trees()->ToString() << "\n"
3230 << "cc::LayerImpls:\n"
3231 << active_tree_->LayerListAsJson();
3232 }
3233 }
3234
ActivateStateForImages()3235 void LayerTreeHostImpl::ActivateStateForImages() {
3236 image_animation_controller_.DidActivate();
3237 tile_manager_.DidActivateSyncTree();
3238 }
3239
OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel level)3240 void LayerTreeHostImpl::OnMemoryPressure(
3241 base::MemoryPressureListener::MemoryPressureLevel level) {
3242 // Only work for low-end devices for now.
3243 if (!base::SysInfo::IsLowEndDevice())
3244 return;
3245
3246 if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
3247 return;
3248
3249 ReleaseTileResources();
3250 active_tree_->OnPurgeMemory();
3251 if (pending_tree_)
3252 pending_tree_->OnPurgeMemory();
3253 if (recycle_tree_)
3254 recycle_tree_->OnPurgeMemory();
3255
3256 EvictAllUIResources();
3257 if (image_decode_cache_) {
3258 image_decode_cache_->SetShouldAggressivelyFreeResources(true);
3259 image_decode_cache_->SetShouldAggressivelyFreeResources(false);
3260 }
3261 if (resource_pool_)
3262 resource_pool_->OnMemoryPressure(level);
3263 tile_manager_.decoded_image_tracker().UnlockAllImages();
3264 }
3265
SetVisible(bool visible)3266 void LayerTreeHostImpl::SetVisible(bool visible) {
3267 DCHECK(task_runner_provider_->IsImplThread());
3268
3269 if (visible_ == visible)
3270 return;
3271 visible_ = visible;
3272 if (visible_)
3273 total_frame_counter_.OnShow(base::TimeTicks::Now());
3274 else
3275 total_frame_counter_.OnHide(base::TimeTicks::Now());
3276 DidVisibilityChange(this, visible_);
3277 UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
3278
3279 // If we just became visible, we have to ensure that we draw high res tiles,
3280 // to prevent checkerboard/low res flashes.
3281 if (visible_) {
3282 // TODO(crbug.com/469175): Replace with RequiresHighResToDraw.
3283 SetRequiresHighResToDraw();
3284 // Prior CompositorFrame may have been discarded and thus we need to ensure
3285 // that we submit a new one, even if there are no tiles. Therefore, force a
3286 // full viewport redraw. However, this is unnecessary when we become visible
3287 // for the first time (before the first commit) as there is no prior
3288 // CompositorFrame to replace. We can safely use |!active_tree_->
3289 // LayerListIsEmpty()| as a proxy for this, because we wouldn't be able to
3290 // draw anything even if this is not the first time we become visible.
3291 if (!active_tree_->LayerListIsEmpty()) {
3292 SetFullViewportDamage();
3293 SetNeedsRedraw();
3294 }
3295 } else {
3296 EvictAllUIResources();
3297 // Call PrepareTiles to evict tiles when we become invisible.
3298 PrepareTiles();
3299 tile_manager_.decoded_image_tracker().UnlockAllImages();
3300 }
3301 }
3302
SetNeedsOneBeginImplFrame()3303 void LayerTreeHostImpl::SetNeedsOneBeginImplFrame() {
3304 // TODO(miletus): This is just the compositor-thread-side call to the
3305 // SwapPromiseMonitor to say something happened that may cause a swap in the
3306 // future. The name should not refer to SetNeedsRedraw but it does for now.
3307 NotifySwapPromiseMonitorsOfSetNeedsRedraw();
3308 events_metrics_manager_.SaveActiveEventMetrics();
3309 client_->SetNeedsOneBeginImplFrameOnImplThread();
3310 }
3311
SetNeedsRedraw()3312 void LayerTreeHostImpl::SetNeedsRedraw() {
3313 NotifySwapPromiseMonitorsOfSetNeedsRedraw();
3314 events_metrics_manager_.SaveActiveEventMetrics();
3315 client_->SetNeedsRedrawOnImplThread();
3316 }
3317
ActualManagedMemoryPolicy() const3318 ManagedMemoryPolicy LayerTreeHostImpl::ActualManagedMemoryPolicy() const {
3319 ManagedMemoryPolicy actual = cached_managed_memory_policy_;
3320 if (debug_state_.rasterize_only_visible_content) {
3321 actual.priority_cutoff_when_visible =
3322 gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY;
3323 } else if (use_gpu_rasterization()) {
3324 actual.priority_cutoff_when_visible =
3325 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
3326 }
3327 return actual;
3328 }
3329
ReleaseTreeResources()3330 void LayerTreeHostImpl::ReleaseTreeResources() {
3331 active_tree_->ReleaseResources();
3332 if (pending_tree_)
3333 pending_tree_->ReleaseResources();
3334 if (recycle_tree_)
3335 recycle_tree_->ReleaseResources();
3336
3337 EvictAllUIResources();
3338 }
3339
ReleaseTileResources()3340 void LayerTreeHostImpl::ReleaseTileResources() {
3341 active_tree_->ReleaseTileResources();
3342 if (pending_tree_)
3343 pending_tree_->ReleaseTileResources();
3344 if (recycle_tree_)
3345 recycle_tree_->ReleaseTileResources();
3346
3347 // Need to update tiles again in order to kick of raster work for all the
3348 // tiles that are dropped here.
3349 active_tree_->set_needs_update_draw_properties();
3350 }
3351
RecreateTileResources()3352 void LayerTreeHostImpl::RecreateTileResources() {
3353 active_tree_->RecreateTileResources();
3354 if (pending_tree_)
3355 pending_tree_->RecreateTileResources();
3356 if (recycle_tree_)
3357 recycle_tree_->RecreateTileResources();
3358 }
3359
CreateTileManagerResources()3360 void LayerTreeHostImpl::CreateTileManagerResources() {
3361 raster_buffer_provider_ = CreateRasterBufferProvider();
3362
3363 viz::ResourceFormat tile_format = TileRasterBufferFormat(
3364 settings_, layer_tree_frame_sink_->context_provider(),
3365 use_gpu_rasterization_);
3366
3367 if (use_gpu_rasterization_) {
3368 image_decode_cache_ = std::make_unique<GpuImageDecodeCache>(
3369 layer_tree_frame_sink_->worker_context_provider(),
3370 can_use_oop_rasterization_,
3371 viz::ResourceFormatToClosestSkColorType(/*gpu_compositing=*/true,
3372 tile_format),
3373 settings_.decoded_image_working_set_budget_bytes, max_texture_size_,
3374 paint_image_generator_client_id_, dark_mode_filter_);
3375 } else {
3376 bool gpu_compositing = !!layer_tree_frame_sink_->context_provider();
3377 image_decode_cache_ = std::make_unique<SoftwareImageDecodeCache>(
3378 viz::ResourceFormatToClosestSkColorType(gpu_compositing, tile_format),
3379 settings_.decoded_image_working_set_budget_bytes,
3380 paint_image_generator_client_id_);
3381 }
3382
3383 // Pass the single-threaded synchronous task graph runner to the worker pool
3384 // if we're in synchronous single-threaded mode.
3385 TaskGraphRunner* task_graph_runner = task_graph_runner_;
3386 if (is_synchronous_single_threaded_) {
3387 DCHECK(!single_thread_synchronous_task_graph_runner_);
3388 single_thread_synchronous_task_graph_runner_.reset(
3389 new SynchronousTaskGraphRunner);
3390 task_graph_runner = single_thread_synchronous_task_graph_runner_.get();
3391 }
3392
3393 tile_manager_.SetResources(resource_pool_.get(), image_decode_cache_.get(),
3394 task_graph_runner, raster_buffer_provider_.get(),
3395 use_gpu_rasterization_, use_oop_rasterization());
3396 tile_manager_.SetCheckerImagingForceDisabled(
3397 settings_.only_checker_images_with_gpu_raster && !use_gpu_rasterization_);
3398 UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
3399 }
3400
3401 std::unique_ptr<RasterBufferProvider>
CreateRasterBufferProvider()3402 LayerTreeHostImpl::CreateRasterBufferProvider() {
3403 DCHECK(GetTaskRunner());
3404
3405 viz::ContextProvider* compositor_context_provider =
3406 layer_tree_frame_sink_->context_provider();
3407 if (!compositor_context_provider)
3408 return std::make_unique<BitmapRasterBufferProvider>(layer_tree_frame_sink_);
3409
3410 const gpu::Capabilities& caps =
3411 compositor_context_provider->ContextCapabilities();
3412 viz::RasterContextProvider* worker_context_provider =
3413 layer_tree_frame_sink_->worker_context_provider();
3414
3415 viz::ResourceFormat tile_format = TileRasterBufferFormat(
3416 settings_, compositor_context_provider, use_gpu_rasterization_);
3417
3418 if (use_gpu_rasterization_) {
3419 DCHECK(worker_context_provider);
3420
3421 return std::make_unique<GpuRasterBufferProvider>(
3422 compositor_context_provider, worker_context_provider,
3423 settings_.resource_settings.use_gpu_memory_buffer_resources,
3424 tile_format, settings_.max_gpu_raster_tile_size,
3425 settings_.unpremultiply_and_dither_low_bit_depth_tiles,
3426 can_use_oop_rasterization_);
3427 }
3428
3429 bool use_zero_copy = settings_.use_zero_copy;
3430 // TODO(reveman): Remove this when mojo supports worker contexts.
3431 // crbug.com/522440
3432 if (!use_zero_copy && !worker_context_provider) {
3433 LOG(ERROR)
3434 << "Forcing zero-copy tile initialization as worker context is missing";
3435 use_zero_copy = true;
3436 }
3437
3438 if (use_zero_copy) {
3439 return std::make_unique<ZeroCopyRasterBufferProvider>(
3440 layer_tree_frame_sink_->gpu_memory_buffer_manager(),
3441 compositor_context_provider, tile_format);
3442 }
3443
3444 const int max_copy_texture_chromium_size =
3445 caps.max_copy_texture_chromium_size;
3446 return std::make_unique<OneCopyRasterBufferProvider>(
3447 GetTaskRunner(), compositor_context_provider, worker_context_provider,
3448 layer_tree_frame_sink_->gpu_memory_buffer_manager(),
3449 max_copy_texture_chromium_size, settings_.use_partial_raster,
3450 settings_.resource_settings.use_gpu_memory_buffer_resources,
3451 settings_.max_staging_buffer_usage_in_bytes, tile_format);
3452 }
3453
SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator)3454 void LayerTreeHostImpl::SetLayerTreeMutator(
3455 std::unique_ptr<LayerTreeMutator> mutator) {
3456 mutator_host_->SetLayerTreeMutator(std::move(mutator));
3457 }
3458
SetPaintWorkletLayerPainter(std::unique_ptr<PaintWorkletLayerPainter> painter)3459 void LayerTreeHostImpl::SetPaintWorkletLayerPainter(
3460 std::unique_ptr<PaintWorkletLayerPainter> painter) {
3461 paint_worklet_painter_ = std::move(painter);
3462 }
3463
QueueImageDecode(int request_id,const PaintImage & image)3464 void LayerTreeHostImpl::QueueImageDecode(int request_id,
3465 const PaintImage& image) {
3466 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
3467 "LayerTreeHostImpl::QueueImageDecode", "frame_key",
3468 image.GetKeyForFrame(PaintImage::kDefaultFrameIndex).ToString());
3469 // Optimistically specify the current raster color space, since we assume that
3470 // it won't change.
3471 auto content_color_usage = image.GetContentColorUsage();
3472 tile_manager_.decoded_image_tracker().QueueImageDecode(
3473 image, GetRasterColorSpace(content_color_usage),
3474 base::BindOnce(&LayerTreeHostImpl::ImageDecodeFinished,
3475 weak_factory_.GetWeakPtr(), request_id));
3476 tile_manager_.checker_image_tracker().DisallowCheckeringForImage(image);
3477 }
3478
ImageDecodeFinished(int request_id,bool decode_succeeded)3479 void LayerTreeHostImpl::ImageDecodeFinished(int request_id,
3480 bool decode_succeeded) {
3481 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
3482 "LayerTreeHostImpl::ImageDecodeFinished");
3483 completed_image_decode_requests_.emplace_back(request_id, decode_succeeded);
3484 client_->NotifyImageDecodeRequestFinished();
3485 }
3486
3487 std::vector<std::pair<int, bool>>
TakeCompletedImageDecodeRequests()3488 LayerTreeHostImpl::TakeCompletedImageDecodeRequests() {
3489 auto result = std::move(completed_image_decode_requests_);
3490 completed_image_decode_requests_.clear();
3491 return result;
3492 }
3493
TakeMutatorEvents()3494 std::unique_ptr<MutatorEvents> LayerTreeHostImpl::TakeMutatorEvents() {
3495 std::unique_ptr<MutatorEvents> events = mutator_host_->CreateEvents();
3496 std::swap(events, mutator_events_);
3497 mutator_host_->TakeTimeUpdatedEvents(events.get());
3498 return events;
3499 }
3500
ClearCaches()3501 void LayerTreeHostImpl::ClearCaches() {
3502 // It is safe to clear the decode policy tracking on navigations since it
3503 // comes with an invalidation and the image ids are never re-used.
3504 bool can_clear_decode_policy_tracking = true;
3505 tile_manager_.ClearCheckerImageTracking(can_clear_decode_policy_tracking);
3506 if (image_decode_cache_)
3507 image_decode_cache_->ClearCache();
3508 image_animation_controller_.set_did_navigate();
3509 }
3510
DidChangeScrollbarVisibility()3511 void LayerTreeHostImpl::DidChangeScrollbarVisibility() {
3512 // Need a commit since input handling for scrollbars is handled in Blink so
3513 // we need to communicate to Blink when the compositor shows/hides the
3514 // scrollbars.
3515 client_->SetNeedsCommitOnImplThread();
3516 }
3517
CleanUpTileManagerResources()3518 void LayerTreeHostImpl::CleanUpTileManagerResources() {
3519 tile_manager_.FinishTasksAndCleanUp();
3520 single_thread_synchronous_task_graph_runner_ = nullptr;
3521 image_decode_cache_ = nullptr;
3522 raster_buffer_provider_ = nullptr;
3523 // Any resources that were allocated previously should be considered not good
3524 // for reuse, as the RasterBufferProvider will be replaced and it may choose
3525 // to allocate future resources differently.
3526 resource_pool_->InvalidateResources();
3527
3528 // We've potentially just freed a large number of resources on our various
3529 // contexts. Flushing now helps ensure these are cleaned up quickly
3530 // preventing driver cache growth. See crbug.com/643251
3531 if (layer_tree_frame_sink_) {
3532 if (auto* compositor_context = layer_tree_frame_sink_->context_provider()) {
3533 // TODO(ericrk): Remove ordering barrier once |compositor_context| no
3534 // longer uses GL.
3535 compositor_context->ContextGL()->OrderingBarrierCHROMIUM();
3536 compositor_context->ContextSupport()->FlushPendingWork();
3537 }
3538 if (auto* worker_context =
3539 layer_tree_frame_sink_->worker_context_provider()) {
3540 viz::RasterContextProvider::ScopedRasterContextLock hold(worker_context);
3541 hold.RasterInterface()->ShallowFlushCHROMIUM();
3542 }
3543 }
3544 }
3545
ReleaseLayerTreeFrameSink()3546 void LayerTreeHostImpl::ReleaseLayerTreeFrameSink() {
3547 TRACE_EVENT0("cc", "LayerTreeHostImpl::ReleaseLayerTreeFrameSink");
3548
3549 if (!layer_tree_frame_sink_) {
3550 DCHECK(!has_valid_layer_tree_frame_sink_);
3551 return;
3552 }
3553
3554 has_valid_layer_tree_frame_sink_ = false;
3555
3556 ReleaseTreeResources();
3557 CleanUpTileManagerResources();
3558 resource_pool_ = nullptr;
3559 ClearUIResources();
3560
3561 if (layer_tree_frame_sink_->context_provider()) {
3562 // TODO(ericrk): Remove this once all uses of ContextGL from LTFS are
3563 // removed.
3564 auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL();
3565 gl->Finish();
3566 }
3567
3568 // Release any context visibility before we destroy the LayerTreeFrameSink.
3569 SetContextVisibility(false);
3570
3571 bool all_resources_are_lost = layer_tree_frame_sink_->context_provider();
3572
3573 // Destroy the submit-frame trackers before destroying the frame sink.
3574 frame_trackers_.ClearAll();
3575
3576 // Detach from the old LayerTreeFrameSink and reset |layer_tree_frame_sink_|
3577 // pointer as this surface is going to be destroyed independent of if binding
3578 // the new LayerTreeFrameSink succeeds or not.
3579 layer_tree_frame_sink_->DetachFromClient();
3580 layer_tree_frame_sink_ = nullptr;
3581
3582 // If gpu compositing, then any resources created with the gpu context in the
3583 // LayerTreeFrameSink were exported to the display compositor may be modified
3584 // by it, and thus we would be unable to determine what state they are in, in
3585 // order to reuse them, so they must be lost. Note that this includes
3586 // resources created using the gpu context associated with
3587 // |layer_tree_frame_sink_| internally by the compositor and any resources
3588 // received from an external source (for instance, TextureLayers). This is
3589 // because the API contract for releasing these external resources requires
3590 // that the compositor return them with a valid sync token and no
3591 // modifications to their GL state. Since that can not be guaranteed, these
3592 // must also be marked lost.
3593 //
3594 // In software compositing, the resources are not modified by the display
3595 // compositor (there is no stateful metadata for shared memory), so we do not
3596 // need to consider them lost.
3597 //
3598 // In both cases, the resources that are exported to the display compositor
3599 // will have no means of being returned to this client without the
3600 // LayerTreeFrameSink, so they should no longer be considered as exported. Do
3601 // this *after* any interactions with the |layer_tree_frame_sink_| in case it
3602 // tries to return resources during destruction.
3603 //
3604 // The assumption being made here is that the display compositor WILL NOT use
3605 // any resources previously exported when the CompositorFrameSink is closed.
3606 // This should be true as the connection is closed when the display compositor
3607 // shuts down/crashes, or when it believes we are a malicious client in which
3608 // case it will not display content from the previous CompositorFrameSink. If
3609 // this assumption is violated, we may modify resources no longer considered
3610 // as exported while the display compositor is still making use of them,
3611 // leading to visual mistakes.
3612 resource_provider_.ReleaseAllExportedResources(all_resources_are_lost);
3613
3614 // We don't know if the next LayerTreeFrameSink will support GPU
3615 // rasterization. Make sure to clear the flag so that we force a
3616 // re-computation.
3617 use_gpu_rasterization_ = false;
3618 }
3619
InitializeFrameSink(LayerTreeFrameSink * layer_tree_frame_sink)3620 bool LayerTreeHostImpl::InitializeFrameSink(
3621 LayerTreeFrameSink* layer_tree_frame_sink) {
3622 TRACE_EVENT0("cc", "LayerTreeHostImpl::InitializeFrameSink");
3623
3624 ReleaseLayerTreeFrameSink();
3625 if (!layer_tree_frame_sink->BindToClient(this)) {
3626 // Avoid recreating tree resources because we might not have enough
3627 // information to do this yet (eg. we don't have a TileManager at this
3628 // point).
3629 return false;
3630 }
3631
3632 layer_tree_frame_sink_ = layer_tree_frame_sink;
3633 has_valid_layer_tree_frame_sink_ = true;
3634
3635 auto* context_provider = layer_tree_frame_sink_->context_provider();
3636
3637 if (context_provider) {
3638 max_texture_size_ =
3639 context_provider->ContextCapabilities().max_texture_size;
3640 } else {
3641 // Pick an arbitrary limit here similar to what hardware might.
3642 max_texture_size_ = 16 * 1024;
3643 }
3644
3645 resource_pool_ = std::make_unique<ResourcePool>(
3646 &resource_provider_, context_provider, GetTaskRunner(),
3647 ResourcePool::kDefaultExpirationDelay,
3648 settings_.disallow_non_exact_resource_reuse);
3649
3650 auto* context = layer_tree_frame_sink_->worker_context_provider();
3651 if (context) {
3652 viz::RasterContextProvider::ScopedRasterContextLock hold(context);
3653 can_use_oop_rasterization_ =
3654 context->ContextCapabilities().supports_oop_raster;
3655 } else {
3656 can_use_oop_rasterization_ = false;
3657 }
3658
3659 // Since the new context may support GPU raster or be capable of MSAA, update
3660 // status here. We don't need to check the return value since we are
3661 // recreating all resources already.
3662 SetNeedUpdateGpuRasterizationStatus();
3663 UpdateGpuRasterizationStatus();
3664
3665 // See note in LayerTreeImpl::UpdateDrawProperties, new LayerTreeFrameSink
3666 // means a new max texture size which affects draw properties. Also, if the
3667 // draw properties were up to date, layers still lost resources and we need to
3668 // UpdateDrawProperties() after calling RecreateTreeResources().
3669 active_tree_->set_needs_update_draw_properties();
3670 if (pending_tree_)
3671 pending_tree_->set_needs_update_draw_properties();
3672
3673 CreateTileManagerResources();
3674 RecreateTileResources();
3675
3676 client_->OnCanDrawStateChanged(CanDraw());
3677 SetFullViewportDamage();
3678 // There will not be anything to draw here, so set high res
3679 // to avoid checkerboards, typically when we are recovering
3680 // from lost context.
3681 // TODO(crbug.com/469175): Replace with RequiresHighResToDraw.
3682 SetRequiresHighResToDraw();
3683
3684 // Always allocate a new viz::LocalSurfaceId when we get a new
3685 // LayerTreeFrameSink to ensure that we do not reuse the same surface after
3686 // it might have been garbage collected.
3687 const viz::LocalSurfaceId& local_surface_id =
3688 child_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
3689 if (local_surface_id.is_valid())
3690 AllocateLocalSurfaceId();
3691
3692 return true;
3693 }
3694
SetBeginFrameSource(viz::BeginFrameSource * source)3695 void LayerTreeHostImpl::SetBeginFrameSource(viz::BeginFrameSource* source) {
3696 client_->SetBeginFrameSource(source);
3697 }
3698
DrawTransform() const3699 const gfx::Transform& LayerTreeHostImpl::DrawTransform() const {
3700 return external_transform_;
3701 }
3702
DidChangeBrowserControlsPosition()3703 void LayerTreeHostImpl::DidChangeBrowserControlsPosition() {
3704 active_tree_->UpdateViewportContainerSizes();
3705 if (pending_tree_)
3706 pending_tree_->UpdateViewportContainerSizes();
3707 SetNeedsRedraw();
3708 SetNeedsOneBeginImplFrame();
3709 SetFullViewportDamage();
3710 }
3711
DidObserveScrollDelay(base::TimeDelta scroll_delay,base::TimeTicks scroll_timestamp)3712 void LayerTreeHostImpl::DidObserveScrollDelay(
3713 base::TimeDelta scroll_delay,
3714 base::TimeTicks scroll_timestamp) {
3715 // Record First Scroll Delay.
3716 if (!has_observed_first_scroll_delay_) {
3717 client_->DidObserveFirstScrollDelay(scroll_delay, scroll_timestamp);
3718 has_observed_first_scroll_delay_ = true;
3719 }
3720 }
3721
TopControlsHeight() const3722 float LayerTreeHostImpl::TopControlsHeight() const {
3723 return active_tree_->top_controls_height();
3724 }
3725
TopControlsMinHeight() const3726 float LayerTreeHostImpl::TopControlsMinHeight() const {
3727 return active_tree_->top_controls_min_height();
3728 }
3729
BottomControlsHeight() const3730 float LayerTreeHostImpl::BottomControlsHeight() const {
3731 return active_tree_->bottom_controls_height();
3732 }
3733
BottomControlsMinHeight() const3734 float LayerTreeHostImpl::BottomControlsMinHeight() const {
3735 return active_tree_->bottom_controls_min_height();
3736 }
3737
SetCurrentBrowserControlsShownRatio(float top_ratio,float bottom_ratio)3738 void LayerTreeHostImpl::SetCurrentBrowserControlsShownRatio(
3739 float top_ratio,
3740 float bottom_ratio) {
3741 if (active_tree_->SetCurrentBrowserControlsShownRatio(top_ratio,
3742 bottom_ratio))
3743 DidChangeBrowserControlsPosition();
3744 }
3745
CurrentTopControlsShownRatio() const3746 float LayerTreeHostImpl::CurrentTopControlsShownRatio() const {
3747 return active_tree_->CurrentTopControlsShownRatio();
3748 }
3749
CurrentBottomControlsShownRatio() const3750 float LayerTreeHostImpl::CurrentBottomControlsShownRatio() const {
3751 return active_tree_->CurrentBottomControlsShownRatio();
3752 }
3753
ViewportScrollOffset() const3754 gfx::ScrollOffset LayerTreeHostImpl::ViewportScrollOffset() const {
3755 return viewport_->TotalScrollOffset();
3756 }
3757
AutoScrollAnimationCreate(const ScrollNode & scroll_node,const gfx::Vector2dF & delta,float autoscroll_velocity)3758 bool LayerTreeHostImpl::AutoScrollAnimationCreate(const ScrollNode& scroll_node,
3759 const gfx::Vector2dF& delta,
3760 float autoscroll_velocity) {
3761 return ScrollAnimationCreateInternal(scroll_node, delta, base::TimeDelta(),
3762 autoscroll_velocity);
3763 }
3764
ScrollAnimationCreate(const ScrollNode & scroll_node,const gfx::Vector2dF & delta,base::TimeDelta delayed_by)3765 bool LayerTreeHostImpl::ScrollAnimationCreate(const ScrollNode& scroll_node,
3766 const gfx::Vector2dF& delta,
3767 base::TimeDelta delayed_by) {
3768 return ScrollAnimationCreateInternal(scroll_node, delta, delayed_by,
3769 base::nullopt);
3770 }
3771
ScrollAnimationCreateInternal(const ScrollNode & scroll_node,const gfx::Vector2dF & delta,base::TimeDelta delayed_by,base::Optional<float> autoscroll_velocity)3772 bool LayerTreeHostImpl::ScrollAnimationCreateInternal(
3773 const ScrollNode& scroll_node,
3774 const gfx::Vector2dF& delta,
3775 base::TimeDelta delayed_by,
3776 base::Optional<float> autoscroll_velocity) {
3777 ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree;
3778
3779 const float kEpsilon = 0.1f;
3780 bool scroll_animated =
3781 (std::abs(delta.x()) > kEpsilon || std::abs(delta.y()) > kEpsilon) ||
3782 autoscroll_velocity;
3783 if (!scroll_animated) {
3784 scroll_tree.ScrollBy(scroll_node, delta, active_tree());
3785 TRACE_EVENT_INSTANT0("cc", "no scroll animation due to small delta",
3786 TRACE_EVENT_SCOPE_THREAD);
3787 return false;
3788 }
3789
3790 gfx::ScrollOffset current_offset =
3791 scroll_tree.current_scroll_offset(scroll_node.element_id);
3792 gfx::ScrollOffset target_offset = scroll_tree.ClampScrollOffsetToLimits(
3793 current_offset + gfx::ScrollOffset(delta), scroll_node);
3794
3795 // Start the animation one full frame in. Without any offset, the animation
3796 // doesn't start until next frame, increasing latency, and preventing our
3797 // input latency tracking architecture from working.
3798 base::TimeDelta animation_start_offset = CurrentBeginFrameArgs().interval;
3799
3800 if (autoscroll_velocity) {
3801 mutator_host_->ImplOnlyAutoScrollAnimationCreate(
3802 scroll_node.element_id, gfx::ScrollOffset(delta), current_offset,
3803 autoscroll_velocity.value(), animation_start_offset);
3804 } else {
3805 mutator_host_->ImplOnlyScrollAnimationCreate(
3806 scroll_node.element_id, target_offset, current_offset, delayed_by,
3807 animation_start_offset);
3808 }
3809
3810 SetNeedsOneBeginImplFrame();
3811
3812 return true;
3813 }
3814
3815
UpdateImageDecodingHints(base::flat_map<PaintImage::Id,PaintImage::DecodingMode> decoding_mode_map)3816 void LayerTreeHostImpl::UpdateImageDecodingHints(
3817 base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
3818 decoding_mode_map) {
3819 tile_manager_.checker_image_tracker().UpdateImageDecodingHints(
3820 std::move(decoding_mode_map));
3821 }
3822
SetRenderFrameObserver(std::unique_ptr<RenderFrameMetadataObserver> observer)3823 void LayerTreeHostImpl::SetRenderFrameObserver(
3824 std::unique_ptr<RenderFrameMetadataObserver> observer) {
3825 render_frame_metadata_observer_ = std::move(observer);
3826 render_frame_metadata_observer_->BindToCurrentThread();
3827 }
3828
WillScrollContent(ElementId element_id)3829 void LayerTreeHostImpl::WillScrollContent(ElementId element_id) {
3830 // Flash the overlay scrollbar even if the scroll delta is 0.
3831 if (settings().scrollbar_flash_after_any_scroll_update) {
3832 FlashAllScrollbars(false);
3833 } else {
3834 if (ScrollbarAnimationController* animation_controller =
3835 ScrollbarAnimationControllerForElementId(element_id))
3836 animation_controller->WillUpdateScroll();
3837 }
3838 }
3839
DidScrollContent(ElementId element_id,bool animated)3840 void LayerTreeHostImpl::DidScrollContent(ElementId element_id, bool animated) {
3841 if (settings().scrollbar_flash_after_any_scroll_update) {
3842 FlashAllScrollbars(true);
3843 } else {
3844 if (ScrollbarAnimationController* animation_controller =
3845 ScrollbarAnimationControllerForElementId(element_id))
3846 animation_controller->DidScrollUpdate();
3847 }
3848
3849 // We may wish to prioritize smoothness over raster when the user is
3850 // interacting with content, but this needs to be evaluated only for direct
3851 // user scrolls, not for programmatic scrolls.
3852 if (input_delegate_->IsCurrentlyScrolling())
3853 client_->RenewTreePriority();
3854
3855 if (!animated) {
3856 // SetNeedsRedraw is only called in non-animated cases since an animation
3857 // won't actually update any scroll offsets until a frame produces a
3858 // tick. Scheduling a redraw here before ticking means the draw gets
3859 // aborted due to no damage and the swap promises broken so a LatencyInfo
3860 // won't be recorded.
3861 SetNeedsRedraw();
3862 }
3863 }
3864
DeviceScaleFactor() const3865 float LayerTreeHostImpl::DeviceScaleFactor() const {
3866 return active_tree_->device_scale_factor();
3867 }
3868
PageScaleFactor() const3869 float LayerTreeHostImpl::PageScaleFactor() const {
3870 return active_tree_->page_scale_factor_for_scroll();
3871 }
3872
BindToInputHandler(std::unique_ptr<InputDelegateForCompositor> delegate)3873 void LayerTreeHostImpl::BindToInputHandler(
3874 std::unique_ptr<InputDelegateForCompositor> delegate) {
3875 input_delegate_ = std::move(delegate);
3876 }
3877
GetScrollTree() const3878 ScrollTree& LayerTreeHostImpl::GetScrollTree() const {
3879 return active_tree_->property_trees()->scroll_tree;
3880 }
3881
HasAnimatedScrollbars() const3882 bool LayerTreeHostImpl::HasAnimatedScrollbars() const {
3883 return !scrollbar_animation_controllers_.empty();
3884 }
3885
CollectScrollbarUpdatesForCommit(CompositorCommitData * commit_data) const3886 void LayerTreeHostImpl::CollectScrollbarUpdatesForCommit(
3887 CompositorCommitData* commit_data) const {
3888 commit_data->scrollbars.reserve(scrollbar_animation_controllers_.size());
3889 for (auto& pair : scrollbar_animation_controllers_) {
3890 commit_data->scrollbars.push_back(
3891 {pair.first, pair.second->ScrollbarsHidden()});
3892 }
3893 }
3894
3895 std::unique_ptr<CompositorCommitData>
ProcessCompositorDeltas()3896 LayerTreeHostImpl::ProcessCompositorDeltas() {
3897 auto commit_data = std::make_unique<CompositorCommitData>();
3898
3899 if (input_delegate_)
3900 input_delegate_->ProcessCommitDeltas(commit_data.get());
3901 CollectScrollbarUpdatesForCommit(commit_data.get());
3902
3903 commit_data->page_scale_delta =
3904 active_tree_->page_scale_factor()->PullDeltaForMainThread();
3905 commit_data->is_pinch_gesture_active = active_tree_->PinchGestureActive();
3906 // We should never process non-unit page_scale_delta for an OOPIF subframe.
3907 // TODO(wjmaclean): Remove this DCHECK as a pre-condition to closing the bug.
3908 // https://crbug.com/845097
3909 DCHECK(!settings().is_layer_tree_for_subframe ||
3910 commit_data->page_scale_delta == 1.f);
3911 commit_data->top_controls_delta =
3912 active_tree()->top_controls_shown_ratio()->PullDeltaForMainThread();
3913 commit_data->bottom_controls_delta =
3914 active_tree()->bottom_controls_shown_ratio()->PullDeltaForMainThread();
3915 commit_data->elastic_overscroll_delta =
3916 active_tree_->elastic_overscroll()->PullDeltaForMainThread();
3917 commit_data->swap_promises.swap(swap_promises_for_main_thread_scroll_update_);
3918
3919 commit_data->ongoing_scroll_animation =
3920 !!mutator_host_->ImplOnlyScrollAnimatingElement();
3921
3922 if (browser_controls_manager()) {
3923 commit_data->browser_controls_constraint =
3924 browser_controls_manager()->PullConstraintForMainThread(
3925 &commit_data->browser_controls_constraint_changed);
3926 }
3927
3928 return commit_data;
3929 }
3930
SetFullViewportDamage()3931 void LayerTreeHostImpl::SetFullViewportDamage() {
3932 // In non-Android-WebView cases, we expect GetDeviceViewport() to be the same
3933 // as internal_device_viewport(), so the full-viewport damage rect is just
3934 // the internal viewport rect. In the case of Android WebView,
3935 // GetDeviceViewport returns the external viewport, but we still want to use
3936 // the internal viewport's origin for setting the damage.
3937 // See https://chromium-review.googlesource.com/c/chromium/src/+/1257555.
3938 SetViewportDamage(gfx::Rect(active_tree_->internal_device_viewport().origin(),
3939 active_tree_->GetDeviceViewport().size()));
3940 }
3941
AnimatePageScale(base::TimeTicks monotonic_time)3942 bool LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) {
3943 if (!page_scale_animation_)
3944 return false;
3945
3946 gfx::ScrollOffset scroll_total = active_tree_->TotalScrollOffset();
3947
3948 if (!page_scale_animation_->IsAnimationStarted())
3949 page_scale_animation_->StartAnimation(monotonic_time);
3950
3951 active_tree_->SetPageScaleOnActiveTree(
3952 page_scale_animation_->PageScaleFactorAtTime(monotonic_time));
3953 gfx::ScrollOffset next_scroll = gfx::ScrollOffset(
3954 page_scale_animation_->ScrollOffsetAtTime(monotonic_time));
3955
3956 viewport().ScrollByInnerFirst(next_scroll.DeltaFrom(scroll_total));
3957
3958 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
3959 page_scale_animation_ = nullptr;
3960 client_->SetNeedsCommitOnImplThread();
3961 client_->RenewTreePriority();
3962 client_->DidCompletePageScaleAnimationOnImplThread();
3963 } else {
3964 SetNeedsOneBeginImplFrame();
3965 }
3966 return true;
3967 }
3968
AnimateBrowserControls(base::TimeTicks time)3969 bool LayerTreeHostImpl::AnimateBrowserControls(base::TimeTicks time) {
3970 if (!browser_controls_offset_manager_->HasAnimation())
3971 return false;
3972
3973 gfx::Vector2dF scroll_delta = browser_controls_offset_manager_->Animate(time);
3974
3975 if (browser_controls_offset_manager_->HasAnimation())
3976 SetNeedsOneBeginImplFrame();
3977
3978 if (active_tree_->TotalScrollOffset().y() == 0.f ||
3979 OnlyExpandTopControlsAtPageTop()) {
3980 return false;
3981 }
3982
3983 if (scroll_delta.IsZero())
3984 return false;
3985
3986 // This counter-scrolls the page to keep the appearance of the page content
3987 // being fixed while the browser controls animate.
3988 viewport().ScrollBy(scroll_delta,
3989 /*viewport_point=*/gfx::Point(),
3990 /*is_wheel_scroll=*/false,
3991 /*affect_browser_controls=*/false,
3992 /*scroll_outer_viewport=*/true);
3993 client_->SetNeedsCommitOnImplThread();
3994 client_->RenewTreePriority();
3995 return true;
3996 }
3997
AnimateScrollbars(base::TimeTicks monotonic_time)3998 bool LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks monotonic_time) {
3999 bool animated = false;
4000 for (auto& pair : scrollbar_animation_controllers_)
4001 animated |= pair.second->Animate(monotonic_time);
4002 return animated;
4003 }
4004
AnimateLayers(base::TimeTicks monotonic_time,bool is_active_tree)4005 bool LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time,
4006 bool is_active_tree) {
4007 const ScrollTree& scroll_tree =
4008 is_active_tree ? active_tree_->property_trees()->scroll_tree
4009 : pending_tree_->property_trees()->scroll_tree;
4010 const bool animated = mutator_host_->TickAnimations(
4011 monotonic_time, scroll_tree, is_active_tree);
4012
4013 // TODO(crbug.com/551134): Only do this if the animations are on the active
4014 // tree, or if they are on the pending tree waiting for some future time to
4015 // start.
4016 // TODO(crbug.com/551138): We currently have a single signal from the
4017 // animation_host, so on the last frame of an animation we will
4018 // still request an extra SetNeedsAnimate here.
4019 if (animated) {
4020 // TODO(crbug.com/1039750): If only scroll animations present, schedule a
4021 // frame only if scroll changes.
4022 SetNeedsOneBeginImplFrame();
4023 frame_trackers_.StartSequence(
4024 FrameSequenceTrackerType::kCompositorAnimation);
4025 } else {
4026 frame_trackers_.StopSequence(
4027 FrameSequenceTrackerType::kCompositorAnimation);
4028 }
4029
4030 // TODO(crbug.com/551138): We could return true only if the animations are on
4031 // the active tree. There's no need to cause a draw to take place from
4032 // animations starting/ticking on the pending tree.
4033 return animated;
4034 }
4035
UpdateAnimationState(bool start_ready_animations)4036 void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
4037 const bool has_active_animations = mutator_host_->UpdateAnimationState(
4038 start_ready_animations, mutator_events_.get());
4039
4040 if (has_active_animations) {
4041 SetNeedsOneBeginImplFrame();
4042 if (!mutator_events_->IsEmpty())
4043 SetNeedsCommit();
4044 }
4045 }
4046
ActivateAnimations()4047 void LayerTreeHostImpl::ActivateAnimations() {
4048 const bool activated =
4049 mutator_host_->ActivateAnimations(mutator_events_.get());
4050 if (activated) {
4051 // Activating an animation changes layer draw properties, such as
4052 // screen_space_transform_is_animating. So when we see a new animation get
4053 // activated, we need to update the draw properties on the active tree.
4054 active_tree()->set_needs_update_draw_properties();
4055 // Request another frame to run the next tick of the animation.
4056 SetNeedsOneBeginImplFrame();
4057 if (!mutator_events_->IsEmpty())
4058 SetNeedsCommit();
4059 }
4060 }
4061
RegisterScrollbarAnimationController(ElementId scroll_element_id,float scrollbar_opacity)4062 void LayerTreeHostImpl::RegisterScrollbarAnimationController(
4063 ElementId scroll_element_id,
4064 float scrollbar_opacity) {
4065 if (ScrollbarAnimationControllerForElementId(scroll_element_id))
4066 return;
4067
4068 scrollbar_animation_controllers_[scroll_element_id] =
4069 active_tree_->CreateScrollbarAnimationController(scroll_element_id,
4070 scrollbar_opacity);
4071 }
4072
DidUnregisterScrollbarLayer(ElementId scroll_element_id,ScrollbarOrientation orientation)4073 void LayerTreeHostImpl::DidUnregisterScrollbarLayer(
4074 ElementId scroll_element_id,
4075 ScrollbarOrientation orientation) {
4076 if (ScrollbarsFor(scroll_element_id).empty())
4077 scrollbar_animation_controllers_.erase(scroll_element_id);
4078 if (input_delegate_)
4079 input_delegate_->DidUnregisterScrollbar(scroll_element_id, orientation);
4080 }
4081
4082 ScrollbarAnimationController*
ScrollbarAnimationControllerForElementId(ElementId scroll_element_id) const4083 LayerTreeHostImpl::ScrollbarAnimationControllerForElementId(
4084 ElementId scroll_element_id) const {
4085 // The viewport layers have only one set of scrollbars. On Android, these are
4086 // registered with the inner viewport, otherwise they're registered with the
4087 // outer viewport. If a controller for one exists, the other shouldn't.
4088 if (InnerViewportScrollNode()) {
4089 DCHECK(OuterViewportScrollNode());
4090 if (scroll_element_id == InnerViewportScrollNode()->element_id ||
4091 scroll_element_id == OuterViewportScrollNode()->element_id) {
4092 auto itr = scrollbar_animation_controllers_.find(
4093 InnerViewportScrollNode()->element_id);
4094 if (itr != scrollbar_animation_controllers_.end())
4095 return itr->second.get();
4096
4097 itr = scrollbar_animation_controllers_.find(
4098 OuterViewportScrollNode()->element_id);
4099 if (itr != scrollbar_animation_controllers_.end())
4100 return itr->second.get();
4101
4102 return nullptr;
4103 }
4104 }
4105
4106 auto i = scrollbar_animation_controllers_.find(scroll_element_id);
4107 if (i == scrollbar_animation_controllers_.end())
4108 return nullptr;
4109 return i->second.get();
4110 }
4111
FlashAllScrollbars(bool did_scroll)4112 void LayerTreeHostImpl::FlashAllScrollbars(bool did_scroll) {
4113 for (auto& pair : scrollbar_animation_controllers_) {
4114 if (did_scroll)
4115 pair.second->DidScrollUpdate();
4116 else
4117 pair.second->WillUpdateScroll();
4118 }
4119 }
4120
PostDelayedScrollbarAnimationTask(base::OnceClosure task,base::TimeDelta delay)4121 void LayerTreeHostImpl::PostDelayedScrollbarAnimationTask(
4122 base::OnceClosure task,
4123 base::TimeDelta delay) {
4124 client_->PostDelayedAnimationTaskOnImplThread(std::move(task), delay);
4125 }
4126
4127 // TODO(danakj): Make this a return value from the Animate() call instead of an
4128 // interface on LTHI. (Also, crbug.com/551138.)
SetNeedsAnimateForScrollbarAnimation()4129 void LayerTreeHostImpl::SetNeedsAnimateForScrollbarAnimation() {
4130 TRACE_EVENT0("cc", "LayerTreeHostImpl::SetNeedsAnimateForScrollbarAnimation");
4131 SetNeedsOneBeginImplFrame();
4132 }
4133
4134 // TODO(danakj): Make this a return value from the Animate() call instead of an
4135 // interface on LTHI. (Also, crbug.com/551138.)
SetNeedsRedrawForScrollbarAnimation()4136 void LayerTreeHostImpl::SetNeedsRedrawForScrollbarAnimation() {
4137 SetNeedsRedraw();
4138 }
4139
ScrollbarsFor(ElementId id) const4140 ScrollbarSet LayerTreeHostImpl::ScrollbarsFor(ElementId id) const {
4141 return active_tree_->ScrollbarsFor(id);
4142 }
4143
AddVideoFrameController(VideoFrameController * controller)4144 void LayerTreeHostImpl::AddVideoFrameController(
4145 VideoFrameController* controller) {
4146 bool was_empty = video_frame_controllers_.empty();
4147 video_frame_controllers_.insert(controller);
4148 if (current_begin_frame_tracker_.DangerousMethodHasStarted() &&
4149 !current_begin_frame_tracker_.DangerousMethodHasFinished())
4150 controller->OnBeginFrame(current_begin_frame_tracker_.Current());
4151 if (was_empty)
4152 client_->SetVideoNeedsBeginFrames(true);
4153 }
4154
RemoveVideoFrameController(VideoFrameController * controller)4155 void LayerTreeHostImpl::RemoveVideoFrameController(
4156 VideoFrameController* controller) {
4157 video_frame_controllers_.erase(controller);
4158 if (video_frame_controllers_.empty())
4159 client_->SetVideoNeedsBeginFrames(false);
4160 }
4161
SetTreePriority(TreePriority priority)4162 void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
4163 if (global_tile_state_.tree_priority == priority)
4164 return;
4165 global_tile_state_.tree_priority = priority;
4166 DidModifyTilePriorities();
4167 }
4168
GetTreePriority() const4169 TreePriority LayerTreeHostImpl::GetTreePriority() const {
4170 return global_tile_state_.tree_priority;
4171 }
4172
CurrentBeginFrameArgs() const4173 const viz::BeginFrameArgs& LayerTreeHostImpl::CurrentBeginFrameArgs() const {
4174 // TODO(mithro): Replace call with current_begin_frame_tracker_.Current()
4175 // once all calls which happens outside impl frames are fixed.
4176 return current_begin_frame_tracker_.DangerousMethodCurrentOrLast();
4177 }
4178
CurrentBeginFrameInterval() const4179 base::TimeDelta LayerTreeHostImpl::CurrentBeginFrameInterval() const {
4180 return current_begin_frame_tracker_.Interval();
4181 }
4182
4183 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
AsValueWithFrame(FrameData * frame) const4184 LayerTreeHostImpl::AsValueWithFrame(FrameData* frame) const {
4185 std::unique_ptr<base::trace_event::TracedValue> state(
4186 new base::trace_event::TracedValue());
4187 AsValueWithFrameInto(frame, state.get());
4188 return std::move(state);
4189 }
4190
AsValueWithFrameInto(FrameData * frame,base::trace_event::TracedValue * state) const4191 void LayerTreeHostImpl::AsValueWithFrameInto(
4192 FrameData* frame,
4193 base::trace_event::TracedValue* state) const {
4194 if (this->pending_tree_) {
4195 state->BeginDictionary("activation_state");
4196 ActivationStateAsValueInto(state);
4197 state->EndDictionary();
4198 }
4199 MathUtil::AddToTracedValue("device_viewport_size",
4200 active_tree_->GetDeviceViewport().size(), state);
4201
4202 std::vector<PrioritizedTile> prioritized_tiles;
4203 active_tree_->GetAllPrioritizedTilesForTracing(&prioritized_tiles);
4204 if (pending_tree_)
4205 pending_tree_->GetAllPrioritizedTilesForTracing(&prioritized_tiles);
4206
4207 state->BeginArray("active_tiles");
4208 for (const auto& prioritized_tile : prioritized_tiles) {
4209 state->BeginDictionary();
4210 prioritized_tile.AsValueInto(state);
4211 state->EndDictionary();
4212 }
4213 state->EndArray();
4214
4215 state->BeginDictionary("tile_manager_basic_state");
4216 tile_manager_.BasicStateAsValueInto(state);
4217 state->EndDictionary();
4218
4219 state->BeginDictionary("active_tree");
4220 active_tree_->AsValueInto(state);
4221 state->EndDictionary();
4222 if (pending_tree_) {
4223 state->BeginDictionary("pending_tree");
4224 pending_tree_->AsValueInto(state);
4225 state->EndDictionary();
4226 }
4227 if (frame) {
4228 state->BeginDictionary("frame");
4229 frame->AsValueInto(state);
4230 state->EndDictionary();
4231 }
4232 }
4233
ActivationStateAsValueInto(base::trace_event::TracedValue * state) const4234 void LayerTreeHostImpl::ActivationStateAsValueInto(
4235 base::trace_event::TracedValue* state) const {
4236 viz::TracedValue::SetIDRef(this, state, "lthi");
4237 state->BeginDictionary("tile_manager");
4238 tile_manager_.BasicStateAsValueInto(state);
4239 state->EndDictionary();
4240 }
4241
SetDebugState(const LayerTreeDebugState & new_debug_state)4242 void LayerTreeHostImpl::SetDebugState(
4243 const LayerTreeDebugState& new_debug_state) {
4244 if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
4245 return;
4246
4247 debug_state_ = new_debug_state;
4248 UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
4249 SetFullViewportDamage();
4250 }
4251
CreateUIResource(UIResourceId uid,const UIResourceBitmap & bitmap)4252 void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
4253 const UIResourceBitmap& bitmap) {
4254 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
4255 "LayerTreeHostImpl::CreateUIResource");
4256 DCHECK_GT(uid, 0);
4257
4258 // Allow for multiple creation requests with the same UIResourceId. The
4259 // previous resource is simply deleted.
4260 viz::ResourceId id = ResourceIdForUIResource(uid);
4261 if (id)
4262 DeleteUIResource(uid);
4263
4264 if (!has_valid_layer_tree_frame_sink_) {
4265 evicted_ui_resources_.insert(uid);
4266 return;
4267 }
4268
4269 viz::ResourceFormat format;
4270 switch (bitmap.GetFormat()) {
4271 case UIResourceBitmap::RGBA8:
4272 if (layer_tree_frame_sink_->context_provider()) {
4273 const gpu::Capabilities& caps =
4274 layer_tree_frame_sink_->context_provider()->ContextCapabilities();
4275 format = viz::PlatformColor::BestSupportedTextureFormat(caps);
4276 } else {
4277 format = viz::RGBA_8888;
4278 }
4279 break;
4280 case UIResourceBitmap::ALPHA_8:
4281 format = viz::ALPHA_8;
4282 break;
4283 case UIResourceBitmap::ETC1:
4284 format = viz::ETC1;
4285 break;
4286 }
4287
4288 const gfx::Size source_size = bitmap.GetSize();
4289 gfx::Size upload_size = bitmap.GetSize();
4290 bool scaled = false;
4291 // UIResources are assumed to be rastered in SRGB.
4292 const gfx::ColorSpace& color_space = gfx::ColorSpace::CreateSRGB();
4293
4294 if (source_size.width() > max_texture_size_ ||
4295 source_size.height() > max_texture_size_) {
4296 // Must resize the bitmap to fit within the max texture size.
4297 scaled = true;
4298 int edge = std::max(source_size.width(), source_size.height());
4299 float scale = static_cast<float>(max_texture_size_ - 1) / edge;
4300 DCHECK_LT(scale, 1.f);
4301 upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale);
4302 }
4303
4304 // For gpu compositing, a SharedImage mailbox will be allocated and the
4305 // UIResource will be uploaded into it.
4306 gpu::Mailbox mailbox;
4307 uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY;
4308 // For gpu compositing, we also calculate the GL texture target.
4309 // TODO(ericrk): Remove references to GL from this code.
4310 GLenum texture_target = GL_TEXTURE_2D;
4311 // For software compositing, shared memory will be allocated and the
4312 // UIResource will be copied into it.
4313 base::MappedReadOnlyRegion shm;
4314 viz::SharedBitmapId shared_bitmap_id;
4315 bool overlay_candidate = false;
4316
4317 if (layer_tree_frame_sink_->context_provider()) {
4318 viz::ContextProvider* context_provider =
4319 layer_tree_frame_sink_->context_provider();
4320 const auto& caps = context_provider->ContextCapabilities();
4321 overlay_candidate =
4322 settings_.resource_settings.use_gpu_memory_buffer_resources &&
4323 caps.texture_storage_image &&
4324 viz::IsGpuMemoryBufferFormatSupported(format);
4325 if (overlay_candidate) {
4326 shared_image_usage |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
4327 texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT,
4328 BufferFormat(format), caps);
4329 }
4330 } else {
4331 shm = viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format);
4332 shared_bitmap_id = viz::SharedBitmap::GenerateId();
4333 }
4334
4335 if (!scaled) {
4336 // If not scaled, we can copy the pixels 1:1 from the source bitmap to our
4337 // destination backing of a texture or shared bitmap.
4338 if (layer_tree_frame_sink_->context_provider()) {
4339 viz::ContextProvider* context_provider =
4340 layer_tree_frame_sink_->context_provider();
4341 auto* sii = context_provider->SharedImageInterface();
4342 mailbox = sii->CreateSharedImage(
4343 format, upload_size, color_space, kTopLeft_GrSurfaceOrigin,
4344 kPremul_SkAlphaType, shared_image_usage,
4345 base::span<const uint8_t>(bitmap.GetPixels(), bitmap.SizeInBytes()));
4346 } else {
4347 DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8);
4348 SkImageInfo src_info =
4349 SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(source_size));
4350 SkImageInfo dst_info =
4351 SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size));
4352
4353 sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(
4354 dst_info, shm.mapping.memory(), dst_info.minRowBytes());
4355 surface->getCanvas()->writePixels(
4356 src_info, const_cast<uint8_t*>(bitmap.GetPixels()),
4357 bitmap.row_bytes(), 0, 0);
4358 }
4359 } else {
4360 // Only support auto-resizing for N32 textures (since this is primarily for
4361 // scrollbars). Users of other types need to ensure they are not too big.
4362 DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8);
4363
4364 float canvas_scale_x =
4365 upload_size.width() / static_cast<float>(source_size.width());
4366 float canvas_scale_y =
4367 upload_size.height() / static_cast<float>(source_size.height());
4368
4369 // Uses N32Premul since that is what SkBitmap's allocN32Pixels makes, and we
4370 // only support the RGBA8 format here.
4371 SkImageInfo info =
4372 SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(source_size));
4373
4374 SkBitmap source_bitmap;
4375 source_bitmap.setInfo(info, bitmap.row_bytes());
4376 source_bitmap.setPixels(const_cast<uint8_t*>(bitmap.GetPixels()));
4377
4378 // This applies the scale to draw the |bitmap| into |scaled_surface|. For
4379 // gpu compositing, we scale into a software bitmap-backed SkSurface here,
4380 // then upload from there into a texture. For software compositing, we scale
4381 // directly into the shared memory backing.
4382 sk_sp<SkSurface> scaled_surface;
4383 if (layer_tree_frame_sink_->context_provider()) {
4384 scaled_surface = SkSurface::MakeRasterN32Premul(upload_size.width(),
4385 upload_size.height());
4386 } else {
4387 SkImageInfo dst_info =
4388 SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size));
4389 scaled_surface = SkSurface::MakeRasterDirect(
4390 dst_info, shm.mapping.memory(), dst_info.minRowBytes());
4391 }
4392 SkCanvas* scaled_canvas = scaled_surface->getCanvas();
4393 scaled_canvas->scale(canvas_scale_x, canvas_scale_y);
4394 // The |canvas_scale_x| and |canvas_scale_y| may have some floating point
4395 // error for large enough values, causing pixels on the edge to be not
4396 // fully filled by drawBitmap(), so we ensure they start empty. (See
4397 // crbug.com/642011 for an example.)
4398 scaled_canvas->clear(SK_ColorTRANSPARENT);
4399 scaled_canvas->drawBitmap(source_bitmap, 0, 0);
4400
4401 if (layer_tree_frame_sink_->context_provider()) {
4402 SkPixmap pixmap;
4403 scaled_surface->peekPixels(&pixmap);
4404 viz::ContextProvider* context_provider =
4405 layer_tree_frame_sink_->context_provider();
4406 auto* sii = context_provider->SharedImageInterface();
4407 mailbox = sii->CreateSharedImage(
4408 format, upload_size, color_space, kTopLeft_GrSurfaceOrigin,
4409 kPremul_SkAlphaType, shared_image_usage,
4410 base::span<const uint8_t>(
4411 reinterpret_cast<const uint8_t*>(pixmap.addr()),
4412 pixmap.computeByteSize()));
4413 }
4414 }
4415
4416 // Once the backing has the UIResource inside it, we have to prepare it for
4417 // export to the display compositor via ImportResource(). For gpu compositing,
4418 // this requires a Mailbox+SyncToken as well. For software compositing, the
4419 // SharedBitmapId must be notified to the LayerTreeFrameSink. The
4420 // OnUIResourceReleased() method will be called once the resource is deleted
4421 // and the display compositor is no longer using it, to free the memory
4422 // allocated in this method above.
4423 viz::TransferableResource transferable;
4424 if (layer_tree_frame_sink_->context_provider()) {
4425 gpu::SyncToken sync_token = layer_tree_frame_sink_->context_provider()
4426 ->SharedImageInterface()
4427 ->GenUnverifiedSyncToken();
4428
4429 transferable = viz::TransferableResource::MakeGL(
4430 mailbox, GL_LINEAR, texture_target, sync_token, upload_size,
4431 overlay_candidate);
4432 transferable.format = format;
4433 } else {
4434 layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(shm.region),
4435 shared_bitmap_id);
4436 transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id,
4437 upload_size, format);
4438 }
4439 transferable.color_space = color_space;
4440 id = resource_provider_.ImportResource(
4441 transferable,
4442 // The OnUIResourceReleased method is bound with a WeakPtr, but the
4443 // resource backing will be deleted when the LayerTreeFrameSink is
4444 // removed before shutdown, so nothing leaks if the WeakPtr is
4445 // invalidated.
4446 viz::SingleReleaseCallback::Create(base::BindOnce(
4447 &LayerTreeHostImpl::OnUIResourceReleased, AsWeakPtr(), uid)));
4448
4449 UIResourceData data;
4450 data.opaque = bitmap.GetOpaque();
4451 data.format = format;
4452 data.shared_bitmap_id = shared_bitmap_id;
4453 data.shared_mapping = std::move(shm.mapping);
4454 data.mailbox = mailbox;
4455 data.resource_id_for_export = id;
4456 ui_resource_map_[uid] = std::move(data);
4457
4458 MarkUIResourceNotEvicted(uid);
4459 }
4460
DeleteUIResource(UIResourceId uid)4461 void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) {
4462 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
4463 "LayerTreeHostImpl::DeleteUIResource");
4464 auto it = ui_resource_map_.find(uid);
4465 if (it != ui_resource_map_.end()) {
4466 UIResourceData& data = it->second;
4467 viz::ResourceId id = data.resource_id_for_export;
4468 // Move the |data| to |deleted_ui_resources_| before removing it from the
4469 // viz::ClientResourceProvider, so that the ReleaseCallback can see it
4470 // there.
4471 deleted_ui_resources_[uid] = std::move(data);
4472 ui_resource_map_.erase(it);
4473
4474 resource_provider_.RemoveImportedResource(id);
4475 }
4476 MarkUIResourceNotEvicted(uid);
4477 }
4478
DeleteUIResourceBacking(UIResourceData data,const gpu::SyncToken & sync_token)4479 void LayerTreeHostImpl::DeleteUIResourceBacking(
4480 UIResourceData data,
4481 const gpu::SyncToken& sync_token) {
4482 // Resources are either software or gpu backed, not both.
4483 DCHECK(!(data.shared_mapping.IsValid() && !data.mailbox.IsZero()));
4484 if (data.shared_mapping.IsValid())
4485 layer_tree_frame_sink_->DidDeleteSharedBitmap(data.shared_bitmap_id);
4486 if (!data.mailbox.IsZero()) {
4487 auto* sii =
4488 layer_tree_frame_sink_->context_provider()->SharedImageInterface();
4489 sii->DestroySharedImage(sync_token, data.mailbox);
4490 }
4491 // |data| goes out of scope and deletes anything it owned.
4492 }
4493
OnUIResourceReleased(UIResourceId uid,const gpu::SyncToken & sync_token,bool lost)4494 void LayerTreeHostImpl::OnUIResourceReleased(UIResourceId uid,
4495 const gpu::SyncToken& sync_token,
4496 bool lost) {
4497 auto it = deleted_ui_resources_.find(uid);
4498 if (it == deleted_ui_resources_.end()) {
4499 // Backing was already deleted, eg if the context was lost.
4500 return;
4501 }
4502 UIResourceData& data = it->second;
4503 // We don't recycle backings here, so |lost| is not relevant, we always delete
4504 // them.
4505 DeleteUIResourceBacking(std::move(data), sync_token);
4506 deleted_ui_resources_.erase(it);
4507 }
4508
ClearUIResources()4509 void LayerTreeHostImpl::ClearUIResources() {
4510 for (auto& pair : ui_resource_map_) {
4511 UIResourceId uid = pair.first;
4512 UIResourceData& data = pair.second;
4513 resource_provider_.RemoveImportedResource(data.resource_id_for_export);
4514 // Immediately drop the backing instead of waiting for the resource to be
4515 // returned from the ResourceProvider, as this is called in cases where the
4516 // ability to clean up the backings will go away (context loss, shutdown).
4517 DeleteUIResourceBacking(std::move(data), gpu::SyncToken());
4518 // This resource is not deleted, and its |uid| is still valid, so it moves
4519 // to the evicted list, not the |deleted_ui_resources_| set. Also, its
4520 // backing is gone, so it would not belong in |deleted_ui_resources_|.
4521 evicted_ui_resources_.insert(uid);
4522 }
4523 ui_resource_map_.clear();
4524 for (auto& pair : deleted_ui_resources_) {
4525 UIResourceData& data = pair.second;
4526 // Immediately drop the backing instead of waiting for the resource to be
4527 // returned from the ResourceProvider, as this is called in cases where the
4528 // ability to clean up the backings will go away (context loss, shutdown).
4529 DeleteUIResourceBacking(std::move(data), gpu::SyncToken());
4530 }
4531 deleted_ui_resources_.clear();
4532 }
4533
EvictAllUIResources()4534 void LayerTreeHostImpl::EvictAllUIResources() {
4535 if (ui_resource_map_.empty())
4536 return;
4537 while (!ui_resource_map_.empty()) {
4538 UIResourceId uid = ui_resource_map_.begin()->first;
4539 DeleteUIResource(uid);
4540 evicted_ui_resources_.insert(uid);
4541 }
4542 client_->SetNeedsCommitOnImplThread();
4543 client_->OnCanDrawStateChanged(CanDraw());
4544 client_->RenewTreePriority();
4545 }
4546
ResourceIdForUIResource(UIResourceId uid) const4547 viz::ResourceId LayerTreeHostImpl::ResourceIdForUIResource(
4548 UIResourceId uid) const {
4549 auto iter = ui_resource_map_.find(uid);
4550 if (iter != ui_resource_map_.end())
4551 return iter->second.resource_id_for_export;
4552 return viz::kInvalidResourceId;
4553 }
4554
IsUIResourceOpaque(UIResourceId uid) const4555 bool LayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) const {
4556 auto iter = ui_resource_map_.find(uid);
4557 DCHECK(iter != ui_resource_map_.end());
4558 return iter->second.opaque;
4559 }
4560
EvictedUIResourcesExist() const4561 bool LayerTreeHostImpl::EvictedUIResourcesExist() const {
4562 return !evicted_ui_resources_.empty();
4563 }
4564
MarkUIResourceNotEvicted(UIResourceId uid)4565 void LayerTreeHostImpl::MarkUIResourceNotEvicted(UIResourceId uid) {
4566 auto found_in_evicted = evicted_ui_resources_.find(uid);
4567 if (found_in_evicted == evicted_ui_resources_.end())
4568 return;
4569 evicted_ui_resources_.erase(found_in_evicted);
4570 if (evicted_ui_resources_.empty())
4571 client_->OnCanDrawStateChanged(CanDraw());
4572 }
4573
ScheduleMicroBenchmark(std::unique_ptr<MicroBenchmarkImpl> benchmark)4574 void LayerTreeHostImpl::ScheduleMicroBenchmark(
4575 std::unique_ptr<MicroBenchmarkImpl> benchmark) {
4576 micro_benchmark_controller_.ScheduleRun(std::move(benchmark));
4577 }
4578
InsertSwapPromiseMonitor(SwapPromiseMonitor * monitor)4579 void LayerTreeHostImpl::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
4580 swap_promise_monitor_.insert(monitor);
4581 }
4582
RemoveSwapPromiseMonitor(SwapPromiseMonitor * monitor)4583 void LayerTreeHostImpl::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
4584 swap_promise_monitor_.erase(monitor);
4585 }
4586
NotifySwapPromiseMonitorsOfSetNeedsRedraw()4587 void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfSetNeedsRedraw() {
4588 auto it = swap_promise_monitor_.begin();
4589 for (; it != swap_promise_monitor_.end(); it++)
4590 (*it)->OnSetNeedsRedrawOnImpl();
4591 }
4592
IsElementInPropertyTrees(ElementId element_id,ElementListType list_type) const4593 bool LayerTreeHostImpl::IsElementInPropertyTrees(
4594 ElementId element_id,
4595 ElementListType list_type) const {
4596 if (list_type == ElementListType::ACTIVE)
4597 return active_tree() && active_tree()->IsElementInPropertyTree(element_id);
4598
4599 return (pending_tree() &&
4600 pending_tree()->IsElementInPropertyTree(element_id)) ||
4601 (recycle_tree() &&
4602 recycle_tree()->IsElementInPropertyTree(element_id));
4603 }
4604
SetMutatorsNeedCommit()4605 void LayerTreeHostImpl::SetMutatorsNeedCommit() {}
4606
SetMutatorsNeedRebuildPropertyTrees()4607 void LayerTreeHostImpl::SetMutatorsNeedRebuildPropertyTrees() {}
4608
SetTreeLayerScrollOffsetMutated(ElementId element_id,LayerTreeImpl * tree,const gfx::ScrollOffset & scroll_offset)4609 void LayerTreeHostImpl::SetTreeLayerScrollOffsetMutated(
4610 ElementId element_id,
4611 LayerTreeImpl* tree,
4612 const gfx::ScrollOffset& scroll_offset) {
4613 if (!tree)
4614 return;
4615
4616 PropertyTrees* property_trees = tree->property_trees();
4617 DCHECK_EQ(1u,
4618 property_trees->element_id_to_scroll_node_index.count(element_id));
4619 const int scroll_node_index =
4620 property_trees->element_id_to_scroll_node_index[element_id];
4621 property_trees->scroll_tree.OnScrollOffsetAnimated(
4622 element_id, scroll_node_index, scroll_offset, tree);
4623 }
4624
SetNeedUpdateGpuRasterizationStatus()4625 void LayerTreeHostImpl::SetNeedUpdateGpuRasterizationStatus() {
4626 need_update_gpu_rasterization_status_ = true;
4627 }
4628
SetElementFilterMutated(ElementId element_id,ElementListType list_type,const FilterOperations & filters)4629 void LayerTreeHostImpl::SetElementFilterMutated(
4630 ElementId element_id,
4631 ElementListType list_type,
4632 const FilterOperations& filters) {
4633 if (list_type == ElementListType::ACTIVE) {
4634 active_tree()->SetFilterMutated(element_id, filters);
4635 } else {
4636 if (pending_tree())
4637 pending_tree()->SetFilterMutated(element_id, filters);
4638 if (recycle_tree())
4639 recycle_tree()->SetFilterMutated(element_id, filters);
4640 }
4641 }
4642
OnCustomPropertyMutated(ElementId element_id,const std::string & custom_property_name,PaintWorkletInput::PropertyValue custom_property_value)4643 void LayerTreeHostImpl::OnCustomPropertyMutated(
4644 ElementId element_id,
4645 const std::string& custom_property_name,
4646 PaintWorkletInput::PropertyValue custom_property_value) {
4647 paint_worklet_tracker_.OnCustomPropertyMutated(
4648 element_id, custom_property_name, std::move(custom_property_value));
4649 }
4650
SetElementBackdropFilterMutated(ElementId element_id,ElementListType list_type,const FilterOperations & backdrop_filters)4651 void LayerTreeHostImpl::SetElementBackdropFilterMutated(
4652 ElementId element_id,
4653 ElementListType list_type,
4654 const FilterOperations& backdrop_filters) {
4655 if (list_type == ElementListType::ACTIVE) {
4656 active_tree()->SetBackdropFilterMutated(element_id, backdrop_filters);
4657 } else {
4658 if (pending_tree())
4659 pending_tree()->SetBackdropFilterMutated(element_id, backdrop_filters);
4660 if (recycle_tree())
4661 recycle_tree()->SetBackdropFilterMutated(element_id, backdrop_filters);
4662 }
4663 }
4664
SetElementOpacityMutated(ElementId element_id,ElementListType list_type,float opacity)4665 void LayerTreeHostImpl::SetElementOpacityMutated(ElementId element_id,
4666 ElementListType list_type,
4667 float opacity) {
4668 if (list_type == ElementListType::ACTIVE) {
4669 active_tree()->SetOpacityMutated(element_id, opacity);
4670 } else {
4671 if (pending_tree())
4672 pending_tree()->SetOpacityMutated(element_id, opacity);
4673 if (recycle_tree())
4674 recycle_tree()->SetOpacityMutated(element_id, opacity);
4675 }
4676 }
4677
SetElementTransformMutated(ElementId element_id,ElementListType list_type,const gfx::Transform & transform)4678 void LayerTreeHostImpl::SetElementTransformMutated(
4679 ElementId element_id,
4680 ElementListType list_type,
4681 const gfx::Transform& transform) {
4682 if (list_type == ElementListType::ACTIVE) {
4683 active_tree()->SetTransformMutated(element_id, transform);
4684 } else {
4685 if (pending_tree())
4686 pending_tree()->SetTransformMutated(element_id, transform);
4687 if (recycle_tree())
4688 recycle_tree()->SetTransformMutated(element_id, transform);
4689 }
4690 }
4691
SetElementScrollOffsetMutated(ElementId element_id,ElementListType list_type,const gfx::ScrollOffset & scroll_offset)4692 void LayerTreeHostImpl::SetElementScrollOffsetMutated(
4693 ElementId element_id,
4694 ElementListType list_type,
4695 const gfx::ScrollOffset& scroll_offset) {
4696 if (list_type == ElementListType::ACTIVE) {
4697 SetTreeLayerScrollOffsetMutated(element_id, active_tree(), scroll_offset);
4698 ShowScrollbarsForImplScroll(element_id);
4699 } else {
4700 SetTreeLayerScrollOffsetMutated(element_id, pending_tree(), scroll_offset);
4701 SetTreeLayerScrollOffsetMutated(element_id, recycle_tree(), scroll_offset);
4702 }
4703 }
4704
ElementIsAnimatingChanged(const PropertyToElementIdMap & element_id_map,ElementListType list_type,const PropertyAnimationState & mask,const PropertyAnimationState & state)4705 void LayerTreeHostImpl::ElementIsAnimatingChanged(
4706 const PropertyToElementIdMap& element_id_map,
4707 ElementListType list_type,
4708 const PropertyAnimationState& mask,
4709 const PropertyAnimationState& state) {
4710 LayerTreeImpl* tree =
4711 list_type == ElementListType::ACTIVE ? active_tree() : pending_tree();
4712 // TODO(wkorman): Explore enabling DCHECK in ElementIsAnimatingChanged()
4713 // below. Currently enabling causes batch of unit test failures.
4714 if (tree && tree->property_trees()->ElementIsAnimatingChanged(
4715 element_id_map, mask, state, false))
4716 tree->set_needs_update_draw_properties();
4717 }
4718
AnimationScalesChanged(ElementId element_id,ElementListType list_type,float maximum_scale,float starting_scale)4719 void LayerTreeHostImpl::AnimationScalesChanged(ElementId element_id,
4720 ElementListType list_type,
4721 float maximum_scale,
4722 float starting_scale) {
4723 if (LayerTreeImpl* tree = list_type == ElementListType::ACTIVE
4724 ? active_tree()
4725 : pending_tree()) {
4726 tree->property_trees()->AnimationScalesChanged(element_id, maximum_scale,
4727 starting_scale);
4728 }
4729 }
4730
ScrollOffsetAnimationFinished()4731 void LayerTreeHostImpl::ScrollOffsetAnimationFinished() {
4732 if (input_delegate_)
4733 input_delegate_->ScrollOffsetAnimationFinished();
4734 }
4735
NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state,ElementListType tree_type)4736 void LayerTreeHostImpl::NotifyAnimationWorkletStateChange(
4737 AnimationWorkletMutationState state,
4738 ElementListType tree_type) {
4739 client_->NotifyAnimationWorkletStateChange(state, tree_type);
4740 if (state != AnimationWorkletMutationState::CANCELED) {
4741 // We have at least one active worklet animation. We need to request a new
4742 // frame to keep the animation ticking.
4743 SetNeedsOneBeginImplFrame();
4744 if (state == AnimationWorkletMutationState::COMPLETED_WITH_UPDATE &&
4745 tree_type == ElementListType::ACTIVE) {
4746 SetNeedsRedraw();
4747 }
4748 }
4749 }
4750
GetScrollOffsetForAnimation(ElementId element_id) const4751 gfx::ScrollOffset LayerTreeHostImpl::GetScrollOffsetForAnimation(
4752 ElementId element_id) const {
4753 if (active_tree()) {
4754 return active_tree()->property_trees()->scroll_tree.current_scroll_offset(
4755 element_id);
4756 }
4757
4758 return gfx::ScrollOffset();
4759 }
4760
SupportsImplScrolling() const4761 bool LayerTreeHostImpl::SupportsImplScrolling() const {
4762 // Supported in threaded mode.
4763 return task_runner_provider_->HasImplThread();
4764 }
4765
CommitToActiveTree() const4766 bool LayerTreeHostImpl::CommitToActiveTree() const {
4767 return settings_.commit_to_active_tree;
4768 }
4769
SetContextVisibility(bool is_visible)4770 void LayerTreeHostImpl::SetContextVisibility(bool is_visible) {
4771 if (!layer_tree_frame_sink_)
4772 return;
4773
4774 // Update the compositor context. If we are already in the correct visibility
4775 // state, skip. This can happen if we transition invisible/visible rapidly,
4776 // before we get a chance to go invisible in NotifyAllTileTasksComplete.
4777 auto* compositor_context = layer_tree_frame_sink_->context_provider();
4778 if (compositor_context && is_visible != !!compositor_context_visibility_) {
4779 if (is_visible) {
4780 compositor_context_visibility_ =
4781 compositor_context->CacheController()->ClientBecameVisible();
4782 } else {
4783 compositor_context->CacheController()->ClientBecameNotVisible(
4784 std::move(compositor_context_visibility_));
4785 }
4786 }
4787
4788 // Update the worker context. If we are already in the correct visibility
4789 // state, skip. This can happen if we transition invisible/visible rapidly,
4790 // before we get a chance to go invisible in NotifyAllTileTasksComplete.
4791 auto* worker_context = layer_tree_frame_sink_->worker_context_provider();
4792 if (worker_context && is_visible != !!worker_context_visibility_) {
4793 viz::RasterContextProvider::ScopedRasterContextLock hold(worker_context);
4794 if (is_visible) {
4795 worker_context_visibility_ =
4796 worker_context->CacheController()->ClientBecameVisible();
4797 } else {
4798 worker_context->CacheController()->ClientBecameNotVisible(
4799 std::move(worker_context_visibility_));
4800 }
4801 }
4802 }
4803
ShowScrollbarsForImplScroll(ElementId element_id)4804 void LayerTreeHostImpl::ShowScrollbarsForImplScroll(ElementId element_id) {
4805 if (settings_.scrollbar_flash_after_any_scroll_update) {
4806 FlashAllScrollbars(true);
4807 return;
4808 }
4809 if (!element_id)
4810 return;
4811 if (ScrollbarAnimationController* animation_controller =
4812 ScrollbarAnimationControllerForElementId(element_id))
4813 animation_controller->DidScrollUpdate();
4814 }
4815
InitializeUkm(std::unique_ptr<ukm::UkmRecorder> recorder)4816 void LayerTreeHostImpl::InitializeUkm(
4817 std::unique_ptr<ukm::UkmRecorder> recorder) {
4818 DCHECK(!ukm_manager_);
4819 ukm_manager_ = std::make_unique<UkmManager>(std::move(recorder));
4820 frame_trackers_.SetUkmManager(ukm_manager_.get());
4821 compositor_frame_reporting_controller_->SetUkmManager(ukm_manager_.get());
4822 }
4823
SetActiveURL(const GURL & url,ukm::SourceId source_id)4824 void LayerTreeHostImpl::SetActiveURL(const GURL& url, ukm::SourceId source_id) {
4825 tile_manager_.set_active_url(url);
4826 has_observed_first_scroll_delay_ = false;
4827 // The active tree might still be from content for the previous page when the
4828 // recorder is updated here, since new content will be pushed with the next
4829 // main frame. But we should only get a few impl frames wrong here in that
4830 // case. Also, since checkerboard stats are only recorded with user
4831 // interaction, it must be in progress when the navigation commits for this
4832 // case to occur.
4833 if (ukm_manager_) {
4834 // The source id has already been associated to the URL.
4835 ukm_manager_->SetSourceId(source_id);
4836 }
4837 total_frame_counter_.Reset();
4838 dropped_frame_counter_.Reset();
4839 is_measuring_smoothness_ = false;
4840 }
4841
SetUkmSmoothnessDestination(base::WritableSharedMemoryMapping ukm_smoothness_data)4842 void LayerTreeHostImpl::SetUkmSmoothnessDestination(
4843 base::WritableSharedMemoryMapping ukm_smoothness_data) {
4844 ukm_smoothness_mapping_ = std::move(ukm_smoothness_data);
4845 dropped_frame_counter_.SetUkmSmoothnessDestination(
4846 ukm_smoothness_mapping_.GetMemoryAs<UkmSmoothnessDataShared>());
4847 }
4848
AllocateLocalSurfaceId()4849 void LayerTreeHostImpl::AllocateLocalSurfaceId() {
4850 child_local_surface_id_allocator_.GenerateId();
4851 }
4852
RequestBeginFrameForAnimatedImages()4853 void LayerTreeHostImpl::RequestBeginFrameForAnimatedImages() {
4854 SetNeedsOneBeginImplFrame();
4855 }
4856
RequestInvalidationForAnimatedImages()4857 void LayerTreeHostImpl::RequestInvalidationForAnimatedImages() {
4858 DCHECK_EQ(impl_thread_phase_, ImplThreadPhase::INSIDE_IMPL_FRAME);
4859
4860 // If we are animating an image, we want at least one draw of the active tree
4861 // before a new tree is activated.
4862 bool needs_first_draw_on_activation = true;
4863 client_->NeedsImplSideInvalidation(needs_first_draw_on_activation);
4864 }
4865
TakeEventsMetrics()4866 EventMetricsSet LayerTreeHostImpl::TakeEventsMetrics() {
4867 return EventMetricsSet(active_tree()->TakeEventsMetrics(),
4868 events_metrics_manager_.TakeSavedEventsMetrics());
4869 }
4870
AsWeakPtr()4871 base::WeakPtr<LayerTreeHostImpl> LayerTreeHostImpl::AsWeakPtr() {
4872 return weak_factory_.GetWeakPtr();
4873 }
4874
4875 } // namespace cc
4876