summaryrefslogtreecommitdiffstats
path: root/chromium/cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-06 12:48:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:33:43 +0000
commit7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (patch)
treefa14ba0ca8d2683ba2efdabd246dc9b18a1229c6 /chromium/cc
parent79b4f909db1049fca459c07cca55af56a9b54fe3 (diff)
BASELINE: Update Chromium to 84.0.4147.141
Change-Id: Ib85eb4cfa1cbe2b2b81e5022c8cad5c493969535 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc')
-rw-r--r--chromium/cc/BUILD.gn18
-rw-r--r--chromium/cc/animation/animation.cc32
-rw-r--r--chromium/cc/animation/animation.h4
-rw-r--r--chromium/cc/animation/animation_curve.cc2
-rw-r--r--chromium/cc/animation/animation_host.cc65
-rw-r--r--chromium/cc/animation/animation_host.h8
-rw-r--r--chromium/cc/animation/animation_host_unittest.cc81
-rw-r--r--chromium/cc/animation/animation_timeline.cc40
-rw-r--r--chromium/cc/animation/animation_timeline.h9
-rw-r--r--chromium/cc/animation/keyframe_effect.cc46
-rw-r--r--chromium/cc/animation/keyframe_effect.h2
-rw-r--r--chromium/cc/animation/scroll_offset_animation_curve.cc2
-rw-r--r--chromium/cc/animation/scroll_timeline.cc32
-rw-r--r--chromium/cc/animation/scroll_timeline.h5
-rw-r--r--chromium/cc/animation/timing_function.cc3
-rw-r--r--chromium/cc/animation/transform_operation.cc3
-rw-r--r--chromium/cc/animation/worklet_animation.cc3
-rw-r--r--chromium/cc/base/features.cc3
-rw-r--r--chromium/cc/base/features.h8
-rw-r--r--chromium/cc/base/list_container_helper.cc2
-rw-r--r--chromium/cc/base/reverse_spiral_iterator.cc2
-rw-r--r--chromium/cc/base/simple_enclosed_region.cc2
-rw-r--r--chromium/cc/base/spiral_iterator.cc2
-rw-r--r--chromium/cc/base/switches.cc9
-rw-r--r--chromium/cc/base/switches.h15
-rw-r--r--chromium/cc/base/tiling_data.cc2
-rw-r--r--chromium/cc/benchmarks/micro_benchmark.cc2
-rw-r--r--chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc20
-rw-r--r--chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h3
-rw-r--r--chromium/cc/debug/BUILD.gn2
-rw-r--r--chromium/cc/debug/debug_colors.cc27
-rw-r--r--chromium/cc/debug/debug_colors.h3
-rw-r--r--chromium/cc/debug/layer_tree_debug_state.cc7
-rw-r--r--chromium/cc/debug/layer_tree_debug_state.h2
-rw-r--r--chromium/cc/debug/picture_debug_util.cc1
-rw-r--r--chromium/cc/input/browser_controls_offset_manager.cc2
-rw-r--r--chromium/cc/input/browser_controls_offset_manager_unittest.cc1
-rw-r--r--chromium/cc/input/input_handler.h23
-rw-r--r--chromium/cc/input/layer_selection_bound.cc1
-rw-r--r--chromium/cc/input/main_thread_scrolling_reason.cc6
-rw-r--r--chromium/cc/input/main_thread_scrolling_reason.h11
-rw-r--r--chromium/cc/input/main_thread_scrolling_reason_unittest.cc3
-rw-r--r--chromium/cc/input/page_scale_animation.cc2
-rw-r--r--chromium/cc/input/scroll_input_type.h20
-rw-r--r--chromium/cc/input/scroll_snap_data.cc3
-rw-r--r--chromium/cc/input/scroll_state.cc7
-rw-r--r--chromium/cc/input/scroll_state.h5
-rw-r--r--chromium/cc/input/scrollbar.h4
-rw-r--r--chromium/cc/input/scrollbar_controller.cc134
-rw-r--r--chromium/cc/input/scrollbar_controller.h23
-rw-r--r--chromium/cc/ipc/cc_param_traits_macros.h10
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.cc40
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.h5
-rw-r--r--chromium/cc/layers/layer.cc24
-rw-r--r--chromium/cc/layers/layer.h22
-rw-r--r--chromium/cc/layers/layer_impl.cc34
-rw-r--r--chromium/cc/layers/layer_impl.h13
-rw-r--r--chromium/cc/layers/layer_perftest.cc3
-rw-r--r--chromium/cc/layers/layer_unittest.cc9
-rw-r--r--chromium/cc/layers/painted_overlay_scrollbar_layer.cc11
-rw-r--r--chromium/cc/layers/painted_overlay_scrollbar_layer.h10
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer.cc10
-rw-r--r--chromium/cc/layers/painted_scrollbar_layer.h5
-rw-r--r--chromium/cc/layers/picture_layer.cc48
-rw-r--r--chromium/cc/layers/picture_layer_impl.cc332
-rw-r--r--chromium/cc/layers/picture_layer_impl.h43
-rw-r--r--chromium/cc/layers/picture_layer_impl_unittest.cc386
-rw-r--r--chromium/cc/layers/recording_source.h1
-rw-r--r--chromium/cc/layers/render_surface_impl.cc6
-rw-r--r--chromium/cc/layers/render_surface_impl.h1
-rw-r--r--chromium/cc/layers/scrollbar_layer_base.cc51
-rw-r--r--chromium/cc/layers/scrollbar_layer_base.h8
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.cc15
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.h8
-rw-r--r--chromium/cc/layers/solid_color_scrollbar_layer.cc28
-rw-r--r--chromium/cc/layers/solid_color_scrollbar_layer.h6
-rw-r--r--chromium/cc/layers/surface_layer.cc3
-rw-r--r--chromium/cc/layers/video_layer_impl.cc2
-rw-r--r--chromium/cc/layers/viewport.cc2
-rw-r--r--chromium/cc/metrics/compositor_frame_reporter.cc554
-rw-r--r--chromium/cc/metrics/compositor_frame_reporter.h125
-rw-r--r--chromium/cc/metrics/compositor_frame_reporter_unittest.cc316
-rw-r--r--chromium/cc/metrics/compositor_frame_reporting_controller.cc80
-rw-r--r--chromium/cc/metrics/compositor_frame_reporting_controller.h25
-rw-r--r--chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc508
-rw-r--r--chromium/cc/metrics/compositor_timing_history.cc10
-rw-r--r--chromium/cc/metrics/compositor_timing_history.h4
-rw-r--r--chromium/cc/metrics/event_metrics.cc54
-rw-r--r--chromium/cc/metrics/event_metrics.h25
-rw-r--r--chromium/cc/metrics/events_metrics_manager.cc30
-rw-r--r--chromium/cc/metrics/events_metrics_manager.h13
-rw-r--r--chromium/cc/metrics/events_metrics_manager_unittest.cc27
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics.cc371
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics.h140
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics_unittest.cc12
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker.cc728
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker.h250
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker_collection.cc316
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker_collection.h156
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker_unittest.cc134
-rw-r--r--chromium/cc/metrics/latency_ukm_reporter.cc2
-rw-r--r--chromium/cc/metrics/latency_ukm_reporter.h2
-rw-r--r--chromium/cc/metrics/lcd_text_metrics_reporter.cc102
-rw-r--r--chromium/cc/metrics/lcd_text_metrics_reporter.h47
-rw-r--r--chromium/cc/metrics/throughput_ukm_reporter.h2
-rw-r--r--chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc3
-rw-r--r--chromium/cc/mojom/BUILD.gn26
-rw-r--r--chromium/cc/mojom/overscroll_behavior.mojom8
-rw-r--r--chromium/cc/paint/display_item_list.cc197
-rw-r--r--chromium/cc/paint/display_item_list.h78
-rw-r--r--chromium/cc/paint/display_item_list_unittest.cc51
-rw-r--r--chromium/cc/paint/element_id.h2
-rw-r--r--chromium/cc/paint/image_transfer_cache_entry_unittest.cc3
-rw-r--r--chromium/cc/paint/oop_pixeltest.cc257
-rw-r--r--chromium/cc/paint/paint_cache.cc6
-rw-r--r--chromium/cc/paint/paint_cache.h5
-rw-r--r--chromium/cc/paint/paint_filter.cc4
-rw-r--r--chromium/cc/paint/paint_filter.h12
-rw-r--r--chromium/cc/paint/paint_image.cc10
-rw-r--r--chromium/cc/paint/paint_image.h7
-rw-r--r--chromium/cc/paint/paint_image_builder.h7
-rw-r--r--chromium/cc/paint/paint_image_generator.cc1
-rw-r--r--chromium/cc/paint/paint_op_buffer.cc24
-rw-r--r--chromium/cc/paint/paint_op_buffer_unittest.cc52
-rw-r--r--chromium/cc/paint/paint_op_reader.cc4
-rw-r--r--chromium/cc/paint/paint_recorder.cc4
-rw-r--r--chromium/cc/paint/paint_recorder.h3
-rw-r--r--chromium/cc/paint/shader_transfer_cache_entry.cc2
-rw-r--r--chromium/cc/paint/texture_backing.h3
-rw-r--r--chromium/cc/paint/transfer_cache_entry.cc2
-rw-r--r--chromium/cc/paint/transfer_cache_serialize_helper.cc2
-rw-r--r--chromium/cc/raster/lcd_text_disallowed_reason.cc39
-rw-r--r--chromium/cc/raster/lcd_text_disallowed_reason.h37
-rw-r--r--chromium/cc/raster/raster_buffer_provider_unittest.cc3
-rw-r--r--chromium/cc/raster/raster_source.cc16
-rw-r--r--chromium/cc/raster/raster_source.h1
-rw-r--r--chromium/cc/raster/raster_source_unittest.cc5
-rw-r--r--chromium/cc/raster/task.cc3
-rw-r--r--chromium/cc/raster/tile_task.cc2
-rw-r--r--chromium/cc/resources/ui_resource_bitmap.cc3
-rw-r--r--chromium/cc/scheduler/begin_frame_tracker.cc2
-rw-r--r--chromium/cc/scheduler/begin_frame_tracker.h2
-rw-r--r--chromium/cc/scheduler/scheduler.cc9
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.cc13
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.h6
-rw-r--r--chromium/cc/scheduler/scheduler_unittest.cc44
-rw-r--r--chromium/cc/tiles/image_decode_cache_utils.cc2
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.cc2
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_utils.h1
-rw-r--r--chromium/cc/tiles/tile.cc5
-rw-r--r--chromium/cc/tiles/tile.h5
-rw-r--r--chromium/cc/tiles/tile_manager_unittest.cc1
-rw-r--r--chromium/cc/trees/draw_properties_unittest.cc143
-rw-r--r--chromium/cc/trees/draw_property_utils.cc42
-rw-r--r--chromium/cc/trees/frame_rate_estimator.cc84
-rw-r--r--chromium/cc/trees/frame_rate_estimator.h48
-rw-r--r--chromium/cc/trees/frame_rate_estimator_unittest.cc73
-rw-r--r--chromium/cc/trees/latency_info_swap_promise.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host.cc10
-rw-r--r--chromium/cc/trees/layer_tree_host.h3
-rw-r--r--chromium/cc/trees/layer_tree_host_client.h5
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc304
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.h80
-rw-r--r--chromium/cc/trees/layer_tree_host_impl_unittest.cc1945
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_blending.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_filters.cc115
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_masks.cc8
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc6
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_readback.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc11
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc6
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest.cc161
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_scroll.cc29
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc12
-rw-r--r--chromium/cc/trees/layer_tree_impl.h3
-rw-r--r--chromium/cc/trees/managed_memory_policy.cc2
-rw-r--r--chromium/cc/trees/mutator_host.h18
-rw-r--r--chromium/cc/trees/occlusion.cc1
-rw-r--r--chromium/cc/trees/occlusion_tracker.cc12
-rw-r--r--chromium/cc/trees/occlusion_tracker_unittest.cc88
-rw-r--r--chromium/cc/trees/property_animation_state.cc1
-rw-r--r--chromium/cc/trees/property_tree.cc16
-rw-r--r--chromium/cc/trees/property_tree.h5
-rw-r--r--chromium/cc/trees/property_tree_builder.cc11
-rw-r--r--chromium/cc/trees/property_tree_builder_unittest.cc179
-rw-r--r--chromium/cc/trees/property_tree_unittest.cc32
-rw-r--r--chromium/cc/trees/proxy_common.h2
-rw-r--r--chromium/cc/trees/proxy_impl.cc7
-rw-r--r--chromium/cc/trees/proxy_impl.h1
-rw-r--r--chromium/cc/trees/proxy_main.cc4
-rw-r--r--chromium/cc/trees/proxy_main.h1
-rw-r--r--chromium/cc/trees/scroll_node.cc8
-rw-r--r--chromium/cc/trees/scroll_node.h2
-rw-r--r--chromium/cc/trees/single_thread_proxy.cc5
-rw-r--r--chromium/cc/trees/single_thread_proxy.h1
-rw-r--r--chromium/cc/trees/swap_promise_monitor.cc4
-rw-r--r--chromium/cc/trees/tree_synchronizer.cc2
-rw-r--r--chromium/cc/trees/ukm_manager.cc8
-rw-r--r--chromium/cc/trees/ukm_manager.h4
200 files changed, 7020 insertions, 3349 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn
index 87888ce868a..deaca4f894b 100644
--- a/chromium/cc/BUILD.gn
+++ b/chromium/cc/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/sanitizers/sanitizers.gni")
import("//gpu/vulkan/features.gni")
+import("//skia/features.gni")
import("//cc/cc.gni")
@@ -42,7 +43,6 @@ cc_component("cc") {
"input/page_scale_animation.h",
"input/scroll_elasticity_helper.cc",
"input/scroll_elasticity_helper.h",
- "input/scroll_input_type.h",
"input/scroll_snap_data.cc",
"input/scroll_snap_data.h",
"input/scroll_state.cc",
@@ -161,10 +161,16 @@ cc_component("cc") {
"metrics/event_metrics.h",
"metrics/events_metrics_manager.cc",
"metrics/events_metrics_manager.h",
+ "metrics/frame_sequence_metrics.cc",
+ "metrics/frame_sequence_metrics.h",
"metrics/frame_sequence_tracker.cc",
"metrics/frame_sequence_tracker.h",
+ "metrics/frame_sequence_tracker_collection.cc",
+ "metrics/frame_sequence_tracker_collection.h",
"metrics/latency_ukm_reporter.cc",
"metrics/latency_ukm_reporter.h",
+ "metrics/lcd_text_metrics_reporter.cc",
+ "metrics/lcd_text_metrics_reporter.h",
"metrics/throughput_ukm_reporter.cc",
"metrics/throughput_ukm_reporter.h",
"metrics/video_playback_roughness_reporter.cc",
@@ -173,6 +179,8 @@ cc_component("cc") {
"raster/bitmap_raster_buffer_provider.h",
"raster/gpu_raster_buffer_provider.cc",
"raster/gpu_raster_buffer_provider.h",
+ "raster/lcd_text_disallowed_reason.cc",
+ "raster/lcd_text_disallowed_reason.h",
"raster/one_copy_raster_buffer_provider.cc",
"raster/one_copy_raster_buffer_provider.h",
"raster/paint_worklet_image_provider.cc",
@@ -306,6 +314,8 @@ cc_component("cc") {
"trees/effect_node.h",
"trees/frame_rate_counter.cc",
"trees/frame_rate_counter.h",
+ "trees/frame_rate_estimator.cc",
+ "trees/frame_rate_estimator.h",
"trees/image_animation_controller.cc",
"trees/image_animation_controller.h",
"trees/latency_info_swap_promise.cc",
@@ -699,6 +709,7 @@ cc_test("cc_unittests") {
"tiles/tile_priority_unittest.cc",
"trees/damage_tracker_unittest.cc",
"trees/draw_properties_unittest.cc",
+ "trees/frame_rate_estimator_unittest.cc",
"trees/image_animation_controller_unittest.cc",
"trees/layer_tree_frame_sink_unittest.cc",
"trees/layer_tree_host_impl_unittest.cc",
@@ -796,7 +807,6 @@ cc_test("cc_unittests") {
defines = []
if (is_fuchsia) {
- defines += [ "GL_NOT_ON_PLATFORM" ]
manifest = "//build/config/fuchsia/gfx_tests.cmx"
}
@@ -815,6 +825,10 @@ cc_test("cc_unittests") {
defines += [ "ENABLE_CC_VULKAN_TESTS" ]
}
}
+
+ if (skia_use_dawn) {
+ defines += [ "ENABLE_CC_DAWN_TESTS" ]
+ }
}
cc_test("cc_perftests") {
diff --git a/chromium/cc/animation/animation.cc b/chromium/cc/animation/animation.cc
index dec58b94a00..5c40eed8453 100644
--- a/chromium/cc/animation/animation.cc
+++ b/chromium/cc/animation/animation.cc
@@ -114,9 +114,35 @@ void Animation::PushPropertiesTo(Animation* animation_impl) {
keyframe_effect_->PushPropertiesTo(animation_impl->keyframe_effect_.get());
}
-void Animation::Tick(base::TimeTicks monotonic_time) {
- DCHECK(!monotonic_time.is_null());
- keyframe_effect_->Tick(monotonic_time);
+void Animation::Tick(base::TimeTicks tick_time) {
+ DCHECK(!IsWorkletAnimation());
+ if (IsScrollLinkedAnimation()) {
+ // blink::Animation uses its start time to calculate local time for each of
+ // its keyframes. However, in cc the start time is stored at the Keyframe
+ // level so we have to delegate the tick time to a lower level to calculate
+ // the local time.
+ // With ScrollTimeline, the start time of the animation is calculated
+ // differently i.e. it is not the current time at the moment of start.
+ // To deal with this the scroll timeline pauses the animation at its desired
+ // time and then ticks it which side-steps the start time altogether. See
+ // crbug.com/1076012 for alternative design choices considered for future
+ // improvement.
+ TickWithLocalTime(tick_time - base::TimeTicks());
+ } else {
+ DCHECK(!tick_time.is_null());
+ keyframe_effect_->Tick(tick_time);
+ }
+}
+
+void Animation::TickWithLocalTime(base::TimeDelta local_time) {
+ // TODO(yigu): KeyframeEffect should support ticking KeyframeModel
+ // directly without using Pause(). https://crbug.com/1076012.
+ keyframe_effect_->Pause(local_time);
+ keyframe_effect_->Tick(base::TimeTicks());
+}
+
+bool Animation::IsScrollLinkedAnimation() const {
+ return animation_timeline_ && animation_timeline_->IsScrollTimeline();
}
void Animation::UpdateState(bool start_ready_animations,
diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h
index 003215c61e4..7fa4136d591 100644
--- a/chromium/cc/animation/animation.h
+++ b/chromium/cc/animation/animation.h
@@ -106,7 +106,8 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> {
// Adds TIME_UPDATED event generated in the current frame to the given
// animation events.
virtual void TakeTimeUpdatedEvent(AnimationEvents* events) {}
- virtual void Tick(base::TimeTicks monotonic_time);
+ virtual void Tick(base::TimeTicks tick_time);
+ bool IsScrollLinkedAnimation() const;
void AddToTicking();
void RemoveFromTicking();
@@ -150,6 +151,7 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> {
explicit Animation(int id);
Animation(int id, std::unique_ptr<KeyframeEffect>);
virtual ~Animation();
+ void TickWithLocalTime(base::TimeDelta local_time);
AnimationHost* animation_host_;
AnimationTimeline* animation_timeline_;
diff --git a/chromium/cc/animation/animation_curve.cc b/chromium/cc/animation/animation_curve.cc
index b7c5891f7e4..1a46580f534 100644
--- a/chromium/cc/animation/animation_curve.cc
+++ b/chromium/cc/animation/animation_curve.cc
@@ -4,7 +4,7 @@
#include "cc/animation/animation_curve.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "cc/animation/scroll_offset_animation_curve.h"
namespace cc {
diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc
index ca3bfb8e707..1dfe39e66c9 100644
--- a/chromium/cc/animation/animation_host.cc
+++ b/chromium/cc/animation/animation_host.cc
@@ -46,19 +46,6 @@ AnimationWorkletMutationState ToAnimationWorkletMutationState(
}
}
-bool TickAnimationsIf(AnimationHost::AnimationsList animations,
- base::TimeTicks monotonic_time,
- bool (*predicate)(const Animation&)) {
- bool did_tick = false;
- for (auto& it : animations) {
- if (predicate(*it)) {
- it->Tick(monotonic_time);
- did_tick = true;
- }
- }
- return did_tick;
-}
-
} // namespace
std::unique_ptr<AnimationHost> AnimationHost::CreateMainInstance() {
@@ -305,6 +292,12 @@ void AnimationHost::PushPropertiesToImplThread(AnimationHost* host_impl) {
host_impl->main_thread_animations_count_ = main_thread_animations_count_;
host_impl->current_frame_had_raf_ = current_frame_had_raf_;
host_impl->next_frame_has_pending_raf_ = next_frame_has_pending_raf_;
+
+ // The pending info list is cleared in LayerTreeHostImpl::CommitComplete
+ // and should be empty when pushing properties.
+ DCHECK(host_impl->pending_throughput_tracker_infos_.empty());
+ host_impl->pending_throughput_tracker_infos_ =
+ TakePendingThroughputTrackerInfos();
}
scoped_refptr<ElementAnimations>
@@ -404,12 +397,17 @@ bool AnimationHost::TickAnimations(base::TimeTicks monotonic_time,
TRACE_EVENT_INSTANT0("cc", "NeedsTickAnimations", TRACE_EVENT_SCOPE_THREAD);
- // Worklet animations are ticked at a later stage. See above comment for
- // details.
- bool animated = TickAnimationsIf(ticking_animations_, monotonic_time,
- [](const Animation& animation) {
- return !animation.IsWorkletAnimation();
- });
+ bool animated = false;
+ for (auto& kv : id_to_timeline_map_) {
+ AnimationTimeline* timeline = kv.second.get();
+ if (timeline->IsScrollTimeline()) {
+ animated |= timeline->TickScrollLinkedAnimations(
+ ticking_animations_, scroll_tree, is_active_tree);
+ } else {
+ animated |= timeline->TickTimeLinkedAnimations(ticking_animations_,
+ monotonic_time);
+ }
+ }
// TODO(majidvp): At the moment we call this for both active and pending
// trees similar to other animations. However our final goal is to only call
@@ -431,10 +429,11 @@ void AnimationHost::TickScrollAnimations(base::TimeTicks monotonic_time,
}
void AnimationHost::TickWorkletAnimations() {
- TickAnimationsIf(ticking_animations_, base::TimeTicks(),
- [](const Animation& animation) {
- return animation.IsWorkletAnimation();
- });
+ for (auto& animation : ticking_animations_) {
+ if (!animation->IsWorkletAnimation())
+ continue;
+ animation->Tick(base::TimeTicks());
+ }
}
std::unique_ptr<MutatorInputState> AnimationHost::CollectWorkletAnimationsState(
@@ -805,4 +804,24 @@ bool AnimationHost::NextFrameHasPendingRAF() const {
return next_frame_has_pending_raf_;
}
+AnimationHost::PendingThroughputTrackerInfos
+AnimationHost::TakePendingThroughputTrackerInfos() {
+ PendingThroughputTrackerInfos infos =
+ std::move(pending_throughput_tracker_infos_);
+ pending_throughput_tracker_infos_ = {};
+ return infos;
+}
+
+void AnimationHost::StartThroughputTracking(
+ TrackedAnimationSequenceId sequence_id) {
+ pending_throughput_tracker_infos_.push_back({sequence_id, true});
+ SetNeedsPushProperties();
+}
+
+void AnimationHost::StopThroughputTracking(
+ TrackedAnimationSequenceId sequnece_id) {
+ pending_throughput_tracker_infos_.push_back({sequnece_id, false});
+ SetNeedsPushProperties();
+}
+
} // namespace cc
diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h
index 38a320ce134..de1ae6f8811 100644
--- a/chromium/cc/animation/animation_host.h
+++ b/chromium/cc/animation/animation_host.h
@@ -212,6 +212,12 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost,
bool HasCustomPropertyAnimations() const override;
bool CurrentFrameHadRAF() const override;
bool NextFrameHasPendingRAF() const override;
+ PendingThroughputTrackerInfos TakePendingThroughputTrackerInfos() override;
+
+ // Starts/stops throughput tracking represented by |sequence_id|.
+ void StartThroughputTracking(TrackedAnimationSequenceId sequence_id);
+ void StopThroughputTracking(TrackedAnimationSequenceId sequnece_id);
+
void SetAnimationCounts(size_t total_animations_count,
bool current_frame_had_raf,
bool next_frame_has_pending_raf);
@@ -268,6 +274,8 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost,
bool current_frame_had_raf_ = false;
bool next_frame_has_pending_raf_ = false;
+ PendingThroughputTrackerInfos pending_throughput_tracker_infos_;
+
base::WeakPtrFactory<AnimationHost> weak_factory_{this};
};
diff --git a/chromium/cc/animation/animation_host_unittest.cc b/chromium/cc/animation/animation_host_unittest.cc
index 0674937ce03..c2659983070 100644
--- a/chromium/cc/animation/animation_host_unittest.cc
+++ b/chromium/cc/animation/animation_host_unittest.cc
@@ -17,11 +17,11 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::_;
using ::testing::InvokeWithoutArgs;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
-using ::testing::_;
namespace cc {
namespace {
@@ -362,5 +362,84 @@ TEST_F(AnimationHostTest, LayerTreeMutatorUpdateReflectsScrollAnimations) {
false);
}
+TEST_F(AnimationHostTest, TickScrollLinkedAnimation) {
+ PropertyTrees property_trees;
+ property_trees.is_main_thread = false;
+ property_trees.is_active = true;
+ CreateScrollingNodeForElement(element_id_, &property_trees);
+
+ // Create scroll timeline that links scroll animation and scroll-linked
+ // animation together.
+ auto scroll_timeline = ScrollTimeline::Create(
+ element_id_, ScrollTimeline::ScrollDown, 0, 100, 1000);
+
+ int animation_id = 11;
+ // Create an animation that is bound to the scroll timeline.
+ scoped_refptr<Animation> animation = Animation::Create(animation_id);
+ host_impl_->AddAnimationTimeline(scroll_timeline);
+ scroll_timeline->AttachAnimation(animation);
+ animation->AddToTicking();
+ ASSERT_TRUE(animation->IsScrollLinkedAnimation());
+
+ animation->AttachElement(element_id_);
+
+ AddOpacityTransitionToAnimation(animation.get(), 1, .7f, .3f, true);
+ auto* keyframe_model = animation->GetKeyframeModel(TargetProperty::OPACITY);
+ EXPECT_EQ(keyframe_model->run_state(),
+ KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY);
+
+ auto& scroll_tree = property_trees.scroll_tree;
+ SetScrollOffset(&property_trees, element_id_, gfx::ScrollOffset(0, 20));
+ EXPECT_TRUE(host_impl_->TickAnimations(base::TimeTicks(),
+ property_trees.scroll_tree, false));
+
+ EXPECT_EQ(keyframe_model->run_state(), KeyframeModel::PAUSED);
+ double tick_time = (scroll_timeline->CurrentTime(scroll_tree, false).value() -
+ base::TimeTicks())
+ .InSecondsF();
+ EXPECT_EQ(tick_time, 0.2);
+
+ scroll_timeline->DetachAnimation(animation);
+ EXPECT_FALSE(host_impl_->TickAnimations(base::TimeTicks(),
+ property_trees.scroll_tree, false));
+}
+
+TEST_F(AnimationHostTest, ScrollTimelineOffsetUpdatedByScrollAnimation) {
+ client_.RegisterElementId(element_id_, ElementListType::ACTIVE);
+ client_impl_.RegisterElementId(element_id_, ElementListType::PENDING);
+ client_impl_.RegisterElementId(element_id_, ElementListType::ACTIVE);
+ host_impl_->AddAnimationTimeline(timeline_);
+
+ PropertyTrees property_trees;
+ property_trees.is_main_thread = false;
+ property_trees.is_active = true;
+ CreateScrollingNodeForElement(element_id_, &property_trees);
+
+ int animation_id = 11;
+ scoped_refptr<MockAnimation> mock_scroll_animation(
+ new MockAnimation(animation_id));
+ EXPECT_CALL(*mock_scroll_animation, Tick(_))
+ .WillOnce(InvokeWithoutArgs([&]() {
+ // Scroll to 20% of the max value.
+ SetScrollOffset(&property_trees, element_id_, gfx::ScrollOffset(0, 20));
+ }));
+
+ // Ensure scroll animation is ticking.
+ timeline_->AttachAnimation(mock_scroll_animation);
+ host_impl_->AddToTicking(mock_scroll_animation);
+
+ auto scroll_timeline = ScrollTimeline::Create(
+ element_id_, ScrollTimeline::ScrollDown, 0, 100, 1000);
+
+ host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree,
+ false);
+
+ double tick_time =
+ (scroll_timeline->CurrentTime(property_trees.scroll_tree, false).value() -
+ base::TimeTicks())
+ .InSecondsF();
+ EXPECT_EQ(tick_time, 0.2);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/animation/animation_timeline.cc b/chromium/cc/animation/animation_timeline.cc
index 766257ac075..d7067c5e235 100644
--- a/chromium/cc/animation/animation_timeline.cc
+++ b/chromium/cc/animation/animation_timeline.cc
@@ -8,6 +8,7 @@
#include "cc/animation/animation.h"
#include "cc/animation/animation_host.h"
+#include "cc/trees/property_tree.h"
namespace cc {
@@ -65,15 +66,6 @@ Animation* AnimationTimeline::GetAnimationById(int animation_id) const {
return f == id_to_animation_map_.end() ? nullptr : f->second.get();
}
-std::vector<Animation*> AnimationTimeline::GetAnimations() const {
- std::vector<Animation*> animations;
- animations.reserve(id_to_animation_map_.size());
-
- for (auto& kv : id_to_animation_map_)
- animations.push_back(kv.second.get());
- return animations;
-}
-
void AnimationTimeline::ClearAnimations() {
for (auto& kv : id_to_animation_map_)
EraseAnimation(kv.second);
@@ -82,6 +74,36 @@ void AnimationTimeline::ClearAnimations() {
SetNeedsPushProperties();
}
+bool AnimationTimeline::TickTimeLinkedAnimations(
+ const std::vector<scoped_refptr<Animation>>& ticking_animations,
+ base::TimeTicks monotonic_time) {
+ DCHECK(!IsScrollTimeline());
+
+ bool animated = false;
+ for (auto& animation : ticking_animations) {
+ if (animation->animation_timeline() != this)
+ continue;
+ // Worklet animations are ticked separately by AnimationHost.
+ if (animation->IsWorkletAnimation())
+ continue;
+
+ // Scroll-linked animations are ticked separately.
+ if (animation->IsScrollLinkedAnimation())
+ continue;
+
+ animation->Tick(monotonic_time);
+ animated = true;
+ }
+ return animated;
+}
+
+bool AnimationTimeline::TickScrollLinkedAnimations(
+ const std::vector<scoped_refptr<Animation>>& ticking_animations,
+ const ScrollTree& scroll_tree,
+ bool is_active_tree) {
+ return false;
+}
+
void AnimationTimeline::SetNeedsPushProperties() {
needs_push_properties_ = true;
if (animation_host_)
diff --git a/chromium/cc/animation/animation_timeline.h b/chromium/cc/animation/animation_timeline.h
index 9c266e1b93d..6ff994afa56 100644
--- a/chromium/cc/animation/animation_timeline.h
+++ b/chromium/cc/animation/animation_timeline.h
@@ -15,6 +15,7 @@ namespace cc {
class Animation;
class AnimationHost;
+class ScrollTree;
// An AnimationTimeline owns a group of Animations.
//
@@ -42,9 +43,15 @@ class CC_ANIMATION_EXPORT AnimationTimeline
void AttachAnimation(scoped_refptr<Animation> animation);
void DetachAnimation(scoped_refptr<Animation> animation);
- std::vector<Animation*> GetAnimations() const;
void ClearAnimations();
bool HasAnimation() const { return !id_to_animation_map_.empty(); }
+ bool TickTimeLinkedAnimations(
+ const std::vector<scoped_refptr<Animation>>& ticking_animations,
+ base::TimeTicks monotonic_time);
+ virtual bool TickScrollLinkedAnimations(
+ const std::vector<scoped_refptr<Animation>>& ticking_animations,
+ const ScrollTree& scroll_tree,
+ bool is_active_tree);
virtual void PushPropertiesTo(AnimationTimeline* timeline_impl);
virtual void ActivateTimeline() {}
diff --git a/chromium/cc/animation/keyframe_effect.cc b/chromium/cc/animation/keyframe_effect.cc
index 4c14471e845..5af52eb211b 100644
--- a/chromium/cc/animation/keyframe_effect.cc
+++ b/chromium/cc/animation/keyframe_effect.cc
@@ -168,7 +168,7 @@ void KeyframeEffect::RemoveFromTicking() {
is_ticking_ = false;
// Resetting last_tick_time_ here ensures that calling ::UpdateState
// before ::Animate doesn't start a keyframe model.
- last_tick_time_ = base::TimeTicks();
+ last_tick_time_ = base::nullopt;
animation_->RemoveFromTicking();
}
@@ -178,19 +178,20 @@ void KeyframeEffect::UpdateState(bool start_ready_keyframe_models,
// Animate hasn't been called, this happens if an element has been added
// between the Commit and Draw phases.
- if (last_tick_time_ == base::TimeTicks())
+ if (last_tick_time_ == base::nullopt)
start_ready_keyframe_models = false;
if (start_ready_keyframe_models)
PromoteStartedKeyframeModels(events);
- MarkFinishedKeyframeModels(last_tick_time_);
- MarkKeyframeModelsForDeletion(last_tick_time_, events);
+ auto last_tick_time = last_tick_time_.value_or(base::TimeTicks());
+ MarkFinishedKeyframeModels(last_tick_time);
+ MarkKeyframeModelsForDeletion(last_tick_time, events);
PurgeKeyframeModelsMarkedForDeletion(/* impl_only */ true);
if (start_ready_keyframe_models) {
if (needs_to_start_keyframe_models_) {
- StartKeyframeModels(last_tick_time_);
+ StartKeyframeModels(last_tick_time);
PromoteStartedKeyframeModels(events);
}
}
@@ -313,7 +314,8 @@ void KeyframeEffect::RemoveKeyframeModel(int keyframe_model_id) {
void KeyframeEffect::AbortKeyframeModel(int keyframe_model_id) {
if (KeyframeModel* keyframe_model = GetKeyframeModelById(keyframe_model_id)) {
if (!keyframe_model->is_finished()) {
- keyframe_model->SetRunState(KeyframeModel::ABORTED, last_tick_time_);
+ keyframe_model->SetRunState(KeyframeModel::ABORTED,
+ last_tick_time_.value_or(base::TimeTicks()));
if (has_bound_element_animations())
element_animations_->UpdateClientAnimationState();
}
@@ -338,10 +340,13 @@ void KeyframeEffect::AbortKeyframeModelsWithProperty(
// Currently only impl-only scroll offset KeyframeModels can be completed
// on the main thread.
if (needs_completion && keyframe_model->is_impl_only()) {
- keyframe_model->SetRunState(KeyframeModel::ABORTED_BUT_NEEDS_COMPLETION,
- last_tick_time_);
+ keyframe_model->SetRunState(
+ KeyframeModel::ABORTED_BUT_NEEDS_COMPLETION,
+ last_tick_time_.value_or(base::TimeTicks()));
} else {
- keyframe_model->SetRunState(KeyframeModel::ABORTED, last_tick_time_);
+ keyframe_model->SetRunState(
+ KeyframeModel::ABORTED,
+ last_tick_time_.value_or(base::TimeTicks()));
}
aborted_keyframe_model = true;
}
@@ -575,7 +580,7 @@ bool KeyframeEffect::IsCurrentlyAnimatingProperty(
ElementListType list_type) const {
for (const auto& keyframe_model : keyframe_models_) {
if (!keyframe_model->is_finished() &&
- keyframe_model->InEffect(last_tick_time_) &&
+ keyframe_model->InEffect(last_tick_time_.value_or(base::TimeTicks())) &&
keyframe_model->target_property_id() == target_property) {
if ((list_type == ElementListType::ACTIVE &&
keyframe_model->affects_active_elements()) ||
@@ -613,7 +618,8 @@ void KeyframeEffect::GetPropertyAnimationState(
for (const auto& keyframe_model : keyframe_models_) {
if (!keyframe_model->is_finished()) {
- bool in_effect = keyframe_model->InEffect(last_tick_time_);
+ bool in_effect =
+ keyframe_model->InEffect(last_tick_time_.value_or(base::TimeTicks()));
bool active = keyframe_model->affects_active_elements();
bool pending = keyframe_model->affects_pending_elements();
int property = keyframe_model->target_property_id();
@@ -642,10 +648,12 @@ void KeyframeEffect::MarkAbortedKeyframeModelsForDeletion(
if (KeyframeModel* keyframe_model =
GetKeyframeModelById(keyframe_model_impl->id())) {
if (keyframe_model->run_state() == KeyframeModel::ABORTED) {
- keyframe_model_impl->SetRunState(KeyframeModel::WAITING_FOR_DELETION,
- keyframe_effect_impl->last_tick_time_);
- keyframe_model->SetRunState(KeyframeModel::WAITING_FOR_DELETION,
- last_tick_time_);
+ keyframe_model_impl->SetRunState(
+ KeyframeModel::WAITING_FOR_DELETION,
+ keyframe_effect_impl->last_tick_time_.value_or(base::TimeTicks()));
+ keyframe_model->SetRunState(
+ KeyframeModel::WAITING_FOR_DELETION,
+ last_tick_time_.value_or(base::TimeTicks()));
keyframe_model_aborted = true;
}
}
@@ -911,16 +919,18 @@ void KeyframeEffect::PromoteStartedKeyframeModels(AnimationEvents* events) {
for (auto& keyframe_model : keyframe_models_) {
if (keyframe_model->run_state() == KeyframeModel::STARTING &&
keyframe_model->affects_active_elements()) {
- keyframe_model->SetRunState(KeyframeModel::RUNNING, last_tick_time_);
+ keyframe_model->SetRunState(KeyframeModel::RUNNING,
+ last_tick_time_.value_or(base::TimeTicks()));
if (!keyframe_model->has_set_start_time() &&
!keyframe_model->needs_synchronized_start_time())
- keyframe_model->set_start_time(last_tick_time_);
+ keyframe_model->set_start_time(
+ last_tick_time_.value_or(base::TimeTicks()));
base::TimeTicks start_time;
if (keyframe_model->has_set_start_time())
start_time = keyframe_model->start_time();
else
- start_time = last_tick_time_;
+ start_time = last_tick_time_.value_or(base::TimeTicks());
GenerateEvent(events, *keyframe_model, AnimationEvent::STARTED,
start_time);
diff --git a/chromium/cc/animation/keyframe_effect.h b/chromium/cc/animation/keyframe_effect.h
index 1d2655395f0..e7806e4cc1d 100644
--- a/chromium/cc/animation/keyframe_effect.h
+++ b/chromium/cc/animation/keyframe_effect.h
@@ -187,7 +187,7 @@ class CC_ANIMATION_EXPORT KeyframeEffect {
bool scroll_offset_animation_was_interrupted_;
bool is_ticking_;
- base::TimeTicks last_tick_time_;
+ base::Optional<base::TimeTicks> last_tick_time_;
bool needs_push_properties_;
};
diff --git a/chromium/cc/animation/scroll_offset_animation_curve.cc b/chromium/cc/animation/scroll_offset_animation_curve.cc
index d6a3000c31f..2914ce4c193 100644
--- a/chromium/cc/animation/scroll_offset_animation_curve.cc
+++ b/chromium/cc/animation/scroll_offset_animation_curve.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include <cmath>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/ranges.h"
#include "cc/animation/timing_function.h"
diff --git a/chromium/cc/animation/scroll_timeline.cc b/chromium/cc/animation/scroll_timeline.cc
index 914381524f0..a3d7e9439aa 100644
--- a/chromium/cc/animation/scroll_timeline.cc
+++ b/chromium/cc/animation/scroll_timeline.cc
@@ -155,6 +155,38 @@ void ScrollTimeline::ActivateTimeline() {
}
}
+bool ScrollTimeline::TickScrollLinkedAnimations(
+ const std::vector<scoped_refptr<Animation>>& ticking_animations,
+ const ScrollTree& scroll_tree,
+ bool is_active_tree) {
+ base::Optional<base::TimeTicks> tick_time =
+ CurrentTime(scroll_tree, is_active_tree);
+ if (!tick_time)
+ return false;
+
+ bool animated = false;
+ // This potentially iterates over all ticking animations multiple
+ // times (# of ScrollTimeline * # of ticking_animations_).
+ // The alternative we have considered here was to maintain a
+ // ticking_animations_ list for each timeline but at the moment we
+ // have opted to avoid this complexity in favor of simpler but less
+ // efficient solution.
+ for (auto& animation : ticking_animations) {
+ if (animation->animation_timeline() != this)
+ continue;
+ // Worklet animations are ticked at a later stage.
+ if (animation->IsWorkletAnimation())
+ continue;
+
+ if (!animation->IsScrollLinkedAnimation())
+ continue;
+
+ animation->Tick(tick_time.value());
+ animated = true;
+ }
+ return animated;
+}
+
void ScrollTimeline::UpdateScrollerIdAndScrollOffsets(
base::Optional<ElementId> pending_id,
base::Optional<double> start_scroll_offset,
diff --git a/chromium/cc/animation/scroll_timeline.h b/chromium/cc/animation/scroll_timeline.h
index 0aee63a239a..fa917824b7b 100644
--- a/chromium/cc/animation/scroll_timeline.h
+++ b/chromium/cc/animation/scroll_timeline.h
@@ -73,6 +73,11 @@ class CC_ANIMATION_EXPORT ScrollTimeline : public AnimationTimeline {
void PushPropertiesTo(AnimationTimeline* impl_timeline) override;
void ActivateTimeline() override;
+ bool TickScrollLinkedAnimations(
+ const std::vector<scoped_refptr<Animation>>& ticking_animations,
+ const ScrollTree& scroll_tree,
+ bool is_active_tree) override;
+
base::Optional<ElementId> GetActiveIdForTest() const { return active_id_; }
base::Optional<ElementId> GetPendingIdForTest() const { return pending_id_; }
ScrollDirection GetDirectionForTest() const { return direction_; }
diff --git a/chromium/cc/animation/timing_function.cc b/chromium/cc/animation/timing_function.cc
index d3a66810330..8906be4d9f7 100644
--- a/chromium/cc/animation/timing_function.cc
+++ b/chromium/cc/animation/timing_function.cc
@@ -7,8 +7,9 @@
#include <cmath>
#include <memory>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
namespace cc {
diff --git a/chromium/cc/animation/transform_operation.cc b/chromium/cc/animation/transform_operation.cc
index f0dcc7723e9..1bb8996d953 100644
--- a/chromium/cc/animation/transform_operation.cc
+++ b/chromium/cc/animation/transform_operation.cc
@@ -5,7 +5,8 @@
#include <algorithm>
#include <limits>
-#include "base/logging.h"
+#include "base/check_op.h"
+#include "base/notreached.h"
#include "base/numerics/math_constants.h"
#include "base/numerics/ranges.h"
#include "cc/animation/transform_operation.h"
diff --git a/chromium/cc/animation/worklet_animation.cc b/chromium/cc/animation/worklet_animation.cc
index 54bb27f6e50..17ed083efcc 100644
--- a/chromium/cc/animation/worklet_animation.cc
+++ b/chromium/cc/animation/worklet_animation.cc
@@ -92,8 +92,7 @@ void WorkletAnimation::Tick(base::TimeTicks monotonic_time) {
// animations lifecycle. To avoid this we pause the underlying keyframe effect
// at the local time obtained from the user script - essentially turning each
// call to |WorkletAnimation::Tick| into a seek in the effect.
- keyframe_effect_->Pause(local_time_.value());
- keyframe_effect_->Tick(monotonic_time);
+ TickWithLocalTime(local_time_.value());
}
void WorkletAnimation::UpdateState(bool start_ready_animations,
diff --git a/chromium/cc/base/features.cc b/chromium/cc/base/features.cc
index 7528a58827a..8c0c599f83d 100644
--- a/chromium/cc/base/features.cc
+++ b/chromium/cc/base/features.cc
@@ -47,4 +47,7 @@ bool IsMainLatencyRecoveryEnabled() {
#endif
}
+const base::Feature kScrollUnification{"ScrollUnification",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
diff --git a/chromium/cc/base/features.h b/chromium/cc/base/features.h
index 01659128cb2..56c620c6eea 100644
--- a/chromium/cc/base/features.h
+++ b/chromium/cc/base/features.h
@@ -22,6 +22,14 @@ CC_BASE_EXPORT extern const base::Feature kMainLatencyRecovery;
CC_BASE_EXPORT bool IsImplLatencyRecoveryEnabled();
CC_BASE_EXPORT bool IsMainLatencyRecoveryEnabled();
+// When enabled, all scrolling is performed on the compositor thread -
+// delegating only the hit test to Blink. This causes Blink to send additional
+// information in the scroll property tree. When a scroll can't be hit tested
+// on the compositor, it will post a hit test task to Blink and continue the
+// scroll when that resolves. For details, see:
+// https://docs.google.com/document/d/1smLAXs-DSLLmkEt4FIPP7PVglJXOcwRc7A5G0SEwxaY/edit
+CC_BASE_EXPORT extern const base::Feature kScrollUnification;
+
} // namespace features
#endif // CC_BASE_FEATURES_H_
diff --git a/chromium/cc/base/list_container_helper.cc b/chromium/cc/base/list_container_helper.cc
index 3a4c0b6a2f9..afd386e3a88 100644
--- a/chromium/cc/base/list_container_helper.cc
+++ b/chromium/cc/base/list_container_helper.cc
@@ -9,7 +9,7 @@
#include <algorithm>
#include <vector>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/aligned_memory.h"
namespace {
diff --git a/chromium/cc/base/reverse_spiral_iterator.cc b/chromium/cc/base/reverse_spiral_iterator.cc
index a0d836878dd..0aca645c247 100644
--- a/chromium/cc/base/reverse_spiral_iterator.cc
+++ b/chromium/cc/base/reverse_spiral_iterator.cc
@@ -6,6 +6,8 @@
#include <algorithm>
+#include "base/check_op.h"
+
namespace cc {
ReverseSpiralIterator::ReverseSpiralIterator()
diff --git a/chromium/cc/base/simple_enclosed_region.cc b/chromium/cc/base/simple_enclosed_region.cc
index 00c58abaae0..24227a0b20c 100644
--- a/chromium/cc/base/simple_enclosed_region.cc
+++ b/chromium/cc/base/simple_enclosed_region.cc
@@ -7,7 +7,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "cc/base/region.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/cc/base/spiral_iterator.cc b/chromium/cc/base/spiral_iterator.cc
index 7d7387bd55e..30a06a4904f 100644
--- a/chromium/cc/base/spiral_iterator.cc
+++ b/chromium/cc/base/spiral_iterator.cc
@@ -4,6 +4,8 @@
#include "cc/base/spiral_iterator.h"
+#include "base/check_op.h"
+
#include <algorithm>
namespace cc {
diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc
index 57409ca3d62..e7e8704263d 100644
--- a/chromium/cc/base/switches.cc
+++ b/chromium/cc/base/switches.cc
@@ -48,10 +48,15 @@ const char kCheckDamageEarly[] = "check-damage-early";
// Enables the GPU benchmarking extension
const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking";
+// Disables LayerTreeHost::OnMemoryPressure
+const char kDisableLayerTreeHostMemoryPressure[] =
+ "disable-layer-tree-host-memory-pressure";
+
// Renders a border around compositor layers to help debug and study
// layer compositing.
const char kShowCompositedLayerBorders[] = "show-composited-layer-borders";
const char kUIShowCompositedLayerBorders[] = "ui-show-composited-layer-borders";
+// Parameters for kUIShowCompositedLayerBorders.
const char kCompositedRenderPassBorders[] = "renderpass";
const char kCompositedSurfaceBorders[] = "surface";
const char kCompositedLayerBorders[] = "layer";
@@ -85,6 +90,10 @@ const char kUIShowSurfaceDamageRects[] = "ui-show-surface-damage-rects";
const char kShowScreenSpaceRects[] = "show-screenspace-rects";
const char kUIShowScreenSpaceRects[] = "ui-show-screenspace-rects";
+// Highlights layers that can't use lcd text. Layers containing no text won't
+// be highlighted. See DebugColors::NonLCDTextHighlightColor() for the colors.
+const char kHighlightNonLCDTextLayers[] = "highlight-non-lcd-text-layers";
+
// Switches the ui compositor to use layer lists instead of layer trees.
const char kUIEnableLayerLists[] = "ui-enable-layer-lists";
diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h
index d3a9d37d839..7b6c6b398e0 100644
--- a/chromium/cc/base/switches.h
+++ b/chromium/cc/base/switches.h
@@ -31,6 +31,9 @@ CC_BASE_EXPORT extern const char kCheckDamageEarly[];
// Switches for both the renderer and ui compositors.
CC_BASE_EXPORT extern const char kEnableGpuBenchmarking[];
+// Switches for LayerTreeHost.
+CC_BASE_EXPORT extern const char kDisableLayerTreeHostMemoryPressure[];
+
// Debug visualizations.
CC_BASE_EXPORT extern const char kShowCompositedLayerBorders[];
CC_BASE_EXPORT extern const char kUIShowCompositedLayerBorders[];
@@ -44,14 +47,18 @@ CC_BASE_EXPORT extern const char kShowSurfaceDamageRects[];
CC_BASE_EXPORT extern const char kUIShowSurfaceDamageRects[];
CC_BASE_EXPORT extern const char kShowScreenSpaceRects[];
CC_BASE_EXPORT extern const char kUIShowScreenSpaceRects[];
-CC_BASE_EXPORT extern const char kUIEnableLayerLists[];
-CC_BASE_EXPORT extern const char kCompositedRenderPassBorders[];
-CC_BASE_EXPORT extern const char kCompositedSurfaceBorders[];
-CC_BASE_EXPORT extern const char kCompositedLayerBorders[];
+CC_BASE_EXPORT extern const char kHighlightNonLCDTextLayers[];
#if DCHECK_IS_ON()
CC_BASE_EXPORT extern const char kLogOnUIDoubleBackgroundBlur[];
#endif
+// Parameters for kUIShowCompositedLayerBorders.
+CC_BASE_EXPORT extern const char kCompositedRenderPassBorders[];
+CC_BASE_EXPORT extern const char kCompositedSurfaceBorders[];
+CC_BASE_EXPORT extern const char kCompositedLayerBorders[];
+
+CC_BASE_EXPORT extern const char kUIEnableLayerLists[];
+
// Test related.
CC_BASE_EXPORT extern const char kCCLayerTreeTestNoTimeout[];
CC_BASE_EXPORT extern const char kCCLayerTreeTestLongTimeout[];
diff --git a/chromium/cc/base/tiling_data.cc b/chromium/cc/base/tiling_data.cc
index b17338e5c5c..deb55701417 100644
--- a/chromium/cc/base/tiling_data.cc
+++ b/chromium/cc/base/tiling_data.cc
@@ -6,6 +6,8 @@
#include <algorithm>
+#include "base/check_op.h"
+#include "base/notreached.h"
#include "base/numerics/ranges.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/cc/benchmarks/micro_benchmark.cc b/chromium/cc/benchmarks/micro_benchmark.cc
index 5f23e66ee37..4479e8abb40 100644
--- a/chromium/cc/benchmarks/micro_benchmark.cc
+++ b/chromium/cc/benchmarks/micro_benchmark.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/callback.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/values.h"
diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
index 609b925b264..84a5e330c6c 100644
--- a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
+++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer_impl.h"
+#include "cc/paint/display_item_list.h"
#include "cc/raster/playback_image_provider.h"
#include "cc/raster/raster_buffer_provider.h"
#include "cc/trees/layer_tree_host_impl.h"
@@ -166,6 +167,17 @@ void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
result->SetInteger("total_picture_layers_off_screen",
rasterize_results_.total_picture_layers_off_screen);
+ std::unique_ptr<base::DictionaryValue> lcd_text_pixels(
+ new base::DictionaryValue());
+ for (size_t i = 0; i < kLCDTextDisallowedReasonCount; i++) {
+ lcd_text_pixels->SetInteger(
+ LCDTextDisallowedReasonToString(
+ static_cast<LCDTextDisallowedReason>(i)),
+ rasterize_results_.visible_pixels_by_lcd_text_disallowed_reason[i]);
+ }
+ result->SetDictionary("visible_pixels_by_lcd_text_disallowed_reason",
+ std::move(lcd_text_pixels));
+
NotifyDone(std::move(result));
}
@@ -180,6 +192,13 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
return;
}
+ int text_pixels =
+ layer->GetRasterSource()->GetDisplayItemList()->AreaOfDrawText(
+ layer->visible_layer_rect());
+ rasterize_results_
+ .visible_pixels_by_lcd_text_disallowed_reason[static_cast<size_t>(
+ layer->lcd_text_disallowed_reason())] += text_pixels;
+
FixedInvalidationPictureLayerTilingClient client(layer,
gfx::Rect(layer->bounds()));
@@ -230,6 +249,7 @@ RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
: pixels_rasterized(0),
pixels_rasterized_with_non_solid_color(0),
pixels_rasterized_as_opaque(0),
+ visible_pixels_by_lcd_text_disallowed_reason{0},
total_layers(0),
total_picture_layers(0),
total_picture_layers_with_no_content(0),
diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h
index be8a6de987c..a4ac27614a5 100644
--- a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h
+++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h
@@ -14,6 +14,7 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "cc/benchmarks/micro_benchmark_impl.h"
+#include "cc/raster/lcd_text_disallowed_reason.h"
#include "cc/raster/task_graph_runner.h"
namespace cc {
@@ -41,6 +42,8 @@ class RasterizeAndRecordBenchmarkImpl : public MicroBenchmarkImpl {
int pixels_rasterized;
int pixels_rasterized_with_non_solid_color;
int pixels_rasterized_as_opaque;
+ int visible_pixels_by_lcd_text_disallowed_reason
+ [kLCDTextDisallowedReasonCount];
base::TimeDelta total_best_time;
int total_layers;
int total_picture_layers;
diff --git a/chromium/cc/debug/BUILD.gn b/chromium/cc/debug/BUILD.gn
index 2bb36bfd8fa..4a046e990a2 100644
--- a/chromium/cc/debug/BUILD.gn
+++ b/chromium/cc/debug/BUILD.gn
@@ -6,6 +6,8 @@ import("//cc/cc.gni")
cc_component("debug") {
output_name = "cc_debug"
sources = [
+ # For enum LCDTextDisallowedReason used in debug_colors.*.
+ "../raster/lcd_text_disallowed_reason.h",
"debug_colors.cc",
"debug_colors.h",
"debug_export.h",
diff --git a/chromium/cc/debug/debug_colors.cc b/chromium/cc/debug/debug_colors.cc
index 76fa7258618..1401b47b0d9 100644
--- a/chromium/cc/debug/debug_colors.cc
+++ b/chromium/cc/debug/debug_colors.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
-
#include "cc/debug/debug_colors.h"
+#include "base/check_op.h"
+#include "base/notreached.h"
+
namespace cc {
static float Scale(float width, float device_scale_factor) {
@@ -321,4 +322,26 @@ SkColor DebugColors::PaintTimeDisplayTextAndGraphColor() {
return SkColorSetRGB(75, 155, 55);
}
+SkColor DebugColors::NonLCDTextHighlightColor(LCDTextDisallowedReason reason) {
+ switch (reason) {
+ case LCDTextDisallowedReason::kNone:
+ return SK_ColorTRANSPARENT;
+ case LCDTextDisallowedReason::kSetting:
+ return SkColorSetARGB(96, 128, 255, 0);
+ case LCDTextDisallowedReason::kBackgroundColorNotOpaque:
+ return SkColorSetARGB(96, 128, 128, 0);
+ case LCDTextDisallowedReason::kContentsNotOpaque:
+ return SkColorSetARGB(96, 255, 0, 0);
+ case LCDTextDisallowedReason::kNonIntegralTranslation:
+ return SkColorSetARGB(96, 255, 128, 0);
+ case LCDTextDisallowedReason::kNonIntegralXOffset:
+ case LCDTextDisallowedReason::kNonIntegralYOffset:
+ return SkColorSetARGB(96, 255, 0, 128);
+ case LCDTextDisallowedReason::kWillChangeTransform:
+ return SkColorSetARGB(96, 128, 0, 255);
+ }
+ NOTREACHED();
+ return SK_ColorTRANSPARENT;
+}
+
} // namespace cc
diff --git a/chromium/cc/debug/debug_colors.h b/chromium/cc/debug/debug_colors.h
index 97e6688bccd..9718669b30b 100644
--- a/chromium/cc/debug/debug_colors.h
+++ b/chromium/cc/debug/debug_colors.h
@@ -7,6 +7,7 @@
#include "base/containers/span.h"
#include "cc/debug/debug_export.h"
+#include "cc/raster/lcd_text_disallowed_reason.h"
#include "third_party/skia/include/core/SkColor.h"
namespace cc {
@@ -125,6 +126,8 @@ class CC_DEBUG_EXPORT DebugColors {
static SkColor FPSDisplayTextAndGraphColor();
static SkColor MemoryDisplayTextColor();
static SkColor PaintTimeDisplayTextAndGraphColor();
+
+ static SkColor NonLCDTextHighlightColor(LCDTextDisallowedReason);
};
} // namespace cc
diff --git a/chromium/cc/debug/layer_tree_debug_state.cc b/chromium/cc/debug/layer_tree_debug_state.cc
index 66d1e134c43..0ce673525cf 100644
--- a/chromium/cc/debug/layer_tree_debug_state.cc
+++ b/chromium/cc/debug/layer_tree_debug_state.cc
@@ -4,7 +4,6 @@
#include "cc/debug/layer_tree_debug_state.h"
-#include "base/logging.h"
namespace cc {
@@ -25,7 +24,7 @@ LayerTreeDebugState::LayerTreeDebugState()
show_layer_animation_bounds_rects(false),
slow_down_raster_scale_factor(0),
rasterize_only_visible_content(false),
- show_picture_borders(false),
+ highlight_non_lcd_text_layers(false),
show_hit_test_borders(false),
record_rendering_stats_(false) {}
@@ -79,7 +78,7 @@ bool LayerTreeDebugState::Equal(const LayerTreeDebugState& a,
b.show_layer_animation_bounds_rects &&
a.slow_down_raster_scale_factor == b.slow_down_raster_scale_factor &&
a.rasterize_only_visible_content == b.rasterize_only_visible_content &&
- a.show_picture_borders == b.show_picture_borders &&
+ a.highlight_non_lcd_text_layers == b.highlight_non_lcd_text_layers &&
a.show_hit_test_borders == b.show_hit_test_borders &&
a.record_rendering_stats_ == b.record_rendering_stats_);
}
@@ -107,7 +106,7 @@ LayerTreeDebugState LayerTreeDebugState::Unite(const LayerTreeDebugState& a,
if (b.slow_down_raster_scale_factor)
r.slow_down_raster_scale_factor = b.slow_down_raster_scale_factor;
r.rasterize_only_visible_content |= b.rasterize_only_visible_content;
- r.show_picture_borders |= b.show_picture_borders;
+ r.highlight_non_lcd_text_layers |= b.highlight_non_lcd_text_layers;
r.show_hit_test_borders |= b.show_hit_test_borders;
diff --git a/chromium/cc/debug/layer_tree_debug_state.h b/chromium/cc/debug/layer_tree_debug_state.h
index db18711a3f0..95b79cda95d 100644
--- a/chromium/cc/debug/layer_tree_debug_state.h
+++ b/chromium/cc/debug/layer_tree_debug_state.h
@@ -46,7 +46,7 @@ class CC_DEBUG_EXPORT LayerTreeDebugState {
int slow_down_raster_scale_factor;
bool rasterize_only_visible_content;
- bool show_picture_borders;
+ bool highlight_non_lcd_text_layers;
bool show_hit_test_borders;
diff --git a/chromium/cc/debug/picture_debug_util.cc b/chromium/cc/debug/picture_debug_util.cc
index 86ca1c6b00f..9b8feaadcde 100644
--- a/chromium/cc/debug/picture_debug_util.cc
+++ b/chromium/cc/debug/picture_debug_util.cc
@@ -11,7 +11,6 @@
#include <vector>
#include "base/base64.h"
-#include "base/logging.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/codec/jpeg_codec.h"
diff --git a/chromium/cc/input/browser_controls_offset_manager.cc b/chromium/cc/input/browser_controls_offset_manager.cc
index 248ad7bf66b..ea4c6e27993 100644
--- a/chromium/cc/input/browser_controls_offset_manager.cc
+++ b/chromium/cc/input/browser_controls_offset_manager.cc
@@ -8,7 +8,7 @@
#include <algorithm>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/ranges.h"
#include "cc/input/browser_controls_offset_manager_client.h"
diff --git a/chromium/cc/input/browser_controls_offset_manager_unittest.cc b/chromium/cc/input/browser_controls_offset_manager_unittest.cc
index 6dfaefd4843..8c443fd0bee 100644
--- a/chromium/cc/input/browser_controls_offset_manager_unittest.cc
+++ b/chromium/cc/input/browser_controls_offset_manager_unittest.cc
@@ -8,7 +8,6 @@
#include <cmath>
#include <memory>
-#include "base/logging.h"
#include "base/time/time.h"
#include "cc/input/browser_controls_offset_manager_client.h"
#include "cc/layers/layer_impl.h"
diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h
index c031f16b0b7..eaaa9afde45 100644
--- a/chromium/cc/input/input_handler.h
+++ b/chromium/cc/input/input_handler.h
@@ -12,7 +12,6 @@
#include "cc/input/event_listener_properties.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/overscroll_behavior.h"
-#include "cc/input/scroll_input_type.h"
#include "cc/input/scroll_state.h"
#include "cc/input/scrollbar.h"
#include "cc/input/touch_action.h"
@@ -20,6 +19,7 @@
#include "cc/paint/element_id.h"
#include "cc/trees/swap_promise_monitor.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "ui/events/types/scroll_input_type.h"
#include "ui/events/types/scroll_types.h"
namespace gfx {
@@ -171,12 +171,12 @@ class CC_EXPORT InputHandler {
// SCROLL_IGNORED if there is nothing to be scrolled at the given
// coordinates.
virtual ScrollStatus ScrollBegin(ScrollState* scroll_state,
- ScrollInputType type) = 0;
+ ui::ScrollInputType type) = 0;
// Similar to ScrollBegin, except the hit test is skipped and scroll always
// targets at the root layer.
virtual ScrollStatus RootScrollBegin(ScrollState* scroll_state,
- ScrollInputType type) = 0;
+ ui::ScrollInputType type) = 0;
// Scroll the layer selected by |ScrollBegin| by given |scroll_state| delta.
// Internally, the delta is transformed to local layer's coordinate space for
@@ -203,9 +203,9 @@ class CC_EXPORT InputHandler {
// Called to notify every time scroll-begin/end is attempted by an input
// event.
- virtual void RecordScrollBegin(ScrollInputType input_type,
+ virtual void RecordScrollBegin(ui::ScrollInputType input_type,
ScrollBeginThreadState scroll_start_state) = 0;
- virtual void RecordScrollEnd(ScrollInputType input_type) = 0;
+ virtual void RecordScrollEnd(ui::ScrollInputType input_type) = 0;
virtual InputHandlerPointerResult MouseMoveAt(
const gfx::Point& mouse_position) = 0;
@@ -243,10 +243,6 @@ class CC_EXPORT InputHandler {
// Returns true if there is an active scroll on the viewport.
virtual bool IsCurrentlyScrollingViewport() const = 0;
- // Whether the layer under |viewport_point| is the currently scrolling layer.
- virtual bool IsCurrentlyScrollingLayerAt(
- const gfx::Point& viewport_point) const = 0;
-
virtual EventListenerProperties GetEventListenerProperties(
EventListenerClass event_class) const = 0;
@@ -279,9 +275,10 @@ class CC_EXPORT InputHandler {
// During the lifetime of the returned EventsMetricsManager::ScopedMonitor, if
// SetNeedsOneBeginImplFrame() or SetNeedsRedraw() are called on
// LayerTreeHostImpl or a scroll animation is updated, |event_metrics| will be
- // saved for reporting event latency metrics.
+ // saved for reporting event latency metrics. It is allowed to pass nullptr as
+ // |event_metrics| in which case the return value would also be nullptr.
virtual std::unique_ptr<EventsMetricsManager::ScopedMonitor>
- GetScopedEventMetricsMonitor(const EventMetrics& event_metrics) = 0;
+ GetScopedEventMetricsMonitor(std::unique_ptr<EventMetrics> event_metrics) = 0;
virtual ScrollElasticityHelper* CreateScrollElasticityHelper() = 0;
@@ -309,6 +306,10 @@ class CC_EXPORT InputHandler {
// it wasn't aborted).
virtual void ScrollEndForSnapFling(bool did_finish) = 0;
+ // Notifies when any input event is received, irrespective of whether it is
+ // being handled by the InputHandler or not.
+ virtual void NotifyInputEvent() = 0;
+
protected:
InputHandler() = default;
virtual ~InputHandler() = default;
diff --git a/chromium/cc/input/layer_selection_bound.cc b/chromium/cc/input/layer_selection_bound.cc
index 81af0bf7d32..7de8f2991c3 100644
--- a/chromium/cc/input/layer_selection_bound.cc
+++ b/chromium/cc/input/layer_selection_bound.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "cc/input/layer_selection_bound.h"
diff --git a/chromium/cc/input/main_thread_scrolling_reason.cc b/chromium/cc/input/main_thread_scrolling_reason.cc
index 56e1d58d4fa..b84c31dd04c 100644
--- a/chromium/cc/input/main_thread_scrolling_reason.cc
+++ b/chromium/cc/input/main_thread_scrolling_reason.cc
@@ -42,16 +42,14 @@ void MainThreadScrollingReason::AddToTracedValue(
traced_value.AppendString("Frame overlay");
if (reasons & kHandlingScrollFromMainThread)
traced_value.AppendString("Handling scroll from main thread");
- if (reasons & kHasOpacityAndLCDText)
- traced_value.AppendString("Has opacity and LCD text");
if (reasons & kHasTransformAndLCDText)
traced_value.AppendString("Has transform and LCD text");
if (reasons & kBackgroundNotOpaqueInRectAndLCDText)
traced_value.AppendString("Background is not opaque in rect and LCD text");
+ if (reasons & kCantPaintScrollingBackground)
+ traced_value.AppendString("Can't paint scrolling background");
if (reasons & kHasClipRelatedProperty)
traced_value.AppendString("Has clip related property");
- if (reasons & kHasBoxShadowFromNonRootLayer)
- traced_value.AppendString("Has box shadow from non-root layer");
if (reasons & kIsNotStackingContextAndLCDText)
traced_value.AppendString("Is not stacking context and LCD text");
diff --git a/chromium/cc/input/main_thread_scrolling_reason.h b/chromium/cc/input/main_thread_scrolling_reason.h
index 2dde0784544..cd129cf69fc 100644
--- a/chromium/cc/input/main_thread_scrolling_reason.h
+++ b/chromium/cc/input/main_thread_scrolling_reason.h
@@ -42,12 +42,11 @@ struct CC_EXPORT MainThreadScrollingReason {
// These *AndLCDText reasons are due to subpixel text rendering which can
// only be applied by blending glyphs with the background at a specific
// screen position; transparency and transforms break this.
- kNonCompositedReasonsFirst = 16,
- kHasOpacityAndLCDText = 1 << 16,
+ kNonCompositedReasonsFirst = 17,
kHasTransformAndLCDText = 1 << 17,
kBackgroundNotOpaqueInRectAndLCDText = 1 << 18,
+ kCantPaintScrollingBackground = 1 << 19,
kHasClipRelatedProperty = 1 << 20,
- kHasBoxShadowFromNonRootLayer = 1 << 21,
kIsNotStackingContextAndLCDText = 1 << 22,
kNonCompositedReasonsLast = 22,
@@ -70,9 +69,9 @@ struct CC_EXPORT MainThreadScrollingReason {
};
static const uint32_t kNonCompositedReasons =
- kHasOpacityAndLCDText | kHasTransformAndLCDText |
- kBackgroundNotOpaqueInRectAndLCDText | kHasClipRelatedProperty |
- kHasBoxShadowFromNonRootLayer | kIsNotStackingContextAndLCDText;
+ kHasTransformAndLCDText | kBackgroundNotOpaqueInRectAndLCDText |
+ kCantPaintScrollingBackground | kHasClipRelatedProperty |
+ kIsNotStackingContextAndLCDText;
// Returns true if the given MainThreadScrollingReason can be set by the main
// thread.
diff --git a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc
index 8744d643907..7cf3f40d164 100644
--- a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc
+++ b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc
@@ -19,11 +19,10 @@ TEST_F(MainThreadScrollingReasonTest, AsText) {
"Scrollbar scrolling, "
"Frame overlay, "
"Handling scroll from main thread, "
- "Has opacity and LCD text, "
"Has transform and LCD text, "
"Background is not opaque in rect and LCD text, "
+ "Can't paint scrolling background, "
"Has clip related property, "
- "Has box shadow from non-root layer, "
"Is not stacking context and LCD text, "
"Non fast scrollable region, "
"Failed hit test, "
diff --git a/chromium/cc/input/page_scale_animation.cc b/chromium/cc/input/page_scale_animation.cc
index fa059d3086a..c307ff967d2 100644
--- a/chromium/cc/input/page_scale_animation.cc
+++ b/chromium/cc/input/page_scale_animation.cc
@@ -6,7 +6,7 @@
#include <math.h>
-#include "base/logging.h"
+#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/cc/input/scroll_input_type.h b/chromium/cc/input/scroll_input_type.h
deleted file mode 100644
index 88e56c8018a..00000000000
--- a/chromium/cc/input/scroll_input_type.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_INPUT_SCROLL_INPUT_TYPE_H_
-#define CC_INPUT_SCROLL_INPUT_TYPE_H_
-
-namespace cc {
-
-enum class ScrollInputType {
- kTouchscreen = 0,
- kWheel,
- kAutoscroll,
- kScrollbar,
- kMaxValue = kScrollbar,
-};
-
-} // namespace cc
-
-#endif // CC_INPUT_SCROLL_INPUT_TYPE_H_
diff --git a/chromium/cc/input/scroll_snap_data.cc b/chromium/cc/input/scroll_snap_data.cc
index 10f3280d34a..f2586f2b976 100644
--- a/chromium/cc/input/scroll_snap_data.cc
+++ b/chromium/cc/input/scroll_snap_data.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "cc/input/scroll_snap_data.h"
+
+#include "base/check.h"
+#include "base/notreached.h"
#include "base/numerics/ranges.h"
#include "cc/input/snap_selection_strategy.h"
diff --git a/chromium/cc/input/scroll_state.cc b/chromium/cc/input/scroll_state.cc
index 521882a0636..7e14c22c82b 100644
--- a/chromium/cc/input/scroll_state.cc
+++ b/chromium/cc/input/scroll_state.cc
@@ -24,4 +24,11 @@ void ScrollState::ConsumeDelta(double x, double y) {
data_.delta_consumed_for_scroll_sequence = true;
}
+gfx::ScrollOffset ScrollState::DeltaOrHint() const {
+ if (is_beginning())
+ return gfx::ScrollOffset(delta_x_hint(), delta_y_hint());
+
+ return gfx::ScrollOffset(delta_x(), delta_y());
+}
+
} // namespace cc
diff --git a/chromium/cc/input/scroll_state.h b/chromium/cc/input/scroll_state.h
index a1a5c8c0d6a..a73b9b117c4 100644
--- a/chromium/cc/input/scroll_state.h
+++ b/chromium/cc/input/scroll_state.h
@@ -11,6 +11,7 @@
#include "cc/cc_export.h"
#include "cc/input/scroll_state_data.h"
#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/vector2d.h"
namespace cc {
@@ -81,6 +82,10 @@ class CC_EXPORT ScrollState {
return data_.delta_granularity;
}
+ // Returns a the delta hints if this is a scroll begin or the real delta if
+ // it's a scroll update
+ gfx::ScrollOffset DeltaOrHint() const;
+
ScrollStateData* data() { return &data_; }
private:
diff --git a/chromium/cc/input/scrollbar.h b/chromium/cc/input/scrollbar.h
index fafe3c267d6..af8cef429b1 100644
--- a/chromium/cc/input/scrollbar.h
+++ b/chromium/cc/input/scrollbar.h
@@ -48,6 +48,10 @@ enum ScrollbarPart {
class Scrollbar : public base::RefCounted<Scrollbar> {
public:
+ // Check if this scrollbar and the other scrollbar are backed with the same
+ // source scrollbar (e.g. blink::Scrollbar).
+ virtual bool IsSame(const Scrollbar&) const = 0;
+
virtual ScrollbarOrientation Orientation() const = 0;
virtual bool IsLeftSideVerticalScrollbar() const = 0;
virtual bool IsSolidColor() const = 0;
diff --git a/chromium/cc/input/scrollbar_controller.cc b/chromium/cc/input/scrollbar_controller.cc
index b4d2ef531e2..aac1d4ceccd 100644
--- a/chromium/cc/input/scrollbar_controller.cc
+++ b/chromium/cc/input/scrollbar_controller.cc
@@ -34,21 +34,6 @@ void ScrollbarController::WillBeginImplFrame() {
RecomputeAutoscrollStateIfNeeded();
}
-gfx::Vector2dF ScrollbarController::GetThumbRelativePoint(
- const ScrollbarLayerImplBase* scrollbar,
- const gfx::PointF position_in_widget) {
- bool clipped;
- const gfx::PointF position_in_layer =
- GetScrollbarRelativePosition(scrollbar, position_in_widget, &clipped);
-
- if (clipped)
- return gfx::Vector2d(0, 0);
-
- const gfx::RectF thumb_rect(scrollbar->ComputeThumbQuadRect());
- DCHECK(thumb_rect.Contains(position_in_layer));
- return position_in_layer - gfx::PointF(thumb_rect.origin());
-}
-
// Retrieves the ScrollbarLayerImplBase corresponding to the stashed ElementId.
ScrollbarLayerImplBase* ScrollbarController::ScrollbarLayer() {
if (!captured_scrollbar_metadata_.has_value())
@@ -75,12 +60,12 @@ InputHandlerPointerResult ScrollbarController::HandlePointerDown(
// empty InputHandlerPointerResult in this case so that when it is bubbled up
// to InputHandlerProxy::RouteToTypeSpecificHandler, the pointer event gets
// passed on to the main thread.
- if (!(layer_impl && layer_impl->ToScrollbarLayer()))
+ if (!(layer_impl && layer_impl->IsScrollbarLayer()))
return InputHandlerPointerResult();
// If the scrollbar layer has faded out (eg: Overlay scrollbars), don't
// initiate a scroll.
- const ScrollbarLayerImplBase* scrollbar = layer_impl->ToScrollbarLayer();
+ const ScrollbarLayerImplBase* scrollbar = ToScrollbarLayer(layer_impl);
if (scrollbar->OverlayScrollbarOpacity() == 0.f)
return InputHandlerPointerResult();
@@ -111,13 +96,14 @@ InputHandlerPointerResult ScrollbarController::HandlePointerDown(
scroll_result.scroll_units = Granularity(scrollbar_part, shift_modifier);
if (scrollbar_part == ScrollbarPart::THUMB) {
drag_state_ = DragState();
- drag_state_->anchor_relative_to_thumb_ =
- GetThumbRelativePoint(scrollbar, position_in_widget);
+ drag_state_->drag_origin = position_in_widget;
// Record the current scroller offset. This will be needed to snap the
// thumb back to its original position if the pointer moves too far away
// from the track during a thumb drag.
drag_state_->scroll_position_at_start_ = scrollbar->current_pos();
+ drag_state_->scroller_length_at_previous_move =
+ scrollbar->scroll_layer_length();
}
if (!scroll_result.scroll_offset.IsZero()) {
@@ -249,69 +235,21 @@ float ScrollbarController::GetScrollDeltaForAbsoluteJump(
return delta * GetScrollerToScrollbarRatio(scrollbar);
}
-gfx::ScrollOffset ScrollbarController::GetScrollOffsetForDragPosition(
+int ScrollbarController::GetScrollDeltaForDragPosition(
const ScrollbarLayerImplBase* scrollbar,
const gfx::PointF pointer_position_in_widget) {
- layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries();
-
- if (SnapToDragOrigin(scrollbar, pointer_position_in_widget)) {
- const float delta =
- scrollbar->current_pos() - drag_state_->scroll_position_at_start_;
- return scrollbar->orientation() == ScrollbarOrientation::VERTICAL
- ? gfx::ScrollOffset(0, -delta)
- : gfx::ScrollOffset(-delta, 0);
- }
-
- const gfx::Rect thumb_rect(scrollbar->ComputeThumbQuadRect());
- const gfx::PointF drag_position_relative_to_layer =
- gfx::PointF(thumb_rect.origin()) + drag_state_->anchor_relative_to_thumb_;
-
- bool clipped = false;
- const gfx::PointF pointer_position_in_layer = GetScrollbarRelativePosition(
- scrollbar, pointer_position_in_widget, &clipped);
-
- if (clipped)
- return gfx::ScrollOffset(0, 0);
-
- // Calculate the delta based on the previously known thumb drag point.
- const gfx::Vector2dF pointer_delta =
- pointer_position_in_layer - drag_position_relative_to_layer;
-
- float scaled_scroller_to_scrollbar_ratio =
- GetScrollerToScrollbarRatio(scrollbar);
- float current_scroll_position = scrollbar->current_pos();
-
- // Thumb position needs to be floored and Values between 0 and 1 are rounded
- // to one to match main thread per pixel behavior. Corresponding main thread
- // code in ScrollbarTheme::ThumbPosition
- float thumb_position = std::max(0.0f, current_scroll_position) /
- scaled_scroller_to_scrollbar_ratio;
- thumb_position = (thumb_position < 1.0 && thumb_position > 0.0)
- ? 1.0
- : floorf(thumb_position);
-
- float delta_in_orientation =
+ const float pointer_delta =
scrollbar->orientation() == ScrollbarOrientation::VERTICAL
- ? pointer_delta.y()
- : pointer_delta.x();
+ ? pointer_position_in_widget.y() - drag_state_->drag_origin.y()
+ : pointer_position_in_widget.x() - drag_state_->drag_origin.x();
- // This is effectively equal to delta_in_orientation *
- // scaled_scroller_to_scrollbar_ratio but is necessary due to truncated delta
- // value. Floored thumb_position cancels out the rounding error introduced
- // in pointer_delta due to static_cast<int> in
- // ScrollbarLayerImplBase::ComputeThumbQuadRectWithThumbThicknessScale
- float scroll_delta = (delta_in_orientation + thumb_position) *
- scaled_scroller_to_scrollbar_ratio -
- current_scroll_position;
-
- gfx::ScrollOffset scaled_thumb_drag_delta;
+ const float new_offset =
+ pointer_delta * GetScrollerToScrollbarRatio(scrollbar);
+ const float scroll_delta = drag_state_->scroll_position_at_start_ +
+ new_offset - scrollbar->current_pos();
// Scroll delta floored to match main thread per pixel behavior
- scrollbar->orientation() == ScrollbarOrientation::VERTICAL
- ? scaled_thumb_drag_delta.set_y(floorf(scroll_delta))
- : scaled_thumb_drag_delta.set_x(floorf(scroll_delta));
-
- return scaled_thumb_drag_delta;
+ return floorf(scroll_delta);
}
// Performs hit test and prepares scroll deltas that will be used by GSU.
@@ -338,6 +276,18 @@ InputHandlerPointerResult ScrollbarController::HandlePointerMove(
if (drag_processed_for_current_frame_)
return scroll_result;
+ if (SnapToDragOrigin(scrollbar, position_in_widget)) {
+ const float delta =
+ scrollbar->current_pos() - drag_state_->scroll_position_at_start_;
+ scroll_result.scroll_units = ui::ScrollGranularity::kScrollByPrecisePixel;
+ scroll_result.scroll_offset =
+ scrollbar->orientation() == ScrollbarOrientation::VERTICAL
+ ? gfx::ScrollOffset(0, -delta)
+ : gfx::ScrollOffset(-delta, 0);
+ drag_processed_for_current_frame_ = true;
+ return scroll_result;
+ }
+
// When initiating a thumb drag, a pointerdown and a pointermove can both
// arrive a the ScrollbarController in succession before a GSB would have
// been dispatched. So, querying LayerTreeHostImpl::CurrentlyScrollingNode()
@@ -352,9 +302,27 @@ InputHandlerPointerResult ScrollbarController::HandlePointerMove(
// valid ScrollNode.
DCHECK(target_node);
+ int delta = GetScrollDeltaForDragPosition(scrollbar, position_in_widget);
+ if (drag_state_->scroller_length_at_previous_move !=
+ scrollbar->scroll_layer_length()) {
+ drag_state_->scroller_displacement = delta;
+ drag_state_->scroller_length_at_previous_move =
+ scrollbar->scroll_layer_length();
+
+ // This is done to ensure that, when the scroller length changes mid thumb
+ // drag, the scroller shouldn't jump. We early out because the delta would
+ // be zero in this case anyway (since drag_state_->scroller_displacement =
+ // delta). So that means, in the worst case you'd miss 1 GSU every time the
+ // scroller expands while a thumb drag is in progress.
+ return scroll_result;
+ }
+ delta -= drag_state_->scroller_displacement;
+
// If scroll_offset can't be consumed, there's no point in continuing on.
- const gfx::ScrollOffset scroll_offset(
- GetScrollOffsetForDragPosition(scrollbar, position_in_widget));
+ const gfx::ScrollOffset scroll_offset(scrollbar->orientation() ==
+ ScrollbarOrientation::VERTICAL
+ ? gfx::ScrollOffset(0, delta)
+ : gfx::ScrollOffset(delta, 0));
const gfx::Vector2dF clamped_scroll_offset(
layer_tree_host_impl_->ComputeScrollDelta(
*target_node, ScrollOffsetToVector2dF(scroll_offset)));
@@ -624,14 +592,16 @@ int ScrollbarController::GetScrollDeltaForScrollbarPart(
const ScrollbarPart scrollbar_part,
const bool shift_modifier) {
int scroll_delta = 0;
- if (layer_tree_host_impl_->settings().percent_based_scrolling) {
- // TODO(arakeri): Implement percent based deltas.
- }
switch (scrollbar_part) {
case ScrollbarPart::BACK_BUTTON:
case ScrollbarPart::FORWARD_BUTTON:
- scroll_delta = kPixelsPerLineStep * ScreenSpaceScaleFactor();
+ if (layer_tree_host_impl_->settings().percent_based_scrolling) {
+ scroll_delta =
+ kPercentDeltaForDirectionalScroll * GetViewportLength(scrollbar);
+ } else {
+ scroll_delta = kPixelsPerLineStep * ScreenSpaceScaleFactor();
+ }
break;
case ScrollbarPart::BACK_TRACK:
case ScrollbarPart::FORWARD_TRACK: {
diff --git a/chromium/cc/input/scrollbar_controller.h b/chromium/cc/input/scrollbar_controller.h
index ab93bde692d..4177c3464e5 100644
--- a/chromium/cc/input/scrollbar_controller.h
+++ b/chromium/cc/input/scrollbar_controller.h
@@ -138,6 +138,7 @@ class CC_EXPORT ScrollbarController {
void DidUnregisterScrollbar(ElementId element_id);
ScrollbarLayerImplBase* ScrollbarLayer();
void WillBeginImplFrame();
+ void ResetState();
private:
// "Autoscroll" here means the continuous scrolling that occurs when the
@@ -163,13 +164,19 @@ class CC_EXPORT ScrollbarController {
};
struct CC_EXPORT DragState {
- // This is used to track the pointer location relative to the thumb origin
- // when a drag has started.
- gfx::Vector2dF anchor_relative_to_thumb_;
+ // This marks the point at which the drag initiated (relative to the widget)
+ gfx::PointF drag_origin;
// This is needed for thumb snapping when the pointer moves too far away
// from the track while scrolling.
float scroll_position_at_start_;
+
+ // The |scroller_displacement| indicates the scroll offset compensation that
+ // needs to be applied when the scroller's length changes dynamically mid
+ // thumb drag. This is needed done to ensure that the scroller does not jump
+ // while a thumb drag is in progress.
+ float scroller_displacement;
+ float scroller_length_at_previous_move;
};
struct CC_EXPORT CapturedScrollbarMetadata {
@@ -223,7 +230,6 @@ class CC_EXPORT ScrollbarController {
// the thumb reaching the pointer or the pointer leaving (or re-entering) the
// bounds.
void RecomputeAutoscrollStateIfNeeded();
- void ResetState();
// Shift (or "Option" in case of Mac) + click is expected to do a non-animated
// jump to a certain offset.
@@ -233,16 +239,11 @@ class CC_EXPORT ScrollbarController {
ui::ScrollGranularity Granularity(const ScrollbarPart scrollbar_part,
bool shift_modifier);
- // Calculates the scroll_offset based on position_in_widget and
- // drag_anchor_relative_to_thumb_.
- gfx::ScrollOffset GetScrollOffsetForDragPosition(
+ // Calculates the delta based on position_in_widget and drag_origin.
+ int GetScrollDeltaForDragPosition(
const ScrollbarLayerImplBase* scrollbar,
const gfx::PointF pointer_position_in_widget);
- // Returns a Vector2dF for position_in_widget relative to the scrollbar thumb.
- gfx::Vector2dF GetThumbRelativePoint(const ScrollbarLayerImplBase* scrollbar,
- const gfx::PointF position_in_widget);
-
// Returns the ratio of the scroller length to the scrollbar length. This is
// needed to scale the scroll delta for thumb drag.
float GetScrollerToScrollbarRatio(const ScrollbarLayerImplBase* scrollbar);
diff --git a/chromium/cc/ipc/cc_param_traits_macros.h b/chromium/cc/ipc/cc_param_traits_macros.h
index eed946bde85..4b1d723b862 100644
--- a/chromium/cc/ipc/cc_param_traits_macros.h
+++ b/chromium/cc/ipc/cc_param_traits_macros.h
@@ -6,12 +6,22 @@
#define CC_IPC_CC_PARAM_TRAITS_MACROS_H_
#include "base/component_export.h"
+#include "cc/input/overscroll_behavior.h"
#include "cc/input/touch_action.h"
#include "ipc/ipc_message_macros.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT COMPONENT_EXPORT(CC_IPC)
+IPC_ENUM_TRAITS_MAX_VALUE(
+ cc::OverscrollBehavior::OverscrollBehaviorType,
+ cc::OverscrollBehavior::OverscrollBehaviorType::kOverscrollBehaviorTypeMax)
+
+IPC_STRUCT_TRAITS_BEGIN(cc::OverscrollBehavior)
+ IPC_STRUCT_TRAITS_MEMBER(x)
+ IPC_STRUCT_TRAITS_MEMBER(y)
+IPC_STRUCT_TRAITS_END()
+
IPC_ENUM_TRAITS_MAX_VALUE(cc::TouchAction, cc::TouchAction::kMax)
#endif // CC_IPC_CC_PARAM_TRAITS_MACROS_H_
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc
index e45fae1cf9f..6851763975f 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.cc
+++ b/chromium/cc/layers/heads_up_display_layer_impl.cc
@@ -553,6 +553,15 @@ void HeadsUpDisplayLayerImpl::UpdateHudContents() {
FrameRateCounter* fps_counter = layer_tree_impl()->frame_rate_counter();
fps_graph_.value = fps_counter->GetAverageFPS();
fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max);
+ current_throughput_ = layer_tree_impl()->current_universal_throughput();
+ if (current_throughput_.has_value()) {
+ if (!max_throughput.has_value() ||
+ current_throughput_.value() > max_throughput.value())
+ max_throughput = current_throughput_;
+ if (!min_throughput.has_value() ||
+ current_throughput_.value() < min_throughput.value())
+ min_throughput = current_throughput_;
+ }
}
if (debug_state.ShowMemoryStats()) {
@@ -682,7 +691,8 @@ SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
const int kHistogramWidth = 37;
int width = kGraphWidth + kHistogramWidth + 4 * kPadding;
- int height = kTitleFontHeight + kFontHeight + kGraphHeight + 6 * kPadding + 2;
+ int height =
+ 2 * kTitleFontHeight + 2 * kFontHeight + kGraphHeight + 10 * kPadding + 2;
int left = 0;
SkRect area = SkRect::MakeXYWH(left, top, width, height);
@@ -702,6 +712,7 @@ SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
SkRect::MakeXYWH(graph_bounds.right() + kGap, graph_bounds.top(),
kHistogramWidth, kGraphHeight);
+ // Draw the fps meter.
const std::string title("Frame Rate");
const std::string value_text =
base::StringPrintf("%5.1f fps", fps_graph_.value);
@@ -722,7 +733,32 @@ SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
DrawGraphLines(canvas, &flags, graph_bounds, fps_graph_);
- // Collect graph and histogram data.
+ // Draw the throughput meter.
+ int current_top = histogram_bounds.bottom() + kPadding;
+ const std::string throughput_title("Throughput");
+ const std::string throughput_value_text =
+ current_throughput_.has_value()
+ ? base::StringPrintf("%d %%", current_throughput_.value())
+ : base::StringPrintf("n/a");
+
+ VLOG(1) << throughput_value_text;
+
+ flags.setColor(DebugColors::HUDTitleColor());
+ DrawText(canvas, flags, throughput_title, TextAlign::kLeft, kTitleFontHeight,
+ title_bounds.left(), title_bounds.bottom() + current_top);
+
+ flags.setColor(DebugColors::FPSDisplayTextAndGraphColor());
+ DrawText(canvas, flags, throughput_value_text, TextAlign::kLeft, kFontHeight,
+ text_bounds.left(), text_bounds.bottom() + current_top);
+ if (min_throughput.has_value()) {
+ const std::string throughput_min_max_text = base::StringPrintf(
+ "%d-%d", min_throughput.value(), max_throughput.value());
+ DrawText(canvas, flags, throughput_min_max_text, TextAlign::kRight,
+ kFontHeight, text_bounds.right(),
+ text_bounds.bottom() + current_top);
+ }
+
+ // Collect fps graph and histogram data.
SkPath path;
const int kHistogramSize = 20;
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h
index e0784ff4b21..323da1fff87 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.h
+++ b/chromium/cc/layers/heads_up_display_layer_impl.h
@@ -164,6 +164,11 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl {
int layout_shift_rects_fade_step_ = 0;
std::vector<DebugRect> paint_rects_;
std::vector<DebugRect> layout_shift_debug_rects_;
+ base::Optional<int> current_throughput_;
+ // The worst and best throughput we have seen so far, they either both have no
+ // value, or both have value.
+ base::Optional<int> min_throughput;
+ base::Optional<int> max_throughput;
base::TimeTicks time_of_last_graph_update_;
};
diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc
index f651c0b2d67..c354081f17b 100644
--- a/chromium/cc/layers/layer.cc
+++ b/chromium/cc/layers/layer.cc
@@ -80,7 +80,6 @@ Layer::Inputs::Inputs(int layer_id)
contents_opaque(false),
is_drawable(false),
double_sided(true),
- is_scrollbar(false),
has_will_change_transform_hint(false),
background_color(0) {}
@@ -1015,12 +1014,8 @@ void Layer::SetScrollable(const gfx::Size& bounds) {
SetNeedsCommit();
}
-void Layer::SetIsScrollbar(bool is_scrollbar) {
- if (inputs_.is_scrollbar == is_scrollbar)
- return;
-
- inputs_.is_scrollbar = is_scrollbar;
- SetNeedsCommit();
+bool Layer::IsScrollbarLayerForTesting() const {
+ return false;
}
void Layer::SetUserScrollable(bool horizontal, bool vertical) {
@@ -1112,16 +1107,6 @@ void Layer::SetForceRenderSurfaceForTesting(bool force) {
SetNeedsCommit();
}
-void Layer::SetDoubleSided(bool double_sided) {
- DCHECK(IsPropertyChangeAllowed());
- if (inputs_.double_sided == double_sided)
- return;
- inputs_.double_sided = double_sided;
- SetNeedsCommit();
- SetPropertyTreesNeedRebuild();
- SetSubtreePropertyChanged();
-}
-
void Layer::SetTransformTreeIndex(int index) {
DCHECK(IsPropertyChangeAllowed());
if (transform_tree_index_ == index)
@@ -1241,13 +1226,14 @@ std::string Layer::ToString() const {
" name: %s\n"
" Bounds: %s\n"
" ElementId: %s\n"
+ " HitTestable: %d\n"
" OffsetToTransformParent: %s\n"
" clip_tree_index: %d\n"
" effect_tree_index: %d\n"
" scroll_tree_index: %d\n"
" transform_tree_index: %d\n",
id(), DebugName().c_str(), bounds().ToString().c_str(),
- element_id().ToString().c_str(),
+ element_id().ToString().c_str(), HitTestable(),
offset_to_transform_parent().ToString().c_str(), clip_tree_index(),
effect_tree_index(), scroll_tree_index(), transform_tree_index());
}
@@ -1339,8 +1325,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
layer->UpdateScrollable();
- layer->set_is_scrollbar(inputs_.is_scrollbar);
-
// The property trees must be safe to access because they will be used below
// to call |SetScrollOffsetClobberActiveValue|.
DCHECK(layer->layer_tree_impl()->lifecycle().AllowsPropertyTreeAccess());
diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h
index 6b7e264a4f3..43debb199e8 100644
--- a/chromium/cc/layers/layer.h
+++ b/chromium/cc/layers/layer.h
@@ -401,8 +401,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> {
: gfx::Size();
}
- void SetIsScrollbar(bool is_scrollbar);
- bool is_scrollbar() const { return inputs_.is_scrollbar; }
+ virtual bool IsScrollbarLayerForTesting() const;
// For layer tree mode only.
// Set or get if this layer is able to be scrolled along each axis. These are
@@ -475,22 +474,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> {
return force_render_surface_for_testing_;
}
- // Set or get if this layer should continue to be visible when rotated such
- // that its back face is facing toward the camera. If false, the layer will
- // disappear when its back face is visible, but if true, the mirror image of
- // its front face will be shown. For instance, with a 180deg rotation around
- // the middle of the layer on the Y axis, if this is false then nothing is
- // visible. But if true, the layer is seen with its contents flipped along the
- // Y axis. Being single-sided applies transitively to the subtree of this
- // layer. If it is hidden because of its back face being visible, then its
- // subtree will be too (even if a subtree layer's front face would have been
- // visible).
- //
- // Note that should_check_backface_visibility() is the final computed value
- // for back face visibility, which is only for internal use.
- void SetDoubleSided(bool double_sided);
- bool double_sided() const { return inputs_.double_sided; }
-
// When true the layer may contribute to the compositor's output. When false,
// it does not. This property does not apply to children of the layer, they
// may contribute while this layer does not. The layer itself will determine
@@ -850,9 +833,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> {
bool double_sided : 1;
- // Indicates that this layer is a scrollbar.
- bool is_scrollbar : 1;
-
bool has_will_change_transform_hint : 1;
SkColor background_color;
diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc
index 13c24539bee..bb1c93f2538 100644
--- a/chromium/cc/layers/layer_impl.cc
+++ b/chromium/cc/layers/layer_impl.cc
@@ -69,7 +69,6 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
current_draw_mode_(DRAW_MODE_NONE),
has_will_change_transform_hint_(false),
needs_push_properties_(false),
- is_scrollbar_(false),
scrollbars_hidden_(false),
needs_show_scrollbars_(false),
raster_even_if_not_drawn_(false),
@@ -408,8 +407,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetBounds(bounds_);
layer->UpdateScrollable();
- layer->set_is_scrollbar(is_scrollbar_);
-
layer->UnionUpdateRect(update_rect_);
layer->UpdateDebugInfo(debug_info_.get());
@@ -512,8 +509,8 @@ void LayerImpl::SetBounds(const gfx::Size& bounds) {
NoteLayerPropertyChanged();
}
-ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() {
- return nullptr;
+bool LayerImpl::IsScrollbarLayer() const {
+ return false;
}
void LayerImpl::SetDrawsContent(bool draws_content) {
@@ -704,7 +701,6 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const {
}
state->SetBoolean("hit_testable", HitTestable());
- state->SetBoolean("can_use_lcd_text", CanUseLCDText());
state->SetBoolean("contents_opaque", contents_opaque());
state->SetBoolean("has_will_change_transform_hint",
@@ -774,32 +770,6 @@ gfx::Transform LayerImpl::ScreenSpaceTransform() const {
return draw_properties().screen_space_transform;
}
-bool LayerImpl::CanUseLCDText() const {
- if (layer_tree_impl()->settings().layers_always_allowed_lcd_text)
- return true;
- if (!layer_tree_impl()->settings().can_use_lcd_text)
- return false;
- if (!contents_opaque())
- return false;
-
- if (GetEffectTree().Node(effect_tree_index())->screen_space_opacity != 1.f)
- return false;
- if (!GetTransformTree()
- .Node(transform_tree_index())
- ->node_and_ancestors_have_only_integer_translation)
- return false;
- if (static_cast<int>(offset_to_transform_parent().x()) !=
- offset_to_transform_parent().x())
- return false;
- if (static_cast<int>(offset_to_transform_parent().y()) !=
- offset_to_transform_parent().y())
- return false;
-
- if (has_will_change_transform_hint())
- return false;
- return true;
-}
-
int LayerImpl::GetSortingContextId() const {
return GetTransformTree().Node(transform_tree_index())->sorting_context_id;
}
diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h
index c7b7845723a..95eb4828df8 100644
--- a/chromium/cc/layers/layer_impl.h
+++ b/chromium/cc/layers/layer_impl.h
@@ -51,7 +51,6 @@ struct LayerDebugInfo;
class LayerTreeImpl;
class MicroBenchmarkImpl;
class PrioritizedTile;
-class ScrollbarLayerImplBase;
class SimpleEnclosedRegion;
class Tile;
@@ -149,7 +148,7 @@ class CC_EXPORT LayerImpl {
virtual void NotifyTileStateChanged(const Tile* tile) {}
- virtual ScrollbarLayerImplBase* ToScrollbarLayer();
+ virtual bool IsScrollbarLayer() const;
// Returns true if this layer has content to draw.
void SetDrawsContent(bool draws_content);
@@ -207,8 +206,6 @@ class CC_EXPORT LayerImpl {
return performance_properties_;
}
- bool CanUseLCDText() const;
-
// Setter for draw_properties_.
void set_visible_layer_rect(const gfx::Rect& visible_rect) {
draw_properties_.visible_layer_rect = visible_rect;
@@ -360,10 +357,6 @@ class CC_EXPORT LayerImpl {
return contributes_to_drawn_render_surface_;
}
- bool is_scrollbar() const { return is_scrollbar_; }
-
- void set_is_scrollbar(bool is_scrollbar) { is_scrollbar_ = is_scrollbar; }
-
void set_may_contain_video(bool yes) { may_contain_video_ = yes; }
bool may_contain_video() const { return may_contain_video_; }
@@ -507,13 +500,12 @@ class CC_EXPORT LayerImpl {
DrawMode current_draw_mode_;
EffectTree& GetEffectTree() const;
-
- private:
PropertyTrees* GetPropertyTrees() const;
ClipTree& GetClipTree() const;
ScrollTree& GetScrollTree() const;
TransformTree& GetTransformTree() const;
+ private:
ElementId element_id_;
// Element ID of the document containing this layer.
ElementId frame_element_id_;
@@ -535,7 +527,6 @@ class CC_EXPORT LayerImpl {
bool has_will_change_transform_hint_ : 1;
bool needs_push_properties_ : 1;
- bool is_scrollbar_ : 1;
bool scrollbars_hidden_ : 1;
// The needs_show_scrollbars_ bit tracks a pending request from Blink to show
diff --git a/chromium/cc/layers/layer_perftest.cc b/chromium/cc/layers/layer_perftest.cc
index 60f73ee4c5a..5218685e1d4 100644
--- a/chromium/cc/layers/layer_perftest.cc
+++ b/chromium/cc/layers/layer_perftest.cc
@@ -74,7 +74,6 @@ TEST_F(LayerPerfTest, PushPropertiesTo) {
float transform_origin_z = 0;
bool scrollable = true;
bool contents_opaque = true;
- bool double_sided = true;
bool hide_layer_and_subtree = true;
bool masks_to_bounds = true;
@@ -84,7 +83,6 @@ TEST_F(LayerPerfTest, PushPropertiesTo) {
test_layer->SetNeedsDisplayRect(gfx::Rect(5, 5));
test_layer->SetTransformOrigin(gfx::Point3F(0.f, 0.f, transform_origin_z));
test_layer->SetContentsOpaque(contents_opaque);
- test_layer->SetDoubleSided(double_sided);
test_layer->SetHideLayerAndSubtree(hide_layer_and_subtree);
test_layer->SetMasksToBounds(masks_to_bounds);
test_layer->PushPropertiesTo(impl_layer.get());
@@ -92,7 +90,6 @@ TEST_F(LayerPerfTest, PushPropertiesTo) {
transform_origin_z += 0.01f;
scrollable = !scrollable;
contents_opaque = !contents_opaque;
- double_sided = !double_sided;
hide_layer_and_subtree = !hide_layer_and_subtree;
masks_to_bounds = !masks_to_bounds;
diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc
index eb64652b974..c49c99b106f 100644
--- a/chromium/cc/layers/layer_unittest.cc
+++ b/chromium/cc/layers/layer_unittest.cc
@@ -360,14 +360,6 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) {
grand_child->PushPropertiesTo(grand_child_impl.get()));
EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
- EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetDoubleSided(false));
- EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
- top->PushPropertiesTo(top_impl.get());
- child->PushPropertiesTo(child_impl.get());
- child2->PushPropertiesTo(child2_impl.get());
- grand_child->PushPropertiesTo(grand_child_impl.get()));
-
- EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetHideLayerAndSubtree(true));
EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
top->PushPropertiesTo(top_impl.get());
@@ -937,7 +929,6 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) {
Region(gfx::Rect(1, 1, 2, 2))));
EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTransform(
gfx::Transform(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)));
- EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetDoubleSided(false));
TouchActionRegion touch_action_region;
touch_action_region.Union(TouchAction::kNone, gfx::Rect(10, 10));
EXPECT_SET_NEEDS_COMMIT(
diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.cc b/chromium/cc/layers/painted_overlay_scrollbar_layer.cc
index cc62a68d921..2014160a634 100644
--- a/chromium/cc/layers/painted_overlay_scrollbar_layer.cc
+++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -30,6 +30,15 @@ std::unique_ptr<LayerImpl> PaintedOverlayScrollbarLayer::CreateLayerImpl(
}
scoped_refptr<PaintedOverlayScrollbarLayer>
+PaintedOverlayScrollbarLayer::CreateOrReuse(
+ scoped_refptr<Scrollbar> scrollbar,
+ PaintedOverlayScrollbarLayer* existing_layer) {
+ if (existing_layer && existing_layer->scrollbar_->IsSame(*scrollbar))
+ return existing_layer;
+ return Create(std::move(scrollbar));
+}
+
+scoped_refptr<PaintedOverlayScrollbarLayer>
PaintedOverlayScrollbarLayer::Create(scoped_refptr<Scrollbar> scrollbar) {
return base::WrapRefCounted(
new PaintedOverlayScrollbarLayer(std::move(scrollbar)));
@@ -180,7 +189,7 @@ bool PaintedOverlayScrollbarLayer::PaintTickmarks() {
}
ScrollbarLayerBase::ScrollbarLayerType
-PaintedOverlayScrollbarLayer::ScrollbarLayerTypeForTesting() const {
+PaintedOverlayScrollbarLayer::GetScrollbarLayerType() const {
return kPaintedOverlay;
}
diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.h b/chromium/cc/layers/painted_overlay_scrollbar_layer.h
index cdb192deee0..8651c6f4144 100644
--- a/chromium/cc/layers/painted_overlay_scrollbar_layer.h
+++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.h
@@ -21,18 +21,22 @@ class CC_EXPORT PaintedOverlayScrollbarLayer : public ScrollbarLayerBase {
public:
std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
+ static scoped_refptr<PaintedOverlayScrollbarLayer> CreateOrReuse(
+ scoped_refptr<Scrollbar> scrollbar,
+ PaintedOverlayScrollbarLayer* existing_layer);
+ static scoped_refptr<PaintedOverlayScrollbarLayer> Create(
+ scoped_refptr<Scrollbar> scrollbar);
+
PaintedOverlayScrollbarLayer(const PaintedOverlayScrollbarLayer&) = delete;
PaintedOverlayScrollbarLayer& operator=(const PaintedOverlayScrollbarLayer&) =
delete;
- static scoped_refptr<PaintedOverlayScrollbarLayer> Create(
- scoped_refptr<Scrollbar> scrollbar);
bool OpacityCanAnimateOnImplThread() const override;
bool Update() override;
void SetLayerTreeHost(LayerTreeHost* host) override;
void PushPropertiesTo(LayerImpl* layer) override;
- ScrollbarLayerType ScrollbarLayerTypeForTesting() const override;
+ ScrollbarLayerType GetScrollbarLayerType() const override;
protected:
explicit PaintedOverlayScrollbarLayer(scoped_refptr<Scrollbar> scrollbar);
diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc
index 2a5745d38af..84f6b872302 100644
--- a/chromium/cc/layers/painted_scrollbar_layer.cc
+++ b/chromium/cc/layers/painted_scrollbar_layer.cc
@@ -20,6 +20,14 @@ std::unique_ptr<LayerImpl> PaintedScrollbarLayer::CreateLayerImpl(
is_overlay_);
}
+scoped_refptr<PaintedScrollbarLayer> PaintedScrollbarLayer::CreateOrReuse(
+ scoped_refptr<Scrollbar> scrollbar,
+ PaintedScrollbarLayer* existing_layer) {
+ if (existing_layer && existing_layer->scrollbar_->IsSame(*scrollbar))
+ return existing_layer;
+ return Create(std::move(scrollbar));
+}
+
scoped_refptr<PaintedScrollbarLayer> PaintedScrollbarLayer::Create(
scoped_refptr<Scrollbar> scrollbar) {
return base::WrapRefCounted(new PaintedScrollbarLayer(std::move(scrollbar)));
@@ -237,7 +245,7 @@ UIResourceBitmap PaintedScrollbarLayer::RasterizeScrollbarPart(
}
ScrollbarLayerBase::ScrollbarLayerType
-PaintedScrollbarLayer::ScrollbarLayerTypeForTesting() const {
+PaintedScrollbarLayer::GetScrollbarLayerType() const {
return kPainted;
}
diff --git a/chromium/cc/layers/painted_scrollbar_layer.h b/chromium/cc/layers/painted_scrollbar_layer.h
index e910a004849..191c37d8e5a 100644
--- a/chromium/cc/layers/painted_scrollbar_layer.h
+++ b/chromium/cc/layers/painted_scrollbar_layer.h
@@ -21,6 +21,9 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerBase {
public:
std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
+ static scoped_refptr<PaintedScrollbarLayer> CreateOrReuse(
+ scoped_refptr<Scrollbar> scrollbar,
+ PaintedScrollbarLayer* existing_layer);
static scoped_refptr<PaintedScrollbarLayer> Create(
scoped_refptr<Scrollbar> scrollbar);
@@ -36,7 +39,7 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerBase {
return internal_content_bounds_;
}
- ScrollbarLayerType ScrollbarLayerTypeForTesting() const override;
+ ScrollbarLayerType GetScrollbarLayerType() const override;
protected:
explicit PaintedScrollbarLayer(scoped_refptr<Scrollbar> scrollbar);
diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc
index 957bcef1174..b7244152c31 100644
--- a/chromium/cc/layers/picture_layer.cc
+++ b/chromium/cc/layers/picture_layer.cc
@@ -15,6 +15,7 @@
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/transform_node.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/gfx/geometry/rect_conversions.h"
namespace cc {
@@ -139,6 +140,24 @@ bool PictureLayer::Update() {
picture_layer_inputs_.display_list =
picture_layer_inputs_.client->PaintContentsToDisplayList(
ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
+
+ // Clear out previous directly composited image state - if the layer
+ // qualifies we'll set up the state below.
+ picture_layer_inputs_.directly_composited_image_size = base::nullopt;
+ picture_layer_inputs_.nearest_neighbor = false;
+ base::Optional<DisplayItemList::DirectlyCompositedImageResult> result =
+ picture_layer_inputs_.display_list->GetDirectlyCompositedImageResult(
+ bounds());
+ if (result) {
+ // Directly composited images are not guaranteed to fully cover every
+ // pixel in the layer due to ceiling when calculating the tile content
+ // rect from the layer bounds.
+ recording_source_->SetRequiresClear(true);
+ picture_layer_inputs_.directly_composited_image_size =
+ result->intrinsic_image_size;
+ picture_layer_inputs_.nearest_neighbor = result->nearest_neighbor;
+ }
+
picture_layer_inputs_.painter_reported_memory_usage =
picture_layer_inputs_.client->GetApproximateUnsharedMemoryUsage();
recording_source_->UpdateDisplayItemList(
@@ -158,33 +177,18 @@ bool PictureLayer::Update() {
}
sk_sp<SkPicture> PictureLayer::GetPicture() const {
- // We could either flatten the RecordingSource into a single SkPicture, or
- // paint a fresh one depending on what we intend to do with it. For now we
- // just paint a fresh one to get consistent results.
- if (!DrawsContent())
+ if (!DrawsContent() || bounds().IsEmpty())
return nullptr;
- gfx::Size layer_size = bounds();
- RecordingSource recording_source;
- Region recording_invalidation;
-
- gfx::Rect new_recorded_viewport =
- picture_layer_inputs_.client->PaintableRegion();
scoped_refptr<DisplayItemList> display_list =
picture_layer_inputs_.client->PaintContentsToDisplayList(
ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
- size_t painter_reported_memory_usage =
- picture_layer_inputs_.client->GetApproximateUnsharedMemoryUsage();
-
- recording_source.UpdateAndExpandInvalidation(
- &recording_invalidation, layer_size, new_recorded_viewport);
- recording_source.UpdateDisplayItemList(
- display_list, painter_reported_memory_usage,
- layer_tree_host()->recording_scale_factor());
-
- scoped_refptr<RasterSource> raster_source =
- recording_source.CreateRasterSource();
- return raster_source->GetFlattenedPicture();
+ SkPictureRecorder recorder;
+ SkCanvas* canvas =
+ recorder.beginRecording(bounds().width(), bounds().height());
+ canvas->clear(SK_ColorTRANSPARENT);
+ display_list->Raster(canvas);
+ return recorder.finishRecordingAsPicture();
}
void PictureLayer::ClearClient() {
diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc
index e1e9864e812..00e845e2b3f 100644
--- a/chromium/cc/layers/picture_layer_impl.cc
+++ b/chromium/cc/layers/picture_layer_impl.cc
@@ -29,6 +29,7 @@
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/occlusion.h"
+#include "cc/trees/transform_node.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/picture_draw_quad.h"
@@ -96,8 +97,9 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
only_used_low_res_last_append_quads_(false),
nearest_neighbor_(false),
use_transformed_rasterization_(false),
- can_use_lcd_text_(true),
+ lcd_text_disallowed_reason_(LCDTextDisallowedReason::kNone),
directly_composited_image_size_(base::nullopt),
+ directly_composited_image_initial_raster_scale_(0.f),
tile_size_calculator_(this) {
layer_tree_impl()->RegisterPictureLayerImpl(this);
}
@@ -175,10 +177,12 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
layer_impl->raster_source_scale_ = raster_source_scale_;
layer_impl->raster_contents_scale_ = raster_contents_scale_;
layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
+ layer_impl->directly_composited_image_initial_raster_scale_ =
+ directly_composited_image_initial_raster_scale_;
// Simply push the value to the active tree without any extra invalidations,
// since the pending tree tiles would have this handled. This is here to
// ensure the state is consistent for future raster.
- layer_impl->can_use_lcd_text_ = can_use_lcd_text_;
+ layer_impl->lcd_text_disallowed_reason_ = lcd_text_disallowed_reason_;
layer_impl->SanityCheckTilingState();
}
@@ -241,6 +245,41 @@ void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass,
tilings_->num_tilings() ? MaximumTilingContentsScale() : 1.f;
PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
contents_opaque());
+
+ if (directly_composited_image_size_) {
+ // Directly composited images should be clipped to the layer's content rect.
+ // When a PictureLayerTiling is created for a directly composited image, the
+ // layer bounds are multiplied by the raster scale in order to compute the
+ // tile size. If the aspect ratio of the layer doesn't match that of the
+ // image, it's possible that one of the dimensions of the resulting size
+ // (layer bounds * raster scale) is a fractional number, as raster scale
+ // does not scale x and y independently.
+ // When this happens, the ToEnclosingRect() operation in
+ // |PictureLayerTiling::EnclosingContentsRectFromLayer()| will
+ // create a tiling that, when scaled by |max_contents_scale| above, is
+ // larger than the layer bounds by a fraction of a pixel.
+ gfx::Rect clip_rect = draw_properties().drawable_content_rect;
+ if (shared_quad_state->is_clipped)
+ clip_rect.Intersect(shared_quad_state->clip_rect);
+
+ shared_quad_state->is_clipped = true;
+ shared_quad_state->clip_rect = clip_rect;
+
+#if DCHECK_IS_ON()
+ // Validate that the tile and bounds size are always within one pixel.
+ PictureLayerTiling* high_res =
+ tilings_->FindTilingWithResolution(HIGH_RESOLUTION);
+ if (high_res) {
+ const float epsilon = 1.f;
+ gfx::SizeF scaled_tiling_size(high_res->tiling_size());
+ scaled_tiling_size.Scale(1 / raster_contents_scale_);
+ DCHECK(std::abs(bounds().width() - scaled_tiling_size.width()) < epsilon);
+ DCHECK(std::abs(bounds().height() - scaled_tiling_size.height()) <
+ epsilon);
+ }
+#endif
+ }
+
Occlusion scaled_occlusion =
draw_properties()
.occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
@@ -359,6 +398,18 @@ void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass,
}
}
+ if (layer_tree_impl()->debug_state().highlight_non_lcd_text_layers) {
+ SkColor color =
+ DebugColors::NonLCDTextHighlightColor(lcd_text_disallowed_reason());
+ if (color != SK_ColorTRANSPARENT &&
+ GetRasterSource()->GetDisplayItemList()->AreaOfDrawText(
+ gfx::Rect(bounds()))) {
+ render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>()->SetNew(
+ shared_quad_state, debug_border_rect, debug_border_rect, color,
+ append_quads_data);
+ }
+ }
+
// Keep track of the tilings that were used so that tilings that are
// unused can be considered for removal.
last_append_quads_tilings_.clear();
@@ -542,9 +593,14 @@ bool PictureLayerImpl::UpdateTiles() {
if (layer_tree_impl()->IsActiveTree())
CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);
+ const float old_ideal_contents_scale = ideal_contents_scale_;
UpdateIdealScales();
- if (!raster_contents_scale_ || ShouldAdjustRasterScale()) {
+ const bool ideal_contents_scale_changed =
+ old_ideal_contents_scale != 0 &&
+ old_ideal_contents_scale != ideal_contents_scale_;
+ if (!raster_contents_scale_ ||
+ ShouldAdjustRasterScale(ideal_contents_scale_changed)) {
RecalculateRasterScales();
AddTilingsForRasterScale();
}
@@ -706,7 +762,7 @@ void PictureLayerImpl::UpdateRasterSource(
// The |raster_source_| is initially null, so have to check for that for the
// first frame.
- bool could_have_tilings = raster_source_.get() && CanHaveTilings();
+ bool could_have_tilings = CanHaveTilings();
raster_source_.swap(raster_source);
// Register images from the new raster source, if the recording was updated.
@@ -758,13 +814,14 @@ bool PictureLayerImpl::UpdateCanUseLCDTextAfterCommit() {
DCHECK(layer_tree_impl()->IsSyncTree());
// Once we disable lcd text, we don't re-enable it.
- if (!can_use_lcd_text_)
+ if (!can_use_lcd_text())
return false;
- if (can_use_lcd_text_ == CanUseLCDText())
+ auto new_lcd_text_disallowed_reason = ComputeLCDTextDisallowedReason();
+ if (lcd_text_disallowed_reason_ == new_lcd_text_disallowed_reason)
return false;
- can_use_lcd_text_ = CanUseLCDText();
+ lcd_text_disallowed_reason_ = new_lcd_text_disallowed_reason;
// Synthetically invalidate everything.
gfx::Rect bounds_rect(bounds());
invalidation_ = Region(bounds_rect);
@@ -773,6 +830,35 @@ bool PictureLayerImpl::UpdateCanUseLCDTextAfterCommit() {
return true;
}
+LCDTextDisallowedReason PictureLayerImpl::ComputeLCDTextDisallowedReason()
+ const {
+ if (layer_tree_impl()->settings().layers_always_allowed_lcd_text)
+ return LCDTextDisallowedReason::kNone;
+ if (!layer_tree_impl()->settings().can_use_lcd_text)
+ return LCDTextDisallowedReason::kSetting;
+ if (!contents_opaque()) {
+ if (SkColorGetA(background_color()) != SK_AlphaOPAQUE)
+ return LCDTextDisallowedReason::kBackgroundColorNotOpaque;
+ return LCDTextDisallowedReason::kContentsNotOpaque;
+ }
+
+ if (!GetTransformTree()
+ .Node(transform_tree_index())
+ ->node_and_ancestors_have_only_integer_translation)
+ return LCDTextDisallowedReason::kNonIntegralTranslation;
+ if (static_cast<int>(offset_to_transform_parent().x()) !=
+ offset_to_transform_parent().x())
+ return LCDTextDisallowedReason::kNonIntegralXOffset;
+ if (static_cast<int>(offset_to_transform_parent().y()) !=
+ offset_to_transform_parent().y())
+ return LCDTextDisallowedReason::kNonIntegralYOffset;
+
+ if (has_will_change_transform_hint())
+ return LCDTextDisallowedReason::kWillChangeTransform;
+
+ return LCDTextDisallowedReason::kNone;
+}
+
void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
if (layer_tree_impl()->IsActiveTree())
damage_rect_.Union(tile->enclosing_layer_rect());
@@ -837,7 +923,7 @@ std::unique_ptr<Tile> PictureLayerImpl::CreateTile(
return layer_tree_impl()->tile_manager()->CreateTile(
info, id(), layer_tree_impl()->source_frame_number(), flags,
- can_use_lcd_text_);
+ can_use_lcd_text());
}
const Region* PictureLayerImpl::GetPendingInvalidation() {
@@ -996,16 +1082,91 @@ void PictureLayerImpl::SetDirectlyCompositedImageSize(
NoteLayerPropertyChanged();
}
-float PictureLayerImpl::GetDirectlyCompositedImageRasterScale() const {
+bool PictureLayerImpl::ShouldDirectlyCompositeImage(float raster_scale) const {
+ // If the results of scaling the bounds by the expected raster scale
+ // would end up with a content rect whose width/height are more than one
+ // pixel different from the layer bounds, don't directly composite the image
+ // to avoid incorrect rendering.
+ gfx::SizeF layer_bounds(bounds());
+ gfx::RectF scaled_bounds_rect(layer_bounds);
+ scaled_bounds_rect.Scale(raster_scale);
+
+ // Take the scaled bounds, get the enclosing rect then scale it back down -
+ // this is the same set of operations that will happen when using the tiling
+ // at that raster scale.
+ gfx::RectF content_rect(gfx::ToEnclosingRect(scaled_bounds_rect));
+ content_rect.Scale(1 / raster_scale);
+
+ return std::abs(layer_bounds.width() - content_rect.width()) < 1.f &&
+ std::abs(layer_bounds.height() - content_rect.height()) < 1.f;
+}
+
+float PictureLayerImpl::GetDefaultDirectlyCompositedImageRasterScale() const {
+ DCHECK(directly_composited_image_size_.has_value());
float x = static_cast<float>(directly_composited_image_size_->width()) /
bounds().width();
float y = static_cast<float>(directly_composited_image_size_->height()) /
bounds().height();
- DCHECK_EQ(x, 1.f);
- DCHECK_EQ(y, 1.f);
return GetPreferredRasterScale(gfx::Vector2dF(x, y));
}
+float PictureLayerImpl::CalculateDirectlyCompositedImageRasterScale() const {
+ float default_raster_scale = GetDefaultDirectlyCompositedImageRasterScale();
+ bool default_raster_scale_changed =
+ default_raster_scale != directly_composited_image_initial_raster_scale_;
+
+ // If the default raster scale didn't change, we will calculate based on the
+ // previous raster source scale. The calculation may change based on updated
+ // ideal source scale.
+ float adjusted_raster_scale = default_raster_scale_changed
+ ? default_raster_scale
+ : raster_source_scale_;
+
+ // We never want a raster scale larger than the default, since that uses more
+ // memory but can't result it better quality (upscaling will happen in the
+ // display compositor instead).
+ float max_scale = std::max(default_raster_scale, MinimumContentsScale());
+ float min_scale = MinimumContentsScale();
+
+ float clamped_ideal_source_scale =
+ base::ClampToRange(ideal_source_scale_, min_scale, max_scale);
+ while (adjusted_raster_scale < clamped_ideal_source_scale)
+ adjusted_raster_scale *= 2.f;
+ while (adjusted_raster_scale > 4 * clamped_ideal_source_scale)
+ adjusted_raster_scale /= 2.f;
+
+ adjusted_raster_scale =
+ base::ClampToRange(adjusted_raster_scale, min_scale, max_scale);
+ return adjusted_raster_scale;
+}
+
+// Log either the tile area saved or added due to directly compositing an
+// image. This is logged every time we choose a raster source scale for a
+// directly composited image.
+void PictureLayerImpl::LogDirectlyCompositedImageRasterScaleUMAs() const {
+ base::CheckedNumeric<int> actual_area =
+ ScaleToCeiledSize(bounds(), raster_source_scale_).GetCheckedArea();
+ base::CheckedNumeric<int> ideal_area =
+ ScaleToCeiledSize(bounds(), ideal_source_scale_).GetCheckedArea();
+ if (actual_area.IsValid() && ideal_area.IsValid()) {
+ int area_difference =
+ std::abs(static_cast<int>((actual_area - ideal_area).ValueOrDie()));
+ bool raster_area_matches = raster_source_scale_ == ideal_source_scale_;
+ UMA_HISTOGRAM_BOOLEAN(
+ "Compositing.Renderer.DirectlyCompositedImage.TileAreaMatches",
+ raster_area_matches);
+ if (raster_source_scale_ < ideal_source_scale_) {
+ UMA_HISTOGRAM_COUNTS_10M(
+ "Compositing.Renderer.DirectlyCompositedImage.TileAreaSaved",
+ area_difference);
+ } else if (raster_source_scale_ > ideal_source_scale_) {
+ UMA_HISTOGRAM_COUNTS_10M(
+ "Compositing.Renderer.DirectlyCompositedImage.TileAreaAdded",
+ area_difference);
+ }
+ }
+}
+
PictureLayerTiling* PictureLayerImpl::AddTiling(
const gfx::AxisTransform2d& contents_transform) {
DCHECK(CanHaveTilings());
@@ -1053,29 +1214,76 @@ void PictureLayerImpl::AddTilingsForRasterScale() {
}
high_res->set_resolution(HIGH_RESOLUTION);
- if (layer_tree_impl()->IsPendingTree()) {
+ if (layer_tree_impl()->IsPendingTree() ||
+ (layer_tree_impl()->settings().commit_to_active_tree &&
+ directly_composited_image_size_.has_value())) {
// On the pending tree, drop any tilings that are non-ideal since we don't
// need them to activate anyway.
+
+ // For DirectlyCompositedImages, if we recomputed a new raster scale, we
+ // should drop the non-ideal ones if we're committing to the active tree.
+ // Otherwise a non-ideal scale that is _larger_ than the HIGH_RESOLUTION
+ // tile will be used as the coverage scale, and we'll produce a slightly
+ // different rendering. We don't drop the tilings on the active tree if
+ // we're not committing to the active tree to prevent checkerboarding.
tilings_->RemoveNonIdealTilings();
}
SanityCheckTilingState();
}
-bool PictureLayerImpl::ShouldAdjustRasterScale() const {
+bool PictureLayerImpl::ShouldAdjustRasterScale(
+ bool ideal_contents_scale_changed) const {
if (directly_composited_image_size_) {
- float desired_raster_scale = GetDirectlyCompositedImageRasterScale();
- float max_scale = std::max(desired_raster_scale, MinimumContentsScale());
+ // If we have a directly composited image size, but previous raster scale
+ // calculations did not set an initial raster scale, we must recalcluate.
+ if (directly_composited_image_initial_raster_scale_ == 0)
+ return true;
+
+ float default_raster_scale = GetDefaultDirectlyCompositedImageRasterScale();
+
+ // First check to see if we need to adjust based on ideal_source_scale_
+ // changing (i.e. scale transform has been modified). These limits exist
+ // so that we don't raster at the intrinsic image size if the layer will
+ // be scaled down more than 4x ideal. This saves memory without sacrificing
+ // noticeable quality. We'll also bump the scale back up in the case where
+ // the ideal scale is increased.
+ float max_scale = std::max(default_raster_scale, MinimumContentsScale());
if (raster_source_scale_ < std::min(ideal_source_scale_, max_scale))
return true;
if (raster_source_scale_ > 4 * ideal_source_scale_)
return true;
- return false;
+
+ // If the default raster scale changed, that means the bounds or image size
+ // changed. We should recalculate in order to raster at the intrinsic image
+ // size. Note that this is not a comparison of the used raster_source_scale_
+ // and desired because of the adjustments in RecalculateRasterScales.
+ bool default_raster_scale_changed =
+ default_raster_scale != directly_composited_image_initial_raster_scale_;
+ if (ideal_contents_scale_changed && !default_raster_scale_changed) {
+ // Log a histogram to indicate that we most likely saved raster costs,
+ // if the ideal contents scale changed but we did not need to recalculate
+ // raster scales because this layer is a directly composited image.
+ bool transform_trigger =
+ draw_properties().screen_space_transform_is_animating ||
+ has_will_change_transform_hint();
+ UMA_HISTOGRAM_BOOLEAN(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ transform_trigger);
+ }
+ return default_raster_scale_changed;
}
if (was_screen_space_transform_animating_ !=
- draw_properties().screen_space_transform_is_animating)
- return true;
+ draw_properties().screen_space_transform_is_animating) {
+ // Skip adjusting raster scale when animations finish if we have a
+ // will-change: transform hint to preserve maximum resolution tiles
+ // needed.
+ if (draw_properties().screen_space_transform_is_animating ||
+ !has_will_change_transform_hint())
+ return true;
+ }
bool is_pinching = layer_tree_impl()->PinchGestureActive();
if (is_pinching && raster_page_scale_) {
@@ -1153,33 +1361,39 @@ void PictureLayerImpl::AddLowResolutionTilingIfNeeded() {
void PictureLayerImpl::RecalculateRasterScales() {
if (directly_composited_image_size_) {
- if (!raster_source_scale_)
- raster_source_scale_ = GetDirectlyCompositedImageRasterScale();
-
- float min_scale = MinimumContentsScale();
- float desired_raster_scale = GetDirectlyCompositedImageRasterScale();
- float max_scale = std::max(desired_raster_scale, MinimumContentsScale());
- float clamped_ideal_source_scale =
- base::ClampToRange(ideal_source_scale_, min_scale, max_scale);
-
- while (raster_source_scale_ < clamped_ideal_source_scale)
- raster_source_scale_ *= 2.f;
- while (raster_source_scale_ > 4 * clamped_ideal_source_scale)
- raster_source_scale_ /= 2.f;
-
- raster_source_scale_ =
- base::ClampToRange(raster_source_scale_, min_scale, max_scale);
-
- raster_page_scale_ = 1.f;
- raster_device_scale_ = 1.f;
- raster_contents_scale_ = raster_source_scale_;
- low_res_raster_contents_scale_ = raster_contents_scale_;
- return;
+ float used_raster_scale = CalculateDirectlyCompositedImageRasterScale();
+ const bool should_directly_composite =
+ ShouldDirectlyCompositeImage(used_raster_scale);
+
+ UMA_HISTOGRAM_BOOLEAN(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ should_directly_composite);
+ if (should_directly_composite) {
+ directly_composited_image_initial_raster_scale_ =
+ GetDefaultDirectlyCompositedImageRasterScale();
+ raster_source_scale_ = used_raster_scale;
+ raster_page_scale_ = 1.f;
+ raster_device_scale_ = 1.f;
+ raster_contents_scale_ = raster_source_scale_;
+ low_res_raster_contents_scale_ = raster_contents_scale_;
+
+ LogDirectlyCompositedImageRasterScaleUMAs();
+ return;
+ }
+
+ // If we should not directly composite this image, reset values and fall
+ // back to normal raster scale calculations below.
+ directly_composited_image_size_ = base::nullopt;
+ directly_composited_image_initial_raster_scale_ = 0.f;
}
float old_raster_contents_scale = raster_contents_scale_;
float old_raster_page_scale = raster_page_scale_;
+ // The raster scale if previous tilings should be preserved.
+ float preserved_raster_contents_scale = old_raster_contents_scale;
+
raster_device_scale_ = ideal_device_scale_;
raster_page_scale_ = ideal_page_scale_;
raster_source_scale_ = ideal_source_scale_;
@@ -1201,8 +1415,9 @@ void PictureLayerImpl::RecalculateRasterScales() {
while (desired_contents_scale < ideal_contents_scale_)
desired_contents_scale *= kMaxScaleRatioDuringPinch;
}
- raster_contents_scale_ = tilings_->GetSnappedContentsScaleKey(
- desired_contents_scale, kSnapToExistingTilingRatio);
+ raster_contents_scale_ = preserved_raster_contents_scale =
+ tilings_->GetSnappedContentsScaleKey(desired_contents_scale,
+ kSnapToExistingTilingRatio);
raster_page_scale_ =
raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
}
@@ -1252,15 +1467,27 @@ void PictureLayerImpl::RecalculateRasterScales() {
if (start_area <= viewport_area)
should_raster_at_starting_scale = true;
}
+
// Use the computed scales for the raster scale directly, do not try to use
// the ideal scale here. The current ideal scale may be way too large in the
// case of an animation with scale, and will be constantly changing.
+ float animation_desired_scale;
if (should_raster_at_starting_scale)
- raster_contents_scale_ = starting_scale;
+ animation_desired_scale = starting_scale;
else if (can_raster_at_maximum_scale)
- raster_contents_scale_ = maximum_scale;
+ animation_desired_scale = maximum_scale;
else
- raster_contents_scale_ = 1.f * ideal_page_scale_ * ideal_device_scale_;
+ animation_desired_scale = 1.f * ideal_page_scale_ * ideal_device_scale_;
+
+ if (has_will_change_transform_hint()) {
+ // If we have a will-change: transform hint, do not shrink the content
+ // raster scale, otherwise we will end up throwing away larger tiles we
+ // may need again.
+ raster_contents_scale_ =
+ std::max(preserved_raster_contents_scale, animation_desired_scale);
+ } else {
+ raster_contents_scale_ = animation_desired_scale;
+ }
}
// Clamp will-change: transform layers to be at least the native scale.
@@ -1378,7 +1605,13 @@ float PictureLayerImpl::MinimumContentsScale() const {
if (!min_dimension)
return setting_min;
- return std::max(1.f / min_dimension, setting_min);
+ // Directly composited images may result in contents scales that are
+ // less than the configured setting. We allow this lower scale so that we
+ // can raster at the intrinsic image size.
+ const float inverse_min_dimension = 1.f / min_dimension;
+ return (directly_composited_image_size_.has_value())
+ ? inverse_min_dimension
+ : std::max(inverse_min_dimension, setting_min);
}
float PictureLayerImpl::MaximumContentsScale() const {
@@ -1409,9 +1642,12 @@ void PictureLayerImpl::ResetRasterScale() {
raster_source_scale_ = 0.f;
raster_contents_scale_ = 0.f;
low_res_raster_contents_scale_ = 0.f;
+ directly_composited_image_initial_raster_scale_ = 0.f;
}
bool PictureLayerImpl::CanHaveTilings() const {
+ if (!raster_source_)
+ return false;
if (raster_source_->IsSolidColor())
return false;
if (!DrawsContent())
@@ -1526,6 +1762,10 @@ void PictureLayerImpl::AsValueInto(
state);
MathUtil::AddToTracedValue("visible_rect", visible_layer_rect(), state);
+ state->SetString(
+ "lcd_text_disallowed_reason",
+ LCDTextDisallowedReasonToString(lcd_text_disallowed_reason_));
+
state->BeginArray("pictures");
raster_source_->AsValueInto(state);
state->EndArray();
diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h
index 1061fc68370..0be0cf1c68a 100644
--- a/chromium/cc/layers/picture_layer_impl.h
+++ b/chromium/cc/layers/picture_layer_impl.h
@@ -18,6 +18,7 @@
#include "cc/layers/tile_size_calculator.h"
#include "cc/paint/discardable_image_map.h"
#include "cc/paint/image_id.h"
+#include "cc/raster/lcd_text_disallowed_reason.h"
#include "cc/tiles/picture_layer_tiling.h"
#include "cc/tiles/picture_layer_tiling_set.h"
#include "cc/tiles/tiling_set_eviction_queue.h"
@@ -136,7 +137,15 @@ class CC_EXPORT PictureLayerImpl
ImageInvalidationResult InvalidateRegionForImages(
const PaintImageIdFlatSet& images_to_invalidate);
- bool can_use_lcd_text() const { return can_use_lcd_text_; }
+ bool can_use_lcd_text() const {
+ return lcd_text_disallowed_reason_ == LCDTextDisallowedReason::kNone;
+ }
+ LCDTextDisallowedReason lcd_text_disallowed_reason() const {
+ return lcd_text_disallowed_reason_;
+ }
+ LCDTextDisallowedReason ComputeLCDTextDisallowedReasonForTesting() const {
+ return ComputeLCDTextDisallowedReason();
+ }
const Region& InvalidationForTesting() const { return invalidation_; }
@@ -164,7 +173,7 @@ class CC_EXPORT PictureLayerImpl
void RemoveAllTilings();
void AddTilingsForRasterScale();
void AddLowResolutionTilingIfNeeded();
- bool ShouldAdjustRasterScale() const;
+ bool ShouldAdjustRasterScale(bool ideal_contents_scale_changed) const;
void RecalculateRasterScales();
gfx::Vector2dF CalculateRasterTranslation(float raster_scale);
void CleanUpTilingsOnActiveLayer(
@@ -173,7 +182,21 @@ class CC_EXPORT PictureLayerImpl
float MaximumContentsScale() const;
void UpdateViewportRectForTilePriorityInContentSpace();
PictureLayerImpl* GetRecycledTwinLayer() const;
- float GetDirectlyCompositedImageRasterScale() const;
+ bool ShouldDirectlyCompositeImage(float raster_scale) const;
+
+ // Returns the default raster scale used for current layer bounds and directly
+ // composited image size. To avoid re-raster on scale changes, this may be
+ // different than the used raster scale, see: |RecalculateRasterScales()| and
+ // |CalculateDirectlyCompositedImageRasterScale()|.
+ float GetDefaultDirectlyCompositedImageRasterScale() const;
+
+ // Returns the raster scale that should be used for a directly composited
+ // image. This takes into account the ideal contents scale to ensure we don't
+ // use too much memory for layers that are small due to contents scale
+ // factors, and bumps up the reduced scale if those layers end up increasing
+ // their contents scale.
+ float CalculateDirectlyCompositedImageRasterScale() const;
+ void LogDirectlyCompositedImageRasterScaleUMAs() const;
void SanityCheckTilingState() const;
@@ -195,6 +218,8 @@ class CC_EXPORT PictureLayerImpl
const std::vector<DiscardableImageMap::PaintWorkletInputWithImageId>&
inputs);
+ LCDTextDisallowedReason ComputeLCDTextDisallowedReason() const;
+
PictureLayerImpl* twin_layer_;
std::unique_ptr<PictureLayerTilingSet> tilings_;
@@ -228,10 +253,20 @@ class CC_EXPORT PictureLayerImpl
bool nearest_neighbor_ : 1;
bool use_transformed_rasterization_ : 1;
- bool can_use_lcd_text_ : 1;
+ LCDTextDisallowedReason lcd_text_disallowed_reason_;
+
+ // The intrinsic size of the directly composited image. A directly composited
+ // image is an image which is the only thing drawn into a layer. In these
+ // cases we attempt to raster the image at its intrinsic size.
base::Optional<gfx::Size> directly_composited_image_size_;
+ // The default raster source scale for a directly composited image, the last
+ // time raster scales were calculated. This will be the same as
+ // |raster_source_scale_| if no adjustments were made in
+ // |CalculateDirectlyCompositedImageRasterScale()|.
+ float directly_composited_image_initial_raster_scale_;
+
// Use this instead of |visible_layer_rect()| for tiling calculations. This
// takes external viewport and transform for tile priority into account.
gfx::Rect viewport_rect_for_tile_priority_in_content_space_;
diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc
index 2631d7ed1e5..25fff7cb2ae 100644
--- a/chromium/cc/layers/picture_layer_impl_unittest.cc
+++ b/chromium/cc/layers/picture_layer_impl_unittest.cc
@@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/stl_util.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/animation/animation_host.h"
#include "cc/base/math_util.h"
@@ -2880,6 +2881,66 @@ TEST_F(LegacySWPictureLayerImplTest, HighResTilingDuringAnimation) {
EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 11.f);
}
+TEST_F(LegacySWPictureLayerImplTest,
+ AnimationTilingChangesWithWillChangeTransformHint) {
+ gfx::Size viewport_size(1000, 1000);
+ host_impl()->active_tree()->SetDeviceViewportRect(gfx::Rect(viewport_size));
+
+ gfx::Size layer_bounds(100, 100);
+ SetupDefaultTrees(layer_bounds);
+
+ float contents_scale = 1.f;
+ float device_scale = 1.f;
+ float page_scale = 1.f;
+ float maximum_animation_scale = 1.f;
+ float starting_animation_scale = 0.f;
+ bool animating_transform = false;
+
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 1.f);
+
+ active_layer()->SetHasWillChangeTransformHint(true);
+ pending_layer()->SetHasWillChangeTransformHint(true);
+
+ // Starting an animation should cause tiling resolution to get set to the
+ // maximum animation scale factor.
+ animating_transform = true;
+ maximum_animation_scale = 2.f;
+ contents_scale = 1.f;
+
+ SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
+ maximum_animation_scale,
+ starting_animation_scale, animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
+
+ // Once we stop animating, because we have a will-change: transform hint
+ // we should not reset the scale factor.
+ animating_transform = false;
+
+ SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
+ maximum_animation_scale,
+ starting_animation_scale, animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
+
+ // Starting an animation with a different maximum animation scale should
+ // not cause a change either.
+ animating_transform = true;
+ maximum_animation_scale = 1.5f;
+
+ SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
+ maximum_animation_scale,
+ starting_animation_scale, animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
+
+ // Again, stop animating, because we have a will-change: transform hint
+ // we should not reset the scale factor.
+ animating_transform = false;
+
+ SetContentsScaleOnBothLayers(contents_scale, device_scale, page_scale,
+ maximum_animation_scale,
+ starting_animation_scale, animating_transform);
+ EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 2.f);
+}
+
TEST_F(LegacySWPictureLayerImplTest, HighResTilingDuringAnimationAspectRatio) {
gfx::Size viewport_size(2000, 1000);
host_impl()->active_tree()->SetDeviceViewportRect(gfx::Rect(viewport_size));
@@ -3441,6 +3502,9 @@ TEST_F(LegacySWPictureLayerImplTest, RasterScaleChangeWithoutAnimation) {
EXPECT_BOTH_EQ(HighResTiling()->contents_scale_key(), 3.f);
}
+TEST_F(LegacySWPictureLayerImplTest,
+ AnimationChangeRespectsWillChangeTransformHint) {}
+
TEST_F(LegacySWPictureLayerImplTest, LowResReadyToDrawNotEnoughToActivate) {
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(1000, 1000);
@@ -5326,6 +5390,328 @@ TEST_F(LegacySWPictureLayerImplTest, CompositedImageRasterScaleChanges) {
}
}
+TEST_F(LegacySWPictureLayerImplTest, CompositedImageRasterOnChange) {
+ gfx::Size layer_bounds(400, 400);
+ scoped_refptr<FakeRasterSource> pending_raster_source =
+ FakeRasterSource::CreateFilled(layer_bounds);
+
+ SetupPendingTree(pending_raster_source);
+
+ // Set an image size that is smaller than the layer bounds.
+ gfx::Size image_size(200, 200);
+ pending_layer()->SetDirectlyCompositedImageSize(image_size);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(0.5f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Change the bounds and ensure we recalculated raster scale.
+ pending_layer()->SetBounds(gfx::Size(320, 320));
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(0.625f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Set an image size much larger than the layer bounds (5x). Verify that the
+ // scaling down code is triggered (we should halve the raster scale until it
+ // is less than 4x the ideal source scale).
+ pending_layer()->SetBounds(layer_bounds);
+ pending_layer()->SetDirectlyCompositedImageSize(gfx::Size(2000, 2000));
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(2.5f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Update the bounds to no longer match the aspect ratio, but still compute
+ // the same raster scale.
+ pending_layer()->SetBounds(gfx::Size(600, 500));
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(4.f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Update the bounds and and bump up the ideal scale so that the scale down
+ // restriction is lifted.
+ pending_layer()->SetBounds(layer_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 4.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(5.f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Lower the ideal scale to see that the clamping still applied as it is
+ // lowered.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.5f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(1.25f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.25f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(0.625f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+}
+
+TEST_F(LegacySWPictureLayerImplTest, CompositedImageRasterOptOutTransitions) {
+ gfx::Size layer_bounds(5, 5);
+ scoped_refptr<FakeRasterSource> pending_raster_source =
+ FakeRasterSource::CreateFilled(layer_bounds);
+
+ SetupPendingTree(pending_raster_source);
+
+ // Start with image and bounds matching to have this layer initially opted
+ // in to directly composited images.
+ pending_layer()->SetBounds(layer_bounds);
+ pending_layer()->SetDirectlyCompositedImageSize(layer_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.3f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(1.f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Change the image and bounds to values that make the layer not eligible for
+ // direct compositing. This must be reflected by a |contents_scale_key()| of
+ // 0.1f (matching the ideal source scale).
+ gfx::Size image_size(300, 300);
+ pending_layer()->SetDirectlyCompositedImageSize(image_size);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.2f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(0.2f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+
+ // Ensure we get back to a directly composited image if the input values
+ // change such that the optimization should apply.
+ pending_layer()->SetBounds(ScaleToFlooredSize(layer_bounds, 2));
+ pending_layer()->SetDirectlyCompositedImageSize(
+ ScaleToFlooredSize(image_size, 2));
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.2f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(0.46875, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+}
+
+TEST_F(LegacySWPictureLayerImplTest, CompositedImageHistograms) {
+ base::HistogramTester histogram_tester;
+
+ gfx::Size layer_bounds(5, 5);
+ scoped_refptr<FakeRasterSource> pending_raster_source =
+ FakeRasterSource::CreateFilled(layer_bounds);
+
+ SetupPendingTree(pending_raster_source);
+
+ // Set the image and bounds to values that make the layer not eligible for
+ // direct compositing. This must be reflected by a |contents_scale_key()| of
+ // 0.2f (matching the ideal source scale).
+ gfx::Size image_size(300, 300);
+ pending_layer()->SetDirectlyCompositedImageSize(image_size);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.2f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(0.2f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ false, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ true, 0);
+
+ // At ideal scale of 1, we save 270000 pixels for a 600x600 layer directly
+ // compositing a 300x300 image.
+ pending_layer()->SetBounds(gfx::Size(600, 600));
+ pending_layer()->SetDirectlyCompositedImageSize(image_size);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaSaved",
+ 270000, 1);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaSaved",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaAdded",
+ 0);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ true, 0);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ false, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ true, 1);
+
+ // Matching bounds should log TileAreaMatches.
+ pending_layer()->SetDirectlyCompositedImageSize(gfx::Size(600, 600));
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ true, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ false, 1);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaSaved",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaAdded",
+ 0);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ true, 2);
+
+ // Changing the bounds to be smaller than the image should add a TileAreaAdded
+ // histogram bucket count.
+ pending_layer()->SetBounds(gfx::Size(300, 300));
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaAdded",
+ 270000, 1);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaSaved",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaAdded",
+ 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ true, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ false, 2);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ true, 3);
+
+ // So far we haven't avoided any re-raster (as sizes have been updated at
+ // every stage of the test). Similarly, just updating tiles with no scale
+ // changes should not result in those histograms being logged.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ false, 0);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ true, 0);
+
+ // Reduce the ideal scale - directly composited image should not re-raster.
+ // Neither will-change:transform or active transformation so the 'false'
+ // bucket should get an entry.
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.5f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ false, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ true, 0);
+
+ // Set will-change:transform and update tiles with a different ideal scale.
+ pending_layer()->SetHasWillChangeTransformHint(true);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.6f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ false, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "AvoidRasterAdjustmentWithTransformTrigger",
+ true, 1);
+
+ // None of the operations past the first one should have incremented this
+ // histogram.
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ false, 1);
+}
+
+TEST_F(LegacySWPictureLayerImplTest, CompositedImageHistogramsOverflow) {
+ base::HistogramTester histogram_tester;
+
+ constexpr int kLargeDimension = std::numeric_limits<int>::max() / 2;
+ gfx::Size layer_bounds(kLargeDimension, kLargeDimension);
+ scoped_refptr<FakeRasterSource> pending_raster_source =
+ FakeRasterSource::CreateFilled(layer_bounds);
+
+ // Overflow the area calculation for the histograms - we should still get
+ // the correct high res scale key, but no histograms should be logged.
+ SetupPendingTree(pending_raster_source);
+ pending_layer()->SetDirectlyCompositedImageSize(layer_bounds);
+ SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f,
+ false);
+ EXPECT_FLOAT_EQ(1.f, pending_layer()
+ ->picture_layer_tiling_set()
+ ->FindTilingWithResolution(HIGH_RESOLUTION)
+ ->contents_scale_key());
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaSaved",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaAdded",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "TileAreaMatches",
+ 0);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ true, 1);
+ histogram_tester.ExpectBucketCount(
+ "Compositing.Renderer.DirectlyCompositedImage."
+ "RasterScaleDirectlyComposited",
+ false, 0);
+}
+
TEST_F(LegacySWPictureLayerImplTest,
ChangeRasterTranslationNukePendingLayerTiles) {
gfx::Size layer_bounds(200, 200);
diff --git a/chromium/cc/layers/recording_source.h b/chromium/cc/layers/recording_source.h
index d09d8db06fe..cd4c2d51e5a 100644
--- a/chromium/cc/layers/recording_source.h
+++ b/chromium/cc/layers/recording_source.h
@@ -63,7 +63,6 @@ class CC_EXPORT RecordingSource {
int slow_down_raster_scale_factor_for_debug_;
bool requires_clear_;
bool is_solid_color_;
- bool clear_canvas_with_debug_color_;
SkColor solid_color_;
SkColor background_color_;
scoped_refptr<DisplayItemList> display_list_;
diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc
index e6d2862ae3c..3d60067a835 100644
--- a/chromium/cc/layers/render_surface_impl.cc
+++ b/chromium/cc/layers/render_surface_impl.cc
@@ -8,7 +8,7 @@
#include <algorithm>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/strings/stringprintf.h"
#include "cc/base/math_util.h"
#include "cc/debug/debug_colors.h"
@@ -110,10 +110,6 @@ SkBlendMode RenderSurfaceImpl::BlendMode() const {
return OwningEffectNode()->blend_mode;
}
-bool RenderSurfaceImpl::UsesDefaultBlendMode() const {
- return BlendMode() == SkBlendMode::kSrcOver;
-}
-
SkColor RenderSurfaceImpl::GetDebugBorderColor() const {
return DebugColors::SurfaceBorderColor();
}
diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h
index 351ad5969f8..72587093ba7 100644
--- a/chromium/cc/layers/render_surface_impl.h
+++ b/chromium/cc/layers/render_surface_impl.h
@@ -62,7 +62,6 @@ class CC_EXPORT RenderSurfaceImpl {
}
SkBlendMode BlendMode() const;
- bool UsesDefaultBlendMode() const;
void SetNearestOcclusionImmuneAncestor(const RenderSurfaceImpl* surface) {
nearest_occlusion_immune_ancestor_ = surface;
diff --git a/chromium/cc/layers/scrollbar_layer_base.cc b/chromium/cc/layers/scrollbar_layer_base.cc
index e676c3eed1e..aa7c2f0c435 100644
--- a/chromium/cc/layers/scrollbar_layer_base.cc
+++ b/chromium/cc/layers/scrollbar_layer_base.cc
@@ -4,19 +4,60 @@
#include "cc/layers/scrollbar_layer_base.h"
+#include "cc/layers/painted_overlay_scrollbar_layer.h"
+#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/scrollbar_layer_impl_base.h"
+#include "cc/layers/solid_color_scrollbar_layer.h"
namespace cc {
ScrollbarLayerBase::ScrollbarLayerBase(ScrollbarOrientation orientation,
bool is_left_side_vertical_scrollbar)
: orientation_(orientation),
- is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar) {
- SetIsScrollbar(true);
-}
+ is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar) {}
ScrollbarLayerBase::~ScrollbarLayerBase() = default;
+scoped_refptr<ScrollbarLayerBase> ScrollbarLayerBase::CreateOrReuse(
+ scoped_refptr<Scrollbar> scrollbar,
+ ScrollbarLayerBase* existing_layer) {
+ DCHECK(scrollbar);
+ ScrollbarLayerType needed_type = kPainted;
+ if (scrollbar->IsSolidColor()) {
+ needed_type = kSolidColor;
+ } else if (scrollbar->UsesNinePatchThumbResource()) {
+ DCHECK(scrollbar->IsOverlay());
+ needed_type = kPaintedOverlay;
+ }
+
+ if (existing_layer &&
+ (existing_layer->GetScrollbarLayerType() != needed_type ||
+ // We don't support change of these fields in a layer.
+ existing_layer->orientation() != scrollbar->Orientation() ||
+ existing_layer->is_left_side_vertical_scrollbar() !=
+ scrollbar->IsLeftSideVerticalScrollbar())) {
+ existing_layer = nullptr;
+ }
+
+ switch (needed_type) {
+ case kSolidColor:
+ return SolidColorScrollbarLayer::CreateOrReuse(
+ std::move(scrollbar),
+ static_cast<SolidColorScrollbarLayer*>(existing_layer));
+ case kPainted:
+ return PaintedScrollbarLayer::CreateOrReuse(
+ std::move(scrollbar),
+ static_cast<PaintedScrollbarLayer*>(existing_layer));
+ case kPaintedOverlay:
+ return PaintedOverlayScrollbarLayer::CreateOrReuse(
+ std::move(scrollbar),
+ static_cast<PaintedOverlayScrollbarLayer*>(existing_layer));
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
void ScrollbarLayerBase::SetScrollElementId(ElementId element_id) {
if (element_id == scroll_element_id_)
return;
@@ -35,4 +76,8 @@ void ScrollbarLayerBase::PushPropertiesTo(LayerImpl* layer) {
scrollbar_layer_impl->SetScrollElementId(scroll_element_id_);
}
+bool ScrollbarLayerBase::IsScrollbarLayerForTesting() const {
+ return true;
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/scrollbar_layer_base.h b/chromium/cc/layers/scrollbar_layer_base.h
index b7c6efe3967..394e5087acb 100644
--- a/chromium/cc/layers/scrollbar_layer_base.h
+++ b/chromium/cc/layers/scrollbar_layer_base.h
@@ -12,6 +12,10 @@ namespace cc {
class CC_EXPORT ScrollbarLayerBase : public Layer {
public:
+ static scoped_refptr<ScrollbarLayerBase> CreateOrReuse(
+ scoped_refptr<Scrollbar>,
+ ScrollbarLayerBase* existing_layer);
+
void SetScrollElementId(ElementId element_id);
ElementId scroll_element_id() const { return scroll_element_id_; }
@@ -27,7 +31,7 @@ class CC_EXPORT ScrollbarLayerBase : public Layer {
kPainted,
kPaintedOverlay,
};
- virtual ScrollbarLayerType ScrollbarLayerTypeForTesting() const = 0;
+ virtual ScrollbarLayerType GetScrollbarLayerType() const = 0;
protected:
ScrollbarLayerBase(ScrollbarOrientation orientation,
@@ -35,6 +39,8 @@ class CC_EXPORT ScrollbarLayerBase : public Layer {
~ScrollbarLayerBase() override;
private:
+ bool IsScrollbarLayerForTesting() const final;
+
const ScrollbarOrientation orientation_;
const bool is_left_side_vertical_scrollbar_;
ElementId scroll_element_id_;
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc
index bc9eabcedbe..2d9e885c030 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.cc
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc
@@ -28,9 +28,7 @@ ScrollbarLayerImplBase::ScrollbarLayerImplBase(
scroll_layer_length_(0.f),
orientation_(orientation),
is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar),
- vertical_adjust_(0.f) {
- set_is_scrollbar(true);
-}
+ vertical_adjust_(0.f) {}
ScrollbarLayerImplBase::~ScrollbarLayerImplBase() {
layer_tree_impl()->UnregisterScrollbar(this);
@@ -38,13 +36,14 @@ ScrollbarLayerImplBase::~ScrollbarLayerImplBase() {
void ScrollbarLayerImplBase::PushPropertiesTo(LayerImpl* layer) {
LayerImpl::PushPropertiesTo(layer);
- DCHECK(layer->ToScrollbarLayer());
- layer->ToScrollbarLayer()->set_is_overlay_scrollbar(is_overlay_scrollbar_);
- layer->ToScrollbarLayer()->SetScrollElementId(scroll_element_id());
+ DCHECK(layer->IsScrollbarLayer());
+ ScrollbarLayerImplBase* scrollbar_layer = ToScrollbarLayer(layer);
+ scrollbar_layer->set_is_overlay_scrollbar(is_overlay_scrollbar_);
+ scrollbar_layer->SetScrollElementId(scroll_element_id());
}
-ScrollbarLayerImplBase* ScrollbarLayerImplBase::ToScrollbarLayer() {
- return this;
+bool ScrollbarLayerImplBase::IsScrollbarLayer() const {
+ return true;
}
void ScrollbarLayerImplBase::SetScrollElementId(ElementId scroll_element_id) {
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.h b/chromium/cc/layers/scrollbar_layer_impl_base.h
index 23a31d35754..3b508f3c17a 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.h
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.h
@@ -49,7 +49,6 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
bool CanScrollOrientation() const;
void PushPropertiesTo(LayerImpl* layer) override;
- ScrollbarLayerImplBase* ToScrollbarLayer() override;
// Thumb quad rect in layer space.
gfx::Rect ComputeThumbQuadRect() const;
@@ -99,6 +98,8 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
virtual bool IsThumbResizable() const = 0;
private:
+ bool IsScrollbarLayer() const final;
+
gfx::Rect ComputeThumbQuadRectWithThumbThicknessScale(
float thumb_thickness_scale_factor) const;
@@ -120,6 +121,11 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl {
ScrollElementIdPushedAcrossCommit);
};
+inline ScrollbarLayerImplBase* ToScrollbarLayer(LayerImpl* layer) {
+ DCHECK(layer->IsScrollbarLayer());
+ return static_cast<ScrollbarLayerImplBase*>(layer);
+}
+
using ScrollbarSet = base::flat_set<ScrollbarLayerImplBase*>;
} // namespace cc
diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.cc b/chromium/cc/layers/solid_color_scrollbar_layer.cc
index e910b1c72ee..d446a39fc2f 100644
--- a/chromium/cc/layers/solid_color_scrollbar_layer.cc
+++ b/chromium/cc/layers/solid_color_scrollbar_layer.cc
@@ -18,6 +18,32 @@ std::unique_ptr<LayerImpl> SolidColorScrollbarLayer::CreateLayerImpl(
is_left_side_vertical_scrollbar());
}
+scoped_refptr<SolidColorScrollbarLayer> SolidColorScrollbarLayer::CreateOrReuse(
+ scoped_refptr<Scrollbar> scrollbar,
+ SolidColorScrollbarLayer* existing_layer) {
+ DCHECK(scrollbar->IsOverlay());
+ bool is_horizontal = scrollbar->Orientation() == HORIZONTAL;
+ gfx::Rect thumb_rect = scrollbar->ThumbRect();
+ int thumb_thickness =
+ is_horizontal ? thumb_rect.height() : thumb_rect.width();
+ gfx::Rect track_rect = scrollbar->TrackRect();
+ int track_start = is_horizontal ? track_rect.x() : track_rect.y();
+
+ if (existing_layer &&
+ // We don't support change of these fields in a layer.
+ existing_layer->thumb_thickness() == thumb_thickness &&
+ existing_layer->track_start() == track_start) {
+ // These fields have been checked in ScrollbarLayerBase::CreateOrReuse().
+ DCHECK_EQ(scrollbar->Orientation(), existing_layer->orientation());
+ DCHECK_EQ(scrollbar->IsLeftSideVerticalScrollbar(),
+ existing_layer->is_left_side_vertical_scrollbar());
+ return existing_layer;
+ }
+
+ return Create(scrollbar->Orientation(), thumb_thickness, track_start,
+ scrollbar->IsLeftSideVerticalScrollbar());
+}
+
scoped_refptr<SolidColorScrollbarLayer> SolidColorScrollbarLayer::Create(
ScrollbarOrientation orientation,
int thumb_thickness,
@@ -62,7 +88,7 @@ bool SolidColorScrollbarLayer::HitTestable() const {
}
ScrollbarLayerBase::ScrollbarLayerType
-SolidColorScrollbarLayer::ScrollbarLayerTypeForTesting() const {
+SolidColorScrollbarLayer::GetScrollbarLayerType() const {
return kSolidColor;
}
diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.h b/chromium/cc/layers/solid_color_scrollbar_layer.h
index 8931b9c90b6..c0cd2ee49f5 100644
--- a/chromium/cc/layers/solid_color_scrollbar_layer.h
+++ b/chromium/cc/layers/solid_color_scrollbar_layer.h
@@ -17,6 +17,10 @@ class CC_EXPORT SolidColorScrollbarLayer : public ScrollbarLayerBase {
public:
std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
+ static scoped_refptr<SolidColorScrollbarLayer> CreateOrReuse(
+ scoped_refptr<Scrollbar>,
+ SolidColorScrollbarLayer* existing_layer);
+
static scoped_refptr<SolidColorScrollbarLayer> Create(
ScrollbarOrientation orientation,
int thumb_thickness,
@@ -35,7 +39,7 @@ class CC_EXPORT SolidColorScrollbarLayer : public ScrollbarLayerBase {
int thumb_thickness() const { return thumb_thickness_; }
int track_start() const { return track_start_; }
- ScrollbarLayerType ScrollbarLayerTypeForTesting() const override;
+ ScrollbarLayerType GetScrollbarLayerType() const override;
private:
SolidColorScrollbarLayer(ScrollbarOrientation orientation,
diff --git a/chromium/cc/layers/surface_layer.cc b/chromium/cc/layers/surface_layer.cc
index ec1c8646a40..baf7ef5f8de 100644
--- a/chromium/cc/layers/surface_layer.cc
+++ b/chromium/cc/layers/surface_layer.cc
@@ -119,13 +119,13 @@ void SurfaceLayer::SetIsReflection(bool is_reflection) {
void SurfaceLayer::SetMayContainVideo(bool may_contain_video) {
may_contain_video_ = may_contain_video;
+ SetNeedsCommit();
}
std::unique_ptr<LayerImpl> SurfaceLayer::CreateLayerImpl(
LayerTreeImpl* tree_impl) {
auto layer_impl = SurfaceLayerImpl::Create(tree_impl, id(),
update_submission_state_callback_);
- layer_impl->set_may_contain_video(may_contain_video_);
return layer_impl;
}
@@ -158,6 +158,7 @@ void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) {
layer_impl->SetStretchContentToFillBounds(stretch_content_to_fill_bounds_);
layer_impl->SetSurfaceHitTestable(surface_hit_testable_);
layer_impl->SetHasPointerEventsNone(has_pointer_events_none_);
+ layer_impl->set_may_contain_video(may_contain_video_);
}
} // namespace cc
diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc
index b5f67bad210..4441f94fcfb 100644
--- a/chromium/cc/layers/video_layer_impl.cc
+++ b/chromium/cc/layers/video_layer_impl.cc
@@ -10,7 +10,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "cc/layers/video_frame_provider_client_impl.h"
#include "cc/trees/layer_tree_frame_sink.h"
diff --git a/chromium/cc/layers/viewport.cc b/chromium/cc/layers/viewport.cc
index fab6235d29f..46b5f15dd64 100644
--- a/chromium/cc/layers/viewport.cc
+++ b/chromium/cc/layers/viewport.cc
@@ -4,7 +4,7 @@
#include "cc/layers/viewport.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "cc/input/browser_controls_offset_manager.h"
#include "cc/trees/layer_tree_host_impl.h"
diff --git a/chromium/cc/metrics/compositor_frame_reporter.cc b/chromium/cc/metrics/compositor_frame_reporter.cc
index 68592504171..13c15d9b1dd 100644
--- a/chromium/cc/metrics/compositor_frame_reporter.cc
+++ b/chromium/cc/metrics/compositor_frame_reporter.cc
@@ -21,11 +21,12 @@ namespace cc {
namespace {
using StageType = CompositorFrameReporter::StageType;
+using FrameReportType = CompositorFrameReporter::FrameReportType;
using BlinkBreakdown = CompositorFrameReporter::BlinkBreakdown;
using VizBreakdown = CompositorFrameReporter::VizBreakdown;
constexpr int kFrameReportTypeCount =
- static_cast<int>(CompositorFrameReporter::FrameReportType::kMaxValue) + 1;
+ static_cast<int>(FrameReportType::kMaxValue) + 1;
constexpr int kStageTypeCount = static_cast<int>(StageType::kStageTypeCount);
constexpr int kAllBreakdownCount =
static_cast<int>(VizBreakdown::kBreakdownCount) +
@@ -62,11 +63,16 @@ constexpr const char* GetVizBreakdownName(VizBreakdown stage) {
// Names for CompositorFrameReporter::StageType, which should be updated in case
// of changes to the enum.
-constexpr const char* GetStageName(int stage_type_index) {
+constexpr const char* GetStageName(int stage_type_index,
+ bool impl_only = false) {
switch (stage_type_index) {
case static_cast<int>(StageType::kBeginImplFrameToSendBeginMainFrame):
+ if (impl_only)
+ return "BeginImplFrameToFinishImpl";
return "BeginImplFrameToSendBeginMainFrame";
case static_cast<int>(StageType::kSendBeginMainFrameToCommit):
+ if (impl_only)
+ return "SendBeginMainFrameToBeginMainAbort";
return "SendBeginMainFrameToCommit";
case static_cast<int>(StageType::kCommit):
return "Commit";
@@ -75,6 +81,8 @@ constexpr const char* GetStageName(int stage_type_index) {
case static_cast<int>(StageType::kActivation):
return "Activation";
case static_cast<int>(StageType::kEndActivateToSubmitCompositorFrame):
+ if (impl_only)
+ return "ImplFrameDoneToSubmitCompositorFrame";
return "EndActivateToSubmitCompositorFrame";
case static_cast<int>(
StageType::kSubmitCompositorFrameToPresentationCompositorFrame):
@@ -140,8 +148,8 @@ constexpr const char* GetStageName(int stage_type_index) {
// Names for CompositorFrameReporter::FrameReportType, which should be
// updated in case of changes to the enum.
-constexpr const char* kReportTypeNames[]{"", "MissedDeadlineFrame.",
- "DroppedFrame."};
+constexpr const char* kReportTypeNames[]{
+ "", "MissedDeadlineFrame.", "DroppedFrame.", "CompositorOnlyFrame."};
static_assert(base::size(kReportTypeNames) == kFrameReportTypeCount,
"Compositor latency report types has changed.");
@@ -159,9 +167,11 @@ constexpr int kCompositorLatencyHistogramBucketCount = 50;
constexpr int kEventLatencyEventTypeCount =
static_cast<int>(ui::EventType::ET_LAST);
constexpr int kEventLatencyScrollTypeCount =
- static_cast<int>(ScrollInputType::kMaxValue) + 1;
-constexpr int kMaxEventLatencyHistogramIndex =
+ static_cast<int>(ui::ScrollInputType::kMaxValue) + 1;
+constexpr int kMaxEventLatencyHistogramBaseIndex =
kEventLatencyEventTypeCount * kEventLatencyScrollTypeCount;
+constexpr int kMaxEventLatencyHistogramIndex =
+ kMaxEventLatencyHistogramBaseIndex * (kStageTypeCount + kAllBreakdownCount);
constexpr int kEventLatencyHistogramMin = 1;
constexpr int kEventLatencyHistogramMax = 5000000;
constexpr int kEventLatencyHistogramBucketCount = 100;
@@ -182,10 +192,13 @@ std::string GetCompositorLatencyHistogramName(
FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
frame_sequence_tracker_type);
DCHECK(tracker_type_name);
+ bool impl_only_frame =
+ (report_type_index ==
+ static_cast<int>(FrameReportType::kCompositorOnlyFrame));
return base::StrCat({"CompositorLatency.",
kReportTypeNames[report_type_index], tracker_type_name,
*tracker_type_name ? "." : "",
- GetStageName(stage_type_index)});
+ GetStageName(stage_type_index, impl_only_frame)});
}
std::string GetEventLatencyHistogramBaseName(
@@ -199,7 +212,7 @@ std::string GetEventLatencyHistogramBaseName(
} // namespace
CompositorFrameReporter::CompositorFrameReporter(
- const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+ const ActiveTrackers& active_trackers,
const viz::BeginFrameId& id,
const base::TimeTicks frame_deadline,
LatencyUkmReporter* latency_ukm_reporter,
@@ -215,16 +228,19 @@ CompositorFrameReporter::CopyReporterAtBeginImplStage() const {
if (stage_history_.empty() ||
stage_history_.front().stage_type !=
StageType::kBeginImplFrameToSendBeginMainFrame ||
- !did_finish_impl_frame())
+ !did_finish_impl_frame()) {
return nullptr;
+ }
auto new_reporter = std::make_unique<CompositorFrameReporter>(
active_trackers_, frame_id_, frame_deadline_, latency_ukm_reporter_,
should_report_metrics_);
new_reporter->did_finish_impl_frame_ = did_finish_impl_frame_;
new_reporter->impl_frame_finish_time_ = impl_frame_finish_time_;
+ new_reporter->main_frame_abort_time_ = main_frame_abort_time_;
new_reporter->current_stage_.stage_type =
StageType::kBeginImplFrameToSendBeginMainFrame;
new_reporter->current_stage_.start_time = stage_history_.front().start_time;
+ new_reporter->set_tick_clock(tick_clock_);
return new_reporter;
}
@@ -248,14 +264,18 @@ void CompositorFrameReporter::StartStage(
EndCurrentStage(start_time);
current_stage_.stage_type = stage_type;
current_stage_.start_time = start_time;
-}
-
-void CompositorFrameReporter::EndCurrentStage(base::TimeTicks end_time) {
- if (current_stage_.start_time == base::TimeTicks())
- return;
- current_stage_.end_time = end_time;
- stage_history_.push_back(current_stage_);
- current_stage_.start_time = base::TimeTicks();
+ switch (stage_type) {
+ case StageType::kSendBeginMainFrameToCommit:
+ DCHECK(blink_start_time_.is_null());
+ blink_start_time_ = start_time;
+ break;
+ case StageType::kSubmitCompositorFrameToPresentationCompositorFrame:
+ DCHECK(viz_start_time_.is_null());
+ viz_start_time_ = start_time;
+ break;
+ default:
+ break;
+ }
}
void CompositorFrameReporter::TerminateFrame(
@@ -279,16 +299,21 @@ void CompositorFrameReporter::OnFinishImplFrame(base::TimeTicks timestamp) {
}
void CompositorFrameReporter::OnAbortBeginMainFrame(base::TimeTicks timestamp) {
- DCHECK(!did_abort_main_frame_);
-
- did_abort_main_frame_ = true;
+ DCHECK(!main_frame_abort_time_.has_value());
+ main_frame_abort_time_ = timestamp;
impl_frame_finish_time_ = timestamp;
// impl_frame_finish_time_ can be used for the end of BeginMain to Commit
// stage
}
-void CompositorFrameReporter::OnDidNotProduceFrame() {
- did_not_produce_frame_ = true;
+void CompositorFrameReporter::OnDidNotProduceFrame(
+ FrameSkippedReason skip_reason) {
+ did_not_produce_frame_time_ = Now();
+ frame_skip_reason_ = skip_reason;
+}
+
+void CompositorFrameReporter::EnableCompositorOnlyReporting() {
+ EnableReportType(FrameReportType::kCompositorOnlyFrame);
}
void CompositorFrameReporter::SetBlinkBreakdown(
@@ -316,42 +341,37 @@ void CompositorFrameReporter::SetEventsMetrics(
events_metrics_ = std::move(events_metrics);
}
-void CompositorFrameReporter::DroppedFrame() {
- report_type_ = FrameReportType::kDroppedFrame;
-}
-
-void CompositorFrameReporter::MissedDeadlineFrame() {
- report_type_ = FrameReportType::kMissedDeadlineFrame;
-}
-
void CompositorFrameReporter::TerminateReporter() {
if (frame_termination_status_ == FrameTerminationStatus::kUnknown)
- TerminateFrame(FrameTerminationStatus::kUnknown, base::TimeTicks::Now());
+ TerminateFrame(FrameTerminationStatus::kUnknown, Now());
+
+ PopulateBlinkBreakdownList();
+ PopulateVizBreakdownList();
+
DCHECK_EQ(current_stage_.start_time, base::TimeTicks());
- bool report_compositor_latency = false;
- bool report_event_latency = false;
- bool report_missed_deadline_frame = false;
const char* termination_status_str = nullptr;
switch (frame_termination_status_) {
case FrameTerminationStatus::kPresentedFrame:
- report_compositor_latency = true;
- report_event_latency = true;
+ EnableReportType(FrameReportType::kNonDroppedFrame);
termination_status_str = "presented_frame";
if (frame_deadline_ < frame_termination_time_)
- report_missed_deadline_frame = true;
+ EnableReportType(FrameReportType::kMissedDeadlineFrame);
break;
case FrameTerminationStatus::kDidNotPresentFrame:
- report_compositor_latency = true;
- DroppedFrame();
+ EnableReportType(FrameReportType::kDroppedFrame);
termination_status_str = "did_not_present_frame";
break;
case FrameTerminationStatus::kReplacedByNewReporter:
- report_compositor_latency = true;
- DroppedFrame();
+ EnableReportType(FrameReportType::kDroppedFrame);
termination_status_str = "replaced_by_new_reporter_at_same_stage";
break;
case FrameTerminationStatus::kDidNotProduceFrame:
termination_status_str = "did_not_produce_frame";
+ if (!frame_skip_reason_.has_value() ||
+ frame_skip_reason() != FrameSkippedReason::kNoDamage) {
+ EnableReportType(FrameReportType::kDroppedFrame);
+ termination_status_str = "dropped_frame";
+ }
break;
case FrameTerminationStatus::kUnknown:
termination_status_str = "terminated_before_ending";
@@ -361,46 +381,91 @@ void CompositorFrameReporter::TerminateReporter() {
ReportAllTraceEvents(termination_status_str);
// Only report compositor latency histograms if the frame was produced.
- if (should_report_metrics_ && report_compositor_latency) {
+ if (should_report_metrics_ && report_types_.any()) {
DCHECK(stage_history_.size());
DCHECK_EQ(SumOfStageHistory(), stage_history_.back().end_time -
stage_history_.front().start_time);
stage_history_.emplace_back(StageType::kTotalLatency,
stage_history_.front().start_time,
stage_history_.back().end_time);
- ReportLatencyHistograms(report_event_latency, report_missed_deadline_frame);
- }
-}
-
-void CompositorFrameReporter::ReportLatencyHistograms(
- bool report_event_latency,
- bool report_delayed_latency) {
- ReportCompositorLatencyHistograms();
- if (report_delayed_latency) {
- // If the frames are delayed also report them under MissedDeadlineFrame.
- MissedDeadlineFrame();
ReportCompositorLatencyHistograms();
+ // Only report event latency histograms if the frame was presented.
+ if (TestReportType(FrameReportType::kNonDroppedFrame))
+ ReportEventLatencyHistograms();
}
+}
- // Only report event latency histograms if the frame was presented.
- if (report_event_latency)
- ReportEventLatencyHistograms();
+void CompositorFrameReporter::EndCurrentStage(base::TimeTicks end_time) {
+ if (current_stage_.start_time == base::TimeTicks())
+ return;
+ current_stage_.end_time = end_time;
+ stage_history_.push_back(current_stage_);
+ current_stage_.start_time = base::TimeTicks();
}
void CompositorFrameReporter::ReportCompositorLatencyHistograms() const {
- UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type", report_type_);
for (const StageData& stage : stage_history_) {
ReportStageHistogramWithBreakdown(stage);
-
- for (const auto& frame_sequence_tracker_type : *active_trackers_) {
- // Report stage breakdowns.
- ReportStageHistogramWithBreakdown(stage, frame_sequence_tracker_type);
+ for (size_t type = 0; type < active_trackers_.size(); ++type) {
+ if (active_trackers_.test(type)) {
+ // Report stage breakdowns.
+ ReportStageHistogramWithBreakdown(
+ stage, static_cast<FrameSequenceTrackerType>(type));
+ }
}
}
- if (latency_ukm_reporter_) {
- latency_ukm_reporter_->ReportLatencyUkm(report_type_, stage_history_,
- active_trackers_, viz_breakdown_);
+ for (size_t type = 0; type < report_types_.size(); ++type) {
+ if (!report_types_.test(type))
+ continue;
+ FrameReportType report_type = static_cast<FrameReportType>(type);
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type", report_type);
+ if (latency_ukm_reporter_) {
+ latency_ukm_reporter_->ReportLatencyUkm(report_type, stage_history_,
+ active_trackers_, viz_breakdown_);
+ }
+ for (size_t fst_type = 0; fst_type < active_trackers_.size(); ++fst_type) {
+ if (!active_trackers_.test(fst_type)) {
+ continue;
+ }
+ switch (static_cast<FrameSequenceTrackerType>(fst_type)) {
+ case FrameSequenceTrackerType::kCompositorAnimation:
+ UMA_HISTOGRAM_ENUMERATION(
+ "CompositorLatency.Type.CompositorAnimation", report_type);
+ break;
+ case FrameSequenceTrackerType::kMainThreadAnimation:
+ UMA_HISTOGRAM_ENUMERATION(
+ "CompositorLatency.Type.MainThreadAnimation", report_type);
+ break;
+ case FrameSequenceTrackerType::kPinchZoom:
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.PinchZoom",
+ report_type);
+ break;
+ case FrameSequenceTrackerType::kRAF:
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.RAF", report_type);
+ break;
+ case FrameSequenceTrackerType::kTouchScroll:
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.TouchScroll",
+ report_type);
+ break;
+ case FrameSequenceTrackerType::kVideo:
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.Video",
+ report_type);
+ break;
+ case FrameSequenceTrackerType::kWheelScroll:
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.WheelScroll",
+ report_type);
+ break;
+ case FrameSequenceTrackerType::kScrollbarScroll:
+ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.ScrollbarScroll",
+ report_type);
+ break;
+ case FrameSequenceTrackerType::kUniversal:
+ case FrameSequenceTrackerType::kCustom:
+ case FrameSequenceTrackerType::kMaxType:
+ break;
+ }
+ }
}
}
@@ -415,123 +480,79 @@ void CompositorFrameReporter::ReportStageHistogramWithBreakdown(
stage_delta);
switch (stage.stage_type) {
case StageType::kSendBeginMainFrameToCommit:
- ReportBlinkBreakdowns(stage.start_time, frame_sequence_tracker_type);
+ ReportCompositorLatencyBlinkBreakdowns(frame_sequence_tracker_type);
break;
case StageType::kSubmitCompositorFrameToPresentationCompositorFrame:
- ReportVizBreakdowns(stage.start_time, frame_sequence_tracker_type);
+ ReportCompositorLatencyVizBreakdowns(frame_sequence_tracker_type);
break;
default:
break;
}
}
-void CompositorFrameReporter::ReportBlinkBreakdowns(
- base::TimeTicks start_time,
+void CompositorFrameReporter::ReportCompositorLatencyBlinkBreakdowns(
FrameSequenceTrackerType frame_sequence_tracker_type) const {
- std::vector<std::pair<BlinkBreakdown, base::TimeDelta>> breakdowns = {
- {BlinkBreakdown::kHandleInputEvents,
- blink_breakdown_.handle_input_events},
- {BlinkBreakdown::kAnimate, blink_breakdown_.animate},
- {BlinkBreakdown::kStyleUpdate, blink_breakdown_.style_update},
- {BlinkBreakdown::kLayoutUpdate, blink_breakdown_.layout_update},
- {BlinkBreakdown::kPrepaint, blink_breakdown_.prepaint},
- {BlinkBreakdown::kComposite, blink_breakdown_.composite},
- {BlinkBreakdown::kPaint, blink_breakdown_.paint},
- {BlinkBreakdown::kScrollingCoordinator,
- blink_breakdown_.scrolling_coordinator},
- {BlinkBreakdown::kCompositeCommit, blink_breakdown_.composite_commit},
- {BlinkBreakdown::kUpdateLayers, blink_breakdown_.update_layers},
- {BlinkBreakdown::kBeginMainSentToStarted,
- begin_main_frame_start_ - start_time}};
-
- for (const auto& pair : breakdowns) {
- ReportCompositorLatencyHistogram(
- frame_sequence_tracker_type,
- kBlinkBreakdownInitialIndex + static_cast<int>(pair.first),
- pair.second);
+ for (size_t i = 0; i < base::size(blink_breakdown_list_); i++) {
+ ReportCompositorLatencyHistogram(frame_sequence_tracker_type,
+ kBlinkBreakdownInitialIndex + i,
+ blink_breakdown_list_[i]);
}
}
-void CompositorFrameReporter::ReportVizBreakdownStage(
- VizBreakdown stage,
- const base::TimeTicks start_time,
- const base::TimeTicks end_time,
+void CompositorFrameReporter::ReportCompositorLatencyVizBreakdowns(
FrameSequenceTrackerType frame_sequence_tracker_type) const {
- base::TimeDelta time_delta = end_time - start_time;
- ReportCompositorLatencyHistogram(
- frame_sequence_tracker_type,
- kVizBreakdownInitialIndex + static_cast<int>(stage), time_delta);
-}
-
-void CompositorFrameReporter::ReportVizBreakdowns(
- base::TimeTicks start_time,
- FrameSequenceTrackerType frame_sequence_tracker_type) const {
- // Check if viz_breakdown is set. Testing indicates that sometimes the
- // received_compositor_frame_timestamp can be earlier than the given
- // start_time. Avoid reporting negative times.
- if (viz_breakdown_.received_compositor_frame_timestamp.is_null() ||
- viz_breakdown_.received_compositor_frame_timestamp < start_time) {
- return;
+ for (size_t i = 0; i < base::size(viz_breakdown_list_); i++) {
+ if (!viz_breakdown_list_[i]) {
+#if DCHECK_IS_ON()
+ // Remaining breakdowns should be unset.
+ for (; i < base::size(viz_breakdown_list_); i++)
+ DCHECK(!viz_breakdown_list_[i]);
+#endif
+ break;
+ }
+ ReportCompositorLatencyHistogram(frame_sequence_tracker_type,
+ kVizBreakdownInitialIndex + i,
+ *viz_breakdown_list_[i]);
}
- ReportVizBreakdownStage(VizBreakdown::kSubmitToReceiveCompositorFrame,
- start_time,
- viz_breakdown_.received_compositor_frame_timestamp,
- frame_sequence_tracker_type);
-
- if (viz_breakdown_.draw_start_timestamp.is_null())
- return;
- ReportVizBreakdownStage(VizBreakdown::kReceivedCompositorFrameToStartDraw,
- viz_breakdown_.received_compositor_frame_timestamp,
- viz_breakdown_.draw_start_timestamp,
- frame_sequence_tracker_type);
-
- if (viz_breakdown_.swap_timings.is_null())
- return;
- ReportVizBreakdownStage(
- VizBreakdown::kStartDrawToSwapStart, viz_breakdown_.draw_start_timestamp,
- viz_breakdown_.swap_timings.swap_start, frame_sequence_tracker_type);
-
- ReportVizBreakdownStage(
- VizBreakdown::kSwapStartToSwapEnd, viz_breakdown_.swap_timings.swap_start,
- viz_breakdown_.swap_timings.swap_end, frame_sequence_tracker_type);
-
- ReportVizBreakdownStage(VizBreakdown::kSwapEndToPresentationCompositorFrame,
- viz_breakdown_.swap_timings.swap_end,
- viz_breakdown_.presentation_feedback.timestamp,
- frame_sequence_tracker_type);
}
void CompositorFrameReporter::ReportCompositorLatencyHistogram(
FrameSequenceTrackerType frame_sequence_tracker_type,
const int stage_type_index,
base::TimeDelta time_delta) const {
- const int report_type_index = static_cast<int>(report_type_);
- const int frame_sequence_tracker_type_index =
- static_cast<int>(frame_sequence_tracker_type);
- const int histogram_index =
- (stage_type_index * kFrameSequenceTrackerTypeCount +
- frame_sequence_tracker_type_index) *
- kFrameReportTypeCount +
- report_type_index;
-
- CHECK_LT(stage_type_index, kStageTypeCount + kAllBreakdownCount);
- CHECK_GE(stage_type_index, 0);
- CHECK_LT(report_type_index, kFrameReportTypeCount);
- CHECK_GE(report_type_index, 0);
- CHECK_LT(histogram_index, kMaxCompositorLatencyHistogramIndex);
- CHECK_GE(histogram_index, 0);
+ for (size_t type = 0; type < report_types_.size(); ++type) {
+ if (!report_types_.test(type))
+ continue;
+ FrameReportType report_type = static_cast<FrameReportType>(type);
+ const int report_type_index = static_cast<int>(report_type);
+ const int frame_sequence_tracker_type_index =
+ static_cast<int>(frame_sequence_tracker_type);
+ const int histogram_index =
+ (stage_type_index * kFrameSequenceTrackerTypeCount +
+ frame_sequence_tracker_type_index) *
+ kFrameReportTypeCount +
+ report_type_index;
+
+ CHECK_LT(stage_type_index, kStageTypeCount + kAllBreakdownCount);
+ CHECK_GE(stage_type_index, 0);
+ CHECK_LT(report_type_index, kFrameReportTypeCount);
+ CHECK_GE(report_type_index, 0);
+ CHECK_LT(histogram_index, kMaxCompositorLatencyHistogramIndex);
+ CHECK_GE(histogram_index, 0);
- STATIC_HISTOGRAM_POINTER_GROUP(
- GetCompositorLatencyHistogramName(
- report_type_index, frame_sequence_tracker_type, stage_type_index),
- histogram_index, kMaxCompositorLatencyHistogramIndex,
- AddTimeMicrosecondsGranularity(time_delta),
- base::Histogram::FactoryGet(
- GetCompositorLatencyHistogramName(
- report_type_index, frame_sequence_tracker_type, stage_type_index),
- kCompositorLatencyHistogramMin, kCompositorLatencyHistogramMax,
- kCompositorLatencyHistogramBucketCount,
- base::HistogramBase::kUmaTargetedHistogramFlag));
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ GetCompositorLatencyHistogramName(
+ report_type_index, frame_sequence_tracker_type, stage_type_index),
+ histogram_index, kMaxCompositorLatencyHistogramIndex,
+ AddTimeMicrosecondsGranularity(time_delta),
+ base::Histogram::FactoryGet(
+ GetCompositorLatencyHistogramName(report_type_index,
+ frame_sequence_tracker_type,
+ stage_type_index),
+ kCompositorLatencyHistogramMin, kCompositorLatencyHistogramMax,
+ kCompositorLatencyHistogramBucketCount,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
+ }
}
void CompositorFrameReporter::ReportEventLatencyHistograms() const {
@@ -543,7 +564,7 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const {
event_metrics.scroll_input_type()
? static_cast<int>(*event_metrics.scroll_input_type())
: 0;
- const int histogram_index =
+ const int histogram_base_index =
event_type_index * kEventLatencyScrollTypeCount + scroll_type_index;
// For scroll events, report total latency up to gpu-swap-end. This is
@@ -556,8 +577,8 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const {
const std::string swap_end_histogram_name =
histogram_base_name + ".TotalLatencyToSwapEnd";
STATIC_HISTOGRAM_POINTER_GROUP(
- swap_end_histogram_name, histogram_index,
- kMaxEventLatencyHistogramIndex,
+ swap_end_histogram_name, histogram_base_index,
+ kMaxEventLatencyHistogramBaseIndex,
AddTimeMicrosecondsGranularity(swap_end_latency),
base::Histogram::FactoryGet(
swap_end_histogram_name, kEventLatencyHistogramMin,
@@ -565,59 +586,130 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const {
base::HistogramBase::kUmaTargetedHistogramFlag));
}
- base::TimeDelta total_latency =
- frame_termination_time_ - event_metrics.time_stamp();
- const std::string histogram_name = histogram_base_name + ".TotalLatency";
- STATIC_HISTOGRAM_POINTER_GROUP(
- histogram_name, histogram_index, kMaxEventLatencyHistogramIndex,
- AddTimeMicrosecondsGranularity(total_latency),
- base::Histogram::FactoryGet(
- histogram_name, kEventLatencyHistogramMin,
- kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount,
- base::HistogramBase::kUmaTargetedHistogramFlag));
-
const auto trace_id = TRACE_ID_LOCAL(&event_metrics);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
"cc,input", "EventLatency", trace_id, event_metrics.time_stamp(),
"event", event_metrics.GetTypeName());
- // Report the breakdowns.
// It is possible for an event to arrive in the compositor in the middle of
// a frame (e.g. the browser received the event *after* renderer received a
// begin-impl, and the event reached the compositor before that frame
// ended). To handle such cases, find the first stage that happens after the
// event's arrival in the browser.
- // TODO(mohsen): Report the breakdowns in UMA too.
size_t index = 0;
for (; index < stage_history_.size(); ++index) {
const auto& stage = stage_history_[index];
if (stage.start_time > event_metrics.time_stamp()) {
+ const char stage_type_name[] = "BrowserToRendererCompositor";
+
+ const base::TimeDelta latency =
+ stage.start_time - event_metrics.time_stamp();
+ const std::string histogram_name =
+ base::StrCat({histogram_base_name, ".", stage_type_name});
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ histogram_name, histogram_base_index,
+ kMaxEventLatencyHistogramBaseIndex,
+ AddTimeMicrosecondsGranularity(latency),
+ base::Histogram::FactoryGet(
+ histogram_name, kEventLatencyHistogramMin,
+ kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
+
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
- "cc,input", "BrowserToRendererCompositor", trace_id,
- event_metrics.time_stamp());
+ "cc,input", stage_type_name, trace_id, event_metrics.time_stamp());
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
- "cc,input", "BrowserToRendererCompositor", trace_id,
- stage.start_time);
+ "cc,input", stage_type_name, trace_id, stage.start_time);
break;
}
}
for (; index < stage_history_.size(); ++index) {
const auto& stage = stage_history_[index];
- if (stage.stage_type == StageType::kTotalLatency)
- break;
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
- "cc,input", GetStageName(static_cast<int>(stage.stage_type)),
- trace_id, stage.start_time);
- TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
- "cc,input", GetStageName(static_cast<int>(stage.stage_type)),
- trace_id, stage.end_time);
+
+ // Total latency is calculated since the event timestamp.
+ const base::TimeTicks start_time =
+ stage.stage_type == StageType::kTotalLatency
+ ? event_metrics.time_stamp()
+ : stage.start_time;
+ const base::TimeDelta latency = stage.end_time - start_time;
+ const int stage_type_index = static_cast<int>(stage.stage_type);
+ ReportEventLatencyHistogram(histogram_base_index, histogram_base_name,
+ stage_type_index, latency);
+
+ switch (stage.stage_type) {
+ case StageType::kSendBeginMainFrameToCommit:
+ ReportEventLatencyBlinkBreakdowns(histogram_base_index,
+ histogram_base_name);
+ break;
+ case StageType::kSubmitCompositorFrameToPresentationCompositorFrame:
+ ReportEventLatencyVizBreakdowns(histogram_base_index,
+ histogram_base_name);
+ break;
+ default:
+ break;
+ }
+
+ if (stage.stage_type != StageType::kTotalLatency) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ "cc,input", GetStageName(stage_type_index), trace_id,
+ stage.start_time);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
+ "cc,input", GetStageName(stage_type_index), trace_id,
+ stage.end_time);
+ }
}
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"cc,input", "EventLatency", trace_id, frame_termination_time_);
}
}
+void CompositorFrameReporter::ReportEventLatencyBlinkBreakdowns(
+ int histogram_base_index,
+ const std::string& histogram_base_name) const {
+ for (size_t i = 0; i < base::size(blink_breakdown_list_); i++) {
+ ReportEventLatencyHistogram(histogram_base_index, histogram_base_name,
+ kBlinkBreakdownInitialIndex + i,
+ blink_breakdown_list_[i]);
+ }
+}
+
+void CompositorFrameReporter::ReportEventLatencyVizBreakdowns(
+ int histogram_base_index,
+ const std::string& histogram_base_name) const {
+ for (size_t i = 0; i < base::size(viz_breakdown_list_); i++) {
+ if (!viz_breakdown_list_[i]) {
+#if DCHECK_IS_ON()
+ // Remaining breakdowns should be unset.
+ for (; i < base::size(viz_breakdown_list_); i++)
+ DCHECK(!viz_breakdown_list_[i]);
+#endif
+ break;
+ }
+ ReportEventLatencyHistogram(histogram_base_index, histogram_base_name,
+ kVizBreakdownInitialIndex + i,
+ *viz_breakdown_list_[i]);
+ }
+}
+
+void CompositorFrameReporter::ReportEventLatencyHistogram(
+ int histogram_base_index,
+ const std::string& histogram_base_name,
+ int stage_type_index,
+ base::TimeDelta latency) const {
+ const std::string histogram_name =
+ base::StrCat({histogram_base_name, ".", GetStageName(stage_type_index)});
+ const int histogram_index =
+ histogram_base_index * (kStageTypeCount + kAllBreakdownCount) +
+ stage_type_index;
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ histogram_name, histogram_index, kMaxEventLatencyHistogramIndex,
+ AddTimeMicrosecondsGranularity(latency),
+ base::Histogram::FactoryGet(
+ histogram_name, kEventLatencyHistogramMin, kEventLatencyHistogramMax,
+ kEventLatencyHistogramBucketCount,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
+}
+
void CompositorFrameReporter::ReportVizBreakdownTrace(
VizBreakdown substage,
const base::TimeTicks start_time,
@@ -653,6 +745,11 @@ void CompositorFrameReporter::ReportAllTraceEvents(
const int stage_type_index = static_cast<int>(stage.stage_type);
CHECK_LT(stage_type_index, static_cast<int>(StageType::kStageTypeCount));
CHECK_GE(stage_type_index, 0);
+ if (stage.start_time >= frame_termination_time_)
+ break;
+ DCHECK_GE(stage.end_time, stage.start_time);
+ if (stage.start_time == stage.end_time)
+ continue;
const char* name = GetStageName(stage_type_index);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"cc,benchmark", name, trace_id, stage.start_time);
@@ -691,13 +788,80 @@ void CompositorFrameReporter::ReportAllTraceEvents(
}
const char* submission_status_str =
- report_type_ == FrameReportType::kDroppedFrame ? "dropped_frame"
+ TestReportType(FrameReportType::kDroppedFrame) ? "dropped_frame"
: "non_dropped_frame";
TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP2(
- "cc,benchmark", "PipelineReporter", trace_id,
- stage_history_.back().end_time, "termination_status",
- termination_status_str, "compositor_frame_submission_status",
- submission_status_str);
+ "cc,benchmark", "PipelineReporter", trace_id, frame_termination_time_,
+ "termination_status", termination_status_str,
+ "compositor_frame_submission_status", submission_status_str);
+}
+
+void CompositorFrameReporter::PopulateBlinkBreakdownList() {
+ if (blink_start_time_.is_null())
+ return;
+
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kHandleInputEvents)] =
+ blink_breakdown_.handle_input_events;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kAnimate)] =
+ blink_breakdown_.animate;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kStyleUpdate)] =
+ blink_breakdown_.style_update;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kLayoutUpdate)] =
+ blink_breakdown_.layout_update;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kPrepaint)] =
+ blink_breakdown_.prepaint;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kComposite)] =
+ blink_breakdown_.composite;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kPaint)] =
+ blink_breakdown_.paint;
+ blink_breakdown_list_[static_cast<int>(
+ BlinkBreakdown::kScrollingCoordinator)] =
+ blink_breakdown_.scrolling_coordinator;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kCompositeCommit)] =
+ blink_breakdown_.composite_commit;
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kUpdateLayers)] =
+ blink_breakdown_.update_layers;
+ blink_breakdown_list_[static_cast<int>(
+ BlinkBreakdown::kBeginMainSentToStarted)] =
+ begin_main_frame_start_ - blink_start_time_;
+}
+
+void CompositorFrameReporter::PopulateVizBreakdownList() {
+ if (viz_start_time_.is_null())
+ return;
+
+ // Check if viz_breakdown is set. Testing indicates that sometimes the
+ // received_compositor_frame_timestamp can be earlier than the given
+ // |start_time|. Avoid reporting negative times.
+ if (viz_breakdown_.received_compositor_frame_timestamp.is_null() ||
+ viz_breakdown_.received_compositor_frame_timestamp < viz_start_time_) {
+ return;
+ }
+ viz_breakdown_list_[static_cast<int>(
+ VizBreakdown::kSubmitToReceiveCompositorFrame)] =
+ viz_breakdown_.received_compositor_frame_timestamp - viz_start_time_;
+
+ if (viz_breakdown_.draw_start_timestamp.is_null())
+ return;
+ viz_breakdown_list_[static_cast<int>(
+ VizBreakdown::kReceivedCompositorFrameToStartDraw)] =
+ viz_breakdown_.draw_start_timestamp -
+ viz_breakdown_.received_compositor_frame_timestamp;
+
+ if (viz_breakdown_.swap_timings.is_null())
+ return;
+ viz_breakdown_list_[static_cast<int>(VizBreakdown::kStartDrawToSwapStart)] =
+ viz_breakdown_.swap_timings.swap_start -
+ viz_breakdown_.draw_start_timestamp;
+
+ viz_breakdown_list_[static_cast<int>(VizBreakdown::kSwapStartToSwapEnd)] =
+ viz_breakdown_.swap_timings.swap_end -
+ viz_breakdown_.swap_timings.swap_start;
+
+ viz_breakdown_list_[static_cast<int>(
+ VizBreakdown::kSwapEndToPresentationCompositorFrame)] =
+ viz_breakdown_.presentation_feedback.timestamp -
+ viz_breakdown_.swap_timings.swap_end;
}
base::TimeDelta CompositorFrameReporter::SumOfStageHistory() const {
@@ -707,4 +871,8 @@ base::TimeDelta CompositorFrameReporter::SumOfStageHistory() const {
return sum;
}
+base::TimeTicks CompositorFrameReporter::Now() const {
+ return tick_clock_->NowTicks();
+}
+
} // namespace cc
diff --git a/chromium/cc/metrics/compositor_frame_reporter.h b/chromium/cc/metrics/compositor_frame_reporter.h
index ebeb2cdee2f..9cae550ba76 100644
--- a/chromium/cc/metrics/compositor_frame_reporter.h
+++ b/chromium/cc/metrics/compositor_frame_reporter.h
@@ -5,16 +5,19 @@
#ifndef CC_METRICS_COMPOSITOR_FRAME_REPORTER_H_
#define CC_METRICS_COMPOSITOR_FRAME_REPORTER_H_
+#include <bitset>
#include <memory>
#include <vector>
-#include "base/containers/flat_set.h"
+#include "base/optional.h"
+#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/base/base_export.h"
#include "cc/cc_export.h"
#include "cc/metrics/begin_main_frame_metrics.h"
#include "cc/metrics/event_metrics.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_metrics.h"
+#include "cc/scheduler/scheduler.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_timing_details.h"
@@ -67,7 +70,8 @@ class CC_EXPORT CompositorFrameReporter {
kNonDroppedFrame = 0,
kMissedDeadlineFrame = 1,
kDroppedFrame = 2,
- kMaxValue = kDroppedFrame
+ kCompositorOnlyFrame = 3,
+ kMaxValue = kCompositorOnlyFrame
};
// These values are used for indexing the UMA histograms.
@@ -119,12 +123,14 @@ class CC_EXPORT CompositorFrameReporter {
~StageData();
};
- CompositorFrameReporter(
- const base::flat_set<FrameSequenceTrackerType>* active_trackers,
- const viz::BeginFrameId& id,
- const base::TimeTicks frame_deadline,
- LatencyUkmReporter* latency_ukm_reporter,
- bool should_report_metrics);
+ using ActiveTrackers =
+ std::bitset<static_cast<size_t>(FrameSequenceTrackerType::kMaxType)>;
+
+ CompositorFrameReporter(const ActiveTrackers& active_trackers,
+ const viz::BeginFrameId& id,
+ const base::TimeTicks frame_deadline,
+ LatencyUkmReporter* latency_ukm_reporter,
+ bool should_report_metrics);
~CompositorFrameReporter();
CompositorFrameReporter(const CompositorFrameReporter& reporter) = delete;
@@ -149,46 +155,63 @@ class CC_EXPORT CompositorFrameReporter {
void OnFinishImplFrame(base::TimeTicks timestamp);
void OnAbortBeginMainFrame(base::TimeTicks timestamp);
- void OnDidNotProduceFrame();
+ void OnDidNotProduceFrame(FrameSkippedReason skip_reason);
+ void EnableCompositorOnlyReporting();
bool did_finish_impl_frame() const { return did_finish_impl_frame_; }
- bool did_abort_main_frame() const { return did_abort_main_frame_; }
- bool did_not_produce_frame() const { return did_not_produce_frame_; }
base::TimeTicks impl_frame_finish_time() const {
return impl_frame_finish_time_;
}
- private:
- void DroppedFrame();
- void MissedDeadlineFrame();
+ bool did_not_produce_frame() const {
+ return did_not_produce_frame_time_.has_value();
+ }
+ base::TimeTicks did_not_produce_frame_time() const {
+ return *did_not_produce_frame_time_;
+ }
+
+ bool did_abort_main_frame() const {
+ return main_frame_abort_time_.has_value();
+ }
+ base::TimeTicks main_frame_abort_time() const {
+ return *main_frame_abort_time_;
+ }
+
+ FrameSkippedReason frame_skip_reason() const { return *frame_skip_reason_; }
+ void set_tick_clock(const base::TickClock* tick_clock) {
+ DCHECK(tick_clock);
+ tick_clock_ = tick_clock;
+ }
+
+ private:
void TerminateReporter();
void EndCurrentStage(base::TimeTicks end_time);
+
void ReportCompositorLatencyHistograms() const;
- void ReportLatencyHistograms(bool report_event_latency = false,
- bool report_delayed_latency = false);
void ReportStageHistogramWithBreakdown(
const StageData& stage,
FrameSequenceTrackerType frame_sequence_tracker_type =
FrameSequenceTrackerType::kMaxType) const;
- void ReportBlinkBreakdowns(
- const base::TimeTicks start_time,
+ void ReportCompositorLatencyBlinkBreakdowns(
FrameSequenceTrackerType frame_sequence_tracker_type) const;
-
- // Report histogram and trace event stage for one Viz breakdown
- void ReportVizBreakdownStage(
- VizBreakdown stage,
- const base::TimeTicks start_time,
- const base::TimeTicks end_time,
- FrameSequenceTrackerType frame_sequence_tracker_type) const;
-
- void ReportVizBreakdowns(
- const base::TimeTicks start_time,
+ void ReportCompositorLatencyVizBreakdowns(
FrameSequenceTrackerType frame_sequence_tracker_type) const;
void ReportCompositorLatencyHistogram(
FrameSequenceTrackerType intraction_type,
const int stage_type_index,
base::TimeDelta time_delta) const;
+
void ReportEventLatencyHistograms() const;
+ void ReportEventLatencyBlinkBreakdowns(
+ int histogram_base_index,
+ const std::string& histogram_base_name) const;
+ void ReportEventLatencyVizBreakdowns(
+ int histogram_base_index,
+ const std::string& histogram_base_name) const;
+ void ReportEventLatencyHistogram(int histogram_base_index,
+ const std::string& histogram_base_name,
+ int stage_type_index,
+ base::TimeDelta latency) const;
// Generate a trace event corresponding to a Viz breakdown under
// SubmitCompositorFrameToPresentationCompositorFrame stage in
@@ -200,43 +223,69 @@ class CC_EXPORT CompositorFrameReporter {
void ReportAllTraceEvents(const char* termination_status_str) const;
+ void EnableReportType(FrameReportType report_type) {
+ report_types_.set(static_cast<size_t>(report_type));
+ }
+ bool TestReportType(FrameReportType report_type) const {
+ return report_types_.test(static_cast<size_t>(report_type));
+ }
+
+ void PopulateBlinkBreakdownList();
+ void PopulateVizBreakdownList();
+
+ // This method is only used for DCheck
+ base::TimeDelta SumOfStageHistory() const;
+
+ base::TimeTicks Now() const;
+
const bool should_report_metrics_;
StageData current_stage_;
+
BeginMainFrameMetrics blink_breakdown_;
+ base::TimeTicks blink_start_time_;
+ base::TimeDelta
+ blink_breakdown_list_[static_cast<int>(BlinkBreakdown::kBreakdownCount)];
+
viz::FrameTimingDetails viz_breakdown_;
+ base::TimeTicks viz_start_time_;
+ base::Optional<base::TimeDelta>
+ viz_breakdown_list_[static_cast<int>(VizBreakdown::kBreakdownCount)];
// Stage data is recorded here. On destruction these stages will be reported
// to UMA if the termination status is |kPresentedFrame|. Reported data will
// be divided based on the frame submission status.
std::vector<StageData> stage_history_;
- // This method is only used for DCheck
- base::TimeDelta SumOfStageHistory() const;
-
// List of metrics for events affecting this frame.
std::vector<EventMetrics> events_metrics_;
- FrameReportType report_type_ = FrameReportType::kNonDroppedFrame;
+ std::bitset<static_cast<size_t>(FrameReportType::kMaxValue) + 1>
+ report_types_;
+
base::TimeTicks frame_termination_time_;
base::TimeTicks begin_main_frame_start_;
FrameTerminationStatus frame_termination_status_ =
FrameTerminationStatus::kUnknown;
- const base::flat_set<FrameSequenceTrackerType>* active_trackers_;
+ const ActiveTrackers active_trackers_;
LatencyUkmReporter* latency_ukm_reporter_;
// Indicates if work on Impl frame is finished.
bool did_finish_impl_frame_ = false;
- // Indicates if main frame is aborted after begin.
- bool did_abort_main_frame_ = false;
- // Flag indicating if DidNotProduceFrame is called for this reporter
- bool did_not_produce_frame_ = false;
// The time that work on Impl frame is finished. It's only valid if the
// reporter is in a stage other than begin impl frame.
base::TimeTicks impl_frame_finish_time_;
base::TimeTicks frame_deadline_;
+
+ // The timestamp of when the frame was marked as not having produced a frame
+ // (through a call to DidNotProduceFrame()).
+ base::Optional<base::TimeTicks> did_not_produce_frame_time_;
+ base::Optional<FrameSkippedReason> frame_skip_reason_;
+ base::Optional<base::TimeTicks> main_frame_abort_time_;
+
+ const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance();
};
} // namespace cc
diff --git a/chromium/cc/metrics/compositor_frame_reporter_unittest.cc b/chromium/cc/metrics/compositor_frame_reporter_unittest.cc
index 1f4ffee37e7..afd8830e3e3 100644
--- a/chromium/cc/metrics/compositor_frame_reporter_unittest.cc
+++ b/chromium/cc/metrics/compositor_frame_reporter_unittest.cc
@@ -10,60 +10,76 @@
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
-#include "cc/input/scroll_input_type.h"
+#include "base/test/simple_test_tick_clock.h"
#include "cc/metrics/compositor_frame_reporting_controller.h"
#include "cc/metrics/event_metrics.h"
#include "components/viz/common/frame_timing_details.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/types/scroll_input_type.h"
namespace cc {
namespace {
-MATCHER(IsWhitelisted,
- base::StrCat({negation ? "isn't" : "is", " whitelisted"})) {
- return arg.IsWhitelisted();
-}
+using ::testing::Each;
+using ::testing::IsEmpty;
+using ::testing::NotNull;
class CompositorFrameReporterTest : public testing::Test {
public:
- const base::flat_set<FrameSequenceTrackerType> active_trackers = {};
CompositorFrameReporterTest()
: pipeline_reporter_(std::make_unique<CompositorFrameReporter>(
- &active_trackers,
+ CompositorFrameReporter::ActiveTrackers(),
viz::BeginFrameId(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(16),
nullptr,
/*should_report_metrics=*/true)) {
+ pipeline_reporter_->set_tick_clock(&test_tick_clock_);
AdvanceNowByMs(1);
}
protected:
- void AdvanceNowByMs(int advance_ms) {
- now_ += base::TimeDelta::FromMicroseconds(advance_ms);
+ base::TimeTicks AdvanceNowByMs(int advance_ms) {
+ test_tick_clock_.Advance(base::TimeDelta::FromMicroseconds(advance_ms));
+ return test_tick_clock_.NowTicks();
}
- base::TimeTicks Now() { return now_; }
+ base::TimeTicks Now() { return test_tick_clock_.NowTicks(); }
+
+ std::unique_ptr<BeginMainFrameMetrics> BuildBlinkBreakdown() {
+ auto breakdown = std::make_unique<BeginMainFrameMetrics>();
+ breakdown->handle_input_events = base::TimeDelta::FromMicroseconds(10);
+ breakdown->animate = base::TimeDelta::FromMicroseconds(9);
+ breakdown->style_update = base::TimeDelta::FromMicroseconds(8);
+ breakdown->layout_update = base::TimeDelta::FromMicroseconds(7);
+ breakdown->prepaint = base::TimeDelta::FromMicroseconds(6);
+ breakdown->composite = base::TimeDelta::FromMicroseconds(5);
+ breakdown->paint = base::TimeDelta::FromMicroseconds(4);
+ breakdown->scrolling_coordinator = base::TimeDelta::FromMicroseconds(3);
+ breakdown->composite_commit = base::TimeDelta::FromMicroseconds(2);
+ breakdown->update_layers = base::TimeDelta::FromMicroseconds(1);
+
+ // Advance now by the sum of the breakdowns.
+ AdvanceNowByMs(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1);
+
+ return breakdown;
+ }
- viz::FrameTimingDetails BuildFrameTimingDetails() {
- viz::FrameTimingDetails frame_timing_details;
- AdvanceNowByMs(1);
- frame_timing_details.received_compositor_frame_timestamp = Now();
- AdvanceNowByMs(1);
- frame_timing_details.draw_start_timestamp = Now();
- AdvanceNowByMs(1);
- frame_timing_details.swap_timings.swap_start = Now();
- AdvanceNowByMs(1);
- frame_timing_details.swap_timings.swap_end = Now();
- AdvanceNowByMs(1);
- frame_timing_details.presentation_feedback.timestamp = Now();
- return frame_timing_details;
+ viz::FrameTimingDetails BuildVizBreakdown() {
+ viz::FrameTimingDetails viz_breakdown;
+ viz_breakdown.received_compositor_frame_timestamp = AdvanceNowByMs(1);
+ viz_breakdown.draw_start_timestamp = AdvanceNowByMs(2);
+ viz_breakdown.swap_timings.swap_start = AdvanceNowByMs(3);
+ viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(4);
+ viz_breakdown.presentation_feedback.timestamp = AdvanceNowByMs(5);
+ return viz_breakdown;
}
- std::unique_ptr<CompositorFrameReporter> pipeline_reporter_;
+ // This should be defined before |pipeline_reporter_| so it is created before
+ // and destroyed after that.
+ base::SimpleTestTickClock test_tick_clock_;
- private:
- base::TimeTicks now_;
+ std::unique_ptr<CompositorFrameReporter> pipeline_reporter_;
};
TEST_F(CompositorFrameReporterTest, MainFrameAbortedReportingTest) {
@@ -209,18 +225,21 @@ TEST_F(CompositorFrameReporterTest, SubmittedDroppedFrameReportingTest) {
"CompositorLatency.DroppedFrame.TotalLatency", 5, 1);
}
-// Tests that when a frame is presented to the user, event latency metrics are
-// reported properly.
-TEST_F(CompositorFrameReporterTest, EventLatencyForPresentedFrameReported) {
+// Tests that when a frame is presented to the user, total event latency metrics
+// are reported properly.
+TEST_F(CompositorFrameReporterTest,
+ EventLatencyTotalForPresentedFrameReported) {
base::HistogramTester histogram_tester;
const base::TimeTicks event_time = Now();
- std::vector<EventMetrics> events_metrics = {
- {ui::ET_TOUCH_PRESSED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_TOUCH_PRESSED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
};
- EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {
+ *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]};
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
@@ -257,19 +276,166 @@ TEST_F(CompositorFrameReporterTest, EventLatencyForPresentedFrameReported) {
latency_ms, 2);
}
-// Tests that when a frame is presented to the user, scroll event latency
+// Tests that when a frame is presented to the user, event latency breakdown
// metrics are reported properly.
TEST_F(CompositorFrameReporterTest,
- EventLatencyScrollForPresentedFrameReported) {
+ EventLatencyBreakdownsForPresentedFrameReported) {
base::HistogramTester histogram_tester;
const base::TimeTicks event_time = Now();
- std::vector<EventMetrics> events_metrics = {
- {ui::ET_GESTURE_SCROLL_BEGIN, event_time, ScrollInputType::kWheel},
- {ui::ET_GESTURE_SCROLL_UPDATE, event_time, ScrollInputType::kWheel},
- {ui::ET_GESTURE_SCROLL_UPDATE, event_time, ScrollInputType::kWheel},
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_TOUCH_PRESSED, event_time, base::nullopt),
};
- EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {*event_metrics_ptrs[0]};
+
+ auto begin_impl_time = AdvanceNowByMs(2);
+ pipeline_reporter_->StartStage(
+ CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
+ begin_impl_time);
+
+ auto begin_main_time = AdvanceNowByMs(3);
+ pipeline_reporter_->StartStage(
+ CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit,
+ begin_main_time);
+
+ auto begin_main_start_time = AdvanceNowByMs(4);
+ std::unique_ptr<BeginMainFrameMetrics> blink_breakdown =
+ BuildBlinkBreakdown();
+ // Make a copy of the breakdown to use in verifying expectations in the end.
+ BeginMainFrameMetrics blink_breakdown_copy = *blink_breakdown;
+ pipeline_reporter_->SetBlinkBreakdown(std::move(blink_breakdown),
+ begin_main_start_time);
+ auto begin_commit_time = AdvanceNowByMs(5);
+ pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+ begin_commit_time);
+
+ auto end_commit_time = AdvanceNowByMs(6);
+ pipeline_reporter_->StartStage(
+ CompositorFrameReporter::StageType::kEndCommitToActivation,
+ end_commit_time);
+
+ auto begin_activation_time = AdvanceNowByMs(7);
+ pipeline_reporter_->StartStage(
+ CompositorFrameReporter::StageType::kActivation, begin_activation_time);
+
+ auto end_activation_time = AdvanceNowByMs(8);
+ pipeline_reporter_->StartStage(
+ CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
+ end_activation_time);
+
+ auto submit_time = AdvanceNowByMs(9);
+ pipeline_reporter_->StartStage(
+ CompositorFrameReporter::StageType::
+ kSubmitCompositorFrameToPresentationCompositorFrame,
+ submit_time);
+ pipeline_reporter_->SetEventsMetrics(std::move(events_metrics));
+
+ AdvanceNowByMs(10);
+ viz::FrameTimingDetails viz_breakdown = BuildVizBreakdown();
+ pipeline_reporter_->SetVizBreakdown(viz_breakdown);
+ pipeline_reporter_->TerminateFrame(
+ CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame,
+ viz_breakdown.presentation_feedback.timestamp);
+
+ pipeline_reporter_ = nullptr;
+
+ struct {
+ const char* name;
+ const base::TimeDelta latency;
+ } expected_latencies[] = {
+ {"EventLatency.TouchPressed.BrowserToRendererCompositor",
+ begin_impl_time - event_time},
+ {"EventLatency.TouchPressed.BeginImplFrameToSendBeginMainFrame",
+ begin_main_time - begin_impl_time},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit",
+ begin_commit_time - begin_main_time},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.HandleInputEvents",
+ blink_breakdown_copy.handle_input_events},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Animate",
+ blink_breakdown_copy.animate},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.StyleUpdate",
+ blink_breakdown_copy.style_update},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.LayoutUpdate",
+ blink_breakdown_copy.layout_update},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Prepaint",
+ blink_breakdown_copy.prepaint},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Composite",
+ blink_breakdown_copy.composite},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Paint",
+ blink_breakdown_copy.paint},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit."
+ "ScrollingCoordinator",
+ blink_breakdown_copy.scrolling_coordinator},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.CompositeCommit",
+ blink_breakdown_copy.composite_commit},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.UpdateLayers",
+ blink_breakdown_copy.update_layers},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit."
+ "BeginMainSentToStarted",
+ begin_main_start_time - begin_main_time},
+ {"EventLatency.TouchPressed.Commit", end_commit_time - begin_commit_time},
+ {"EventLatency.TouchPressed.EndCommitToActivation",
+ begin_activation_time - end_commit_time},
+ {"EventLatency.TouchPressed.Activation",
+ end_activation_time - begin_activation_time},
+ {"EventLatency.TouchPressed.EndActivateToSubmitCompositorFrame",
+ submit_time - end_activation_time},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ viz_breakdown.presentation_feedback.timestamp - submit_time},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "SubmitToReceiveCompositorFrame",
+ viz_breakdown.received_compositor_frame_timestamp - submit_time},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "ReceivedCompositorFrameToStartDraw",
+ viz_breakdown.draw_start_timestamp -
+ viz_breakdown.received_compositor_frame_timestamp},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "StartDrawToSwapStart",
+ viz_breakdown.swap_timings.swap_start -
+ viz_breakdown.draw_start_timestamp},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToSwapEnd",
+ viz_breakdown.swap_timings.swap_end -
+ viz_breakdown.swap_timings.swap_start},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "SwapEndToPresentationCompositorFrame",
+ viz_breakdown.presentation_feedback.timestamp -
+ viz_breakdown.swap_timings.swap_end},
+ {"EventLatency.TouchPressed.TotalLatency",
+ viz_breakdown.presentation_feedback.timestamp - event_time},
+ };
+
+ for (const auto& expected_latency : expected_latencies) {
+ histogram_tester.ExpectTotalCount(expected_latency.name, 1);
+ histogram_tester.ExpectBucketCount(
+ expected_latency.name, expected_latency.latency.InMicroseconds(), 1);
+ }
+}
+
+// Tests that when a frame is presented to the user, total scroll event latency
+// metrics are reported properly.
+TEST_F(CompositorFrameReporterTest,
+ EventLatencyScrollTotalForPresentedFrameReported) {
+ base::HistogramTester histogram_tester;
+
+ const base::TimeTicks event_time = Now();
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_GESTURE_SCROLL_BEGIN, event_time,
+ ui::ScrollInputType::kWheel),
+ EventMetrics::Create(ui::ET_GESTURE_SCROLL_UPDATE, event_time,
+ ui::ScrollInputType::kWheel),
+ EventMetrics::Create(ui::ET_GESTURE_SCROLL_UPDATE, event_time,
+ ui::ScrollInputType::kWheel),
+ };
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {
+ *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]};
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
@@ -289,40 +455,39 @@ TEST_F(CompositorFrameReporterTest,
pipeline_reporter_->SetEventsMetrics(std::move(events_metrics));
AdvanceNowByMs(3);
- viz::FrameTimingDetails frame_timing_details = BuildFrameTimingDetails();
- pipeline_reporter_->SetVizBreakdown(frame_timing_details);
+ viz::FrameTimingDetails viz_breakdown = BuildVizBreakdown();
+ pipeline_reporter_->SetVizBreakdown(viz_breakdown);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame,
- frame_timing_details.presentation_feedback.timestamp);
+ viz_breakdown.presentation_feedback.timestamp);
pipeline_reporter_ = nullptr;
const int total_latency_ms =
- (frame_timing_details.presentation_feedback.timestamp - event_time)
+ (viz_breakdown.presentation_feedback.timestamp - event_time)
.InMicroseconds();
const int swap_end_latency_ms =
- (frame_timing_details.swap_timings.swap_end - event_time)
- .InMicroseconds();
- histogram_tester.ExpectTotalCount(
- "EventLatency.GestureScrollBegin.Wheel.TotalLatency", 1);
- histogram_tester.ExpectTotalCount(
- "EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd", 1);
- histogram_tester.ExpectTotalCount(
- "EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 2);
- histogram_tester.ExpectTotalCount(
- "EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd", 2);
- histogram_tester.ExpectBucketCount(
- "EventLatency.GestureScrollBegin.Wheel.TotalLatency", total_latency_ms,
- 1);
- histogram_tester.ExpectBucketCount(
- "EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd",
- swap_end_latency_ms, 1);
- histogram_tester.ExpectBucketCount(
- "EventLatency.GestureScrollUpdate.Wheel.TotalLatency", total_latency_ms,
- 2);
- histogram_tester.ExpectBucketCount(
- "EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd",
- swap_end_latency_ms, 2);
+ (viz_breakdown.swap_timings.swap_end - event_time).InMicroseconds();
+ struct {
+ const char* name;
+ const int64_t latency_ms;
+ const int count;
+ } expected_counts[] = {
+ {"EventLatency.GestureScrollBegin.Wheel.TotalLatency", total_latency_ms,
+ 1},
+ {"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd",
+ swap_end_latency_ms, 1},
+ {"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", total_latency_ms,
+ 2},
+ {"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd",
+ swap_end_latency_ms, 2},
+ };
+ for (const auto& expected_count : expected_counts) {
+ histogram_tester.ExpectTotalCount(expected_count.name,
+ expected_count.count);
+ histogram_tester.ExpectBucketCount(
+ expected_count.name, expected_count.latency_ms, expected_count.count);
+ }
}
// Tests that when the frame is not presented to the user, event latency metrics
@@ -332,12 +497,14 @@ TEST_F(CompositorFrameReporterTest,
base::HistogramTester histogram_tester;
const base::TimeTicks event_time = Now();
- std::vector<EventMetrics> events_metrics = {
- {ui::ET_TOUCH_PRESSED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_TOUCH_PRESSED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
};
- EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {
+ *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]};
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
@@ -363,9 +530,8 @@ TEST_F(CompositorFrameReporterTest,
pipeline_reporter_ = nullptr;
- histogram_tester.ExpectTotalCount("EventLatency.TouchPressed.TotalLatency",
- 0);
- histogram_tester.ExpectTotalCount("EventLatency.TouchMoved.TotalLatency", 0);
+ EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("EventLaterncy."),
+ IsEmpty());
}
} // namespace
diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller.cc b/chromium/cc/metrics/compositor_frame_reporting_controller.cc
index 8a0f6dcb913..cd0ae991606 100644
--- a/chromium/cc/metrics/compositor_frame_reporting_controller.cc
+++ b/chromium/cc/metrics/compositor_frame_reporting_controller.cc
@@ -49,23 +49,28 @@ CompositorFrameReportingController::SubmittedCompositorFrame::
SubmittedCompositorFrame(SubmittedCompositorFrame&& other) = default;
base::TimeTicks CompositorFrameReportingController::Now() const {
- return base::TimeTicks::Now();
+ return tick_clock_->NowTicks();
+}
+
+bool CompositorFrameReportingController::HasReporterAt(
+ PipelineStage stage) const {
+ return !!reporters_[stage].get();
}
void CompositorFrameReportingController::WillBeginImplFrame(
const viz::BeginFrameArgs& args) {
base::TimeTicks begin_time = Now();
if (reporters_[PipelineStage::kBeginImplFrame]) {
- // If the the reporter is replaced in this stage, it means that Impl frame
- // caused no damage.
- reporters_[PipelineStage::kBeginImplFrame]->TerminateFrame(
- FrameTerminationStatus::kDidNotProduceFrame, begin_time);
+ auto& reporter = reporters_[PipelineStage::kBeginImplFrame];
+ DCHECK(reporter->did_finish_impl_frame());
+ DCHECK(reporter->did_not_produce_frame());
+ reporter->TerminateFrame(FrameTerminationStatus::kDidNotProduceFrame,
+ reporter->did_not_produce_frame_time());
}
- std::unique_ptr<CompositorFrameReporter> reporter =
- std::make_unique<CompositorFrameReporter>(
- &active_trackers_, args.frame_id,
- args.frame_time + (args.interval * 1.5), latency_ukm_reporter_.get(),
- should_report_metrics_);
+ auto reporter = std::make_unique<CompositorFrameReporter>(
+ active_trackers_, args.frame_id, args.frame_time + (args.interval * 1.5),
+ latency_ukm_reporter_.get(), should_report_metrics_);
+ reporter->set_tick_clock(tick_clock_);
reporter->StartStage(StageType::kBeginImplFrameToSendBeginMainFrame,
begin_time);
reporters_[PipelineStage::kBeginImplFrame] = std::move(reporter);
@@ -88,11 +93,11 @@ void CompositorFrameReportingController::WillBeginMainFrame(
// In this case we have already submitted the ImplFrame, but we received
// beginMain frame before next BeginImplFrame (Not reached the ImplFrame
// deadline yet). So will start a new reporter at BeginMainFrame.
- std::unique_ptr<CompositorFrameReporter> reporter =
- std::make_unique<CompositorFrameReporter>(
- &active_trackers_, args.frame_id,
- args.frame_time + (args.interval * 1.5),
- latency_ukm_reporter_.get(), should_report_metrics_);
+ auto reporter = std::make_unique<CompositorFrameReporter>(
+ active_trackers_, args.frame_id,
+ args.frame_time + (args.interval * 1.5), latency_ukm_reporter_.get(),
+ should_report_metrics_);
+ reporter->set_tick_clock(tick_clock_);
reporter->StartStage(StageType::kSendBeginMainFrameToCommit, Now());
reporters_[PipelineStage::kBeginMainFrame] = std::move(reporter);
}
@@ -236,6 +241,7 @@ void CompositorFrameReportingController::DidSubmitCompositorFrame(
}
if (impl_reporter) {
+ impl_reporter->EnableCompositorOnlyReporting();
impl_reporter->StartStage(
StageType::kSubmitCompositorFrameToPresentationCompositorFrame, Now());
impl_reporter->SetEventsMetrics(
@@ -246,7 +252,8 @@ void CompositorFrameReportingController::DidSubmitCompositorFrame(
}
void CompositorFrameReportingController::DidNotProduceFrame(
- const viz::BeginFrameId& id) {
+ const viz::BeginFrameId& id,
+ FrameSkippedReason skip_reason) {
for (auto& stage_reporter : reporters_) {
if (stage_reporter && stage_reporter->frame_id_ == id) {
// The reporter will be flagged and terminated when replaced by another
@@ -256,7 +263,7 @@ void CompositorFrameReportingController::DidNotProduceFrame(
// long, then DidNotProduceFrame() is called for the reporter in the
// BeginMain stage, but the main-thread can make updates, which can be
// submitted with the next frame.
- stage_reporter->OnDidNotProduceFrame();
+ stage_reporter->OnDidNotProduceFrame(skip_reason);
return;
}
}
@@ -291,6 +298,20 @@ void CompositorFrameReportingController::DidPresentCompositorFrame(
}
}
+void CompositorFrameReportingController::OnStoppedRequestingBeginFrames() {
+ // If the client stopped requesting begin-frames, that means the begin-frames
+ // currently being handled are no longer expected to produce any
+ // compositor-frames. So terminate the reporters.
+ auto now = Now();
+ for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) {
+ if (reporters_[i]) {
+ reporters_[i]->OnDidNotProduceFrame(FrameSkippedReason::kNoDamage);
+ reporters_[i]->TerminateFrame(FrameTerminationStatus::kDidNotProduceFrame,
+ now);
+ }
+ }
+}
+
void CompositorFrameReportingController::SetBlinkBreakdown(
std::unique_ptr<BeginMainFrameMetrics> details,
base::TimeTicks main_thread_start_time) {
@@ -301,24 +322,31 @@ void CompositorFrameReportingController::SetBlinkBreakdown(
void CompositorFrameReportingController::AddActiveTracker(
FrameSequenceTrackerType type) {
- active_trackers_.insert(type);
+ active_trackers_.set(static_cast<size_t>(type));
}
void CompositorFrameReportingController::RemoveActiveTracker(
FrameSequenceTrackerType type) {
- active_trackers_.erase(type);
+ active_trackers_.reset(static_cast<size_t>(type));
}
void CompositorFrameReportingController::AdvanceReporterStage(
PipelineStage start,
PipelineStage target) {
- if (reporters_[target]) {
- if (reporters_[target]->did_not_produce_frame())
- reporters_[target]->TerminateFrame(
- FrameTerminationStatus::kDidNotProduceFrame, Now());
- else
- reporters_[target]->TerminateFrame(
- FrameTerminationStatus::kReplacedByNewReporter, Now());
+ auto& reporter = reporters_[target];
+ if (reporter) {
+ auto termination_status = FrameTerminationStatus::kReplacedByNewReporter;
+ base::TimeTicks termination_time;
+ if (reporter->did_not_produce_frame()) {
+ termination_time = reporter->did_not_produce_frame_time();
+ termination_status = FrameTerminationStatus::kDidNotProduceFrame;
+ } else if (target == PipelineStage::kBeginMainFrame &&
+ reporter->did_abort_main_frame()) {
+ termination_time = reporter->main_frame_abort_time();
+ } else {
+ termination_time = Now();
+ }
+ reporter->TerminateFrame(termination_status, termination_time);
}
reporters_[target] = std::move(reporters_[start]);
}
diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller.h b/chromium/cc/metrics/compositor_frame_reporting_controller.h
index 8eb99e019df..fb6b219ce27 100644
--- a/chromium/cc/metrics/compositor_frame_reporting_controller.h
+++ b/chromium/cc/metrics/compositor_frame_reporting_controller.h
@@ -8,17 +8,19 @@
#include <memory>
#include <vector>
+#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "cc/metrics/compositor_frame_reporter.h"
#include "cc/metrics/event_metrics.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_metrics.h"
namespace viz {
struct FrameTimingDetails;
}
namespace cc {
+class UkmManager;
struct BeginMainFrameMetrics;
// This is used for managing simultaneous CompositorFrameReporter instances
@@ -60,11 +62,13 @@ class CC_EXPORT CompositorFrameReportingController {
const viz::BeginFrameId& current_frame_id,
const viz::BeginFrameId& last_activated_frame_id,
EventMetricsSet events_metrics);
- virtual void DidNotProduceFrame(const viz::BeginFrameId& id);
+ virtual void DidNotProduceFrame(const viz::BeginFrameId& id,
+ FrameSkippedReason skip_reason);
virtual void OnFinishImplFrame(const viz::BeginFrameId& id);
virtual void DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details);
+ void OnStoppedRequestingBeginFrames();
void SetBlinkBreakdown(std::unique_ptr<BeginMainFrameMetrics> details,
base::TimeTicks main_thread_start_time);
@@ -74,7 +78,12 @@ class CC_EXPORT CompositorFrameReportingController {
virtual void AddActiveTracker(FrameSequenceTrackerType type);
virtual void RemoveActiveTracker(FrameSequenceTrackerType type);
- base::flat_set<FrameSequenceTrackerType> active_trackers_;
+ void set_tick_clock(const base::TickClock* tick_clock) {
+ DCHECK(tick_clock);
+ tick_clock_ = tick_clock;
+ }
+
+ std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; }
protected:
struct SubmittedCompositorFrame {
@@ -87,8 +96,8 @@ class CC_EXPORT CompositorFrameReportingController {
~SubmittedCompositorFrame();
};
base::TimeTicks Now() const;
- std::unique_ptr<CompositorFrameReporter>
- reporters_[PipelineStage::kNumPipelineStages];
+
+ bool HasReporterAt(PipelineStage stage) const;
private:
void AdvanceReporterStage(PipelineStage start, PipelineStage target);
@@ -101,6 +110,7 @@ class CC_EXPORT CompositorFrameReportingController {
viz::BeginFrameId last_submitted_frame_id_;
bool next_activate_has_invalidation_ = false;
+ CompositorFrameReporter::ActiveTrackers active_trackers_;
// The latency reporter passed to each CompositorFrameReporter. Owned here
// because it must be common among all reporters.
@@ -108,11 +118,16 @@ class CC_EXPORT CompositorFrameReportingController {
// outlive the objects in |submitted_compositor_frames_|.
std::unique_ptr<LatencyUkmReporter> latency_ukm_reporter_;
+ std::unique_ptr<CompositorFrameReporter>
+ reporters_[PipelineStage::kNumPipelineStages];
+
// Mapping of frame token to pipeline reporter for submitted compositor
// frames.
// DO NOT reorder this line and the one above. The latency_ukm_reporter_ must
// outlive the objects in |submitted_compositor_frames_|.
base::circular_deque<SubmittedCompositorFrame> submitted_compositor_frames_;
+
+ const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance();
};
} // namespace cc
diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc
index 64da64b3a3d..ca70577d732 100644
--- a/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc
+++ b/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -10,20 +10,20 @@
#include "base/macros.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
-#include "cc/input/scroll_input_type.h"
+#include "base/test/simple_test_tick_clock.h"
#include "cc/metrics/event_metrics.h"
#include "components/viz/common/frame_timing_details.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/types/scroll_input_type.h"
namespace cc {
namespace {
-MATCHER(IsWhitelisted,
- base::StrCat({negation ? "isn't" : "is", " whitelisted"})) {
- return arg.IsWhitelisted();
-}
+using ::testing::Each;
+using ::testing::IsEmpty;
+using ::testing::NotNull;
class TestCompositorFrameReportingController
: public CompositorFrameReportingController {
@@ -37,27 +37,35 @@ class TestCompositorFrameReportingController
TestCompositorFrameReportingController& operator=(
const TestCompositorFrameReportingController& controller) = delete;
- std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; }
-
int ActiveReporters() {
int count = 0;
for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) {
- if (reporters_[i])
+ if (reporters()[i])
++count;
}
return count;
}
+
+ void ResetReporters() {
+ for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) {
+ reporters()[i] = nullptr;
+ }
+ }
};
class CompositorFrameReportingControllerTest : public testing::Test {
public:
CompositorFrameReportingControllerTest() : current_id_(1, 1) {
+ test_tick_clock_.SetNowTicks(base::TimeTicks::Now());
+ reporting_controller_.set_tick_clock(&test_tick_clock_);
args_ = SimulateBeginFrameArgs(current_id_);
}
// The following functions simulate the actions that would
// occur for each phase of the reporting controller.
void SimulateBeginImplFrame() {
+ IncrementCurrentId();
+ begin_impl_time_ = AdvanceNowByMs(10);
reporting_controller_.WillBeginImplFrame(args_);
}
@@ -68,22 +76,25 @@ class CompositorFrameReportingControllerTest : public testing::Test {
CHECK(
reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginImplFrame]);
+ begin_main_time_ = AdvanceNowByMs(10);
reporting_controller_.WillBeginMainFrame(args_);
+ begin_main_start_time_ = AdvanceNowByMs(10);
}
void SimulateCommit(std::unique_ptr<BeginMainFrameMetrics> blink_breakdown) {
if (!reporting_controller_
.reporters()[CompositorFrameReportingController::PipelineStage::
kBeginMainFrame]) {
- begin_main_start_ = base::TimeTicks::Now();
SimulateBeginMainFrame();
}
CHECK(
reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginMainFrame]);
reporting_controller_.SetBlinkBreakdown(std::move(blink_breakdown),
- begin_main_start_);
+ begin_main_start_time_);
+ begin_commit_time_ = AdvanceNowByMs(10);
reporting_controller_.WillCommit();
+ end_commit_time_ = AdvanceNowByMs(10);
reporting_controller_.DidCommit();
}
@@ -93,7 +104,9 @@ class CompositorFrameReportingControllerTest : public testing::Test {
SimulateCommit(nullptr);
CHECK(reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kCommit]);
+ begin_activation_time_ = AdvanceNowByMs(10);
reporting_controller_.WillActivate();
+ end_activation_time_ = AdvanceNowByMs(10);
reporting_controller_.DidActivate();
last_activated_id_ = current_id_;
}
@@ -105,6 +118,7 @@ class CompositorFrameReportingControllerTest : public testing::Test {
SimulateActivate();
CHECK(reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kActivate]);
+ submit_time_ = AdvanceNowByMs(10);
reporting_controller_.DidSubmitCompositorFrame(frame_token, current_id_,
last_activated_id_,
std::move(events_metrics));
@@ -114,32 +128,74 @@ class CompositorFrameReportingControllerTest : public testing::Test {
++next_token_;
SimulateSubmitCompositorFrame(*next_token_, {});
viz::FrameTimingDetails details = {};
- details.presentation_feedback.timestamp = base::TimeTicks::Now();
+ details.presentation_feedback.timestamp = AdvanceNowByMs(10);
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
}
- viz::BeginFrameArgs SimulateBeginFrameArgs(
- viz::BeginFrameId frame_id,
- base::TimeTicks frame_time = base::TimeTicks::Now(),
- base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16)) {
+ viz::BeginFrameArgs SimulateBeginFrameArgs(viz::BeginFrameId frame_id) {
args_ = viz::BeginFrameArgs();
args_.frame_id = frame_id;
- args_.frame_time = frame_time;
- args_.interval = interval;
+ args_.frame_time = AdvanceNowByMs(10);
+ args_.interval = base::TimeDelta::FromMilliseconds(16);
return args_;
}
+ std::unique_ptr<BeginMainFrameMetrics> BuildBlinkBreakdown() {
+ auto breakdown = std::make_unique<BeginMainFrameMetrics>();
+ breakdown->handle_input_events = base::TimeDelta::FromMicroseconds(10);
+ breakdown->animate = base::TimeDelta::FromMicroseconds(9);
+ breakdown->style_update = base::TimeDelta::FromMicroseconds(8);
+ breakdown->layout_update = base::TimeDelta::FromMicroseconds(7);
+ breakdown->prepaint = base::TimeDelta::FromMicroseconds(6);
+ breakdown->composite = base::TimeDelta::FromMicroseconds(5);
+ breakdown->paint = base::TimeDelta::FromMicroseconds(4);
+ breakdown->scrolling_coordinator = base::TimeDelta::FromMicroseconds(3);
+ breakdown->composite_commit = base::TimeDelta::FromMicroseconds(2);
+ breakdown->update_layers = base::TimeDelta::FromMicroseconds(1);
+
+ // Advance now by the sum of the breakdowns.
+ AdvanceNowByMs(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1);
+
+ return breakdown;
+ }
+
+ viz::FrameTimingDetails BuildVizBreakdown() {
+ viz::FrameTimingDetails viz_breakdown;
+ viz_breakdown.received_compositor_frame_timestamp = AdvanceNowByMs(1);
+ viz_breakdown.draw_start_timestamp = AdvanceNowByMs(2);
+ viz_breakdown.swap_timings.swap_start = AdvanceNowByMs(3);
+ viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(4);
+ viz_breakdown.presentation_feedback.timestamp = AdvanceNowByMs(5);
+ return viz_breakdown;
+ }
+
void IncrementCurrentId() {
current_id_.sequence_number++;
args_.frame_id = current_id_;
}
+ base::TimeTicks AdvanceNowByMs(int64_t advance_ms) {
+ test_tick_clock_.Advance(base::TimeDelta::FromMicroseconds(advance_ms));
+ return test_tick_clock_.NowTicks();
+ }
+
protected:
+ // This should be defined before |reporting_controller_| so it is created
+ // before and destroyed after that.
+ base::SimpleTestTickClock test_tick_clock_;
+
TestCompositorFrameReportingController reporting_controller_;
viz::BeginFrameArgs args_;
viz::BeginFrameId current_id_;
viz::BeginFrameId last_activated_id_;
- base::TimeTicks begin_main_start_;
+ base::TimeTicks begin_impl_time_;
+ base::TimeTicks begin_main_time_;
+ base::TimeTicks begin_main_start_time_;
+ base::TimeTicks begin_commit_time_;
+ base::TimeTicks end_commit_time_;
+ base::TimeTicks begin_activation_time_;
+ base::TimeTicks end_activation_time_;
+ base::TimeTicks submit_time_;
viz::FrameTokenGenerator next_token_;
};
@@ -166,11 +222,17 @@ TEST_F(CompositorFrameReportingControllerTest, ActiveReporterCounts) {
// BF
reporting_controller_.WillBeginImplFrame(args_1);
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
+ reporting_controller_.OnFinishImplFrame(args_1.frame_id);
+ reporting_controller_.DidNotProduceFrame(args_1.frame_id,
+ FrameSkippedReason::kNoDamage);
// BF -> BF
// Should replace previous reporter.
reporting_controller_.WillBeginImplFrame(args_2);
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
+ reporting_controller_.OnFinishImplFrame(args_2.frame_id);
+ reporting_controller_.DidNotProduceFrame(args_2.frame_id,
+ FrameSkippedReason::kNoDamage);
// BF -> BMF -> BF
// Should add new reporter.
@@ -207,22 +269,47 @@ TEST_F(CompositorFrameReportingControllerTest, ActiveReporterCounts) {
last_activated_id_, {});
EXPECT_EQ(0, reporting_controller_.ActiveReporters());
- // 4 simultaneous reporters active.
+ // Start a frame and take it all the way to the activate stage.
SimulateActivate();
+ EXPECT_EQ(1, reporting_controller_.ActiveReporters());
+ // Start another frame and let it progress up to the commit stage.
SimulateCommit(nullptr);
+ EXPECT_EQ(2, reporting_controller_.ActiveReporters());
+ // Start the next frame, and let it progress up to the main-frame.
SimulateBeginMainFrame();
+ EXPECT_EQ(3, reporting_controller_.ActiveReporters());
+ // Start the next frame.
SimulateBeginImplFrame();
EXPECT_EQ(4, reporting_controller_.ActiveReporters());
+ reporting_controller_.OnFinishImplFrame(args_.frame_id);
+ reporting_controller_.DidNotProduceFrame(args_.frame_id,
+ FrameSkippedReason::kNoDamage);
+
// Any additional BeginImplFrame's would be ignored.
SimulateBeginImplFrame();
EXPECT_EQ(4, reporting_controller_.ActiveReporters());
}
TEST_F(CompositorFrameReportingControllerTest,
+ StopRequestingFramesCancelsInFlightFrames) {
+ base::HistogramTester histogram_tester;
+
+ // 2 reporters active.
+ SimulateActivate();
+ SimulateCommit(nullptr);
+
+ reporting_controller_.OnStoppedRequestingBeginFrames();
+ reporting_controller_.ResetReporters();
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kDroppedFrame, 0);
+}
+
+TEST_F(CompositorFrameReportingControllerTest,
SubmittedFrameHistogramReporting) {
base::HistogramTester histogram_tester;
@@ -288,9 +375,25 @@ TEST_F(CompositorFrameReportingControllerTest, ImplFrameCausedNoDamage) {
base::HistogramTester histogram_tester;
SimulateBeginImplFrame();
+ reporting_controller_.OnFinishImplFrame(args_.frame_id);
+ reporting_controller_.DidNotProduceFrame(args_.frame_id,
+ FrameSkippedReason::kNoDamage);
SimulateBeginImplFrame();
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kDroppedFrame, 0);
+
+ reporting_controller_.OnFinishImplFrame(args_.frame_id);
+ reporting_controller_.DidNotProduceFrame(args_.frame_id,
+ FrameSkippedReason::kWaitingOnMain);
+ SimulateBeginImplFrame();
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 1);
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kDroppedFrame, 1);
}
TEST_F(CompositorFrameReportingControllerTest, MainFrameCausedNoDamage) {
@@ -308,13 +411,15 @@ TEST_F(CompositorFrameReportingControllerTest, MainFrameCausedNoDamage) {
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.BeginMainFrameAborted(current_id_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
- reporting_controller_.DidNotProduceFrame(current_id_1);
+ reporting_controller_.DidNotProduceFrame(current_id_1,
+ FrameSkippedReason::kNoDamage);
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.WillBeginMainFrame(args_2);
reporting_controller_.OnFinishImplFrame(current_id_2);
reporting_controller_.BeginMainFrameAborted(current_id_2);
- reporting_controller_.DidNotProduceFrame(current_id_2);
+ reporting_controller_.DidNotProduceFrame(current_id_2,
+ FrameSkippedReason::kNoDamage);
reporting_controller_.WillBeginImplFrame(args_3);
reporting_controller_.WillBeginMainFrame(args_3);
@@ -337,7 +442,8 @@ TEST_F(CompositorFrameReportingControllerTest, DidNotProduceFrame) {
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
- reporting_controller_.DidNotProduceFrame(current_id_1);
+ reporting_controller_.DidNotProduceFrame(current_id_1,
+ FrameSkippedReason::kNoDamage);
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.OnFinishImplFrame(current_id_2);
@@ -367,6 +473,73 @@ TEST_F(CompositorFrameReportingControllerTest, DidNotProduceFrame) {
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
2);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame.BeginImplFrameToFinishImpl", 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "ImplFrameDoneToSubmitCompositorFrame",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ 1);
+}
+
+TEST_F(CompositorFrameReportingControllerTest,
+ DidNotProduceFrameDueToWaitingOnMain) {
+ base::HistogramTester histogram_tester;
+
+ viz::BeginFrameId current_id_1(1, 1);
+ viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
+
+ viz::BeginFrameId current_id_2(1, 2);
+ viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
+ args_2.frame_time = args_1.frame_time + args_1.interval;
+
+ viz::BeginFrameId current_id_3(1, 3);
+ viz::BeginFrameArgs args_3 = SimulateBeginFrameArgs(current_id_3);
+ args_3.frame_time = args_2.frame_time + args_2.interval;
+
+ reporting_controller_.WillBeginImplFrame(args_1);
+ reporting_controller_.WillBeginMainFrame(args_1);
+ reporting_controller_.OnFinishImplFrame(current_id_1);
+ reporting_controller_.DidNotProduceFrame(current_id_1,
+ FrameSkippedReason::kWaitingOnMain);
+
+ reporting_controller_.WillBeginImplFrame(args_2);
+ reporting_controller_.OnFinishImplFrame(current_id_2);
+ reporting_controller_.DidNotProduceFrame(current_id_2,
+ FrameSkippedReason::kWaitingOnMain);
+
+ reporting_controller_.WillBeginImplFrame(args_3);
+ reporting_controller_.WillCommit();
+ reporting_controller_.DidCommit();
+ reporting_controller_.WillActivate();
+ reporting_controller_.DidActivate();
+ reporting_controller_.OnFinishImplFrame(current_id_3);
+ reporting_controller_.DidSubmitCompositorFrame(1, current_id_3, current_id_1,
+ {});
+ viz::FrameTimingDetails details;
+ details.presentation_feedback = {args_3.frame_time + args_3.interval,
+ args_3.interval, 0};
+ reporting_controller_.DidPresentCompositorFrame(1, details);
+
+ // Frame for |args_2| was dropped waiting on the main-thread.
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kDroppedFrame, 1);
+
+ // Frames for |args_1| and |args_3| were presented, although |args_1| missed
+ // its deadline.
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kNonDroppedFrame, 2);
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kMissedDeadlineFrame, 1);
+ histogram_tester.ExpectBucketCount(
+ "CompositorLatency.Type",
+ CompositorFrameReporter::FrameReportType::kCompositorOnlyFrame, 1);
}
TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted) {
@@ -384,6 +557,8 @@ TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted) {
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 0);
histogram_tester.ExpectTotalCount(
@@ -391,6 +566,20 @@ TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted) {
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame.BeginImplFrameToFinishImpl", 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SendBeginMainFrameToBeginMainAbort",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "ImplFrameDoneToSubmitCompositorFrame",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ 1);
}
TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted2) {
@@ -533,6 +722,20 @@ TEST_F(CompositorFrameReportingControllerTest, LongMainFrame) {
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
2);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame.BeginImplFrameToFinishImpl", 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SendBeginMainFrameToBeginMainAbort",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "ImplFrameDoneToSubmitCompositorFrame",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ 1);
reporting_controller_.WillBeginImplFrame(args_3);
reporting_controller_.OnFinishImplFrame(current_id_3);
@@ -557,6 +760,20 @@ TEST_F(CompositorFrameReportingControllerTest, LongMainFrame) {
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
4);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame.BeginImplFrameToFinishImpl", 2);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SendBeginMainFrameToBeginMainAbort",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "ImplFrameDoneToSubmitCompositorFrame",
+ 2);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ 2);
}
TEST_F(CompositorFrameReportingControllerTest, LongMainFrame2) {
@@ -617,24 +834,27 @@ TEST_F(CompositorFrameReportingControllerTest, LongMainFrame2) {
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
2);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame.BeginImplFrameToFinishImpl", 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SendBeginMainFrameToBeginMainAbort",
+ 0);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "ImplFrameDoneToSubmitCompositorFrame",
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "CompositorLatency.CompositorOnlyFrame."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ 1);
}
TEST_F(CompositorFrameReportingControllerTest, BlinkBreakdown) {
base::HistogramTester histogram_tester;
std::unique_ptr<BeginMainFrameMetrics> blink_breakdown =
- std::make_unique<BeginMainFrameMetrics>();
- blink_breakdown->handle_input_events = base::TimeDelta::FromMicroseconds(10);
- blink_breakdown->animate = base::TimeDelta::FromMicroseconds(9);
- blink_breakdown->style_update = base::TimeDelta::FromMicroseconds(8);
- blink_breakdown->layout_update = base::TimeDelta::FromMicroseconds(7);
- blink_breakdown->prepaint = base::TimeDelta::FromMicroseconds(6);
- blink_breakdown->composite = base::TimeDelta::FromMicroseconds(5);
- blink_breakdown->paint = base::TimeDelta::FromMicroseconds(4);
- blink_breakdown->scrolling_coordinator = base::TimeDelta::FromMicroseconds(3);
- blink_breakdown->composite_commit = base::TimeDelta::FromMicroseconds(2);
- blink_breakdown->update_layers = base::TimeDelta::FromMicroseconds(1);
-
+ BuildBlinkBreakdown();
SimulateActivate();
SimulateCommit(std::move(blink_breakdown));
SimulatePresentCompositorFrame();
@@ -710,6 +930,8 @@ TEST_F(CompositorFrameReportingControllerTest, ReportingMissedDeadlineFrame1) {
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 1, 0);
// Dropped cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 2, 0);
+ // Impl only cases.
+ histogram_tester.ExpectBucketCount("CompositorLatency.Type", 3, 0);
}
// If the presentation of the frame happens after deadline.
@@ -749,19 +971,21 @@ TEST_F(CompositorFrameReportingControllerTest, ReportingMissedDeadlineFrame2) {
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 2, 0);
}
-// Tests that EventLatency histograms are reported properly when a frame is
-// presented to the user.
+// Tests that EventLatency total latency histograms are reported properly when a
+// frame is presented to the user.
TEST_F(CompositorFrameReportingControllerTest,
- EventLatencyForPresentedFrameReported) {
+ EventLatencyTotalForPresentedFrameReported) {
base::HistogramTester histogram_tester;
- const base::TimeTicks event_time = base::TimeTicks::Now();
- std::vector<EventMetrics> events_metrics = {
- {ui::ET_TOUCH_PRESSED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
+ const base::TimeTicks event_time = AdvanceNowByMs(10);
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_TOUCH_PRESSED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
};
- EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {
+ *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]};
// Submit a compositor frame and notify CompositorFrameReporter of the events
// affecting the frame.
@@ -769,13 +993,13 @@ TEST_F(CompositorFrameReportingControllerTest,
SimulateSubmitCompositorFrame(*next_token_, {std::move(events_metrics), {}});
// Present the submitted compositor frame to the user.
- const base::TimeTicks presentation_time = base::TimeTicks::Now();
+ const base::TimeTicks presentation_time = AdvanceNowByMs(10);
viz::FrameTimingDetails details;
details.presentation_feedback.timestamp = presentation_time;
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
// Verify that EventLatency histograms are recorded.
- const int latency_ms = (presentation_time - event_time).InMicroseconds();
+ const int64_t latency_ms = (presentation_time - event_time).InMicroseconds();
histogram_tester.ExpectTotalCount("EventLatency.TouchPressed.TotalLatency",
1);
histogram_tester.ExpectTotalCount("EventLatency.TouchMoved.TotalLatency", 2);
@@ -785,19 +1009,134 @@ TEST_F(CompositorFrameReportingControllerTest,
latency_ms, 2);
}
-// Tests that EventLatency histograms are reported properly for scroll events
-// when a frame is presented to the user.
+// Tests that EventLatency breakdown histograms are reported properly when a
+// frame is presented to the user.
TEST_F(CompositorFrameReportingControllerTest,
- EventLatencyScrollForPresentedFrameReported) {
+ EventLatencyBreakdownsForPresentedFrameReported) {
base::HistogramTester histogram_tester;
- const base::TimeTicks event_time = base::TimeTicks::Now();
- std::vector<EventMetrics> events_metrics = {
- {ui::ET_GESTURE_SCROLL_BEGIN, event_time, ScrollInputType::kWheel},
- {ui::ET_GESTURE_SCROLL_UPDATE, event_time, ScrollInputType::kWheel},
- {ui::ET_GESTURE_SCROLL_UPDATE, event_time, ScrollInputType::kWheel},
+ const base::TimeTicks event_time = AdvanceNowByMs(10);
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_TOUCH_PRESSED, event_time, base::nullopt),
};
- EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {*event_metrics_ptrs[0]};
+
+ // Do a commit with a breakdown of blink stages.
+ std::unique_ptr<BeginMainFrameMetrics> blink_breakdown =
+ BuildBlinkBreakdown();
+ // Make a copy of the breakdown to use in verifying expectations in the end.
+ BeginMainFrameMetrics blink_breakdown_copy = *blink_breakdown;
+ SimulateCommit(std::move(blink_breakdown));
+
+ // Submit a compositor frame and notify CompositorFrameReporter of the events
+ // affecting the frame.
+ ++next_token_;
+ SimulateSubmitCompositorFrame(*next_token_, {std::move(events_metrics), {}});
+
+ // Present the submitted compositor frame to the user.
+ AdvanceNowByMs(10);
+ viz::FrameTimingDetails viz_breakdown = BuildVizBreakdown();
+ reporting_controller_.DidPresentCompositorFrame(*next_token_, viz_breakdown);
+
+ // Verify that EventLatency histograms are recorded.
+ struct {
+ const char* name;
+ const base::TimeDelta latency;
+ } expected_latencies[] = {
+ {"EventLatency.TouchPressed.BrowserToRendererCompositor",
+ begin_impl_time_ - event_time},
+ {"EventLatency.TouchPressed.BeginImplFrameToSendBeginMainFrame",
+ begin_main_time_ - begin_impl_time_},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit",
+ begin_commit_time_ - begin_main_time_},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.HandleInputEvents",
+ blink_breakdown_copy.handle_input_events},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Animate",
+ blink_breakdown_copy.animate},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.StyleUpdate",
+ blink_breakdown_copy.style_update},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.LayoutUpdate",
+ blink_breakdown_copy.layout_update},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Prepaint",
+ blink_breakdown_copy.prepaint},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Composite",
+ blink_breakdown_copy.composite},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.Paint",
+ blink_breakdown_copy.paint},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit."
+ "ScrollingCoordinator",
+ blink_breakdown_copy.scrolling_coordinator},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.CompositeCommit",
+ blink_breakdown_copy.composite_commit},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit.UpdateLayers",
+ blink_breakdown_copy.update_layers},
+ {"EventLatency.TouchPressed.SendBeginMainFrameToCommit."
+ "BeginMainSentToStarted",
+ begin_main_start_time_ - begin_main_time_},
+ {"EventLatency.TouchPressed.Commit",
+ end_commit_time_ - begin_commit_time_},
+ {"EventLatency.TouchPressed.EndCommitToActivation",
+ begin_activation_time_ - end_commit_time_},
+ {"EventLatency.TouchPressed.Activation",
+ end_activation_time_ - begin_activation_time_},
+ {"EventLatency.TouchPressed.EndActivateToSubmitCompositorFrame",
+ submit_time_ - end_activation_time_},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame",
+ viz_breakdown.presentation_feedback.timestamp - submit_time_},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "SubmitToReceiveCompositorFrame",
+ viz_breakdown.received_compositor_frame_timestamp - submit_time_},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "ReceivedCompositorFrameToStartDraw",
+ viz_breakdown.draw_start_timestamp -
+ viz_breakdown.received_compositor_frame_timestamp},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "StartDrawToSwapStart",
+ viz_breakdown.swap_timings.swap_start -
+ viz_breakdown.draw_start_timestamp},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame.SwapStartToSwapEnd",
+ viz_breakdown.swap_timings.swap_end -
+ viz_breakdown.swap_timings.swap_start},
+ {"EventLatency.TouchPressed."
+ "SubmitCompositorFrameToPresentationCompositorFrame."
+ "SwapEndToPresentationCompositorFrame",
+ viz_breakdown.presentation_feedback.timestamp -
+ viz_breakdown.swap_timings.swap_end},
+ {"EventLatency.TouchPressed.TotalLatency",
+ viz_breakdown.presentation_feedback.timestamp - event_time},
+ };
+
+ for (const auto& expected_latency : expected_latencies) {
+ histogram_tester.ExpectTotalCount(expected_latency.name, 1);
+ histogram_tester.ExpectBucketCount(
+ expected_latency.name, expected_latency.latency.InMicroseconds(), 1);
+ }
+}
+
+// Tests that EventLatency total latency histograms are reported properly for
+// scroll events when a frame is presented to the user.
+TEST_F(CompositorFrameReportingControllerTest,
+ EventLatencyScrollTotalForPresentedFrameReported) {
+ base::HistogramTester histogram_tester;
+
+ const base::TimeTicks event_time = AdvanceNowByMs(10);
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_GESTURE_SCROLL_BEGIN, event_time,
+ ui::ScrollInputType::kWheel),
+ EventMetrics::Create(ui::ET_GESTURE_SCROLL_UPDATE, event_time,
+ ui::ScrollInputType::kWheel),
+ EventMetrics::Create(ui::ET_GESTURE_SCROLL_UPDATE, event_time,
+ ui::ScrollInputType::kWheel),
+ };
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {
+ *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]};
// Submit a compositor frame and notify CompositorFrameReporter of the events
// affecting the frame.
@@ -805,21 +1144,39 @@ TEST_F(CompositorFrameReportingControllerTest,
SimulateSubmitCompositorFrame(*next_token_, {std::move(events_metrics), {}});
// Present the submitted compositor frame to the user.
- const base::TimeTicks presentation_time = base::TimeTicks::Now();
viz::FrameTimingDetails details;
- details.presentation_feedback.timestamp = presentation_time;
+ details.received_compositor_frame_timestamp = AdvanceNowByMs(10);
+ details.draw_start_timestamp = AdvanceNowByMs(10);
+ details.swap_timings.swap_start = AdvanceNowByMs(10);
+ details.swap_timings.swap_end = AdvanceNowByMs(10);
+ details.presentation_feedback.timestamp = AdvanceNowByMs(10);
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
// Verify that EventLatency histograms are recorded.
- const int latency_ms = (presentation_time - event_time).InMicroseconds();
- histogram_tester.ExpectTotalCount(
- "EventLatency.GestureScrollBegin.Wheel.TotalLatency", 1);
- histogram_tester.ExpectTotalCount(
- "EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 2);
- histogram_tester.ExpectBucketCount(
- "EventLatency.GestureScrollBegin.Wheel.TotalLatency", latency_ms, 1);
- histogram_tester.ExpectBucketCount(
- "EventLatency.GestureScrollUpdate.Wheel.TotalLatency", latency_ms, 2);
+ const int64_t total_latency_ms =
+ (details.presentation_feedback.timestamp - event_time).InMicroseconds();
+ const int64_t swap_end_latency_ms =
+ (details.swap_timings.swap_end - event_time).InMicroseconds();
+ struct {
+ const char* name;
+ const int64_t latency_ms;
+ const int count;
+ } expected_counts[] = {
+ {"EventLatency.GestureScrollBegin.Wheel.TotalLatency", total_latency_ms,
+ 1},
+ {"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapEnd",
+ swap_end_latency_ms, 1},
+ {"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", total_latency_ms,
+ 2},
+ {"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapEnd",
+ swap_end_latency_ms, 2},
+ };
+ for (const auto& expected_count : expected_counts) {
+ histogram_tester.ExpectTotalCount(expected_count.name,
+ expected_count.count);
+ histogram_tester.ExpectBucketCount(
+ expected_count.name, expected_count.latency_ms, expected_count.count);
+ }
}
// Tests that EventLatency histograms are not reported when the frame is dropped
@@ -828,13 +1185,15 @@ TEST_F(CompositorFrameReportingControllerTest,
EventLatencyForDidNotPresentFrameNotReported) {
base::HistogramTester histogram_tester;
- const base::TimeTicks event_time = base::TimeTicks::Now();
- std::vector<EventMetrics> events_metrics = {
- {ui::ET_TOUCH_PRESSED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
- {ui::ET_TOUCH_MOVED, event_time, base::nullopt},
+ const base::TimeTicks event_time = AdvanceNowByMs(10);
+ std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
+ EventMetrics::Create(ui::ET_TOUCH_PRESSED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
+ EventMetrics::Create(ui::ET_TOUCH_MOVED, event_time, base::nullopt),
};
- EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
+ EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
+ std::vector<EventMetrics> events_metrics = {
+ *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]};
// Submit a compositor frame and notify CompositorFrameReporter of the events
// affecting the frame.
@@ -848,13 +1207,12 @@ TEST_F(CompositorFrameReportingControllerTest,
// Present the second compositor frame to the uesr, dropping the first one.
viz::FrameTimingDetails details;
- details.presentation_feedback.timestamp = base::TimeTicks::Now();
+ details.presentation_feedback.timestamp = AdvanceNowByMs(10);
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
// Verify that no EventLatency histogram is recorded.
- histogram_tester.ExpectTotalCount("EventLatency.TouchPressed.TotalLatency",
- 0);
- histogram_tester.ExpectTotalCount("EventLatency.TouchMoved.TotalLatency", 0);
+ EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("EventLatency."),
+ IsEmpty());
}
} // namespace
diff --git a/chromium/cc/metrics/compositor_timing_history.cc b/chromium/cc/metrics/compositor_timing_history.cc
index db507429503..d0cc7d44262 100644
--- a/chromium/cc/metrics/compositor_timing_history.cc
+++ b/chromium/cc/metrics/compositor_timing_history.cc
@@ -514,13 +514,10 @@ CompositorTimingHistory::CreateUMAReporter(UMACategory category) {
switch (category) {
case RENDERER_UMA:
return base::WrapUnique(new RendererUMAReporter);
- break;
case BROWSER_UMA:
return base::WrapUnique(new BrowserUMAReporter);
- break;
case NULL_UMA:
return base::WrapUnique(new NullUMAReporter);
- break;
}
NOTREACHED();
return base::WrapUnique<CompositorTimingHistory::UMAReporter>(nullptr);
@@ -662,6 +659,7 @@ void CompositorTimingHistory::WillFinishImplFrame(bool needs_redraw,
void CompositorTimingHistory::BeginImplFrameNotExpectedSoon() {
SetBeginMainFrameNeededContinuously(false);
SetCompositorDrawingContinuously(false);
+ compositor_frame_reporting_controller_->OnStoppedRequestingBeginFrames();
}
void CompositorTimingHistory::WillBeginMainFrame(
@@ -951,8 +949,10 @@ void CompositorTimingHistory::DidSubmitCompositorFrame(
submit_start_time_ = Now();
}
-void CompositorTimingHistory::DidNotProduceFrame(const viz::BeginFrameId& id) {
- compositor_frame_reporting_controller_->DidNotProduceFrame(id);
+void CompositorTimingHistory::DidNotProduceFrame(
+ const viz::BeginFrameId& id,
+ FrameSkippedReason skip_reason) {
+ compositor_frame_reporting_controller_->DidNotProduceFrame(id, skip_reason);
}
void CompositorTimingHistory::DidReceiveCompositorFrameAck() {
diff --git a/chromium/cc/metrics/compositor_timing_history.h b/chromium/cc/metrics/compositor_timing_history.h
index 9ec86a2328c..1d265a8419a 100644
--- a/chromium/cc/metrics/compositor_timing_history.h
+++ b/chromium/cc/metrics/compositor_timing_history.h
@@ -11,6 +11,7 @@
#include "cc/base/rolling_time_delta_history.h"
#include "cc/cc_export.h"
#include "cc/metrics/event_metrics.h"
+#include "cc/scheduler/scheduler.h"
#include "cc/tiles/tile_priority.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -100,7 +101,8 @@ class CC_EXPORT CompositorTimingHistory {
const viz::BeginFrameId& current_frame_id,
const viz::BeginFrameId& last_activated_frame_id,
EventMetricsSet events_metrics);
- void DidNotProduceFrame(const viz::BeginFrameId& id);
+ void DidNotProduceFrame(const viz::BeginFrameId& id,
+ FrameSkippedReason skip_reason);
void DidReceiveCompositorFrameAck();
void DidPresentCompositorFrame(uint32_t frame_token,
const viz::FrameTimingDetails& details);
diff --git a/chromium/cc/metrics/event_metrics.cc b/chromium/cc/metrics/event_metrics.cc
index f7f03b91810..326eaee70a1 100644
--- a/chromium/cc/metrics/event_metrics.cc
+++ b/chromium/cc/metrics/event_metrics.cc
@@ -4,24 +4,18 @@
#include "cc/metrics/event_metrics.h"
-#include <tuple>
-
+#include "base/check.h"
+#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
#include "base/stl_util.h"
namespace cc {
-EventMetrics::EventMetrics(ui::EventType type,
- base::TimeTicks time_stamp,
- base::Optional<ScrollInputType> scroll_input_type)
- : type_(type),
- time_stamp_(time_stamp),
- scroll_input_type_(scroll_input_type) {}
-
-EventMetrics::EventMetrics(const EventMetrics&) = default;
-EventMetrics& EventMetrics::operator=(const EventMetrics&) = default;
-
-bool EventMetrics::IsWhitelisted() const {
- switch (type_) {
+std::unique_ptr<EventMetrics> EventMetrics::Create(
+ ui::EventType type,
+ base::TimeTicks time_stamp,
+ base::Optional<ui::ScrollInputType> scroll_input_type) {
+ switch (type) {
case ui::ET_MOUSE_PRESSED:
case ui::ET_MOUSE_RELEASED:
case ui::ET_MOUSEWHEEL:
@@ -33,16 +27,25 @@ bool EventMetrics::IsWhitelisted() const {
case ui::ET_GESTURE_SCROLL_BEGIN:
case ui::ET_GESTURE_SCROLL_UPDATE:
case ui::ET_GESTURE_SCROLL_END:
- return true;
+ return base::WrapUnique(
+ new EventMetrics(type, time_stamp, scroll_input_type));
default:
- return false;
+ return nullptr;
}
}
-const char* EventMetrics::GetTypeName() const {
- DCHECK(IsWhitelisted()) << "Event type is not whitelisted for event metrics: "
- << type_;
+EventMetrics::EventMetrics(
+ ui::EventType type,
+ base::TimeTicks time_stamp,
+ base::Optional<ui::ScrollInputType> scroll_input_type)
+ : type_(type),
+ time_stamp_(time_stamp),
+ scroll_input_type_(scroll_input_type) {}
+EventMetrics::EventMetrics(const EventMetrics&) = default;
+EventMetrics& EventMetrics::operator=(const EventMetrics&) = default;
+
+const char* EventMetrics::GetTypeName() const {
switch (type_) {
case ui::ET_MOUSE_PRESSED:
return "MousePressed";
@@ -51,6 +54,9 @@ const char* EventMetrics::GetTypeName() const {
case ui::ET_MOUSEWHEEL:
return "MouseWheel";
case ui::ET_KEY_PRESSED:
+ // TODO(crbug/1071645): Currently, all ET_KEY_PRESSED events are reported
+ // under EventLatency.KeyPressed histogram. This includes both key-down
+ // and key-char events. Consider reporting them separately.
return "KeyPressed";
case ui::ET_KEY_RELEASED:
return "KeyReleased";
@@ -73,18 +79,16 @@ const char* EventMetrics::GetTypeName() const {
}
const char* EventMetrics::GetScrollTypeName() const {
- DCHECK(IsWhitelisted()) << "Event type is not whitelisted for event metrics: "
- << type_;
DCHECK(scroll_input_type_) << "Event is not a scroll event";
switch (*scroll_input_type_) {
- case ScrollInputType::kTouchscreen:
+ case ui::ScrollInputType::kTouchscreen:
return "Touchscreen";
- case ScrollInputType::kWheel:
+ case ui::ScrollInputType::kWheel:
return "Wheel";
- case ScrollInputType::kAutoscroll:
+ case ui::ScrollInputType::kAutoscroll:
return "Autoscroll";
- case ScrollInputType::kScrollbar:
+ case ui::ScrollInputType::kScrollbar:
return "Scrollbar";
}
}
diff --git a/chromium/cc/metrics/event_metrics.h b/chromium/cc/metrics/event_metrics.h
index 3f6b9d3cb20..8de2fc58be9 100644
--- a/chromium/cc/metrics/event_metrics.h
+++ b/chromium/cc/metrics/event_metrics.h
@@ -5,11 +5,13 @@
#ifndef CC_METRICS_EVENT_METRICS_H_
#define CC_METRICS_EVENT_METRICS_H_
+#include <memory>
+
#include "base/optional.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
-#include "cc/input/scroll_input_type.h"
#include "ui/events/types/event_type.h"
+#include "ui/events/types/scroll_input_type.h"
namespace cc {
@@ -17,17 +19,16 @@ namespace cc {
// latency metrics.
class CC_EXPORT EventMetrics {
public:
- EventMetrics(ui::EventType type,
- base::TimeTicks time_stamp,
- base::Optional<ScrollInputType> scroll_input_type);
+ // Returns a new instance if |type| is a whitelisted event type. Otherwise,
+ // returns nullptr.
+ static std::unique_ptr<EventMetrics> Create(
+ ui::EventType type,
+ base::TimeTicks time_stamp,
+ base::Optional<ui::ScrollInputType> scroll_input_type);
EventMetrics(const EventMetrics&);
EventMetrics& operator=(const EventMetrics&);
- // Determines if the event is whitelisted for event latency reporting. If not,
- // this event is ignored in histogram reporting.
- bool IsWhitelisted() const;
-
// Returns a string representing event type. Should only be called for
// whitelisted event types.
const char* GetTypeName() const;
@@ -40,7 +41,7 @@ class CC_EXPORT EventMetrics {
base::TimeTicks time_stamp() const { return time_stamp_; }
- const base::Optional<ScrollInputType>& scroll_input_type() const {
+ const base::Optional<ui::ScrollInputType>& scroll_input_type() const {
return scroll_input_type_;
}
@@ -48,12 +49,16 @@ class CC_EXPORT EventMetrics {
bool operator==(const EventMetrics& other) const;
private:
+ EventMetrics(ui::EventType type,
+ base::TimeTicks time_stamp,
+ base::Optional<ui::ScrollInputType> scroll_input_type);
+
ui::EventType type_;
base::TimeTicks time_stamp_;
// Only available for scroll events and represents the type of input device
// for the event.
- base::Optional<ScrollInputType> scroll_input_type_;
+ base::Optional<ui::ScrollInputType> scroll_input_type_;
};
// Struct storing event metrics from both main and impl threads.
diff --git a/chromium/cc/metrics/events_metrics_manager.cc b/chromium/cc/metrics/events_metrics_manager.cc
index cd008372af9..b4481d32b20 100644
--- a/chromium/cc/metrics/events_metrics_manager.cc
+++ b/chromium/cc/metrics/events_metrics_manager.cc
@@ -4,9 +4,11 @@
#include "cc/metrics/events_metrics_manager.h"
-#include <memory>
#include <utility>
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
#include "base/stl_util.h"
namespace cc {
@@ -14,15 +16,11 @@ namespace {
class ScopedMonitorImpl : public EventsMetricsManager::ScopedMonitor {
public:
- explicit ScopedMonitorImpl(base::Optional<EventMetrics>* active_event)
- : active_event_(active_event) {
- DCHECK(active_event_);
- }
-
- ~ScopedMonitorImpl() override { *active_event_ = base::nullopt; }
+ explicit ScopedMonitorImpl(base::OnceClosure done_callback)
+ : closure_runner_(std::move(done_callback)) {}
private:
- base::Optional<EventMetrics>* active_event_;
+ base::ScopedClosureRunner closure_runner_;
};
} // namespace
@@ -33,18 +31,20 @@ EventsMetricsManager::EventsMetricsManager() = default;
EventsMetricsManager::~EventsMetricsManager() = default;
std::unique_ptr<EventsMetricsManager::ScopedMonitor>
-EventsMetricsManager::GetScopedMonitor(const EventMetrics& event_metrics) {
+EventsMetricsManager::GetScopedMonitor(
+ std::unique_ptr<EventMetrics> event_metrics) {
DCHECK(!active_event_);
- if (!event_metrics.IsWhitelisted())
+ if (!event_metrics)
return nullptr;
- active_event_ = event_metrics;
- return std::make_unique<ScopedMonitorImpl>(&active_event_);
+ active_event_ = std::move(event_metrics);
+ return std::make_unique<ScopedMonitorImpl>(base::BindOnce(
+ &EventsMetricsManager::OnScopedMonitorEnded, weak_factory_.GetWeakPtr()));
}
void EventsMetricsManager::SaveActiveEventMetrics() {
if (active_event_) {
saved_events_.push_back(*active_event_);
- active_event_ = base::nullopt;
+ active_event_.reset();
}
}
@@ -54,4 +54,8 @@ std::vector<EventMetrics> EventsMetricsManager::TakeSavedEventsMetrics() {
return result;
}
+void EventsMetricsManager::OnScopedMonitorEnded() {
+ active_event_.reset();
+}
+
} // namespace cc
diff --git a/chromium/cc/metrics/events_metrics_manager.h b/chromium/cc/metrics/events_metrics_manager.h
index 8dd3bbfb9bd..6c44f62d212 100644
--- a/chromium/cc/metrics/events_metrics_manager.h
+++ b/chromium/cc/metrics/events_metrics_manager.h
@@ -8,7 +8,7 @@
#include <memory>
#include <vector>
-#include "base/optional.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "cc/metrics/event_metrics.h"
@@ -40,9 +40,10 @@ class CC_EXPORT EventsMetricsManager {
EventsMetricsManager& operator=(const EventsMetricsManager&) = delete;
// Called by clients when they start handling an event. Destruction of the
- // scoped monitor indicates the end of event handling.
+ // scoped monitor indicates the end of event handling. |event_metrics| is
+ // allowed to be nullptr in which case the return value would also be nullptr.
std::unique_ptr<ScopedMonitor> GetScopedMonitor(
- const EventMetrics& event_metrics);
+ std::unique_ptr<EventMetrics> event_metrics);
// Called by clients when a frame needs to be produced. If any scoped monitor
// is active at this time, its corresponding event metrics would be saved.
@@ -53,11 +54,15 @@ class CC_EXPORT EventsMetricsManager {
std::vector<EventMetrics> TakeSavedEventsMetrics();
private:
+ void OnScopedMonitorEnded();
+
// Current active EventMetrics, if any.
- base::Optional<EventMetrics> active_event_;
+ std::unique_ptr<EventMetrics> active_event_;
// List of saved event metrics.
std::vector<EventMetrics> saved_events_;
+
+ base::WeakPtrFactory<EventsMetricsManager> weak_factory_{this};
};
} // namespace cc
diff --git a/chromium/cc/metrics/events_metrics_manager_unittest.cc b/chromium/cc/metrics/events_metrics_manager_unittest.cc
index d2f38aa3abf..ba162cc3283 100644
--- a/chromium/cc/metrics/events_metrics_manager_unittest.cc
+++ b/chromium/cc/metrics/events_metrics_manager_unittest.cc
@@ -7,11 +7,11 @@
#include <utility>
#include <vector>
-#include "cc/input/scroll_input_type.h"
#include "cc/metrics/event_metrics.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/types/event_type.h"
+#include "ui/events/types/scroll_input_type.h"
namespace cc {
namespace {
@@ -39,42 +39,43 @@ TEST_F(EventsMetricsManagerTest, EventsMetricsSaved) {
kSaveOutsideScope,
};
- std::vector<std::pair<EventMetrics, Behavior>> events = {
+ std::pair<std::unique_ptr<EventMetrics>, Behavior> events[] = {
// A whitelisted event type for which SaveActiveEventMetrics() is not
// called.
- {{ui::ET_MOUSE_PRESSED, TimeAtMs(0), base::nullopt},
+ {EventMetrics::Create(ui::ET_MOUSE_PRESSED, TimeAtMs(0), base::nullopt),
Behavior::kDoNotSave},
// A whitelisted event type for which SaveActiveEventMetrics() is called
// inside its monitor scope.
- {{ui::ET_MOUSE_PRESSED, TimeAtMs(1), base::nullopt},
+ {EventMetrics::Create(ui::ET_MOUSE_PRESSED, TimeAtMs(1), base::nullopt),
Behavior::kSaveInsideScope},
// A whitelisted event type for which SaveActiveEventMetrics() is called
- // after its monitor scope is finished.
- {{ui::ET_MOUSE_PRESSED, TimeAtMs(2), base::nullopt},
+ // after
+ // its monitor scope is finished.
+ {EventMetrics::Create(ui::ET_MOUSE_PRESSED, TimeAtMs(2), base::nullopt),
Behavior::kSaveOutsideScope},
// A non-whitelisted event type for which SaveActiveEventMetrics() is
// called inside its monitor scope.
- {{ui::ET_MOUSE_MOVED, TimeAtMs(3), base::nullopt},
+ {EventMetrics::Create(ui::ET_MOUSE_MOVED, TimeAtMs(3), base::nullopt),
Behavior::kSaveInsideScope},
};
- EXPECT_TRUE(events[0].first.IsWhitelisted());
- EXPECT_TRUE(events[1].first.IsWhitelisted());
- EXPECT_TRUE(events[2].first.IsWhitelisted());
- EXPECT_FALSE(events[3].first.IsWhitelisted());
+ EXPECT_NE(events[0].first, nullptr);
+ EXPECT_NE(events[1].first, nullptr);
+ EXPECT_NE(events[2].first, nullptr);
+ EXPECT_EQ(events[3].first, nullptr);
// Out of the above events, only those with a whitelisted event type, for
// which SaveActiveEventMetrics() is called inside its monitor scope, are
// expected to be saved.
std::vector<EventMetrics> expected_saved_events = {
- events[1].first,
+ *events[1].first,
};
for (auto& event : events) {
{
- auto monitor = manager_.GetScopedMonitor(event.first);
+ auto monitor = manager_.GetScopedMonitor(std::move(event.first));
if (event.second == Behavior::kSaveInsideScope)
manager_.SaveActiveEventMetrics();
// Ending the scope destroys the |monitor|.
diff --git a/chromium/cc/metrics/frame_sequence_metrics.cc b/chromium/cc/metrics/frame_sequence_metrics.cc
new file mode 100644
index 00000000000..0cefe55fd51
--- /dev/null
+++ b/chromium/cc/metrics/frame_sequence_metrics.cc
@@ -0,0 +1,371 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/metrics/frame_sequence_metrics.h"
+
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/traced_value.h"
+#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/throughput_ukm_reporter.h"
+
+namespace cc {
+
+namespace {
+
+// Avoid reporting any throughput metric for sequences that do not have a
+// sufficient number of frames.
+constexpr int kMinFramesForThroughputMetric = 100;
+
+constexpr int kBuiltinSequenceNum =
+ static_cast<int>(FrameSequenceTrackerType::kMaxType) + 1;
+constexpr int kMaximumHistogramIndex = 3 * kBuiltinSequenceNum;
+
+int GetIndexForMetric(FrameSequenceMetrics::ThreadType thread_type,
+ FrameSequenceTrackerType type) {
+ if (thread_type == FrameSequenceMetrics::ThreadType::kMain)
+ return static_cast<int>(type);
+ if (thread_type == FrameSequenceMetrics::ThreadType::kCompositor)
+ return static_cast<int>(type) + kBuiltinSequenceNum;
+ return static_cast<int>(type) + 2 * kBuiltinSequenceNum;
+}
+
+std::string GetCheckerboardingHistogramName(FrameSequenceTrackerType type) {
+ return base::StrCat(
+ {"Graphics.Smoothness.Checkerboarding.",
+ FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type)});
+}
+
+std::string GetThroughputHistogramName(FrameSequenceTrackerType type,
+ const char* thread_name) {
+ return base::StrCat(
+ {"Graphics.Smoothness.PercentDroppedFrames.", thread_name, ".",
+ FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type)});
+}
+
+std::string GetFrameSequenceLengthHistogramName(FrameSequenceTrackerType type) {
+ return base::StrCat(
+ {"Graphics.Smoothness.FrameSequenceLength.",
+ FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type)});
+}
+
+bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type,
+ FrameSequenceMetrics::ThreadType thread_type) {
+ if (sequence_type == FrameSequenceTrackerType::kCompositorAnimation)
+ return thread_type == FrameSequenceMetrics::ThreadType::kCompositor;
+
+ if (sequence_type == FrameSequenceTrackerType::kMainThreadAnimation ||
+ sequence_type == FrameSequenceTrackerType::kRAF)
+ return thread_type == FrameSequenceMetrics::ThreadType::kMain;
+
+ return false;
+}
+
+bool ShouldReportForInteraction(FrameSequenceMetrics* metrics,
+ FrameSequenceMetrics::ThreadType thread_type) {
+ const auto sequence_type = metrics->type();
+
+ // For touch/wheel scroll, the slower thread is the one we want to report. For
+ // pinch-zoom, it's the compositor-thread.
+ if (sequence_type == FrameSequenceTrackerType::kTouchScroll ||
+ sequence_type == FrameSequenceTrackerType::kWheelScroll)
+ return thread_type == metrics->GetEffectiveThread();
+
+ if (sequence_type == FrameSequenceTrackerType::kPinchZoom)
+ return thread_type == FrameSequenceMetrics::ThreadType::kCompositor;
+
+ return false;
+}
+
+bool IsInteractionType(FrameSequenceTrackerType sequence_type) {
+ return sequence_type == FrameSequenceTrackerType::kTouchScroll ||
+ sequence_type == FrameSequenceTrackerType::kWheelScroll ||
+ sequence_type == FrameSequenceTrackerType::kPinchZoom;
+}
+
+} // namespace
+
+FrameSequenceMetrics::FrameSequenceMetrics(FrameSequenceTrackerType type,
+ ThroughputUkmReporter* ukm_reporter)
+ : type_(type), throughput_ukm_reporter_(ukm_reporter) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(this), "name",
+ FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type_));
+}
+
+FrameSequenceMetrics::~FrameSequenceMetrics() {
+ if (HasDataLeftForReporting()) {
+ ReportMetrics();
+ }
+}
+
+void FrameSequenceMetrics::SetScrollingThread(ThreadType scrolling_thread) {
+ DCHECK(type_ == FrameSequenceTrackerType::kTouchScroll ||
+ type_ == FrameSequenceTrackerType::kWheelScroll ||
+ type_ == FrameSequenceTrackerType::kScrollbarScroll);
+ DCHECK_EQ(scrolling_thread_, ThreadType::kUnknown);
+ scrolling_thread_ = scrolling_thread;
+}
+
+void FrameSequenceMetrics::SetCustomReporter(CustomReporter custom_reporter) {
+ DCHECK_EQ(FrameSequenceTrackerType::kCustom, type_);
+ custom_reporter_ = std::move(custom_reporter);
+}
+
+FrameSequenceMetrics::ThreadType FrameSequenceMetrics::GetEffectiveThread()
+ const {
+ switch (type_) {
+ case FrameSequenceTrackerType::kCompositorAnimation:
+ case FrameSequenceTrackerType::kPinchZoom:
+ return ThreadType::kCompositor;
+
+ case FrameSequenceTrackerType::kMainThreadAnimation:
+ case FrameSequenceTrackerType::kRAF:
+ case FrameSequenceTrackerType::kVideo:
+ return ThreadType::kMain;
+
+ case FrameSequenceTrackerType::kTouchScroll:
+ case FrameSequenceTrackerType::kScrollbarScroll:
+ case FrameSequenceTrackerType::kWheelScroll:
+ return scrolling_thread_;
+
+ case FrameSequenceTrackerType::kUniversal:
+ return ThreadType::kSlower;
+
+ case FrameSequenceTrackerType::kCustom:
+ case FrameSequenceTrackerType::kMaxType:
+ NOTREACHED();
+ }
+ return ThreadType::kUnknown;
+}
+
+void FrameSequenceMetrics::Merge(
+ std::unique_ptr<FrameSequenceMetrics> metrics) {
+ DCHECK_EQ(type_, metrics->type_);
+ DCHECK_EQ(GetEffectiveThread(), metrics->GetEffectiveThread());
+ impl_throughput_.Merge(metrics->impl_throughput_);
+ main_throughput_.Merge(metrics->main_throughput_);
+ aggregated_throughput_.Merge(metrics->aggregated_throughput_);
+ frames_checkerboarded_ += metrics->frames_checkerboarded_;
+
+ // Reset the state of |metrics| before destroying it, so that it doesn't end
+ // up reporting the metrics.
+ metrics->impl_throughput_ = {};
+ metrics->main_throughput_ = {};
+ metrics->aggregated_throughput_ = {};
+ metrics->frames_checkerboarded_ = 0;
+}
+
+bool FrameSequenceMetrics::HasEnoughDataForReporting() const {
+ return impl_throughput_.frames_expected >= kMinFramesForThroughputMetric ||
+ main_throughput_.frames_expected >= kMinFramesForThroughputMetric;
+}
+
+bool FrameSequenceMetrics::HasDataLeftForReporting() const {
+ return impl_throughput_.frames_expected > 0 ||
+ main_throughput_.frames_expected > 0;
+}
+
+void FrameSequenceMetrics::ComputeAggregatedThroughput() {
+ // Whenever we are expecting and producing main frames, we are expecting and
+ // producing impl frames as well. As an example, if we expect one main frame
+ // to be produced, and when that main frame is presented, we are expecting 3
+ // impl frames, then the number of expected frames is 3 for the aggregated
+ // throughput.
+ aggregated_throughput_.frames_expected = impl_throughput_.frames_expected;
+ DCHECK_LE(aggregated_throughput_.frames_produced,
+ aggregated_throughput_.frames_expected);
+}
+
+void FrameSequenceMetrics::ReportMetrics() {
+ DCHECK_LE(impl_throughput_.frames_produced, impl_throughput_.frames_expected);
+ DCHECK_LE(main_throughput_.frames_produced, main_throughput_.frames_expected);
+ TRACE_EVENT_NESTABLE_ASYNC_END2(
+ "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(this), "args",
+ ThroughputData::ToTracedValue(impl_throughput_, main_throughput_),
+ "checkerboard", frames_checkerboarded_);
+
+ if (type_ == FrameSequenceTrackerType::kCustom) {
+ DCHECK(!custom_reporter_.is_null());
+ std::move(custom_reporter_).Run(std::move(main_throughput_));
+
+ main_throughput_ = {};
+ impl_throughput_ = {};
+ aggregated_throughput_ = {};
+ frames_checkerboarded_ = 0;
+ return;
+ }
+
+ ComputeAggregatedThroughput();
+
+ // Report the throughput metrics.
+ base::Optional<int> impl_throughput_percent = ThroughputData::ReportHistogram(
+ this, ThreadType::kCompositor,
+ GetIndexForMetric(FrameSequenceMetrics::ThreadType::kCompositor, type_),
+ impl_throughput_);
+ base::Optional<int> main_throughput_percent = ThroughputData::ReportHistogram(
+ this, ThreadType::kMain,
+ GetIndexForMetric(FrameSequenceMetrics::ThreadType::kMain, type_),
+ main_throughput_);
+
+ // Report for the 'slower thread' for the metrics where it makes sense.
+ bool should_report_slower_thread =
+ IsInteractionType(type_) || type_ == FrameSequenceTrackerType::kUniversal;
+ base::Optional<int> aggregated_throughput_percent;
+ if (should_report_slower_thread) {
+ aggregated_throughput_percent = ThroughputData::ReportHistogram(
+ this, ThreadType::kSlower,
+ GetIndexForMetric(FrameSequenceMetrics::ThreadType::kSlower, type_),
+ aggregated_throughput_);
+ if (aggregated_throughput_percent.has_value() && throughput_ukm_reporter_) {
+ throughput_ukm_reporter_->ReportThroughputUkm(
+ aggregated_throughput_percent, impl_throughput_percent,
+ main_throughput_percent, type_);
+ }
+ }
+
+ // Report for the 'scrolling thread' for the scrolling interactions.
+ if (scrolling_thread_ != ThreadType::kUnknown) {
+ base::Optional<int> scrolling_thread_throughput;
+ switch (scrolling_thread_) {
+ case ThreadType::kCompositor:
+ scrolling_thread_throughput = impl_throughput_percent;
+ break;
+ case ThreadType::kMain:
+ scrolling_thread_throughput = main_throughput_percent;
+ break;
+ case ThreadType::kSlower:
+ case ThreadType::kUnknown:
+ NOTREACHED();
+ break;
+ }
+ if (scrolling_thread_throughput.has_value()) {
+ // It's OK to use the UMA histogram in the following code while still
+ // using |GetThroughputHistogramName()| to get the name of the metric,
+ // since the input-params to the function never change at runtime.
+ if (type_ == FrameSequenceTrackerType::kWheelScroll) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ GetThroughputHistogramName(FrameSequenceTrackerType::kWheelScroll,
+ "ScrollingThread"),
+ scrolling_thread_throughput.value());
+ } else if (type_ == FrameSequenceTrackerType::kTouchScroll) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ GetThroughputHistogramName(FrameSequenceTrackerType::kTouchScroll,
+ "ScrollingThread"),
+ scrolling_thread_throughput.value());
+ } else {
+ DCHECK_EQ(type_, FrameSequenceTrackerType::kScrollbarScroll);
+ UMA_HISTOGRAM_PERCENTAGE(
+ GetThroughputHistogramName(
+ FrameSequenceTrackerType::kScrollbarScroll, "ScrollingThread"),
+ scrolling_thread_throughput.value());
+ }
+ }
+ }
+
+ // Report the checkerboarding metrics.
+ if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) {
+ const int checkerboarding_percent = static_cast<int>(
+ 100 * frames_checkerboarded_ / impl_throughput_.frames_expected);
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ GetCheckerboardingHistogramName(type_), static_cast<int>(type_),
+ static_cast<int>(FrameSequenceTrackerType::kMaxType),
+ Add(checkerboarding_percent),
+ base::LinearHistogram::FactoryGet(
+ GetCheckerboardingHistogramName(type_), 1, 100, 101,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
+ frames_checkerboarded_ = 0;
+ }
+
+ // Reset the metrics that reach reporting threshold.
+ if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) {
+ impl_throughput_ = {};
+ aggregated_throughput_ = {};
+ }
+ if (main_throughput_.frames_expected >= kMinFramesForThroughputMetric)
+ main_throughput_ = {};
+}
+
+base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
+ FrameSequenceMetrics* metrics,
+ ThreadType thread_type,
+ int metric_index,
+ const ThroughputData& data) {
+ const auto sequence_type = metrics->type();
+ DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType);
+
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ GetFrameSequenceLengthHistogramName(sequence_type),
+ static_cast<int>(sequence_type),
+ static_cast<int>(FrameSequenceTrackerType::kMaxType),
+ Add(data.frames_expected),
+ base::Histogram::FactoryGet(
+ GetFrameSequenceLengthHistogramName(sequence_type), 1, 1000, 50,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
+
+ if (data.frames_expected < kMinFramesForThroughputMetric)
+ return base::nullopt;
+
+ // Throughput means the percent of frames that was expected to show on the
+ // screen but didn't. In other words, the lower the throughput is, the
+ // smoother user experience.
+ const int percent =
+ std::ceil(100 * (data.frames_expected - data.frames_produced) /
+ static_cast<double>(data.frames_expected));
+
+ const bool is_animation =
+ ShouldReportForAnimation(sequence_type, thread_type);
+ const bool is_interaction = ShouldReportForInteraction(metrics, thread_type);
+
+ ThroughputUkmReporter* const ukm_reporter = metrics->ukm_reporter();
+
+ if (is_animation) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Graphics.Smoothness.PercentDroppedFrames.AllAnimations", percent);
+ if (ukm_reporter) {
+ ukm_reporter->ReportAggregateThroughput(AggregationType::kAllAnimations,
+ percent);
+ }
+ }
+
+ if (is_interaction) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Graphics.Smoothness.PercentDroppedFrames.AllInteractions", percent);
+ if (ukm_reporter) {
+ ukm_reporter->ReportAggregateThroughput(AggregationType::kAllInteractions,
+ percent);
+ }
+ }
+
+ if (is_animation || is_interaction) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Graphics.Smoothness.PercentDroppedFrames.AllSequences", percent);
+ if (ukm_reporter) {
+ ukm_reporter->ReportAggregateThroughput(AggregationType::kAllSequences,
+ percent);
+ }
+ }
+
+ if (!is_animation && !IsInteractionType(sequence_type) &&
+ sequence_type != FrameSequenceTrackerType::kUniversal &&
+ sequence_type != FrameSequenceTrackerType::kVideo) {
+ return base::nullopt;
+ }
+
+ const char* thread_name =
+ thread_type == ThreadType::kCompositor
+ ? "CompositorThread"
+ : thread_type == ThreadType::kMain ? "MainThread" : "SlowerThread";
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ GetThroughputHistogramName(sequence_type, thread_name), metric_index,
+ kMaximumHistogramIndex, Add(percent),
+ base::LinearHistogram::FactoryGet(
+ GetThroughputHistogramName(sequence_type, thread_name), 1, 100, 101,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
+ return percent;
+}
+
+} // namespace cc
diff --git a/chromium/cc/metrics/frame_sequence_metrics.h b/chromium/cc/metrics/frame_sequence_metrics.h
new file mode 100644
index 00000000000..0417899c3a9
--- /dev/null
+++ b/chromium/cc/metrics/frame_sequence_metrics.h
@@ -0,0 +1,140 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_METRICS_FRAME_SEQUENCE_METRICS_H_
+#define CC_METRICS_FRAME_SEQUENCE_METRICS_H_
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "base/trace_event/traced_value.h"
+#include "cc/cc_export.h"
+
+namespace cc {
+class ThroughputUkmReporter;
+
+enum class FrameSequenceTrackerType {
+ // Used as an enum for metrics. DO NOT reorder or delete values. Rather,
+ // add them at the end and increment kMaxType.
+ kCompositorAnimation = 0,
+ kMainThreadAnimation = 1,
+ kPinchZoom = 2,
+ kRAF = 3,
+ kTouchScroll = 4,
+ kUniversal = 5,
+ kVideo = 6,
+ kWheelScroll = 7,
+ kScrollbarScroll = 8,
+ kCustom = 9, // Note that the metrics for kCustom are not reported on UMA,
+ // and instead are dispatched back to the LayerTreeHostClient.
+ kMaxType
+};
+
+class CC_EXPORT FrameSequenceMetrics {
+ public:
+ FrameSequenceMetrics(FrameSequenceTrackerType type,
+ ThroughputUkmReporter* ukm_reporter);
+ ~FrameSequenceMetrics();
+
+ FrameSequenceMetrics(const FrameSequenceMetrics&) = delete;
+ FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete;
+
+ enum class ThreadType { kMain, kCompositor, kSlower, kUnknown };
+
+ struct ThroughputData {
+ static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue(
+ const ThroughputData& impl,
+ const ThroughputData& main);
+
+ // Returns the throughput in percent, a return value of base::nullopt
+ // indicates that no throughput metric is reported.
+ static base::Optional<int> ReportHistogram(FrameSequenceMetrics* metrics,
+ ThreadType thread_type,
+ int metric_index,
+ const ThroughputData& data);
+
+ void Merge(const ThroughputData& data) {
+ frames_expected += data.frames_expected;
+ frames_produced += data.frames_produced;
+#if DCHECK_IS_ON()
+ frames_processed += data.frames_processed;
+ frames_received += data.frames_received;
+#endif
+ }
+
+ // Tracks the number of frames that were expected to be shown during this
+ // frame-sequence.
+ uint32_t frames_expected = 0;
+
+ // Tracks the number of frames that were actually presented to the user
+ // during this frame-sequence.
+ uint32_t frames_produced = 0;
+
+#if DCHECK_IS_ON()
+ // Tracks the number of frames that is either submitted or reported as no
+ // damage.
+ uint32_t frames_processed = 0;
+
+ // Tracks the number of begin-frames that are received.
+ uint32_t frames_received = 0;
+#endif
+ };
+
+ void SetScrollingThread(ThreadType thread);
+
+ using CustomReporter =
+ base::OnceCallback<void(ThroughputData throughput_data)>;
+ // Sets reporter callback for kCustom typed sequence.
+ void SetCustomReporter(CustomReporter custom_reporter);
+
+ // Returns the 'effective thread' for the metrics (i.e. the thread most
+ // relevant for this metric).
+ ThreadType GetEffectiveThread() const;
+
+ void Merge(std::unique_ptr<FrameSequenceMetrics> metrics);
+ bool HasEnoughDataForReporting() const;
+ bool HasDataLeftForReporting() const;
+ // Report related metrics: throughput, checkboarding...
+ void ReportMetrics();
+ void ComputeAggregatedThroughputForTesting() {
+ ComputeAggregatedThroughput();
+ }
+
+ ThroughputData& impl_throughput() { return impl_throughput_; }
+ ThroughputData& main_throughput() { return main_throughput_; }
+ ThroughputData& aggregated_throughput() { return aggregated_throughput_; }
+ void add_checkerboarded_frames(int64_t frames) {
+ frames_checkerboarded_ += frames;
+ }
+ uint32_t frames_checkerboarded() const { return frames_checkerboarded_; }
+
+ FrameSequenceTrackerType type() const { return type_; }
+ ThroughputUkmReporter* ukm_reporter() const {
+ return throughput_ukm_reporter_;
+ }
+
+ private:
+ void ComputeAggregatedThroughput();
+ const FrameSequenceTrackerType type_;
+
+ // Pointer to the reporter owned by the FrameSequenceTrackerCollection.
+ ThroughputUkmReporter* const throughput_ukm_reporter_;
+
+ ThroughputData impl_throughput_;
+ ThroughputData main_throughput_;
+ // The aggregated throughput for the main/compositor thread.
+ ThroughputData aggregated_throughput_;
+
+ ThreadType scrolling_thread_ = ThreadType::kUnknown;
+
+ // Tracks the number of produced frames that had some amount of
+ // checkerboarding, and how many frames showed such checkerboarded frames.
+ uint32_t frames_checkerboarded_ = 0;
+
+ // Callback invoked to report metrics for kCustom typed sequence.
+ CustomReporter custom_reporter_;
+};
+
+} // namespace cc
+
+#endif // CC_METRICS_FRAME_SEQUENCE_METRICS_H_
diff --git a/chromium/cc/metrics/frame_sequence_metrics_unittest.cc b/chromium/cc/metrics/frame_sequence_metrics_unittest.cc
index b52a81020ae..ae43da19a24 100644
--- a/chromium/cc/metrics/frame_sequence_metrics_unittest.cc
+++ b/chromium/cc/metrics/frame_sequence_metrics_unittest.cc
@@ -23,6 +23,18 @@ TEST(FrameSequenceMetricsTest, AggregatedThroughput) {
EXPECT_EQ(first.aggregated_throughput().frames_expected, 200u);
}
+TEST(FrameSequenceMetricsTest, AggregatedThroughputClearedAfterReport) {
+ FrameSequenceMetrics first(FrameSequenceTrackerType::kCompositorAnimation,
+ nullptr);
+ first.impl_throughput().frames_expected = 200u;
+ first.impl_throughput().frames_produced = 190u;
+ first.aggregated_throughput().frames_produced = 150u;
+
+ first.ReportMetrics();
+ EXPECT_EQ(first.aggregated_throughput().frames_expected, 0u);
+ EXPECT_EQ(first.aggregated_throughput().frames_produced, 0u);
+}
+
TEST(FrameSequenceMetricsTest, MergeMetrics) {
// Create a metric with only a small number of frames. It shouldn't report any
// metrics.
diff --git a/chromium/cc/metrics/frame_sequence_tracker.cc b/chromium/cc/metrics/frame_sequence_tracker.cc
index 0b1dbc1f38e..f1a1fd9b995 100644
--- a/chromium/cc/metrics/frame_sequence_tracker.cc
+++ b/chromium/cc/metrics/frame_sequence_tracker.cc
@@ -4,16 +4,11 @@
#include "cc/metrics/frame_sequence_tracker.h"
-#include "base/memory/ptr_util.h"
+#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
-#include "base/strings/strcat.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
-#include "cc/metrics/compositor_frame_reporting_controller.h"
-#include "cc/metrics/throughput_ukm_reporter.h"
-#include "cc/trees/ukm_manager.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "ui/gfx/presentation_feedback.h"
@@ -22,7 +17,7 @@
#if DCHECK_IS_ON()
#define TRACKER_TRACE_STREAM frame_sequence_trace_
#define TRACKER_DCHECK_MSG \
- " in " << GetFrameSequenceTrackerTypeName(this->type_) \
+ " in " << GetFrameSequenceTrackerTypeName(this->type()) \
<< " tracker: " << frame_sequence_trace_.str() << " (" \
<< frame_sequence_trace_.str().size() << ")";
#else
@@ -32,6 +27,10 @@
namespace cc {
+// In the |TRACKER_TRACE_STREAM|, we mod the numbers such as frame sequence
+// number, or frame token, such that the debug string is not too long.
+constexpr int kDebugStrMod = 1000;
+
const char* FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
FrameSequenceTrackerType type) {
switch (type) {
@@ -60,574 +59,27 @@ const char* FrameSequenceTracker::GetFrameSequenceTrackerTypeName(
}
}
-namespace {
-
-// Avoid reporting any throughput metric for sequences that do not have a
-// sufficient number of frames.
-constexpr int kMinFramesForThroughputMetric = 100;
-
-constexpr int kBuiltinSequenceNum =
- static_cast<int>(FrameSequenceTrackerType::kMaxType) + 1;
-constexpr int kMaximumHistogramIndex = 3 * kBuiltinSequenceNum;
-
-int GetIndexForMetric(FrameSequenceMetrics::ThreadType thread_type,
- FrameSequenceTrackerType type) {
- if (thread_type == FrameSequenceMetrics::ThreadType::kMain)
- return static_cast<int>(type);
- if (thread_type == FrameSequenceMetrics::ThreadType::kCompositor)
- return static_cast<int>(type) + kBuiltinSequenceNum;
- return static_cast<int>(type) + 2 * kBuiltinSequenceNum;
-}
-
-std::string GetCheckerboardingHistogramName(FrameSequenceTrackerType type) {
- return base::StrCat(
- {"Graphics.Smoothness.Checkerboarding.",
- FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type)});
-}
-
-std::string GetThroughputHistogramName(FrameSequenceTrackerType type,
- const char* thread_name) {
- return base::StrCat(
- {"Graphics.Smoothness.PercentDroppedFrames.", thread_name, ".",
- FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type)});
-}
-
-std::string GetFrameSequenceLengthHistogramName(FrameSequenceTrackerType type) {
- return base::StrCat(
- {"Graphics.Smoothness.FrameSequenceLength.",
- FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type)});
-}
-
-bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type,
- FrameSequenceMetrics::ThreadType thread_type) {
- if (sequence_type == FrameSequenceTrackerType::kCompositorAnimation)
- return thread_type == FrameSequenceMetrics::ThreadType::kCompositor;
-
- if (sequence_type == FrameSequenceTrackerType::kMainThreadAnimation ||
- sequence_type == FrameSequenceTrackerType::kRAF)
- return thread_type == FrameSequenceMetrics::ThreadType::kMain;
-
- return false;
-}
-
-bool ShouldReportForInteraction(FrameSequenceMetrics* metrics,
- FrameSequenceMetrics::ThreadType thread_type) {
- const auto sequence_type = metrics->type();
-
- // For touch/wheel scroll, the slower thread is the one we want to report. For
- // pinch-zoom, it's the compositor-thread.
- if (sequence_type == FrameSequenceTrackerType::kTouchScroll ||
- sequence_type == FrameSequenceTrackerType::kWheelScroll)
- return thread_type == metrics->GetEffectiveThread();
-
- if (sequence_type == FrameSequenceTrackerType::kPinchZoom)
- return thread_type == FrameSequenceMetrics::ThreadType::kCompositor;
-
- return false;
-}
-
-bool IsInteractionType(FrameSequenceTrackerType sequence_type) {
- return sequence_type == FrameSequenceTrackerType::kTouchScroll ||
- sequence_type == FrameSequenceTrackerType::kWheelScroll ||
- sequence_type == FrameSequenceTrackerType::kPinchZoom;
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// FrameSequenceMetrics
-
-FrameSequenceMetrics::FrameSequenceMetrics(FrameSequenceTrackerType type,
- ThroughputUkmReporter* ukm_reporter)
- : type_(type),
- throughput_ukm_reporter_(ukm_reporter) {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
- "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(this), "name",
- FrameSequenceTracker::GetFrameSequenceTrackerTypeName(type_));
-}
-
-FrameSequenceMetrics::~FrameSequenceMetrics() {
- if (HasDataLeftForReporting()) {
- ReportMetrics();
- }
-}
-
-void FrameSequenceMetrics::SetScrollingThread(ThreadType scrolling_thread) {
- DCHECK(type_ == FrameSequenceTrackerType::kTouchScroll ||
- type_ == FrameSequenceTrackerType::kWheelScroll ||
- type_ == FrameSequenceTrackerType::kScrollbarScroll);
- DCHECK_EQ(scrolling_thread_, ThreadType::kUnknown);
- scrolling_thread_ = scrolling_thread;
-}
-
-FrameSequenceMetrics::ThreadType FrameSequenceMetrics::GetEffectiveThread()
- const {
- switch (type_) {
- case FrameSequenceTrackerType::kCompositorAnimation:
- case FrameSequenceTrackerType::kPinchZoom:
- return ThreadType::kCompositor;
-
- case FrameSequenceTrackerType::kMainThreadAnimation:
- case FrameSequenceTrackerType::kRAF:
- case FrameSequenceTrackerType::kVideo:
- return ThreadType::kMain;
-
- case FrameSequenceTrackerType::kTouchScroll:
- case FrameSequenceTrackerType::kScrollbarScroll:
- case FrameSequenceTrackerType::kWheelScroll:
- return scrolling_thread_;
-
- case FrameSequenceTrackerType::kUniversal:
- return ThreadType::kSlower;
-
- case FrameSequenceTrackerType::kCustom:
- case FrameSequenceTrackerType::kMaxType:
- NOTREACHED();
- }
- return ThreadType::kUnknown;
-}
-
-void FrameSequenceMetrics::Merge(
- std::unique_ptr<FrameSequenceMetrics> metrics) {
- DCHECK_EQ(type_, metrics->type_);
- DCHECK_EQ(GetEffectiveThread(), metrics->GetEffectiveThread());
- impl_throughput_.Merge(metrics->impl_throughput_);
- main_throughput_.Merge(metrics->main_throughput_);
- aggregated_throughput_.Merge(metrics->aggregated_throughput_);
- frames_checkerboarded_ += metrics->frames_checkerboarded_;
-
- // Reset the state of |metrics| before destroying it, so that it doesn't end
- // up reporting the metrics.
- metrics->impl_throughput_ = {};
- metrics->main_throughput_ = {};
- metrics->aggregated_throughput_ = {};
- metrics->frames_checkerboarded_ = 0;
-}
-
-bool FrameSequenceMetrics::HasEnoughDataForReporting() const {
- return impl_throughput_.frames_expected >= kMinFramesForThroughputMetric ||
- main_throughput_.frames_expected >= kMinFramesForThroughputMetric;
-}
-
-bool FrameSequenceMetrics::HasDataLeftForReporting() const {
- return impl_throughput_.frames_expected > 0 ||
- main_throughput_.frames_expected > 0;
-}
-
-void FrameSequenceMetrics::ComputeAggregatedThroughput() {
- // Whenever we are expecting and producing main frames, we are expecting and
- // producing impl frames as well. As an example, if we expect one main frame
- // to be produced, and when that main frame is presented, we are expecting 3
- // impl frames, then the number of expected frames is 3 for the aggregated
- // throughput.
- aggregated_throughput_.frames_expected = impl_throughput_.frames_expected;
- DCHECK_LE(aggregated_throughput_.frames_produced,
- aggregated_throughput_.frames_produced);
-}
-
-void FrameSequenceMetrics::ReportMetrics() {
- DCHECK_LE(impl_throughput_.frames_produced, impl_throughput_.frames_expected);
- DCHECK_LE(main_throughput_.frames_produced, main_throughput_.frames_expected);
- TRACE_EVENT_NESTABLE_ASYNC_END2(
- "cc,benchmark", "FrameSequenceTracker", TRACE_ID_LOCAL(this), "args",
- ThroughputData::ToTracedValue(impl_throughput_, main_throughput_),
- "checkerboard", frames_checkerboarded_);
-
- // Data for kCustom typed tracker is handled by caller instead being
- // reported here.
- if (type_ == FrameSequenceTrackerType::kCustom)
- return;
-
- ComputeAggregatedThroughput();
-
- // Report the throughput metrics.
- base::Optional<int> impl_throughput_percent = ThroughputData::ReportHistogram(
- this, ThreadType::kCompositor,
- GetIndexForMetric(FrameSequenceMetrics::ThreadType::kCompositor, type_),
- impl_throughput_);
- base::Optional<int> main_throughput_percent = ThroughputData::ReportHistogram(
- this, ThreadType::kMain,
- GetIndexForMetric(FrameSequenceMetrics::ThreadType::kMain, type_),
- main_throughput_);
-
- // Report for the 'slower thread' for the metrics where it makes sense.
- bool should_report_slower_thread =
- IsInteractionType(type_) || type_ == FrameSequenceTrackerType::kUniversal;
- base::Optional<int> aggregated_throughput_percent;
- if (should_report_slower_thread) {
- aggregated_throughput_percent = ThroughputData::ReportHistogram(
- this, ThreadType::kSlower,
- GetIndexForMetric(FrameSequenceMetrics::ThreadType::kSlower, type_),
- aggregated_throughput_);
- if (aggregated_throughput_percent.has_value() && throughput_ukm_reporter_) {
- throughput_ukm_reporter_->ReportThroughputUkm(
- aggregated_throughput_percent, impl_throughput_percent,
- main_throughput_percent, type_);
- }
- }
-
- // Report for the 'scrolling thread' for the scrolling interactions.
- if (scrolling_thread_ != ThreadType::kUnknown) {
- base::Optional<int> scrolling_thread_throughput;
- switch (scrolling_thread_) {
- case ThreadType::kCompositor:
- scrolling_thread_throughput = impl_throughput_percent;
- break;
- case ThreadType::kMain:
- scrolling_thread_throughput = main_throughput_percent;
- break;
- case ThreadType::kSlower:
- case ThreadType::kUnknown:
- NOTREACHED();
- break;
- }
- if (scrolling_thread_throughput.has_value()) {
- // It's OK to use the UMA histogram in the following code while still
- // using |GetThroughputHistogramName()| to get the name of the metric,
- // since the input-params to the function never change at runtime.
- if (type_ == FrameSequenceTrackerType::kWheelScroll) {
- UMA_HISTOGRAM_PERCENTAGE(
- GetThroughputHistogramName(FrameSequenceTrackerType::kWheelScroll,
- "ScrollingThread"),
- scrolling_thread_throughput.value());
- } else if (type_ == FrameSequenceTrackerType::kTouchScroll) {
- UMA_HISTOGRAM_PERCENTAGE(
- GetThroughputHistogramName(FrameSequenceTrackerType::kTouchScroll,
- "ScrollingThread"),
- scrolling_thread_throughput.value());
- } else {
- DCHECK_EQ(type_, FrameSequenceTrackerType::kScrollbarScroll);
- UMA_HISTOGRAM_PERCENTAGE(
- GetThroughputHistogramName(
- FrameSequenceTrackerType::kScrollbarScroll, "ScrollingThread"),
- scrolling_thread_throughput.value());
- }
- }
- }
-
- // Report the checkerboarding metrics.
- if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) {
- const int checkerboarding_percent = static_cast<int>(
- 100 * frames_checkerboarded_ / impl_throughput_.frames_expected);
- STATIC_HISTOGRAM_POINTER_GROUP(
- GetCheckerboardingHistogramName(type_), static_cast<int>(type_),
- static_cast<int>(FrameSequenceTrackerType::kMaxType),
- Add(checkerboarding_percent),
- base::LinearHistogram::FactoryGet(
- GetCheckerboardingHistogramName(type_), 1, 100, 101,
- base::HistogramBase::kUmaTargetedHistogramFlag));
- frames_checkerboarded_ = 0;
- }
-
- // Reset the metrics that reach reporting threshold.
- if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric)
- impl_throughput_ = {};
- if (main_throughput_.frames_expected >= kMinFramesForThroughputMetric)
- main_throughput_ = {};
- if (aggregated_throughput_percent.has_value())
- aggregated_throughput_ = {};
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FrameSequenceTrackerCollection
-
-FrameSequenceTrackerCollection::FrameSequenceTrackerCollection(
- bool is_single_threaded,
- CompositorFrameReportingController* compositor_frame_reporting_controller)
- : is_single_threaded_(is_single_threaded),
- compositor_frame_reporting_controller_(
- compositor_frame_reporting_controller) {}
-
-FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() {
- frame_trackers_.clear();
- removal_trackers_.clear();
-}
-
-FrameSequenceMetrics* FrameSequenceTrackerCollection::StartSequence(
- FrameSequenceTrackerType type) {
- DCHECK_NE(FrameSequenceTrackerType::kCustom, type);
-
- if (is_single_threaded_)
- return nullptr;
- if (frame_trackers_.contains(type))
- return frame_trackers_[type]->metrics();
- auto tracker = base::WrapUnique(
- new FrameSequenceTracker(type, throughput_ukm_reporter_.get()));
- frame_trackers_[type] = std::move(tracker);
-
- if (compositor_frame_reporting_controller_)
- compositor_frame_reporting_controller_->AddActiveTracker(type);
- return frame_trackers_[type]->metrics();
-}
-
-void FrameSequenceTrackerCollection::StopSequence(
- FrameSequenceTrackerType type) {
- DCHECK_NE(FrameSequenceTrackerType::kCustom, type);
-
- if (!frame_trackers_.contains(type))
- return;
-
- std::unique_ptr<FrameSequenceTracker> tracker =
- std::move(frame_trackers_[type]);
-
- if (compositor_frame_reporting_controller_)
- compositor_frame_reporting_controller_->RemoveActiveTracker(tracker->type_);
-
- frame_trackers_.erase(type);
- tracker->ScheduleTerminate();
- removal_trackers_.push_back(std::move(tracker));
- DestroyTrackers();
-}
-
-void FrameSequenceTrackerCollection::StartCustomSequence(int sequence_id) {
- DCHECK(!base::Contains(custom_frame_trackers_, sequence_id));
-
- custom_frame_trackers_[sequence_id] = base::WrapUnique(
- new FrameSequenceTracker(FrameSequenceTrackerType::kCustom,
- /*throughput_ukm_reporter=*/nullptr,
- /*custom_sequence_id=*/sequence_id));
-}
-
-void FrameSequenceTrackerCollection::StopCustomSequence(int sequence_id) {
- auto it = custom_frame_trackers_.find(sequence_id);
- // This happens when an animation is aborted before starting.
- if (it == custom_frame_trackers_.end())
- return;
-
- std::unique_ptr<FrameSequenceTracker> tracker = std::move(it->second);
- custom_frame_trackers_.erase(it);
- tracker->ScheduleTerminate();
- removal_trackers_.push_back(std::move(tracker));
-}
-
-void FrameSequenceTrackerCollection::ClearAll() {
- frame_trackers_.clear();
- custom_frame_trackers_.clear();
- removal_trackers_.clear();
-}
-
-void FrameSequenceTrackerCollection::NotifyBeginImplFrame(
- const viz::BeginFrameArgs& args) {
- RecreateTrackers(args);
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportBeginImplFrame(args);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportBeginImplFrame(args);
-}
-
-void FrameSequenceTrackerCollection::NotifyBeginMainFrame(
- const viz::BeginFrameArgs& args) {
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportBeginMainFrame(args);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportBeginMainFrame(args);
-}
-
-void FrameSequenceTrackerCollection::NotifyMainFrameProcessed(
- const viz::BeginFrameArgs& args) {
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportMainFrameProcessed(args);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportMainFrameProcessed(args);
-}
-
-void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage(
- const viz::BeginFrameAck& ack) {
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportImplFrameCausedNoDamage(ack);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportImplFrameCausedNoDamage(ack);
-
- // Removal trackers continue to process any frames which they started
- // observing.
- for (auto& tracker : removal_trackers_)
- tracker->ReportImplFrameCausedNoDamage(ack);
-}
-
-void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage(
- const viz::BeginFrameArgs& args) {
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportMainFrameCausedNoDamage(args);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportMainFrameCausedNoDamage(args);
-}
-
-void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() {
- for (auto& tracker : frame_trackers_)
- tracker.second->PauseFrameProduction();
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->PauseFrameProduction();
-}
-
-void FrameSequenceTrackerCollection::NotifySubmitFrame(
- uint32_t frame_token,
- bool has_missing_content,
- const viz::BeginFrameAck& ack,
- const viz::BeginFrameArgs& origin_args) {
- for (auto& tracker : frame_trackers_) {
- tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack,
- origin_args);
- }
- for (auto& tracker : custom_frame_trackers_) {
- tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack,
- origin_args);
- }
-
- // Removal trackers continue to process any frames which they started
- // observing.
- for (auto& tracker : removal_trackers_) {
- tracker->ReportSubmitFrame(frame_token, has_missing_content, ack,
- origin_args);
- }
-
- // TODO(crbug.com/1072482): find a proper way to terminate a tracker. Please
- // refer to details in FrameSequenceTracker::ReportSubmitFrame
- DestroyTrackers();
-}
-
-void FrameSequenceTrackerCollection::NotifyFrameEnd(
- const viz::BeginFrameArgs& args,
- const viz::BeginFrameArgs& main_args) {
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportFrameEnd(args, main_args);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportFrameEnd(args, main_args);
-
- // Removal trackers continue to process any frames which they started
- // observing.
- for (auto& tracker : removal_trackers_)
- tracker->ReportFrameEnd(args, main_args);
- DestroyTrackers();
-}
-
-void FrameSequenceTrackerCollection::NotifyFramePresented(
- uint32_t frame_token,
- const gfx::PresentationFeedback& feedback) {
- for (auto& tracker : frame_trackers_)
- tracker.second->ReportFramePresented(frame_token, feedback);
- for (auto& tracker : custom_frame_trackers_)
- tracker.second->ReportFramePresented(frame_token, feedback);
-
- for (auto& tracker : removal_trackers_)
- tracker->ReportFramePresented(frame_token, feedback);
-
- for (auto& tracker : removal_trackers_) {
- if (tracker->termination_status() ==
- FrameSequenceTracker::TerminationStatus::kReadyForTermination) {
- // The tracker is ready to be terminated.
- // For non kCustom typed trackers, take the metrics from the tracker.
- // merge with any outstanding metrics from previous trackers of the same
- // type. If there are enough frames to report the metrics, then report the
- // metrics and destroy it. Otherwise, retain it to be merged with
- // follow-up sequences.
- // For kCustom typed trackers, put its result in |custom_tracker_results_|
- // to be picked up by caller.
- auto metrics = tracker->TakeMetrics();
- if (tracker->type() == FrameSequenceTrackerType::kCustom) {
- custom_tracker_results_[tracker->custom_sequence_id()] =
- metrics->main_throughput();
- // |custom_tracker_results_| should be picked up timely.
- DCHECK_LT(custom_tracker_results_.size(), 500u);
- continue;
- }
-
- auto key = std::make_pair(tracker->type(), metrics->GetEffectiveThread());
- if (accumulated_metrics_.contains(key)) {
- metrics->Merge(std::move(accumulated_metrics_[key]));
- accumulated_metrics_.erase(key);
- }
-
- if (metrics->HasEnoughDataForReporting())
- metrics->ReportMetrics();
- if (metrics->HasDataLeftForReporting())
- accumulated_metrics_[key] = std::move(metrics);
- }
- }
-
- DestroyTrackers();
-}
-
-void FrameSequenceTrackerCollection::DestroyTrackers() {
- base::EraseIf(
- removal_trackers_,
- [](const std::unique_ptr<FrameSequenceTracker>& tracker) {
- return tracker->termination_status() ==
- FrameSequenceTracker::TerminationStatus::kReadyForTermination;
- });
-}
-
-void FrameSequenceTrackerCollection::RecreateTrackers(
- const viz::BeginFrameArgs& args) {
- std::vector<FrameSequenceTrackerType> recreate_trackers;
- for (const auto& tracker : frame_trackers_) {
- if (tracker.second->ShouldReportMetricsNow(args))
- recreate_trackers.push_back(tracker.first);
- }
-
- for (const auto& tracker_type : recreate_trackers) {
- // StopSequence put the tracker in the |removal_trackers_|, which will
- // report its throughput data when its frame is presented.
- StopSequence(tracker_type);
- // The frame sequence is still active, so create a new tracker to keep
- // tracking this sequence.
- StartSequence(tracker_type);
- }
-}
-
-ActiveFrameSequenceTrackers
-FrameSequenceTrackerCollection::FrameSequenceTrackerActiveTypes() {
- ActiveFrameSequenceTrackers encoded_types = 0;
- for (const auto& tracker : frame_trackers_) {
- encoded_types |= static_cast<ActiveFrameSequenceTrackers>(
- 1 << static_cast<unsigned>(tracker.first));
- }
- return encoded_types;
-}
-
-CustomTrackerResults
-FrameSequenceTrackerCollection::TakeCustomTrackerResults() {
- return std::move(custom_tracker_results_);
-}
-
-FrameSequenceTracker* FrameSequenceTrackerCollection::GetTrackerForTesting(
- FrameSequenceTrackerType type) {
- if (!frame_trackers_.contains(type))
- return nullptr;
- return frame_trackers_[type].get();
-}
-
-FrameSequenceTracker*
-FrameSequenceTrackerCollection::GetRemovalTrackerForTesting(
- FrameSequenceTrackerType type) {
- for (const auto& tracker : removal_trackers_)
- if (tracker->type_ == type)
- return tracker.get();
- return nullptr;
-}
-
-void FrameSequenceTrackerCollection::SetUkmManager(UkmManager* manager) {
- DCHECK(frame_trackers_.empty());
- if (manager)
- throughput_ukm_reporter_ = std::make_unique<ThroughputUkmReporter>(manager);
- else
- throughput_ukm_reporter_ = nullptr;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FrameSequenceTracker
-
FrameSequenceTracker::FrameSequenceTracker(
FrameSequenceTrackerType type,
- ThroughputUkmReporter* throughput_ukm_reporter,
- int custom_sequence_id)
- : type_(type),
- custom_sequence_id_(custom_sequence_id),
+ ThroughputUkmReporter* throughput_ukm_reporter)
+ : custom_sequence_id_(-1),
metrics_(std::make_unique<FrameSequenceMetrics>(type,
throughput_ukm_reporter)),
trace_data_(metrics_.get()) {
- DCHECK_LT(type_, FrameSequenceTrackerType::kMaxType);
- DCHECK(type_ != FrameSequenceTrackerType::kCustom ||
- custom_sequence_id_ >= 0);
+ DCHECK_LT(type, FrameSequenceTrackerType::kMaxType);
+ DCHECK(type != FrameSequenceTrackerType::kCustom);
+}
+
+FrameSequenceTracker::FrameSequenceTracker(
+ int custom_sequence_id,
+ FrameSequenceMetrics::CustomReporter custom_reporter)
+ : custom_sequence_id_(custom_sequence_id),
+ metrics_(std::make_unique<FrameSequenceMetrics>(
+ FrameSequenceTrackerType::kCustom,
+ /*ukm_reporter=*/nullptr)),
+ trace_data_(metrics_.get()) {
+ DCHECK_GT(custom_sequence_id_, 0);
+ metrics_->SetCustomReporter(std::move(custom_reporter));
}
FrameSequenceTracker::~FrameSequenceTracker() = default;
@@ -649,7 +101,8 @@ void FrameSequenceTracker::ReportBeginImplFrame(
if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
return;
- TRACKER_TRACE_STREAM << "b(" << args.frame_id.sequence_number << ")";
+ TRACKER_TRACE_STREAM << "b(" << args.frame_id.sequence_number % kDebugStrMod
+ << ")";
DCHECK(!is_inside_frame_) << TRACKER_DCHECK_MSG;
is_inside_frame_ = true;
@@ -689,8 +142,11 @@ void FrameSequenceTracker::ReportBeginMainFrame(
if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
return;
- TRACKER_TRACE_STREAM << "B(" << begin_main_frame_data_.previous_sequence
- << "," << args.frame_id.sequence_number << ")";
+ TRACKER_TRACE_STREAM << "B("
+ << begin_main_frame_data_.previous_sequence %
+ kDebugStrMod
+ << "," << args.frame_id.sequence_number % kDebugStrMod
+ << ")";
if (first_received_main_sequence_ &&
first_received_main_sequence_ > args.frame_id.sequence_number) {
@@ -732,7 +188,8 @@ void FrameSequenceTracker::ReportMainFrameProcessed(
if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
return;
- TRACKER_TRACE_STREAM << "E(" << args.frame_id.sequence_number << ")";
+ TRACKER_TRACE_STREAM << "E(" << args.frame_id.sequence_number % kDebugStrMod
+ << ")";
const bool previous_main_frame_submitted_or_no_damage =
previous_begin_main_sequence_ != 0 &&
@@ -779,6 +236,7 @@ void FrameSequenceTracker::ReportSubmitFrame(
// not going to be presented, and thus terminate this tracker.
const uint32_t frames_to_terminate_tracker = 3;
if (termination_status_ == TerminationStatus::kScheduledForTermination &&
+ last_submitted_frame_ != 0 &&
viz::FrameTokenGT(frame_token,
last_submitted_frame_ + frames_to_terminate_tracker)) {
termination_status_ = TerminationStatus::kReadyForTermination;
@@ -805,7 +263,7 @@ void FrameSequenceTracker::ReportSubmitFrame(
last_submitted_frame_ = frame_token;
compositor_frame_submitted_ = true;
- TRACKER_TRACE_STREAM << "s(" << frame_token << ")";
+ TRACKER_TRACE_STREAM << "s(" << frame_token % kDebugStrMod << ")";
had_impl_frame_submitted_between_commits_ = true;
const bool main_changes_after_sequence_started =
@@ -825,7 +283,9 @@ void FrameSequenceTracker::ReportSubmitFrame(
if (main_changes_after_sequence_started &&
main_changes_include_new_changes && !main_change_had_no_damage) {
submitted_frame_had_new_main_content_ = true;
- TRACKER_TRACE_STREAM << "S(" << origin_args.frame_id.sequence_number
+ TRACKER_TRACE_STREAM << "S("
+ << origin_args.frame_id.sequence_number %
+ kDebugStrMod
<< ")";
last_submitted_main_sequence_ = origin_args.frame_id.sequence_number;
@@ -856,8 +316,10 @@ void FrameSequenceTracker::ReportFrameEnd(
if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
return;
- TRACKER_TRACE_STREAM << "e(" << args.frame_id.sequence_number << ","
- << main_args.frame_id.sequence_number << ")";
+ TRACKER_TRACE_STREAM << "e(" << args.frame_id.sequence_number % kDebugStrMod
+ << ","
+ << main_args.frame_id.sequence_number % kDebugStrMod
+ << ")";
bool should_ignore_sequence =
ShouldIgnoreSequence(args.frame_id.sequence_number);
@@ -923,18 +385,24 @@ void FrameSequenceTracker::ReportFrameEnd(
void FrameSequenceTracker::ReportFramePresented(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) {
+ // TODO(xidachen): We should early exit if |last_submitted_frame_| = 0, as it
+ // means that we are presenting the same frame_token again.
+ const bool submitted_frame_since_last_presentation = !!last_submitted_frame_;
// !viz::FrameTokenGT(a, b) is equivalent to b >= a.
const bool frame_token_acks_last_frame =
!viz::FrameTokenGT(last_submitted_frame_, frame_token);
+ // Even if the presentation timestamp is null, we set last_submitted_frame_ to
+ // 0 such that the tracker can be terminated.
+ if (last_submitted_frame_ && frame_token_acks_last_frame)
+ last_submitted_frame_ = 0;
// Update termination status if this is scheduled for termination, and it is
// not waiting for any frames, or it has received the presentation-feedback
// for the latest frame it is tracking.
//
// We should always wait for an impl frame to end, that is, ReportFrameEnd.
if (termination_status_ == TerminationStatus::kScheduledForTermination &&
- (last_submitted_frame_ == 0 || frame_token_acks_last_frame) &&
- !is_inside_frame_) {
+ last_submitted_frame_ == 0 && !is_inside_frame_) {
termination_status_ = TerminationStatus::kReadyForTermination;
}
@@ -945,28 +413,25 @@ void FrameSequenceTracker::ReportFramePresented(
return;
}
- TRACKER_TRACE_STREAM << "P(" << frame_token << ")";
+ TRACKER_TRACE_STREAM << "P(" << frame_token % kDebugStrMod << ")";
- if (ignored_frame_tokens_.contains(frame_token))
- return;
base::EraseIf(ignored_frame_tokens_, [frame_token](const uint32_t& token) {
return viz::FrameTokenGT(frame_token, token);
});
+ if (ignored_frame_tokens_.contains(frame_token))
+ return;
uint32_t impl_frames_produced = 0;
uint32_t main_frames_produced = 0;
trace_data_.Advance(feedback.timestamp);
const bool was_presented = !feedback.timestamp.is_null();
- if (was_presented && last_submitted_frame_) {
+ if (was_presented && submitted_frame_since_last_presentation) {
DCHECK_LT(impl_throughput().frames_produced,
impl_throughput().frames_expected)
<< TRACKER_DCHECK_MSG;
++impl_throughput().frames_produced;
++impl_frames_produced;
-
- if (frame_token_acks_last_frame)
- last_submitted_frame_ = 0;
}
if (was_presented) {
@@ -1062,7 +527,8 @@ void FrameSequenceTracker::ReportImplFrameCausedNoDamage(
if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id))
return;
- TRACKER_TRACE_STREAM << "n(" << ack.frame_id.sequence_number << ")";
+ TRACKER_TRACE_STREAM << "n(" << ack.frame_id.sequence_number % kDebugStrMod
+ << ")";
// This tracker would be scheduled to terminate, and this frame doesn't belong
// to that tracker.
@@ -1087,8 +553,11 @@ void FrameSequenceTracker::ReportMainFrameCausedNoDamage(
if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
return;
- TRACKER_TRACE_STREAM << "N(" << begin_main_frame_data_.previous_sequence
- << "," << args.frame_id.sequence_number << ")";
+ TRACKER_TRACE_STREAM << "N("
+ << begin_main_frame_data_.previous_sequence %
+ kDebugStrMod
+ << "," << args.frame_id.sequence_number % kDebugStrMod
+ << ")";
if (!first_received_main_sequence_ ||
first_received_main_sequence_ > args.frame_id.sequence_number) {
@@ -1206,85 +675,6 @@ std::unique_ptr<FrameSequenceMetrics> FrameSequenceTracker::TakeMetrics() {
return std::move(metrics_);
}
-base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
- FrameSequenceMetrics* metrics,
- ThreadType thread_type,
- int metric_index,
- const ThroughputData& data) {
- const auto sequence_type = metrics->type();
- DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType);
-
- STATIC_HISTOGRAM_POINTER_GROUP(
- GetFrameSequenceLengthHistogramName(sequence_type),
- static_cast<int>(sequence_type),
- static_cast<int>(FrameSequenceTrackerType::kMaxType),
- Add(data.frames_expected),
- base::Histogram::FactoryGet(
- GetFrameSequenceLengthHistogramName(sequence_type), 1, 1000, 50,
- base::HistogramBase::kUmaTargetedHistogramFlag));
-
- if (data.frames_expected < kMinFramesForThroughputMetric)
- return base::nullopt;
-
- // Throughput means the percent of frames that was expected to show on the
- // screen but didn't. In other words, the lower the throughput is, the
- // smoother user experience.
- const int percent =
- std::ceil(100 * (data.frames_expected - data.frames_produced) /
- static_cast<double>(data.frames_expected));
-
- const bool is_animation =
- ShouldReportForAnimation(sequence_type, thread_type);
- const bool is_interaction = ShouldReportForInteraction(metrics, thread_type);
-
- ThroughputUkmReporter* const ukm_reporter = metrics->ukm_reporter();
-
- if (is_animation) {
- UMA_HISTOGRAM_PERCENTAGE(
- "Graphics.Smoothness.PercentDroppedFrames.AllAnimations", percent);
- if (ukm_reporter) {
- ukm_reporter->ReportAggregateThroughput(AggregationType::kAllAnimations,
- percent);
- }
- }
-
- if (is_interaction) {
- UMA_HISTOGRAM_PERCENTAGE(
- "Graphics.Smoothness.PercentDroppedFrames.AllInteractions", percent);
- if (ukm_reporter) {
- ukm_reporter->ReportAggregateThroughput(AggregationType::kAllInteractions,
- percent);
- }
- }
-
- if (is_animation || is_interaction) {
- UMA_HISTOGRAM_PERCENTAGE(
- "Graphics.Smoothness.PercentDroppedFrames.AllSequences", percent);
- if (ukm_reporter) {
- ukm_reporter->ReportAggregateThroughput(AggregationType::kAllSequences,
- percent);
- }
- }
-
- if (!is_animation && !IsInteractionType(sequence_type) &&
- sequence_type != FrameSequenceTrackerType::kUniversal &&
- sequence_type != FrameSequenceTrackerType::kVideo) {
- return base::nullopt;
- }
-
- const char* thread_name =
- thread_type == ThreadType::kCompositor
- ? "CompositorThread"
- : thread_type == ThreadType::kMain ? "MainThread" : "SlowerThread";
- STATIC_HISTOGRAM_POINTER_GROUP(
- GetThroughputHistogramName(sequence_type, thread_name), metric_index,
- kMaximumHistogramIndex, Add(percent),
- base::LinearHistogram::FactoryGet(
- GetThroughputHistogramName(sequence_type, thread_name), 1, 100, 101,
- base::HistogramBase::kUmaTargetedHistogramFlag));
- return percent;
-}
-
FrameSequenceTracker::CheckerboardingData::CheckerboardingData() = default;
FrameSequenceTracker::CheckerboardingData::~CheckerboardingData() = default;
diff --git a/chromium/cc/metrics/frame_sequence_tracker.h b/chromium/cc/metrics/frame_sequence_tracker.h
index b45fd72dac5..680b2a85ad9 100644
--- a/chromium/cc/metrics/frame_sequence_tracker.h
+++ b/chromium/cc/metrics/frame_sequence_tracker.h
@@ -5,20 +5,12 @@
#ifndef CC_METRICS_FRAME_SEQUENCE_TRACKER_H_
#define CC_METRICS_FRAME_SEQUENCE_TRACKER_H_
-#include <stdint.h>
-#include <memory>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/callback_helpers.h"
#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
-#include "base/macros.h"
#include "base/optional.h"
-#include "base/trace_event/traced_value.h"
#include "cc/cc_export.h"
+#include "cc/metrics/frame_sequence_metrics.h"
namespace gfx {
struct PresentationFeedback;
@@ -31,237 +23,7 @@ struct BeginFrameId;
} // namespace viz
namespace cc {
-class FrameSequenceTracker;
-class CompositorFrameReportingController;
class ThroughputUkmReporter;
-class UkmManager;
-
-enum class FrameSequenceTrackerType {
- // Used as an enum for metrics. DO NOT reorder or delete values. Rather,
- // add them at the end and increment kMaxType.
- kCompositorAnimation = 0,
- kMainThreadAnimation = 1,
- kPinchZoom = 2,
- kRAF = 3,
- kTouchScroll = 4,
- kUniversal = 5,
- kVideo = 6,
- kWheelScroll = 7,
- kScrollbarScroll = 8,
- kCustom = 9, // Note that the metrics for kCustom are not reported on UMA,
- // and instead are dispatched back to the LayerTreeHostClient.
- kMaxType
-};
-
-typedef uint16_t ActiveFrameSequenceTrackers;
-
-class CC_EXPORT FrameSequenceMetrics {
- public:
- FrameSequenceMetrics(FrameSequenceTrackerType type,
- ThroughputUkmReporter* ukm_reporter);
- ~FrameSequenceMetrics();
-
- FrameSequenceMetrics(const FrameSequenceMetrics&) = delete;
- FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete;
-
- enum class ThreadType { kMain, kCompositor, kSlower, kUnknown };
-
- struct ThroughputData {
- static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue(
- const ThroughputData& impl,
- const ThroughputData& main);
-
- // Returns the throughput in percent, a return value of base::nullopt
- // indicates that no throughput metric is reported.
- static base::Optional<int> ReportHistogram(FrameSequenceMetrics* metrics,
- ThreadType thread_type,
- int metric_index,
- const ThroughputData& data);
-
- void Merge(const ThroughputData& data) {
- frames_expected += data.frames_expected;
- frames_produced += data.frames_produced;
-#if DCHECK_IS_ON()
- frames_processed += data.frames_processed;
- frames_received += data.frames_received;
-#endif
- }
-
- // Tracks the number of frames that were expected to be shown during this
- // frame-sequence.
- uint32_t frames_expected = 0;
-
- // Tracks the number of frames that were actually presented to the user
- // during this frame-sequence.
- uint32_t frames_produced = 0;
-
-#if DCHECK_IS_ON()
- // Tracks the number of frames that is either submitted or reported as no
- // damage.
- uint32_t frames_processed = 0;
-
- // Tracks the number of begin-frames that are received.
- uint32_t frames_received = 0;
-#endif
- };
-
- void SetScrollingThread(ThreadType thread);
-
- // Returns the 'effective thread' for the metrics (i.e. the thread most
- // relevant for this metric).
- ThreadType GetEffectiveThread() const;
-
- void Merge(std::unique_ptr<FrameSequenceMetrics> metrics);
- bool HasEnoughDataForReporting() const;
- bool HasDataLeftForReporting() const;
- // Report related metrics: throughput, checkboarding...
- void ReportMetrics();
- void ComputeAggregatedThroughputForTesting() {
- ComputeAggregatedThroughput();
- }
-
- ThroughputData& impl_throughput() { return impl_throughput_; }
- ThroughputData& main_throughput() { return main_throughput_; }
- ThroughputData& aggregated_throughput() { return aggregated_throughput_; }
- void add_checkerboarded_frames(int64_t frames) {
- frames_checkerboarded_ += frames;
- }
- uint32_t frames_checkerboarded() const { return frames_checkerboarded_; }
-
- FrameSequenceTrackerType type() const { return type_; }
- ThroughputUkmReporter* ukm_reporter() const {
- return throughput_ukm_reporter_;
- }
-
- private:
- void ComputeAggregatedThroughput();
- const FrameSequenceTrackerType type_;
-
- // Pointer to the reporter owned by the FrameSequenceTrackerCollection.
- ThroughputUkmReporter* const throughput_ukm_reporter_;
-
- ThroughputData impl_throughput_;
- ThroughputData main_throughput_;
- // The aggregated throughput for the main/compositor thread.
- ThroughputData aggregated_throughput_;
-
- ThreadType scrolling_thread_ = ThreadType::kUnknown;
-
- // Tracks the number of produced frames that had some amount of
- // checkerboarding, and how many frames showed such checkerboarded frames.
- uint32_t frames_checkerboarded_ = 0;
-};
-
-// Map of kCustom tracker results keyed by a sequence id.
-using CustomTrackerResults =
- base::flat_map<int, FrameSequenceMetrics::ThroughputData>;
-
-// Used for notifying attached FrameSequenceTracker's of begin-frames and
-// submitted frames.
-class CC_EXPORT FrameSequenceTrackerCollection {
- public:
- FrameSequenceTrackerCollection(
- bool is_single_threaded,
- CompositorFrameReportingController* frame_reporting_controller);
- ~FrameSequenceTrackerCollection();
-
- FrameSequenceTrackerCollection(const FrameSequenceTrackerCollection&) =
- delete;
- FrameSequenceTrackerCollection& operator=(
- const FrameSequenceTrackerCollection&) = delete;
-
- // Creates a tracker for the specified sequence-type.
- FrameSequenceMetrics* StartSequence(FrameSequenceTrackerType type);
-
- // Schedules |tracker| for destruction. This is preferred instead of outright
- // desrtruction of the tracker, since this ensures that the actual tracker
- // instance is destroyed *after* the presentation-feedbacks have been received
- // for all submitted frames.
- void StopSequence(FrameSequenceTrackerType type);
-
- // Creates a kCustom tracker for the given sequence id. It is an error and
- // DCHECKs if there is already a tracker associated with the sequence id.
- void StartCustomSequence(int sequence_id);
-
- // Schedules the kCustom tracker representing |sequence_id| for destruction.
- // It is a no-op if there is no tracker associated with the sequence id.
- // Similar to StopSequence above, the tracker instance is destroyed *after*
- // the presentation feedbacks have been received for all submitted frames.
- void StopCustomSequence(int sequence_id);
-
- // Removes all trackers. This also immediately destroys all trackers that had
- // been scheduled for destruction, even if there are pending
- // presentation-feedbacks. This is typically used if the client no longer
- // expects to receive presentation-feedbacks for the previously submitted
- // frames (e.g. when the gpu process dies).
- void ClearAll();
-
- // Notifies all trackers of various events.
- void NotifyBeginImplFrame(const viz::BeginFrameArgs& args);
- void NotifyBeginMainFrame(const viz::BeginFrameArgs& args);
- void NotifyMainFrameProcessed(const viz::BeginFrameArgs& args);
- void NotifyImplFrameCausedNoDamage(const viz::BeginFrameAck& ack);
- void NotifyMainFrameCausedNoDamage(const viz::BeginFrameArgs& args);
- void NotifyPauseFrameProduction();
- void NotifySubmitFrame(uint32_t frame_token,
- bool has_missing_content,
- const viz::BeginFrameAck& ack,
- const viz::BeginFrameArgs& origin_args);
- void NotifyFrameEnd(const viz::BeginFrameArgs& args,
- const viz::BeginFrameArgs& main_args);
-
- // Note that this notifies the trackers of the presentation-feedbacks, and
- // destroys any tracker that had been scheduled for destruction (using
- // |ScheduleRemoval()|) if it has no more pending frames. Data from non
- // kCustom typed trackers are reported to UMA. Data from kCustom typed
- // trackers are added to |custom_tracker_results_| for caller to pick up.
- void NotifyFramePresented(uint32_t frame_token,
- const gfx::PresentationFeedback& feedback);
-
- // Return the type of each active frame tracker, encoded into a 16 bit
- // integer with the bit at each position corresponding to the enum value of
- // each type.
- ActiveFrameSequenceTrackers FrameSequenceTrackerActiveTypes();
-
- // Reports the accumulated kCustom tracker results and clears it.
- CustomTrackerResults TakeCustomTrackerResults();
-
- FrameSequenceTracker* GetTrackerForTesting(FrameSequenceTrackerType type);
- FrameSequenceTracker* GetRemovalTrackerForTesting(
- FrameSequenceTrackerType type);
-
- void SetUkmManager(UkmManager* manager);
-
- private:
- friend class FrameSequenceTrackerTest;
-
- void RecreateTrackers(const viz::BeginFrameArgs& args);
- // Destroy the trackers that are ready to be terminated.
- void DestroyTrackers();
-
- const bool is_single_threaded_;
- // The callsite can use the type to manipulate the tracker.
- base::flat_map<FrameSequenceTrackerType,
- std::unique_ptr<FrameSequenceTracker>>
- frame_trackers_;
-
- // Custom trackers are keyed by a custom sequence id.
- base::flat_map<int, std::unique_ptr<FrameSequenceTracker>>
- custom_frame_trackers_;
- CustomTrackerResults custom_tracker_results_;
-
- std::vector<std::unique_ptr<FrameSequenceTracker>> removal_trackers_;
- CompositorFrameReportingController* const
- compositor_frame_reporting_controller_;
-
- // The reporter takes throughput data and connect to UkmManager to report it.
- std::unique_ptr<ThroughputUkmReporter> throughput_ukm_reporter_;
-
- base::flat_map<
- std::pair<FrameSequenceTrackerType, FrameSequenceMetrics::ThreadType>,
- std::unique_ptr<FrameSequenceMetrics>>
- accumulated_metrics_;
-};
// Tracks a sequence of frames to determine the throughput. It tracks this by
// tracking the vsync sequence-numbers (from |BeginFrameArgs::sequence_number|),
@@ -334,7 +96,7 @@ class CC_EXPORT FrameSequenceTracker {
bool ShouldReportMetricsNow(const viz::BeginFrameArgs& args) const;
FrameSequenceMetrics* metrics() { return metrics_.get(); }
- FrameSequenceTrackerType type() const { return type_; }
+ FrameSequenceTrackerType type() const { return metrics_->type(); }
int custom_sequence_id() const { return custom_sequence_id_; }
std::unique_ptr<FrameSequenceMetrics> TakeMetrics();
@@ -343,9 +105,12 @@ class CC_EXPORT FrameSequenceTracker {
friend class FrameSequenceTrackerCollection;
friend class FrameSequenceTrackerTest;
+ // Constructs a tracker for a typed sequence other than kCustom.
FrameSequenceTracker(FrameSequenceTrackerType type,
- ThroughputUkmReporter* throughput_ukm_reporter,
- int custom_sequence_id = -1);
+ ThroughputUkmReporter* throughput_ukm_reporter);
+ // Constructs a tracker for a kCustom typed sequence.
+ FrameSequenceTracker(int custom_sequence_id,
+ FrameSequenceMetrics::CustomReporter custom_reporter);
FrameSequenceMetrics::ThroughputData& impl_throughput() {
return metrics_->impl_throughput();
@@ -393,7 +158,6 @@ class CC_EXPORT FrameSequenceTracker {
bool ShouldIgnoreSequence(uint64_t sequence_number) const;
- const FrameSequenceTrackerType type_;
const int custom_sequence_id_;
TerminationStatus termination_status_ = TerminationStatus::kActive;
diff --git a/chromium/cc/metrics/frame_sequence_tracker_collection.cc b/chromium/cc/metrics/frame_sequence_tracker_collection.cc
new file mode 100644
index 00000000000..8dd78ca0ccd
--- /dev/null
+++ b/chromium/cc/metrics/frame_sequence_tracker_collection.cc
@@ -0,0 +1,316 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/metrics/frame_sequence_tracker_collection.h"
+
+#include "base/memory/ptr_util.h"
+#include "cc/metrics/compositor_frame_reporting_controller.h"
+#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/throughput_ukm_reporter.h"
+
+namespace cc {
+
+FrameSequenceTrackerCollection::FrameSequenceTrackerCollection(
+ bool is_single_threaded,
+ CompositorFrameReportingController* compositor_frame_reporting_controller)
+ : is_single_threaded_(is_single_threaded),
+ compositor_frame_reporting_controller_(
+ compositor_frame_reporting_controller) {}
+
+FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() {
+ frame_trackers_.clear();
+ removal_trackers_.clear();
+}
+
+FrameSequenceMetrics* FrameSequenceTrackerCollection::StartSequence(
+ FrameSequenceTrackerType type) {
+ DCHECK_NE(FrameSequenceTrackerType::kCustom, type);
+
+ if (is_single_threaded_)
+ return nullptr;
+ if (frame_trackers_.contains(type))
+ return frame_trackers_[type]->metrics();
+ auto tracker = base::WrapUnique(
+ new FrameSequenceTracker(type, throughput_ukm_reporter_.get()));
+ frame_trackers_[type] = std::move(tracker);
+
+ if (compositor_frame_reporting_controller_)
+ compositor_frame_reporting_controller_->AddActiveTracker(type);
+ return frame_trackers_[type]->metrics();
+}
+
+void FrameSequenceTrackerCollection::StopSequence(
+ FrameSequenceTrackerType type) {
+ DCHECK_NE(FrameSequenceTrackerType::kCustom, type);
+
+ if (!frame_trackers_.contains(type))
+ return;
+
+ std::unique_ptr<FrameSequenceTracker> tracker =
+ std::move(frame_trackers_[type]);
+
+ if (compositor_frame_reporting_controller_)
+ compositor_frame_reporting_controller_->RemoveActiveTracker(
+ tracker->type());
+
+ frame_trackers_.erase(type);
+ tracker->ScheduleTerminate();
+ removal_trackers_.push_back(std::move(tracker));
+ DestroyTrackers();
+}
+
+void FrameSequenceTrackerCollection::StartCustomSequence(int sequence_id) {
+ DCHECK(!base::Contains(custom_frame_trackers_, sequence_id));
+
+ // base::Unretained() is safe here because |this| owns FrameSequenceTracker
+ // and FrameSequenceMetrics.
+ custom_frame_trackers_[sequence_id] =
+ base::WrapUnique(new FrameSequenceTracker(
+ sequence_id,
+ base::BindOnce(
+ &FrameSequenceTrackerCollection::AddCustomTrackerResult,
+ base::Unretained(this), sequence_id)));
+}
+
+void FrameSequenceTrackerCollection::StopCustomSequence(int sequence_id) {
+ auto it = custom_frame_trackers_.find(sequence_id);
+ // This happens when an animation is aborted before starting.
+ if (it == custom_frame_trackers_.end())
+ return;
+
+ std::unique_ptr<FrameSequenceTracker> tracker = std::move(it->second);
+ custom_frame_trackers_.erase(it);
+ tracker->ScheduleTerminate();
+ removal_trackers_.push_back(std::move(tracker));
+ DestroyTrackers();
+}
+
+void FrameSequenceTrackerCollection::ClearAll() {
+ frame_trackers_.clear();
+ custom_frame_trackers_.clear();
+ removal_trackers_.clear();
+}
+
+void FrameSequenceTrackerCollection::NotifyBeginImplFrame(
+ const viz::BeginFrameArgs& args) {
+ RecreateTrackers(args);
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportBeginImplFrame(args);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportBeginImplFrame(args);
+}
+
+void FrameSequenceTrackerCollection::NotifyBeginMainFrame(
+ const viz::BeginFrameArgs& args) {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportBeginMainFrame(args);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportBeginMainFrame(args);
+}
+
+void FrameSequenceTrackerCollection::NotifyMainFrameProcessed(
+ const viz::BeginFrameArgs& args) {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportMainFrameProcessed(args);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportMainFrameProcessed(args);
+}
+
+void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage(
+ const viz::BeginFrameAck& ack) {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportImplFrameCausedNoDamage(ack);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportImplFrameCausedNoDamage(ack);
+
+ // Removal trackers continue to process any frames which they started
+ // observing.
+ for (auto& tracker : removal_trackers_)
+ tracker->ReportImplFrameCausedNoDamage(ack);
+}
+
+void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage(
+ const viz::BeginFrameArgs& args) {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportMainFrameCausedNoDamage(args);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportMainFrameCausedNoDamage(args);
+}
+
+void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->PauseFrameProduction();
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->PauseFrameProduction();
+}
+
+void FrameSequenceTrackerCollection::NotifySubmitFrame(
+ uint32_t frame_token,
+ bool has_missing_content,
+ const viz::BeginFrameAck& ack,
+ const viz::BeginFrameArgs& origin_args) {
+ for (auto& tracker : frame_trackers_) {
+ tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack,
+ origin_args);
+ }
+ for (auto& tracker : custom_frame_trackers_) {
+ tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack,
+ origin_args);
+ }
+
+ // Removal trackers continue to process any frames which they started
+ // observing.
+ for (auto& tracker : removal_trackers_) {
+ tracker->ReportSubmitFrame(frame_token, has_missing_content, ack,
+ origin_args);
+ }
+
+ // TODO(crbug.com/1072482): find a proper way to terminate a tracker. Please
+ // refer to details in FrameSequenceTracker::ReportSubmitFrame
+ DestroyTrackers();
+}
+
+void FrameSequenceTrackerCollection::NotifyFrameEnd(
+ const viz::BeginFrameArgs& args,
+ const viz::BeginFrameArgs& main_args) {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportFrameEnd(args, main_args);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportFrameEnd(args, main_args);
+
+ // Removal trackers continue to process any frames which they started
+ // observing.
+ for (auto& tracker : removal_trackers_)
+ tracker->ReportFrameEnd(args, main_args);
+ DestroyTrackers();
+}
+
+void FrameSequenceTrackerCollection::NotifyFramePresented(
+ uint32_t frame_token,
+ const gfx::PresentationFeedback& feedback) {
+ for (auto& tracker : frame_trackers_)
+ tracker.second->ReportFramePresented(frame_token, feedback);
+ for (auto& tracker : custom_frame_trackers_)
+ tracker.second->ReportFramePresented(frame_token, feedback);
+
+ for (auto& tracker : removal_trackers_)
+ tracker->ReportFramePresented(frame_token, feedback);
+
+ for (auto& tracker : removal_trackers_) {
+ if (tracker->termination_status() ==
+ FrameSequenceTracker::TerminationStatus::kReadyForTermination) {
+ // The tracker is ready to be terminated.
+ // For non kCustom typed trackers, take the metrics from the tracker.
+ // merge with any outstanding metrics from previous trackers of the same
+ // type. If there are enough frames to report the metrics, then report the
+ // metrics and destroy it. Otherwise, retain it to be merged with
+ // follow-up sequences.
+ // For kCustom typed trackers, |metrics| invokes AddCustomTrackerResult
+ // on its destruction, which add its data to |custom_tracker_results_|
+ // to be picked up by caller.
+ auto metrics = tracker->TakeMetrics();
+ if (metrics->type() == FrameSequenceTrackerType::kCustom)
+ continue;
+
+ auto key = std::make_pair(metrics->type(), metrics->GetEffectiveThread());
+ if (accumulated_metrics_.contains(key)) {
+ metrics->Merge(std::move(accumulated_metrics_[key]));
+ accumulated_metrics_.erase(key);
+ }
+
+ if (metrics->HasEnoughDataForReporting()) {
+ if (metrics->type() == FrameSequenceTrackerType::kUniversal) {
+ uint32_t frames_expected = metrics->impl_throughput().frames_expected;
+ uint32_t frames_produced =
+ metrics->aggregated_throughput().frames_produced;
+ current_universal_throughput_ = std::floor(
+ 100 * frames_produced / static_cast<float>(frames_expected));
+ }
+ metrics->ReportMetrics();
+ }
+ if (metrics->HasDataLeftForReporting())
+ accumulated_metrics_[key] = std::move(metrics);
+ }
+ }
+
+ DestroyTrackers();
+}
+
+void FrameSequenceTrackerCollection::DestroyTrackers() {
+ base::EraseIf(
+ removal_trackers_,
+ [](const std::unique_ptr<FrameSequenceTracker>& tracker) {
+ return tracker->termination_status() ==
+ FrameSequenceTracker::TerminationStatus::kReadyForTermination;
+ });
+}
+
+void FrameSequenceTrackerCollection::RecreateTrackers(
+ const viz::BeginFrameArgs& args) {
+ std::vector<FrameSequenceTrackerType> recreate_trackers;
+ for (const auto& tracker : frame_trackers_) {
+ if (tracker.second->ShouldReportMetricsNow(args))
+ recreate_trackers.push_back(tracker.first);
+ }
+
+ for (const auto& tracker_type : recreate_trackers) {
+ // StopSequence put the tracker in the |removal_trackers_|, which will
+ // report its throughput data when its frame is presented.
+ StopSequence(tracker_type);
+ // The frame sequence is still active, so create a new tracker to keep
+ // tracking this sequence.
+ StartSequence(tracker_type);
+ }
+}
+
+ActiveFrameSequenceTrackers
+FrameSequenceTrackerCollection::FrameSequenceTrackerActiveTypes() {
+ ActiveFrameSequenceTrackers encoded_types = 0;
+ for (const auto& tracker : frame_trackers_) {
+ encoded_types |= static_cast<ActiveFrameSequenceTrackers>(
+ 1 << static_cast<unsigned>(tracker.first));
+ }
+ return encoded_types;
+}
+
+CustomTrackerResults
+FrameSequenceTrackerCollection::TakeCustomTrackerResults() {
+ CustomTrackerResults results;
+ results.swap(custom_tracker_results_);
+ return results;
+}
+
+FrameSequenceTracker* FrameSequenceTrackerCollection::GetTrackerForTesting(
+ FrameSequenceTrackerType type) {
+ if (!frame_trackers_.contains(type))
+ return nullptr;
+ return frame_trackers_[type].get();
+}
+
+FrameSequenceTracker*
+FrameSequenceTrackerCollection::GetRemovalTrackerForTesting(
+ FrameSequenceTrackerType type) {
+ for (const auto& tracker : removal_trackers_)
+ if (tracker->type() == type)
+ return tracker.get();
+ return nullptr;
+}
+
+void FrameSequenceTrackerCollection::SetUkmManager(UkmManager* manager) {
+ DCHECK(frame_trackers_.empty());
+ if (manager)
+ throughput_ukm_reporter_ = std::make_unique<ThroughputUkmReporter>(manager);
+ else
+ throughput_ukm_reporter_ = nullptr;
+}
+
+void FrameSequenceTrackerCollection::AddCustomTrackerResult(
+ int custom_sequence_id,
+ FrameSequenceMetrics::ThroughputData throughput_data) {
+ // |custom_tracker_results_| should be picked up timely.
+ DCHECK_LT(custom_tracker_results_.size(), 500u);
+ custom_tracker_results_[custom_sequence_id] = std::move(throughput_data);
+}
+
+} // namespace cc
diff --git a/chromium/cc/metrics/frame_sequence_tracker_collection.h b/chromium/cc/metrics/frame_sequence_tracker_collection.h
new file mode 100644
index 00000000000..9eaf1efb6b2
--- /dev/null
+++ b/chromium/cc/metrics/frame_sequence_tracker_collection.h
@@ -0,0 +1,156 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_METRICS_FRAME_SEQUENCE_TRACKER_COLLECTION_H_
+#define CC_METRICS_FRAME_SEQUENCE_TRACKER_COLLECTION_H_
+
+#include <memory>
+
+#include "base/containers/flat_map.h"
+#include "base/optional.h"
+#include "cc/cc_export.h"
+#include "cc/metrics/frame_sequence_metrics.h"
+
+namespace gfx {
+struct PresentationFeedback;
+}
+
+namespace viz {
+struct BeginFrameAck;
+struct BeginFrameArgs;
+} // namespace viz
+
+namespace cc {
+class FrameSequenceTracker;
+class CompositorFrameReportingController;
+class ThroughputUkmReporter;
+class UkmManager;
+
+// Map of kCustom tracker results keyed by a sequence id.
+using CustomTrackerResults =
+ base::flat_map<int, FrameSequenceMetrics::ThroughputData>;
+
+typedef uint16_t ActiveFrameSequenceTrackers;
+
+// Used for notifying attached FrameSequenceTracker's of begin-frames and
+// submitted frames.
+class CC_EXPORT FrameSequenceTrackerCollection {
+ public:
+ FrameSequenceTrackerCollection(
+ bool is_single_threaded,
+ CompositorFrameReportingController* frame_reporting_controller);
+ ~FrameSequenceTrackerCollection();
+
+ FrameSequenceTrackerCollection(const FrameSequenceTrackerCollection&) =
+ delete;
+ FrameSequenceTrackerCollection& operator=(
+ const FrameSequenceTrackerCollection&) = delete;
+
+ // Creates a tracker for the specified sequence-type.
+ FrameSequenceMetrics* StartSequence(FrameSequenceTrackerType type);
+
+ // Schedules |tracker| for destruction. This is preferred instead of outright
+ // desrtruction of the tracker, since this ensures that the actual tracker
+ // instance is destroyed *after* the presentation-feedbacks have been received
+ // for all submitted frames.
+ void StopSequence(FrameSequenceTrackerType type);
+
+ // Creates a kCustom tracker for the given sequence id. It is an error and
+ // DCHECKs if there is already a tracker associated with the sequence id.
+ void StartCustomSequence(int sequence_id);
+
+ // Schedules the kCustom tracker representing |sequence_id| for destruction.
+ // It is a no-op if there is no tracker associated with the sequence id.
+ // Similar to StopSequence above, the tracker instance is destroyed *after*
+ // the presentation feedbacks have been received for all submitted frames.
+ void StopCustomSequence(int sequence_id);
+
+ // Removes all trackers. This also immediately destroys all trackers that had
+ // been scheduled for destruction, even if there are pending
+ // presentation-feedbacks. This is typically used if the client no longer
+ // expects to receive presentation-feedbacks for the previously submitted
+ // frames (e.g. when the gpu process dies).
+ void ClearAll();
+
+ // Notifies all trackers of various events.
+ void NotifyBeginImplFrame(const viz::BeginFrameArgs& args);
+ void NotifyBeginMainFrame(const viz::BeginFrameArgs& args);
+ void NotifyMainFrameProcessed(const viz::BeginFrameArgs& args);
+ void NotifyImplFrameCausedNoDamage(const viz::BeginFrameAck& ack);
+ void NotifyMainFrameCausedNoDamage(const viz::BeginFrameArgs& args);
+ void NotifyPauseFrameProduction();
+ void NotifySubmitFrame(uint32_t frame_token,
+ bool has_missing_content,
+ const viz::BeginFrameAck& ack,
+ const viz::BeginFrameArgs& origin_args);
+ void NotifyFrameEnd(const viz::BeginFrameArgs& args,
+ const viz::BeginFrameArgs& main_args);
+
+ // Note that this notifies the trackers of the presentation-feedbacks, and
+ // destroys any tracker that had been scheduled for destruction (using
+ // |ScheduleRemoval()|) if it has no more pending frames. Data from non
+ // kCustom typed trackers are reported to UMA. Data from kCustom typed
+ // trackers are added to |custom_tracker_results_| for caller to pick up.
+ void NotifyFramePresented(uint32_t frame_token,
+ const gfx::PresentationFeedback& feedback);
+
+ // Return the type of each active frame tracker, encoded into a 16 bit
+ // integer with the bit at each position corresponding to the enum value of
+ // each type.
+ ActiveFrameSequenceTrackers FrameSequenceTrackerActiveTypes();
+
+ // Reports the accumulated kCustom tracker results and clears it.
+ CustomTrackerResults TakeCustomTrackerResults();
+
+ FrameSequenceTracker* GetTrackerForTesting(FrameSequenceTrackerType type);
+ FrameSequenceTracker* GetRemovalTrackerForTesting(
+ FrameSequenceTrackerType type);
+
+ void SetUkmManager(UkmManager* manager);
+
+ base::Optional<int> current_universal_throughput() {
+ return current_universal_throughput_;
+ }
+
+ private:
+ friend class FrameSequenceTrackerTest;
+
+ void RecreateTrackers(const viz::BeginFrameArgs& args);
+ // Destroy the trackers that are ready to be terminated.
+ void DestroyTrackers();
+
+ // Adds collected metrics data for |custom_sequence_id| to be picked up via
+ // TakeCustomTrackerResults() below.
+ void AddCustomTrackerResult(
+ int custom_sequence_id,
+ FrameSequenceMetrics::ThroughputData throughput_data);
+
+ const bool is_single_threaded_;
+ // The callsite can use the type to manipulate the tracker.
+ base::flat_map<FrameSequenceTrackerType,
+ std::unique_ptr<FrameSequenceTracker>>
+ frame_trackers_;
+
+ // Custom trackers are keyed by a custom sequence id.
+ base::flat_map<int, std::unique_ptr<FrameSequenceTracker>>
+ custom_frame_trackers_;
+ CustomTrackerResults custom_tracker_results_;
+
+ std::vector<std::unique_ptr<FrameSequenceTracker>> removal_trackers_;
+ CompositorFrameReportingController* const
+ compositor_frame_reporting_controller_;
+
+ // The reporter takes throughput data and connect to UkmManager to report it.
+ std::unique_ptr<ThroughputUkmReporter> throughput_ukm_reporter_;
+
+ base::flat_map<
+ std::pair<FrameSequenceTrackerType, FrameSequenceMetrics::ThreadType>,
+ std::unique_ptr<FrameSequenceMetrics>>
+ accumulated_metrics_;
+ base::Optional<int> current_universal_throughput_;
+};
+
+} // namespace cc
+
+#endif // CC_METRICS_FRAME_SEQUENCE_TRACKER_COLLECTION_H_
diff --git a/chromium/cc/metrics/frame_sequence_tracker_unittest.cc b/chromium/cc/metrics/frame_sequence_tracker_unittest.cc
index 8e6e977aec0..2a6b8cd2b82 100644
--- a/chromium/cc/metrics/frame_sequence_tracker_unittest.cc
+++ b/chromium/cc/metrics/frame_sequence_tracker_unittest.cc
@@ -4,11 +4,10 @@
#include "cc/metrics/frame_sequence_tracker.h"
-#include <vector>
-
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "cc/metrics/compositor_frame_reporting_controller.h"
+#include "cc/metrics/frame_sequence_tracker_collection.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -107,7 +106,7 @@ class FrameSequenceTrackerTest : public testing::Test {
bool RemovalTrackerExists(unsigned index,
FrameSequenceTrackerType type) const {
DCHECK_GT(collection_.removal_trackers_.size(), index);
- return collection_.removal_trackers_[index]->type_ == type;
+ return collection_.removal_trackers_[index]->type() == type;
}
void GenerateSequence(const char* str) {
@@ -229,7 +228,7 @@ class FrameSequenceTrackerTest : public testing::Test {
void ReportMetrics() { tracker_->metrics_->ReportMetrics(); }
- base::TimeDelta TimeDeltaToReort() const {
+ base::TimeDelta TimeDeltaToReport() const {
return tracker_->time_delta_to_report_;
}
@@ -246,6 +245,7 @@ class FrameSequenceTrackerTest : public testing::Test {
uint64_t BeginImplFrameDataPreviousSequence() const {
return tracker_->begin_impl_frame_data_.previous_sequence;
}
+
uint64_t BeginMainFrameDataPreviousSequence() const {
return tracker_->begin_main_frame_data_.previous_sequence;
}
@@ -257,31 +257,28 @@ class FrameSequenceTrackerTest : public testing::Test {
FrameSequenceMetrics::ThroughputData& ImplThroughput() const {
return tracker_->impl_throughput();
}
+
FrameSequenceMetrics::ThroughputData& MainThroughput() const {
return tracker_->main_throughput();
}
+
FrameSequenceMetrics::ThroughputData& AggregatedThroughput() const {
return tracker_->aggregated_throughput();
}
- void SetTerminationStatus(FrameSequenceTracker::TerminationStatus status) {
- tracker_->termination_status_ = status;
+ FrameSequenceTracker::TerminationStatus GetTerminationStatus(
+ FrameSequenceTracker* tracker) {
+ return tracker->termination_status_;
}
-
FrameSequenceTracker::TerminationStatus GetTerminationStatus() {
return tracker_->termination_status_;
}
- FrameSequenceTracker::TerminationStatus GetTerminationStatusForTracker(
- FrameSequenceTracker* tracker) {
- return tracker->termination_status_;
- }
-
- protected:
- uint32_t number_of_frames_checkerboarded() const {
+ uint32_t NumberOfFramesCheckerboarded() const {
return tracker_->metrics_->frames_checkerboarded();
}
+ protected:
std::unique_ptr<CompositorFrameReportingController>
compositor_frame_reporting_controller_;
FrameSequenceTrackerCollection collection_;
@@ -383,7 +380,7 @@ TEST_F(FrameSequenceTrackerTest, CheckerboardingSimple) {
gfx::PresentationFeedback(base::TimeTicks::Now() + interval, interval, 0);
collection_.NotifyFramePresented(frame_token, feedback);
- EXPECT_EQ(1u, number_of_frames_checkerboarded());
+ EXPECT_EQ(1u, NumberOfFramesCheckerboarded());
}
// Present a single frame with checkerboarding, followed by a non-checkerboard
@@ -414,7 +411,7 @@ TEST_F(FrameSequenceTrackerTest, CheckerboardingMultipleFrames) {
interval, 0);
collection_.NotifyFramePresented(frame_token, feedback);
- EXPECT_EQ(3u, number_of_frames_checkerboarded());
+ EXPECT_EQ(3u, NumberOfFramesCheckerboarded());
}
// Present multiple checkerboarded frames, followed by a non-checkerboard
@@ -452,7 +449,7 @@ TEST_F(FrameSequenceTrackerTest, MultipleCheckerboardingFrames) {
gfx::PresentationFeedback feedback(present_now, interval, 0);
collection_.NotifyFramePresented(frame_token, feedback);
- EXPECT_EQ(kFrames, number_of_frames_checkerboarded());
+ EXPECT_EQ(kFrames, NumberOfFramesCheckerboarded());
}
TEST_F(FrameSequenceTrackerTest, ReportMetrics) {
@@ -533,7 +530,7 @@ TEST_F(FrameSequenceTrackerTest, ReportMetricsAtFixedInterval) {
// Now args.frame_time is 5s since the tracker creation time, so this tracker
// should be scheduled to report its throughput.
args = CreateBeginFrameArgs(source, ++sequence,
- args.frame_time + TimeDeltaToReort());
+ args.frame_time + TimeDeltaToReport());
collection_.NotifyBeginImplFrame(args);
collection_.NotifyImplFrameCausedNoDamage(viz::BeginFrameAck(args, false));
collection_.NotifyFrameEnd(args, args);
@@ -1076,13 +1073,13 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame1) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
// There is still one impl-frame not processed not, so the tracker is not yet
// ready for termination.
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
@@ -1100,7 +1097,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame2) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)e(1,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1128,7 +1125,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame3) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1156,7 +1153,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame4) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1182,11 +1179,11 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame5) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
@@ -1197,11 +1194,11 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame6) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
@@ -1225,7 +1222,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame7) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1253,7 +1250,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame8) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1281,7 +1278,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame9) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1304,11 +1301,11 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame10) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(2)P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
@@ -1319,11 +1316,11 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame11) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
@@ -1342,7 +1339,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame12) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(2)e(2,0)");
// Now the |removal_tracker| should have been destroyed.
@@ -1370,7 +1367,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame13) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(2,0)");
// Now the |removal_tracker| should have been destroyed.
@@ -1426,7 +1423,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame15) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)e(1,0)b(2)s(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1454,7 +1451,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame16) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)b(2)s(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1482,7 +1479,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame17) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("b(2)s(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1511,7 +1508,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame18) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)e(1,0)b(2)n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1539,7 +1536,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame19) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)b(2)n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1567,7 +1564,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame20) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("b(2)n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
@@ -1597,7 +1594,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame21) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(1)e(1,0)");
// Ensure that this tracker is actually removed from the |removal_trackers_|
@@ -1622,7 +1619,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame22) {
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
- EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
+ EXPECT_EQ(GetTerminationStatus(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)");
// Ensure that this tracker is actually removed from the |removal_trackers_|
@@ -1663,27 +1660,15 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame24) {
}
TEST_F(FrameSequenceTrackerTest, IgnoredFrameTokensRemovedAtPresentation1) {
- GenerateSequence("b(5)");
+ GenerateSequence("b(5)s(1)e(5,0)P(1)");
auto args = CreateBeginFrameArgs(/*source_id=*/1u, 1u);
// Ack to an impl frame that doesn't exist in this tracker.
- collection_.NotifySubmitFrame(1, /*has_missing_content=*/false,
+ collection_.NotifySubmitFrame(2, /*has_missing_content=*/false,
viz::BeginFrameAck(args, true), args);
EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
- args = CreateBeginFrameArgs(1u, 5u);
- collection_.NotifySubmitFrame(2, false, viz::BeginFrameAck(args, true), args);
- GenerateSequence("e(5,0)b(6)");
- // Ack to an impl frame that doesn't exist in this tracker.
- args = CreateBeginFrameArgs(1u, 1u);
- collection_.NotifySubmitFrame(3, false, viz::BeginFrameAck(args, true), args);
- args = CreateBeginFrameArgs(1u, 6u);
- collection_.NotifySubmitFrame(4, false, viz::BeginFrameAck(args, true), args);
- EXPECT_EQ(IgnoredFrameTokens().size(), 2u);
- GenerateSequence("P(2)");
- // frame_token = 2 is presented, frame_token = 3 remains in the list.
- EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
- GenerateSequence("P(4)");
- // Now frame_token = 4 is presented, frame_token = 3 should be removed.
- EXPECT_TRUE(IgnoredFrameTokens().empty());
+ GenerateSequence("P(3)");
+ // Any token that is < 3 should have been removed.
+ EXPECT_EQ(IgnoredFrameTokens().size(), 0u);
}
// Test the case where the frame tokens wraps around the 32-bit max value.
@@ -1701,6 +1686,19 @@ TEST_F(FrameSequenceTrackerTest, IgnoredFrameTokensRemovedAtPresentation2) {
EXPECT_TRUE(IgnoredFrameTokens().empty());
}
+TEST_F(FrameSequenceTrackerTest, TerminationWithNullPresentationTimeStamp) {
+ GenerateSequence("b(1)s(1)");
+ collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
+ EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
+ // Even if the presentation timestamp is null, as long as this presentation
+ // is acking the last impl frame, we consider that impl frame completed and
+ // so the tracker is ready for termination.
+ collection_.NotifyFramePresented(
+ 1, {base::TimeTicks(), viz::BeginFrameArgs::DefaultInterval(), 0});
+ GenerateSequence("e(1,0)");
+ EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
+}
+
// Test that a tracker is terminated after 3 submitted frames, remove this
// once crbug.com/1072482 is fixed.
TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions1) {
@@ -1724,6 +1722,15 @@ TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions2) {
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
}
+TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions3) {
+ GenerateSequence(
+ "b(1)s(1)e(1,0)P(1)b(2)s(2)e(2,0)P(2)b(3)s(3)e(3,0)P(3)b(4)");
+ collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
+ EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
+ GenerateSequence("s(4)");
+ EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
+}
+
TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage1) {
const char sequence[] =
"b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)n(2)e(2,1)b(3)E(2)B(2,3)n(3)e(3,2)";
@@ -1887,11 +1894,10 @@ TEST_F(FrameSequenceTrackerTest, CustomTrackers) {
collection_.StopCustomSequence(2);
EXPECT_EQ(2u, NumberOfCustomTrackers());
- // Tracker 2 should report with no data.
+ // Tracker 2 has no data to report.
collection_.NotifyFramePresented(frame_token, {});
results = collection_.TakeCustomTrackerResults();
- EXPECT_EQ(1u, results.size());
- EXPECT_EQ(0u, results[2].frames_expected);
+ EXPECT_EQ(0u, results.size());
// Simple sequence of one frame.
const char sequence[] = "b(1)B(0,1)s(1)S(1)e(1,0)P(1)";
diff --git a/chromium/cc/metrics/latency_ukm_reporter.cc b/chromium/cc/metrics/latency_ukm_reporter.cc
index 9678edee540..072ccb31daf 100644
--- a/chromium/cc/metrics/latency_ukm_reporter.cc
+++ b/chromium/cc/metrics/latency_ukm_reporter.cc
@@ -12,7 +12,7 @@ namespace cc {
void LatencyUkmReporter::ReportLatencyUkm(
CompositorFrameReporter::FrameReportType report_type,
const std::vector<CompositorFrameReporter::StageData>& stage_history,
- const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+ const CompositorFrameReporter::ActiveTrackers& active_trackers,
const viz::FrameTimingDetails& viz_breakdown) {
if (!ukm_manager_)
return;
diff --git a/chromium/cc/metrics/latency_ukm_reporter.h b/chromium/cc/metrics/latency_ukm_reporter.h
index 9bbc810cec4..3ee27823a4b 100644
--- a/chromium/cc/metrics/latency_ukm_reporter.h
+++ b/chromium/cc/metrics/latency_ukm_reporter.h
@@ -23,7 +23,7 @@ class CC_EXPORT LatencyUkmReporter {
void ReportLatencyUkm(
CompositorFrameReporter::FrameReportType report_type,
const std::vector<CompositorFrameReporter::StageData>& stage_history,
- const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+ const CompositorFrameReporter::ActiveTrackers& active_trackers,
const viz::FrameTimingDetails& viz_breakdown);
void SetUkmManager(UkmManager* manager) { ukm_manager_ = manager; }
diff --git a/chromium/cc/metrics/lcd_text_metrics_reporter.cc b/chromium/cc/metrics/lcd_text_metrics_reporter.cc
new file mode 100644
index 00000000000..023651ce2c7
--- /dev/null
+++ b/chromium/cc/metrics/lcd_text_metrics_reporter.cc
@@ -0,0 +1,102 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/metrics/lcd_text_metrics_reporter.h"
+
+#include "base/lazy_instance.h"
+#include "base/metrics/histogram_macros.h"
+#include "cc/base/histograms.h"
+#include "cc/layers/picture_layer_impl.h"
+#include "cc/paint/display_item_list.h"
+#include "cc/trees/layer_tree_host_impl.h"
+#include "cc/trees/layer_tree_impl.h"
+
+namespace cc {
+
+namespace {
+
+constexpr auto kMinimumTimeInterval = base::TimeDelta::FromMinutes(1);
+constexpr unsigned kMinimumFrameInterval = 500;
+
+// This must be the same as that used in DeviceScaleEnsuresTextQuality() in
+// content/renderer/render_widget.cc.
+constexpr float kHighDPIDeviceScaleFactorThreshold = 1.5f;
+constexpr char kMetricNameLCDTextKPixelsHighDPI[] =
+ "Compositing.Renderer.LCDTextDisallowedReasonKPixels.HighDPI";
+constexpr char kMetricNameLCDTextKPixelsLowDPI[] =
+ "Compositing.Renderer.LCDTextDisallowedReasonKPixels.LowDPI";
+constexpr char kMetricNameLCDTextLayersHighDPI[] =
+ "Compositing.Renderer.LCDTextDisallowedReasonLayers.HighDPI";
+constexpr char kMetricNameLCDTextLayersLowDPI[] =
+ "Compositing.Renderer.LCDTextDisallowedReasonLayers.LowDPI";
+
+} // anonymous namespace
+
+std::unique_ptr<LCDTextMetricsReporter> LCDTextMetricsReporter::CreateIfNeeded(
+ const LayerTreeHostImpl* layer_tree_host_impl) {
+ const char* client_name = GetClientNameForMetrics();
+ // The metrics are for the renderer only.
+ if (!client_name || strcmp(client_name, "Renderer") != 0)
+ return nullptr;
+ return base::WrapUnique(new LCDTextMetricsReporter(layer_tree_host_impl));
+}
+
+LCDTextMetricsReporter::LCDTextMetricsReporter(
+ const LayerTreeHostImpl* layer_tree_host_impl)
+ : layer_tree_host_impl_(layer_tree_host_impl) {}
+
+LCDTextMetricsReporter::~LCDTextMetricsReporter() = default;
+
+void LCDTextMetricsReporter::NotifySubmitFrame(
+ const viz::BeginFrameArgs& args) {
+ current_frame_time_ = args.frame_time;
+ frame_count_since_last_report_++;
+ if (last_report_frame_time_.is_null())
+ last_report_frame_time_ = current_frame_time_;
+}
+
+void LCDTextMetricsReporter::NotifyPauseFrameProduction() {
+ if (current_frame_time_.is_null() ||
+ current_frame_time_ - last_report_frame_time_ < kMinimumTimeInterval ||
+ frame_count_since_last_report_ < kMinimumFrameInterval) {
+ return;
+ }
+
+ last_report_frame_time_ = current_frame_time_;
+ frame_count_since_last_report_ = 0;
+
+ float device_scale_factor =
+ layer_tree_host_impl_->settings().use_painted_device_scale_factor
+ ? layer_tree_host_impl_->active_tree()->painted_device_scale_factor()
+ : layer_tree_host_impl_->active_tree()->device_scale_factor();
+ bool is_high_dpi = device_scale_factor >= kHighDPIDeviceScaleFactorThreshold;
+
+ for (const auto* layer :
+ layer_tree_host_impl_->active_tree()->picture_layers()) {
+ if (!layer->DrawsContent() || !layer->GetRasterSource())
+ continue;
+ const scoped_refptr<DisplayItemList>& display_item_list =
+ layer->GetRasterSource()->GetDisplayItemList();
+ if (!display_item_list)
+ continue;
+
+ int text_pixels = static_cast<int>(
+ display_item_list->AreaOfDrawText(layer->visible_layer_rect()));
+ if (!text_pixels)
+ continue;
+
+ auto reason = layer->lcd_text_disallowed_reason();
+ if (is_high_dpi) {
+ UMA_HISTOGRAM_SCALED_ENUMERATION(kMetricNameLCDTextKPixelsHighDPI, reason,
+ text_pixels, 1000);
+ UMA_HISTOGRAM_ENUMERATION(kMetricNameLCDTextLayersHighDPI, reason);
+ } else {
+ UMA_HISTOGRAM_SCALED_ENUMERATION(kMetricNameLCDTextKPixelsLowDPI, reason,
+ text_pixels, 1000);
+ UMA_HISTOGRAM_ENUMERATION(kMetricNameLCDTextLayersLowDPI, reason);
+ }
+ }
+}
+
+} // namespace cc
diff --git a/chromium/cc/metrics/lcd_text_metrics_reporter.h b/chromium/cc/metrics/lcd_text_metrics_reporter.h
new file mode 100644
index 00000000000..b2aede915a5
--- /dev/null
+++ b/chromium/cc/metrics/lcd_text_metrics_reporter.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_METRICS_LCD_TEXT_METRICS_REPORTER_H_
+#define CC_METRICS_LCD_TEXT_METRICS_REPORTER_H_
+
+#include <cstdint>
+#include <memory>
+
+#include "base/time/time.h"
+#include "cc/cc_export.h"
+
+namespace viz {
+struct BeginFrameArgs;
+}
+
+namespace cc {
+
+class LayerTreeHostImpl;
+
+// See tools/metrics/histograms/histograms.xml for description of the metrics
+// (names listed in .cc).
+class CC_EXPORT LCDTextMetricsReporter {
+ public:
+ static std::unique_ptr<LCDTextMetricsReporter> CreateIfNeeded(
+ const LayerTreeHostImpl*);
+ ~LCDTextMetricsReporter();
+
+ LCDTextMetricsReporter(const LCDTextMetricsReporter&) = delete;
+ LCDTextMetricsReporter& operator=(const LCDTextMetricsReporter&) = delete;
+
+ void NotifySubmitFrame(const viz::BeginFrameArgs&);
+ void NotifyPauseFrameProduction();
+
+ private:
+ explicit LCDTextMetricsReporter(const LayerTreeHostImpl*);
+
+ const LayerTreeHostImpl* layer_tree_host_impl_;
+ base::TimeTicks last_report_frame_time_;
+ base::TimeTicks current_frame_time_;
+ uint64_t frame_count_since_last_report_ = 0;
+};
+
+} // namespace cc
+
+#endif // CC_METRICS_LCD_TEXT_METRICS_REPORTER_H_
diff --git a/chromium/cc/metrics/throughput_ukm_reporter.h b/chromium/cc/metrics/throughput_ukm_reporter.h
index b544946f941..441be89f88a 100644
--- a/chromium/cc/metrics/throughput_ukm_reporter.h
+++ b/chromium/cc/metrics/throughput_ukm_reporter.h
@@ -7,7 +7,7 @@
#include "base/optional.h"
#include "cc/cc_export.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_metrics.h"
namespace cc {
class UkmManager;
diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc
index 6d3f094e50b..b37945a42f1 100644
--- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc
+++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -131,6 +131,9 @@ bool AsyncLayerTreeFrameSink::BindToClient(LayerTreeFrameSinkClient* client) {
if (wants_animate_only_begin_frames_)
compositor_frame_sink_->SetWantsAnimateOnlyBeginFrames();
+ compositor_frame_sink_ptr_->InitializeCompositorFrameSinkType(
+ viz::mojom::CompositorFrameSinkType::kLayerTree);
+
return true;
}
diff --git a/chromium/cc/mojom/BUILD.gn b/chromium/cc/mojom/BUILD.gn
index fdafe611497..12d79257d5d 100644
--- a/chromium/cc/mojom/BUILD.gn
+++ b/chromium/cc/mojom/BUILD.gn
@@ -6,7 +6,10 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
generate_java = true
- sources = [ "touch_action.mojom" ]
+ sources = [
+ "overscroll_behavior.mojom",
+ "touch_action.mojom",
+ ]
public_deps = [ "//mojo/public/mojom/base" ]
@@ -21,6 +24,23 @@ mojom("mojom") {
traits_public_deps = [ "//cc/ipc" ]
}
- cpp_typemaps = [ touch_action_typemap ]
- blink_cpp_typemaps = [ touch_action_typemap ]
+ overscroll_behavior_typemap = {
+ types = [
+ {
+ mojom = "cc.mojom.OverscrollBehavior"
+ cpp = "::cc::OverscrollBehavior"
+ },
+ ]
+ traits_headers = [ "//cc/ipc/cc_param_traits_macros.h" ]
+ traits_public_deps = [ "//cc/ipc" ]
+ }
+
+ cpp_typemaps = [
+ overscroll_behavior_typemap,
+ touch_action_typemap,
+ ]
+ blink_cpp_typemaps = [
+ overscroll_behavior_typemap,
+ touch_action_typemap,
+ ]
}
diff --git a/chromium/cc/mojom/overscroll_behavior.mojom b/chromium/cc/mojom/overscroll_behavior.mojom
new file mode 100644
index 00000000000..df6f7827cbc
--- /dev/null
+++ b/chromium/cc/mojom/overscroll_behavior.mojom
@@ -0,0 +1,8 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module cc.mojom;
+
+[Native]
+struct OverscrollBehavior;
diff --git a/chromium/cc/paint/display_item_list.cc b/chromium/cc/paint/display_item_list.cc
index 9429fef1569..52a3aac9f07 100644
--- a/chromium/cc/paint/display_item_list.cc
+++ b/chromium/cc/paint/display_item_list.cc
@@ -31,31 +31,39 @@ bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) {
return true;
}
-void FillTextContent(const PaintOpBuffer* buffer,
- std::vector<NodeId>* content) {
+template <typename Function>
+void IterateTextContent(const PaintOpBuffer* buffer, const Function& yield) {
for (auto* op : PaintOpBuffer::Iterator(buffer)) {
if (op->GetType() == PaintOpType::DrawTextBlob) {
- content->push_back(static_cast<DrawTextBlobOp*>(op)->node_id);
+ yield(static_cast<DrawTextBlobOp*>(op));
} else if (op->GetType() == PaintOpType::DrawRecord) {
- FillTextContent(static_cast<DrawRecordOp*>(op)->record.get(), content);
+ IterateTextContent(static_cast<DrawRecordOp*>(op)->record.get(), yield);
}
}
}
-void FillTextContentByOffsets(const PaintOpBuffer* buffer,
- const std::vector<size_t>& offsets,
- std::vector<NodeId>* content) {
+template <typename Function>
+void IterateTextContentByOffsets(const PaintOpBuffer* buffer,
+ const std::vector<size_t>& offsets,
+ const Function& yield) {
if (!buffer)
return;
for (auto* op : PaintOpBuffer::OffsetIterator(buffer, &offsets)) {
if (op->GetType() == PaintOpType::DrawTextBlob) {
- content->push_back(static_cast<DrawTextBlobOp*>(op)->node_id);
+ yield(static_cast<DrawTextBlobOp*>(op));
} else if (op->GetType() == PaintOpType::DrawRecord) {
- FillTextContent(static_cast<DrawRecordOp*>(op)->record.get(), content);
+ IterateTextContent(static_cast<DrawRecordOp*>(op)->record.get(), yield);
}
}
}
+bool RotationEquivalentToAxisFlip(const SkMatrix& matrix) {
+ float skew_x = matrix.getSkewX();
+ float skew_y = matrix.getSkewY();
+ return ((skew_x == 1.f || skew_x == -1.f) &&
+ (skew_y == 1.f || skew_y == -1.f));
+}
+
} // namespace
DisplayItemList::DisplayItemList(UsageHint usage_hint)
@@ -63,7 +71,7 @@ DisplayItemList::DisplayItemList(UsageHint usage_hint)
if (usage_hint_ == kTopLevelDisplayItemList) {
visual_rects_.reserve(1024);
offsets_.reserve(1024);
- begin_paired_indices_.reserve(32);
+ paired_begin_stack_.reserve(32);
}
}
@@ -85,7 +93,54 @@ void DisplayItemList::CaptureContent(const gfx::Rect& rect,
std::vector<NodeId>* content) const {
std::vector<size_t> offsets;
rtree_.Search(rect, &offsets);
- FillTextContentByOffsets(&paint_op_buffer_, offsets, content);
+ IterateTextContentByOffsets(
+ &paint_op_buffer_, offsets,
+ [content](const DrawTextBlobOp* op) { content->push_back(op->node_id); });
+}
+
+double DisplayItemList::AreaOfDrawText(const gfx::Rect& rect) const {
+ std::vector<size_t> offsets;
+ rtree_.Search(rect, &offsets);
+ double area = 0;
+ IterateTextContentByOffsets(
+ &paint_op_buffer_, offsets, [&area](const DrawTextBlobOp* op) {
+ // This is not fully accurate, e.g. when there is transform operations,
+ // but is good for statistics purpose.
+ SkRect bounds = op->blob->bounds();
+ area += static_cast<double>(bounds.width()) * bounds.height();
+ });
+ return area;
+}
+
+void DisplayItemList::EndPaintOfPairedEnd() {
+#if DCHECK_IS_ON()
+ DCHECK(IsPainting());
+ DCHECK_LT(current_range_start_, paint_op_buffer_.size());
+ current_range_start_ = kNotPainting;
+#endif
+ if (usage_hint_ == kToBeReleasedAsPaintOpBuffer)
+ return;
+
+ DCHECK(paired_begin_stack_.size());
+ size_t last_begin_index = paired_begin_stack_.back().first_index;
+ size_t last_begin_count = paired_begin_stack_.back().count;
+ DCHECK_GT(last_begin_count, 0u);
+
+ // Copy the visual rect at |last_begin_index| to all indices that constitute
+ // the begin item. Note that because we possibly reallocate the
+ // |visual_rects_| buffer below, we need an actual copy instead of a const
+ // reference which can become dangling.
+ auto visual_rect = visual_rects_[last_begin_index];
+ for (size_t i = 1; i < last_begin_count; ++i)
+ visual_rects_[i + last_begin_index] = visual_rect;
+ paired_begin_stack_.pop_back();
+
+ // Copy the visual rect of the matching begin item to the end item(s).
+ visual_rects_.resize(paint_op_buffer_.size(), visual_rect);
+
+ // The block that ended needs to be included in the bounds of the enclosing
+ // block.
+ GrowCurrentBeginItemVisualRect(visual_rect);
}
void DisplayItemList::Finalize() {
@@ -96,7 +151,7 @@ void DisplayItemList::Finalize() {
DCHECK(!IsPainting());
// If this fails we had more calls to EndPaintOfPairedBegin() than
// to EndPaintOfPairedEnd().
- DCHECK(begin_paired_indices_.empty());
+ DCHECK(paired_begin_stack_.empty());
DCHECK_EQ(visual_rects_.size(), offsets_.size());
#endif
@@ -117,7 +172,7 @@ void DisplayItemList::Finalize() {
visual_rects_.shrink_to_fit();
offsets_.clear();
offsets_.shrink_to_fit();
- begin_paired_indices_.shrink_to_fit();
+ paired_begin_stack_.shrink_to_fit();
}
size_t DisplayItemList::BytesUsed() const {
@@ -229,7 +284,7 @@ void DisplayItemList::GenerateDiscardableImagesMetadata() {
void DisplayItemList::Reset() {
#if DCHECK_IS_ON()
DCHECK(!IsPainting());
- DCHECK(begin_paired_indices_.empty());
+ DCHECK(paired_begin_stack_.empty());
#endif
rtree_.Reset();
@@ -239,8 +294,8 @@ void DisplayItemList::Reset() {
visual_rects_.shrink_to_fit();
offsets_.clear();
offsets_.shrink_to_fit();
- begin_paired_indices_.clear();
- begin_paired_indices_.shrink_to_fit();
+ paired_begin_stack_.clear();
+ paired_begin_stack_.shrink_to_fit();
has_draw_ops_ = false;
}
@@ -273,4 +328,114 @@ bool DisplayItemList::GetColorIfSolidInRect(const gfx::Rect& rect,
return false;
}
+base::Optional<DisplayItemList::DirectlyCompositedImageResult>
+DisplayItemList::GetDirectlyCompositedImageResult(
+ gfx::Size containing_layer_bounds) const {
+ const PaintOpBuffer* op_buffer = nullptr;
+ if (paint_op_buffer_.size() == 1) {
+ // The actual ops are wrapped in DrawRecord if they were previously
+ // recorded.
+ if (paint_op_buffer_.GetFirstOp()->GetType() == PaintOpType::DrawRecord) {
+ const DrawRecordOp* draw_record =
+ static_cast<const DrawRecordOp*>(paint_op_buffer_.GetFirstOp());
+ op_buffer = draw_record->record.get();
+ } else {
+ op_buffer = &paint_op_buffer_;
+ }
+ } else {
+ return base::nullopt;
+ }
+
+ const DrawImageRectOp* draw_image_rect_op = nullptr;
+ bool transpose_image_size = false;
+ constexpr size_t kNumDrawImageForOrientationOps = 10;
+ if (op_buffer->size() == 1 &&
+ op_buffer->GetFirstOp()->GetType() == PaintOpType::DrawImageRect) {
+ draw_image_rect_op =
+ static_cast<const DrawImageRectOp*>(op_buffer->GetFirstOp());
+ } else if (op_buffer->size() < kNumDrawImageForOrientationOps) {
+ // Images that respect orientation will have 5 paint operations:
+ // (1) Save
+ // (2) Translate
+ // (3) Concat (rotation matrix)
+ // (4) DrawImageRect
+ // (5) Restore
+ // Detect these the paint op buffer and disqualify the layer as a directly
+ // composited image if any other paint op is detected.
+ for (auto* op : PaintOpBuffer::Iterator(op_buffer)) {
+ switch (op->GetType()) {
+ case PaintOpType::Save:
+ case PaintOpType::Restore:
+ break;
+ case PaintOpType::Translate: {
+ const TranslateOp* translate = static_cast<const TranslateOp*>(op);
+ if (translate->dx != 0 || translate->dy != 0)
+ return base::nullopt;
+ break;
+ }
+ case PaintOpType::Concat: {
+ // We only expect a single rotation. If we see another one, then this
+ // image won't be eligible for directly compositing.
+ if (transpose_image_size)
+ return base::nullopt;
+
+ const ConcatOp* concat_op = static_cast<const ConcatOp*>(op);
+ if (concat_op->matrix.hasPerspective() ||
+ !concat_op->matrix.preservesAxisAlignment())
+ return base::nullopt;
+
+ // If the rotation is not an axis flip, we'll need to transpose the
+ // width and height dimensions to account for the same transform
+ // applying when the layer bounds were calculated.
+ transpose_image_size =
+ RotationEquivalentToAxisFlip(concat_op->matrix);
+ break;
+ }
+ case PaintOpType::DrawImageRect:
+ if (draw_image_rect_op)
+ return base::nullopt;
+ draw_image_rect_op = static_cast<const DrawImageRectOp*>(op);
+ break;
+ default:
+ return base::nullopt;
+ }
+ }
+ }
+
+ if (!draw_image_rect_op)
+ return base::nullopt;
+
+ // The src rect must match the image size exactly, i.e. the entire image
+ // must be drawn.
+ const SkRect& src = draw_image_rect_op->src;
+ if (src.fLeft != 0 || src.fTop != 0 ||
+ src.fRight != draw_image_rect_op->image.width() ||
+ src.fBottom != draw_image_rect_op->image.height())
+ return base::nullopt;
+
+ // The DrawImageRect op's destination rect must match the layer bounds
+ // exactly. Note that the layer bounds have already taken into account image
+ // orientation so transpose the dst width/height before comparing, if
+ // appropriate.
+ const SkRect& dst = draw_image_rect_op->dst;
+ int dst_width = transpose_image_size ? dst.fBottom : dst.fRight;
+ int dst_height = transpose_image_size ? dst.fRight : dst.fBottom;
+ if (dst.fLeft != 0 || dst.fTop != 0 ||
+ dst_width != containing_layer_bounds.width() ||
+ dst_height != containing_layer_bounds.height())
+ return base::nullopt;
+
+ int width = transpose_image_size ? draw_image_rect_op->image.height()
+ : draw_image_rect_op->image.width();
+ int height = transpose_image_size ? draw_image_rect_op->image.width()
+ : draw_image_rect_op->image.height();
+ DirectlyCompositedImageResult result;
+ result.intrinsic_image_size = gfx::Size(width, height);
+ // Ensure the layer will use nearest neighbor when drawn by the display
+ // compositor, if required.
+ result.nearest_neighbor =
+ draw_image_rect_op->flags.getFilterQuality() == kNone_SkFilterQuality;
+ return result;
+}
+
} // namespace cc
diff --git a/chromium/cc/paint/display_item_list.h b/chromium/cc/paint/display_item_list.h
index 3054d27c09b..b518d67715a 100644
--- a/chromium/cc/paint/display_item_list.h
+++ b/chromium/cc/paint/display_item_list.h
@@ -62,11 +62,15 @@ class CC_PAINT_EXPORT DisplayItemList
void Raster(SkCanvas* canvas, ImageProvider* image_provider = nullptr) const;
- // Captures the DrawTextBlobOp within |rect| and returns the associated
- // NodeId in |content|.
+ // Captures |DrawTextBlobOp|s intersecting |rect| and returns the associated
+ // |NodeId|s in |content|.
void CaptureContent(const gfx::Rect& rect,
std::vector<NodeId>* content) const;
+ // Returns the approximate total area covered by |DrawTextBlobOp|s
+ // intersecting |rect|, used for statistics purpose.
+ double AreaOfDrawText(const gfx::Rect& rect) const;
+
void StartPaint() {
#if DCHECK_IS_ON()
DCHECK(!IsPainting());
@@ -124,48 +128,27 @@ class CC_PAINT_EXPORT DisplayItemList
DCHECK_LT(visual_rects_.size(), paint_op_buffer_.size());
size_t count = paint_op_buffer_.size() - visual_rects_.size();
+ paired_begin_stack_.push_back({visual_rects_.size(), count});
visual_rects_.resize(paint_op_buffer_.size());
- begin_paired_indices_.push_back(
- std::make_pair(visual_rects_.size() - 1, count));
}
- void EndPaintOfPairedEnd() {
-#if DCHECK_IS_ON()
- DCHECK(IsPainting());
- DCHECK_LT(current_range_start_, paint_op_buffer_.size());
- current_range_start_ = kNotPainting;
-#endif
- if (usage_hint_ == kToBeReleasedAsPaintOpBuffer)
- return;
-
- DCHECK(begin_paired_indices_.size());
- size_t last_begin_index = begin_paired_indices_.back().first;
- size_t last_begin_count = begin_paired_indices_.back().second;
- DCHECK_GT(last_begin_count, 0u);
- DCHECK_GE(last_begin_index, last_begin_count - 1);
-
- // Copy the visual rect at |last_begin_index| to all indices that constitute
- // the begin item. Note that because we possibly reallocate the
- // |visual_rects_| buffer below, we need an actual copy instead of a const
- // reference which can become dangling.
- auto visual_rect = visual_rects_[last_begin_index];
- for (size_t i = last_begin_index - last_begin_count + 1;
- i < last_begin_index; ++i) {
- visual_rects_[i] = visual_rect;
- }
- begin_paired_indices_.pop_back();
-
- // Copy the visual rect of the matching begin item to the end item(s).
- visual_rects_.resize(paint_op_buffer_.size(), visual_rect);
-
- // The block that ended needs to be included in the bounds of the enclosing
- // block.
- GrowCurrentBeginItemVisualRect(visual_rect);
- }
+ void EndPaintOfPairedEnd();
// Called after all items are appended, to process the items.
void Finalize();
+ struct DirectlyCompositedImageResult {
+ gfx::Size intrinsic_image_size;
+ bool nearest_neighbor;
+ };
+
+ // If this list represents an image that should be directly composited (i.e.
+ // rasterized at the intrinsic size of the image), return the intrinsic size
+ // of the image and whether or not to use nearest neighbor filtering when
+ // scaling the layer.
+ base::Optional<DirectlyCompositedImageResult>
+ GetDirectlyCompositedImageResult(gfx::Size containing_layer_bounds) const;
+
int NumSlowPaths() const { return paint_op_buffer_.numSlowPaths(); }
bool HasNonAAPaint() const { return paint_op_buffer_.HasNonAAPaint(); }
@@ -200,6 +183,9 @@ class CC_PAINT_EXPORT DisplayItemList
std::string ToString() const;
bool has_draw_ops() const { return has_draw_ops_; }
+ // Ops with nested paint ops are considered as a single op.
+ size_t num_paint_ops() const { return paint_op_buffer_.size(); }
+
private:
friend class DisplayItemListTest;
friend gpu::raster::RasterImplementation;
@@ -217,8 +203,8 @@ class CC_PAINT_EXPORT DisplayItemList
// given visual rect with the begin display item's visual rect.
void GrowCurrentBeginItemVisualRect(const gfx::Rect& visual_rect) {
DCHECK_EQ(usage_hint_, kTopLevelDisplayItemList);
- if (!begin_paired_indices_.empty())
- visual_rects_[begin_paired_indices_.back().first].Union(visual_rect);
+ if (!paired_begin_stack_.empty())
+ visual_rects_[paired_begin_stack_.back().first_index].Union(visual_rect);
}
// RTree stores indices into the paint op buffer.
@@ -233,11 +219,15 @@ class CC_PAINT_EXPORT DisplayItemList
std::vector<gfx::Rect> visual_rects_;
// Byte offsets associated with each of the ops.
std::vector<size_t> offsets_;
- // A stack of pairs of indices and counts. The indices are into the
- // |visual_rects_| for each paired begin range that hasn't been closed. The
- // counts refer to the number of visual rects in that begin sequence that end
- // with the index.
- std::vector<std::pair<size_t, size_t>> begin_paired_indices_;
+ // A stack of paired begin sequences that haven't been closed.
+ struct PairedBeginInfo {
+ // Index (into virual_rects_ and offsets_) of the first operation in the
+ // paired begin sequence.
+ size_t first_index;
+ // Number of operations in the paired begin sequence.
+ size_t count;
+ };
+ std::vector<PairedBeginInfo> paired_begin_stack_;
#if DCHECK_IS_ON()
// While recording a range of ops, this is the position in the PaintOpBuffer
diff --git a/chromium/cc/paint/display_item_list_unittest.cc b/chromium/cc/paint/display_item_list_unittest.cc
index f15b5a63c16..a4dea57bbfb 100644
--- a/chromium/cc/paint/display_item_list_unittest.cc
+++ b/chromium/cc/paint/display_item_list_unittest.cc
@@ -1132,4 +1132,55 @@ TEST_F(DisplayItemListTest, TotalOpCount) {
EXPECT_EQ(8u, list->TotalOpCount());
}
+TEST_F(DisplayItemListTest, AreaOfDrawText) {
+ auto list = base::MakeRefCounted<DisplayItemList>();
+ auto sub_list = base::MakeRefCounted<DisplayItemList>();
+
+ auto text_blob1 = SkTextBlob::MakeFromString("ABCD", SkFont());
+ auto text_blob1_bounds = text_blob1->bounds();
+ auto text_blob1_area = text_blob1_bounds.width() * text_blob1_bounds.height();
+ auto text_blob2 = SkTextBlob::MakeFromString("EFG", SkFont());
+ auto text_blob2_bounds = text_blob2->bounds();
+ auto text_blob2_area = text_blob2_bounds.width() * text_blob2_bounds.height();
+
+ sub_list->StartPaint();
+ sub_list->push<DrawRectOp>(SkRect::MakeWH(100, 200), PaintFlags());
+ sub_list->push<DrawTextBlobOp>(text_blob1, 0, 0, PaintFlags());
+ sub_list->EndPaintOfUnpaired(gfx::Rect());
+ auto record = sub_list->ReleaseAsRecord();
+
+ list->StartPaint();
+ list->push<SaveOp>();
+ list->push<TranslateOp>(100, 100);
+ list->push<DrawRecordOp>(record);
+ list->push<RestoreOp>();
+ list->EndPaintOfUnpaired(gfx::Rect(100, 100, 100, 200));
+
+ list->StartPaint();
+ list->push<SaveOp>();
+ list->push<TranslateOp>(100, 400);
+ list->push<DrawRecordOp>(record);
+ list->push<RestoreOp>();
+ list->EndPaintOfUnpaired(gfx::Rect(100, 400, 100, 200));
+
+ list->StartPaint();
+ list->push<DrawRectOp>(SkRect::MakeWH(100, 100), PaintFlags());
+ list->push<DrawTextBlobOp>(text_blob2, 10, 20, PaintFlags());
+ list->EndPaintOfUnpaired(gfx::Rect(0, 0, 100, 100));
+
+ list->StartPaint();
+ list->push<DrawTextBlobOp>(text_blob2, 400, 100, PaintFlags());
+ list->push<DrawRectOp>(SkRect::MakeXYWH(400, 100, 100, 100), PaintFlags());
+ list->EndPaintOfUnpaired(gfx::Rect(400, 100, 100, 100));
+
+ list->Finalize();
+ // This includes the DrawTextBlobOp in the first DrawRecordOp the the first
+ // direct DrawTextBlobOp.
+ EXPECT_EQ(static_cast<int>(text_blob1_area + text_blob2_area),
+ static_cast<int>(list->AreaOfDrawText(gfx::Rect(0, 0, 200, 200))));
+ // This includes all DrawTextBlobOps.
+ EXPECT_EQ(static_cast<int>(text_blob1_area * 2 + text_blob2_area * 2),
+ static_cast<int>(list->AreaOfDrawText(gfx::Rect(0, 0, 500, 500))));
+}
+
} // namespace cc
diff --git a/chromium/cc/paint/element_id.h b/chromium/cc/paint/element_id.h
index b9e36acd592..a4108a13b37 100644
--- a/chromium/cc/paint/element_id.h
+++ b/chromium/cc/paint/element_id.h
@@ -12,7 +12,7 @@
#include <iosfwd>
#include <memory>
-#include "base/hash/hash.h"
+#include "base/check_op.h"
#include "cc/paint/paint_export.h"
namespace base {
diff --git a/chromium/cc/paint/image_transfer_cache_entry_unittest.cc b/chromium/cc/paint/image_transfer_cache_entry_unittest.cc
index 4c03a544e4f..24a334eedbb 100644
--- a/chromium/cc/paint/image_transfer_cache_entry_unittest.cc
+++ b/chromium/cc/paint/image_transfer_cache_entry_unittest.cc
@@ -10,8 +10,9 @@
#include <utility>
#include <vector>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
+#include "base/notreached.h"
#include "build/build_config.h"
#include "cc/paint/image_transfer_cache_entry.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/cc/paint/oop_pixeltest.cc b/chromium/cc/paint/oop_pixeltest.cc
index ea32f1f5e7b..6c9f1c1e192 100644
--- a/chromium/cc/paint/oop_pixeltest.cc
+++ b/chromium/cc/paint/oop_pixeltest.cc
@@ -33,6 +33,7 @@
#include "gpu/ipc/gl_in_process_context.h"
#include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkFontLCDConfig.h"
#include "third_party/skia/include/core/SkGraphics.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -162,7 +163,6 @@ class OopPixelTest : public testing::Test,
options.color_space,
PlaybackImageProvider::Settings());
- gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL();
int width = options.resource_size.width();
int height = options.resource_size.height();
@@ -209,6 +209,17 @@ class OopPixelTest : public testing::Test,
EXPECT_EQ(raster_implementation->GetError(),
static_cast<unsigned>(GL_NO_ERROR));
+ gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL();
+ SkBitmap result = ReadbackMailbox(gl, mailbox, options);
+ gpu::SyncToken sync_token;
+ gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ sii->DestroySharedImage(sync_token, mailbox);
+ return result;
+ }
+
+ SkBitmap ReadbackMailbox(gpu::gles2::GLES2Interface* gl,
+ const gpu::Mailbox& mailbox,
+ const RasterOptions& options) {
// Import the texture in gl, create an fbo and bind the texture to it.
GLuint gl_texture_id = gl->CreateAndConsumeTextureCHROMIUM(mailbox.name);
GLuint fbo_id;
@@ -218,6 +229,8 @@ class OopPixelTest : public testing::Test,
GL_TEXTURE_2D, gl_texture_id, 0);
// Read the data back.
+ int width = options.resource_size.width();
+ int height = options.resource_size.height();
std::unique_ptr<unsigned char[]> data(
new unsigned char[width * height * 4]);
gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.get());
@@ -225,11 +238,7 @@ class OopPixelTest : public testing::Test,
gl->DeleteTextures(1, &gl_texture_id);
gl->DeleteFramebuffers(1, &fbo_id);
- gpu::SyncToken sync_token;
- gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
- sii->DestroySharedImage(sync_token, mailbox);
-
- // Swizzle rgba->bgra if needed.
+ // Swizzle rgba->bgra
std::vector<SkPMColor> colors;
colors.reserve(width * height);
for (int h = 0; h < height; ++h) {
@@ -242,14 +251,26 @@ class OopPixelTest : public testing::Test,
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height);
- SkPixmap pixmap(SkImageInfo::MakeN32Premul(options.resource_size.width(),
- options.resource_size.height()),
- colors.data(),
- options.resource_size.width() * sizeof(SkColor));
+ SkPixmap pixmap(SkImageInfo::MakeN32Premul(width, height), colors.data(),
+ width * sizeof(SkColor));
bitmap.writePixels(pixmap);
return bitmap;
}
+ gpu::Mailbox CreateMailboxSharedImage(gpu::raster::RasterInterface* ri,
+ gpu::SharedImageInterface* sii,
+ const RasterOptions& options,
+ viz::ResourceFormat image_format) {
+ uint32_t flags = gpu::SHARED_IMAGE_USAGE_RASTER |
+ gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
+ gpu::Mailbox mailbox = sii->CreateSharedImage(
+ image_format, options.resource_size, options.color_space, flags);
+ EXPECT_TRUE(mailbox.Verify());
+ ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
+
+ return mailbox;
+ }
+
SkBitmap RasterExpectedBitmap(
scoped_refptr<DisplayItemList> display_item_list,
const gfx::Size& playback_size) {
@@ -1612,6 +1633,222 @@ TEST_F(OopPixelTest, DrawTextBlobPersistentShaderCache) {
ExpectEquals(actual, expected);
}
+TEST_F(OopPixelTest, WritePixels) {
+ gfx::Size dest_size(10, 10);
+ RasterOptions options(dest_size);
+ auto* ri = raster_context_provider_->RasterInterface();
+ auto* sii = raster_context_provider_->SharedImageInterface();
+ gpu::Mailbox dest_mailbox = CreateMailboxSharedImage(
+ ri, sii, options, viz::ResourceFormat::RGBA_8888);
+ std::vector<SkPMColor> expected_pixels(dest_size.width() * dest_size.height(),
+ SkPreMultiplyARGB(255, 0, 0, 255));
+ SkBitmap expected;
+ expected.installPixels(
+ SkImageInfo::MakeN32Premul(dest_size.width(), dest_size.height()),
+ expected_pixels.data(), dest_size.width() * sizeof(SkColor));
+
+ ri->WritePixels(dest_mailbox, 0, 0, 0, expected.info().minRowBytes(),
+ expected.info(), expected.getPixels());
+ ri->OrderingBarrierCHROMIUM();
+ EXPECT_EQ(ri->GetError(), static_cast<unsigned>(GL_NO_ERROR));
+
+ gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL();
+ SkBitmap actual = ReadbackMailbox(gl, dest_mailbox, options);
+ gpu::SyncToken sync_token;
+ gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ sii->DestroySharedImage(sync_token, dest_mailbox);
+ ExpectEquals(actual, expected);
+}
+
+namespace {
+void UploadPixels(gpu::gles2::GLES2Interface* gl,
+ const gpu::Mailbox& mailbox,
+ const gfx::Size& size,
+ GLenum format,
+ GLenum type,
+ const void* data) {
+ GLuint texture = gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name);
+ gl->BindTexture(GL_TEXTURE_2D, texture);
+ gl->TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.width(), size.height(), format,
+ type, data);
+ gl->BindTexture(GL_TEXTURE_2D, 0);
+ gl->DeleteTextures(1, &texture);
+}
+
+GrBackendTexture MakeBackendTexture(gpu::gles2::GLES2Interface* gl,
+ const gpu::Mailbox& mailbox,
+ gfx::Size size,
+ GLenum type) {
+ GrGLTextureInfo tex_info = {
+ GL_TEXTURE_2D, gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name),
+ type};
+ return GrBackendTexture(size.width(), size.height(), GrMipMapped::kNo,
+ tex_info);
+}
+} // namespace
+
+TEST_F(OopPixelTest, ConvertYUVToRGB) {
+ RasterOptions options(gfx::Size(16, 16));
+ RasterOptions uv_options(gfx::Size(options.resource_size.width() / 2,
+ options.resource_size.height() / 2));
+ auto* ri = raster_context_provider_->RasterInterface();
+ auto* sii = raster_context_provider_->SharedImageInterface();
+ gpu::Mailbox dest_mailbox = CreateMailboxSharedImage(
+ ri, sii, options, viz::ResourceFormat::RGBA_8888);
+ gpu::Mailbox y_mailbox = CreateMailboxSharedImage(
+ ri, sii, options, viz::ResourceFormat::LUMINANCE_8);
+ gpu::Mailbox u_mailbox = CreateMailboxSharedImage(
+ ri, sii, uv_options, viz::ResourceFormat::LUMINANCE_8);
+ gpu::Mailbox v_mailbox = CreateMailboxSharedImage(
+ ri, sii, uv_options, viz::ResourceFormat::LUMINANCE_8);
+
+ size_t y_pixels_size = options.resource_size.GetArea();
+ size_t uv_pixels_size = uv_options.resource_size.GetArea();
+ auto y_pix = std::make_unique<uint8_t[]>(y_pixels_size);
+ auto u_pix = std::make_unique<uint8_t[]>(uv_pixels_size);
+ auto v_pix = std::make_unique<uint8_t[]>(uv_pixels_size);
+
+ // Create a blue image
+ memset(y_pix.get(), 0x1d, y_pixels_size);
+ memset(u_pix.get(), 0xff, uv_pixels_size);
+ memset(v_pix.get(), 0x6b, uv_pixels_size);
+
+ // Upload initial yuv image data
+ gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL();
+ UploadPixels(gl, y_mailbox, options.resource_size, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE, y_pix.get());
+ UploadPixels(gl, u_mailbox, uv_options.resource_size, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE, u_pix.get());
+ UploadPixels(gl, v_mailbox, uv_options.resource_size, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE, v_pix.get());
+ gl->OrderingBarrierCHROMIUM();
+
+ ri->ConvertYUVMailboxesToRGB(dest_mailbox, kJPEG_SkYUVColorSpace, y_mailbox,
+ u_mailbox, v_mailbox);
+ ri->OrderingBarrierCHROMIUM();
+ SkBitmap actual_bitmap = ReadbackMailbox(gl, dest_mailbox, options);
+
+ // Create the expected result using SkImage::MakeFromYUVTextures
+ GrBackendTexture backend_textures[3];
+ backend_textures[0] = MakeBackendTexture(gl, y_mailbox, options.resource_size,
+ GL_LUMINANCE8_EXT);
+ backend_textures[1] = MakeBackendTexture(
+ gl, u_mailbox, uv_options.resource_size, GL_LUMINANCE8_EXT);
+ backend_textures[2] = MakeBackendTexture(
+ gl, v_mailbox, uv_options.resource_size, GL_LUMINANCE8_EXT);
+
+ SkYUVAIndex yuva_indices[4];
+ yuva_indices[SkYUVAIndex::kY_Index] = {0, SkColorChannel::kR};
+ yuva_indices[SkYUVAIndex::kU_Index] = {1, SkColorChannel::kR};
+ yuva_indices[SkYUVAIndex::kV_Index] = {2, SkColorChannel::kR};
+ yuva_indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kA};
+
+ auto expected_image = SkImage::MakeFromYUVATextures(
+ gles2_context_provider_->GrContext(), kJPEG_SkYUVColorSpace,
+ backend_textures, yuva_indices,
+ {options.resource_size.width(), options.resource_size.height()},
+ kTopLeft_GrSurfaceOrigin, nullptr);
+
+ SkBitmap expected_bitmap;
+ expected_bitmap.allocN32Pixels(options.resource_size.width(),
+ options.resource_size.height());
+ expected_image->readPixels(expected_bitmap.pixmap(), 0, 0);
+ ExpectEquals(actual_bitmap, expected_bitmap);
+
+ for (auto& backend : backend_textures) {
+ GrGLTextureInfo info;
+ if (backend.getGLTextureInfo(&info))
+ gl->DeleteTextures(1, &info.fID);
+ }
+
+ gpu::SyncToken sync_token;
+ gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ sii->DestroySharedImage(sync_token, dest_mailbox);
+ sii->DestroySharedImage(sync_token, y_mailbox);
+ sii->DestroySharedImage(sync_token, u_mailbox);
+ sii->DestroySharedImage(sync_token, v_mailbox);
+}
+
+// A workaround on Android that forces the use of GLES 2.0 instead of 3.0
+// prevents the use of the GL_RG textures required for NV12 format. This
+// test will be reactiviated on Android once the workaround is removed.
+#ifndef OS_ANDROID
+TEST_F(OopPixelTest, ConvertNV12ToRGB) {
+ RasterOptions options(gfx::Size(16, 16));
+ RasterOptions uv_options(gfx::Size(options.resource_size.width() / 2,
+ options.resource_size.height() / 2));
+ auto* ri = raster_context_provider_->RasterInterface();
+ auto* sii = raster_context_provider_->SharedImageInterface();
+
+ gpu::Mailbox dest_mailbox = CreateMailboxSharedImage(
+ ri, sii, options, viz::ResourceFormat::RGBA_8888);
+ gpu::Mailbox y_mailbox = CreateMailboxSharedImage(
+ ri, sii, options, viz::ResourceFormat::LUMINANCE_8);
+ gpu::Mailbox uv_mailbox =
+ CreateMailboxSharedImage(ri, sii, uv_options, viz::ResourceFormat::RG_88);
+
+ size_t y_pixels_size = options.resource_size.GetArea();
+ size_t uv_pixels_size = uv_options.resource_size.GetArea() * 2;
+ auto y_pix = std::make_unique<uint8_t[]>(y_pixels_size);
+ auto uv_pix = std::make_unique<uint8_t[]>(uv_pixels_size);
+
+ memset(y_pix.get(), 0x1d, y_pixels_size);
+ for (size_t i = 0; i < uv_pixels_size; i += 2) {
+ uv_pix[i] = 0xff;
+ uv_pix[i + 1] = 0x6d;
+ }
+
+ gpu::gles2::GLES2Interface* gl = gles2_context_provider_->ContextGL();
+ UploadPixels(gl, y_mailbox, options.resource_size, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE, y_pix.get());
+ UploadPixels(gl, uv_mailbox, uv_options.resource_size, GL_RG,
+ GL_UNSIGNED_BYTE, uv_pix.get());
+ gl->OrderingBarrierCHROMIUM();
+
+ ri->ConvertNV12MailboxesToRGB(dest_mailbox, kJPEG_SkYUVColorSpace, y_mailbox,
+ uv_mailbox);
+ ri->OrderingBarrierCHROMIUM();
+ SkBitmap actual_bitmap = ReadbackMailbox(gl, dest_mailbox, options);
+
+ // Create the expected result using SkImage::MakeFromYUVTextures
+ GrBackendTexture backend_textures[2];
+ backend_textures[0] = MakeBackendTexture(gl, y_mailbox, options.resource_size,
+ GL_LUMINANCE8_EXT);
+ backend_textures[1] =
+ MakeBackendTexture(gl, uv_mailbox, uv_options.resource_size, GL_RG8);
+
+ SkYUVAIndex yuva_indices[4];
+ yuva_indices[SkYUVAIndex::kY_Index] = {0, SkColorChannel::kR};
+ yuva_indices[SkYUVAIndex::kU_Index] = {1, SkColorChannel::kR};
+ yuva_indices[SkYUVAIndex::kV_Index] = {1, SkColorChannel::kG};
+ yuva_indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kA};
+
+ auto expected_image = SkImage::MakeFromYUVATextures(
+ gles2_context_provider_->GrContext(), kJPEG_SkYUVColorSpace,
+ backend_textures, yuva_indices,
+ {options.resource_size.width(), options.resource_size.height()},
+ kTopLeft_GrSurfaceOrigin, nullptr);
+
+ SkBitmap expected_bitmap;
+ expected_bitmap.allocN32Pixels(options.resource_size.width(),
+ options.resource_size.height());
+ expected_image->readPixels(expected_bitmap.pixmap(), 0, 0);
+ ExpectEquals(actual_bitmap, expected_bitmap);
+
+ for (auto& backend : backend_textures) {
+ GrGLTextureInfo info;
+ if (backend.getGLTextureInfo(&info))
+ gl->DeleteTextures(1, &info.fID);
+ }
+
+ gpu::SyncToken sync_token;
+ gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ sii->DestroySharedImage(sync_token, dest_mailbox);
+ sii->DestroySharedImage(sync_token, y_mailbox);
+ sii->DestroySharedImage(sync_token, uv_mailbox);
+}
+#endif // OS_ANDROID
+
class OopPathPixelTest : public OopPixelTest,
public ::testing::WithParamInterface<bool> {
public:
diff --git a/chromium/cc/paint/paint_cache.cc b/chromium/cc/paint/paint_cache.cc
index 35b3882be39..b75a938d19a 100644
--- a/chromium/cc/paint/paint_cache.cc
+++ b/chromium/cc/paint/paint_cache.cc
@@ -4,8 +4,10 @@
#include "cc/paint/paint_cache.h"
+#include "base/check_op.h"
#include "base/containers/flat_set.h"
#include "base/no_destructor.h"
+#include "base/notreached.h"
#include "base/synchronization/lock.h"
namespace cc {
@@ -21,6 +23,8 @@ void EraseFromMap(T* map, size_t n, const volatile PaintCacheId* ids) {
} // namespace
+constexpr size_t ClientPaintCache::kNoCachingBudget;
+
ClientPaintCache::ClientPaintCache(size_t max_budget_bytes)
: cache_map_(CacheMap::NO_AUTO_EVICT), max_budget_(max_budget_bytes) {}
ClientPaintCache::~ClientPaintCache() = default;
@@ -32,6 +36,8 @@ bool ClientPaintCache::Get(PaintCacheDataType type, PaintCacheId id) {
void ClientPaintCache::Put(PaintCacheDataType type,
PaintCacheId id,
size_t size) {
+ if (max_budget_ == kNoCachingBudget)
+ return;
auto key = std::make_pair(type, id);
DCHECK(cache_map_.Peek(key) == cache_map_.end());
diff --git a/chromium/cc/paint/paint_cache.h b/chromium/cc/paint/paint_cache.h
index 89f9274cf98..728df5a36f3 100644
--- a/chromium/cc/paint/paint_cache.h
+++ b/chromium/cc/paint/paint_cache.h
@@ -49,6 +49,11 @@ constexpr size_t PaintCacheDataTypeCount =
class CC_PAINT_EXPORT ClientPaintCache {
public:
+ // If ClientPaintCache is constructed with a max_budget_bytes of
+ // kNoCachingBudget, its Put() method becomes a no-op, rendering the instance
+ // a no-op instance.
+ static constexpr size_t kNoCachingBudget = 0u;
+
explicit ClientPaintCache(size_t max_budget_bytes);
ClientPaintCache(const ClientPaintCache&) = delete;
~ClientPaintCache();
diff --git a/chromium/cc/paint/paint_filter.cc b/chromium/cc/paint/paint_filter.cc
index de15aaa7e26..279258b26b7 100644
--- a/chromium/cc/paint/paint_filter.cc
+++ b/chromium/cc/paint/paint_filter.cc
@@ -801,8 +801,8 @@ bool MergePaintFilter::operator==(const MergePaintFilter& other) const {
}
MorphologyPaintFilter::MorphologyPaintFilter(MorphType morph_type,
- int radius_x,
- int radius_y,
+ float radius_x,
+ float radius_y,
sk_sp<PaintFilter> input,
const CropRect* crop_rect)
: PaintFilter(kType, crop_rect, HasDiscardableImages(input)),
diff --git a/chromium/cc/paint/paint_filter.h b/chromium/cc/paint/paint_filter.h
index bdf724ab1e2..cec36ef7c6a 100644
--- a/chromium/cc/paint/paint_filter.h
+++ b/chromium/cc/paint/paint_filter.h
@@ -557,15 +557,15 @@ class CC_PAINT_EXPORT MorphologyPaintFilter final : public PaintFilter {
enum class MorphType : uint32_t { kDilate, kErode, kMaxMorphType = kErode };
static constexpr Type kType = Type::kMorphology;
MorphologyPaintFilter(MorphType morph_type,
- int radius_x,
- int radius_y,
+ float radius_x,
+ float radius_y,
sk_sp<PaintFilter> input,
const CropRect* crop_rect = nullptr);
~MorphologyPaintFilter() override;
MorphType morph_type() const { return morph_type_; }
- int radius_x() const { return radius_x_; }
- int radius_y() const { return radius_y_; }
+ float radius_x() const { return radius_x_; }
+ float radius_y() const { return radius_y_; }
const sk_sp<PaintFilter>& input() const { return input_; }
size_t SerializedSize() const override;
@@ -577,8 +577,8 @@ class CC_PAINT_EXPORT MorphologyPaintFilter final : public PaintFilter {
private:
MorphType morph_type_;
- int radius_x_;
- int radius_y_;
+ float radius_x_;
+ float radius_y_;
sk_sp<PaintFilter> input_;
};
diff --git a/chromium/cc/paint/paint_image.cc b/chromium/cc/paint/paint_image.cc
index be183635641..86deeddd70f 100644
--- a/chromium/cc/paint/paint_image.cc
+++ b/chromium/cc/paint/paint_image.cc
@@ -152,6 +152,8 @@ void PaintImage::CreateSkImage() {
SkImage::MakeFromGenerator(std::make_unique<SkiaPaintImageGenerator>(
paint_image_generator_, kDefaultFrameIndex,
kDefaultGeneratorClientId));
+ } else if (texture_backing_) {
+ cached_sk_image_ = texture_backing_->GetAcceleratedSkImage();
}
if (!subset_rect_.IsEmpty() && cached_sk_image_) {
@@ -278,6 +280,14 @@ SkColorType PaintImage::GetColorType() const {
return kUnknown_SkColorType;
}
+SkAlphaType PaintImage::GetAlphaType() const {
+ if (paint_image_generator_)
+ return paint_image_generator_->GetSkImageInfo().alphaType();
+ if (GetSkImage())
+ return GetSkImage()->alphaType();
+ return kUnknown_SkAlphaType;
+}
+
int PaintImage::width() const {
return paint_worklet_input_
? static_cast<int>(paint_worklet_input_->GetSize().width())
diff --git a/chromium/cc/paint/paint_image.h b/chromium/cc/paint/paint_image.h
index e7d38dddcb3..95881204e0a 100644
--- a/chromium/cc/paint/paint_image.h
+++ b/chromium/cc/paint/paint_image.h
@@ -25,9 +25,10 @@ namespace cc {
class PaintImageGenerator;
class PaintOpBuffer;
class PaintWorkletInput;
+class TextureBacking;
using PaintRecord = PaintOpBuffer;
-enum class ImageType { kPNG, kJPEG, kWEBP, kGIF, kICO, kBMP, kInvalid };
+enum class ImageType { kPNG, kJPEG, kWEBP, kGIF, kICO, kBMP, kAVIF, kInvalid };
enum class YUVSubsampling { k410, k411, k420, k422, k440, k444, kUnknown };
@@ -271,8 +272,9 @@ class CC_PAINT_EXPORT PaintImage {
SkYUVAIndex* plane_indices = nullptr,
SkYUVColorSpace* yuv_color_space = nullptr) const;
- // Returns the color type of this image.
+ // Get metadata associated with this image.
SkColorType GetColorType() const;
+ SkAlphaType GetAlphaType() const;
// Returns general information about the underlying image. Returns nullptr if
// there is no available |paint_image_generator_|.
@@ -333,6 +335,7 @@ class CC_PAINT_EXPORT PaintImage {
ContentId content_id_ = kInvalidContentId;
sk_sp<PaintImageGenerator> paint_image_generator_;
+ sk_sp<TextureBacking> texture_backing_;
Id id_ = 0;
AnimationType animation_type_ = AnimationType::STATIC;
diff --git a/chromium/cc/paint/paint_image_builder.h b/chromium/cc/paint/paint_image_builder.h
index b7b389962af..25a20bf1a9c 100644
--- a/chromium/cc/paint/paint_image_builder.h
+++ b/chromium/cc/paint/paint_image_builder.h
@@ -11,6 +11,7 @@
#include "cc/paint/paint_op_buffer.h"
#include "cc/paint/paint_worklet_input.h"
#include "cc/paint/skia_paint_image_generator.h"
+#include "cc/paint/texture_backing.h"
#include "third_party/skia/include/core/SkImage.h"
namespace cc {
@@ -104,6 +105,12 @@ class CC_PAINT_EXPORT PaintImageBuilder {
paint_image_.paint_worklet_input_ = std::move(input);
return std::move(*this);
}
+ PaintImageBuilder&& set_texture_backing(sk_sp<TextureBacking> texture_backing,
+ PaintImage::ContentId content_id) {
+ paint_image_.texture_backing_ = std::move(texture_backing);
+ paint_image_.content_id_ = content_id;
+ return std::move(*this);
+ }
PaintImage TakePaintImage();
diff --git a/chromium/cc/paint/paint_image_generator.cc b/chromium/cc/paint/paint_image_generator.cc
index 740808e21e1..6ceae174db3 100644
--- a/chromium/cc/paint/paint_image_generator.cc
+++ b/chromium/cc/paint/paint_image_generator.cc
@@ -7,7 +7,6 @@
#include "cc/paint/paint_image_generator.h"
#include "base/atomic_sequence_num.h"
-#include "base/logging.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkSize.h"
diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc
index 6417c049cde..51955bcf32f 100644
--- a/chromium/cc/paint/paint_op_buffer.cc
+++ b/chromium/cc/paint/paint_op_buffer.cc
@@ -1310,7 +1310,6 @@ void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params) {
- SkPaint paint = flags ? flags->ToSkPaint() : SkPaint();
// TODO(crbug.com/931704): make sure to support the case where paint worklet
// generated images are used in other raster work such as canvas2d.
if (op->image.IsPaintWorklet()) {
@@ -1322,6 +1321,11 @@ void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op,
ImageProvider::ScopedResult result =
params.image_provider->GetRasterContent(DrawImage(op->image));
+ // Check that we are not using loopers with paint worklets, since converting
+ // PaintFlags to SkPaint drops loopers.
+ DCHECK(!flags->getLooper());
+ SkPaint paint = flags ? flags->ToSkPaint() : SkPaint();
+
DCHECK(IsScaleAdjustmentIdentity(op->scale_adjustment));
SkAutoCanvasRestore save_restore(canvas, true);
canvas->concat(
@@ -1344,8 +1348,11 @@ void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op,
if (!params.image_provider) {
SkRect adjusted_src = AdjustSrcRectForScale(op->src, op->scale_adjustment);
- canvas->drawImageRect(op->image.GetSkImage().get(), adjusted_src, op->dst,
- &paint, skconstraint);
+ flags->DrawToSk(canvas, [op, adjusted_src, skconstraint](SkCanvas* c,
+ const SkPaint& p) {
+ c->drawImageRect(op->image.GetSkImage().get(), adjusted_src, op->dst, &p,
+ skconstraint);
+ });
return;
}
@@ -1374,9 +1381,13 @@ void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op,
op->src.makeOffset(decoded_image.src_rect_offset().width(),
decoded_image.src_rect_offset().height());
adjusted_src = AdjustSrcRectForScale(adjusted_src, scale_adjustment);
- paint.setFilterQuality(decoded_image.filter_quality());
- canvas->drawImageRect(decoded_image.image().get(), adjusted_src, op->dst,
- &paint, skconstraint);
+ flags->DrawToSk(canvas, [op, &decoded_image, adjusted_src, skconstraint](
+ SkCanvas* c, const SkPaint& p) {
+ SkPaint paint_with_filter_quality(p);
+ paint_with_filter_quality.setFilterQuality(decoded_image.filter_quality());
+ c->drawImageRect(decoded_image.image().get(), adjusted_src, op->dst,
+ &paint_with_filter_quality, skconstraint);
+ });
}
void DrawIRectOp::RasterWithFlags(const DrawIRectOp* op,
@@ -1992,7 +2003,6 @@ void PaintOp::Raster(SkCanvas* canvas, const PlaybackParams& params) const {
size_t PaintOp::Serialize(void* memory,
size_t size,
const SerializeOptions& options) const {
- DCHECK(options.transfer_cache);
DCHECK(options.canvas);
// Need at least enough room for a skip/type header.
diff --git a/chromium/cc/paint/paint_op_buffer_unittest.cc b/chromium/cc/paint/paint_op_buffer_unittest.cc
index f340389e168..7a2861e76a7 100644
--- a/chromium/cc/paint/paint_op_buffer_unittest.cc
+++ b/chromium/cc/paint/paint_op_buffer_unittest.cc
@@ -3132,6 +3132,56 @@ TEST(PaintOpBufferTest, ReplacesImagesFromProvider) {
buffer.Playback(&canvas, PlaybackParams(&image_provider));
}
+TEST(PaintOpBufferTest, DrawImageRectOpWithLooperNoImageProvider) {
+ PaintOpBuffer buffer;
+ PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
+ SkLayerDrawLooper::Builder sk_draw_looper_builder;
+ sk_draw_looper_builder.addLayer(20.0, 20.0);
+ SkLayerDrawLooper::LayerInfo info_unmodified;
+ sk_draw_looper_builder.addLayerOnTop(info_unmodified);
+
+ PaintFlags paint_flags;
+ paint_flags.setLooper(sk_draw_looper_builder.detach());
+ buffer.push<DrawImageRectOp>(
+ image, SkRect::MakeWH(100, 100), SkRect::MakeWH(100, 100), &paint_flags,
+ PaintCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
+
+ testing::StrictMock<MockCanvas> canvas;
+ EXPECT_CALL(canvas, willSave);
+ EXPECT_CALL(canvas, didTranslate);
+ EXPECT_CALL(canvas, willRestore);
+ EXPECT_CALL(canvas, onDrawImageRect).Times(2);
+
+ buffer.Playback(&canvas, PlaybackParams(nullptr));
+}
+
+TEST(PaintOpBufferTest, DrawImageRectOpWithLooperWithImageProvider) {
+ PaintOpBuffer buffer;
+ PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
+ SkLayerDrawLooper::Builder sk_draw_looper_builder;
+ sk_draw_looper_builder.addLayer(20.0, 20.0);
+ SkLayerDrawLooper::LayerInfo info_unmodified;
+ sk_draw_looper_builder.addLayerOnTop(info_unmodified);
+
+ PaintFlags paint_flags;
+ paint_flags.setLooper(sk_draw_looper_builder.detach());
+ buffer.push<DrawImageRectOp>(
+ image, SkRect::MakeWH(100, 100), SkRect::MakeWH(100, 100), &paint_flags,
+ PaintCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
+
+ testing::StrictMock<MockCanvas> canvas;
+ EXPECT_CALL(canvas, willSave);
+ EXPECT_CALL(canvas, didTranslate);
+ EXPECT_CALL(canvas, willRestore);
+ EXPECT_CALL(canvas, onDrawImageRect).Times(2);
+
+ std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
+ std::vector<SkSize> scale_adjustment = {SkSize::Make(1.0f, 1.0f)};
+ std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality};
+ MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
+ buffer.Playback(&canvas, PlaybackParams(&image_provider));
+}
+
TEST(PaintOpBufferTest, ReplacesImagesFromProviderOOP) {
PaintOpBuffer buffer;
SkSize expected_scale = SkSize::Make(0.2f, 0.5f);
@@ -3221,7 +3271,7 @@ TEST_P(PaintFilterSerializationTest, Basic) {
SkMatrixConvolutionImageFilter::kClampToBlack_TileMode, true,
nullptr)},
sk_sp<PaintFilter>{new MorphologyPaintFilter(
- MorphologyPaintFilter::MorphType::kErode, 15, 30, nullptr)},
+ MorphologyPaintFilter::MorphType::kErode, 15.5f, 30.2f, nullptr)},
sk_sp<PaintFilter>{new OffsetPaintFilter(-1.f, -2.f, nullptr)},
sk_sp<PaintFilter>{new TilePaintFilter(
SkRect::MakeXYWH(1, 2, 3, 4), SkRect::MakeXYWH(4, 3, 2, 1), nullptr)},
diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc
index 078b528e6e1..5118c0f814a 100644
--- a/chromium/cc/paint/paint_op_reader.cc
+++ b/chromium/cc/paint/paint_op_reader.cc
@@ -1103,8 +1103,8 @@ void PaintOpReader::ReadMorphologyPaintFilter(
sk_sp<PaintFilter>* filter,
const base::Optional<PaintFilter::CropRect>& crop_rect) {
uint32_t morph_type_int = 0;
- int radius_x = 0;
- int radius_y = 0;
+ float radius_x = 0;
+ float radius_y = 0;
sk_sp<PaintFilter> input;
Read(&morph_type_int);
Read(&radius_x);
diff --git a/chromium/cc/paint/paint_recorder.cc b/chromium/cc/paint/paint_recorder.cc
index 1fb95143f49..cded3e21e40 100644
--- a/chromium/cc/paint/paint_recorder.cc
+++ b/chromium/cc/paint/paint_recorder.cc
@@ -51,4 +51,8 @@ bool PaintRecorder::ListHasDrawOps() const {
return display_item_list_->has_draw_ops();
}
+size_t PaintRecorder::num_paint_ops() const {
+ return display_item_list_->num_paint_ops();
+}
+
} // namespace cc
diff --git a/chromium/cc/paint/paint_recorder.h b/chromium/cc/paint/paint_recorder.h
index 6beb024c236..5195835342b 100644
--- a/chromium/cc/paint/paint_recorder.h
+++ b/chromium/cc/paint/paint_recorder.h
@@ -39,6 +39,9 @@ class CC_PAINT_EXPORT PaintRecorder {
bool ListHasDrawOps() const;
+ // Ops with nested paint ops are considered as a single op.
+ size_t num_paint_ops() const;
+
protected:
virtual std::unique_ptr<RecordPaintCanvas> CreateCanvas(DisplayItemList* list,
const SkRect& bounds);
diff --git a/chromium/cc/paint/shader_transfer_cache_entry.cc b/chromium/cc/paint/shader_transfer_cache_entry.cc
index dc184f6e84d..fda25bd40ef 100644
--- a/chromium/cc/paint/shader_transfer_cache_entry.cc
+++ b/chromium/cc/paint/shader_transfer_cache_entry.cc
@@ -4,6 +4,8 @@
#include "cc/paint/shader_transfer_cache_entry.h"
+#include "base/notreached.h"
+
namespace cc {
ServiceShaderTransferCacheEntry::ServiceShaderTransferCacheEntry(
diff --git a/chromium/cc/paint/texture_backing.h b/chromium/cc/paint/texture_backing.h
index feadf9a194e..51055d27b29 100644
--- a/chromium/cc/paint/texture_backing.h
+++ b/chromium/cc/paint/texture_backing.h
@@ -10,7 +10,7 @@
#include "third_party/skia/include/core/SkImageInfo.h"
namespace gpu {
-class Mailbox;
+struct Mailbox;
} // namespace gpu
namespace cc {
@@ -19,6 +19,7 @@ namespace cc {
// This class must be created, used and destroyed on the same thread.
class CC_PAINT_EXPORT TextureBacking : public SkRefCnt {
public:
+ TextureBacking() = default;
TextureBacking(const TextureBacking&) = delete;
~TextureBacking() override = default;
diff --git a/chromium/cc/paint/transfer_cache_entry.cc b/chromium/cc/paint/transfer_cache_entry.cc
index 47d4ae2d76b..e192ed1cce1 100644
--- a/chromium/cc/paint/transfer_cache_entry.cc
+++ b/chromium/cc/paint/transfer_cache_entry.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/logging.h"
+#include "base/notreached.h"
#include "cc/paint/image_transfer_cache_entry.h"
#include "cc/paint/raw_memory_transfer_cache_entry.h"
#include "cc/paint/shader_transfer_cache_entry.h"
diff --git a/chromium/cc/paint/transfer_cache_serialize_helper.cc b/chromium/cc/paint/transfer_cache_serialize_helper.cc
index 7a59ca0d197..28ca6675a26 100644
--- a/chromium/cc/paint/transfer_cache_serialize_helper.cc
+++ b/chromium/cc/paint/transfer_cache_serialize_helper.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "base/logging.h"
+#include "base/check_op.h"
namespace cc {
diff --git a/chromium/cc/raster/lcd_text_disallowed_reason.cc b/chromium/cc/raster/lcd_text_disallowed_reason.cc
new file mode 100644
index 00000000000..2bfffcc8b62
--- /dev/null
+++ b/chromium/cc/raster/lcd_text_disallowed_reason.cc
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/raster/lcd_text_disallowed_reason.h"
+
+#include <iostream>
+#include "base/notreached.h"
+
+namespace cc {
+
+const char* LCDTextDisallowedReasonToString(LCDTextDisallowedReason reason) {
+ switch (reason) {
+ case LCDTextDisallowedReason::kNone:
+ return "none";
+ case LCDTextDisallowedReason::kSetting:
+ return "setting";
+ case LCDTextDisallowedReason::kBackgroundColorNotOpaque:
+ return "background-color-not-opaque";
+ case LCDTextDisallowedReason::kContentsNotOpaque:
+ return "contents-not-opaque";
+ case LCDTextDisallowedReason::kNonIntegralTranslation:
+ return "non-integral-translation";
+ case LCDTextDisallowedReason::kNonIntegralXOffset:
+ return "non-integral-x-offset";
+ case LCDTextDisallowedReason::kNonIntegralYOffset:
+ return "non-integral-y-offset";
+ case LCDTextDisallowedReason::kWillChangeTransform:
+ return "will-change-transform";
+ }
+ NOTREACHED();
+ return "";
+}
+
+std::ostream& operator<<(std::ostream& os, LCDTextDisallowedReason reason) {
+ return os << LCDTextDisallowedReasonToString(reason);
+}
+
+} // namespace cc
diff --git a/chromium/cc/raster/lcd_text_disallowed_reason.h b/chromium/cc/raster/lcd_text_disallowed_reason.h
new file mode 100644
index 00000000000..024b974d4ce
--- /dev/null
+++ b/chromium/cc/raster/lcd_text_disallowed_reason.h
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RASTER_LCD_TEXT_DISALLOWED_REASON_H_
+#define CC_RASTER_LCD_TEXT_DISALLOWED_REASON_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <iosfwd>
+
+#include "cc/cc_export.h"
+
+namespace cc {
+
+// These values are used in UMA and benchmarks. Entries should not be renumbered
+// and numeric values should never be reused.
+enum class LCDTextDisallowedReason : uint8_t {
+ kNone = 0,
+ kSetting = 1,
+ kBackgroundColorNotOpaque = 2,
+ kContentsNotOpaque = 3,
+ kNonIntegralTranslation = 4,
+ kNonIntegralXOffset = 5,
+ kNonIntegralYOffset = 6,
+ kWillChangeTransform = 7,
+ kMaxValue = kWillChangeTransform,
+};
+constexpr size_t kLCDTextDisallowedReasonCount =
+ static_cast<size_t>(LCDTextDisallowedReason::kMaxValue) + 1;
+CC_EXPORT const char* LCDTextDisallowedReasonToString(LCDTextDisallowedReason);
+
+CC_EXPORT std::ostream& operator<<(std::ostream&, LCDTextDisallowedReason);
+
+} // namespace cc
+
+#endif // CC_RASTER_LCD_TEXT_DISALLOWED_REASON_H_
diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc
index 28b44791fef..bee4146a7cd 100644
--- a/chromium/cc/raster/raster_buffer_provider_unittest.cc
+++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc
@@ -17,10 +17,11 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/cancelable_callback.h"
+#include "base/check.h"
#include "base/location.h"
-#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_base.h"
+#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
diff --git a/chromium/cc/raster/raster_source.cc b/chromium/cc/raster/raster_source.cc
index 58d7ea0b03f..99d6d88018a 100644
--- a/chromium/cc/raster/raster_source.cc
+++ b/chromium/cc/raster/raster_source.cc
@@ -16,11 +16,11 @@
#include "cc/paint/skia_paint_canvas.h"
#include "components/viz/common/traced_value.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect_conversions.h"
namespace cc {
+
RasterSource::RasterSource(const RecordingSource* other)
: display_list_(other->display_list_),
painter_reported_memory_usage_(other->painter_reported_memory_usage_),
@@ -33,6 +33,7 @@ RasterSource::RasterSource(const RecordingSource* other)
slow_down_raster_scale_factor_for_debug_(
other->slow_down_raster_scale_factor_for_debug_),
recording_scale_factor_(other->recording_scale_factor_) {}
+
RasterSource::~RasterSource() = default;
void RasterSource::ClearForOpaqueRaster(
@@ -146,19 +147,6 @@ void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
display_list_->Raster(raster_canvas, image_provider);
}
-sk_sp<SkPicture> RasterSource::GetFlattenedPicture() {
- TRACE_EVENT0("cc", "RasterSource::GetFlattenedPicture");
-
- SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(size_.width(), size_.height());
- if (!size_.IsEmpty()) {
- canvas->clear(SK_ColorTRANSPARENT);
- PlaybackToCanvas(canvas, nullptr);
- }
-
- return recorder.finishRecordingAsPicture();
-}
-
size_t RasterSource::GetMemoryUsage() const {
if (!display_list_)
return 0;
diff --git a/chromium/cc/raster/raster_source.h b/chromium/cc/raster/raster_source.h
index c0686dea5d5..7a70742f127 100644
--- a/chromium/cc/raster/raster_source.h
+++ b/chromium/cc/raster/raster_source.h
@@ -109,7 +109,6 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
// Tracing functionality.
void DidBeginTracing();
void AsValueInto(base::trace_event::TracedValue* array) const;
- sk_sp<SkPicture> GetFlattenedPicture();
size_t GetMemoryUsage() const;
const scoped_refptr<DisplayItemList>& GetDisplayItemList() const {
diff --git a/chromium/cc/raster/raster_source_unittest.cc b/chromium/cc/raster/raster_source_unittest.cc
index d21339b63a2..41ee8c0b387 100644
--- a/chromium/cc/raster/raster_source_unittest.cc
+++ b/chromium/cc/raster/raster_source_unittest.cc
@@ -254,7 +254,6 @@ TEST(RasterSourceTest, RasterFullContents) {
std::unique_ptr<FakeRecordingSource> recording_source =
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
recording_source->SetBackgroundColor(SK_ColorBLACK);
- recording_source->SetClearCanvasWithDebugColor(false);
// Because the caller sets content opaque, it also promises that it
// has at least filled in layer_bounds opaquely.
@@ -320,7 +319,6 @@ TEST(RasterSourceTest, RasterPartialContents) {
std::unique_ptr<FakeRecordingSource> recording_source =
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
recording_source->SetBackgroundColor(SK_ColorGREEN);
- recording_source->SetClearCanvasWithDebugColor(false);
// First record everything as white.
PaintFlags white_flags;
@@ -415,7 +413,6 @@ TEST(RasterSourceTest, RasterPartialClear) {
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
recording_source->SetBackgroundColor(SK_ColorGREEN);
recording_source->SetRequiresClear(true);
- recording_source->SetClearCanvasWithDebugColor(false);
// First record everything as white.
const unsigned alpha_dark = 10u;
@@ -462,7 +459,6 @@ TEST(RasterSourceTest, RasterPartialClear) {
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
recording_source_light->SetBackgroundColor(SK_ColorGREEN);
recording_source_light->SetRequiresClear(true);
- recording_source_light->SetClearCanvasWithDebugColor(false);
// Record everything as a slightly lighter white.
const unsigned alpha_light = 18u;
@@ -506,7 +502,6 @@ TEST(RasterSourceTest, RasterContentsTransparent) {
FakeRecordingSource::CreateFilledRecordingSource(layer_bounds);
recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
recording_source->SetRequiresClear(true);
- recording_source->SetClearCanvasWithDebugColor(false);
recording_source->Rerecord();
scoped_refptr<RasterSource> raster = recording_source->CreateRasterSource();
diff --git a/chromium/cc/raster/task.cc b/chromium/cc/raster/task.cc
index 415b8dbc0f6..5a34ca86ad2 100644
--- a/chromium/cc/raster/task.cc
+++ b/chromium/cc/raster/task.cc
@@ -4,7 +4,8 @@
#include "cc/raster/task.h"
-#include "base/logging.h"
+#include "base/check.h"
+#include "base/notreached.h"
namespace cc {
diff --git a/chromium/cc/raster/tile_task.cc b/chromium/cc/raster/tile_task.cc
index d731433c2c0..052a6b06b70 100644
--- a/chromium/cc/raster/tile_task.cc
+++ b/chromium/cc/raster/tile_task.cc
@@ -4,7 +4,7 @@
#include "cc/raster/tile_task.h"
-#include "base/logging.h"
+#include "base/check.h"
namespace cc {
diff --git a/chromium/cc/resources/ui_resource_bitmap.cc b/chromium/cc/resources/ui_resource_bitmap.cc
index c21048553fa..974706def78 100644
--- a/chromium/cc/resources/ui_resource_bitmap.cc
+++ b/chromium/cc/resources/ui_resource_bitmap.cc
@@ -8,7 +8,8 @@
#include <memory>
-#include "base/logging.h"
+#include "base/check_op.h"
+#include "base/notreached.h"
#include "base/numerics/checked_math.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
diff --git a/chromium/cc/scheduler/begin_frame_tracker.cc b/chromium/cc/scheduler/begin_frame_tracker.cc
index fe8f84012ad..0480a2c24b2 100644
--- a/chromium/cc/scheduler/begin_frame_tracker.cc
+++ b/chromium/cc/scheduler/begin_frame_tracker.cc
@@ -16,7 +16,7 @@ BeginFrameTracker::BeginFrameTracker(const base::Location& location)
BeginFrameTracker::~BeginFrameTracker() = default;
-void BeginFrameTracker::Start(viz::BeginFrameArgs new_args) {
+void BeginFrameTracker::Start(const viz::BeginFrameArgs& new_args) {
// Trace the frame time being passed between BeginFrameTrackers.
TRACE_EVENT_FLOW_STEP0(
TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
diff --git a/chromium/cc/scheduler/begin_frame_tracker.h b/chromium/cc/scheduler/begin_frame_tracker.h
index 2f5f3b1c27e..fc041094891 100644
--- a/chromium/cc/scheduler/begin_frame_tracker.h
+++ b/chromium/cc/scheduler/begin_frame_tracker.h
@@ -49,7 +49,7 @@ class CC_EXPORT BeginFrameTracker {
// Start using a new BFA value and check invariant properties.
// **Must** only be called after finishing with any previous BFA.
- void Start(viz::BeginFrameArgs new_args);
+ void Start(const viz::BeginFrameArgs& new_args);
// Finish using the current BFA.
// **Must** only be called while still using a BFA.
void Finish();
diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc
index 8ec008c1220..445e0696639 100644
--- a/chromium/cc/scheduler/scheduler.cc
+++ b/chromium/cc/scheduler/scheduler.cc
@@ -9,8 +9,8 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/check_op.h"
#include "base/location.h"
-#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
@@ -583,7 +583,9 @@ void Scheduler::FinishImplFrame() {
// ensures that the acks are sent in order.
if (!state_machine_.did_submit_in_last_frame()) {
SendDidNotProduceFrame(begin_impl_frame_tracker_.Current(),
- FrameSkippedReason::kWaitingOnMain);
+ state_machine_.draw_succeeded_in_last_frame()
+ ? FrameSkippedReason::kNoDamage
+ : FrameSkippedReason::kWaitingOnMain);
}
begin_impl_frame_tracker_.Finish();
@@ -605,8 +607,7 @@ void Scheduler::SendDidNotProduceFrame(const viz::BeginFrameArgs& args,
return;
last_begin_frame_ack_ = viz::BeginFrameAck(args, false /* has_damage */);
client_->DidNotProduceFrame(last_begin_frame_ack_, reason);
- if (reason == FrameSkippedReason::kNoDamage)
- compositor_timing_history_->DidNotProduceFrame(args.frame_id);
+ compositor_timing_history_->DidNotProduceFrame(args.frame_id, reason);
}
// BeginImplFrame starts a compositor frame that will wait up until a deadline
diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc
index 908c5957027..e69c54ce465 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.cc
+++ b/chromium/cc/scheduler/scheduler_state_machine.cc
@@ -4,8 +4,9 @@
#include "cc/scheduler/scheduler_state_machine.h"
+#include "base/check_op.h"
#include "base/format_macros.h"
-#include "base/logging.h"
+#include "base/notreached.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "base/values.h"
@@ -266,7 +267,7 @@ void SchedulerStateMachine::AsProtozeroInto(
minor_state->set_video_needs_begin_frames(video_needs_begin_frames_);
minor_state->set_defer_begin_main_frame(defer_begin_main_frame_);
minor_state->set_last_commit_had_no_updates(last_commit_had_no_updates_);
- minor_state->set_did_draw_in_last_frame(did_draw_in_last_frame_);
+ minor_state->set_did_draw_in_last_frame(did_attempt_draw_in_last_frame_);
minor_state->set_did_submit_in_last_frame(did_submit_in_last_frame_);
minor_state->set_needs_impl_side_invalidation(needs_impl_side_invalidation_);
minor_state->set_current_pending_tree_is_impl_side(
@@ -981,10 +982,11 @@ void SchedulerStateMachine::WillDraw() {
// Set this to true to proactively request a new BeginFrame. We can't set this
// in WillDrawInternal because AbortDraw calls WillDrawInternal but shouldn't
// request another frame.
- did_draw_in_last_frame_ = true;
+ did_attempt_draw_in_last_frame_ = true;
}
void SchedulerStateMachine::DidDraw(DrawResult draw_result) {
+ draw_succeeded_in_last_frame_ = draw_result == DRAW_SUCCESS;
DidDrawInternal(draw_result);
}
@@ -1126,7 +1128,7 @@ bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
// frame soon. This helps avoid negative glitches in our SetNeedsBeginFrame
// requests, which may propagate to the BeginImplFrame provider and get
// sampled at an inopportune time, delaying the next BeginImplFrame.
- if (did_draw_in_last_frame_)
+ if (did_attempt_draw_in_last_frame_)
return true;
// If the last commit was aborted because of early out (no updates), we should
@@ -1154,7 +1156,8 @@ void SchedulerStateMachine::OnBeginImplFrame(const viz::BeginFrameId& frame_id,
last_frame_events_.did_commit_during_frame = did_commit_during_frame_;
last_commit_had_no_updates_ = false;
- did_draw_in_last_frame_ = false;
+ did_attempt_draw_in_last_frame_ = false;
+ draw_succeeded_in_last_frame_ = false;
did_submit_in_last_frame_ = false;
needs_one_begin_impl_frame_ = false;
diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h
index 25b6b5f8ed6..f6a8d0a37f1 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.h
+++ b/chromium/cc/scheduler/scheduler_state_machine.h
@@ -323,6 +323,9 @@ class CC_EXPORT SchedulerStateMachine {
bool video_needs_begin_frames() const { return video_needs_begin_frames_; }
bool did_submit_in_last_frame() const { return did_submit_in_last_frame_; }
+ bool draw_succeeded_in_last_frame() const {
+ return draw_succeeded_in_last_frame_;
+ }
bool needs_impl_side_invalidation() const {
return needs_impl_side_invalidation_;
@@ -450,7 +453,8 @@ class CC_EXPORT SchedulerStateMachine {
bool video_needs_begin_frames_ = false;
bool last_commit_had_no_updates_ = false;
bool active_tree_is_ready_to_draw_ = true;
- bool did_draw_in_last_frame_ = false;
+ bool did_attempt_draw_in_last_frame_ = false;
+ bool draw_succeeded_in_last_frame_ = false;
bool did_submit_in_last_frame_ = false;
bool needs_impl_side_invalidation_ = false;
bool next_invalidation_needs_first_draw_on_activation_ = false;
diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc
index 6f324622056..4ce0028b0f3 100644
--- a/chromium/cc/scheduler/scheduler_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_unittest.cc
@@ -11,8 +11,9 @@
#include "base/auto_reset.h"
#include "base/bind.h"
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/ptr_util.h"
+#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/test/test_mock_time_task_runner.h"
@@ -60,6 +61,7 @@ class FakeSchedulerClient : public SchedulerClient,
num_draws_ = 0;
last_begin_main_frame_args_ = viz::BeginFrameArgs();
last_begin_frame_ack_ = viz::BeginFrameAck();
+ last_frame_skipped_reason_.reset();
}
void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
@@ -130,6 +132,7 @@ class FakeSchedulerClient : public SchedulerClient,
EXPECT_FALSE(inside_action_);
base::AutoReset<bool> mark_inside(&inside_action_, true);
last_begin_frame_ack_ = ack;
+ last_frame_skipped_reason_ = reason;
}
void WillNotReceiveBeginFrame() override {}
@@ -153,23 +156,26 @@ class FakeSchedulerClient : public SchedulerClient,
return last_begin_frame_ack_;
}
+ FrameSkippedReason last_frame_skipped_reason() const {
+ return last_frame_skipped_reason_.value();
+ }
+
DrawResult ScheduledActionDrawIfPossible() override {
EXPECT_FALSE(inside_action_);
base::AutoReset<bool> mark_inside(&inside_action_, true);
PushAction("ScheduledActionDrawIfPossible");
num_draws_++;
- DrawResult result =
- draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
- bool swap_will_happen =
- draw_will_happen_ && swap_will_happen_if_draw_happens_;
- if (swap_will_happen) {
+ if (!draw_will_happen_)
+ return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
+
+ if (swap_will_happen_if_draw_happens_) {
last_begin_frame_ack_ = scheduler_->CurrentBeginFrameAckForActiveTree();
scheduler_->DidSubmitCompositorFrame(0, EventMetricsSet());
if (automatic_ack_)
scheduler_->DidReceiveCompositorFrameAck();
}
- return result;
+ return DRAW_SUCCESS;
}
DrawResult ScheduledActionDrawForced() override {
EXPECT_FALSE(inside_action_);
@@ -283,6 +289,7 @@ class FakeSchedulerClient : public SchedulerClient,
std::vector<const char*> actions_;
TestScheduler* scheduler_ = nullptr;
base::TimeDelta frame_interval_;
+ base::Optional<FrameSkippedReason> last_frame_skipped_reason_;
};
enum BeginFrameSourceType {
@@ -1813,6 +1820,8 @@ void SchedulerTest::ImplFrameSkippedAfterLateAck(
EXPECT_NO_ACTION();
EXPECT_FALSE(client_->IsInsideBeginImplFrame());
EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
+ EXPECT_EQ(FrameSkippedReason::kRecoverLatency,
+ client_->last_frame_skipped_reason());
// Verify that we do not perform any actions after we are no longer
// swap throttled.
@@ -1939,6 +1948,8 @@ TEST_F(SchedulerTest,
EXPECT_NO_ACTION();
EXPECT_FALSE(client_->IsInsideBeginImplFrame());
EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
+ EXPECT_EQ(FrameSkippedReason::kRecoverLatency,
+ client_->last_frame_skipped_reason());
// Verify that we do not perform any actions after we are no longer
// swap throttled.
@@ -3850,7 +3861,26 @@ TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) {
has_damage = false;
EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
client_->last_begin_frame_ack());
+ EXPECT_EQ(FrameSkippedReason::kWaitingOnMain,
+ client_->last_frame_skipped_reason());
client_->Reset();
+
+ // Draw succeeds, but 'swap' does not happen (i.e. no frame is submitted).
+ args = SendNextBeginFrame();
+ EXPECT_ACTIONS("WillBeginImplFrame");
+ EXPECT_TRUE(client_->IsInsideBeginImplFrame());
+ EXPECT_TRUE(scheduler_->begin_frames_expected());
+ client_->Reset();
+ client_->SetDrawWillHappen(true);
+ client_->SetSwapWillHappenIfDrawHappens(false);
+ task_runner_->RunPendingTasks(); // Run posted deadline.
+
+ // Draw with no damage.
+ has_damage = false;
+ EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
+ client_->last_begin_frame_ack());
+ EXPECT_EQ(FrameSkippedReason::kNoDamage,
+ client_->last_frame_skipped_reason());
}
TEST_F(SchedulerTest, BeginFrameAckForSkippedImplFrame) {
diff --git a/chromium/cc/tiles/image_decode_cache_utils.cc b/chromium/cc/tiles/image_decode_cache_utils.cc
index a50f2464110..fb0e1bc04ca 100644
--- a/chromium/cc/tiles/image_decode_cache_utils.cc
+++ b/chromium/cc/tiles/image_decode_cache_utils.cc
@@ -7,7 +7,7 @@
#include "cc/tiles/image_decode_cache_utils.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc
index 116f3c4db58..aefe88d22b8 100644
--- a/chromium/cc/tiles/picture_layer_tiling.cc
+++ b/chromium/cc/tiles/picture_layer_tiling.cc
@@ -11,8 +11,8 @@
#include <limits>
#include <set>
+#include "base/check_op.h"
#include "base/containers/flat_map.h"
-#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/cc/tiles/software_image_decode_cache_utils.h b/chromium/cc/tiles/software_image_decode_cache_utils.h
index 0d2b8cc560a..071f7d216a7 100644
--- a/chromium/cc/tiles/software_image_decode_cache_utils.h
+++ b/chromium/cc/tiles/software_image_decode_cache_utils.h
@@ -9,6 +9,7 @@
#include <memory>
#include <string>
+#include "base/callback.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/scoped_refptr.h"
#include "cc/cc_export.h"
diff --git a/chromium/cc/tiles/tile.cc b/chromium/cc/tiles/tile.cc
index 96962c83b25..f0cf47dcfea 100644
--- a/chromium/cc/tiles/tile.cc
+++ b/chromium/cc/tiles/tile.cc
@@ -40,7 +40,10 @@ Tile::Tile(TileManager* tile_manager,
can_use_lcd_text_(can_use_lcd_text),
id_(tile_manager->GetUniqueTileId()),
invalidated_id_(0),
- scheduled_priority_(0) {}
+ scheduled_priority_(0) {
+ raster_rects_.push_back(
+ std::make_pair(info.content_rect, info.raster_transform));
+}
Tile::~Tile() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(
diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h
index 84f68cb8c14..34726608547 100644
--- a/chromium/cc/tiles/tile.h
+++ b/chromium/cc/tiles/tile.h
@@ -170,6 +170,11 @@ class CC_EXPORT Tile {
Id id_;
+ // List of Rect-Transform pairs, representing unoccluded parts of the
+ // tile, to support raster culling. See Bug: 1071932
+ std::vector<std::pair<const gfx::Rect, const gfx::AxisTransform2d>>
+ raster_rects_;
+
// The rect bounding the changes in this Tile vs the previous tile it
// replaced.
gfx::Rect invalidated_content_rect_;
diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc
index 0d032b7627a..5aa183e3009 100644
--- a/chromium/cc/tiles/tile_manager_unittest.cc
+++ b/chromium/cc/tiles/tile_manager_unittest.cc
@@ -1752,7 +1752,6 @@ TEST_F(PixelInspectTileManagerTest, LowResHasNoImage) {
FakeRecordingSource::CreateFilledRecordingSource(size);
recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
recording_source->SetRequiresClear(true);
- recording_source->SetClearCanvasWithDebugColor(false);
PaintFlags flags;
flags.setColor(SK_ColorGREEN);
recording_source->add_draw_rect_with_flags(gfx::Rect(size), flags);
diff --git a/chromium/cc/trees/draw_properties_unittest.cc b/chromium/cc/trees/draw_properties_unittest.cc
index 538b33043fe..6abe4863df5 100644
--- a/chromium/cc/trees/draw_properties_unittest.cc
+++ b/chromium/cc/trees/draw_properties_unittest.cc
@@ -3571,8 +3571,8 @@ class LCDTextTest : public DrawPropertiesTestBase,
void SetUp() override {
root_ = root_layer();
- child_ = AddLayer<LayerImpl>();
- grand_child_ = AddLayer<LayerImpl>();
+ child_ = AddLayer<PictureLayerImpl>();
+ grand_child_ = AddLayer<PictureLayerImpl>();
SetElementIdsForTesting();
root_->SetContentsOpaque(true);
@@ -3593,23 +3593,36 @@ class LCDTextTest : public DrawPropertiesTestBase,
CopyProperties(child_, grand_child_);
}
+ void CheckCanUseLCDText(LCDTextDisallowedReason expected_disallowed_reason,
+ PictureLayerImpl* layer = nullptr) {
+ if (layers_always_allowed_lcd_text_)
+ expected_disallowed_reason = LCDTextDisallowedReason::kNone;
+ else if (!can_use_lcd_text_)
+ expected_disallowed_reason = LCDTextDisallowedReason::kSetting;
+
+ if (layer) {
+ EXPECT_EQ(expected_disallowed_reason,
+ layer->ComputeLCDTextDisallowedReasonForTesting());
+ } else {
+ EXPECT_EQ(expected_disallowed_reason,
+ child_->ComputeLCDTextDisallowedReasonForTesting());
+ EXPECT_EQ(expected_disallowed_reason,
+ grand_child_->ComputeLCDTextDisallowedReasonForTesting());
+ }
+ }
+
bool can_use_lcd_text_;
bool layers_always_allowed_lcd_text_;
LayerImpl* root_ = nullptr;
- LayerImpl* child_ = nullptr;
- LayerImpl* grand_child_ = nullptr;
+ PictureLayerImpl* child_ = nullptr;
+ PictureLayerImpl* grand_child_ = nullptr;
};
TEST_P(LCDTextTest, CanUseLCDText) {
- bool expect_lcd_text = can_use_lcd_text_ || layers_always_allowed_lcd_text_;
- bool expect_not_lcd_text = layers_always_allowed_lcd_text_;
-
// Case 1: Identity transform.
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
// Case 2: Integral translation.
gfx::Transform integral_translation;
@@ -3617,124 +3630,105 @@ TEST_P(LCDTextTest, CanUseLCDText) {
SetTransform(child_, integral_translation);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
// Case 3: Non-integral translation.
gfx::Transform non_integral_translation;
non_integral_translation.Translate(1.5, 2.5);
SetTransform(child_, non_integral_translation);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation);
// Case 4: Rotation.
gfx::Transform rotation;
rotation.Rotate(10.0);
SetTransform(child_, rotation);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation);
// Case 5: Scale.
gfx::Transform scale;
scale.Scale(2.0, 2.0);
SetTransform(child_, scale);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation);
// Case 6: Skew.
gfx::Transform skew;
skew.Skew(10.0, 0.0);
SetTransform(child_, skew);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation);
- // Case 7: Translucent.
+ // Case 7: Translucent: LCD-text is allowed.
SetTransform(child_, gfx::Transform());
SetOpacity(child_, 0.5f);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
// Case 8: Sanity check: restore transform and opacity.
SetTransform(child_, gfx::Transform());
SetOpacity(child_, 1.f);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
- // Case 9: Non-opaque content.
+ // Case 9a: Non-opaque content and opaque background.
child_->SetContentsOpaque(false);
+ child_->SetBackgroundColor(SK_ColorGREEN);
+ UpdateActiveTreeDrawProperties();
+ CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_);
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_);
+
+ // Case 9b: Non-opaque content and non-opaque background.
+ child_->SetBackgroundColor(SkColorSetARGB(128, 255, 255, 255));
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kBackgroundColorNotOpaque,
+ child_);
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_);
// Case 10: Sanity check: restore content opaqueness.
child_->SetContentsOpaque(true);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
// Case 11: will-change: transform
child_->SetHasWillChangeTransformHint(true);
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kWillChangeTransform, child_);
+ // TODO(wangxianzhu): Is this correct?
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_);
}
TEST_P(LCDTextTest, CanUseLCDTextWithAnimation) {
- bool expect_lcd_text = can_use_lcd_text_ || layers_always_allowed_lcd_text_;
- bool expect_not_lcd_text = layers_always_allowed_lcd_text_;
-
// Sanity check: Make sure can_use_lcd_text_ is set on each node.
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
// Add opacity animation.
- SetOpacity(child_, 0.9f);
- AddOpacityTransitionToElementWithAnimation(child_->element_id(), timeline(),
- 10.0, 0.9f, 0.1f, false);
+ gfx::Transform non_integral_translation;
+ non_integral_translation.Translate(1.5, 2.5);
+ SetTransform(child_, non_integral_translation);
+ AddAnimatedTransformToElementWithAnimation(child_->element_id(), timeline(),
+ 10.0, 12, 34);
UpdateActiveTreeDrawProperties();
// Text LCD should be adjusted while animation is active.
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation);
}
TEST_P(LCDTextTest, CanUseLCDTextWithAnimationContentsOpaque) {
- bool expect_lcd_text = can_use_lcd_text_ || layers_always_allowed_lcd_text_;
- bool expect_not_lcd_text = layers_always_allowed_lcd_text_;
-
// Sanity check: Make sure can_use_lcd_text_ is set on each node.
UpdateActiveTreeDrawProperties();
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone);
// Mark contents non-opaque within the first animation frame.
child_->SetContentsOpaque(false);
+ child_->SetBackgroundColor(SK_ColorWHITE);
AddOpacityTransitionToElementWithAnimation(child_->element_id(), timeline(),
10.0, 0.9f, 0.1f, false);
UpdateActiveTreeDrawProperties();
// LCD text should be disabled for non-opaque layers even during animations.
- EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText());
- EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText());
- EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText());
+ CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_);
+ CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_);
}
INSTANTIATE_TEST_SUITE_P(DrawPropertiesTest,
@@ -4481,10 +4475,13 @@ TEST_F(DrawPropertiesTest,
TEST_F(DrawPropertiesTest, TransformAnimationUpdatesBackfaceVisibility) {
LayerImpl* root = root_layer();
+ root->SetDrawsContent(true);
LayerImpl* back_facing = AddLayer<LayerImpl>();
+ back_facing->SetDrawsContent(true);
LayerImpl* render_surface1 = AddLayer<LayerImpl>();
+ render_surface1->SetDrawsContent(true);
LayerImpl* render_surface2 = AddLayer<LayerImpl>();
-
+ render_surface2->SetDrawsContent(true);
gfx::Transform rotate_about_y;
rotate_about_y.RotateAboutYAxis(180.0);
@@ -4519,7 +4516,11 @@ TEST_F(DrawPropertiesTest, TransformAnimationUpdatesBackfaceVisibility) {
UpdateActiveTreeDrawProperties();
EXPECT_TRUE(GetEffectNode(render_surface1)->hidden_by_backface_visibility);
+ EXPECT_EQ(gfx::Rect(), render_surface1->visible_layer_rect());
EXPECT_TRUE(GetEffectNode(render_surface2)->hidden_by_backface_visibility);
+ EXPECT_EQ(gfx::Rect(), render_surface2->visible_layer_rect());
+
+ EXPECT_EQ(1u, GetRenderSurfaceList().size());
root->layer_tree_impl()->SetTransformMutated(back_facing->element_id(),
gfx::Transform());
@@ -4527,13 +4528,24 @@ TEST_F(DrawPropertiesTest, TransformAnimationUpdatesBackfaceVisibility) {
rotate_about_y);
UpdateActiveTreeDrawProperties();
EXPECT_FALSE(GetEffectNode(render_surface1)->hidden_by_backface_visibility);
+ EXPECT_EQ(gfx::Rect(0, 0, 30, 30), render_surface1->visible_layer_rect());
EXPECT_TRUE(GetEffectNode(render_surface2)->hidden_by_backface_visibility);
+ EXPECT_EQ(gfx::Rect(), render_surface2->visible_layer_rect());
+
+ EXPECT_EQ(2u, GetRenderSurfaceList().size());
root->layer_tree_impl()->SetTransformMutated(render_surface1->element_id(),
rotate_about_y);
UpdateActiveTreeDrawProperties();
EXPECT_TRUE(GetEffectNode(render_surface1)->hidden_by_backface_visibility);
+ // Draw properties are only updated for visible layers, so this remains the
+ // cached value from last time. The expectation is commented out because
+ // this result is not required.
+ // EXPECT_EQ(gfx::Rect(0, 0, 30, 30), render_surface1->visible_layer_rect());
EXPECT_TRUE(GetEffectNode(render_surface2)->hidden_by_backface_visibility);
+ EXPECT_EQ(gfx::Rect(), render_surface2->visible_layer_rect());
+
+ EXPECT_EQ(1u, GetRenderSurfaceList().size());
}
TEST_F(DrawPropertiesTest, ScrollChildAndScrollParentDifferentTargets) {
@@ -6616,7 +6628,6 @@ TEST_F(DrawPropertiesTestWithLayerTree, SkippingLayerImpl) {
// A double sided render surface with backface visible should not be skipped
ImplOf(grandchild)->set_visible_layer_rect(gfx::Rect());
child->SetForceRenderSurfaceForTesting(true);
- child->SetDoubleSided(true);
child->SetTransform(rotate_back_and_translate);
CommitAndActivate();
EXPECT_EQ(gfx::Rect(10, 10), ImplOf(grandchild)->visible_layer_rect());
@@ -6817,12 +6828,10 @@ TEST_F(DrawPropertiesTestWithLayerTree, SkippingLayer) {
child->SetBounds(gfx::Size(10, 10));
gfx::Transform rotate;
- child->SetDoubleSided(false);
rotate.RotateAboutXAxis(180.f);
child->SetTransform(rotate);
CommitAndActivate();
EXPECT_EQ(gfx::Rect(0, 0), ImplOf(child)->visible_layer_rect());
- child->SetDoubleSided(true);
child->SetTransform(gfx::Transform());
child->SetOpacity(0.f);
diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc
index 654c341b8b8..f9fdebf8218 100644
--- a/chromium/cc/trees/draw_property_utils.cc
+++ b/chromium/cc/trees/draw_property_utils.cc
@@ -445,16 +445,21 @@ bool LayerNeedsUpdate(LayerType* layer,
// backface is not visible.
if (TransformToScreenIsKnown(layer, backface_transform_id, tree) &&
!HasSingularTransform(backface_transform_id, tree) &&
- IsLayerBackFaceVisible(layer, backface_transform_id, property_trees))
+ IsLayerBackFaceVisible(layer, backface_transform_id, property_trees)) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Compositing.Renderer.LayerUpdateSkippedDueToBackface", true);
return false;
+ }
}
+ UMA_HISTOGRAM_BOOLEAN("Compositing.Renderer.LayerUpdateSkippedDueToBackface",
+ false);
+
return true;
}
-template <typename LayerType>
inline bool LayerShouldBeSkippedForDrawPropertiesComputation(
- LayerType* layer,
+ Layer* layer,
const TransformTree& transform_tree,
const EffectTree& effect_tree) {
const EffectNode* effect_node = effect_tree.Node(layer->effect_tree_index());
@@ -466,7 +471,36 @@ inline bool LayerShouldBeSkippedForDrawPropertiesComputation(
const TransformNode* transform_node =
transform_tree.Node(layer->transform_tree_index());
return !transform_node->node_and_ancestors_are_animated_or_invertible ||
- effect_node->hidden_by_backface_visibility || !effect_node->is_drawn;
+ !effect_node->is_drawn;
+}
+
+inline bool LayerShouldBeSkippedForDrawPropertiesComputation(
+ LayerImpl* layer,
+ const TransformTree& transform_tree,
+ const EffectTree& effect_tree) {
+ const EffectNode* effect_node = effect_tree.Node(layer->effect_tree_index());
+
+ if (effect_node->HasRenderSurface() && effect_node->subtree_has_copy_request)
+ return false;
+
+ // Skip if the node's subtree is hidden and no need to cache.
+ if (effect_node->subtree_hidden && !effect_node->cache_render_surface)
+ return true;
+
+ // If the layer transform is not invertible, it should be skipped. In case the
+ // transform is animating and singular, we should not skip it.
+ const TransformNode* transform_node =
+ transform_tree.Node(layer->transform_tree_index());
+
+ if (!transform_node->node_and_ancestors_are_animated_or_invertible ||
+ !effect_node->is_drawn)
+ return true;
+
+ UMA_HISTOGRAM_BOOLEAN(
+ "Compositing.Renderer.LayerSkippedForDrawPropertiesDueToBackface",
+ effect_node->hidden_by_backface_visibility);
+
+ return effect_node->hidden_by_backface_visibility;
}
gfx::Rect LayerDrawableContentRect(
diff --git a/chromium/cc/trees/frame_rate_estimator.cc b/chromium/cc/trees/frame_rate_estimator.cc
new file mode 100644
index 00000000000..577b6a1d710
--- /dev/null
+++ b/chromium/cc/trees/frame_rate_estimator.cc
@@ -0,0 +1,84 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/frame_rate_estimator.h"
+
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+
+namespace cc {
+namespace {
+
+constexpr auto kInputPriorityDelay = base::TimeDelta::FromMilliseconds(250);
+
+} // namespace
+
+FrameRateEstimator::FrameRateEstimator(base::SequencedTaskRunner* task_runner)
+ : notifier_(
+ task_runner,
+ base::BindRepeating(&FrameRateEstimator::OnExitInputPriorityMode,
+ base::Unretained(this)),
+ kInputPriorityDelay) {}
+
+FrameRateEstimator::~FrameRateEstimator() = default;
+
+void FrameRateEstimator::SetFrameEstimationEnabled(bool enabled) {
+ if (enabled == frame_rate_estimation_enabled_)
+ return;
+
+ frame_rate_estimation_enabled_ = enabled;
+ last_draw_time_ = base::TimeTicks();
+ num_of_consecutive_frames_with_min_delta_ = 0u;
+}
+
+void FrameRateEstimator::WillDraw(base::TimeTicks now) {
+ if (!frame_rate_estimation_enabled_ || input_priority_mode_)
+ return;
+
+ if (last_draw_time_ == base::TimeTicks()) {
+ last_draw_time_ = now;
+ return;
+ }
+
+ auto draw_delta = now - last_draw_time_;
+ last_draw_time_ = now;
+
+ // If we see that the page is animating consistently at 30 fps or more, then
+ // we assume that BeginFrames can not be throttled. But if the animation
+ // frequency is lower than that, then using a lower frame rate is permitted.
+ // The delta below is to account for minor offsets in frame times.
+ constexpr auto kFudgeDelta = base::TimeDelta::FromMilliseconds(1);
+ constexpr auto kMinDelta =
+ (viz::BeginFrameArgs::DefaultInterval() * 2) + kFudgeDelta;
+ if (draw_delta < kMinDelta)
+ num_of_consecutive_frames_with_min_delta_++;
+ else
+ num_of_consecutive_frames_with_min_delta_ = 0u;
+}
+
+base::TimeDelta FrameRateEstimator::GetPreferredInterval() const {
+ if (!frame_rate_estimation_enabled_ || input_priority_mode_)
+ return viz::BeginFrameArgs::MinInterval();
+
+ constexpr size_t kMinNumOfFramesWithMinDelta = 4u;
+ if (num_of_consecutive_frames_with_min_delta_ >= kMinNumOfFramesWithMinDelta)
+ return viz::BeginFrameArgs::MinInterval();
+
+ return viz::BeginFrameArgs::DefaultInterval() * 2;
+}
+
+void FrameRateEstimator::NotifyInputEvent() {
+ if (!frame_rate_estimation_enabled_)
+ return;
+
+ input_priority_mode_ = true;
+ notifier_.Schedule();
+}
+
+void FrameRateEstimator::OnExitInputPriorityMode() {
+ input_priority_mode_ = false;
+ last_draw_time_ = base::TimeTicks();
+ num_of_consecutive_frames_with_min_delta_ = 0u;
+}
+
+} // namespace cc
diff --git a/chromium/cc/trees/frame_rate_estimator.h b/chromium/cc/trees/frame_rate_estimator.h
new file mode 100644
index 00000000000..7ea16833ca5
--- /dev/null
+++ b/chromium/cc/trees/frame_rate_estimator.h
@@ -0,0 +1,48 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_FRAME_RATE_ESTIMATOR_H_
+#define CC_TREES_FRAME_RATE_ESTIMATOR_H_
+
+#include "base/single_thread_task_runner.h"
+#include "cc/base/delayed_unique_notifier.h"
+#include "cc/cc_export.h"
+
+namespace cc {
+
+class CC_EXPORT FrameRateEstimator {
+ public:
+ explicit FrameRateEstimator(base::SequencedTaskRunner* task_runner);
+ ~FrameRateEstimator();
+
+ void SetFrameEstimationEnabled(bool enabled);
+ void WillDraw(base::TimeTicks now);
+ void NotifyInputEvent();
+ base::TimeDelta GetPreferredInterval() const;
+
+ private:
+ void OnExitInputPriorityMode();
+
+ // Set if an estimated frame rate should be used or we should assume the
+ // highest frame rate available.
+ bool frame_rate_estimation_enabled_ = false;
+
+ // The frame time for the last drawn frame since frame estimation was
+ // enabled.
+ base::TimeTicks last_draw_time_;
+
+ // The number of consecutive frames drawn within the time delta required to
+ // lower the frame rate.
+ size_t num_of_consecutive_frames_with_min_delta_ = 0u;
+
+ // We conservatively switch to high frame rate after an input event to lower
+ // the input latency for a minimum duration. This tracks when we are in this
+ // mode.
+ bool input_priority_mode_ = false;
+ DelayedUniqueNotifier notifier_;
+};
+
+} // namespace cc
+
+#endif // CC_TREES_FRAME_RATE_ESTIMATOR_H_
diff --git a/chromium/cc/trees/frame_rate_estimator_unittest.cc b/chromium/cc/trees/frame_rate_estimator_unittest.cc
new file mode 100644
index 00000000000..d99fabf842b
--- /dev/null
+++ b/chromium/cc/trees/frame_rate_estimator_unittest.cc
@@ -0,0 +1,73 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/frame_rate_estimator.h"
+
+#include "base/test/test_simple_task_runner.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class FrameRateEstimatorTest : public testing::Test {
+ public:
+ FrameRateEstimatorTest() = default;
+ ~FrameRateEstimatorTest() override = default;
+
+ void SetUp() override {
+ task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
+ estimator_ = std::make_unique<FrameRateEstimator>(task_runner_.get());
+ }
+
+ void TearDown() override {
+ estimator_.reset();
+ task_runner_.reset();
+ }
+
+ protected:
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+ std::unique_ptr<FrameRateEstimator> estimator_;
+};
+
+TEST_F(FrameRateEstimatorTest, ToggleEstimationEnabled) {
+ EXPECT_EQ(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+ estimator_->SetFrameEstimationEnabled(true);
+ EXPECT_NE(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+ estimator_->SetFrameEstimationEnabled(false);
+ EXPECT_EQ(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+}
+
+TEST_F(FrameRateEstimatorTest, FrameHistoryUsed) {
+ estimator_->SetFrameEstimationEnabled(true);
+ EXPECT_NE(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+ base::TimeTicks time;
+ for (int i = 0; i < 10; ++i) {
+ estimator_->WillDraw(time);
+ time += viz::BeginFrameArgs::DefaultInterval();
+ }
+ EXPECT_EQ(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+
+ estimator_->WillDraw(time + (3 * viz::BeginFrameArgs::DefaultInterval()));
+ EXPECT_NE(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+}
+
+TEST_F(FrameRateEstimatorTest, InputPriorityMode) {
+ estimator_->SetFrameEstimationEnabled(true);
+ estimator_->NotifyInputEvent();
+ EXPECT_EQ(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+
+ task_runner_->RunUntilIdle();
+ EXPECT_NE(estimator_->GetPreferredInterval(),
+ viz::BeginFrameArgs::MinInterval());
+}
+} // namespace
+} // namespace cc
diff --git a/chromium/cc/trees/latency_info_swap_promise.cc b/chromium/cc/trees/latency_info_swap_promise.cc
index 2edc793bbc7..183e912e3b1 100644
--- a/chromium/cc/trees/latency_info_swap_promise.cc
+++ b/chromium/cc/trees/latency_info_swap_promise.cc
@@ -6,7 +6,7 @@
#include <stdint.h>
-#include "base/logging.h"
+#include "base/check.h"
#include "base/trace_event/trace_event.h"
#include "services/tracing/public/cpp/perfetto/flow_event_utils.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc
index cf848af9541..b1a4798682b 100644
--- a/chromium/cc/trees/layer_tree_host.cc
+++ b/chromium/cc/trees/layer_tree_host.cc
@@ -246,8 +246,9 @@ SwapPromiseManager* LayerTreeHost::GetSwapPromiseManager() {
}
std::unique_ptr<EventsMetricsManager::ScopedMonitor>
-LayerTreeHost::GetScopedEventMetricsMonitor(const EventMetrics& event_metrics) {
- return events_metrics_manager_.GetScopedMonitor(event_metrics);
+LayerTreeHost::GetScopedEventMetricsMonitor(
+ std::unique_ptr<EventMetrics> event_metrics) {
+ return events_metrics_manager_.GetScopedMonitor(std::move(event_metrics));
}
void LayerTreeHost::ClearEventsMetrics() {
@@ -979,6 +980,11 @@ void LayerTreeHost::RecordEndOfFrameMetrics(
client_->RecordEndOfFrameMetrics(frame_begin_time, trackers);
}
+void LayerTreeHost::NotifyThroughputTrackerResults(
+ CustomTrackerResults results) {
+ client_->NotifyThroughputTrackerResults(std::move(results));
+}
+
const base::WeakPtr<InputHandler>& LayerTreeHost::GetInputHandler() const {
return input_handler_weak_ptr_;
}
diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h
index 60d3ff91e45..8aae435b230 100644
--- a/chromium/cc/trees/layer_tree_host.h
+++ b/chromium/cc/trees/layer_tree_host.h
@@ -179,7 +179,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
SwapPromiseManager* GetSwapPromiseManager();
std::unique_ptr<EventsMetricsManager::ScopedMonitor>
- GetScopedEventMetricsMonitor(const EventMetrics& event_metrics);
+ GetScopedEventMetricsMonitor(std::unique_ptr<EventMetrics> event_metrics);
void ClearEventsMetrics();
// Visibility and LayerTreeFrameSink -------------------------------
@@ -592,6 +592,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void RecordStartOfFrameMetrics();
void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time,
ActiveFrameSequenceTrackers trackers);
+ void NotifyThroughputTrackerResults(CustomTrackerResults results);
LayerTreeHostClient* client() { return client_; }
LayerTreeHostSchedulingClient* scheduling_client() {
diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h
index cae833370e8..ae48bd94a18 100644
--- a/chromium/cc/trees/layer_tree_host_client.h
+++ b/chromium/cc/trees/layer_tree_host_client.h
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "cc/input/browser_controls_state.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_tracker_collection.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -168,9 +168,10 @@ class LayerTreeHostClient {
// committed to the compositor, which is before the call to
// RecordEndOfFrameMetrics.
virtual std::unique_ptr<BeginMainFrameMetrics> GetBeginMainFrameMetrics() = 0;
+ virtual void NotifyThroughputTrackerResults(CustomTrackerResults results) = 0;
protected:
- virtual ~LayerTreeHostClient() {}
+ virtual ~LayerTreeHostClient() = default;
};
// LayerTreeHost->WebThreadScheduler callback interface. Instances of this class
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index 1889f1df493..4fcc3210311 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -13,6 +13,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/containers/adapters.h"
#include "base/containers/flat_map.h"
@@ -31,13 +32,13 @@
#include "cc/base/devtools_instrumentation.h"
#include "cc/base/histograms.h"
#include "cc/base/math_util.h"
+#include "cc/base/switches.h"
#include "cc/benchmarks/benchmark_instrumentation.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/input/browser_controls_offset_manager.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/page_scale_animation.h"
#include "cc/input/scroll_elasticity_helper.h"
-#include "cc/input/scroll_input_type.h"
#include "cc/input/scroll_state.h"
#include "cc/input/scrollbar.h"
#include "cc/input/scrollbar_animation_controller.h"
@@ -53,6 +54,8 @@
#include "cc/layers/surface_layer_impl.h"
#include "cc/layers/viewport.h"
#include "cc/metrics/compositor_frame_reporting_controller.h"
+#include "cc/metrics/frame_sequence_metrics.h"
+#include "cc/metrics/lcd_text_metrics_reporter.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_worklet_job.h"
#include "cc/paint/paint_worklet_layer_painter.h"
@@ -115,6 +118,7 @@
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.h"
#include "third_party/skia/include/gpu/GrContext.h"
+#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -138,15 +142,16 @@ const float kMobileViewportWidthEpsilon = 0.15f;
// kHitTestAsk after the threshold is reached.
const size_t kAssumeOverlapThreshold = 100;
-FrameSequenceTrackerType GetTrackerTypeForScroll(ScrollInputType input_type) {
+FrameSequenceTrackerType GetTrackerTypeForScroll(
+ ui::ScrollInputType input_type) {
switch (input_type) {
- case ScrollInputType::kWheel:
+ case ui::ScrollInputType::kWheel:
return FrameSequenceTrackerType::kWheelScroll;
- case ScrollInputType::kTouchscreen:
+ case ui::ScrollInputType::kTouchscreen:
return FrameSequenceTrackerType::kTouchScroll;
- case ScrollInputType::kScrollbar:
+ case ui::ScrollInputType::kScrollbar:
return FrameSequenceTrackerType::kScrollbarScroll;
- case ScrollInputType::kAutoscroll:
+ case ui::ScrollInputType::kAutoscroll:
return FrameSequenceTrackerType::kMaxType;
}
}
@@ -221,13 +226,13 @@ void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
enum ScrollThread { MAIN_THREAD, CC_THREAD };
-void RecordCompositorSlowScrollMetric(ScrollInputType type,
+void RecordCompositorSlowScrollMetric(ui::ScrollInputType type,
ScrollThread scroll_thread) {
bool scroll_on_main_thread = (scroll_thread == MAIN_THREAD);
- if (type == ScrollInputType::kWheel) {
+ if (type == ui::ScrollInputType::kWheel) {
UMA_HISTOGRAM_BOOLEAN("Renderer4.CompositorWheelScrollUpdateThread",
scroll_on_main_thread);
- } else if (type == ScrollInputType::kTouchscreen) {
+ } else if (type == ui::ScrollInputType::kTouchscreen) {
UMA_HISTOGRAM_BOOLEAN("Renderer4.CompositorTouchScrollUpdateThread",
scroll_on_main_thread);
}
@@ -243,6 +248,30 @@ void PopulateMetadataContentColorUsage(
}
}
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class SourceIdConsistency : int {
+ kConsistent = 0,
+ kContainsInvalid = 1,
+ kNonUnique = 2,
+ kInvalidAndNonUnique = 3,
+ kMaxValue = kInvalidAndNonUnique,
+};
+
+void RecordSourceIdConsistency(bool all_valid, bool all_unique) {
+ SourceIdConsistency consistency =
+ all_unique ? (all_valid ? SourceIdConsistency::kConsistent
+ : SourceIdConsistency::kContainsInvalid)
+ : (all_valid ? SourceIdConsistency::kNonUnique
+ : SourceIdConsistency::kInvalidAndNonUnique);
+
+ // TODO(crbug.com/1062764): we're sometimes seeing unexpected values for the
+ // ukm::SourceId. We'll use this histogram to track how often it happens so
+ // we can properly (de-)prioritize a fix.
+ UMA_HISTOGRAM_ENUMERATION("Event.LatencyInfo.Debug.SourceIdConsistency",
+ consistency);
+}
+
} // namespace
DEFINE_SCOPED_UMA_HISTOGRAM_TIMER(PendingTreeRasterDurationHistogramTimer,
@@ -323,7 +352,9 @@ LayerTreeHostImpl::LayerTreeHostImpl(
scrollbar_controller_(std::make_unique<ScrollbarController>(this)),
frame_trackers_(settings.single_thread_proxy_scheduler,
compositor_frame_reporting_controller_.get()),
- scroll_gesture_did_end_(false) {
+ scroll_gesture_did_end_(false),
+ lcd_text_metrics_reporter_(LCDTextMetricsReporter::CreateIfNeeded(this)),
+ frame_rate_estimator_(GetTaskRunner()) {
DCHECK(mutator_host_);
mutator_host_->SetMutatorHostClient(this);
mutator_events_ = mutator_host_->CreateEvents();
@@ -346,9 +377,12 @@ LayerTreeHostImpl::LayerTreeHostImpl(
this, settings.top_controls_show_threshold,
settings.top_controls_hide_threshold);
- memory_pressure_listener_.reset(
- new base::MemoryPressureListener(base::BindRepeating(
- &LayerTreeHostImpl::OnMemoryPressure, base::Unretained(this))));
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableLayerTreeHostMemoryPressure)) {
+ memory_pressure_listener_.reset(
+ new base::MemoryPressureListener(base::BindRepeating(
+ &LayerTreeHostImpl::OnMemoryPressure, base::Unretained(this))));
+ }
SetDebugState(settings.initial_debug_state);
}
@@ -491,6 +525,15 @@ void LayerTreeHostImpl::CommitComplete() {
frame_trackers_.StartSequence(
FrameSequenceTrackerType::kMainThreadAnimation);
}
+
+ for (const auto& info : mutator_host_->TakePendingThroughputTrackerInfos()) {
+ const MutatorHost::TrackedAnimationSequenceId sequence_id = info.id;
+ const bool start = info.start;
+ if (start)
+ frame_trackers_.StartCustomSequence(sequence_id);
+ else
+ frame_trackers_.StopCustomSequence(sequence_id);
+ }
}
void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() {
@@ -856,33 +899,6 @@ bool LayerTreeHostImpl::IsCurrentlyScrollingViewport() const {
return viewport().ShouldScroll(*node);
}
-bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt(
- const gfx::Point& viewport_point) const {
- auto* scrolling_node = CurrentlyScrollingNode();
- if (!scrolling_node)
- return false;
-
- gfx::PointF device_viewport_point = gfx::ScalePoint(
- gfx::PointF(viewport_point), active_tree_->device_scale_factor());
-
- LayerImpl* layer_impl =
- active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
-
- bool scroll_on_main_thread = false;
- uint32_t main_thread_scrolling_reasons;
- auto* test_scroll_node = FindScrollNodeForDeviceViewportPoint(
- device_viewport_point, layer_impl, &scroll_on_main_thread,
- &main_thread_scrolling_reasons);
-
- if (scroll_on_main_thread)
- return false;
-
- if (scrolling_node == test_scroll_node)
- return true;
-
- return false;
-}
-
EventListenerProperties LayerTreeHostImpl::GetEventListenerProperties(
EventListenerClass event_class) const {
return active_tree_->event_listener_properties(event_class);
@@ -979,8 +995,8 @@ LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor(
std::unique_ptr<EventsMetricsManager::ScopedMonitor>
LayerTreeHostImpl::GetScopedEventMetricsMonitor(
- const EventMetrics& event_metrics) {
- return events_metrics_manager_.GetScopedMonitor(event_metrics);
+ std::unique_ptr<EventMetrics> event_metrics) {
+ return events_metrics_manager_.GetScopedMonitor(std::move(event_metrics));
}
ScrollElasticityHelper* LayerTreeHostImpl::CreateScrollElasticityHelper() {
@@ -1033,6 +1049,10 @@ bool LayerTreeHostImpl::ScrollingShouldSwitchtoMainThread() {
return false;
}
+void LayerTreeHostImpl::NotifyInputEvent() {
+ frame_rate_estimator_.NotifyInputEvent();
+}
+
void LayerTreeHostImpl::QueueSwapPromiseForMainThreadScrollUpdate(
std::unique_ptr<SwapPromise> swap_promise) {
swap_promises_for_main_thread_scroll_update_.push_back(
@@ -1257,6 +1277,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
bool have_copy_request =
active_tree()->property_trees()->effect_tree.HasCopyRequests();
bool have_missing_animated_tiles = false;
+ int num_of_layers_with_videos = 0;
// Advance our de-jelly state. This is a no-op if de-jelly is not active.
de_jelly_state_.AdvanceFrame(active_tree_.get());
@@ -1296,8 +1317,10 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
DCHECK_EQ(active_tree_.get(), layer->layer_tree_impl());
frame->will_draw_layers.push_back(layer);
- if (layer->may_contain_video())
+ if (layer->may_contain_video()) {
+ num_of_layers_with_videos++;
frame->may_contain_video = true;
+ }
layer->AppendQuads(target_render_pass, &append_quads_data);
if (settings_.allow_de_jelly_effect) {
@@ -1362,6 +1385,11 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
}
+ // Only enable frame rate estimation if it would help lower the composition
+ // rate for videos.
+ const bool enable_frame_rate_estimation = num_of_layers_with_videos > 1;
+ frame_rate_estimator_.SetFrameEstimationEnabled(enable_frame_rate_estimation);
+
// When doing a resourceless software draw, we don't have control over the
// surface the compositor draws to, so even though the frame may not be
// complete, the previous frame has already been potentially lost, so an
@@ -2010,10 +2038,19 @@ void LayerTreeHostImpl::DidPresentCompositorFrame(
// is in charge of posting them to the main thread.
client_->DidPresentCompositorFrameOnImplThread(
frame_token, std::move(activated.main_thread_callbacks), details);
+
+ // Send throughput tracker results to main-thread if any.
+ auto throughput_tracker_results = frame_trackers_.TakeCustomTrackerResults();
+ if (!throughput_tracker_results.empty()) {
+ client_->NotifyThroughputTrackerResults(
+ std::move(throughput_tracker_results));
+ }
}
void LayerTreeHostImpl::DidNotNeedBeginFrame() {
frame_trackers_.NotifyPauseFrameProduction();
+ if (lcd_text_metrics_reporter_)
+ lcd_text_metrics_reporter_->NotifyPauseFrameProduction();
}
void LayerTreeHostImpl::ReclaimResources(
@@ -2318,6 +2355,11 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
FrameSequenceTrackerType::kMainThreadAnimation);
}
+ if (lcd_text_metrics_reporter_) {
+ lcd_text_metrics_reporter_->NotifySubmitFrame(
+ frame->origin_begin_main_frame_args);
+ }
+
// Clears the list of swap promises after calling DidSwap on each of them to
// signal that the swap is over.
active_tree()->ClearSwapPromises();
@@ -2404,6 +2446,10 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame(
frame->deadline_in_frames.value_or(0u), CurrentBeginFrameArgs().interval,
frame->use_default_lower_bound_deadline);
+ frame_rate_estimator_.WillDraw(CurrentBeginFrameArgs().frame_time);
+ metadata.preferred_frame_interval =
+ frame_rate_estimator_.GetPreferredInterval();
+
metadata.activation_dependencies = std::move(frame->activation_dependencies);
active_tree()->FinishSwapPromises(&metadata);
// The swap-promises should not change the frame-token.
@@ -2427,12 +2473,20 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame(
active_tree()->TakeForceSendMetadataRequest());
}
- if (!CommitToActiveTree()) {
+ if (!CommitToActiveTree() && !metadata.latency_info.empty()) {
base::TimeTicks draw_time = base::TimeTicks::Now();
+
+ ukm::SourceId exemplar = metadata.latency_info.front().ukm_source_id();
+ bool all_valid = true;
+ bool all_unique = true;
for (auto& latency : metadata.latency_info) {
latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, draw_time);
+ all_valid &= latency.ukm_source_id() != ukm::kInvalidSourceId;
+ all_unique &= latency.ukm_source_id() == exemplar;
}
+
+ RecordSourceIdConsistency(all_valid, all_unique);
}
ui::LatencyInfo::TraceIntermediateFlowEvents(
metadata.latency_info,
@@ -3745,7 +3799,7 @@ base::flat_set<int> LayerTreeHostImpl::NonFastScrollableNodes(
return non_fast_scrollable_nodes;
}
-ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint(
+ScrollNode* LayerTreeHostImpl::FindScrollNodeForCompositedScrolling(
const gfx::PointF& device_viewport_point,
LayerImpl* layer_impl,
bool* scroll_on_main_thread,
@@ -3768,9 +3822,9 @@ ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint(
// layer corresponding to the scrollbars owner and then use its
// scroll_tree_index instead.
int scroll_tree_index = layer_impl->scroll_tree_index();
- if (layer_impl->ToScrollbarLayer()) {
+ if (layer_impl->IsScrollbarLayer()) {
LayerImpl* owner_scroll_layer = active_tree_->LayerByElementId(
- layer_impl->ToScrollbarLayer()->scroll_element_id());
+ ToScrollbarLayer(layer_impl)->scroll_element_id());
scroll_tree_index = owner_scroll_layer->scroll_tree_index();
}
@@ -3828,7 +3882,7 @@ ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint(
InputHandler::ScrollStatus LayerTreeHostImpl::RootScrollBegin(
ScrollState* scroll_state,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
TRACE_EVENT0("cc", "LayerTreeHostImpl::RootScrollBegin");
if (!OuterViewportScrollNode()) {
ScrollStatus scroll_status;
@@ -3845,7 +3899,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::RootScrollBegin(
InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
ScrollState* scroll_state,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
DCHECK(scroll_state);
DCHECK(scroll_state->delta_x() == 0 && scroll_state->delta_y() == 0);
@@ -3866,7 +3920,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds();
}
- if (CurrentlyScrollingNode()) {
+ if (CurrentlyScrollingNode() && type == latched_scroll_type_) {
// It's possible we haven't yet cleared the CurrentlyScrollingNode if we
// received a GSE but we're still animating the last scroll. If that's the
// case, we'll simply un-defer the GSE and continue latching to the same
@@ -3932,7 +3986,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
}
}
- ScrollNode* starting_node = FindScrollNodeForDeviceViewportPoint(
+ ScrollNode* starting_node = FindScrollNodeForCompositedScrolling(
device_viewport_point, layer_impl, &scroll_on_main_thread,
&scroll_status.main_thread_scrolling_reasons);
@@ -3980,14 +4034,51 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin(
return scroll_status;
}
+ScrollNode* LayerTreeHostImpl::HitTestScrollNode(
+ const gfx::PointF& device_viewport_point) const {
+ LayerImpl* layer_impl =
+ active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
+
+ if (!layer_impl)
+ return nullptr;
+
+ // There are some cases where the hit layer may not be correct (e.g. layer
+ // squashing). If we detect this case, we can't target a scroll node here.
+ {
+ LayerImpl* first_scrolling_layer_or_scrollbar =
+ active_tree_->FindFirstScrollingLayerOrScrollbarThatIsHitByPoint(
+ device_viewport_point);
+
+ if (!IsInitialScrollHitTestReliable(layer_impl,
+ first_scrolling_layer_or_scrollbar)) {
+ TRACE_EVENT_INSTANT0("cc", "Failed Hit Test", TRACE_EVENT_SCOPE_THREAD);
+ return nullptr;
+ }
+ }
+
+ // If we hit a scrollbar layer, get the ScrollNode from its associated
+ // scrolling layer, rather than directly from the scrollbar layer. The latter
+ // would return the parent scroller's ScrollNode.
+ if (layer_impl->IsScrollbarLayer()) {
+ layer_impl = active_tree_->LayerByElementId(
+ ToScrollbarLayer(layer_impl)->scroll_element_id());
+ DCHECK(layer_impl);
+ }
+
+ ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree;
+ ScrollNode* scroll_node = scroll_tree.Node(layer_impl->scroll_tree_index());
+
+ return GetNodeToScroll(scroll_node);
+}
+
// Requires falling back to main thread scrolling when it hit tests in scrollbar
// from touch.
bool LayerTreeHostImpl::IsTouchDraggingScrollbar(
LayerImpl* first_scrolling_layer_or_scrollbar,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
return first_scrolling_layer_or_scrollbar &&
- first_scrolling_layer_or_scrollbar->is_scrollbar() &&
- type == ScrollInputType::kTouchscreen;
+ first_scrolling_layer_or_scrollbar->IsScrollbarLayer() &&
+ type == ui::ScrollInputType::kTouchscreen;
}
ScrollNode* LayerTreeHostImpl::GetNodeToScroll(ScrollNode* node) const {
@@ -4022,28 +4113,14 @@ ScrollNode* LayerTreeHostImpl::GetNodeToScroll(ScrollNode* node) const {
return node;
}
-// Initial scroll hit testing can be unreliable in the presence of squashed
-// layers. In this case, we fall back to main thread scrolling. This function
-// compares |layer_impl| returned from a regular hit test to the layer
-// returned from a hit test performed only on scrollers and scrollbars. If the
-// closest scrolling ancestor of |layer_impl| is not the other layer, then the
-// layer_impl must be a squasing layer overtop of some other scroller and we
-// must rely on the main thread.
-//
-// Note, position: fixed layers use the inner viewport as their ScrollNode
-// (since they don't scroll with the outer viewport), however, scrolls from the
-// fixed layer still chain to the outer viewport. It's also possible for a node
-// to have the inner viewport as its ancestor without going through the outer
-// viewport; however, it may still scroll using the viewport(). Hence, this
-// method must use the same scroll chaining logic we use in ApplyScroll.
bool LayerTreeHostImpl::IsInitialScrollHitTestReliable(
LayerImpl* layer_impl,
- LayerImpl* first_scrolling_layer_or_scrollbar) {
+ LayerImpl* first_scrolling_layer_or_scrollbar) const {
if (!first_scrolling_layer_or_scrollbar)
return true;
// Hit tests directly on a composited scrollbar are always reliable.
- if (layer_impl->ToScrollbarLayer()) {
+ if (layer_impl->IsScrollbarLayer()) {
DCHECK(layer_impl == first_scrolling_layer_or_scrollbar);
return true;
}
@@ -4065,7 +4142,7 @@ bool LayerTreeHostImpl::IsInitialScrollHitTestReliable(
// a scrollabe layer with a scroll node. If this scroll node corresponds to
// first scrollable ancestor along the scroll tree for |layer_impl|, the hit
// test has not escaped to other areas of the scroll tree and is reliable.
- if (!first_scrolling_layer_or_scrollbar->is_scrollbar()) {
+ if (!first_scrolling_layer_or_scrollbar->IsScrollbarLayer()) {
return closest_scroll_node->id ==
first_scrolling_layer_or_scrollbar->scroll_tree_index();
}
@@ -4382,7 +4459,7 @@ void LayerTreeHostImpl::ScrollLatchedScroller(ScrollState* scroll_state,
// controls if needed.
Viewport::ScrollResult result = viewport().ScrollBy(
delta, viewport_point, scroll_state->is_direct_manipulation(),
- latched_scroll_type_ != ScrollInputType::kWheel,
+ latched_scroll_type_ != ui::ScrollInputType::kWheel,
scroll_node.scrolls_outer_viewport);
applied_delta = result.consumed_delta;
@@ -4438,7 +4515,7 @@ static bool CanPropagate(ScrollNode* scroll_node, float x, float y) {
ScrollNode* LayerTreeHostImpl::FindNodeToLatch(ScrollState* scroll_state,
ScrollNode* starting_node,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree;
ScrollNode* scroll_node = nullptr;
for (ScrollNode* cur_node = starting_node; cur_node;
@@ -4456,7 +4533,7 @@ ScrollNode* LayerTreeHostImpl::FindNodeToLatch(ScrollState* scroll_state,
// For UX reasons, autoscrolling should always latch to the top-most
// scroller, even if it can't scroll in the initial direction.
- if (type == ScrollInputType::kAutoscroll ||
+ if (type == ui::ScrollInputType::kAutoscroll ||
CanConsumeDelta(*scroll_state, *cur_node)) {
scroll_node = cur_node;
break;
@@ -4483,7 +4560,7 @@ ScrollNode* LayerTreeHostImpl::FindNodeToLatch(ScrollState* scroll_state,
}
void LayerTreeHostImpl::DidLatchToScroller(const ScrollState& scroll_state,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
DCHECK(CurrentlyScrollingNode());
deferred_scroll_end_ = false;
browser_controls_offset_manager_->ScrollBegin();
@@ -4493,6 +4570,7 @@ void LayerTreeHostImpl::DidLatchToScroller(const ScrollState& scroll_state,
scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds();
last_latched_scroller_ = CurrentlyScrollingNode()->element_id;
latched_scroll_type_ = type;
+ last_scroll_begin_state_ = scroll_state;
client_->RenewTreePriority();
RecordCompositorSlowScrollMetric(type, CC_THREAD);
@@ -4524,6 +4602,10 @@ bool LayerTreeHostImpl::CanConsumeDelta(const ScrollState& scroll_state,
return false;
}
delta_to_scroll = local_scroll_delta;
+ } else if (scroll_state.delta_granularity() ==
+ ui::ScrollGranularity::kScrollByPercentage) {
+ delta_to_scroll =
+ ResolveScrollPercentageToPixels(scroll_node, delta_to_scroll);
}
if (ComputeScrollDelta(scroll_node, delta_to_scroll) != gfx::Vector2dF())
@@ -4559,7 +4641,7 @@ bool LayerTreeHostImpl::ShouldAnimateScroll(
// Mac does not smooth scroll wheel events (crbug.com/574283). We allow tests
// to force it on.
- return latched_scroll_type_ == ScrollInputType::kScrollbar
+ return latched_scroll_type_ == ui::ScrollInputType::kScrollbar
? true
: force_smooth_wheel_scrolling_for_testing_;
#else
@@ -4737,13 +4819,20 @@ bool LayerTreeHostImpl::SnapAtScrollEnd() {
SnapContainerData& data = scroll_node->snap_container_data.value();
gfx::ScrollOffset current_position = GetVisualScrollOffset(*scroll_node);
- DCHECK(last_scroll_update_state_);
+ // You might think that if a scroll never received a scroll update we could
+ // just drop the snap. However, if the GSB+GSE arrived while we were mid-snap
+ // from a previous gesture, this would leave the scroller at a
+ // non-snap-point.
+ DCHECK(last_scroll_update_state_ || last_scroll_begin_state_);
+ ScrollState& last_scroll_state = last_scroll_update_state_
+ ? *last_scroll_update_state_
+ : *last_scroll_begin_state_;
+
bool imprecise_wheel_scrolling =
- latched_scroll_type_ == ScrollInputType::kWheel &&
- last_scroll_update_state_->delta_granularity() !=
+ latched_scroll_type_ == ui::ScrollInputType::kWheel &&
+ last_scroll_state.delta_granularity() !=
ui::ScrollGranularity::kScrollByPrecisePixel;
- gfx::ScrollOffset last_scroll_delta(last_scroll_update_state_->delta_x(),
- last_scroll_update_state_->delta_y());
+ gfx::ScrollOffset last_scroll_delta = last_scroll_state.DeltaOrHint();
std::unique_ptr<SnapSelectionStrategy> strategy;
@@ -4869,9 +4958,11 @@ void LayerTreeHostImpl::ClearCurrentlyScrollingNode() {
scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds();
latched_scroll_type_.reset();
last_scroll_update_state_.reset();
+ last_scroll_begin_state_.reset();
}
void LayerTreeHostImpl::ScrollEnd(bool should_snap) {
+ scrollbar_controller_->ResetState();
if (!CurrentlyScrollingNode())
return;
@@ -4899,7 +4990,7 @@ void LayerTreeHostImpl::ScrollEnd(bool should_snap) {
}
void LayerTreeHostImpl::RecordScrollBegin(
- ScrollInputType input_type,
+ ui::ScrollInputType input_type,
ScrollBeginThreadState scroll_start_state) {
auto tracker_type = GetTrackerTypeForScroll(input_type);
DCHECK_NE(tracker_type, FrameSequenceTrackerType::kMaxType);
@@ -4927,7 +5018,7 @@ void LayerTreeHostImpl::RecordScrollBegin(
metrics->SetScrollingThread(scrolling_thread);
}
-void LayerTreeHostImpl::RecordScrollEnd(ScrollInputType input_type) {
+void LayerTreeHostImpl::RecordScrollEnd(ui::ScrollInputType input_type) {
frame_trackers_.StopSequence(GetTrackerTypeForScroll(input_type));
}
@@ -4987,33 +5078,18 @@ InputHandlerPointerResult LayerTreeHostImpl::MouseMoveAt(
gfx::PointF device_viewport_point = gfx::ScalePoint(
gfx::PointF(viewport_point), active_tree_->device_scale_factor());
- LayerImpl* layer_impl =
- active_tree_->FindLayerThatIsHitByPoint(device_viewport_point);
+ ScrollNode* scroll_node = HitTestScrollNode(device_viewport_point);
- // Check if mouse is over a scrollbar or not.
- // TODO(sahel): get rid of this extera checking when
- // FindScrollNodeForDeviceViewportPoint finds the proper node for scrolling on
- // the main thread when the mouse is over a scrollbar as well.
- ElementId scroll_element_id;
- if (layer_impl && layer_impl->ToScrollbarLayer())
- scroll_element_id = layer_impl->ToScrollbarLayer()->scroll_element_id();
- if (!scroll_element_id) {
- bool scroll_on_main_thread = false;
- uint32_t main_thread_scrolling_reasons;
- auto* scroll_node = FindScrollNodeForDeviceViewportPoint(
- device_viewport_point, layer_impl, &scroll_on_main_thread,
- &main_thread_scrolling_reasons);
- if (scroll_node)
- scroll_element_id = scroll_node->element_id;
-
- // Scrollbars for the viewport are registered with the outer viewport layer.
- if (InnerViewportScrollNode() &&
- scroll_element_id == InnerViewportScrollNode()->element_id) {
- DCHECK(OuterViewportScrollNode());
- scroll_element_id = OuterViewportScrollNode()->element_id;
- }
- }
+ // The hit test can fail in some cases, e.g. we don't know if a region of a
+ // squashed layer has content or is empty.
+ if (!scroll_node)
+ return result;
+
+ // Scrollbars for the viewport are registered with the outer viewport layer.
+ if (scroll_node->scrolls_inner_viewport)
+ scroll_node = OuterViewportScrollNode();
+ ElementId scroll_element_id = scroll_node->element_id;
ScrollbarAnimationController* new_animation_controller =
ScrollbarAnimationControllerForElementId(scroll_element_id);
if (scroll_element_id != scroll_element_id_mouse_currently_over_) {
@@ -5025,7 +5101,7 @@ InputHandlerPointerResult LayerTreeHostImpl::MouseMoveAt(
scroll_element_id_mouse_currently_over_ = scroll_element_id;
- // Experiment: Enables will flash scorllbar when user move mouse enter a
+ // Experiment: Enables will flash scrollbar when user move mouse enter a
// scrollable area.
if (settings_.scrollbar_flash_when_mouse_enter && new_animation_controller)
new_animation_controller->DidScrollUpdate();
@@ -5418,7 +5494,7 @@ TreePriority LayerTreeHostImpl::GetTreePriority() const {
return global_tile_state_.tree_priority;
}
-viz::BeginFrameArgs LayerTreeHostImpl::CurrentBeginFrameArgs() const {
+const viz::BeginFrameArgs& LayerTreeHostImpl::CurrentBeginFrameArgs() const {
// TODO(mithro): Replace call with current_begin_frame_tracker_.Current()
// once all calls which happens outside impl frames are fixed.
return current_begin_frame_tracker_.DangerousMethodCurrentOrLast();
@@ -6120,14 +6196,14 @@ void LayerTreeHostImpl::SetContextVisibility(bool is_visible) {
}
void LayerTreeHostImpl::UpdateScrollSourceInfo(const ScrollState& scroll_state,
- ScrollInputType type) {
- if (type == ScrollInputType::kWheel &&
+ ui::ScrollInputType type) {
+ if (type == ui::ScrollInputType::kWheel &&
scroll_state.delta_granularity() ==
ui::ScrollGranularity::kScrollByPrecisePixel) {
has_scrolled_by_precisiontouchpad_ = true;
- } else if (type == ScrollInputType::kWheel) {
+ } else if (type == ui::ScrollInputType::kWheel) {
has_scrolled_by_wheel_ = true;
- } else if (type == ScrollInputType::kTouchscreen) {
+ } else if (type == ui::ScrollInputType::kTouchscreen) {
has_scrolled_by_touch_ = true;
}
}
diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h
index 2352d8e17c3..f7ce4e673e6 100644
--- a/chromium/cc/trees/layer_tree_host_impl.h
+++ b/chromium/cc/trees/layer_tree_host_impl.h
@@ -18,6 +18,7 @@
#include "base/containers/flat_set.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/shared_memory_mapping.h"
+#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "cc/base/synced_property.h"
@@ -25,13 +26,12 @@
#include "cc/cc_export.h"
#include "cc/input/browser_controls_offset_manager_client.h"
#include "cc/input/input_handler.h"
-#include "cc/input/scroll_input_type.h"
#include "cc/input/scrollbar_animation_controller.h"
#include "cc/input/scrollbar_controller.h"
#include "cc/layers/layer_collections.h"
#include "cc/metrics/event_metrics.h"
#include "cc/metrics/events_metrics_manager.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_tracker_collection.h"
#include "cc/paint/discardable_image_map.h"
#include "cc/paint/paint_worklet_job.h"
#include "cc/resources/ui_resource_client.h"
@@ -45,6 +45,7 @@
#include "cc/tiles/tile_manager.h"
#include "cc/trees/animated_paint_worklet_tracker.h"
#include "cc/trees/de_jelly_state.h"
+#include "cc/trees/frame_rate_estimator.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_mutator.h"
@@ -63,6 +64,7 @@
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_range.h"
+#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/rect.h"
namespace gfx {
@@ -83,6 +85,7 @@ class DebugRectHistory;
class EvictionTilePriorityQueue;
class FrameRateCounter;
class ImageAnimationController;
+class LCDTextMetricsReporter;
class LayerImpl;
class LayerTreeFrameSink;
class LayerTreeImpl;
@@ -171,8 +174,10 @@ class LayerTreeHostImplClient {
virtual void NotifyPaintWorkletStateChange(
Scheduler::PaintWorkletState state) = 0;
+ virtual void NotifyThroughputTrackerResults(CustomTrackerResults results) = 0;
+
protected:
- virtual ~LayerTreeHostImplClient() {}
+ virtual ~LayerTreeHostImplClient() = default;
};
// LayerTreeHostImpl owns the LayerImpl trees as well as associated rendering
@@ -261,9 +266,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// InputHandler implementation
void BindToClient(InputHandlerClient* client) override;
InputHandler::ScrollStatus ScrollBegin(ScrollState* scroll_state,
- ScrollInputType type) override;
+ ui::ScrollInputType type) override;
InputHandler::ScrollStatus RootScrollBegin(ScrollState* scroll_state,
- ScrollInputType type) override;
+ ui::ScrollInputType type) override;
InputHandlerScrollResult ScrollUpdate(
ScrollState* scroll_state,
base::TimeDelta delayed_by = base::TimeDelta()) override;
@@ -271,9 +276,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
void SetSynchronousInputHandlerRootScrollOffset(
const gfx::ScrollOffset& root_content_offset) override;
void ScrollEnd(bool should_snap = false) override;
- void RecordScrollBegin(ScrollInputType input_type,
+ void RecordScrollBegin(ui::ScrollInputType input_type,
ScrollBeginThreadState scroll_start_state) override;
- void RecordScrollEnd(ScrollInputType input_type) override;
+ void RecordScrollEnd(ui::ScrollInputType input_type) override;
InputHandlerPointerResult MouseDown(const gfx::PointF& viewport_point,
bool shift_modifier) override;
@@ -297,8 +302,6 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
base::TimeDelta duration);
void SetNeedsAnimateInput() override;
bool IsCurrentlyScrollingViewport() const override;
- bool IsCurrentlyScrollingLayerAt(
- const gfx::Point& viewport_point) const override;
EventListenerProperties GetEventListenerProperties(
EventListenerClass event_class) const override;
InputHandler::TouchStartOrMoveEventListenerType
@@ -310,13 +313,15 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
std::unique_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
ui::LatencyInfo* latency) override;
std::unique_ptr<EventsMetricsManager::ScopedMonitor>
- GetScopedEventMetricsMonitor(const EventMetrics& event_metrics) override;
+ GetScopedEventMetricsMonitor(
+ std::unique_ptr<EventMetrics> event_metrics) override;
ScrollElasticityHelper* CreateScrollElasticityHelper() override;
bool GetScrollOffsetForLayer(ElementId element_id,
gfx::ScrollOffset* offset) override;
bool ScrollLayerTo(ElementId element_id,
const gfx::ScrollOffset& offset) override;
bool ScrollingShouldSwitchtoMainThread() override;
+ void NotifyInputEvent() override;
// BrowserControlsOffsetManagerClient implementation.
float TopControlsHeight() const override;
@@ -637,6 +642,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
std::unique_ptr<ScrollAndScaleSet> ProcessScrollDeltas();
FrameRateCounter* fps_counter() { return fps_counter_.get(); }
+ base::Optional<int> current_universal_throughput() {
+ return frame_trackers_.current_universal_throughput();
+ }
MemoryHistory* memory_history() { return memory_history_.get(); }
DebugRectHistory* debug_rect_history() { return debug_rect_history_.get(); }
viz::ClientResourceProvider* resource_provider() {
@@ -654,6 +662,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
}
MutatorHost* mutator_host() const { return mutator_host_.get(); }
+ ScrollbarController* scrollbar_controller_for_testing() const {
+ return scrollbar_controller_.get();
+ }
void SetDebugState(const LayerTreeDebugState& new_debug_state);
const LayerTreeDebugState& debug_state() const { return debug_state_; }
@@ -682,7 +693,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// TODO(mithro): Remove this methods which exposes the internal
// viz::BeginFrameArgs to external callers.
- virtual viz::BeginFrameArgs CurrentBeginFrameArgs() const;
+ virtual const viz::BeginFrameArgs& CurrentBeginFrameArgs() const;
// Expected time between two begin impl frame calls.
base::TimeDelta CurrentBeginFrameInterval() const;
@@ -944,10 +955,25 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
bool IsTouchDraggingScrollbar(
LayerImpl* first_scrolling_layer_or_drawn_scrollbar,
- ScrollInputType type);
+ ui::ScrollInputType type);
+
+ // Initial scroll hit testing can be unreliable in the presence of squashed
+ // layers. In this case, we fall back to main thread scrolling. This function
+ // compares |layer_impl| returned from a regular hit test to the layer
+ // returned from a hit test performed only on scrollers and scrollbars. If the
+ // closest scrolling ancestor of |layer_impl| is not the other layer, then the
+ // layer_impl must be a squasing layer overtop of some other scroller and we
+ // must rely on the main thread.
+ //
+ // Note, position: fixed layers use the inner viewport as their ScrollNode
+ // (since they don't scroll with the outer viewport), however, scrolls from
+ // the fixed layer still chain to the outer viewport. It's also possible for a
+ // node to have the inner viewport as its ancestor without going through the
+ // outer viewport; however, it may still scroll using the viewport(). Hence,
+ // this method must use the same scroll chaining logic we use in ApplyScroll.
bool IsInitialScrollHitTestReliable(
LayerImpl* layer,
- LayerImpl* first_scrolling_layer_or_drawn_scrollbar);
+ LayerImpl* first_scrolling_layer_or_drawn_scrollbar) const;
// Given a starting node (determined by hit-test), walks up the scroll tree
// looking for the first node that can consume scroll from the given
@@ -955,7 +981,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// starting_node is nullptr, returns nullptr;
ScrollNode* FindNodeToLatch(ScrollState* scroll_state,
ScrollNode* starting_node,
- ScrollInputType type);
+ ui::ScrollInputType type);
// Called during ScrollBegin once a scroller was successfully latched to
// (i.e. it can and will consume scroll delta on the compositor thread). The
@@ -964,7 +990,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// get consensus on terminology to use and apply it consistently.
// https://crrev.com/c/1981336/9/cc/trees/layer_tree_host_impl.cc#4520
void DidLatchToScroller(const ScrollState& scroll_state,
- ScrollInputType type);
+ ui::ScrollInputType type);
// Applies the scroll_state to the currently latched scroller. See comment in
// InputHandler::ScrollUpdate declaration for the meaning of |delayed_by|.
@@ -991,7 +1017,18 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
void ClearCurrentlyScrollingNode();
- ScrollNode* FindScrollNodeForDeviceViewportPoint(
+ // Performs a hit test to determine the ScrollNode to use when scrolling at
+ // |viewport_point|. Can return nullptr if the hit test fails; see the
+ // comment in IsInitialScrollHitTestReliable
+ ScrollNode* HitTestScrollNode(const gfx::PointF& device_viewport_point) const;
+
+ // Similar to above but includes complicated logic to determine whether the
+ // ScrollNode is able to be scrolled on the compositor or requires main
+ // thread scrolling. If main thread scrolling is required
+ // |scroll_on_main_thread| is set to true and the reason is given in
+ // |main_thread_scrolling_reason| to on of the enum values in
+ // main_thread_scrolling_reason.h.
+ ScrollNode* FindScrollNodeForCompositedScrolling(
const gfx::PointF& device_viewport_point,
LayerImpl* layer_hit_by_point,
bool* scroll_on_main_thread,
@@ -1038,7 +1075,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// sources per page load. TODO(crbug.com/691886): Use GRC API to plumb the
// scroll source info for Use Counters.
void UpdateScrollSourceInfo(const ScrollState& scroll_state,
- ScrollInputType type);
+ ui::ScrollInputType type);
bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor);
void ShowScrollbarsForImplScroll(ElementId element_id);
@@ -1140,8 +1177,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// time a CompositorFrame is generated.
gfx::Vector2dF scroll_accumulated_this_frame_;
- // Tracks the last scroll update state received. Used to infer the most
+ // Tracks the last scroll update/begin state received. Used to infer the most
// recent scroll type and direction.
+ base::Optional<ScrollState> last_scroll_begin_state_;
base::Optional<ScrollState> last_scroll_update_state_;
std::vector<std::unique_ptr<SwapPromise>>
@@ -1321,7 +1359,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
// The source device type that started the scroll gesture. Only set between a
// ScrollBegin and ScrollEnd.
- base::Optional<ScrollInputType> latched_scroll_type_;
+ base::Optional<ui::ScrollInputType> latched_scroll_type_;
// Scroll animation can finish either before or after GSE arrival.
// deferred_scroll_end_ is set when the GSE has arrvied before scroll
@@ -1359,6 +1397,10 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
EventsMetricsManager events_metrics_manager_;
+ std::unique_ptr<LCDTextMetricsReporter> lcd_text_metrics_reporter_;
+
+ FrameRateEstimator frame_rate_estimator_;
+
// Must be the last member to ensure this is destroyed first in the
// destruction order and invalidates all weak pointers.
base::WeakPtrFactory<LayerTreeHostImpl> weak_factory_{this};
diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
index c5c6a044aaa..3d1cfc76a5d 100644
--- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
@@ -31,7 +31,6 @@
#include "cc/input/browser_controls_offset_manager.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/page_scale_animation.h"
-#include "cc/input/scroll_input_type.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer_impl.h"
@@ -93,6 +92,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
+#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/angle_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -261,6 +261,7 @@ class LayerTreeHostImplTest : public testing::Test,
ElementListType tree_type) override {}
void NotifyPaintWorkletStateChange(
Scheduler::PaintWorkletState state) override {}
+ void NotifyThroughputTrackerResults(CustomTrackerResults results) override {}
void set_reduce_memory_result(bool reduce_memory_result) {
reduce_memory_result_ = reduce_memory_result;
@@ -498,9 +499,9 @@ class LayerTreeHostImplTest : public testing::Test,
// is not an ancestor of squash1 layer, we cannot scroll on impl thread.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(230, 150), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
ASSERT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
ASSERT_EQ(MainThreadScrollingReason::kFailedHitTest,
status.main_thread_scrolling_reasons);
@@ -508,9 +509,9 @@ class LayerTreeHostImplTest : public testing::Test,
// The point hits squash1 layer and also scrollbar layer.
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(350, 150), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
ASSERT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
ASSERT_EQ(MainThreadScrollingReason::kFailedHitTest,
status.main_thread_scrolling_reasons);
@@ -519,9 +520,9 @@ class LayerTreeHostImplTest : public testing::Test,
// is an ancestor of squash2 layer, we should scroll on impl.
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(230, 450), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
ASSERT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
}
@@ -581,7 +582,7 @@ class LayerTreeHostImplTest : public testing::Test,
std::unique_ptr<ScrollState> BeginState(const gfx::Point& point,
const gfx::Vector2dF& delta_hint,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
ScrollStateData scroll_state_data;
scroll_state_data.is_beginning = true;
scroll_state_data.position_x = point.x();
@@ -589,7 +590,7 @@ class LayerTreeHostImplTest : public testing::Test,
scroll_state_data.delta_x_hint = delta_hint.x();
scroll_state_data.delta_y_hint = delta_hint.y();
scroll_state_data.is_direct_manipulation =
- type == ScrollInputType::kTouchscreen;
+ type == ui::ScrollInputType::kTouchscreen;
std::unique_ptr<ScrollState> scroll_state(
new ScrollState(scroll_state_data));
return scroll_state;
@@ -597,14 +598,14 @@ class LayerTreeHostImplTest : public testing::Test,
std::unique_ptr<ScrollState> UpdateState(const gfx::Point& point,
const gfx::Vector2dF& delta,
- ScrollInputType type) {
+ ui::ScrollInputType type) {
ScrollStateData scroll_state_data;
scroll_state_data.delta_x = delta.x();
scroll_state_data.delta_y = delta.y();
scroll_state_data.position_x = point.x();
scroll_state_data.position_y = point.y();
scroll_state_data.is_direct_manipulation =
- type == ScrollInputType::kTouchscreen;
+ type == ui::ScrollInputType::kTouchscreen;
std::unique_ptr<ScrollState> scroll_state(
new ScrollState(scroll_state_data));
return scroll_state;
@@ -613,7 +614,7 @@ class LayerTreeHostImplTest : public testing::Test,
std::unique_ptr<ScrollState> AnimatedUpdateState(
const gfx::Point& point,
const gfx::Vector2dF& delta) {
- auto state = UpdateState(point, delta, ScrollInputType::kWheel);
+ auto state = UpdateState(point, delta, ui::ScrollInputType::kWheel);
state->data()->delta_granularity = ui::ScrollGranularity::kScrollByPixel;
return state;
}
@@ -1075,18 +1076,20 @@ TEST_F(CommitToPendingTreeLayerTreeHostImplTest,
}
TEST_F(LayerTreeHostImplTest, ScrollBeforeRootLayerAttached) {
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 1), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 1),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
- status = host_impl_->RootScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 1), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ status =
+ host_impl_->RootScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 1),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
@@ -1106,10 +1109,10 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateAndEndNoOpWithoutBegin) {
{
EXPECT_FALSE(host_impl_->CurrentlyScrollingNode());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_FALSE(host_impl_->CurrentlyScrollingNode());
host_impl_->ScrollEnd();
@@ -1119,14 +1122,14 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateAndEndNoOpWithoutBegin) {
{
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_TRUE(host_impl_->CurrentlyScrollingNode());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 10),
CurrentScrollOffset(OuterViewportScrollLayer()));
@@ -1148,8 +1151,8 @@ TEST_F(LayerTreeHostImplTest, TargetMainThreadScroller) {
// Try on a node that should scroll on the compositor. Confirm it works.
{
- InputHandler::ScrollStatus status =
- host_impl_->ScrollBegin(scroll_state.get(), ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
+ scroll_state.get(), ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(host_impl_->OuterViewportScrollNode(),
host_impl_->CurrentlyScrollingNode());
@@ -1162,8 +1165,8 @@ TEST_F(LayerTreeHostImplTest, TargetMainThreadScroller) {
MainThreadScrollingReason::kThreadedScrollingDisabled;
{
- InputHandler::ScrollStatus status =
- host_impl_->ScrollBegin(scroll_state.get(), ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
+ scroll_state.get(), ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(
host_impl_->OuterViewportScrollNode()->main_thread_scrolling_reasons,
@@ -1176,21 +1179,21 @@ TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100));
DrawFrame();
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
+ EXPECT_TRUE(host_impl_->CurrentlyScrollingNode());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10)));
host_impl_->ScrollEnd();
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
+ EXPECT_FALSE(host_impl_->CurrentlyScrollingNode());
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
}
@@ -1212,9 +1215,9 @@ TEST_F(LayerTreeHostImplTest, ActivelyTouchScrollingOnlyAfterScrollMovement) {
{
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -1222,13 +1225,13 @@ TEST_F(LayerTreeHostImplTest, ActivelyTouchScrollingOnlyAfterScrollMovement) {
// There is no extent upwards so the scroll won't consume any delta.
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling());
// This should scroll so ensure the bit flips to true.
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_TRUE(host_impl_->IsActivelyPrecisionScrolling());
host_impl_->ScrollEnd();
@@ -1240,10 +1243,11 @@ TEST_F(LayerTreeHostImplTest, ActivelyTouchScrollingOnlyAfterScrollMovement) {
// Ensure an animated wheel scroll doesn't cause the bit to flip even when
// scrolling occurs.
{
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling());
@@ -1285,10 +1289,11 @@ TEST_F(LayerTreeHostImplTest, ActivelyTouchScrollingOnlyAfterScrollMovement) {
TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
// We should not crash when trying to scroll an empty layer tree.
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
@@ -1308,10 +1313,11 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
// We should not crash when trying to scroll after the renderer initialization
// fails.
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -1328,9 +1334,9 @@ TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
host_impl_
->ScrollBegin(BeginState(gfx::Point(),
gfx::ScrollOffsetToVector2dF(scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
ClearLayersAndPropertyTrees(host_impl_->active_tree());
@@ -1341,7 +1347,7 @@ TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
// new tree.
host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -1355,15 +1361,15 @@ TEST_F(LayerTreeHostImplTest, ActivateTreeScrollingNodeDisappeared) {
auto status = host_impl_->ScrollBegin(
BeginState(gfx::Point(30, 30), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(host_impl_->active_tree()->CurrentlyScrollingNode());
// Create the pending tree containing only the root layer.
@@ -1398,10 +1404,11 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
EXPECT_FALSE(host_impl_->HasBlockingWheelEventHandlerAt(gfx::Point(30, 30)));
// But they don't influence the actual handling of the scroll gestures.
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -1435,9 +1442,9 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
// But they don't influence the actual handling of the scroll gestures.
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -1466,19 +1473,20 @@ TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
DrawFrame();
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
status.main_thread_scrolling_reasons);
status =
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
status.main_thread_scrolling_reasons);
@@ -1523,9 +1531,9 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) {
// scrollbar layer is a drawn scrollbar, we cannot scroll on the impl thread.
auto status = host_impl_->ScrollBegin(
BeginState(gfx::Point(350, 150), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest,
status.main_thread_scrolling_reasons);
@@ -1534,9 +1542,9 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) {
// the impl thread.
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(350, 500), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -1626,56 +1634,49 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
// All scroll types inside the non-fast scrollable region should fail.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(25, 25), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
status.main_thread_scrolling_reasons);
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25)));
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(25, 25), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
status.main_thread_scrolling_reasons);
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25)));
// All scroll types outside this region should succeed.
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(75, 75), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25)));
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(75, 75), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75)));
}
TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
@@ -1692,25 +1693,24 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
// moved the layer left by 25 pixels.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(40, 10), gfx::Vector2d(0, 1),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10)));
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 1), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 1),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
// This point is still inside the non-fast region.
status = host_impl_->ScrollBegin(
BeginState(gfx::Point(10, 10), gfx::Vector2d(0, 1),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
status.main_thread_scrolling_reasons);
@@ -1723,9 +1723,9 @@ TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
host_impl_->ScrollEnd();
EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
@@ -1738,9 +1738,9 @@ TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
host_impl_->ScrollEnd();
EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
@@ -1752,9 +1752,9 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateReturnsCorrectValue) {
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(-10, 0),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -1763,37 +1763,37 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateReturnsCorrectValue) {
EXPECT_FALSE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_FALSE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_FALSE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
// Scrolling to the right/bottom will succeed.
EXPECT_TRUE(host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(10, 0),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_TRUE(host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(10, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
@@ -1801,19 +1801,19 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateReturnsCorrectValue) {
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-10, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
@@ -1821,19 +1821,19 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateReturnsCorrectValue) {
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(10, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-10, 0),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-10, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
@@ -1841,7 +1841,7 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateReturnsCorrectValue) {
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(5000, 5000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
}
@@ -1856,16 +1856,17 @@ TEST_F(LayerTreeHostImplTest, ScrollSnapOnX) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
@@ -1900,16 +1901,17 @@ TEST_F(LayerTreeHostImplTest, ScrollSnapOnY) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, y_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, y_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
@@ -1943,17 +1945,17 @@ TEST_F(LayerTreeHostImplTest, ScrollSnapOnBoth) {
gfx::Vector2dF delta(20, 20);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
- ->ScrollBegin(
- BeginState(pointer_position, delta, ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel)
+ ->ScrollBegin(BeginState(pointer_position, delta,
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, delta, ui::ScrollInputType::kWheel).get());
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
@@ -1980,6 +1982,23 @@ TEST_F(LayerTreeHostImplTest, ScrollSnapOnBoth) {
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
}
+// Simulate a ScrollBegin and ScrollEnd without any intervening ScrollUpdate.
+// This test passes if it doesn't crash.
+TEST_F(LayerTreeHostImplTest, SnapAfterEmptyScroll) {
+ CreateLayerForSnapping();
+
+ gfx::Point pointer_position(10, 10);
+ gfx::Vector2dF y_delta(0, 20);
+ EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_
+ ->ScrollBegin(BeginState(pointer_position, y_delta,
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel)
+ .thread);
+ host_impl_->ScrollEnd(true);
+}
+
TEST_F(LayerTreeHostImplTest, ScrollSnapAfterAnimatedScroll) {
LayerImpl* overflow = CreateLayerForSnapping();
@@ -1988,10 +2007,10 @@ TEST_F(LayerTreeHostImplTest, ScrollSnapAfterAnimatedScroll) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
- ->ScrollBegin(
- BeginState(pointer_position, delta, ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel)
+ ->ScrollBegin(BeginState(pointer_position, delta,
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(AnimatedUpdateState(pointer_position, delta).get());
host_impl_->ScrollEnd();
@@ -2046,14 +2065,15 @@ TEST_F(LayerTreeHostImplTest, SnapAnimationTargetUpdated) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, y_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, y_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
viz::BeginFrameArgs begin_frame_args =
@@ -2108,14 +2128,15 @@ TEST_F(LayerTreeHostImplTest, SnapAnimationCancelledByScroll) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
viz::BeginFrameArgs begin_frame_args =
@@ -2139,12 +2160,13 @@ TEST_F(LayerTreeHostImplTest, SnapAnimationCancelledByScroll) {
// Interrupt the snap animation with ScrollBegin.
auto begin_state =
- BeginState(pointer_position, x_delta, ScrollInputType::kWheel);
+ BeginState(pointer_position, x_delta, ui::ScrollInputType::kWheel);
begin_state->data()->delta_granularity =
ui::ScrollGranularity::kScrollByPrecisePixel;
- EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
- host_impl_->ScrollBegin(begin_state.get(), ScrollInputType::kWheel)
- .thread);
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel)
+ .thread);
EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
EXPECT_EQ(TargetSnapAreaElementIds(),
GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds());
@@ -2170,15 +2192,16 @@ TEST_F(LayerTreeHostImplTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
// There is a snap target at 50, scroll to it directly.
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(host_impl_->IsAnimatingForSnap());
viz::BeginFrameArgs begin_frame_args =
@@ -2218,16 +2241,16 @@ TEST_F(LayerTreeHostImplTest,
gfx::Vector2dF delta(4, 4);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
- ->ScrollBegin(
- BeginState(pointer_position, delta, ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel)
+ ->ScrollBegin(BeginState(pointer_position, delta,
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
// Should be (20, 20) in the scroller's coordinate.
InputHandlerScrollResult result = host_impl_->ScrollUpdate(
- UpdateState(pointer_position, delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, delta, ui::ScrollInputType::kWheel).get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(overflow));
EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset);
@@ -2257,16 +2280,16 @@ TEST_F(LayerTreeHostImplTest, SnapFlingAnimationEndWithoutFinishing) {
gfx::Vector2dF delta(4, 4);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
- ->ScrollBegin(
- BeginState(pointer_position, delta, ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel)
+ ->ScrollBegin(BeginState(pointer_position, delta,
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
// Should be (20, 20) in the scroller's coordinate.
InputHandlerScrollResult result = host_impl_->ScrollUpdate(
- UpdateState(pointer_position, delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, delta, ui::ScrollInputType::kWheel).get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(overflow));
EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset);
@@ -2309,15 +2332,16 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(30, 30), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
@@ -2333,15 +2357,16 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
@@ -2351,15 +2376,16 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, y_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, y_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
@@ -2369,15 +2395,15 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, diagonal_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, diagonal_delta, ScrollInputType::kWheel)
+ UpdateState(pointer_position, diagonal_delta, ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer));
@@ -2395,15 +2421,16 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
@@ -2413,15 +2440,16 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, y_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, y_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
@@ -2431,15 +2459,15 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, diagonal_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, diagonal_delta, ScrollInputType::kWheel)
+ UpdateState(pointer_position, diagonal_delta, ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
@@ -2456,21 +2484,25 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(pointer_position, x_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, -x_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, -x_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, y_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollUpdate(
- UpdateState(pointer_position, -y_delta, ScrollInputType::kWheel).get());
+ UpdateState(pointer_position, -y_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(overflow));
@@ -2494,15 +2526,15 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(scroll_position, scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(scroll_position, scroll_delta, ScrollInputType::kWheel)
+ UpdateState(scroll_position, scroll_delta, ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer));
@@ -2515,15 +2547,15 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(scroll_position, scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(scroll_position, scroll_delta, ScrollInputType::kWheel)
+ UpdateState(scroll_position, scroll_delta, ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(scroll_layer));
@@ -2535,15 +2567,15 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(scroll_position, scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(scroll_layer));
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(overflow));
host_impl_->ScrollUpdate(
- UpdateState(scroll_position, scroll_delta, ScrollInputType::kWheel)
+ UpdateState(scroll_position, scroll_delta, ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(scroll_layer));
@@ -2560,9 +2592,9 @@ TEST_F(LayerTreeHostImplTest, ForceMainThreadScrollWithoutScrollLayer) {
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(25, 25), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
status.main_thread_scrolling_reasons);
@@ -2819,9 +2851,9 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
// gesture that doesn't cause (initial) scrolling?
// https://crbug.com/1030262
host_impl_->ScrollBegin(BeginState(gfx::Point(50, 50), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
host_impl_->PinchGestureEnd(gfx::Point(50, 50), true);
@@ -2848,9 +2880,9 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
float page_scale_delta = 2;
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -2860,12 +2892,13 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -2952,9 +2985,9 @@ TEST_F(LayerTreeHostImplTest, ViewportScrollOrder) {
MaxScrollOffset(outer_scroll_layer));
host_impl_->ScrollBegin(BeginState(gfx::Point(250, 250), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, gfx::Point(0, 0));
host_impl_->PinchGestureEnd(gfx::Point(0, 0), true);
@@ -2968,12 +3001,12 @@ TEST_F(LayerTreeHostImplTest, ViewportScrollOrder) {
// Scroll down - only the inner viewport should scroll.
host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -2986,12 +3019,12 @@ TEST_F(LayerTreeHostImplTest, ViewportScrollOrder) {
// its maximum.
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -3025,12 +3058,12 @@ TEST_F(LayerTreeHostImplTest, ScrollViewportWithFractionalAmounts) {
// Scroll only the layout viewport.
host_impl_->ScrollBegin(
BeginState(gfx::Point(250, 250), gfx::Vector2dF(0.125f, 0.125f),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(250, 250),
gfx::Vector2dF(0.125f, 0.125f),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f),
CurrentScrollOffset(outer_scroll_layer));
@@ -3043,12 +3076,12 @@ TEST_F(LayerTreeHostImplTest, ScrollViewportWithFractionalAmounts) {
// Now that we zoomed in, the scroll should be applied to the inner viewport.
host_impl_->ScrollBegin(
BeginState(gfx::Point(250, 250), gfx::Vector2dF(0.5f, 0.5f),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(250, 250),
gfx::Vector2dF(0.5f, 0.5f),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f),
CurrentScrollOffset(outer_scroll_layer));
@@ -3079,9 +3112,9 @@ TEST_F(LayerTreeHostImplTest, ScrollDuringPinchGesture) {
MaxScrollOffset(outer_scroll_layer));
host_impl_->ScrollBegin(BeginState(gfx::Point(250, 250), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
@@ -3095,7 +3128,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDuringPinchGesture) {
host_impl_->ScrollUpdate(UpdateState(gfx::Point(250, 250),
gfx::Vector2dF(10, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0),
CurrentScrollOffset(outer_scroll_layer));
@@ -3106,7 +3139,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDuringPinchGesture) {
host_impl_->ScrollUpdate(UpdateState(gfx::Point(250, 250),
gfx::Vector2dF(400, 400),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(80, 80),
CurrentScrollOffset(outer_scroll_layer));
@@ -3136,8 +3169,9 @@ TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
// Pinch in within the margins. The scroll should stay exactly locked to the
// bottom and right.
host_impl_->ScrollBegin(
- BeginState(anchor, gfx::Vector2dF(), ScrollInputType::kTouchscreen).get(),
- ScrollInputType::kTouchscreen);
+ BeginState(anchor, gfx::Vector2dF(), ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, anchor);
host_impl_->PinchGestureEnd(anchor, true);
@@ -3155,8 +3189,9 @@ TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
// top and left.
anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
host_impl_->ScrollBegin(
- BeginState(anchor, gfx::Vector2dF(), ScrollInputType::kTouchscreen).get(),
- ScrollInputType::kTouchscreen);
+ BeginState(anchor, gfx::Vector2dF(), ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, anchor);
host_impl_->PinchGestureEnd(anchor, true);
@@ -3174,8 +3209,9 @@ TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
host_impl_->ScrollBegin(
- BeginState(anchor, gfx::Vector2dF(), ScrollInputType::kTouchscreen).get(),
- ScrollInputType::kTouchscreen);
+ BeginState(anchor, gfx::Vector2dF(), ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, anchor);
host_impl_->PinchGestureEnd(anchor, true);
@@ -3194,8 +3230,9 @@ TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
anchor = gfx::Point(viewport_size.width() - offsetFromEdge,
viewport_size.height() - offsetFromEdge);
host_impl_->ScrollBegin(
- BeginState(anchor, gfx::Vector2dF(), ScrollInputType::kTouchscreen).get(),
- ScrollInputType::kTouchscreen);
+ BeginState(anchor, gfx::Vector2dF(), ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, anchor);
host_impl_->PinchGestureEnd(anchor, true);
@@ -3223,11 +3260,11 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
// Scroll by a small amount, there should be no bubbling to the outer
// viewport.
host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(10, 20),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(10, 20),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -3238,12 +3275,12 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
// Scroll by the inner viewport's max scroll extent, the remainder
// should bubble up to the outer viewport.
host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -3255,12 +3292,12 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
// Scroll by the outer viewport's max scroll extent, it should all go to the
// outer viewport.
host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(190, 180),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(190, 180),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -3281,12 +3318,12 @@ TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(
std::move(swap_promise));
@@ -3323,16 +3360,16 @@ TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) {
{
host_impl_->ScrollBegin(BeginState(gfx::Point(21, 21), gfx::Vector2d(5, 5),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(21, 21),
gfx::Vector2d(5, 5),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(21, 21),
gfx::Vector2d(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -3351,24 +3388,24 @@ TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) {
{
host_impl_->ScrollBegin(BeginState(gfx::Point(21, 21), gfx::Vector2d(3, 4),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(21, 21),
gfx::Vector2d(3, 4),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(21, 21),
gfx::Vector2d(2, 1),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(21, 21),
gfx::Vector2d(2, 1),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(21, 21),
gfx::Vector2d(2, 1),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -3401,9 +3438,9 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
float page_scale_delta = 2;
host_impl_->ScrollBegin(BeginState(gfx::Point(50, 50), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
host_impl_->PinchGestureEnd(gfx::Point(50, 50), true);
@@ -3425,9 +3462,9 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
float page_scale_delta = 10;
host_impl_->ScrollBegin(BeginState(gfx::Point(50, 50), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
host_impl_->PinchGestureEnd(gfx::Point(50, 50), true);
@@ -3453,9 +3490,9 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
float page_scale_delta = 0.1f;
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -3483,9 +3520,9 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
float page_scale_delta = 1;
host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
@@ -3514,14 +3551,14 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
float page_scale_delta = 1;
host_impl_->ScrollBegin(
BeginState(gfx::Point(10, 10), gfx::Vector2dF(-10, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
host_impl_->ScrollUpdate(UpdateState(gfx::Point(10, 10),
gfx::Vector2d(-10, -10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
host_impl_->PinchGestureEnd(gfx::Point(20, 20), true);
@@ -3547,9 +3584,9 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
scroll_layer->element_id(), gfx::ScrollOffset(0, 0));
host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, gfx::Point(0, 0));
host_impl_->PinchGestureUpdate(1, gfx::Point(0, 0));
@@ -3559,7 +3596,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) {
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2d(10, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->PinchGestureUpdate(1, gfx::Point(10, 10));
host_impl_->PinchGestureEnd(gfx::Point(10, 10), true);
@@ -3596,14 +3633,14 @@ TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollDelta) {
float page_scale_delta = 1;
host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
host_impl_->ScrollUpdate(UpdateState(gfx::Point(10, 10),
gfx::Vector2dF(0, -1.001f),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 9));
host_impl_->PinchGestureEnd(gfx::Point(10, 9), true);
@@ -3640,12 +3677,12 @@ TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollFromFractionalActiveBase) {
scroll_layer->element_id(), gfx::ScrollOffset(0, 20.5f));
host_impl_->ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2dF(0, -1),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(10, 10),
gfx::Vector2dF(0, -1),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -4181,10 +4218,10 @@ TEST_F(LayerTreeHostImplTest, AnimatedGranularityCausesSmoothScroll) {
// TODO(bokan): Unfortunately, Mac currently doesn't support smooth scrolling
// wheel events. https://crbug.com/574283.
#if defined(OS_MACOSX)
- std::vector<ScrollInputType> types = {ScrollInputType::kScrollbar};
+ std::vector<ui::ScrollInputType> types = {ui::ScrollInputType::kScrollbar};
#else
- std::vector<ScrollInputType> types = {ScrollInputType::kScrollbar,
- ScrollInputType::kWheel};
+ std::vector<ui::ScrollInputType> types = {ui::ScrollInputType::kScrollbar,
+ ui::ScrollInputType::kWheel};
#endif
for (auto type : types) {
auto begin_state = BeginState(position, offset, type);
@@ -4251,8 +4288,8 @@ TEST_F(LayerTreeHostImplTest, NonAnimatedGranularityCausesInstantScroll) {
gfx::Point position(295, 195);
gfx::Vector2dF offset(0, 50);
- std::vector<ScrollInputType> types = {ScrollInputType::kScrollbar,
- ScrollInputType::kWheel};
+ std::vector<ui::ScrollInputType> types = {ui::ScrollInputType::kScrollbar,
+ ui::ScrollInputType::kWheel};
for (auto type : types) {
auto begin_state = BeginState(position, offset, type);
begin_state->data()->set_current_native_scrolling_element(
@@ -4299,17 +4336,17 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
nullptr,
nullptr) {}
- viz::BeginFrameArgs CurrentBeginFrameArgs() const override {
- return viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
- fake_current_physical_time_);
+ const viz::BeginFrameArgs& CurrentBeginFrameArgs() const override {
+ return current_begin_frame_args_;
}
void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
- fake_current_physical_time_ = fake_now;
+ current_begin_frame_args_ = viz::CreateBeginFrameArgsForTesting(
+ BEGINFRAME_FROM_HERE, 0, 1, fake_now);
}
private:
- base::TimeTicks fake_current_physical_time_;
+ viz::BeginFrameArgs current_begin_frame_args_;
};
class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
@@ -4381,9 +4418,9 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
// If no scroll happened during a scroll gesture, it should have no effect.
host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kWheel)
+ BeginState(gfx::Point(), gfx::Vector2dF(), ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollEnd();
EXPECT_FALSE(did_request_next_frame_);
EXPECT_FALSE(did_request_redraw_);
@@ -4393,12 +4430,12 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
// For Aura Overlay Scrollbar, if no scroll happened during a scroll
// gesture, shows scrollbars and schedules a delay fade out.
host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kWheel)
+ BeginState(gfx::Point(), gfx::Vector2dF(), ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2dF(0, 0), ScrollInputType::kWheel)
- .get());
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, 0),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_FALSE(did_request_next_frame_);
EXPECT_FALSE(did_request_redraw_);
@@ -4428,13 +4465,13 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
// After a scroll, a scrollbar animation should be scheduled about 20ms from
// now.
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 5), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2dF(0, 5), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 5),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, 5),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(did_request_next_frame_);
EXPECT_TRUE(did_request_redraw_);
did_request_redraw_ = false;
@@ -4580,13 +4617,13 @@ class LayerTreeHostImplTestScrollbarOpacity : public LayerTreeHostImplTest {
EXPECT_EQ(nullptr, host_impl_->ScrollbarAnimationControllerForElementId(
scroll->element_id()));
}
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 5), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2dF(0, 5), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 5),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, 5),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
CreatePendingTree();
@@ -4711,11 +4748,11 @@ TEST_F(LayerTreeHostImplTestMultiScrollable,
// Scroll on root should flash all scrollbars.
host_impl_->RootScrollBegin(
BeginState(gfx::Point(20, 20), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(20, 20), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -4727,9 +4764,9 @@ TEST_F(LayerTreeHostImplTestMultiScrollable,
// Scroll on child should flash all scrollbars.
host_impl_->ScrollBegin(BeginState(gfx::Point(70, 70), gfx::Vector2dF(0, 100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(70, 70), gfx::Vector2d(0, 100)).get());
host_impl_->ScrollEnd();
@@ -4808,10 +4845,11 @@ TEST_F(LayerTreeHostImplTest, ScrollHitTestOnScrollbar) {
// Wheel scroll on root scrollbar should process on impl thread.
{
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(1, 1), gfx::Vector2dF(), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(1, 1), gfx::Vector2dF(),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
host_impl_->ScrollEnd();
}
@@ -4820,9 +4858,9 @@ TEST_F(LayerTreeHostImplTest, ScrollHitTestOnScrollbar) {
{
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(1, 1), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling,
status.main_thread_scrolling_reasons);
@@ -4832,9 +4870,9 @@ TEST_F(LayerTreeHostImplTest, ScrollHitTestOnScrollbar) {
{
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(51, 51), gfx::Vector2dF(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -4845,9 +4883,9 @@ TEST_F(LayerTreeHostImplTest, ScrollHitTestOnScrollbar) {
{
InputHandler::ScrollStatus status =
host_impl_->ScrollBegin(BeginState(gfx::Point(51, 51), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling,
status.main_thread_scrolling_reasons);
@@ -4992,13 +5030,13 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) {
// Scrolling the viewport should result in a scrollbar animation update.
animation_task_.Reset();
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(10, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(10, 10), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(10, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(10, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_FALSE(animation_task_.is_null());
animation_task_.Reset();
@@ -5052,11 +5090,13 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeMouseMove) {
SetupViewportLayersInnerScrolls(viewport_size, content_size);
auto* root_scroll = OuterViewportScrollLayer();
+ const int kScrollbarThickness = 5;
auto* vert_scrollbar = AddLayer<SolidColorScrollbarLayerImpl>(
- host_impl_->active_tree(), VERTICAL, 5, 0, false);
+ host_impl_->active_tree(), VERTICAL, kScrollbarThickness, 0, false);
SetupScrollbarLayer(root_scroll, vert_scrollbar);
vert_scrollbar->SetBounds(gfx::Size(10, 200));
- vert_scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(300, 0));
+ vert_scrollbar->SetOffsetToTransformParent(
+ gfx::Vector2dF(300 - kScrollbarThickness, 0));
host_impl_->active_tree()->UpdateScrollbarGeometries();
@@ -5066,26 +5106,27 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeMouseMove) {
root_scroll->element_id());
const float kDistanceToTriggerThumb =
+ vert_scrollbar->ComputeThumbQuadRect().height() +
SingleScrollbarAnimationControllerThinning::
kMouseMoveDistanceToTriggerExpand;
- // Move the mouse near the thumb in the top position.
- auto near_thumb_at_top = gfx::Point(300, -kDistanceToTriggerThumb + 1);
+ // Move the mouse near the thumb while its at the viewport top.
+ auto near_thumb_at_top = gfx::Point(295, kDistanceToTriggerThumb - 1);
host_impl_->MouseMoveAt(near_thumb_at_top);
EXPECT_TRUE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL));
// Move the mouse away from the thumb.
- host_impl_->MouseMoveAt(gfx::Point(300, -kDistanceToTriggerThumb - 1));
+ host_impl_->MouseMoveAt(gfx::Point(295, kDistanceToTriggerThumb + 1));
EXPECT_FALSE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL));
- // Scroll the page down which moves the thumb down.
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 100), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 100), ScrollInputType::kWheel)
- .get());
+ // Scroll the page down which moves the thumb down to the viewport bottom.
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 800),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 800),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
// Move the mouse near the thumb in the top position.
@@ -5093,13 +5134,13 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeMouseMove) {
EXPECT_FALSE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL));
// Scroll the page up which moves the thumb back up.
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, -100), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, -100), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -800),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -800),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
// Move the mouse near the thumb in the top position.
@@ -5316,13 +5357,13 @@ TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
{
viz::CompositorFrameMetadata metadata =
host_impl_->MakeCompositorFrameMetadata();
@@ -5336,10 +5377,10 @@ TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
}
// Page scale should update metadata correctly (shrinking only the viewport).
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kTouchscreen)
- .get(),
- ScrollInputType::kTouchscreen);
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -5870,10 +5911,11 @@ TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
DrawFrame();
// Scroll event is ignored because layer is not scrollable.
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
@@ -6005,9 +6047,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->browser_controls_manager()->ScrollBegin();
@@ -6062,9 +6104,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
ASSERT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
// Hide the browser controls by 25px. The outer clip should expand by 50px as
@@ -6072,7 +6114,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
// case 0.5. Therefore, changes to the outer viewport need to be divided by
// the minimum scale as well.
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0), gfx::Vector2dF(0, 25),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VIEWPORT_GEOMETRIES(0.5f);
@@ -6112,9 +6154,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 25),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->browser_controls_manager()->ScrollBegin();
@@ -6167,9 +6209,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), top_controls_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
// Make the test scroll delta a fractional amount, to verify that the
@@ -6207,12 +6249,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, 50),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
// The entire scroll delta should have been used to hide the browser controls.
@@ -6224,7 +6266,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
// The inner viewport should be scrollable by 50px * page_scale.
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(50, CurrentScrollOffset(inner_scroll).y());
EXPECT_EQ(0, CurrentScrollOffset(outer_scroll).y());
@@ -6235,15 +6277,15 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -50),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
outer_scroll->scroll_tree_index());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, -50),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
// The entire scroll delta should have been used to show the browser controls.
@@ -6258,19 +6300,19 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
// Now when we continue scrolling, make sure the outer viewport gets scrolled
// since it wasn't scrollable when the scroll began.
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, -20),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(25, CurrentScrollOffset(outer_scroll).y());
EXPECT_EQ(15, CurrentScrollOffset(inner_scroll).y());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, -30),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(25, CurrentScrollOffset(outer_scroll).y());
EXPECT_EQ(0, CurrentScrollOffset(inner_scroll).y());
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0.f, -50),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -6296,9 +6338,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, FixedContainerDelta) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), top_controls_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
// Scroll down, the browser controls hiding should expand the viewport size so
@@ -6319,9 +6361,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, FixedContainerDelta) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), top_controls_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->browser_controls_manager()->ScrollBegin();
host_impl_->browser_controls_manager()->ScrollBy(top_controls_scroll_delta);
@@ -6337,9 +6379,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, FixedContainerDelta) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), -top_controls_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->browser_controls_manager()->ScrollBegin();
host_impl_->browser_controls_manager()->ScrollBy(-top_controls_scroll_delta);
@@ -6410,12 +6452,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -6611,12 +6653,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
// scrolling down at the max extents no longer hides the browser controls
@@ -6642,12 +6684,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -6676,12 +6718,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, BrowserControlsAspectRatio) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -6718,12 +6760,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(OuterViewportScrollLayer()->scroll_tree_index(),
@@ -6739,12 +6781,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ContentTopOffset());
@@ -6762,12 +6804,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(top_controls_height_,
@@ -6788,9 +6830,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 50),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->browser_controls_manager()->ScrollBegin();
@@ -6807,9 +6849,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -25),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
float scroll_increment_y = -25;
@@ -6839,9 +6881,9 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
}
@@ -6878,11 +6920,11 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
// Fully scroll the viewport.
host_impl_->ScrollBegin(
BeginState(gfx::Point(75, 75), gfx::Vector2dF(0, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
}
@@ -7000,13 +7042,13 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
@@ -7029,13 +7071,13 @@ TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
@@ -7052,9 +7094,9 @@ TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
// boundaries.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(15, 5), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
@@ -7080,9 +7122,9 @@ TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
// viewer and there is nothing scrollable behind it.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
@@ -7110,9 +7152,9 @@ TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
// main thread.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
status.main_thread_scrolling_reasons);
@@ -7134,12 +7176,13 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
// Set new page scale from main thread.
@@ -7176,20 +7219,21 @@ TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
// Set new page scale on impl thread by pinching.
float page_scale = 2;
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kTouchscreen)
- .get(),
- ScrollInputType::kTouchscreen);
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -7235,10 +7279,10 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
UpdateDrawProperties(host_impl_->active_tree());
// Set new page scale on impl thread by pinching.
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kTouchscreen)
- .get(),
- ScrollInputType::kTouchscreen);
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -7274,12 +7318,13 @@ TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
float page_scale = 2;
@@ -7331,12 +7376,13 @@ TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -7388,9 +7434,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, -100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, -100)).get());
@@ -7472,13 +7518,13 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
host_impl_->ScrollEnd();
std::unique_ptr<ScrollAndScaleSet> scroll_info =
@@ -7497,15 +7543,15 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
child_layer->scroll_tree_index());
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
child_layer->scroll_tree_index());
host_impl_->ScrollEnd();
@@ -7528,15 +7574,15 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
grand_child_layer->scroll_tree_index());
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
grand_child_layer->scroll_tree_index());
host_impl_->ScrollEnd();
@@ -7561,15 +7607,15 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(1, 1), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(grand_child_layer->scroll_tree_index(),
host_impl_->CurrentlyScrollingNode()->id);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
host_impl_->ScrollEnd();
scroll_info = host_impl_->ProcessScrollDeltas();
@@ -7606,13 +7652,13 @@ TEST_F(LayerTreeHostImplTest, ChildrenOfInnerScrollNodeCanScrollOnThread) {
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5),
gfx::ScrollOffsetToVector2dF(scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -7649,13 +7695,13 @@ TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5),
gfx::ScrollOffsetToVector2dF(scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -7688,9 +7734,9 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
}
@@ -7711,12 +7757,12 @@ TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gesture_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gesture_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -7735,14 +7781,14 @@ TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
->ScrollBegin(
BeginState(gfx::Point(),
gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
UpdateState(gfx::Point(),
gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -7790,12 +7836,12 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(1, 1), gesture_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gesture_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -7821,12 +7867,12 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(1, 1), gesture_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gesture_scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -7904,14 +7950,14 @@ TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) {
->ScrollBegin(BeginState(viewport_point,
gfx::ScrollOffsetToVector2dF(
gesture_scroll_deltas[i]),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
UpdateState(viewport_point,
gfx::ScrollOffsetToVector2dF(gesture_scroll_deltas[i]),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
viewport_point +=
gfx::ScrollOffsetToFlooredVector2d(gesture_scroll_deltas[i]);
@@ -7944,12 +7990,12 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -7969,14 +8015,14 @@ TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
->ScrollBegin(
BeginState(gfx::Point(),
gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
UpdateState(gfx::Point(),
gfx::ScrollOffsetToVector2dF(wheel_scroll_delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
host_impl_->ScrollEnd();
@@ -8055,10 +8101,10 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
// The pinch gesture doesn't put the delegate into a state where the scroll
// offset is outside of the scroll range. (this is verified by DCHECKs in the
// delegate).
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kTouchscreen)
- .get(),
- ScrollInputType::kTouchscreen);
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, gfx::Point());
host_impl_->PinchGestureUpdate(.5f, gfx::Point());
@@ -8072,14 +8118,14 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
scroll_watcher.last_set_scroll_offset());
@@ -8087,7 +8133,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
current_offset = gfx::ScrollOffset(42, 41);
host_impl_->SetSynchronousInputHandlerRootScrollOffset(current_offset);
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
scroll_watcher.last_set_scroll_offset());
@@ -8182,17 +8228,17 @@ TEST_F(LayerTreeHostImplTest, ViewportUserScrollable) {
gfx::Vector2dF scroll_delta(30 * page_scale_factor, 0);
{
- auto begin_state =
- BeginState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen);
+ auto begin_state = BeginState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
- ->ScrollBegin(begin_state.get(), ScrollInputType::kTouchscreen)
+ ->ScrollBegin(begin_state.get(), ui::ScrollInputType::kTouchscreen)
.thread);
// Try scrolling right, the inner viewport should be allowed to scroll.
- auto update_state =
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen);
+ auto update_state = UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(update_state.get());
EXPECT_VECTOR_EQ(gfx::ScrollOffset(30, 0),
@@ -8202,14 +8248,14 @@ TEST_F(LayerTreeHostImplTest, ViewportUserScrollable) {
// Continue scrolling. The inner viewport should scroll until its extent,
// however, the outer viewport should not accept any scroll.
- update_state =
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen);
+ update_state = UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(update_state.get());
- update_state =
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen);
+ update_state = UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(update_state.get());
- update_state =
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen);
+ update_state = UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(update_state.get());
EXPECT_VECTOR_EQ(gfx::ScrollOffset(50, 0),
@@ -8226,10 +8272,10 @@ TEST_F(LayerTreeHostImplTest, ViewportUserScrollable) {
{
auto begin_state =
- BeginState(gfx::Point(), scroll_delta, ScrollInputType::kWheel);
+ BeginState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel);
EXPECT_EQ(
InputHandler::SCROLL_ON_IMPL_THREAD,
- host_impl_->ScrollBegin(begin_state.get(), ScrollInputType::kWheel)
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel)
.thread);
// Try scrolling right, the inner viewport should be allowed to scroll.
@@ -8453,22 +8499,24 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
// Overscroll events are reflected immediately.
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 50), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 50),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
@@ -8477,9 +8525,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
host_impl_->accumulated_root_overscroll());
// In-bounds scrolling resets accumulated overscroll for the scrolled axes.
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, -50), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -50),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
@@ -8487,9 +8536,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, -10), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -10),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
@@ -8497,9 +8547,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(10, 0), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(10, 0),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
@@ -8507,9 +8558,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(-15, 0), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(-15, 0),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
@@ -8517,9 +8569,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 60), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 60),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
@@ -8527,9 +8580,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(10, -60), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(10, -60),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
@@ -8539,9 +8593,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
// Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
// as no scroll occurs.
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, -20), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -20),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
@@ -8549,9 +8604,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, -20), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -20),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
@@ -8560,9 +8616,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
host_impl_->accumulated_root_overscroll());
// Overscroll resets on valid scroll.
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
@@ -8570,9 +8627,10 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
EXPECT_EQ(scroll_result.accumulated_root_overscroll,
host_impl_->accumulated_root_overscroll());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, -20), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -20),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
@@ -8615,13 +8673,14 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
grand_child_layer->scroll_tree_index());
EXPECT_TRUE(scroll_result.did_scroll);
@@ -8635,9 +8694,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
child_layer->scroll_tree_index());
@@ -8647,13 +8706,14 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
@@ -8667,15 +8727,16 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
grand_child_layer->scroll_tree_index());
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
@@ -8697,22 +8758,25 @@ TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
@@ -8736,13 +8800,14 @@ TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
- scroll_result = host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ scroll_result =
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
@@ -8762,13 +8827,13 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
scroll_result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::Vector2dF(0, 100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
@@ -8776,7 +8841,7 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
host_impl_->accumulated_root_overscroll().ToString());
scroll_result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::Vector2dF(0, -2.30f),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
@@ -8789,13 +8854,13 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 20),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
scroll_result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::Vector2dF(0, 20),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_TRUE(scroll_result.did_scroll);
EXPECT_TRUE(scroll_result.did_overscroll_root);
@@ -8804,7 +8869,7 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
scroll_result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
@@ -8817,13 +8882,13 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
host_impl_
->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(-0.12f, 0.1f),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
scroll_result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
EXPECT_FALSE(scroll_result.did_scroll);
EXPECT_FALSE(scroll_result.did_overscroll_root);
@@ -8851,12 +8916,12 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) {
{
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100),
@@ -8870,7 +8935,7 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) {
{
InputHandlerScrollResult result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(0, 0), gfx::Vector2dF(120, 140),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200),
@@ -8885,7 +8950,7 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) {
{
InputHandlerScrollResult result = host_impl_->ScrollUpdate(
UpdateState(gfx::Point(0, 0), gfx::Vector2dF(20, 40),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200),
@@ -8920,9 +8985,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnMainThread) {
InputHandler::SCROLL_ON_MAIN_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(0, 60), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
// Overscroll initiated inside layers will be handled by the main thread.
@@ -8932,9 +8997,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnMainThread) {
InputHandler::SCROLL_ON_MAIN_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
}
@@ -8968,12 +9033,12 @@ TEST_F(LayerTreeHostImplTest, ScrollFromOuterViewportSibling) {
{
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -8990,21 +9055,21 @@ TEST_F(LayerTreeHostImplTest, ScrollFromOuterViewportSibling) {
{
gfx::Vector2d scroll_delta(0, 10);
host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ ui::ScrollInputType::kTouchscreen);
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_EQ(0, host_impl_->active_tree()->CurrentTopControlsShownRatio());
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll_layer));
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 10),
CurrentScrollOffset(inner_scroll_layer));
@@ -9047,12 +9112,12 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) {
{
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(200, 200),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(200, 200),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9061,12 +9126,12 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) {
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(200, 200),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(200, 200),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9083,12 +9148,12 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) {
{
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9113,12 +9178,12 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) {
{
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9127,12 +9192,12 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) {
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9181,12 +9246,12 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
// This should fully scroll the layer.
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9198,12 +9263,12 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
// rather than an ancestor, we shouldn't chain to it.
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(1000, 1000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9231,9 +9296,9 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
page_scale_factor = 2;
gfx::Point anchor(viewport_size.width() / 2, viewport_size.height() / 2);
host_impl_->ScrollBegin(
- BeginState(anchor, gfx::Vector2dF(), ScrollInputType::kTouchscreen)
+ BeginState(anchor, gfx::Vector2dF(), ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_factor, anchor);
host_impl_->PinchGestureEnd(anchor, true);
@@ -9241,9 +9306,9 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
EXPECT_VECTOR_EQ(gfx::Vector2dF(anchor.x() / 2, anchor.y() / 2),
CurrentScrollOffset(inner_scroll_layer));
- host_impl_->ScrollUpdate(
- UpdateState(anchor, viewport_size_vec, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(anchor, viewport_size_vec,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_VECTOR_EQ(ScaleVector2d(viewport_size_vec, 1 / page_scale_factor),
CurrentScrollOffset(inner_scroll_layer));
@@ -9271,12 +9336,12 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
// scroller, it shouldn't chain up to the inner viewport yet.
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(2000, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9287,12 +9352,12 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
// Scrolling now should chain up to the inner viewport.
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(2000, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9303,12 +9368,12 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) {
// No more scrolling should be possible.
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(2000, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(2000, 2000),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -9339,9 +9404,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnImplThread) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(0, 60), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollEnd();
@@ -9353,9 +9418,9 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnImplThread) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
}
@@ -10793,10 +10858,11 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
DrawFrame();
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest,
status.main_thread_scrolling_reasons);
@@ -10828,10 +10894,11 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
DrawFrame();
- InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(0, 10), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ InputHandler::ScrollStatus status =
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest,
status.main_thread_scrolling_reasons);
@@ -10854,9 +10921,9 @@ TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_EQ(child_scroll->scroll_tree_index(),
@@ -11041,14 +11108,14 @@ TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
host_impl_->ScrollEnd();
@@ -11062,14 +11129,14 @@ TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
host_impl_->ScrollEnd();
@@ -11171,18 +11238,18 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
CurrentScrollOffset(scroll_layer).ToString());
- result = host_impl_->ScrollUpdate(UpdateState(gfx::Point(),
- gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
- .get());
+ result = host_impl_->ScrollUpdate(
+ UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_TRUE(result.did_scroll);
EXPECT_FLOAT_EQ(-offset,
@@ -11193,10 +11260,10 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
// Scroll across the boundary
const float content_scroll = 20;
offset = residue + content_scroll;
- result = host_impl_->ScrollUpdate(UpdateState(gfx::Point(),
- gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
- .get());
+ result = host_impl_->ScrollUpdate(
+ UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_TRUE(result.did_scroll);
EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_EQ(-top_controls_height_,
@@ -11206,10 +11273,10 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
// Now scroll back to the top of the content
offset = -content_scroll;
- result = host_impl_->ScrollUpdate(UpdateState(gfx::Point(),
- gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
- .get());
+ result = host_impl_->ScrollUpdate(
+ UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_TRUE(result.did_scroll);
EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_EQ(-top_controls_height_,
@@ -11219,10 +11286,10 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
// And scroll the browser controls completely into view
offset = -top_controls_height_;
- result = host_impl_->ScrollUpdate(UpdateState(gfx::Point(),
- gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
- .get());
+ result = host_impl_->ScrollUpdate(
+ UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_TRUE(result.did_scroll);
EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -11230,10 +11297,10 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
CurrentScrollOffset(scroll_layer).ToString());
// And attempt to scroll past the end
- result = host_impl_->ScrollUpdate(UpdateState(gfx::Point(),
- gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
- .get());
+ result = host_impl_->ScrollUpdate(
+ UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
+ ui::ScrollInputType::kTouchscreen)
+ .get());
EXPECT_FALSE(result.did_scroll);
EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
@@ -11258,9 +11325,9 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(viewport_layer));
@@ -11270,7 +11337,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get())
.did_scroll);
EXPECT_FLOAT_EQ(0,
@@ -11281,7 +11348,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, delta),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get())
.did_scroll);
EXPECT_FLOAT_EQ(0,
@@ -11306,9 +11373,9 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -11318,7 +11385,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_FLOAT_EQ(-offset,
@@ -11397,9 +11464,9 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
@@ -11409,7 +11476,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_FLOAT_EQ(-offset,
@@ -11475,16 +11542,16 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset());
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_EQ(-offset,
@@ -11495,7 +11562,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
@@ -11504,7 +11571,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
@@ -11519,7 +11586,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(),
gfx::Vector2d(0, overscrollamount),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
@@ -11530,7 +11597,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(host_impl_
->ScrollUpdate(UpdateState(gfx::Point(),
gfx::Vector2d(0, -2 * offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
@@ -11541,7 +11608,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest,
EXPECT_TRUE(
host_impl_
->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -offset),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get())
.did_scroll);
EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
@@ -11591,12 +11658,12 @@ TEST_F(LayerTreeHostImplBrowserControlsTest,
{
host_impl_->ScrollBegin(
BeginState(gfx::Point(0, 0), gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(0, 0),
gfx::Vector2dF(100, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
host_impl_->ScrollEnd();
@@ -11666,18 +11733,16 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
// Scroll near the edge of the outer viewport.
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kTouchscreen)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), scroll_delta,
+ ui::ScrollInputType::kTouchscreen)
+ .get());
inner_expected += scroll_delta;
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
EXPECT_VECTOR_EQ(inner_expected, CurrentScrollOffset(inner_scroll));
EXPECT_VECTOR_EQ(outer_expected, CurrentScrollOffset(outer_scroll));
@@ -11687,13 +11752,11 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
// and outer viewport layers is perfect.
host_impl_->ScrollUpdate(UpdateState(gfx::Point(),
gfx::ScaleVector2d(scroll_delta, 2),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
outer_expected += scroll_delta;
inner_expected += scroll_delta;
host_impl_->ScrollEnd();
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
EXPECT_VECTOR_EQ(inner_expected, CurrentScrollOffset(inner_scroll));
EXPECT_VECTOR_EQ(outer_expected, CurrentScrollOffset(outer_scroll));
@@ -11720,9 +11783,9 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->RootScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode(),
host_impl_->OuterViewportScrollNode());
@@ -11730,9 +11793,9 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
EXPECT_EQ(host_impl_->CurrentlyScrollingNode()->id,
child_scroll->scroll_tree_index());
@@ -11759,13 +11822,13 @@ TEST_F(LayerTreeHostImplVirtualViewportTest,
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
scroll_result =
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2dF(0, 100),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll));
@@ -12143,9 +12206,9 @@ TEST_F(LayerTreeHostImplTest, MacWheelIsNonAnimated) {
ASSERT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get());
@@ -12181,9 +12244,9 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get());
@@ -12283,8 +12346,8 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimatedLatching) {
{
gfx::Point position(40, 40);
auto begin_state =
- BeginState(position, gfx::Vector2d(0, 50), ScrollInputType::kWheel);
- host_impl_->ScrollBegin(begin_state.get(), ScrollInputType::kWheel);
+ BeginState(position, gfx::Vector2d(0, 50), ui::ScrollInputType::kWheel);
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel);
auto update_state = AnimatedUpdateState(position, gfx::Vector2d(0, 50));
host_impl_->ScrollUpdate(update_state.get());
EXPECT_EQ(outer_scroll->scroll_tree_index(),
@@ -12329,8 +12392,8 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimatedLatching) {
{
gfx::Point position(10, 10);
auto begin_state =
- BeginState(position, gfx::Vector2d(0, 50), ScrollInputType::kWheel);
- host_impl_->ScrollBegin(begin_state.get(), ScrollInputType::kWheel);
+ BeginState(position, gfx::Vector2d(0, 50), ui::ScrollInputType::kWheel);
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel);
EXPECT_EQ(outer_scroll->scroll_tree_index(),
host_impl_->CurrentlyScrollingNode()->id);
}
@@ -12388,9 +12451,9 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimatedWhileZoomed) {
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2d(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(10, 10), gfx::Vector2d(0, 10)).get());
@@ -12463,8 +12526,8 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimatedUpdateInnerViewport) {
// Start an animated scroll on the inner viewport.
{
auto begin_state = BeginState(gfx::Point(10, 10), gfx::Vector2d(0, 60),
- ScrollInputType::kWheel);
- host_impl_->ScrollBegin(begin_state.get(), ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(10, 10), gfx::Vector2d(0, 60)).get());
@@ -12569,9 +12632,9 @@ TEST_F(LayerTreeHostImplTest, FadedOutPaintedOverlayScrollbarHitTest) {
// Set up the scroll node and other state required for scrolling.
host_impl_->ScrollBegin(BeginState(gfx::Point(350, 18), gfx::Vector2dF(),
- ScrollInputType::kScrollbar)
+ ui::ScrollInputType::kScrollbar)
.get(),
- ScrollInputType::kScrollbar);
+ ui::ScrollInputType::kScrollbar);
TestInputHandlerClient input_handler_client;
host_impl_->BindToClient(&input_handler_client);
@@ -12656,9 +12719,9 @@ TEST_F(LayerTreeHostImplTest, PointerMoveOutOfSequence) {
begin_frame_args.frame_id.sequence_number++;
host_impl_->WillBeginImplFrame(begin_frame_args);
host_impl_->ScrollBegin(BeginState(gfx::Point(350, 18), gfx::Vector2dF(),
- ScrollInputType::kScrollbar)
+ ui::ScrollInputType::kScrollbar)
.get(),
- ScrollInputType::kScrollbar);
+ ui::ScrollInputType::kScrollbar);
EXPECT_TRUE(host_impl_->CurrentlyScrollingNode());
// The PointerMove(s) that follow should be handled and are expected to have a
@@ -12759,9 +12822,9 @@ TEST_F(LayerTreeHostImplTest, SingleGSUForScrollbarThumbDragPerFrame) {
scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0));
host_impl_->ScrollBegin(BeginState(gfx::Point(350, 18), gfx::Vector2dF(),
- ScrollInputType::kScrollbar)
+ ui::ScrollInputType::kScrollbar)
.get(),
- ScrollInputType::kScrollbar);
+ ui::ScrollInputType::kScrollbar);
TestInputHandlerClient input_handler_client;
host_impl_->BindToClient(&input_handler_client);
@@ -12812,6 +12875,213 @@ TEST_F(LayerTreeHostImplTest, SingleGSUForScrollbarThumbDragPerFrame) {
host_impl_ = nullptr;
}
+// Tests that an animated scrollbar scroll aborts when a different device (like
+// a mousewheel) wants to animate the scroll offset.
+TEST_F(LayerTreeHostImplTest, AnimatedScrollYielding) {
+ LayerTreeSettings settings = DefaultSettings();
+ settings.compositor_threaded_scrollbar_scrolling = true;
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+
+ // Setup the viewport.
+ const gfx::Size viewport_size = gfx::Size(360, 600);
+ const gfx::Size content_size = gfx::Size(345, 3800);
+ SetupViewportLayersOuterScrolls(viewport_size, content_size);
+ LayerImpl* scroll_layer = OuterViewportScrollLayer();
+
+ // Set up the scrollbar and its dimensions.
+ LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
+ auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(
+ layer_tree_impl, VERTICAL, /*is_left_side_vertical_scrollbar*/ false,
+ /*is_overlay*/ false);
+
+ // TODO(arakeri): crbug.com/1070063 Setting the dimensions for scrollbar parts
+ // (like thumb, track etc) should be moved to SetupScrollbarLayer.
+ SetupScrollbarLayer(scroll_layer, scrollbar);
+ const gfx::Size scrollbar_size = gfx::Size(15, 600);
+ scrollbar->SetBounds(scrollbar_size);
+ host_impl_->set_force_smooth_wheel_scrolling_for_testing(true);
+
+ // Set up the thumb dimensions.
+ scrollbar->SetThumbThickness(15);
+ scrollbar->SetThumbLength(50);
+ scrollbar->SetTrackRect(gfx::Rect(0, 15, 15, 575));
+
+ // Set up scrollbar arrows.
+ scrollbar->SetBackButtonRect(
+ gfx::Rect(gfx::Point(345, 0), gfx::Size(15, 15)));
+ scrollbar->SetForwardButtonRect(
+ gfx::Rect(gfx::Point(345, 570), gfx::Size(15, 15)));
+ scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0));
+
+ TestInputHandlerClient input_handler_client;
+ host_impl_->BindToClient(&input_handler_client);
+
+ {
+ // Set up an animated scrollbar autoscroll.
+ host_impl_->scrollbar_controller_for_testing()->HandlePointerDown(
+ gfx::PointF(350, 560), /*shift_modifier*/ false);
+ auto begin_state = BeginState(gfx::Point(350, 560), gfx::Vector2d(0, 40),
+ ui::ScrollInputType::kScrollbar);
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_
+ ->ScrollBegin(begin_state.get(), ui::ScrollInputType::kScrollbar)
+ .thread);
+ auto update_state = UpdateState(gfx::Point(350, 560), gfx::Vector2dF(0, 40),
+ ui::ScrollInputType::kScrollbar);
+ update_state->data()->delta_granularity =
+ ui::ScrollGranularity::kScrollByPixel;
+ host_impl_->ScrollUpdate(update_state.get());
+
+ // Autoscroll animations should be active.
+ EXPECT_TRUE(host_impl_->scrollbar_controller_for_testing()
+ ->ScrollbarScrollIsActive());
+ EXPECT_TRUE(GetImplAnimationHost()->ImplOnlyScrollAnimatingElement());
+ }
+
+ {
+ // While the cc autoscroll is in progress, a mousewheel tick takes place.
+ auto begin_state = BeginState(gfx::Point(), gfx::Vector2d(350, 560),
+ ui::ScrollInputType::kWheel);
+ begin_state->data()->delta_granularity =
+ ui::ScrollGranularity::kScrollByPixel;
+
+ // InputHandlerProxy calls LayerTreeHostImpl::ScrollEnd to end the
+ // autoscroll as it has detected a device change.
+ host_impl_->ScrollEnd();
+
+ // This then leads to ScrollbarController::ResetState getting called which
+ // clears ScrollbarController::autoscroll_state_,
+ // captured_scrollbar_metadata_ etc. That means
+ // ScrollbarController::ScrollbarLayer should return null.
+ EXPECT_FALSE(
+ host_impl_->scrollbar_controller_for_testing()->ScrollbarLayer());
+
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel)
+ .thread);
+
+ // Autoscroll animation should be aborted at this point.
+ EXPECT_FALSE(GetImplAnimationHost()->ImplOnlyScrollAnimatingElement());
+ host_impl_->ScrollUpdate(
+ AnimatedUpdateState(gfx::Point(350, 560), gfx::Vector2d(0, 40)).get());
+
+ // Mousewheel animation should be active.
+ EXPECT_TRUE(GetImplAnimationHost()->ImplOnlyScrollAnimatingElement());
+
+ // This should not trigger any DCHECKs and will be a no-op.
+ host_impl_->scrollbar_controller_for_testing()->WillBeginImplFrame();
+ }
+
+ // Tear down the LayerTreeHostImpl before the InputHandlerClient.
+ host_impl_->ReleaseLayerTreeFrameSink();
+ host_impl_ = nullptr;
+}
+
+// Tests that changing the scroller length in the middle of a thumb drag doesn't
+// cause the scroller to jump.
+TEST_F(LayerTreeHostImplTest, ThumbDragScrollerLengthIncrease) {
+ LayerTreeSettings settings = DefaultSettings();
+ settings.compositor_threaded_scrollbar_scrolling = true;
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+
+ // Setup the viewport.
+ const gfx::Size viewport_size = gfx::Size(360, 600);
+ const gfx::Size content_size = gfx::Size(345, 3800);
+ SetupViewportLayersOuterScrolls(viewport_size, content_size);
+ LayerImpl* scroll_layer = OuterViewportScrollLayer();
+
+ // Set up the scrollbar and its dimensions.
+ LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
+ auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(
+ layer_tree_impl, VERTICAL, /*is_left_side_vertical_scrollbar*/ false,
+ /*is_overlay*/ false);
+
+ // TODO(arakeri): crbug.com/1070063 Setting the dimensions for scrollbar parts
+ // (like thumb, track etc) should be moved to SetupScrollbarLayer.
+ SetupScrollbarLayer(scroll_layer, scrollbar);
+ const gfx::Size scrollbar_size = gfx::Size(15, 600);
+ scrollbar->SetBounds(scrollbar_size);
+
+ // Set up the thumb dimensions.
+ scrollbar->SetThumbThickness(15);
+ scrollbar->SetThumbLength(50);
+ scrollbar->SetTrackRect(gfx::Rect(0, 15, 15, 575));
+
+ // Set up scrollbar arrows.
+ scrollbar->SetBackButtonRect(
+ gfx::Rect(gfx::Point(345, 0), gfx::Size(15, 15)));
+ scrollbar->SetForwardButtonRect(
+ gfx::Rect(gfx::Point(345, 570), gfx::Size(15, 15)));
+ scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0));
+
+ TestInputHandlerClient input_handler_client;
+ host_impl_->BindToClient(&input_handler_client);
+
+ // ----------------------------- Start frame 0 -----------------------------
+ viz::BeginFrameArgs begin_frame_args =
+ viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+ base::TimeTicks start_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(200);
+ begin_frame_args.frame_time = start_time;
+ begin_frame_args.frame_id.sequence_number++;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ InputHandlerPointerResult result =
+ host_impl_->MouseDown(gfx::PointF(350, 18), /*shift_modifier*/ false);
+ EXPECT_EQ(result.scroll_offset.y(), 0);
+ EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll);
+ host_impl_->DidFinishImplFrame(begin_frame_args);
+
+ // ----------------------------- Start frame 1 -----------------------------
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(250);
+ begin_frame_args.frame_id.sequence_number++;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+
+ result = host_impl_->MouseMoveAt(gfx::Point(350, 20));
+ EXPECT_EQ(result.scroll_offset.y(), 12);
+
+ // This is intentional. The thumb drags that follow will test the behavior
+ // *after* the scroller length expansion.
+ scrollbar->SetScrollLayerLength(7000);
+ host_impl_->DidFinishImplFrame(begin_frame_args);
+
+ // ----------------------------- Start frame 2 -----------------------------
+ // The very first mousemove after the scroller length change will result in a
+ // zero offset. This is done to ensure that the scroller doesn't jump ahead
+ // when the length changes mid thumb drag. So, every time the scroller length
+ // changes mid thumb drag, a GSU is lost (in the worst case).
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(300);
+ begin_frame_args.frame_id.sequence_number++;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ result = host_impl_->MouseMoveAt(gfx::Point(350, 22));
+ EXPECT_EQ(result.scroll_offset.y(), 0);
+ host_impl_->DidFinishImplFrame(begin_frame_args);
+
+ // ----------------------------- Start frame 3 -----------------------------
+ // All subsequent mousemoves then produce deltas which are "displaced" by a
+ // certain amount. The previous mousemove (to y = 22) would have calculated
+ // the drag_state_->scroller_displacement value as 48 (based on the pointer
+ // movement). The current pointermove (to y = 26) calculates the delta as 97.
+ // Since delta -= drag_state_->scroller_displacement, the actual delta becomes
+ // 97 - 48 which is 49. The math that calculates the deltas (i.e 97 and 48)
+ // can be found in ScrollbarController::GetScrollDeltaForDragPosition.
+ begin_frame_args.frame_time =
+ start_time + base::TimeDelta::FromMilliseconds(350);
+ begin_frame_args.frame_id.sequence_number++;
+ host_impl_->WillBeginImplFrame(begin_frame_args);
+ result = host_impl_->MouseMoveAt(gfx::Point(350, 26));
+ EXPECT_EQ(result.scroll_offset.y(), 49);
+ host_impl_->MouseUp(gfx::PointF(350, 26));
+ host_impl_->DidFinishImplFrame(begin_frame_args);
+
+ // Tear down the LayerTreeHostImpl before the InputHandlerClient.
+ host_impl_->ReleaseLayerTreeFrameSink();
+ host_impl_ = nullptr;
+}
+
TEST_F(LayerTreeHostImplTest, MainThreadFallback) {
LayerTreeSettings settings = DefaultSettings();
settings.compositor_threaded_scrollbar_scrolling = true;
@@ -12876,9 +13146,9 @@ TEST_F(LayerTreeHostImplTest, SecondScrollAnimatedBeginNotIgnored) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollEnd();
@@ -12887,9 +13157,9 @@ TEST_F(LayerTreeHostImplTest, SecondScrollAnimatedBeginNotIgnored) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
}
@@ -12916,9 +13186,9 @@ TEST_F(LayerTreeHostImplTest, AnimatedScrollUpdateTargetBeforeStarting) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get());
@@ -12969,9 +13239,9 @@ TEST_F(LayerTreeHostImplTest, ScrollAnimatedWithDelay) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 100),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 100)).get(),
@@ -13035,9 +13305,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get());
@@ -13073,22 +13343,20 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) {
// Perform instant scroll.
// Use "precise pixel" granularity to avoid animating.
auto begin_state = BeginState(gfx::Point(0, y), gfx::Vector2dF(0, 50),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
begin_state->data()->delta_granularity =
ui::ScrollGranularity::kScrollByPrecisePixel;
- EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
- host_impl_->ScrollBegin(begin_state.get(), ScrollInputType::kWheel)
- .thread);
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y)));
+ EXPECT_EQ(
+ InputHandler::SCROLL_ON_IMPL_THREAD,
+ host_impl_->ScrollBegin(begin_state.get(), ui::ScrollInputType::kWheel)
+ .thread);
auto update_state = UpdateState(gfx::Point(0, y), gfx::Vector2d(0, 50),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
// Use "precise pixel" granularity to avoid animating.
update_state->data()->delta_granularity =
ui::ScrollGranularity::kScrollByPrecisePixel;
host_impl_->ScrollUpdate(update_state.get());
- EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y + 50)));
host_impl_->ScrollEnd();
- EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point()));
// The instant scroll should have marked the smooth scroll animation as
// aborted.
@@ -13118,9 +13386,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get());
@@ -13208,9 +13476,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimated) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(10, 20),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(10, 20)).get());
@@ -13304,9 +13572,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimatedUpdate) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(90, 90),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(90, 90)).get());
@@ -13368,9 +13636,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedNotUserScrollable) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(50, 50),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(50, 50)).get());
@@ -13452,10 +13720,10 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedChangingBounds) {
viz::BeginFrameArgs begin_frame_args =
viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2d(500, 500), ScrollInputType::kWheel)
- .get(),
- ScrollInputType::kWheel);
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(500, 500),
+ ui::ScrollInputType::kWheel)
+ .get(),
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(
AnimatedUpdateState(gfx::Point(), gfx::Vector2d(500, 500)).get());
@@ -13571,9 +13839,9 @@ TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
float page_scale_delta = 2;
host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -13583,14 +13851,15 @@ TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer));
host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), scroll_delta, ScrollInputType::kWheel).get());
+ UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel)
+ .get());
host_impl_->ScrollEnd();
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5), CurrentScrollOffset(scroll_layer));
}
@@ -14649,13 +14918,13 @@ TEST_F(LayerTreeHostImplTest, RenderFrameMetadata) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.thread);
- host_impl_->ScrollUpdate(
- UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ScrollInputType::kWheel)
- .get());
+ host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10),
+ ui::ScrollInputType::kWheel)
+ .get());
{
RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata();
EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset);
@@ -14716,10 +14985,10 @@ TEST_F(LayerTreeHostImplTest, RenderFrameMetadata) {
#endif
// Page scale should update metadata correctly (shrinking only the viewport).
- host_impl_->ScrollBegin(
- BeginState(gfx::Point(), gfx::Vector2dF(), ScrollInputType::kTouchscreen)
- .get(),
- ScrollInputType::kTouchscreen);
+ host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2, gfx::Point());
host_impl_->PinchGestureEnd(gfx::Point(), true);
@@ -14873,11 +15142,11 @@ TEST_F(LayerTreeHostImplTest,
// If the test leg contains a scroll, perform it.
if (!test_leg.scroll_delta.IsZero()) {
host_impl_->ScrollBegin(BeginState(gfx::Point(), test_leg.scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get(),
- ScrollInputType::kWheel);
+ ui::ScrollInputType::kWheel);
host_impl_->ScrollUpdate(UpdateState(gfx::Point(), test_leg.scroll_delta,
- ScrollInputType::kWheel)
+ ui::ScrollInputType::kWheel)
.get());
}
@@ -14910,9 +15179,9 @@ TEST_F(LayerTreeHostImplTest, ScrollUpdateDoesNotSetScrollingNode) {
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.thread);
ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode();
@@ -15336,9 +15605,9 @@ TEST_F(LayerTreeHostImplTest, TouchScrollOnAndroidScrollbar) {
// scrollbar should not be hit.
InputHandler::ScrollStatus status = host_impl_->ScrollBegin(
BeginState(gfx::Point(350, 50), gfx::Vector2dF(0, 10),
- ScrollInputType::kTouchscreen)
+ ui::ScrollInputType::kTouchscreen)
.get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
}
@@ -15515,5 +15784,69 @@ TEST_F(ForceActivateAfterPaintWorkletPaintLayerTreeHostImplTest,
EXPECT_FALSE(did_prepare_tiles_);
}
+// Verify that the device scale factor is not used to rescale scrollbar deltas
+// in percent-based scrolling.
+TEST_F(LayerTreeHostImplTest, PercentBasedScrollbarDeltasDSF3) {
+ LayerTreeSettings settings = DefaultSettings();
+ settings.percent_based_scrolling = true;
+ settings.use_zoom_for_dsf = true;
+ settings.use_painted_device_scale_factor = true;
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+
+ const gfx::Size viewport_size = gfx::Size(800, 800);
+ SetupViewportLayersOuterScrolls(viewport_size, viewport_size);
+
+ LayerImpl* content_layer = AddContentLayer();
+ LayerImpl* scroll_layer = AddScrollableLayer(
+ content_layer, gfx::Size(185, 200), gfx::Size(185, 3800));
+
+ auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(
+ host_impl_->active_tree(), VERTICAL, false, true);
+ SetupScrollbarLayer(scroll_layer, scrollbar);
+
+ scrollbar->SetBounds(gfx::Size(15, 200));
+
+ scrollbar->SetThumbThickness(15);
+ scrollbar->SetThumbLength(50);
+ scrollbar->SetTrackRect(gfx::Rect(0, 15, 15, 185));
+
+ scrollbar->SetBackButtonRect(gfx::Rect(gfx::Point(0, 0), gfx::Size(15, 15)));
+ scrollbar->SetForwardButtonRect(
+ gfx::Rect(gfx::Point(0, 185), gfx::Size(15, 15)));
+ scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(185, 0));
+
+ DrawFrame();
+
+ TestInputHandlerClient input_handler_client;
+ host_impl_->BindToClient(&input_handler_client);
+
+ // Test scrolling with device scale factor = 3.
+ const float expected_delta = kPercentDeltaForDirectionalScroll * 200u;
+
+ host_impl_->active_tree()->set_painted_device_scale_factor(3);
+
+ InputHandlerPointerResult scroll_result =
+ host_impl_->MouseDown(gfx::PointF(190, 190), false);
+ host_impl_->MouseUp(gfx::PointF(190, 190));
+
+ EXPECT_EQ(scroll_result.scroll_offset.y(), expected_delta);
+ EXPECT_FALSE(GetScrollNode(scroll_layer)->main_thread_scrolling_reasons);
+
+ // Test with DSF = 1. As the scrollable layers aren't rescaled by the DSF,
+ // neither the scroll offset, the same result for DSF = 3 is expected.
+ host_impl_->active_tree()->set_painted_device_scale_factor(1);
+
+ InputHandlerPointerResult scroll_with_dsf_1 =
+ host_impl_->MouseDown(gfx::PointF(190, 190), false);
+ host_impl_->MouseUp(gfx::PointF(190, 190));
+
+ EXPECT_EQ(scroll_with_dsf_1.scroll_offset.y(), expected_delta);
+ EXPECT_FALSE(GetScrollNode(scroll_layer)->main_thread_scrolling_reasons);
+
+ // Tear down the LayerTreeHostImpl before the InputHandlerClient.
+ host_impl_->ReleaseLayerTreeFrameSink();
+ host_impl_ = nullptr;
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
index 4c8f1e9603c..b55a4b3b733 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -259,10 +259,8 @@ class LayerTreeHostBlendingPixelTest
std::vector<PixelResourceTestCase> const kTestCases = {
{LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE},
-#if !defined(GL_NOT_ON_PLATFORM)
{LayerTreeTest::RENDERER_GL, ZERO_COPY},
{LayerTreeTest::RENDERER_SKIA_GL, GPU},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
{LayerTreeTest::RENDERER_SKIA_VK, GPU},
#endif // defined(ENABLE_CC_VULKAN_TESTS)
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
index b8214db99a0..c93b84e3271 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -36,6 +36,8 @@ class LayerTreeHostFiltersPixelTest
return "skia_gl";
case RENDERER_SKIA_VK:
return "skia_vk";
+ case RENDERER_SKIA_DAWN:
+ return "skia_dawn";
case RENDERER_SOFTWARE:
return "sw";
}
@@ -71,14 +73,14 @@ class LayerTreeHostFiltersPixelTest
};
LayerTreeTest::RendererType const kRendererTypes[] = {
-#if !defined(GL_NOT_ON_PLATFORM)
- LayerTreeTest::RENDERER_GL,
- LayerTreeTest::RENDERER_SKIA_GL,
-#endif // !defined(GL_NOT_ON_PLATFORM)
+ LayerTreeTest::RENDERER_GL, LayerTreeTest::RENDERER_SKIA_GL,
LayerTreeTest::RENDERER_SOFTWARE,
#if defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RENDERER_SKIA_VK,
#endif // defined(ENABLE_CC_VULKAN_TESTS)
+#if defined(ENABLE_CC_DAWN_TESTS)
+ LayerTreeTest::RENDERER_SKIA_DAWN,
+#endif // defined(ENABLE_CC_DAWN_TESTS)
};
INSTANTIATE_TEST_SUITE_P(All,
@@ -87,21 +89,20 @@ INSTANTIATE_TEST_SUITE_P(All,
using LayerTreeHostFiltersPixelTestGPU = LayerTreeHostFiltersPixelTest;
-#if !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RendererType const kRendererTypesGpu[] = {
-#if !defined(GL_NOT_ON_PLATFORM)
LayerTreeTest::RENDERER_GL,
LayerTreeTest::RENDERER_SKIA_GL,
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RENDERER_SKIA_VK,
#endif // defined(ENABLE_CC_VULKAN_TESTS)
+#if defined(ENABLE_CC_DAWN_TESTS)
+ LayerTreeTest::RENDERER_SKIA_DAWN,
+#endif // defined(ENABLE_CC_DAWN_TESTS)
};
INSTANTIATE_TEST_SUITE_P(All,
LayerTreeHostFiltersPixelTestGPU,
::testing::ValuesIn(kRendererTypesGpu));
-#endif // !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRect) {
scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
@@ -196,6 +197,9 @@ TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRadius) {
float average_error_allowed_in_bad_pixels = 1.f;
int large_error_allowed = 1;
int small_error_allowed = 0;
+ // Windows using Dawn D3D12 has 2982 pixels off by 1.
+ if (use_d3d12())
+ percentage_pixels_large_error = 1.864f; // 2982px / (400*400)
pixel_comparator_.reset(new FuzzyPixelComparator(
true, // discard_alpha
percentage_pixels_large_error, percentage_pixels_small_error,
@@ -296,7 +300,7 @@ TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOutsets) {
large_error_allowed,
small_error_allowed));
#else
- if (use_vulkan())
+ if (use_skia_vulkan())
pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true);
#endif
@@ -425,11 +429,19 @@ class LayerTreeHostBlurFiltersPixelTestGPULayerList
}
};
-#if !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
+// TODO(sgilhuly): Enable these tests for Skia Dawn, and switch over to using
+// kRendererTypesGpu.
+LayerTreeTest::RendererType const kRendererTypesGpuNonDawn[] = {
+ LayerTreeTest::RENDERER_GL,
+ LayerTreeTest::RENDERER_SKIA_GL,
+#if defined(ENABLE_CC_VULKAN_TESTS)
+ LayerTreeTest::RENDERER_SKIA_VK,
+#endif // defined(ENABLE_CC_VULKAN_TESTS)
+};
+
INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
LayerTreeHostBlurFiltersPixelTestGPULayerList,
- ::testing::ValuesIn(kRendererTypesGpu));
-#endif // !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
+ ::testing::ValuesIn(kRendererTypesGpuNonDawn));
TEST_P(LayerTreeHostBlurFiltersPixelTestGPULayerList,
BackdropFilterBlurOffAxis) {
@@ -453,7 +465,7 @@ TEST_P(LayerTreeHostBlurFiltersPixelTestGPULayerList,
large_error_allowed,
small_error_allowed));
#else
- if (use_vulkan())
+ if (use_skia_vulkan())
pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true);
#endif
@@ -645,6 +657,11 @@ TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterScaled) {
// Windows has 153 pixels off by at most 2: crbug.com/225027
float percentage_pixels_large_error = 0.3825f; // 153px / (200*200)
int large_error_allowed = 2;
+ // Windows using Dawn D3D12 has 166 pixels off by 1.
+ if (use_d3d12()) {
+ percentage_pixels_large_error = 0.415f; // 166px / (200*200)
+ large_error_allowed = 1;
+ }
#elif defined(_MIPS_ARCH_LOONGSON)
// Loongson has 2 pixels off by at most 2: crbug.com/819075
float percentage_pixels_large_error = 0.005f; // 2px / (200*200)
@@ -755,20 +772,27 @@ TEST_P(LayerTreeHostFiltersPixelTest, ImageRenderSurfaceScaled) {
background->AddChild(render_surface_layer);
- // Software has some huge differences in the AA'd pixels on the different
- // trybots. See crbug.com/452198.
+ float percentage_pixels_large_error = 0.0f;
+ float percentage_pixels_small_error = 0.0f;
+ float average_error_allowed_in_bad_pixels = 0.0f;
+ int large_error_allowed = 0;
+ int small_error_allowed = 0;
if (use_software_renderer()) {
- float percentage_pixels_large_error = 0.686f;
- float percentage_pixels_small_error = 0.0f;
- float average_error_allowed_in_bad_pixels = 16.f;
- int large_error_allowed = 17;
- int small_error_allowed = 0;
- pixel_comparator_.reset(new FuzzyPixelComparator(
- true, // discard_alpha
- percentage_pixels_large_error, percentage_pixels_small_error,
- average_error_allowed_in_bad_pixels, large_error_allowed,
- small_error_allowed));
+ // Software has some huge differences in the AA'd pixels on the different
+ // trybots. See crbug.com/452198.
+ percentage_pixels_large_error = 0.686f;
+ average_error_allowed_in_bad_pixels = 16.f;
+ large_error_allowed = 17;
+ } else if (use_d3d12()) {
+ // Windows using Dawn D3D12 has 25 pixels off by 1.
+ percentage_pixels_large_error = 0.028;
+ average_error_allowed_in_bad_pixels = 1.f;
+ large_error_allowed = 1;
}
+ pixel_comparator_.reset(new FuzzyPixelComparator(
+ /*discard_alpha=*/true, percentage_pixels_large_error,
+ percentage_pixels_small_error, average_error_allowed_in_bad_pixels,
+ large_error_allowed, small_error_allowed));
RunPixelTest(
background,
@@ -776,7 +800,24 @@ TEST_P(LayerTreeHostFiltersPixelTest, ImageRenderSurfaceScaled) {
.InsertBeforeExtensionASCII(GetRendererSuffix()));
}
-TEST_P(LayerTreeHostFiltersPixelTest, ZoomFilter) {
+// TODO(sgilhuly): Enable these tests for Skia Dawn, and switch over to using
+// kRendererTypes.
+using LayerTreeHostFiltersPixelTestNonDawn = LayerTreeHostFiltersPixelTest;
+
+LayerTreeTest::RendererType const kRendererTypesNonDawn[] = {
+ LayerTreeTest::RENDERER_GL,
+ LayerTreeTest::RENDERER_SKIA_GL,
+ LayerTreeTest::RENDERER_SOFTWARE,
+#if defined(ENABLE_CC_VULKAN_TESTS)
+ LayerTreeTest::RENDERER_SKIA_VK,
+#endif // defined(ENABLE_CC_VULKAN_TESTS)
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+ LayerTreeHostFiltersPixelTestNonDawn,
+ ::testing::ValuesIn(kRendererTypesNonDawn));
+
+TEST_P(LayerTreeHostFiltersPixelTestNonDawn, ZoomFilter) {
scoped_refptr<SolidColorLayer> root =
CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE);
@@ -879,6 +920,9 @@ TEST_P(LayerTreeHostFiltersPixelTest, RotatedFilter) {
float percentage_pixels_large_error = 0.00111112f; // 1px / (300*300)
float average_error_allowed_in_bad_pixels = 1.f;
int large_error_allowed = 1;
+ // Windows using Dawn D3D12 has 104 pixels off by 1.
+ if (use_d3d12())
+ percentage_pixels_large_error = 0.115556f; // 104px / (300*300)
#else
float percentage_pixels_large_error = 0.0f; // 1px / (300*300)
float average_error_allowed_in_bad_pixels = 0.0f;
@@ -936,6 +980,9 @@ TEST_P(LayerTreeHostFiltersPixelTest, RotatedDropShadowFilter) {
float percentage_pixels_large_error = 0.00333334f; // 3px / (300*300)
float average_error_allowed_in_bad_pixels = 1.f;
int large_error_allowed = 1;
+ // Windows using Dawn D3D12 has 22 pixels off by 1.
+ if (use_d3d12())
+ percentage_pixels_large_error = 0.02445; // 22px / (300*300)
#endif
float percentage_pixels_small_error = 0.0f;
int small_error_allowed = 0;
@@ -945,7 +992,7 @@ TEST_P(LayerTreeHostFiltersPixelTest, RotatedDropShadowFilter) {
average_error_allowed_in_bad_pixels, large_error_allowed,
small_error_allowed));
#else
- if (use_vulkan())
+ if (use_skia_vulkan())
pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true);
#endif
@@ -989,7 +1036,7 @@ TEST_P(LayerTreeHostFiltersPixelTest, TranslatedFilter) {
parent->AddChild(child);
clip->AddChild(parent);
- if (use_software_renderer())
+ if (use_software_renderer() || renderer_type_ == RENDERER_SKIA_DAWN)
pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true);
RunPixelTest(clip, base::FilePath(
@@ -1225,6 +1272,18 @@ class BackdropFilterInvertTest : public LayerTreeHostFiltersPixelTest {
base::NumberToString(device_scale_factor) + "x");
if (use_software_renderer()) {
expected_result = expected_result.InsertBeforeExtensionASCII("_sw");
+ } else if (use_d3d12()) {
+ // Windows using Dawn D3D12 has 16 pixels off by 1.
+ float percentage_pixels_large_error = 0.04f; // 16px / (200*200)
+ float average_error_allowed_in_bad_pixels = 1.f;
+ int large_error_allowed = 1;
+ float percentage_pixels_small_error = 0.0f;
+ int small_error_allowed = 0;
+ pixel_comparator_.reset(new FuzzyPixelComparator(
+ true, // discard_alpha
+ percentage_pixels_large_error, percentage_pixels_small_error,
+ average_error_allowed_in_bad_pixels, large_error_allowed,
+ small_error_allowed));
}
RunPixelTest(std::move(root), expected_result);
}
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
index e0b98e69b30..7e39b785622 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -30,14 +30,12 @@ namespace {
// https://crbug.com/979703
std::vector<PixelResourceTestCase> const kTestCases = {
{LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE},
-#if !defined(GL_NOT_ON_PLATFORM)
{LayerTreeTest::RENDERER_GL, GPU},
{LayerTreeTest::RENDERER_GL, ONE_COPY},
{LayerTreeTest::RENDERER_GL, ZERO_COPY},
{LayerTreeTest::RENDERER_SKIA_GL, GPU},
{LayerTreeTest::RENDERER_SKIA_GL, ONE_COPY},
{LayerTreeTest::RENDERER_SKIA_GL, ZERO_COPY},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
{LayerTreeTest::RENDERER_SKIA_VK, GPU},
#endif // defined(ENABLE_CC_VULKAN_TESTS)
@@ -585,7 +583,7 @@ TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTestWithLayerList, Test) {
? base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter_gpu.png"))
: base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter.png"));
- if (use_vulkan() && raster_type() == GPU) {
+ if (use_skia_vulkan() && raster_type() == GPU) {
// Vulkan with GPU raster has 4 pixels errors (the circle mask shape is
// slight different).
float percentage_pixels_large_error = 0.04f; // 4px / (100*100)
@@ -644,7 +642,7 @@ TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTestWithLayerTree, Test) {
? base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter_gpu.png"))
: base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter.png"));
- if (use_vulkan() && raster_type() == GPU) {
+ if (use_skia_vulkan() && raster_type() == GPU) {
// Vulkan with GPU raster has 4 pixels errors (the circle mask shape is
// slight different).
float percentage_pixels_large_error = 0.04f; // 4px / (100*100)
@@ -874,7 +872,6 @@ class LayerTreeHostMaskAsBlendingPixelTest
MaskTestConfig const kTestConfigs[] = {
MaskTestConfig{{LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE}, 0},
-#if !defined(GL_NOT_ON_PLATFORM)
MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, 0},
MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, kUseAntialiasing},
MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, kForceShaders},
@@ -883,7 +880,6 @@ MaskTestConfig const kTestConfigs[] = {
MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_GL, ZERO_COPY}, 0},
MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_GL, ZERO_COPY},
kUseAntialiasing},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_VK, ZERO_COPY}, 0},
MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_VK, ZERO_COPY},
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc b/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc
index f34ac66a8af..82a9f66663b 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc
@@ -25,10 +25,8 @@ class LayerTreeHostMirrorPixelTest
};
const LayerTreeTest::RendererType kRendererTypes[] = {
-#if !defined(GL_NOT_ON_PLATFORM)
LayerTreeTest::RENDERER_GL,
LayerTreeTest::RENDERER_SKIA_GL,
-#endif // !defined(GL_NOT_ON_PLATFORM)
LayerTreeTest::RENDERER_SOFTWARE,
#if defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RENDERER_SKIA_VK,
@@ -72,10 +70,8 @@ TEST_P(LayerTreeHostMirrorPixelTest, MirrorLayer) {
max_abs_error_limit, small_error_threshold);
}
-#if defined(ENABLE_CC_VULKAN_TESTS) && defined(OS_LINUX)
- if (use_vulkan())
+ if (use_skia_vulkan())
pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true);
-#endif
RunPixelTest(background,
base::FilePath(FILE_PATH_LITERAL("mirror_layer.png")));
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
index d314bdd7efb..6d7e9365f4b 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -418,7 +418,6 @@ TEST_P(LayerTreeHostReadbackPixelTest, MultipleReadbacksOnLayer) {
// readback.
ReadbackTestConfig const kTestConfigs[] = {
ReadbackTestConfig{LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP},
-#if !defined(GL_NOT_ON_PLATFORM)
ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_TEXTURE},
ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_BITMAP},
// TODO(crbug.com/1046788): The skia readback path doesn't support
@@ -427,7 +426,6 @@ ReadbackTestConfig const kTestConfigs[] = {
//
// ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE},
ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_VK, READBACK_BITMAP},
#endif // defined(ENABLE_CC_VULKAN_TESTS)
@@ -441,7 +439,6 @@ INSTANTIATE_TEST_SUITE_P(All,
// MSan are used.
ReadbackTestConfig const kMaybeVulkanTestConfigs[] = {
ReadbackTestConfig{LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP},
-#if !defined(GL_NOT_ON_PLATFORM)
ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_TEXTURE},
ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_BITMAP},
// TODO(crbug.com/1046788): The skia readback path doesn't support
@@ -450,7 +447,6 @@ ReadbackTestConfig const kMaybeVulkanTestConfigs[] = {
//
// ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE},
ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS) && !defined(THREAD_SANITIZER) && \
!defined(MEMORY_SANITIZER)
ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_VK, READBACK_BITMAP},
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
index a04ddde31ad..5dc2efdea40 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
@@ -73,12 +73,9 @@ class PaintedScrollbar : public FakeScrollbar {
SkColor color_ = SK_ColorGREEN;
};
-#if !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RendererType const kRendererTypes[] = {
-#if !defined(GL_NOT_ON_PLATFORM)
LayerTreeTest::RENDERER_GL,
LayerTreeTest::RENDERER_SKIA_GL,
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RENDERER_SKIA_VK,
#endif // defined(ENABLE_CC_VULKAN_TESTS)
@@ -87,7 +84,6 @@ LayerTreeTest::RendererType const kRendererTypes[] = {
INSTANTIATE_TEST_SUITE_P(All,
LayerTreeHostScrollbarsPixelTest,
::testing::ValuesIn(kRendererTypes));
-#endif // !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
TEST_P(LayerTreeHostScrollbarsPixelTest, NoScale) {
scoped_refptr<SolidColorLayer> background =
@@ -188,7 +184,7 @@ TEST_P(LayerTreeHostScrollbarsPixelTest, MAYBE_HugeTransformScale) {
pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true);
RunPixelTest(background,
- use_vulkan()
+ use_skia_vulkan()
? base::FilePath(FILE_PATH_LITERAL("spiral_64_scale_vk.png"))
: base::FilePath(FILE_PATH_LITERAL("spiral_64_scale.png")));
}
@@ -200,8 +196,7 @@ class LayerTreeHostOverlayScrollbarsPixelTest
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
LayerImpl* layer = host_impl->active_tree()->LayerById(scrollbar_layer_id_);
- ScrollbarLayerImplBase* scrollbar = layer->ToScrollbarLayer();
- scrollbar->SetThumbThicknessScaleFactor(thickness_scale_);
+ ToScrollbarLayer(layer)->SetThumbThicknessScaleFactor(thickness_scale_);
}
int scrollbar_layer_id_;
@@ -256,11 +251,9 @@ class PaintedOverlayScrollbar : public FakeScrollbar {
~PaintedOverlayScrollbar() override = default;
};
-#if !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
INSTANTIATE_TEST_SUITE_P(All,
LayerTreeHostOverlayScrollbarsPixelTest,
::testing::ValuesIn(kRendererTypes));
-#endif // !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
// Simulate increasing the thickness of a painted overlay scrollbar. Ensure that
// the scrollbar border remains crisp.
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc
index c832b869d30..2739d9880bb 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc
@@ -54,12 +54,9 @@ class LayerTreeHostSynchronousPixelTest
bool use_zero_copy_ = false;
};
-#if !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RendererType const kRendererTypesGpu[] = {
-#if !defined(GL_NOT_ON_PLATFORM)
LayerTreeTest::RENDERER_GL,
LayerTreeTest::RENDERER_SKIA_GL,
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
LayerTreeTest::RENDERER_SKIA_VK,
#endif // defined(ENABLE_CC_VULKAN_TESTS)
@@ -68,7 +65,6 @@ LayerTreeTest::RendererType const kRendererTypesGpu[] = {
INSTANTIATE_TEST_SUITE_P(All,
LayerTreeHostSynchronousPixelTest,
::testing::ValuesIn(kRendererTypesGpu));
-#endif // !defined(GL_NOT_ON_PLATFORM) || defined(ENABLE_CC_VULKAN_TESTS)
TEST_P(LayerTreeHostSynchronousPixelTest, OneContentLayerZeroCopy) {
use_zero_copy_ = true;
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 13ca041f5cd..9464beb4941 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -181,12 +181,10 @@ class LayerTreeHostTilesTestPartialInvalidation
std::vector<TilesTestConfig> const kTestCases = {
{LayerTreeTest::RENDERER_SOFTWARE, BITMAP},
-#if !defined(GL_NOT_ON_PLATFORM)
{LayerTreeTest::RENDERER_GL, ONE_COPY},
{LayerTreeTest::RENDERER_GL, GPU},
{LayerTreeTest::RENDERER_SKIA_GL, ONE_COPY},
{LayerTreeTest::RENDERER_SKIA_GL, GPU},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
{LayerTreeTest::RENDERER_SKIA_VK, ONE_COPY},
{LayerTreeTest::RENDERER_SKIA_VK, GPU},
@@ -211,10 +209,8 @@ TEST_P(LayerTreeHostTilesTestPartialInvalidation, FullRaster) {
}
std::vector<TilesTestConfig> const kTestCasesMultiThread = {
-#if !defined(GL_NOT_ON_PLATFORM)
{LayerTreeTest::RENDERER_GL, ONE_COPY},
{LayerTreeTest::RENDERER_SKIA_GL, ONE_COPY},
-#endif // !defined(GL_NOT_ON_PLATFORM)
#if defined(ENABLE_CC_VULKAN_TESTS)
{LayerTreeTest::RENDERER_SKIA_VK, ONE_COPY},
#endif // defined(ENABLE_CC_VULKAN_TESTS)
@@ -255,14 +251,12 @@ using LayerTreeHostTilesTestPartialInvalidationLowBitDepth =
// This test doesn't work on Vulkan because on our hardware we can't render to
// RGBA4444 format using either SwiftShader or native Vulkan. See
// crbug.com/987278 for details
-#if !defined(GL_NOT_ON_PLATFORM)
INSTANTIATE_TEST_SUITE_P(
All,
LayerTreeHostTilesTestPartialInvalidationLowBitDepth,
::testing::Values(
TilesTestConfig{LayerTreeTest::RENDERER_SKIA_GL, GPU_LOW_BIT_DEPTH},
TilesTestConfig{LayerTreeTest::RENDERER_GL, GPU_LOW_BIT_DEPTH}));
-#endif // !defined(GL_NOT_ON_PLATFORM)
TEST_P(LayerTreeHostTilesTestPartialInvalidationLowBitDepth, PartialRaster) {
use_partial_raster_ = true;
diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc
index bc6cc793d87..edbee8ea336 100644
--- a/chromium/cc/trees/layer_tree_host_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest.cc
@@ -20,6 +20,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "cc/animation/animation_host.h"
#include "cc/animation/timing_function.h"
#include "cc/input/scroll_elasticity_helper.h"
#include "cc/layers/content_layer_client.h"
@@ -874,6 +875,99 @@ class LayerTreeHostTestPushPropertiesTo : public LayerTreeHostTest {
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPushPropertiesTo);
+// Verify that invisible render passes are excluded in CompositorFrame.
+class LayerTreeHostTestInvisibleLayersSkipRenderPass
+ : public LayerTreeHostTest {
+ protected:
+ enum Step {
+ kAllInvisible,
+ kOneVisible,
+ kAllVisible,
+ kAllInvisibleAgain,
+ kDone,
+ };
+
+ void SetupTree() override {
+ SetInitialRootBounds(gfx::Size(10, 10));
+ LayerTreeHostTest::SetupTree();
+ auto* root = layer_tree_host()->root_layer();
+ child1_ = CreateChild(root);
+ child2_ = CreateChild(root);
+ }
+
+ scoped_refptr<Layer> CreateChild(scoped_refptr<Layer> root) {
+ auto child = Layer::Create();
+ // Initially hidden.
+ child->SetHideLayerAndSubtree(true);
+ AddBackgroundBlurFilter(child.get());
+ root->AddChild(child.get());
+ return child;
+ }
+
+ void AddBackgroundBlurFilter(Layer* layer) {
+ FilterOperations filters;
+ filters.Append(FilterOperation::CreateBlurFilter(
+ 30, SkBlurImageFilter::kClamp_TileMode));
+ layer->SetBackdropFilters(filters);
+ }
+
+ void BeginTest() override {
+ index_ = kAllInvisible;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void DidCommitAndDrawFrame() override {
+ ++index_;
+ switch (index_) {
+ case kAllInvisible:
+ NOTREACHED();
+ break;
+ case kOneVisible:
+ child1_->SetHideLayerAndSubtree(false);
+ break;
+ case kAllVisible:
+ child2_->SetHideLayerAndSubtree(false);
+ break;
+ case kAllInvisibleAgain:
+ child1_->SetHideLayerAndSubtree(true);
+ child2_->SetHideLayerAndSubtree(true);
+ break;
+ case kDone:
+ EndTest();
+ break;
+ }
+ }
+
+ void DisplayReceivedCompositorFrameOnThread(
+ const viz::CompositorFrame& frame) override {
+ size_t num_render_passes = frame.render_pass_list.size();
+ switch (index_) {
+ case kAllInvisible:
+ // There is only a root render pass.
+ EXPECT_EQ(1u, num_render_passes);
+ break;
+ case kOneVisible:
+ EXPECT_EQ(2u, num_render_passes);
+ break;
+ case kAllVisible:
+ EXPECT_EQ(3u, num_render_passes);
+ break;
+ case kAllInvisibleAgain:
+ EXPECT_EQ(1u, num_render_passes);
+ break;
+ case kDone:
+ EndTest();
+ break;
+ }
+ }
+
+ int index_ = kAllInvisible;
+ scoped_refptr<Layer> child1_;
+ scoped_refptr<Layer> child2_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestInvisibleLayersSkipRenderPass);
+
class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest {
protected:
void SetupTree() override {
@@ -1107,7 +1201,7 @@ class LayerTreeHostTestSurfaceDamage : public LayerTreeHostTest {
root_->SetBounds(gfx::Size(20, 20));
break;
case 3:
- child_->SetDoubleSided(false);
+ child_->SetOpacity(0.8f);
break;
}
}
@@ -3883,12 +3977,12 @@ class LayerTreeHostTestLCDChange : public LayerTreeHostTest {
PostSetNeedsCommitToMainThread();
break;
case 2:
- // Change layer opacity that should trigger lcd change.
- layer_tree_host()->root_layer()->SetOpacity(.5f);
+ // Change contents_opaque that should trigger lcd change.
+ layer_tree_host()->root_layer()->SetContentsOpaque(false);
break;
case 3:
- // Change layer opacity that should not trigger lcd change.
- layer_tree_host()->root_layer()->SetOpacity(1.f);
+ // Change contents_opaque that should trigger lcd change.
+ layer_tree_host()->root_layer()->SetContentsOpaque(true);
break;
case 4:
EndTest();
@@ -3905,7 +3999,8 @@ class LayerTreeHostTestLCDChange : public LayerTreeHostTest {
PictureLayerImpl* root_layer =
static_cast<PictureLayerImpl*>(host_impl->active_tree()->root_layer());
bool can_use_lcd_text =
- host_impl->active_tree()->root_layer()->CanUseLCDText();
+ root_layer->ComputeLCDTextDisallowedReasonForTesting() ==
+ LCDTextDisallowedReason::kNone;
switch (host_impl->active_tree()->source_frame_number()) {
case 0:
// The first draw.
@@ -8782,5 +8877,59 @@ class LayerTreeHostTopControlsDeltaTriggersViewportUpdate
MULTI_THREAD_TEST_F(LayerTreeHostTopControlsDeltaTriggersViewportUpdate);
+// Tests that custom sequence throughput tracking result is reported to
+// LayerTreeHostClient.
+constexpr MutatorHost::TrackedAnimationSequenceId kSequenceId = 1u;
+class LayerTreeHostCustomThrougputTrackerTest : public LayerTreeHostTest {
+ public:
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DidCommit() override {
+ // FrameSequenceTracker typically sees the following sequence:
+ // e(2,2)b(3)B(0,3)E(3)s(3)S(3)e(3,3)P(3)b(4)B(3,4)E(4)s(4)S(4)e(4,4)P(4)
+ switch (layer_tree_host()->SourceFrameNumber()) {
+ case 1:
+ animation_host()->StartThroughputTracking(kSequenceId);
+ break;
+ case 3:
+ animation_host()->StopThroughputTracking(kSequenceId);
+ break;
+ default:
+ break;
+ }
+
+ PostSetNeedsCommitWithForcedRedrawToMainThread();
+ }
+
+ void NotifyThroughputTrackerResults(CustomTrackerResults results) override {
+ ASSERT_TRUE(base::Contains(results, kSequenceId));
+ const auto& throughput = results[kSequenceId];
+ // Frame 3 and 4 are counted. See the sequence in DidCommit comment for
+ // normal case that expects 2 for both frames_expected and frames_produced.
+ //
+ // However, on slow bots, things could be different.
+ // - Begin frame could be skipped but still counted as expected frames,
+ //
+ // e(5,5)b(8)B(0,8)E(8)s(3)S(8)e(8,8)b(11)
+ // B(8,11)E(11)ts(4)S(11)e(11,11)P(3)e(14,14)P(4)
+ //
+ // B(0, 8) and B(8, 11) make frame_expected to be 4, more than 2 expected
+ // by test.
+ //
+ // - Finish before frame 4 is presented in multi-thread mode.
+ //
+ // e(3,3)b(4)B(0,4)E(4)s(2)e(4,4)b(6)B(4,6)E(6)s(3)S(4)e(6,6)
+ // P(2)e(7,7)P(3)
+ //
+ // Only P(3) is counted thus frames_produced is 1.
+ EXPECT_GE(throughput.frames_expected, 2u);
+ EXPECT_GE(throughput.frames_produced, 1u);
+
+ EndTest();
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCustomThrougputTrackerTest);
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
index 80fc33f5398..a5f7b6e522a 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -14,7 +14,6 @@
#include "cc/base/completion_event.h"
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/input/scroll_elasticity_helper.h"
-#include "cc/input/scroll_input_type.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer.h"
@@ -33,6 +32,7 @@
#include "cc/trees/transform_node.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/events/types/scroll_input_type.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
@@ -686,7 +686,7 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
gfx::PointF(-0.5f, -0.5f) +
GetTransformNode(expected_scroll_layer_impl)->post_translation);
InputHandler::ScrollStatus status = impl->ScrollBegin(
- BeginState(scroll_point).get(), ScrollInputType::kTouchscreen);
+ BeginState(scroll_point).get(), ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
impl->ScrollUpdate(UpdateState(gfx::Point(), scroll_amount_).get());
auto* scrolling_node = impl->CurrentlyScrollingNode();
@@ -709,7 +709,7 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
gfx::PointF(0.5f, 0.5f) +
GetTransformNode(expected_scroll_layer_impl)->post_translation);
InputHandler::ScrollStatus status = impl->ScrollBegin(
- BeginState(scroll_point).get(), ScrollInputType::kWheel);
+ BeginState(scroll_point).get(), ui::ScrollInputType::kWheel);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
impl->ScrollUpdate(UpdateState(gfx::Point(), scroll_amount_).get());
impl->ScrollEnd();
@@ -1068,8 +1068,8 @@ void DoGestureScroll(LayerTreeHostImpl* host_impl,
begin_scroll_state_data.delta_y_hint = offset.y();
std::unique_ptr<ScrollState> begin_scroll_state(
new ScrollState(begin_scroll_state_data));
- auto scroll_status = host_impl->ScrollBegin(begin_scroll_state.get(),
- ScrollInputType::kTouchscreen);
+ auto scroll_status = host_impl->ScrollBegin(
+ begin_scroll_state.get(), ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, scroll_status.thread);
auto* scrolling_node = host_impl->CurrentlyScrollingNode();
EXPECT_TRUE(scrolling_node);
@@ -1453,13 +1453,13 @@ class LayerTreeHostScrollTestScrollNonDrawnLayer
// checking whether the screen space point is inside the non-fast
// scrollable region.
InputHandler::ScrollStatus status = impl->ScrollBegin(
- BeginState(gfx::Point(0, 0)).get(), ScrollInputType::kTouchscreen);
+ BeginState(gfx::Point(0, 0)).get(), ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
status.main_thread_scrolling_reasons);
status = impl->ScrollBegin(BeginState(gfx::Point(21, 21)).get(),
- ScrollInputType::kTouchscreen);
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
status.main_thread_scrolling_reasons);
@@ -2461,16 +2461,18 @@ class NonScrollingNonFastScrollableRegion : public LayerTreeHostScrollTest {
// The top-left hit should immediately hit the top layer's non-fast region
// which forces main-thread scrolling.
- auto top_left_status = impl->ScrollBegin(
- BeginState(gfx::Point(20, 20)).get(), ScrollInputType::kTouchscreen);
+ auto top_left_status =
+ impl->ScrollBegin(BeginState(gfx::Point(20, 20)).get(),
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, top_left_status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
top_left_status.main_thread_scrolling_reasons);
// The top-right hit should hit the top layer but not the non-fast region so
// the scroll should continue to scroll on the impl.
- InputHandler::ScrollStatus top_right_status = impl->ScrollBegin(
- BeginState(gfx::Point(80, 20)).get(), ScrollInputType::kTouchscreen);
+ InputHandler::ScrollStatus top_right_status =
+ impl->ScrollBegin(BeginState(gfx::Point(80, 20)).get(),
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, top_right_status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
top_right_status.main_thread_scrolling_reasons);
@@ -2480,8 +2482,9 @@ class NonScrollingNonFastScrollableRegion : public LayerTreeHostScrollTest {
// the middle layer is a composited scroller and is hit first, we cannot do
// a fast scroll because an ancestor on the scroll chain has hit a non-fast
// region.
- InputHandler::ScrollStatus bottom_right_status = impl->ScrollBegin(
- BeginState(gfx::Point(80, 80)).get(), ScrollInputType::kTouchscreen);
+ InputHandler::ScrollStatus bottom_right_status =
+ impl->ScrollBegin(BeginState(gfx::Point(80, 80)).get(),
+ ui::ScrollInputType::kTouchscreen);
EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, bottom_right_status.thread);
EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
bottom_right_status.main_thread_scrolling_reasons);
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index 45f7e5707a0..600c987976c 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -1585,6 +1585,10 @@ FrameRateCounter* LayerTreeImpl::frame_rate_counter() const {
return host_impl_->fps_counter();
}
+base::Optional<int> LayerTreeImpl::current_universal_throughput() {
+ return host_impl_->current_universal_throughput();
+}
+
MemoryHistory* LayerTreeImpl::memory_history() const {
return host_impl_->memory_history();
}
@@ -1627,7 +1631,7 @@ bool LayerTreeImpl::PinchGestureActive() const {
return host_impl_->pinch_gesture_active();
}
-viz::BeginFrameArgs LayerTreeImpl::CurrentBeginFrameArgs() const {
+const viz::BeginFrameArgs& LayerTreeImpl::CurrentBeginFrameArgs() const {
return host_impl_->CurrentBeginFrameArgs();
}
@@ -1945,9 +1949,9 @@ ScrollbarSet LayerTreeImpl::ScrollbarsFor(ElementId scroll_element_id) const {
if (it != element_id_to_scrollbar_layer_ids_.end()) {
const ScrollbarLayerIds& layer_ids = it->second;
if (layer_ids.horizontal != Layer::INVALID_ID)
- scrollbars.insert(LayerById(layer_ids.horizontal)->ToScrollbarLayer());
+ scrollbars.insert(ToScrollbarLayer(LayerById(layer_ids.horizontal)));
if (layer_ids.vertical != Layer::INVALID_ID)
- scrollbars.insert(LayerById(layer_ids.vertical)->ToScrollbarLayer());
+ scrollbars.insert(ToScrollbarLayer(LayerById(layer_ids.vertical)));
}
return scrollbars;
}
@@ -2158,7 +2162,7 @@ LayerImpl* LayerTreeImpl::FindFirstScrollingLayerOrScrollbarThatIsHitByPoint(
auto HitTestScrollingLayerOrScrollbarFunctor =
[this](const LayerImpl* layer) {
return layer->HitTestable() &&
- (layer->is_scrollbar() ||
+ (layer->IsScrollbarLayer() ||
(property_trees()->scroll_tree.FindNodeFromElementId(
layer->element_id())));
};
diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h
index f87d0c3f5a5..5c2f586a0ea 100644
--- a/chromium/cc/trees/layer_tree_impl.h
+++ b/chromium/cc/trees/layer_tree_impl.h
@@ -128,6 +128,7 @@ class CC_EXPORT LayerTreeImpl {
ImageDecodeCache* image_decode_cache() const;
ImageAnimationController* image_animation_controller() const;
FrameRateCounter* frame_rate_counter() const;
+ base::Optional<int> current_universal_throughput();
MemoryHistory* memory_history() const;
DebugRectHistory* debug_rect_history() const;
bool IsActiveTree() const;
@@ -137,7 +138,7 @@ class CC_EXPORT LayerTreeImpl {
LayerImpl* FindActiveTreeLayerById(int id);
LayerImpl* FindPendingTreeLayerById(int id);
bool PinchGestureActive() const;
- viz::BeginFrameArgs CurrentBeginFrameArgs() const;
+ const viz::BeginFrameArgs& CurrentBeginFrameArgs() const;
base::TimeDelta CurrentBeginFrameInterval() const;
const gfx::Rect ViewportRectForTilePriority() const;
std::unique_ptr<ScrollbarAnimationController>
diff --git a/chromium/cc/trees/managed_memory_policy.cc b/chromium/cc/trees/managed_memory_policy.cc
index 3583c8b0d2e..a8b7d9c5d3e 100644
--- a/chromium/cc/trees/managed_memory_policy.cc
+++ b/chromium/cc/trees/managed_memory_policy.cc
@@ -6,7 +6,7 @@
#include <stddef.h>
-#include "base/logging.h"
+#include "base/notreached.h"
namespace cc {
diff --git a/chromium/cc/trees/mutator_host.h b/chromium/cc/trees/mutator_host.h
index e9c2d537c18..1292e0ec826 100644
--- a/chromium/cc/trees/mutator_host.h
+++ b/chromium/cc/trees/mutator_host.h
@@ -6,6 +6,7 @@
#define CC_TREES_MUTATOR_HOST_H_
#include <memory>
+#include <vector>
#include "base/callback_forward.h"
#include "base/time/time.h"
@@ -39,7 +40,7 @@ const float kNotScaled = 0;
// MutatorHostClient interface.
class MutatorHost {
public:
- virtual ~MutatorHost() {}
+ virtual ~MutatorHost() = default;
virtual std::unique_ptr<MutatorHost> CreateImplInstance(
bool supports_impl_scrolling) const = 0;
@@ -164,11 +165,24 @@ class MutatorHost {
virtual bool HasCustomPropertyAnimations() const = 0;
virtual bool CurrentFrameHadRAF() const = 0;
virtual bool NextFrameHasPendingRAF() const = 0;
+
+ using TrackedAnimationSequenceId = size_t;
+ struct PendingThroughputTrackerInfo {
+ // Id of a tracked animation sequence.
+ TrackedAnimationSequenceId id = 0u;
+ // True means the tracking for |id| is pending to start and false means
+ // the tracking is pending to stop.
+ bool start = false;
+ };
+ // Takes info of throughput trackers that are pending start or stop.
+ using PendingThroughputTrackerInfos =
+ std::vector<PendingThroughputTrackerInfo>;
+ virtual PendingThroughputTrackerInfos TakePendingThroughputTrackerInfos() = 0;
};
class MutatorEvents {
public:
- virtual ~MutatorEvents() {}
+ virtual ~MutatorEvents() = default;
virtual bool IsEmpty() const = 0;
};
diff --git a/chromium/cc/trees/occlusion.cc b/chromium/cc/trees/occlusion.cc
index d0f5f1f5525..7edb53303b6 100644
--- a/chromium/cc/trees/occlusion.cc
+++ b/chromium/cc/trees/occlusion.cc
@@ -4,6 +4,7 @@
#include "cc/trees/occlusion.h"
+#include "base/check_op.h"
#include "cc/base/math_util.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc
index ad2da282dcc..7a6bf2068f6 100644
--- a/chromium/cc/trees/occlusion_tracker.cc
+++ b/chromium/cc/trees/occlusion_tracker.cc
@@ -179,6 +179,12 @@ void OcclusionTracker::EnterRenderTarget(
gfx::Rect(), old_target_to_new_target_transform));
}
+// A blend mode is occluding if a fully opaque source can fully occlude the
+// destination and the result is also fully opaque.
+static bool IsOccludingBlendMode(SkBlendMode blend_mode) {
+ return blend_mode == SkBlendMode::kSrc || blend_mode == SkBlendMode::kSrcOver;
+}
+
void OcclusionTracker::FinishedRenderTarget(
const RenderSurfaceImpl* finished_target_surface) {
// Make sure we know about the target surface.
@@ -198,7 +204,7 @@ void OcclusionTracker::FinishedRenderTarget(
// the surface's subtree, then clear the occlusion here so it won't be used.
if (finished_target_surface->HasMaskingContributingSurface() ||
finished_target_surface->draw_opacity() < 1 ||
- !finished_target_surface->UsesDefaultBlendMode() ||
+ !IsOccludingBlendMode(finished_target_surface->BlendMode()) ||
target_is_only_for_copy_request_or_force_render_surface ||
finished_target_surface->Filters().HasFilterThatAffectsOpacity()) {
stack_.back().occlusion_from_outside_target.Clear();
@@ -351,7 +357,7 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) {
if (opaque_layer_region.IsEmpty())
return;
- // If the blend mode is not kSrcOver and the effect doesn't have a render
+ // If the blend mode is not occluding and the effect doesn't have a render
// surface, then the layer should not occlude. An example of this would
// otherwise be wrong is that this layer is a non-render-surface mask layer
// with kDstIn blend mode.
@@ -359,7 +365,7 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) {
layer->layer_tree_impl()->property_trees()->effect_tree.Node(
layer->effect_tree_index());
if (!effect_node->HasRenderSurface() &&
- effect_node->blend_mode != SkBlendMode::kSrcOver)
+ !IsOccludingBlendMode(effect_node->blend_mode))
return;
DCHECK(layer->visible_layer_rect().Contains(opaque_layer_region.bounds()));
diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc
index 5ab0b6552fc..920c746638d 100644
--- a/chromium/cc/trees/occlusion_tracker_unittest.cc
+++ b/chromium/cc/trees/occlusion_tracker_unittest.cc
@@ -1830,10 +1830,82 @@ class OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded
ALL_OCCLUSIONTRACKER_TEST(
OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded)
-class OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude
+class OcclusionTrackerTestRenderSurfaceOccludingBlendMode
: public OcclusionTrackerTest {
protected:
- explicit OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude(
+ explicit OcclusionTrackerTestRenderSurfaceOccludingBlendMode(
+ bool opaque_layers,
+ SkBlendMode blend_mode)
+ : OcclusionTrackerTest(opaque_layers), blend_mode_(blend_mode) {}
+
+ void RunMyTest() override {
+ TestContentLayerImpl* parent = CreateRoot(gfx::Size(100, 100));
+ LayerImpl* blend_mode_layer =
+ CreateDrawingSurface(parent, identity_matrix, gfx::PointF(0.f, 0.f),
+ gfx::Size(100, 100), true);
+ LayerImpl* top_layer =
+ CreateDrawingLayer(parent, identity_matrix, gfx::PointF(10.f, 12.f),
+ gfx::Size(20, 22), true);
+
+ GetEffectNode(blend_mode_layer)->render_surface_reason =
+ RenderSurfaceReason::kTest;
+ GetEffectNode(blend_mode_layer)->blend_mode = blend_mode_;
+
+ this->CalcDrawEtc();
+
+ TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000));
+
+ ASSERT_NO_FATAL_FAILURE(VisitLayer(top_layer, &occlusion));
+ // |top_layer| occludes.
+ EXPECT_EQ(gfx::Rect(10, 12, 20, 22).ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+ EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
+
+ ASSERT_NO_FATAL_FAILURE(VisitLayer(blend_mode_layer, &occlusion));
+ // |top_layer| and |blend_mode_layer| both occlude.
+ EXPECT_EQ(gfx::Rect(100, 100).ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+ EXPECT_EQ(gfx::Rect(10, 12, 20, 22).ToString(),
+ occlusion.occlusion_from_outside_target().ToString());
+
+ ASSERT_NO_FATAL_FAILURE(
+ this->VisitContributingSurface(blend_mode_layer, &occlusion));
+ // |top_layer| and |blend_mode_layer| still both occlude.
+ EXPECT_EQ(gfx::Rect(100, 100).ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+ EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
+ }
+
+ private:
+ SkBlendMode blend_mode_;
+};
+
+class OcclusionTrackerTestRenderSurfaceBlendModeSrcOver
+ : public OcclusionTrackerTestRenderSurfaceOccludingBlendMode {
+ protected:
+ explicit OcclusionTrackerTestRenderSurfaceBlendModeSrcOver(bool opaque_layers)
+ : OcclusionTrackerTestRenderSurfaceOccludingBlendMode(
+ opaque_layers,
+ SkBlendMode::kSrcOver) {}
+};
+
+ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRenderSurfaceBlendModeSrcOver)
+
+class OcclusionTrackerTestRenderSurfaceBlendModeSrc
+ : public OcclusionTrackerTestRenderSurfaceOccludingBlendMode {
+ protected:
+ explicit OcclusionTrackerTestRenderSurfaceBlendModeSrc(bool opaque_layers)
+ : OcclusionTrackerTestRenderSurfaceOccludingBlendMode(opaque_layers,
+ SkBlendMode::kSrc) {
+ }
+};
+
+ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRenderSurfaceBlendModeSrc)
+
+class OcclusionTrackerTestRenderSurfaceNonOccludingBlendMode
+ : public OcclusionTrackerTest {
+ protected:
+ explicit OcclusionTrackerTestRenderSurfaceNonOccludingBlendMode(
bool opaque_layers)
: OcclusionTrackerTest(opaque_layers) {}
void RunMyTest() override {
@@ -1877,12 +1949,16 @@ class OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude
};
ALL_OCCLUSIONTRACKER_TEST(
- OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude)
+ OcclusionTrackerTestRenderSurfaceNonOccludingBlendMode)
+
+// No OcclusionTrackerTestNonRenderSurfaceOccludingBlendMode because kSrcOver is
+// default and is tested in many other tests, and kSrc always creates a render
+// surface.
-class OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude
+class OcclusionTrackerTestNonRenderSurfaceNonOccludingBlendMode
: public OcclusionTrackerTest {
protected:
- explicit OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude(
+ explicit OcclusionTrackerTestNonRenderSurfaceNonOccludingBlendMode(
bool opaque_layers)
: OcclusionTrackerTest(opaque_layers) {}
void RunMyTest() override {
@@ -1908,7 +1984,7 @@ class OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude
};
ALL_OCCLUSIONTRACKER_TEST(
- OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude)
+ OcclusionTrackerTestNonRenderSurfaceNonOccludingBlendMode)
class OcclusionTrackerTestMinimumTrackingSize : public OcclusionTrackerTest {
protected:
diff --git a/chromium/cc/trees/property_animation_state.cc b/chromium/cc/trees/property_animation_state.cc
index b82efc75ec4..6c785231ac0 100644
--- a/chromium/cc/trees/property_animation_state.cc
+++ b/chromium/cc/trees/property_animation_state.cc
@@ -4,7 +4,6 @@
#include "cc/trees/property_animation_state.h"
-#include "base/logging.h"
namespace cc {
diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc
index 63eed878cb5..cbdb9d43e73 100644
--- a/chromium/cc/trees/property_tree.cc
+++ b/chromium/cc/trees/property_tree.cc
@@ -7,7 +7,7 @@
#include <set>
#include <vector>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/checked_math.h"
#include "base/trace_event/traced_value.h"
@@ -1202,6 +1202,10 @@ const ScrollNode* ScrollTree::FindNodeFromElementId(ElementId id) const {
return Node(iterator->second);
}
+bool ScrollTree::IsComposited(const ScrollNode& node) const {
+ return node.is_composited;
+}
+
void ScrollTree::clear() {
PropertyTree<ScrollNode>::clear();
@@ -1387,8 +1391,14 @@ const gfx::ScrollOffset ScrollTree::GetPixelSnappedScrollOffset(
if (transform_node->needs_local_transform_update)
property_trees()->transform_tree.UpdateTransforms(transform_node->id);
- offset.set_x(offset.x() - transform_node->snap_amount.x());
- offset.set_y(offset.y() - transform_node->snap_amount.y());
+ // The calculated pixel snap amount can be slightly larger than the actual
+ // snapping needed, due to floating point precision errors. In general this
+ // is fine, but we never want to report a negative scroll offset so avoid
+ // that case here.
+ // TODO(crbug.com/1076878): Remove the clamping when scroll timeline effects
+ // always match the snapping.
+ offset = ClampScrollOffsetToLimits(
+ offset - gfx::ScrollOffset(transform_node->snap_amount), *scroll_node);
}
return offset;
diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h
index add08e3b897..4dcf7d7a0bd 100644
--- a/chromium/cc/trees/property_tree.h
+++ b/chromium/cc/trees/property_tree.h
@@ -489,6 +489,11 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
void NotifyDidChangeScrollbarsHidden(ElementId scroll_element_id,
bool hidden);
+ // A composited scroll node is a scroll node that has an associated composited
+ // layer, otherwise the scroll node corresponds to a scroller that requires
+ // repainting.
+ bool IsComposited(const ScrollNode& node) const;
+
private:
// ScrollTree doesn't use the needs_update flag.
using PropertyTree::needs_update;
diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc
index 6350605baca..b036be21cbd 100644
--- a/chromium/cc/trees/property_tree_builder.cc
+++ b/chromium/cc/trees/property_tree_builder.cc
@@ -470,7 +470,6 @@ bool PropertyTreeBuilderContext::AddEffectNodeIfNeeded(
node->trilinear_filtering = layer->trilinear_filtering();
node->has_potential_opacity_animation = has_potential_opacity_animation;
node->has_potential_filter_animation = has_potential_filter_animation;
- node->double_sided = layer->double_sided();
node->subtree_hidden = layer->hide_layer_and_subtree();
node->is_currently_animating_opacity =
OpacityIsAnimating(mutator_host_, layer);
@@ -633,15 +632,6 @@ void PropertyTreeBuilderContext::AddScrollNodeIfNeeded(
layer->SetScrollTreeIndex(node_id);
}
-void SetBackfaceVisibilityTransform(Layer* layer, bool created_transform_node) {
- // A double-sided layer's backface can been shown when its visible.
- // In addition, we need to check if (1) there might be a local 3D transform
- // on the layer that might turn it to the backface, or (2) it is not drawn
- // into a flattened space.
- layer->SetShouldCheckBackfaceVisibility(!layer->double_sided() &&
- created_transform_node);
-}
-
void SetSafeOpaqueBackgroundColor(const DataForRecursion& data_from_ancestor,
Layer* layer,
DataForRecursion* data_for_children) {
@@ -673,7 +663,6 @@ void PropertyTreeBuilderContext::BuildPropertyTreesInternal(
AddScrollNodeIfNeeded(data_from_parent, layer, &data_for_children);
- SetBackfaceVisibilityTransform(layer, created_transform_node);
SetSafeOpaqueBackgroundColor(data_from_parent, layer, &data_for_children);
bool not_axis_aligned_since_last_clip =
diff --git a/chromium/cc/trees/property_tree_builder_unittest.cc b/chromium/cc/trees/property_tree_builder_unittest.cc
index f46440c6793..af760bc828a 100644
--- a/chromium/cc/trees/property_tree_builder_unittest.cc
+++ b/chromium/cc/trees/property_tree_builder_unittest.cc
@@ -453,185 +453,6 @@ TEST_F(PropertyTreeBuilderTest, TextureLayerSnapping) {
EXPECT_EQ(layer_bounds_in_screen_space, gfx::RectF(11.f, 20.f, 100.f, 100.f));
}
-// Verify the behavior of back-face culling when there are no preserve-3d
-// layers. Note that 3d transforms still apply in this case, but they are
-// "flattened" to each parent layer according to current W3C spec.
-TEST_F(PropertyTreeBuilderTest, BackFaceCullingWithoutPreserves3d) {
- auto root = Layer::Create();
- host()->SetRootLayer(root);
- auto front_facing_child = Layer::Create();
- root->AddChild(front_facing_child);
- auto back_facing_child = Layer::Create();
- root->AddChild(back_facing_child);
- auto front_facing_surface = Layer::Create();
- root->AddChild(front_facing_surface);
- auto back_facing_surface = Layer::Create();
- root->AddChild(back_facing_surface);
- auto front_facing_child_of_front_facing_surface = Layer::Create();
- front_facing_surface->AddChild(front_facing_child_of_front_facing_surface);
- auto back_facing_child_of_front_facing_surface = Layer::Create();
- front_facing_surface->AddChild(back_facing_child_of_front_facing_surface);
- auto front_facing_child_of_back_facing_surface = Layer::Create();
- back_facing_surface->AddChild(front_facing_child_of_back_facing_surface);
- auto back_facing_child_of_back_facing_surface = Layer::Create();
- back_facing_surface->AddChild(back_facing_child_of_back_facing_surface);
-
- // Nothing is double-sided
- front_facing_child->SetDoubleSided(false);
- back_facing_child->SetDoubleSided(false);
- front_facing_surface->SetDoubleSided(false);
- back_facing_surface->SetDoubleSided(false);
- front_facing_child_of_front_facing_surface->SetDoubleSided(false);
- back_facing_child_of_front_facing_surface->SetDoubleSided(false);
- front_facing_child_of_back_facing_surface->SetDoubleSided(false);
- back_facing_child_of_back_facing_surface->SetDoubleSided(false);
-
- // Everything draws content.
- front_facing_child->SetIsDrawable(true);
- back_facing_child->SetIsDrawable(true);
- front_facing_surface->SetIsDrawable(true);
- back_facing_surface->SetIsDrawable(true);
- front_facing_child_of_front_facing_surface->SetIsDrawable(true);
- back_facing_child_of_front_facing_surface->SetIsDrawable(true);
- front_facing_child_of_back_facing_surface->SetIsDrawable(true);
- back_facing_child_of_back_facing_surface->SetIsDrawable(true);
-
- gfx::Transform backface_matrix;
- backface_matrix.Translate(50.0, 50.0);
- backface_matrix.RotateAboutYAxis(180.0);
- backface_matrix.Translate(-50.0, -50.0);
-
- root->SetBounds(gfx::Size(100, 100));
- front_facing_child->SetBounds(gfx::Size(100, 100));
- back_facing_child->SetBounds(gfx::Size(100, 100));
- front_facing_surface->SetBounds(gfx::Size(100, 100));
- back_facing_surface->SetBounds(gfx::Size(100, 100));
- front_facing_child_of_front_facing_surface->SetBounds(gfx::Size(100, 100));
- back_facing_child_of_front_facing_surface->SetBounds(gfx::Size(100, 100));
- front_facing_child_of_back_facing_surface->SetBounds(gfx::Size(100, 100));
- back_facing_child_of_back_facing_surface->SetBounds(gfx::Size(100, 100));
-
- front_facing_surface->SetForceRenderSurfaceForTesting(true);
- back_facing_surface->SetForceRenderSurfaceForTesting(true);
-
- back_facing_child->SetTransform(backface_matrix);
- back_facing_surface->SetTransform(backface_matrix);
- back_facing_child_of_front_facing_surface->SetTransform(backface_matrix);
- back_facing_child_of_back_facing_surface->SetTransform(backface_matrix);
-
- // Note: No layers preserve 3d. According to current W3C CSS gfx::Transforms
- // spec, these layers should blindly use their own local transforms to
- // determine back-face culling.
- CommitAndActivate();
-
- // Verify which render surfaces were created.
- EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child),
- GetRenderSurfaceImpl(root));
- EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child),
- GetRenderSurfaceImpl(root));
- EXPECT_NE(GetRenderSurfaceImpl(front_facing_surface),
- GetRenderSurfaceImpl(root));
- EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
- GetRenderSurfaceImpl(root));
- EXPECT_NE(GetRenderSurfaceImpl(back_facing_surface),
- GetRenderSurfaceImpl(front_facing_surface));
- EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child_of_front_facing_surface),
- GetRenderSurfaceImpl(front_facing_surface));
- EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child_of_front_facing_surface),
- GetRenderSurfaceImpl(front_facing_surface));
- EXPECT_EQ(GetRenderSurfaceImpl(front_facing_child_of_back_facing_surface),
- GetRenderSurfaceImpl(back_facing_surface));
- EXPECT_EQ(GetRenderSurfaceImpl(back_facing_child_of_back_facing_surface),
- GetRenderSurfaceImpl(back_facing_surface));
-
- EXPECT_EQ(3u, update_layer_impl_list().size());
- EXPECT_TRUE(UpdateLayerImplListContains(front_facing_child->id()));
- EXPECT_TRUE(UpdateLayerImplListContains(front_facing_surface->id()));
- EXPECT_TRUE(UpdateLayerImplListContains(
- front_facing_child_of_front_facing_surface->id()));
-}
-
-// Verify that layers are appropriately culled when their back face is showing
-// and they are not double sided, while animations are going on.
-// Even layers that are animating get culled if their back face is showing and
-// they are not double sided.
-TEST_F(PropertyTreeBuilderTest, BackFaceCullingWithAnimatingTransforms) {
- auto root = Layer::Create();
- host()->SetRootLayer(root);
- auto child = Layer::Create();
- root->AddChild(child);
- auto animating_surface = Layer::Create();
- root->AddChild(animating_surface);
- auto child_of_animating_surface = Layer::Create();
- animating_surface->AddChild(child_of_animating_surface);
- auto animating_child = Layer::Create();
- root->AddChild(animating_child);
- auto child2 = Layer::Create();
- root->AddChild(child2);
-
- // Nothing is double-sided
- child->SetDoubleSided(false);
- child2->SetDoubleSided(false);
- animating_surface->SetDoubleSided(false);
- child_of_animating_surface->SetDoubleSided(false);
- animating_child->SetDoubleSided(false);
-
- // Everything draws content.
- child->SetIsDrawable(true);
- child2->SetIsDrawable(true);
- animating_surface->SetIsDrawable(true);
- child_of_animating_surface->SetIsDrawable(true);
- animating_child->SetIsDrawable(true);
-
- gfx::Transform backface_matrix;
- backface_matrix.Translate(50.0, 50.0);
- backface_matrix.RotateAboutYAxis(180.0);
- backface_matrix.Translate(-50.0, -50.0);
-
- host()->SetElementIdsForTesting();
-
- // Animate the transform on the render surface.
- AddAnimatedTransformToElementWithAnimation(animating_surface->element_id(),
- timeline(), 10.0, 30, 0);
- // This is just an animating layer, not a surface.
- AddAnimatedTransformToElementWithAnimation(animating_child->element_id(),
- timeline(), 10.0, 30, 0);
-
- root->SetBounds(gfx::Size(100, 100));
- child->SetBounds(gfx::Size(100, 100));
- child->SetTransform(backface_matrix);
- animating_surface->SetBounds(gfx::Size(100, 100));
- animating_surface->SetTransform(backface_matrix);
- animating_surface->SetForceRenderSurfaceForTesting(true);
- child_of_animating_surface->SetBounds(gfx::Size(100, 100));
- child_of_animating_surface->SetTransform(backface_matrix);
- animating_child->SetBounds(gfx::Size(100, 100));
- animating_child->SetTransform(backface_matrix);
- child2->SetBounds(gfx::Size(100, 100));
-
- CommitAndActivate();
-
- EXPECT_EQ(GetRenderSurfaceImpl(child), GetRenderSurfaceImpl(root));
- EXPECT_TRUE(GetRenderSurfaceImpl(animating_surface));
- EXPECT_EQ(GetRenderSurfaceImpl(child_of_animating_surface),
- GetRenderSurfaceImpl(animating_surface));
- EXPECT_EQ(GetRenderSurfaceImpl(animating_child), GetRenderSurfaceImpl(root));
- EXPECT_EQ(GetRenderSurfaceImpl(child2), GetRenderSurfaceImpl(root));
-
- EXPECT_EQ(1u, update_layer_impl_list().size());
-
- // The back facing layers are culled from the layer list, and have an empty
- // visible rect.
- EXPECT_TRUE(UpdateLayerImplListContains(child2->id()));
- EXPECT_TRUE(ImplOf(child)->visible_layer_rect().IsEmpty());
- EXPECT_TRUE(ImplOf(animating_surface)->visible_layer_rect().IsEmpty());
- EXPECT_TRUE(
- ImplOf(child_of_animating_surface)->visible_layer_rect().IsEmpty());
- EXPECT_TRUE(ImplOf(animating_child)->visible_layer_rect().IsEmpty());
-
- EXPECT_EQ(gfx::Rect(100, 100), ImplOf(child2)->visible_layer_rect());
-}
-
// Verify that having animated opacity but current opacity 1 still creates
// a render surface.
TEST_F(PropertyTreeBuilderTest, AnimatedOpacityCreatesRenderSurface) {
diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc
index 890e9032ba6..8ac81691db8 100644
--- a/chromium/cc/trees/property_tree_unittest.cc
+++ b/chromium/cc/trees/property_tree_unittest.cc
@@ -634,5 +634,37 @@ TEST(EffectTreeTest, CopyOutputRequestsThatBecomeIllegalAreDropped) {
EXPECT_TRUE(requests_out.empty());
}
+// Tests that GetPixelSnappedScrollOffset cannot return a negative offset, even
+// when the snap amount is larger than the scroll offset. The snap amount can be
+// (fractionally) larger due to floating point precision errors, and if the
+// scroll offset is near zero that can naively lead to a negative offset being
+// returned which is not desirable.
+TEST(ScrollTreeTest, GetPixelSnappedScrollOffsetNegativeOffset) {
+ PropertyTrees property_trees;
+ ScrollTree& scroll_tree = property_trees.scroll_tree;
+ TransformTree& transform_tree = property_trees.transform_tree;
+
+ ElementId element_id(5);
+ int transform_node_id = transform_tree.Insert(TransformNode(), 0);
+ int scroll_node_id = scroll_tree.Insert(ScrollNode(), 0);
+ scroll_tree.Node(scroll_node_id)->transform_id = transform_node_id;
+ scroll_tree.Node(scroll_node_id)->element_id = element_id;
+
+ // Set a scroll value close to 0.
+ scroll_tree.SetScrollOffset(element_id, gfx::ScrollOffset(0, 0.1));
+ transform_tree.Node(transform_node_id)->scrolls = true;
+ transform_tree.Node(transform_node_id)->scroll_offset =
+ gfx::ScrollOffset(0, 0.1);
+
+ // Pretend that the snap amount was slightly larger than 0.1.
+ transform_tree.Node(transform_node_id)->snap_amount = gfx::Vector2dF(0, 0.2);
+ transform_tree.Node(transform_node_id)->needs_local_transform_update = false;
+
+ // The returned offset should be clamped at a minimum of 0.
+ gfx::ScrollOffset offset =
+ scroll_tree.GetPixelSnappedScrollOffset(scroll_node_id);
+ EXPECT_EQ(offset.y(), 0);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/proxy_common.h b/chromium/cc/trees/proxy_common.h
index bc45efa8b8a..8dacb9c39d2 100644
--- a/chromium/cc/trees/proxy_common.h
+++ b/chromium/cc/trees/proxy_common.h
@@ -9,7 +9,7 @@
#include "base/callback_forward.h"
#include "cc/cc_export.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_tracker_collection.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
namespace cc {
diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc
index ba19daeb353..544ad6392e3 100644
--- a/chromium/cc/trees/proxy_impl.cc
+++ b/chromium/cc/trees/proxy_impl.cc
@@ -535,6 +535,13 @@ void ProxyImpl::NotifyPaintWorkletStateChange(
scheduler_->NotifyPaintWorkletStateChange(state);
}
+void ProxyImpl::NotifyThroughputTrackerResults(CustomTrackerResults results) {
+ DCHECK(IsImplThread());
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&ProxyMain::NotifyThroughputTrackerResults,
+ proxy_main_weak_ptr_, std::move(results)));
+}
+
bool ProxyImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
DCHECK(IsImplThread());
return host_impl_->WillBeginImplFrame(args);
diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h
index 5457428faf4..3050199e43d 100644
--- a/chromium/cc/trees/proxy_impl.h
+++ b/chromium/cc/trees/proxy_impl.h
@@ -118,6 +118,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
ElementListType element_list_type) override;
void NotifyPaintWorkletStateChange(
Scheduler::PaintWorkletState state) override;
+ void NotifyThroughputTrackerResults(CustomTrackerResults results) override;
// SchedulerClient implementation
bool WillBeginImplFrame(const viz::BeginFrameArgs& args) override;
diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc
index 5fb3d5ce309..22976f62b02 100644
--- a/chromium/cc/trees/proxy_main.cc
+++ b/chromium/cc/trees/proxy_main.cc
@@ -374,6 +374,10 @@ void ProxyMain::DidPresentCompositorFrame(
feedback);
}
+void ProxyMain::NotifyThroughputTrackerResults(CustomTrackerResults results) {
+ layer_tree_host_->NotifyThroughputTrackerResults(std::move(results));
+}
+
bool ProxyMain::IsStarted() const {
DCHECK(IsMainThread());
return started_;
diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h
index 27d960bf8a2..8738cb1f38f 100644
--- a/chromium/cc/trees/proxy_main.h
+++ b/chromium/cc/trees/proxy_main.h
@@ -57,6 +57,7 @@ class CC_EXPORT ProxyMain : public Proxy {
uint32_t frame_token,
std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
const gfx::PresentationFeedback& feedback);
+ void NotifyThroughputTrackerResults(CustomTrackerResults results);
CommitPipelineStage max_requested_pipeline_stage() const {
return max_requested_pipeline_stage_;
diff --git a/chromium/cc/trees/scroll_node.cc b/chromium/cc/trees/scroll_node.cc
index ab20c16bcda..5a83875a7ed 100644
--- a/chromium/cc/trees/scroll_node.cc
+++ b/chromium/cc/trees/scroll_node.cc
@@ -28,7 +28,8 @@ ScrollNode::ScrollNode()
user_scrollable_horizontal(false),
user_scrollable_vertical(false),
transform_id(0),
- overscroll_behavior(OverscrollBehavior::kOverscrollBehaviorTypeAuto) {}
+ overscroll_behavior(OverscrollBehavior::kOverscrollBehaviorTypeAuto),
+ is_composited(false) {}
ScrollNode::ScrollNode(const ScrollNode& other) = default;
@@ -51,7 +52,8 @@ bool ScrollNode::operator==(const ScrollNode& other) const {
user_scrollable_vertical == other.user_scrollable_vertical &&
element_id == other.element_id && transform_id == other.transform_id &&
overscroll_behavior == other.overscroll_behavior &&
- snap_container_data == other.snap_container_data;
+ snap_container_data == other.snap_container_data &&
+ is_composited == other.is_composited;
}
void ScrollNode::AsValueInto(base::trace_event::TracedValue* value) const {
@@ -87,6 +89,8 @@ void ScrollNode::AsValueInto(base::trace_event::TracedValue* value) const {
value->EndArray();
}
}
+
+ value->SetBoolean("is_composited", is_composited);
}
} // namespace cc
diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h
index 57357bdf2e9..c822b5ab711 100644
--- a/chromium/cc/trees/scroll_node.h
+++ b/chromium/cc/trees/scroll_node.h
@@ -63,6 +63,8 @@ struct CC_EXPORT ScrollNode {
base::Optional<SnapContainerData> snap_container_data;
+ bool is_composited : 1;
+
bool operator==(const ScrollNode& other) const;
void AsValueInto(base::trace_event::TracedValue* value) const;
};
diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc
index 7d6ac6449d0..6f469a42c4e 100644
--- a/chromium/cc/trees/single_thread_proxy.cc
+++ b/chromium/cc/trees/single_thread_proxy.cc
@@ -550,6 +550,11 @@ void SingleThreadProxy::NotifyPaintWorkletStateChange(
NOTREACHED();
}
+void SingleThreadProxy::NotifyThroughputTrackerResults(
+ CustomTrackerResults results) {
+ layer_tree_host_->NotifyThroughputTrackerResults(std::move(results));
+}
+
void SingleThreadProxy::RequestBeginMainFrameNotExpected(bool new_state) {
if (scheduler_on_impl_thread_) {
scheduler_on_impl_thread_->SetMainThreadWantsBeginMainFrameNotExpected(
diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h
index 1d24289df85..96228af593c 100644
--- a/chromium/cc/trees/single_thread_proxy.h
+++ b/chromium/cc/trees/single_thread_proxy.h
@@ -136,6 +136,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
ElementListType element_list_type) override;
void NotifyPaintWorkletStateChange(
Scheduler::PaintWorkletState state) override;
+ void NotifyThroughputTrackerResults(CustomTrackerResults results) override;
void RequestNewLayerTreeFrameSink();
diff --git a/chromium/cc/trees/swap_promise_monitor.cc b/chromium/cc/trees/swap_promise_monitor.cc
index 635f17ab3c3..0cb85ca54d0 100644
--- a/chromium/cc/trees/swap_promise_monitor.cc
+++ b/chromium/cc/trees/swap_promise_monitor.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
+#include "cc/trees/swap_promise_monitor.h"
+#include "base/check.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/swap_promise_manager.h"
-#include "cc/trees/swap_promise_monitor.h"
namespace cc {
diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc
index 711a7ea1b49..5c5a70d2020 100644
--- a/chromium/cc/trees/tree_synchronizer.cc
+++ b/chromium/cc/trees/tree_synchronizer.cc
@@ -8,10 +8,10 @@
#include <set>
+#include "base/check_op.h"
#include "base/containers/flat_set.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
-#include "base/logging.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "cc/layers/layer.h"
diff --git a/chromium/cc/trees/ukm_manager.cc b/chromium/cc/trees/ukm_manager.cc
index 5a9e68cf8f2..2141cf1a21c 100644
--- a/chromium/cc/trees/ukm_manager.cc
+++ b/chromium/cc/trees/ukm_manager.cc
@@ -190,7 +190,7 @@ void UkmManager::RecordAggregateThroughput(AggregationType aggregation_type,
void UkmManager::RecordLatencyUKM(
CompositorFrameReporter::FrameReportType report_type,
const std::vector<CompositorFrameReporter::StageData>& stage_history,
- const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+ const CompositorFrameReporter::ActiveTrackers& active_trackers,
const viz::FrameTimingDetails& viz_breakdown) const {
ukm::builders::Graphics_Smoothness_Latency builder(source_id_);
@@ -258,7 +258,11 @@ void UkmManager::RecordLatencyUKM(
}
// Record the active trackers
- for (const auto& frame_sequence_tracker_type : *active_trackers) {
+ for (size_t type = 0; type < active_trackers.size(); ++type) {
+ if (!active_trackers.test(type))
+ continue;
+ const auto frame_sequence_tracker_type =
+ static_cast<FrameSequenceTrackerType>(type);
if (frame_sequence_tracker_type == FrameSequenceTrackerType::kUniversal)
continue;
switch (frame_sequence_tracker_type) {
diff --git a/chromium/cc/trees/ukm_manager.h b/chromium/cc/trees/ukm_manager.h
index 08cce51e755..50653814f85 100644
--- a/chromium/cc/trees/ukm_manager.h
+++ b/chromium/cc/trees/ukm_manager.h
@@ -7,7 +7,7 @@
#include "cc/cc_export.h"
#include "cc/metrics/compositor_frame_reporter.h"
-#include "cc/metrics/frame_sequence_tracker.h"
+#include "cc/metrics/frame_sequence_metrics.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/gurl.h"
@@ -51,7 +51,7 @@ class CC_EXPORT UkmManager {
void RecordLatencyUKM(
CompositorFrameReporter::FrameReportType report_type,
const std::vector<CompositorFrameReporter::StageData>& stage_history,
- const base::flat_set<FrameSequenceTrackerType>* active_trackers,
+ const CompositorFrameReporter::ActiveTrackers& active_trackers,
const viz::FrameTimingDetails& viz_breakdown) const;
ukm::UkmRecorder* recorder_for_testing() { return recorder_.get(); }