summaryrefslogtreecommitdiff
path: root/chromium/cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-26 13:57:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-11-02 11:31:01 +0000
commit1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch)
tree8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/cc
parent21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff)
downloadqtwebengine-chromium-1943b3c2a1dcee36c233724fc4ee7613d71b9cf6.tar.gz
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc')
-rw-r--r--chromium/cc/BUILD.gn4
-rw-r--r--chromium/cc/DEPS1
-rw-r--r--chromium/cc/OWNERS7
-rw-r--r--chromium/cc/PRESUBMIT.py9
-rw-r--r--chromium/cc/README.md14
-rw-r--r--chromium/cc/animation/animation.cc1
-rw-r--r--chromium/cc/animation/animation_timeline.cc3
-rw-r--r--chromium/cc/animation/animation_timeline.h5
-rw-r--r--chromium/cc/animation/animation_unittest.cc6
-rw-r--r--chromium/cc/animation/element_animations.cc16
-rw-r--r--chromium/cc/animation/keyframe_effect.cc2
-rw-r--r--chromium/cc/animation/keyframe_model.cc12
-rw-r--r--chromium/cc/animation/keyframe_model.h4
-rw-r--r--chromium/cc/animation/keyframe_model_unittest.cc2
-rw-r--r--chromium/cc/animation/scroll_offset_animation_curve.cc10
-rw-r--r--chromium/cc/base/devtools_instrumentation.cc1
-rw-r--r--chromium/cc/base/devtools_instrumentation.h43
-rw-r--r--chromium/cc/base/features.cc18
-rw-r--r--chromium/cc/base/features.h9
-rw-r--r--chromium/cc/base/index_rect_unittest.cc3
-rw-r--r--chromium/cc/base/list_container_helper.cc99
-rw-r--r--chromium/cc/base/list_container_helper.h1
-rw-r--r--chromium/cc/base/list_container_unittest.cc2
-rw-r--r--chromium/cc/base/math_util.cc316
-rw-r--r--chromium/cc/base/math_util.h35
-rw-r--r--chromium/cc/base/math_util_unittest.cc350
-rw-r--r--chromium/cc/base/switches.cc3
-rw-r--r--chromium/cc/base/switches.h2
-rw-r--r--chromium/cc/base/tiling_data.cc14
-rw-r--r--chromium/cc/benchmarks/invalidation_benchmark.cc9
-rw-r--r--chromium/cc/benchmarks/micro_benchmark_controller.cc2
-rw-r--r--chromium/cc/benchmarks/micro_benchmark_controller_impl.cc2
-rw-r--r--chromium/cc/benchmarks/rasterize_and_record_benchmark.cc21
-rw-r--r--chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc9
-rw-r--r--chromium/cc/input/browser_controls_offset_manager.cc22
-rw-r--r--chromium/cc/input/browser_controls_offset_manager.h1
-rw-r--r--chromium/cc/input/compositor_input_interfaces.h3
-rw-r--r--chromium/cc/input/input_handler.h5
-rw-r--r--chromium/cc/input/main_thread_scrolling_reason.cc2
-rw-r--r--chromium/cc/input/scroll_snap_data.cc12
-rw-r--r--chromium/cc/input/scroll_snap_data.h2
-rw-r--r--chromium/cc/input/scroll_state_data.cc4
-rw-r--r--chromium/cc/input/scroll_state_data.h1
-rw-r--r--chromium/cc/input/scroll_utils.cc1
-rw-r--r--chromium/cc/input/scrollbar_animation_controller.cc4
-rw-r--r--chromium/cc/input/scrollbar_controller.h3
-rw-r--r--chromium/cc/input/single_scrollbar_animation_controller_thinning.cc5
-rw-r--r--chromium/cc/input/threaded_input_handler.cc33
-rw-r--r--chromium/cc/input/threaded_input_handler.h7
-rw-r--r--chromium/cc/layers/deadline_policy.cc27
-rw-r--r--chromium/cc/layers/deadline_policy.h3
-rw-r--r--chromium/cc/layers/heads_up_display_layer_impl.cc20
-rw-r--r--chromium/cc/layers/layer.cc8
-rw-r--r--chromium/cc/layers/layer.h10
-rw-r--r--chromium/cc/layers/layer_impl_unittest.cc1
-rw-r--r--chromium/cc/layers/layer_unittest.cc18
-rw-r--r--chromium/cc/layers/picture_layer.h2
-rw-r--r--chromium/cc/layers/picture_layer_impl.cc20
-rw-r--r--chromium/cc/layers/picture_layer_impl.h9
-rw-r--r--chromium/cc/layers/picture_layer_impl_unittest.cc3
-rw-r--r--chromium/cc/layers/render_surface_impl.cc8
-rw-r--r--chromium/cc/layers/render_surface_impl.h9
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.cc8
-rw-r--r--chromium/cc/layers/surface_layer_impl.cc2
-rw-r--r--chromium/cc/layers/texture_layer.cc1
-rw-r--r--chromium/cc/layers/texture_layer_impl.cc1
-rw-r--r--chromium/cc/layers/video_layer.cc10
-rw-r--r--chromium/cc/layers/video_layer.h9
-rw-r--r--chromium/cc/layers/video_layer_impl.cc30
-rw-r--r--chromium/cc/layers/video_layer_impl.h12
-rw-r--r--chromium/cc/metrics/average_lag_tracker.cc43
-rw-r--r--chromium/cc/metrics/average_lag_tracker.h7
-rw-r--r--chromium/cc/metrics/average_lag_tracker_unittest.cc68
-rw-r--r--chromium/cc/metrics/average_lag_tracking_manager.cc5
-rw-r--r--chromium/cc/metrics/average_lag_tracking_manager.h9
-rw-r--r--chromium/cc/metrics/average_lag_tracking_manager_unittest.cc62
-rw-r--r--chromium/cc/metrics/begin_main_frame_metrics.cc3
-rw-r--r--chromium/cc/metrics/begin_main_frame_metrics.h1
-rw-r--r--chromium/cc/metrics/compositor_frame_reporter.cc14
-rw-r--r--chromium/cc/metrics/compositor_frame_reporter.h13
-rw-r--r--chromium/cc/metrics/compositor_frame_reporter_unittest.cc115
-rw-r--r--chromium/cc/metrics/compositor_frame_reporting_controller.cc2
-rw-r--r--chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc239
-rw-r--r--chromium/cc/metrics/compositor_timing_history.cc44
-rw-r--r--chromium/cc/metrics/compositor_timing_history.h12
-rw-r--r--chromium/cc/metrics/dropped_frame_counter.cc17
-rw-r--r--chromium/cc/metrics/dropped_frame_counter.h4
-rw-r--r--chromium/cc/metrics/dropped_frame_counter_unittest.cc128
-rw-r--r--chromium/cc/metrics/event_metrics.cc119
-rw-r--r--chromium/cc/metrics/event_metrics.h30
-rw-r--r--chromium/cc/metrics/events_metrics_manager.cc1
-rw-r--r--chromium/cc/metrics/events_metrics_manager_unittest.cc6
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics.cc96
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics.h11
-rw-r--r--chromium/cc/metrics/frame_sequence_metrics_unittest.cc15
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker.cc1
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker.h2
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker_collection.cc1
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker_collection.h1
-rw-r--r--chromium/cc/metrics/frame_sequence_tracker_unittest.cc120
-rw-r--r--chromium/cc/metrics/jank_metrics.cc23
-rw-r--r--chromium/cc/metrics/jank_metrics_unittest.cc82
-rw-r--r--chromium/cc/metrics/video_playback_roughness_reporter.cc7
-rw-r--r--chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc4
-rw-r--r--chromium/cc/paint/decoded_draw_image.cc8
-rw-r--r--chromium/cc/paint/decoded_draw_image.h13
-rw-r--r--chromium/cc/paint/discardable_image_map.cc4
-rw-r--r--chromium/cc/paint/discardable_image_map_unittest.cc9
-rw-r--r--chromium/cc/paint/display_item_list.cc4
-rw-r--r--chromium/cc/paint/display_item_list.h1
-rw-r--r--chromium/cc/paint/display_item_list_unittest.cc32
-rw-r--r--chromium/cc/paint/draw_image.cc6
-rw-r--r--chromium/cc/paint/draw_image.h8
-rw-r--r--chromium/cc/paint/filter_operation.cc30
-rw-r--r--chromium/cc/paint/filter_operation.h14
-rw-r--r--chromium/cc/paint/filter_operations.cc6
-rw-r--r--chromium/cc/paint/filter_operations_unittest.cc4
-rw-r--r--chromium/cc/paint/image_provider.h1
-rw-r--r--chromium/cc/paint/oop_pixeltest.cc71
-rw-r--r--chromium/cc/paint/paint_cache.h5
-rw-r--r--chromium/cc/paint/paint_cache_unittest.cc1
-rw-r--r--chromium/cc/paint/paint_canvas.h25
-rw-r--r--chromium/cc/paint/paint_filter.cc395
-rw-r--r--chromium/cc/paint/paint_filter.h80
-rw-r--r--chromium/cc/paint/paint_filter_unittest.cc13
-rw-r--r--chromium/cc/paint/paint_flags.cc25
-rw-r--r--chromium/cc/paint/paint_flags.h27
-rw-r--r--chromium/cc/paint/paint_op_buffer.cc60
-rw-r--r--chromium/cc/paint/paint_op_buffer.h30
-rw-r--r--chromium/cc/paint/paint_op_buffer_serializer.cc9
-rw-r--r--chromium/cc/paint/paint_op_buffer_serializer.h15
-rw-r--r--chromium/cc/paint/paint_op_buffer_unittest.cc200
-rw-r--r--chromium/cc/paint/paint_op_helper_unittest.cc12
-rw-r--r--chromium/cc/paint/paint_op_perftest.cc1
-rw-r--r--chromium/cc/paint/paint_op_reader.cc93
-rw-r--r--chromium/cc/paint/paint_op_reader.h16
-rw-r--r--chromium/cc/paint/paint_op_writer.cc88
-rw-r--r--chromium/cc/paint/paint_op_writer.h15
-rw-r--r--chromium/cc/paint/paint_recorder.h1
-rw-r--r--chromium/cc/paint/paint_shader.cc66
-rw-r--r--chromium/cc/paint/paint_shader.h27
-rw-r--r--chromium/cc/paint/paint_worklet_input.h3
-rw-r--r--chromium/cc/paint/record_paint_canvas.cc12
-rw-r--r--chromium/cc/paint/record_paint_canvas.h9
-rw-r--r--chromium/cc/paint/render_surface_filters.cc7
-rw-r--r--chromium/cc/paint/scoped_raster_flags.cc2
-rw-r--r--chromium/cc/paint/scoped_raster_flags.h1
-rw-r--r--chromium/cc/paint/skia_paint_canvas.cc8
-rw-r--r--chromium/cc/paint/skia_paint_canvas.h9
-rw-r--r--chromium/cc/paint/solid_color_analyzer.h1
-rw-r--r--chromium/cc/paint/solid_color_analyzer_unittest.cc2
-rw-r--r--chromium/cc/raster/gpu_raster_buffer_provider.cc9
-rw-r--r--chromium/cc/raster/paint_worklet_image_provider.cc9
-rw-r--r--chromium/cc/raster/playback_image_provider_unittest.cc30
-rw-r--r--chromium/cc/raster/raster_buffer_provider_unittest.cc1
-rw-r--r--chromium/cc/raster/raster_source.h6
-rw-r--r--chromium/cc/raster/task.cc3
-rw-r--r--chromium/cc/resources/resource_pool.cc16
-rw-r--r--chromium/cc/resources/resource_pool.h19
-rw-r--r--chromium/cc/resources/ui_resource_bitmap.cc28
-rw-r--r--chromium/cc/scheduler/begin_frame_tracker.cc18
-rw-r--r--chromium/cc/scheduler/begin_frame_tracker.h2
-rw-r--r--chromium/cc/scheduler/scheduler.cc123
-rw-r--r--chromium/cc/scheduler/scheduler.h10
-rw-r--r--chromium/cc/scheduler/scheduler_settings.cc6
-rw-r--r--chromium/cc/scheduler/scheduler_settings.h10
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.cc22
-rw-r--r--chromium/cc/scheduler/scheduler_state_machine.h29
-rw-r--r--chromium/cc/scheduler/scheduler_unittest.cc410
-rw-r--r--chromium/cc/tiles/checker_image_tracker.cc1
-rw-r--r--chromium/cc/tiles/checker_image_tracker.h2
-rw-r--r--chromium/cc/tiles/checker_image_tracker_unittest.cc8
-rw-r--r--chromium/cc/tiles/decoded_image_tracker.cc5
-rw-r--r--chromium/cc/tiles/decoded_image_tracker_unittest.cc15
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache.cc33
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache.h10
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache_perftest.cc6
-rw-r--r--chromium/cc/tiles/gpu_image_decode_cache_unittest.cc157
-rw-r--r--chromium/cc/tiles/image_controller_unittest.cc4
-rw-r--r--chromium/cc/tiles/image_decode_cache_utils.cc4
-rw-r--r--chromium/cc/tiles/image_decode_cache_utils.h8
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.cc19
-rw-r--r--chromium/cc/tiles/picture_layer_tiling.h2
-rw-r--r--chromium/cc/tiles/picture_layer_tiling_set.cc4
-rw-r--r--chromium/cc/tiles/prioritized_tile.h2
-rw-r--r--chromium/cc/tiles/software_image_decode_cache.cc10
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_perftest.cc6
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_unittest.cc201
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_unittest_combinations.cc3
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_utils.cc9
-rw-r--r--chromium/cc/tiles/software_image_decode_cache_utils.h1
-rw-r--r--chromium/cc/tiles/tile_manager.cc10
-rw-r--r--chromium/cc/tiles/tile_manager_perftest.cc2
-rw-r--r--chromium/cc/tiles/tile_manager_unittest.cc138
-rw-r--r--chromium/cc/trees/animated_paint_worklet_tracker.cc1
-rw-r--r--chromium/cc/trees/clip_expander.cc2
-rw-r--r--chromium/cc/trees/clip_expander.h1
-rw-r--r--chromium/cc/trees/compositor_commit_data.h1
-rw-r--r--chromium/cc/trees/damage_tracker_unittest.cc46
-rw-r--r--chromium/cc/trees/de_jelly_state.h2
-rw-r--r--chromium/cc/trees/draw_properties_unittest.cc13
-rw-r--r--chromium/cc/trees/draw_property_utils.cc87
-rw-r--r--chromium/cc/trees/effect_node.cc7
-rw-r--r--chromium/cc/trees/effect_node.h3
-rw-r--r--chromium/cc/trees/frame_rate_estimator_unittest.cc2
-rw-r--r--chromium/cc/trees/image_animation_controller.h1
-rw-r--r--chromium/cc/trees/layer_tree_host.cc73
-rw-r--r--chromium/cc/trees/layer_tree_host.h33
-rw-r--r--chromium/cc/trees/layer_tree_host_client.h7
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc144
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.h55
-rw-r--r--chromium/cc/trees/layer_tree_host_impl_unittest.cc159
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_blending.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_masks.cc4
-rw-r--r--chromium/cc/trees/layer_tree_host_pixeltest_readback.cc26
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest.cc335
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_animation.cc9
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_capture_content.cc5
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_context.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc83
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_damage.cc5
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_scroll.cc36
-rw-r--r--chromium/cc/trees/layer_tree_host_unittest_video.cc7
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc20
-rw-r--r--chromium/cc/trees/layer_tree_impl.h12
-rw-r--r--chromium/cc/trees/layer_tree_impl_unittest.cc6
-rw-r--r--chromium/cc/trees/layer_tree_settings.cc4
-rw-r--r--chromium/cc/trees/layer_tree_settings.h4
-rw-r--r--chromium/cc/trees/mobile_optimized_viewport_util.cc41
-rw-r--r--chromium/cc/trees/mobile_optimized_viewport_util.h34
-rw-r--r--chromium/cc/trees/occlusion_tracker.cc4
-rw-r--r--chromium/cc/trees/occlusion_unittest.cc2
-rw-r--r--chromium/cc/trees/paint_holding_commit_trigger.cc22
-rw-r--r--chromium/cc/trees/paint_holding_commit_trigger.h12
-rw-r--r--chromium/cc/trees/paint_holding_reason.h21
-rw-r--r--chromium/cc/trees/presentation_time_callback_buffer.cc43
-rw-r--r--chromium/cc/trees/presentation_time_callback_buffer.h33
-rw-r--r--chromium/cc/trees/presentation_time_callback_buffer_unittest.cc113
-rw-r--r--chromium/cc/trees/property_tree.cc20
-rw-r--r--chromium/cc/trees/property_tree.h41
-rw-r--r--chromium/cc/trees/property_tree_builder.cc19
-rw-r--r--chromium/cc/trees/property_tree_builder_unittest.cc37
-rw-r--r--chromium/cc/trees/proxy.h9
-rw-r--r--chromium/cc/trees/proxy_impl.cc15
-rw-r--r--chromium/cc/trees/proxy_impl.h2
-rw-r--r--chromium/cc/trees/proxy_main.cc71
-rw-r--r--chromium/cc/trees/proxy_main.h13
-rw-r--r--chromium/cc/trees/scroll_node.h1
-rw-r--r--chromium/cc/trees/single_thread_proxy.cc47
-rw-r--r--chromium/cc/trees/single_thread_proxy.h10
-rw-r--r--chromium/cc/trees/sticky_position_constraint.cc3
-rw-r--r--chromium/cc/trees/sticky_position_constraint.h1
-rw-r--r--chromium/cc/trees/throttle_decider.cc9
-rw-r--r--chromium/cc/trees/throttle_decider.h4
-rw-r--r--chromium/cc/trees/transform_node.cc2
-rw-r--r--chromium/cc/trees/transform_node.h1
-rw-r--r--chromium/cc/trees/tree_synchronizer_unittest.cc6
-rw-r--r--chromium/cc/trees/ukm_manager_unittest.cc29
258 files changed, 4943 insertions, 2455 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn
index eaa675ba6a9..3234a484465 100644
--- a/chromium/cc/BUILD.gn
+++ b/chromium/cc/BUILD.gn
@@ -373,13 +373,17 @@ cc_component("cc") {
"trees/layer_tree_settings.h",
"trees/managed_memory_policy.cc",
"trees/managed_memory_policy.h",
+ "trees/mobile_optimized_viewport_util.cc",
+ "trees/mobile_optimized_viewport_util.h",
"trees/mutator_host.h",
"trees/mutator_host_client.h",
"trees/occlusion.cc",
"trees/occlusion.h",
"trees/occlusion_tracker.cc",
"trees/occlusion_tracker.h",
+ "trees/paint_holding_commit_trigger.cc",
"trees/paint_holding_commit_trigger.h",
+ "trees/paint_holding_reason.h",
"trees/presentation_time_callback_buffer.cc",
"trees/presentation_time_callback_buffer.h",
"trees/property_animation_state.cc",
diff --git a/chromium/cc/DEPS b/chromium/cc/DEPS
index b694c05b487..dc197834bf6 100644
--- a/chromium/cc/DEPS
+++ b/chromium/cc/DEPS
@@ -37,6 +37,7 @@ include_rules = [
"+third_party/libyuv",
"+third_party/skia/include",
"+third_party/skia/src/core/SkRemoteGlyphCache.h",
+ "+third_party/skia/src/effects/imagefilters/SkRuntimeImageFilter.h",
"+third_party/perfetto/protos/perfetto/trace/track_event",
"+ui/events/types",
"+ui/latency",
diff --git a/chromium/cc/OWNERS b/chromium/cc/OWNERS
index 57a11c57c6f..2d8d597dbc8 100644
--- a/chromium/cc/OWNERS
+++ b/chromium/cc/OWNERS
@@ -23,6 +23,7 @@ vmpstr@chromium.org
sunnyps@chromium.org
# math / geometry
+dbaron@chromium.org
flackr@chromium.org
# property trees
@@ -45,15 +46,15 @@ jonross@chromium.org
# input, scrolling
bokan@chromium.org
-# scroll snap
-majidvp@chromium.org
-
# metrics
sadrul@chromium.org
+behdadb@chromium.org
# paint
sunnyps@chromium.org
vasilyt@chromium.org
+reed@google.com
+fmalita@chromium.org
# general
vmpstr@chromium.org
diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py
index c375a37d367..a3a40eda5ef 100644
--- a/chromium/cc/PRESUBMIT.py
+++ b/chromium/cc/PRESUBMIT.py
@@ -9,8 +9,8 @@ for more details about the presubmit API built into depot_tools.
"""
import re
-import string
+USE_PYTHON3 = True
CC_SOURCE_FILES=(r'^cc[\\/].*\.(cc|h)$',)
def CheckChangeLintsClean(input_api, output_api):
@@ -105,9 +105,9 @@ def CheckPassByValue(input_api,
for f in input_api.AffectedSourceFiles(source_file_filter):
contents = input_api.ReadFile(f, 'rb')
+ sep = '|'
match = re.search(
- r'\bconst +' + '(?P<type>(%s))&' %
- string.join(pass_by_value_types, '|'),
+ r'\bconst +' + '(?P<type>(%s))&' % sep.join(pass_by_value_types),
contents)
if match:
local_errors.append(output_api.PresubmitError(
@@ -297,7 +297,8 @@ def CheckForDisallowMacros(input_api, output_api, allowlist=CC_SOURCE_FILES,
if disallow_macro_files:
return [output_api.PresubmitError(
- 'The following files use DISALLOW* macros. In cc, please use deleted constructors/operators instead.',
+ 'The following files use DISALLOW* macros. In cc, please use deleted '
+ 'constructors/operators instead.',
items=disallow_macro_files)]
return []
diff --git a/chromium/cc/README.md b/chromium/cc/README.md
index e8ae01d7bfb..86dc284e11a 100644
--- a/chromium/cc/README.md
+++ b/chromium/cc/README.md
@@ -33,11 +33,10 @@ which batches up a set of DrawQuads and RenderPasses into a
CompositorFrame which is sent via a CompositorFrameSink.
CompositorFrames from individual compositors are sent to the
-SurfaceManager (currently in the browser process). The
-SurfaceAggregator combines all CompositorFrames together and asks
-the Display to finally draw the frame via Renderer, which is either
-a viz::GLRenderer or a SoftwareRenderer, which finally draws the entire
-composited browser contents into a backbuffer or a bitmap, respectively.
+SurfaceManager (which is in the GPU process). The SurfaceAggregator combines all
+CompositorFrames together when asked to by the Display. These are given to the
+viz::DirectRenderer, which finally draws the entire composited browser contents.
+See //components/viz for more details on the display compositor.
Design documents for the graphics stack can be found at
[chromium-graphics](https://www.chromium.org/developers/design-documents/chromium-graphics).
@@ -76,7 +75,8 @@ that is responsible for a composited animation. Some additional information in
### DirectRenderer
An abstraction that provides an API for the Display to draw a fully-aggregated
CompositorFrame to a physical output. Subclasses of it provide implementations
-for various backends, currently GL or Software.
+for various backends, currently GL, Skia, or Software. See [viz::DirectRenderer](https://codesearch.chromium.org/chromium/src/components/viz/service/display/direct_renderer.h)
+for details.
### Layer
A conceptual piece of content that can appear on screen and has some known
@@ -102,7 +102,7 @@ and [Blink Property Trees](https://docs.google.com/presentation/u/1/d/1ak7YVrJIT
### Display
A controller class that takes CompositorFrames for each surface and draws them
-to a physical output.
+to a physical output. See [viz::Display](https://codesearch.chromium.org/chromium/src/components/viz/service/display/display.h) for details.
### Draw
Filling pixels in a physical output (technically could be to an offscreen
diff --git a/chromium/cc/animation/animation.cc b/chromium/cc/animation/animation.cc
index 220347a9220..34af25da509 100644
--- a/chromium/cc/animation/animation.cc
+++ b/chromium/cc/animation/animation.cc
@@ -10,7 +10,6 @@
#include <string>
#include <utility>
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/animation_events.h"
diff --git a/chromium/cc/animation/animation_timeline.cc b/chromium/cc/animation/animation_timeline.cc
index d7067c5e235..ac3a92e9c2c 100644
--- a/chromium/cc/animation/animation_timeline.cc
+++ b/chromium/cc/animation/animation_timeline.cc
@@ -5,7 +5,10 @@
#include "cc/animation/animation_timeline.h"
#include <algorithm>
+#include <utility>
+#include <vector>
+#include "base/time/time.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_host.h"
#include "cc/trees/property_tree.h"
diff --git a/chromium/cc/animation/animation_timeline.h b/chromium/cc/animation/animation_timeline.h
index 6ff994afa56..3f23c39416c 100644
--- a/chromium/cc/animation/animation_timeline.h
+++ b/chromium/cc/animation/animation_timeline.h
@@ -7,10 +7,15 @@
#include <memory>
#include <unordered_map>
+#include <vector>
#include "base/memory/ref_counted.h"
#include "cc/animation/animation_export.h"
+namespace base {
+class TimeTicks;
+}
+
namespace cc {
class Animation;
diff --git a/chromium/cc/animation/animation_unittest.cc b/chromium/cc/animation/animation_unittest.cc
index 15fe8962b49..2fc379f5957 100644
--- a/chromium/cc/animation/animation_unittest.cc
+++ b/chromium/cc/animation/animation_unittest.cc
@@ -463,7 +463,7 @@ TEST_F(AnimationTest, ToString) {
base::StringPrintf("Animation{id=%d, element_id=%s, "
"keyframe_models=[KeyframeModel{id=42, "
"group=73, target_property_type=1, "
- "custom_property_name=, native_property_type=1, "
+ "custom_property_name=, native_property_type=2, "
"run_state=WAITING_FOR_TARGET_AVAILABILITY, "
"element_id=(0)}]}",
animation_->id(), element_id_.ToString().c_str()),
@@ -476,10 +476,10 @@ TEST_F(AnimationTest, ToString) {
"Animation{id=%d, element_id=%s, "
"keyframe_models=[KeyframeModel{id=42, "
"group=73, target_property_type=1, custom_property_name=, "
- "native_property_type=1, "
+ "native_property_type=2, "
"run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}, "
"KeyframeModel{id=45, group=76, target_property_type=5, "
- "custom_property_name=, native_property_type=1, "
+ "custom_property_name=, native_property_type=2, "
"run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}]}",
animation_->id(), element_id_.ToString().c_str()),
animation_->ToString());
diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc
index bb4fad08e90..ebe6c50fd61 100644
--- a/chromium/cc/animation/element_animations.cc
+++ b/chromium/cc/animation/element_animations.cc
@@ -8,8 +8,9 @@
#include <algorithm>
#include <utility>
+#include <vector>
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/animation_events.h"
#include "cc/animation/animation_host.h"
@@ -119,6 +120,12 @@ void ElementAnimations::ClearAffectedElementTypes(
RemoveKeyframeEffectsFromTicking();
}
+// TODO(crbug.com/1240712): the ReservedElementId should always be 'registered'.
+// Instead of calling this from AnimationHost::UpdateRegisteredElementIds, we
+// can ensure that the |has_element_in_active_list_| and the
+// |has_element_in_pending_list_| are true for ReservedElementId, and this
+// should result in animations ticking right away. With that, we do not need to
+// add anything to the |keyframe_effects_list_| for ReservedElementId.
void ElementAnimations::ElementIdRegistered(ElementId element_id,
ElementListType list_type) {
DCHECK_EQ(element_id_, element_id);
@@ -224,7 +231,7 @@ void ElementAnimations::OnFloatAnimated(const float& value,
target_property_id);
break;
case TargetProperty::OPACITY: {
- float opacity = base::ClampToRange(value, 0.0f, 1.0f);
+ float opacity = base::clamp(value, 0.0f, 1.0f);
if (KeyframeModelAffectsActiveElements(keyframe_model))
OnOpacityAnimated(ElementListType::ACTIVE, opacity, keyframe_model);
if (KeyframeModelAffectsPendingElements(keyframe_model))
@@ -305,6 +312,11 @@ void ElementAnimations::InitClientAnimationState() {
void ElementAnimations::UpdateClientAnimationState() {
if (!element_id())
return;
+ // For a custom property animation, or an animation that uses paint worklet,
+ // it is not associated with any property node, and thus this function is not
+ // needed.
+ if (element_id().GetStableId() == ElementId::kReservedElementId)
+ return;
DCHECK(animation_host_);
if (!animation_host_->mutator_host_client())
return;
diff --git a/chromium/cc/animation/keyframe_effect.cc b/chromium/cc/animation/keyframe_effect.cc
index 1076d5a2e0e..99beca105a1 100644
--- a/chromium/cc/animation/keyframe_effect.cc
+++ b/chromium/cc/animation/keyframe_effect.cc
@@ -9,7 +9,7 @@
#include <string>
#include <utility>
-#include "base/stl_util.h"
+#include "base/containers/cxx20_erase.h"
#include "base/time/time.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_host.h"
diff --git a/chromium/cc/animation/keyframe_model.cc b/chromium/cc/animation/keyframe_model.cc
index 7f4801ea695..95d6a7a651b 100644
--- a/chromium/cc/animation/keyframe_model.cc
+++ b/chromium/cc/animation/keyframe_model.cc
@@ -12,7 +12,6 @@
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
@@ -55,15 +54,22 @@ KeyframeModel::TargetPropertyId::TargetPropertyId(
KeyframeModel::TargetPropertyId::TargetPropertyId(
const TargetPropertyId& other) = default;
+KeyframeModel::TargetPropertyId::TargetPropertyId(TargetPropertyId&& other) =
+ default;
+
KeyframeModel::TargetPropertyId::~TargetPropertyId() = default;
+KeyframeModel::TargetPropertyId& KeyframeModel::TargetPropertyId::operator=(
+ TargetPropertyId&& other) = default;
+
std::unique_ptr<KeyframeModel> KeyframeModel::Create(
std::unique_ptr<gfx::AnimationCurve> curve,
int keyframe_model_id,
int group_id,
TargetPropertyId target_property_id) {
return base::WrapUnique(new KeyframeModel(std::move(curve), keyframe_model_id,
- group_id, target_property_id));
+ group_id,
+ std::move(target_property_id)));
}
std::unique_ptr<KeyframeModel> KeyframeModel::CreateImplInstance(
@@ -97,7 +103,7 @@ KeyframeModel::KeyframeModel(std::unique_ptr<gfx::AnimationCurve> curve,
keyframe_model_id,
target_property_id.target_property_type()),
group_(group_id),
- target_property_id_(target_property_id),
+ target_property_id_(std::move(target_property_id)),
needs_synchronized_start_time_(false),
received_finished_event_(false),
is_controlling_instance_(false),
diff --git a/chromium/cc/animation/keyframe_model.h b/chromium/cc/animation/keyframe_model.h
index 8be005fd25e..2c9edb9170d 100644
--- a/chromium/cc/animation/keyframe_model.h
+++ b/chromium/cc/animation/keyframe_model.h
@@ -12,7 +12,6 @@
#include "cc/animation/animation_export.h"
#include "cc/paint/element_id.h"
#include "cc/paint/paint_worklet_input.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/animation/keyframe/keyframe_model.h"
namespace cc {
@@ -43,8 +42,11 @@ class CC_ANIMATION_EXPORT KeyframeModel : public gfx::KeyframeModel {
int target_property_type,
PaintWorkletInput::NativePropertyType native_property_type);
TargetPropertyId(const TargetPropertyId&);
+ TargetPropertyId(TargetPropertyId&&);
~TargetPropertyId();
+ TargetPropertyId& operator=(TargetPropertyId&& other);
+
int target_property_type() const { return target_property_type_; }
const std::string& custom_property_name() const {
return custom_property_name_;
diff --git a/chromium/cc/animation/keyframe_model_unittest.cc b/chromium/cc/animation/keyframe_model_unittest.cc
index 1e01ad2ac47..c4003ed28dd 100644
--- a/chromium/cc/animation/keyframe_model_unittest.cc
+++ b/chromium/cc/animation/keyframe_model_unittest.cc
@@ -1388,7 +1388,7 @@ TEST(KeyframeModelTest, ToString) {
KeyframeModel::TargetPropertyId(TargetProperty::OPACITY));
EXPECT_EQ(base::StringPrintf(
"KeyframeModel{id=%d, group=73, target_property_type=1, "
- "custom_property_name=, native_property_type=1, "
+ "custom_property_name=, native_property_type=2, "
"run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}",
keyframe_model->id()),
keyframe_model->ToString());
diff --git a/chromium/cc/animation/scroll_offset_animation_curve.cc b/chromium/cc/animation/scroll_offset_animation_curve.cc
index 1b4d045c74c..0ba2a8dd155 100644
--- a/chromium/cc/animation/scroll_offset_animation_curve.cc
+++ b/chromium/cc/animation/scroll_offset_animation_curve.cc
@@ -9,8 +9,8 @@
#include <utility>
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/numerics/ranges.h"
#include "ui/gfx/animation/keyframe/timing_function.h"
#include "ui/gfx/animation/tween.h"
@@ -56,7 +56,7 @@ static float MaximumDimension(const gfx::Vector2dF& delta) {
static std::unique_ptr<TimingFunction> EaseInOutWithInitialSlope(double slope) {
// Clamp slope to a sane value.
- slope = base::ClampToRange(slope, -1000.0, 1000.0);
+ slope = base::clamp(slope, -1000.0, 1000.0);
// Based on CubicBezierTimingFunction::EaseType::EASE_IN_OUT preset
// with first control point scaled.
@@ -193,8 +193,8 @@ base::TimeDelta ScrollOffsetAnimationCurve::EaseInOutSegmentDuration(
case DurationBehavior::INVERSE_DELTA:
duration = kInverseDeltaOffset +
std::abs(MaximumDimension(delta)) * kInverseDeltaSlope;
- duration = base::ClampToRange(duration, kInverseDeltaMinDuration,
- kInverseDeltaMaxDuration);
+ duration = base::clamp(duration, kInverseDeltaMinDuration,
+ kInverseDeltaMaxDuration);
break;
}
duration /= kDurationDivisor;
@@ -268,7 +268,7 @@ base::TimeDelta ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
} else {
double duration_in_milliseconds =
kImpulseMillisecondsPerPixel * std::abs(MaximumDimension(delta));
- duration_in_milliseconds = base::ClampToRange(
+ duration_in_milliseconds = base::clamp(
duration_in_milliseconds, kImpulseMinDurationMs, kImpulseMaxDurationMs);
duration = base::TimeDelta::FromMillisecondsD(duration_in_milliseconds);
}
diff --git a/chromium/cc/base/devtools_instrumentation.cc b/chromium/cc/base/devtools_instrumentation.cc
index 85141d8ce59..79c321ae344 100644
--- a/chromium/cc/base/devtools_instrumentation.cc
+++ b/chromium/cc/base/devtools_instrumentation.cc
@@ -38,6 +38,7 @@ const char kFrameId[] = "frameId";
const char kLayerId[] = "layerId";
const char kLayerTreeId[] = "layerTreeId";
const char kPixelRefId[] = "pixelRefId";
+const char kFrameSequenceNumber[] = "frameSeqId";
const char kImageUploadTask[] = "ImageUploadTask";
const char kImageDecodeTask[] = "ImageDecodeTask";
diff --git a/chromium/cc/base/devtools_instrumentation.h b/chromium/cc/base/devtools_instrumentation.h
index 0b19cf006da..39a816a3ae8 100644
--- a/chromium/cc/base/devtools_instrumentation.h
+++ b/chromium/cc/base/devtools_instrumentation.h
@@ -14,6 +14,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
+#include "base/trace_event/typed_macros.h"
#include "cc/base/base_export.h"
namespace cc {
@@ -33,6 +34,7 @@ CC_BASE_EXPORT extern const char kFrameId[];
CC_BASE_EXPORT extern const char kLayerId[];
CC_BASE_EXPORT extern const char kLayerTreeId[];
CC_BASE_EXPORT extern const char kPixelRefId[];
+CC_BASE_EXPORT extern const char kFrameSequenceNumber[];
CC_BASE_EXPORT extern const char kImageDecodeTask[];
CC_BASE_EXPORT extern const char kBeginFrame[];
@@ -142,10 +144,11 @@ class CC_BASE_EXPORT ScopedLayerTreeTask {
struct CC_BASE_EXPORT ScopedCommitTrace {
public:
- explicit ScopedCommitTrace(int layer_tree_host_id) {
- TRACE_EVENT_BEGIN1(internal::CategoryName::kTimeline,
+ explicit ScopedCommitTrace(int layer_tree_host_id, uint64_t sequence_number) {
+ TRACE_EVENT_BEGIN2(internal::CategoryName::kTimeline,
internal::kCompositeLayers, internal::kLayerTreeId,
- layer_tree_host_id);
+ layer_tree_host_id, internal::kFrameSequenceNumber,
+ sequence_number);
}
ScopedCommitTrace(const ScopedCommitTrace&) = delete;
~ScopedCommitTrace() {
@@ -176,18 +179,22 @@ inline void CC_BASE_EXPORT DidActivateLayerTree(int layer_tree_host_id,
internal::kFrameId, frame_id);
}
-inline void CC_BASE_EXPORT
-DidBeginFrame(int layer_tree_host_id, base::TimeTicks begin_frame_timestamp) {
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
- internal::CategoryName::kTimelineFrame, internal::kBeginFrame,
- TRACE_EVENT_SCOPE_THREAD, begin_frame_timestamp, internal::kLayerTreeId,
- layer_tree_host_id);
+inline void CC_BASE_EXPORT DidBeginFrame(int layer_tree_host_id,
+ base::TimeTicks begin_frame_timestamp,
+ uint64_t sequence_number) {
+ TRACE_EVENT_INSTANT(internal::CategoryName::kTimelineFrame,
+ perfetto::StaticString(internal::kBeginFrame),
+ begin_frame_timestamp, internal::kLayerTreeId,
+ layer_tree_host_id, internal::kFrameSequenceNumber,
+ sequence_number);
}
-inline void CC_BASE_EXPORT DidDrawFrame(int layer_tree_host_id) {
- TRACE_EVENT_INSTANT1(internal::CategoryName::kTimelineFrame,
+inline void CC_BASE_EXPORT DidDrawFrame(int layer_tree_host_id,
+ uint64_t sequence_number) {
+ TRACE_EVENT_INSTANT2(internal::CategoryName::kTimelineFrame,
internal::kDrawFrame, TRACE_EVENT_SCOPE_THREAD,
- internal::kLayerTreeId, layer_tree_host_id);
+ internal::kLayerTreeId, layer_tree_host_id,
+ internal::kFrameSequenceNumber, sequence_number);
}
inline void CC_BASE_EXPORT DidRequestMainThreadFrame(int layer_tree_host_id) {
@@ -198,11 +205,13 @@ inline void CC_BASE_EXPORT DidRequestMainThreadFrame(int layer_tree_host_id) {
inline void CC_BASE_EXPORT
DidDropSmoothnessFrame(int layer_tree_host_id,
- base::TimeTicks dropped_frame_timestamp) {
- TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
- internal::CategoryName::kTimelineFrame, internal::kDroppedFrame,
- TRACE_EVENT_SCOPE_THREAD, dropped_frame_timestamp, internal::kLayerTreeId,
- layer_tree_host_id);
+ base::TimeTicks dropped_frame_timestamp,
+ uint64_t sequence_number) {
+ TRACE_EVENT_INSTANT(internal::CategoryName::kTimelineFrame,
+ perfetto::StaticString(internal::kDroppedFrame),
+ dropped_frame_timestamp, internal::kLayerTreeId,
+ layer_tree_host_id, internal::kFrameSequenceNumber,
+ sequence_number);
}
inline std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/chromium/cc/base/features.cc b/chromium/cc/base/features.cc
index ce01099c141..eea90717aa6 100644
--- a/chromium/cc/base/features.cc
+++ b/chromium/cc/base/features.cc
@@ -39,20 +39,6 @@ const base::Feature kSynchronizedScrolling = {
base::FEATURE_ENABLED_BY_DEFAULT};
#endif
-bool IsImplLatencyRecoveryEnabled() {
- // TODO(crbug.com/1142598): Latency recovery has been disabled by default
- // since M87. For now, only the flag is removed. If all goes well, remove the
- // code supporting latency recovery.
- return false;
-}
-
-bool IsMainLatencyRecoveryEnabled() {
- // TODO(crbug.com/1142598): Latency recovery has been disabled by default
- // since M87. For now, only the flag is removed. If all goes well, remove the
- // code supporting latency recovery.
- return false;
-}
-
const base::Feature kRemoveMobileViewportDoubleTap{
"RemoveMobileViewportDoubleTap", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -71,4 +57,8 @@ const base::Feature kHudDisplayForPerformanceMetrics{
const base::Feature kJankInjectionAblationFeature{
"JankInjectionAblation", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kPreferNewContentForCheckerboardedScrolls{
+ "PreferNewContentForCheckerboardedScrolls",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
diff --git a/chromium/cc/base/features.h b/chromium/cc/base/features.h
index d630c265dbd..652d5f88f57 100644
--- a/chromium/cc/base/features.h
+++ b/chromium/cc/base/features.h
@@ -15,9 +15,6 @@ CC_BASE_EXPORT extern const base::Feature kAnimatedImageResume;
CC_BASE_EXPORT extern const base::Feature kImpulseScrollAnimations;
CC_BASE_EXPORT extern const base::Feature kSynchronizedScrolling;
-CC_BASE_EXPORT bool IsImplLatencyRecoveryEnabled();
-CC_BASE_EXPORT bool IsMainLatencyRecoveryEnabled();
-
// When enabled, the double tap to zoom will be disabled when the viewport
// meta tag is properly set for mobile using content=width=device-width
// or content=initial-scale=1.0
@@ -50,6 +47,12 @@ CC_BASE_EXPORT extern const base::Feature kHudDisplayForPerformanceMetrics;
// When enabled, some jank is injected to the animation/scrolling pipeline.
CC_BASE_EXPORT extern const base::Feature kJankInjectionAblationFeature;
+// When enabled, scheduler tree priority will change to
+// NEW_CONTENT_TAKES_PRIORITY if during a scrollbar scroll, CC has to
+// checkerboard.
+CC_BASE_EXPORT extern const base::Feature
+ kPreferNewContentForCheckerboardedScrolls;
+
} // namespace features
#endif // CC_BASE_FEATURES_H_
diff --git a/chromium/cc/base/index_rect_unittest.cc b/chromium/cc/base/index_rect_unittest.cc
index 1580a3947e7..d66813ed902 100644
--- a/chromium/cc/base/index_rect_unittest.cc
+++ b/chromium/cc/base/index_rect_unittest.cc
@@ -3,7 +3,8 @@
// found in the LICENSE file.
#include "cc/base/index_rect.h"
-#include "base/stl_util.h"
+
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
diff --git a/chromium/cc/base/list_container_helper.cc b/chromium/cc/base/list_container_helper.cc
index 7b594b4a458..1e5a35030b3 100644
--- a/chromium/cc/base/list_container_helper.cc
+++ b/chromium/cc/base/list_container_helper.cc
@@ -8,6 +8,7 @@
#include <algorithm>
#include <cstring>
+#include <utility>
#include <vector>
#include "base/check_op.h"
@@ -30,8 +31,14 @@ class ListContainerHelper::CharAllocator {
// This class holds the raw memory chunk, as well as information about its
// size and availability.
struct InnerList {
- InnerList(const InnerList&) = delete;
- InnerList& operator=(const InnerList&) = delete;
+ InnerList(size_t capacity, size_t element_size, size_t alignment)
+ : data(static_cast<char*>(
+ base::AlignedAlloc(capacity * element_size, alignment))),
+ capacity(capacity),
+ size(0),
+ step(element_size) {}
+ InnerList(InnerList&& other) = default;
+ InnerList& operator=(InnerList&& other) = default;
std::unique_ptr<char[], base::AlignedFreeDeleter> data;
// The number of elements in total the memory can hold. The difference
@@ -44,8 +51,6 @@ class ListContainerHelper::CharAllocator {
// elements' memory locations.
size_t step;
- InnerList() : capacity(0), size(0), step(0) {}
-
void Erase(char* position) {
// Confident that destructor is called by caller of this function. Since
// CharAllocator does not handle construction after
@@ -116,7 +121,7 @@ class ListContainerHelper::CharAllocator {
DCHECK_EQ(element_size % alignment, 0u);
AllocateNewList(element_count > 0 ? element_count
: kDefaultNumElementTypesToReserve);
- last_list_ = storage_[last_list_index_].get();
+ last_list_ = &storage_[last_list_index_];
}
CharAllocator(const CharAllocator&) = delete;
@@ -132,7 +137,7 @@ class ListContainerHelper::CharAllocator {
AllocateNewList(last_list_->capacity * 2);
++last_list_index_;
- last_list_ = storage_[last_list_index_].get();
+ last_list_ = &storage_[last_list_index_];
}
++size_;
@@ -148,7 +153,7 @@ class ListContainerHelper::CharAllocator {
size_t Capacity() const {
size_t capacity_sum = 0;
for (const auto& inner_list : storage_)
- capacity_sum += inner_list->capacity;
+ capacity_sum += inner_list.capacity;
return capacity_sum;
}
@@ -157,7 +162,7 @@ class ListContainerHelper::CharAllocator {
DCHECK(!storage_.empty());
storage_.erase(storage_.begin() + 1, storage_.end());
last_list_index_ = 0;
- last_list_ = storage_[0].get();
+ last_list_ = &storage_[0];
last_list_->size = 0;
size_ = 0;
}
@@ -167,7 +172,7 @@ class ListContainerHelper::CharAllocator {
last_list_->RemoveLast();
if (last_list_->IsEmpty() && last_list_index_ > 0) {
--last_list_index_;
- last_list_ = storage_[last_list_index_].get();
+ last_list_ = &storage_[last_list_index_];
// If there are now two empty inner lists, free one of them.
if (last_list_index_ + 2 < storage_.size())
@@ -180,12 +185,12 @@ class ListContainerHelper::CharAllocator {
DCHECK_EQ(this, position->ptr_to_container);
// Update |position| to point to the element after the erased element.
- InnerList* list = storage_[position->vector_index].get();
+ InnerList& list = storage_[position->vector_index];
char* item_iterator = position->item_iterator;
- if (item_iterator == list->LastElement())
+ if (item_iterator == list.LastElement())
position->Increment();
- list->Erase(item_iterator);
+ list.Erase(item_iterator);
// TODO(weiliangc): Free the InnerList if it is empty.
--size_;
}
@@ -200,20 +205,20 @@ class ListContainerHelper::CharAllocator {
// Set |position| to be the first inserted element.
Allocate();
position->vector_index = storage_.size() - 1;
- position->item_iterator = storage_[position->vector_index]->LastElement();
+ position->item_iterator = storage_[position->vector_index].LastElement();
// Allocate the rest.
for (size_t i = 1; i < count; ++i)
Allocate();
} else {
- storage_[position->vector_index]->InsertBefore(
+ storage_[position->vector_index].InsertBefore(
alignment_, &position->item_iterator, count);
size_ += count;
}
}
- InnerList* InnerListById(size_t id) const {
+ const InnerList& InnerListById(size_t id) const {
DCHECK_LT(id, storage_.size());
- return storage_[id].get();
+ return storage_[id];
}
size_t FirstInnerListId() const {
@@ -221,7 +226,7 @@ class ListContainerHelper::CharAllocator {
// non-empty.
DCHECK_GT(size_, 0u);
size_t id = 0;
- while (storage_[id]->size == 0)
+ while (storage_[id].size == 0)
++id;
return id;
}
@@ -231,7 +236,7 @@ class ListContainerHelper::CharAllocator {
// non-empty.
DCHECK_GT(size_, 0u);
size_t id = storage_.size() - 1;
- while (storage_[id]->size == 0)
+ while (storage_[id].size == 0)
--id;
return id;
}
@@ -242,16 +247,10 @@ class ListContainerHelper::CharAllocator {
private:
void AllocateNewList(size_t list_size) {
- std::unique_ptr<InnerList> new_list(new InnerList);
- new_list->capacity = list_size;
- new_list->size = 0;
- new_list->step = element_size_;
- new_list->data.reset(static_cast<char*>(
- base::AlignedAlloc(list_size * element_size_, alignment_)));
- storage_.push_back(std::move(new_list));
+ storage_.emplace_back(list_size, element_size_, alignment_);
}
- std::vector<std::unique_ptr<InnerList>> storage_;
+ std::vector<InnerList> storage_;
const size_t alignment_;
const size_t element_size_;
@@ -271,6 +270,10 @@ class ListContainerHelper::CharAllocator {
ListContainerHelper::PositionInCharAllocator::PositionInCharAllocator(
const ListContainerHelper::PositionInCharAllocator& other) = default;
+ListContainerHelper::PositionInCharAllocator&
+ListContainerHelper::PositionInCharAllocator::operator=(
+ const ListContainerHelper::PositionInCharAllocator& other) = default;
+
ListContainerHelper::PositionInCharAllocator::PositionInCharAllocator(
ListContainerHelper::CharAllocator* container,
size_t vector_ind,
@@ -293,47 +296,45 @@ bool ListContainerHelper::PositionInCharAllocator::operator!=(
ListContainerHelper::PositionInCharAllocator
ListContainerHelper::PositionInCharAllocator::Increment() {
- CharAllocator::InnerList* list =
- ptr_to_container->InnerListById(vector_index);
- if (item_iterator == list->LastElement()) {
+ const auto& list = ptr_to_container->InnerListById(vector_index);
+ if (item_iterator == list.LastElement()) {
++vector_index;
while (vector_index < ptr_to_container->list_count()) {
- if (ptr_to_container->InnerListById(vector_index)->size != 0)
+ if (ptr_to_container->InnerListById(vector_index).size != 0)
break;
++vector_index;
}
if (vector_index < ptr_to_container->list_count())
- item_iterator = ptr_to_container->InnerListById(vector_index)->Begin();
+ item_iterator = ptr_to_container->InnerListById(vector_index).Begin();
else
item_iterator = nullptr;
} else {
- item_iterator += list->step;
+ item_iterator += list.step;
}
return *this;
}
ListContainerHelper::PositionInCharAllocator
ListContainerHelper::PositionInCharAllocator::ReverseIncrement() {
- CharAllocator::InnerList* list =
- ptr_to_container->InnerListById(vector_index);
- if (item_iterator == list->Begin()) {
+ const auto& list = ptr_to_container->InnerListById(vector_index);
+ if (item_iterator == list.Begin()) {
--vector_index;
// Since |vector_index| is unsigned, we compare < list_count() instead of
// comparing >= 0, as the variable will wrap around when it goes out of
// range (below 0).
while (vector_index < ptr_to_container->list_count()) {
- if (ptr_to_container->InnerListById(vector_index)->size != 0)
+ if (ptr_to_container->InnerListById(vector_index).size != 0)
break;
--vector_index;
}
if (vector_index < ptr_to_container->list_count()) {
item_iterator =
- ptr_to_container->InnerListById(vector_index)->LastElement();
+ ptr_to_container->InnerListById(vector_index).LastElement();
} else {
item_iterator = nullptr;
}
} else {
- item_iterator -= list->step;
+ item_iterator -= list.step;
}
return *this;
}
@@ -343,9 +344,9 @@ ListContainerHelper::PositionInCharAllocator::ReverseIncrement() {
ListContainerHelper::ListContainerHelper(size_t alignment,
size_t max_size_for_derived_class,
size_t num_of_elements_to_reserve_for)
- : data_(new CharAllocator(alignment,
- max_size_for_derived_class,
- num_of_elements_to_reserve_for)) {}
+ : data_(std::make_unique<CharAllocator>(alignment,
+ max_size_for_derived_class,
+ num_of_elements_to_reserve_for)) {}
ListContainerHelper::~ListContainerHelper() = default;
@@ -370,7 +371,7 @@ ListContainerHelper::ConstReverseIterator ListContainerHelper::crbegin() const {
size_t id = data_->LastInnerListId();
return ConstReverseIterator(data_.get(), id,
- data_->InnerListById(id)->LastElement(), 0);
+ data_->InnerListById(id).LastElement(), 0);
}
ListContainerHelper::ConstReverseIterator ListContainerHelper::crend() const {
@@ -384,7 +385,7 @@ ListContainerHelper::ReverseIterator ListContainerHelper::rbegin() {
size_t id = data_->LastInnerListId();
return ReverseIterator(data_.get(), id,
- data_->InnerListById(id)->LastElement(), 0);
+ data_->InnerListById(id).LastElement(), 0);
}
ListContainerHelper::ReverseIterator ListContainerHelper::rend() {
@@ -396,7 +397,7 @@ ListContainerHelper::ConstIterator ListContainerHelper::cbegin() const {
return cend();
size_t id = data_->FirstInnerListId();
- return ConstIterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0);
+ return ConstIterator(data_.get(), id, data_->InnerListById(id).Begin(), 0);
}
ListContainerHelper::ConstIterator ListContainerHelper::cend() const {
@@ -412,7 +413,7 @@ ListContainerHelper::Iterator ListContainerHelper::begin() {
return end();
size_t id = data_->FirstInnerListId();
- return Iterator(data_.get(), id, data_->InnerListById(id)->Begin(), 0);
+ return Iterator(data_.get(), id, data_->InnerListById(id).Begin(), 0);
}
ListContainerHelper::Iterator ListContainerHelper::end() {
@@ -429,13 +430,13 @@ ListContainerHelper::ConstIterator ListContainerHelper::IteratorAt(
size_t original_index = index;
size_t list_index;
for (list_index = 0; list_index < data_->list_count(); ++list_index) {
- size_t current_size = data_->InnerListById(list_index)->size;
+ size_t current_size = data_->InnerListById(list_index).size;
if (index < current_size)
break;
index -= current_size;
}
return ConstIterator(data_.get(), list_index,
- data_->InnerListById(list_index)->ElementAt(index),
+ data_->InnerListById(list_index).ElementAt(index),
original_index);
}
@@ -444,13 +445,13 @@ ListContainerHelper::Iterator ListContainerHelper::IteratorAt(size_t index) {
size_t original_index = index;
size_t list_index;
for (list_index = 0; list_index < data_->list_count(); ++list_index) {
- size_t current_size = data_->InnerListById(list_index)->size;
+ size_t current_size = data_->InnerListById(list_index).size;
if (index < current_size)
break;
index -= current_size;
}
return Iterator(data_.get(), list_index,
- data_->InnerListById(list_index)->ElementAt(index),
+ data_->InnerListById(list_index).ElementAt(index),
original_index);
}
diff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h
index 31658bc8486..7fc3bcebc56 100644
--- a/chromium/cc/base/list_container_helper.h
+++ b/chromium/cc/base/list_container_helper.h
@@ -41,6 +41,7 @@ class CC_BASE_EXPORT ListContainerHelper final {
char* item_iterator;
PositionInCharAllocator(const PositionInCharAllocator& other);
+ PositionInCharAllocator& operator=(const PositionInCharAllocator& other);
PositionInCharAllocator(CharAllocator* container,
size_t vector_ind,
diff --git a/chromium/cc/base/list_container_unittest.cc b/chromium/cc/base/list_container_unittest.cc
index b053305bcc7..c2975adcc49 100644
--- a/chromium/cc/base/list_container_unittest.cc
+++ b/chromium/cc/base/list_container_unittest.cc
@@ -9,7 +9,7 @@
#include <algorithm>
#include <vector>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
diff --git a/chromium/cc/base/math_util.cc b/chromium/cc/base/math_util.cc
index 26a7156d9b4..decdb8ca885 100644
--- a/chromium/cc/base/math_util.cc
+++ b/chromium/cc/base/math_util.cc
@@ -11,7 +11,7 @@
#include <xmmintrin.h>
#endif
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "base/trace_event/traced_value.h"
#include "base/values.h"
#include "ui/gfx/geometry/angle_conversions.h"
@@ -64,17 +64,21 @@ static HomogeneousCoordinate MapHomogeneousPoint(
return result;
}
-static void homogenousLimitAtZero(SkScalar a1,
- SkScalar w1,
- SkScalar a2,
- SkScalar w2,
- float t,
- float* limit) {
- // This is the tolerance for detecting an eyepoint-aligned edge.
- static const float kStationaryPointEplison = 0.00001f;
+namespace {
- if (std::abs(a1 * w2 / w1 / a2 - 1.0f) > kStationaryPointEplison) {
- // We are going to explode towards an infity, but we choose the one that
+// This is the tolerance for detecting an eyepoint-aligned edge.
+const float kStationaryPointEpsilon = 0.00001f;
+
+} // namespace
+
+static void homogeneousLimitAtZero(SkScalar a1,
+ SkScalar w1,
+ SkScalar a2,
+ SkScalar w2,
+ float t,
+ float* limit) {
+ if (std::abs(a1 * w2 / w1 / a2 - 1.0f) > kStationaryPointEpsilon) {
+ // We are going to explode towards an infinity, but we choose the one that
// corresponds to the one on the positive side of w.
if (((1.0f - t) * a1 + t * a2) > 0) {
*limit = HomogeneousCoordinate::kInfiniteCoordinate;
@@ -102,16 +106,43 @@ static gfx::PointF ComputeClippedCartesianPoint2dForEdge(
// i.e., either the coordinate is not moving, or is trending to one
// infinity or the other.
+ // This assertion isn't really as strong as it looks because
+ // std::isfinite(h1.w()) or std::isfinite(h2.w()) might not be true
+ // (and they could be NaN).
+ // TODO(crbug.com/1219622): We should be able to assert something
+ // stronger here, and avoid dependencies on undefined floating point
+ // behavior.
+ DCHECK_NE(h1.w() <= 0, h2.w() <= 0);
+
float t = h1.w() / (h1.w() - h2.w());
float x;
float y;
- homogenousLimitAtZero(h1.x(), h1.w(), h2.x(), h2.w(), t, &x);
- homogenousLimitAtZero(h1.y(), h1.w(), h2.y(), h2.w(), t, &y);
+ homogeneousLimitAtZero(h1.x(), h1.w(), h2.x(), h2.w(), t, &x);
+ homogeneousLimitAtZero(h1.y(), h1.w(), h2.y(), h2.w(), t, &y);
return gfx::PointF(x, y);
}
+static void homogeneousLimitNearZero(SkScalar a1,
+ SkScalar w1,
+ SkScalar a2,
+ SkScalar w2,
+ float t,
+ float* limit) {
+ if (std::abs(a1 * w2 / w1 / a2 - 1.0f) > kStationaryPointEpsilon) {
+ // t has been computed so that w is near but not at zero.
+ *limit = ((1.0f - t) * a1 + t * a2) / ((1.0f - t) * w1 + t * w2);
+ // std::abs(*limit) should now be somewhere near
+ // HomogeneousCoordinate::kInfiniteCoordinate, preferably smaller than it,
+ // but there are edge cases where it will be larger (for example, if the
+ // point where a crosses 0 is very close to the point where w crosses 0),
+ // so it's hard to DCHECK() that this is the case.
+ } else {
+ *limit = a1 / w1; // (== a2 / w2) && == (1.0f - t) * a1 / w1 + t * a2 / w2
+ }
+}
+
static gfx::Point3F ComputeClippedCartesianPoint3dForEdge(
const HomogeneousCoordinate& h1,
const HomogeneousCoordinate& h2) {
@@ -129,14 +160,47 @@ static gfx::Point3F ComputeClippedCartesianPoint3dForEdge(
// i.e., either the coordinate is not moving, or is trending to one
// infinity or the other.
- float t = h1.w() / (h1.w() - h2.w());
+ // When we clamp to HomogeneousCoordinate::kInfiniteCoordinate we want
+ // to keep the result in the correct plane, which we do by computing
+ // a t that will result in the largest (in absolute value) of x, y, or
+ // z being HomogeneousCoordinate::kInfiniteCoordinate
+
+ // This assertion isn't really as strong as it looks because
+ // std::isfinite(h1.w()) or std::isfinite(h2.w()) might not be true
+ // (and they could be NaN).
+ // TODO(crbug.com/1219622): We should be able to assert something
+ // stronger here, and avoid dependencies on undefined floating point
+ // behavior.
+ DCHECK_NE(h1.w() <= 0, h2.w() <= 0);
+
+ float w_diff = h1.w() - h2.w();
+ float t = h1.w() / w_diff;
+ float max_numerator = std::max({std::abs((1.0f - t) * h1.x() + t * h2.x()),
+ std::abs((1.0f - t) * h1.y() + t * h2.y()),
+ std::abs((1.0f - t) * h1.z() + t * h2.z())});
+
+ // Shift t away from the point where w is zero, far enough so that the
+ // largest of the resulting x, y, and z will be about
+ // kInfiniteCoordinate. Add an extra epsilon() / 2.0 so that there's
+ // always enough movement (in case t_shift is very small, which it
+ // often is).
+ const float t_shift =
+ max_numerator / w_diff / HomogeneousCoordinate::kInfiniteCoordinate;
+ constexpr float half_epsilon = std::numeric_limits<float>::epsilon() / 2.0f;
+ DCHECK_EQ(w_diff > 0, t_shift > 0);
+ if (w_diff > 0) {
+ t = std::max(0.0f, t - (t_shift + half_epsilon));
+ } else {
+ t = std::min(1.0f, t - (t_shift - half_epsilon));
+ }
+
float x;
float y;
float z;
- homogenousLimitAtZero(h1.x(), h1.w(), h2.x(), h2.w(), t, &x);
- homogenousLimitAtZero(h1.y(), h1.w(), h2.y(), h2.w(), t, &y);
- homogenousLimitAtZero(h1.z(), h1.w(), h2.z(), h2.w(), t, &z);
+ homogeneousLimitNearZero(h1.x(), h1.w(), h2.x(), h2.w(), t, &x);
+ homogeneousLimitNearZero(h1.y(), h1.w(), h2.y(), h2.w(), t, &y);
+ homogeneousLimitNearZero(h1.z(), h1.w(), h2.z(), h2.w(), t, &z);
return gfx::Point3F(x, y, z);
}
@@ -175,14 +239,24 @@ static inline bool IsNearlyTheSame(const gfx::Point3F& lhs,
static inline void AddVertexToClippedQuad3d(const gfx::Point3F& new_vertex,
gfx::Point3F clipped_quad[6],
- int* num_vertices_in_clipped_quad) {
+ int* num_vertices_in_clipped_quad,
+ bool* need_to_clamp) {
if (*num_vertices_in_clipped_quad > 0 &&
IsNearlyTheSame(clipped_quad[*num_vertices_in_clipped_quad - 1],
new_vertex))
return;
+ DCHECK_LT(*num_vertices_in_clipped_quad, 6);
clipped_quad[*num_vertices_in_clipped_quad] = new_vertex;
(*num_vertices_in_clipped_quad)++;
+ if (new_vertex.x() < -HomogeneousCoordinate::kInfiniteCoordinate ||
+ new_vertex.x() > HomogeneousCoordinate::kInfiniteCoordinate ||
+ new_vertex.y() < -HomogeneousCoordinate::kInfiniteCoordinate ||
+ new_vertex.y() > HomogeneousCoordinate::kInfiniteCoordinate ||
+ new_vertex.z() < -HomogeneousCoordinate::kInfiniteCoordinate ||
+ new_vertex.z() > HomogeneousCoordinate::kInfiniteCoordinate) {
+ *need_to_clamp = true;
+ }
}
gfx::Rect MathUtil::MapEnclosingClippedRect(const gfx::Transform& transform,
@@ -296,6 +370,8 @@ gfx::Rect MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
const gfx::Transform& transform,
const gfx::Rect& rect) {
DCHECK(transform.Preserves2dAxisAlignment());
+ DCHECK_GT(transform.matrix().get(3, 3), 0);
+ DCHECK(std::isnormal(transform.matrix().get(3, 3)));
if (transform.IsIdentityOrIntegerTranslation()) {
gfx::Vector2d offset(static_cast<int>(transform.matrix().getFloat(0, 3)),
@@ -331,6 +407,11 @@ bool MathUtil::MapClippedQuad3d(const gfx::Transform& transform,
const gfx::QuadF& src_quad,
gfx::Point3F clipped_quad[6],
int* num_vertices_in_clipped_quad) {
+ // This is different from the 2D version because, when we clamp
+ // coordinates to [-HomogeneousCoordinate::kInfiniteCoordinate,
+ // HomogeneousCoordinate::kInfiniteCoordinate], we need to do the
+ // clamping while keeping the points coplanar.
+
HomogeneousCoordinate h1 =
MapHomogeneousPoint(transform, gfx::Point3F(src_quad.p1()));
HomogeneousCoordinate h2 =
@@ -344,45 +425,50 @@ bool MathUtil::MapClippedQuad3d(const gfx::Transform& transform,
// clockwise / counter-clockwise orientation is retained.
*num_vertices_in_clipped_quad = 0;
+ bool need_to_clamp = false;
if (!h1.ShouldBeClipped()) {
- AddVertexToClippedQuad3d(
- h1.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad);
+ AddVertexToClippedQuad3d(h1.CartesianPoint3dUnclamped(), clipped_quad,
+ num_vertices_in_clipped_quad, &need_to_clamp);
}
if (h1.ShouldBeClipped() ^ h2.ShouldBeClipped()) {
AddVertexToClippedQuad3d(ComputeClippedCartesianPoint3dForEdge(h1, h2),
- clipped_quad, num_vertices_in_clipped_quad);
+ clipped_quad, num_vertices_in_clipped_quad,
+ &need_to_clamp);
}
if (!h2.ShouldBeClipped()) {
- AddVertexToClippedQuad3d(
- h2.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad);
+ AddVertexToClippedQuad3d(h2.CartesianPoint3dUnclamped(), clipped_quad,
+ num_vertices_in_clipped_quad, &need_to_clamp);
}
if (h2.ShouldBeClipped() ^ h3.ShouldBeClipped()) {
AddVertexToClippedQuad3d(ComputeClippedCartesianPoint3dForEdge(h2, h3),
- clipped_quad, num_vertices_in_clipped_quad);
+ clipped_quad, num_vertices_in_clipped_quad,
+ &need_to_clamp);
}
if (!h3.ShouldBeClipped()) {
- AddVertexToClippedQuad3d(
- h3.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad);
+ AddVertexToClippedQuad3d(h3.CartesianPoint3dUnclamped(), clipped_quad,
+ num_vertices_in_clipped_quad, &need_to_clamp);
}
if (h3.ShouldBeClipped() ^ h4.ShouldBeClipped()) {
AddVertexToClippedQuad3d(ComputeClippedCartesianPoint3dForEdge(h3, h4),
- clipped_quad, num_vertices_in_clipped_quad);
+ clipped_quad, num_vertices_in_clipped_quad,
+ &need_to_clamp);
}
if (!h4.ShouldBeClipped()) {
- AddVertexToClippedQuad3d(
- h4.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad);
+ AddVertexToClippedQuad3d(h4.CartesianPoint3dUnclamped(), clipped_quad,
+ num_vertices_in_clipped_quad, &need_to_clamp);
}
if (h4.ShouldBeClipped() ^ h1.ShouldBeClipped()) {
AddVertexToClippedQuad3d(ComputeClippedCartesianPoint3dForEdge(h4, h1),
- clipped_quad, num_vertices_in_clipped_quad);
+ clipped_quad, num_vertices_in_clipped_quad,
+ &need_to_clamp);
}
if (*num_vertices_in_clipped_quad > 2 &&
@@ -390,6 +476,147 @@ bool MathUtil::MapClippedQuad3d(const gfx::Transform& transform,
clipped_quad[*num_vertices_in_clipped_quad - 1]))
*num_vertices_in_clipped_quad -= 1;
+ if (need_to_clamp) {
+ // Some of the values need to be clamped, but we need to keep them
+ // coplanar while doing so.
+
+ // First, build a normal vector to the plane by averaging the
+ // cross products of adjacent edges.
+ gfx::Vector3dF normal(0.0f, 0.0f, 0.0f);
+ if (*num_vertices_in_clipped_quad > 2) {
+ gfx::Vector3dF loop_vector =
+ clipped_quad[0] - clipped_quad[*num_vertices_in_clipped_quad - 1];
+ gfx::Vector3dF prev_vector(loop_vector);
+ for (int i = 1; i < *num_vertices_in_clipped_quad; ++i) {
+ gfx::Vector3dF cur_vector = clipped_quad[i] - clipped_quad[i - 1];
+ normal += CrossProduct(prev_vector, cur_vector);
+ prev_vector = cur_vector;
+ }
+ normal += CrossProduct(prev_vector, loop_vector);
+ }
+
+ bool clamp_by_points = false;
+ float length = normal.Length();
+ if (std::isnormal(length)) { // exclude 0, denormals, +/- inf, NaN
+ normal.Scale(1.0f / length);
+
+ // Find the vector to the point in the plane closest to (0,0,0).
+ gfx::Vector3dF shortest_from_zero(normal);
+ shortest_from_zero.Scale(
+ DotProduct(normal, clipped_quad[0] - gfx::Point3F(0.0f, 0.0f, 0.0f)));
+
+ // Find the the point in the plane that is at x=0 and y=0
+ float z_at_xy_zero = 0.0f;
+ if (shortest_from_zero.x() == 0.0f && shortest_from_zero.y() == 0.0f) {
+ z_at_xy_zero = shortest_from_zero.z();
+ } else if (shortest_from_zero.z() != 0) {
+ // Compute the vector v pointing from the shortest_from_zero
+ // point to the point with x=0 and y=0. If both v and normal
+ // are projected into the x/y plane, they should point in
+ // opposite directions.
+ gfx::Vector3dF v = CrossProduct(
+ normal, CrossProduct(gfx::Vector3dF(0.0f, 0.0f, 1.0f), normal));
+ DCHECK(std::abs(normal.x() * v.y() - normal.y() * v.x()) < 0.00001f);
+ // It doesn't matter whether we use x or y, unless one of them
+ // is zero or very close to it.
+ float r = std::abs(v.x()) > std::abs(v.y())
+ ? shortest_from_zero.x() / v.x()
+ : shortest_from_zero.y() / v.y();
+ z_at_xy_zero = shortest_from_zero.z() - v.z() * r;
+ } else {
+ // Plane is parallel to the z axis. This means it's not
+ // visible, so just fall back to clamping by points.
+ clamp_by_points = true;
+ }
+
+ if (!clamp_by_points) {
+ // If z_at_xy_zero is more than 3/4 of kInfiniteCoordinate
+ // distance from zero, move everything in the z axis so
+ // z_at_xy_zero is that distance from zero, so that we don't end
+ // up clamping away the parts that fit within what's likely to
+ // be the visible area.
+ constexpr float max_distance =
+ 0.75 * HomogeneousCoordinate::kInfiniteCoordinate;
+ if (std::abs(z_at_xy_zero) > max_distance) {
+ float z_delta;
+ if (z_at_xy_zero > 0) {
+ z_delta = max_distance - z_at_xy_zero;
+ } else {
+ z_delta = -max_distance - z_at_xy_zero;
+ }
+ for (int i = 0; i < *num_vertices_in_clipped_quad; ++i) {
+ clipped_quad[i].set_z(clipped_quad[i].z() + z_delta);
+ }
+ z_at_xy_zero += z_delta;
+ }
+
+ // Move all the points towards (0, 0, z_at_xy_zero) until all
+ // their coordinates are less than kInfiniteCoordinate.
+ for (int i = 0; i < *num_vertices_in_clipped_quad; ++i) {
+ gfx::Point3F& point = clipped_quad[i];
+ float t = 1.0f;
+
+ float x_abs = std::abs(point.x());
+ if (x_abs > HomogeneousCoordinate::kInfiniteCoordinate) {
+ t = std::min(t, HomogeneousCoordinate::kInfiniteCoordinate / x_abs);
+ }
+
+ float y_abs = std::abs(point.y());
+ if (y_abs > HomogeneousCoordinate::kInfiniteCoordinate) {
+ t = std::min(t, HomogeneousCoordinate::kInfiniteCoordinate / y_abs);
+ }
+
+ float z = point.z();
+ if (std::abs(z) > HomogeneousCoordinate::kInfiniteCoordinate) {
+ // From the clamping to max_distance above, we should have
+ // made std::abs(z_at_xy_zero) < kInfiniteCoordinate.
+ // However, if it started off very large we might not have.
+ float z_at_xy_zero_clamped =
+ std::min(float{HomogeneousCoordinate::kInfiniteCoordinate},
+ std::max(-HomogeneousCoordinate::kInfiniteCoordinate,
+ z_at_xy_zero));
+ float z_offset = z - z_at_xy_zero_clamped;
+ float z_space =
+ (z > 0 ? HomogeneousCoordinate::kInfiniteCoordinate
+ : -HomogeneousCoordinate::kInfiniteCoordinate) -
+ z_at_xy_zero_clamped;
+ DCHECK_NE(z_offset, 0.0f);
+ DCHECK_NE(z_space, 0.0f);
+ DCHECK_EQ(z_offset > 0, z_space > 0);
+ t = std::min(t, z_space / z_offset);
+ }
+
+ if (t != 1.0f) {
+ DCHECK(0.0f <= t && t < 1.0f);
+ point.set_x(t * point.x());
+ point.set_y(t * point.y());
+ point.set_z((1.0f - t) * z_at_xy_zero + t * point.z());
+ }
+ }
+ }
+ } else {
+ // Our points were colinear, so there's no plane to maintain.
+ clamp_by_points = true;
+ }
+
+ if (clamp_by_points) {
+ // Just clamp each point separately in each axis, just like we do
+ // for 2D.
+ for (int i = 0; i < *num_vertices_in_clipped_quad; ++i) {
+ gfx::Point3F& point = clipped_quad[i];
+ point.set_x(
+ base::clamp(point.x(), -HomogeneousCoordinate::kInfiniteCoordinate,
+ float{HomogeneousCoordinate::kInfiniteCoordinate}));
+ point.set_y(
+ base::clamp(point.y(), -HomogeneousCoordinate::kInfiniteCoordinate,
+ float{HomogeneousCoordinate::kInfiniteCoordinate}));
+ point.set_z(
+ base::clamp(point.z(), -HomogeneousCoordinate::kInfiniteCoordinate,
+ float{HomogeneousCoordinate::kInfiniteCoordinate}));
+ }
+ }
+ }
+
DCHECK_LE(*num_vertices_in_clipped_quad, 6);
return (*num_vertices_in_clipped_quad >= 4);
}
@@ -582,7 +809,7 @@ float MathUtil::SmallestAngleBetweenVectors(const gfx::Vector2dF& v1,
const gfx::Vector2dF& v2) {
double dot_product = gfx::DotProduct(v1, v2) / v1.Length() / v2.Length();
// Clamp to compensate for rounding errors.
- dot_product = base::ClampToRange(dot_product, -1.0, 1.0);
+ dot_product = base::clamp(dot_product, -1.0, 1.0);
return static_cast<float>(gfx::RadToDeg(std::acos(dot_product)));
}
@@ -595,22 +822,25 @@ gfx::Vector2dF MathUtil::ProjectVector(const gfx::Vector2dF& source,
}
bool MathUtil::FromValue(const base::Value* raw_value, gfx::Rect* out_rect) {
- const base::ListValue* value = nullptr;
- if (!raw_value->GetAsList(&value))
+ if (!raw_value->is_list())
return false;
- if (value->GetSize() != 4)
- return false;
+ base::Value::ConstListView list_view = raw_value->GetList();
- int x, y, w, h;
- bool ok = true;
- ok &= value->GetInteger(0, &x);
- ok &= value->GetInteger(1, &y);
- ok &= value->GetInteger(2, &w);
- ok &= value->GetInteger(3, &h);
- if (!ok)
+ if (list_view.size() != 4)
return false;
+ for (const auto& val : list_view) {
+ if (!val.is_int()) {
+ return false;
+ }
+ }
+
+ int x = list_view[0].GetInt();
+ int y = list_view[1].GetInt();
+ int w = list_view[2].GetInt();
+ int h = list_view[3].GetInt();
+
*out_rect = gfx::Rect(x, y, w, h);
return true;
}
@@ -729,7 +959,7 @@ void MathUtil::AddToTracedValue(const char* name,
const gfx::Transform& transform,
base::trace_event::TracedValue* res) {
res->BeginArray(name);
- const SkMatrix44& m = transform.matrix();
+ const skia::Matrix44& m = transform.matrix();
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 4; ++col)
res->AppendDouble(m.getDouble(row, col));
diff --git a/chromium/cc/base/math_util.h b/chromium/cc/base/math_util.h
index e6940430086..b7c762b258f 100644
--- a/chromium/cc/base/math_util.h
+++ b/chromium/cc/base/math_util.h
@@ -10,7 +10,7 @@
#include <vector>
#include "base/check.h"
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/base/base_export.h"
#include "third_party/skia/include/core/SkM44.h"
@@ -71,10 +71,10 @@ struct HomogeneousCoordinate {
SkScalar inv_w = SK_Scalar1 / w();
// However, w may be close to 0 and we lose precision on our geometry
// calculations if we allow scaling to extremely large values.
- return gfx::PointF(base::ClampToRange(x() * inv_w, -kInfiniteCoordinate,
- float{kInfiniteCoordinate}),
- base::ClampToRange(y() * inv_w, -kInfiniteCoordinate,
- float{kInfiniteCoordinate}));
+ return gfx::PointF(base::clamp(x() * inv_w, -kInfiniteCoordinate,
+ float{kInfiniteCoordinate}),
+ base::clamp(y() * inv_w, -kInfiniteCoordinate,
+ float{kInfiniteCoordinate}));
}
gfx::Point3F CartesianPoint3d() const {
@@ -87,12 +87,25 @@ struct HomogeneousCoordinate {
SkScalar inv_w = SK_Scalar1 / w();
// However, w may be close to 0 and we lose precision on our geometry
// calculations if we allow scaling to extremely large values.
- return gfx::Point3F(base::ClampToRange(x() * inv_w, -kInfiniteCoordinate,
- float{kInfiniteCoordinate}),
- base::ClampToRange(y() * inv_w, -kInfiniteCoordinate,
- float{kInfiniteCoordinate}),
- base::ClampToRange(z() * inv_w, -kInfiniteCoordinate,
- float{kInfiniteCoordinate}));
+ return gfx::Point3F(base::clamp(x() * inv_w, -kInfiniteCoordinate,
+ float{kInfiniteCoordinate}),
+ base::clamp(y() * inv_w, -kInfiniteCoordinate,
+ float{kInfiniteCoordinate}),
+ base::clamp(z() * inv_w, -kInfiniteCoordinate,
+ float{kInfiniteCoordinate}));
+ }
+
+ gfx::Point3F CartesianPoint3dUnclamped() const {
+ if (w() == SK_Scalar1)
+ return gfx::Point3F(x(), y(), z());
+
+ // For now, because this code is used privately only by MathUtil, it should
+ // never be called when w == 0, and we do not yet need to handle that case.
+ DCHECK(w());
+ SkScalar inv_w = SK_Scalar1 / w();
+ // However, w may be close to 0 and we lose precision on our geometry
+ // calculations if we allow scaling to extremely large values.
+ return gfx::Point3F(x() * inv_w, y() * inv_w, z() * inv_w);
}
SkScalar x() const { return vec[0]; }
diff --git a/chromium/cc/base/math_util_unittest.cc b/chromium/cc/base/math_util_unittest.cc
index 789145584b6..6931856891c 100644
--- a/chromium/cc/base/math_util_unittest.cc
+++ b/chromium/cc/base/math_util_unittest.cc
@@ -619,16 +619,16 @@ TEST(MathUtilTest, ApproximatePoint3F) {
}
// This takes a quad for which two points, (at x = -99) are behind and below
-// the eyepoint and checks to make sure we build a triangle. We used to build
-// a degenerate quad.
+// the eyepoint and checks to make sure we build a quad that doesn't include
+// anything from w<0 space. We used to build a degenerate quad.
TEST(MathUtilTest, MapClippedQuadDuplicateTriangle) {
gfx::Transform transform;
transform.MakeIdentity();
transform.ApplyPerspectiveDepth(50.0);
transform.RotateAboutYAxis(89.0);
- // We are amost looking along the X-Y plane from (-50, almost 0)
+ // We are almost looking along the X-Y plane from (-50, almost 0)
- gfx::QuadF src_quad(gfx::PointF(0.0f, 100.0f), gfx::PointF(0.0f, -100.0f),
+ gfx::QuadF src_quad(gfx::PointF(0.0f, -50.0f), gfx::PointF(0.0f, -100.0f),
gfx::PointF(-99.0f, -300.0f),
gfx::PointF(-99.0f, -100.0f));
@@ -638,21 +638,44 @@ TEST(MathUtilTest, MapClippedQuadDuplicateTriangle) {
MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
&num_vertices_in_clipped_quad);
+ // If we include anything from w<0 space, it will produce positive y
+ // coordinates rather than negative ones.
+ for (int i = 0; i < num_vertices_in_clipped_quad; ++i) {
+ EXPECT_LE(clipped_quad[i].y(), 0);
+ }
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+}
+
+// This takes a quad for which two points are identical and checks to make
+// sure we build a triangle.
+TEST(MathUtilTest, MapClippedQuadDuplicatePoints) {
+ gfx::Transform transform;
+ transform.MakeIdentity();
+ transform.RotateAboutYAxis(45.0);
+
+ gfx::QuadF src_quad(gfx::PointF(-99.0f, -50.0f), gfx::PointF(-99.0f, -50.0f),
+ gfx::PointF(0.0f, 100.0f), gfx::PointF(0.0f, -100.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
EXPECT_EQ(num_vertices_in_clipped_quad, 3);
}
-// This takes a quad for which two points, (at x = -99) are behind and below
-// the eyepoint and checks to make sure we build a triangle. We used to build
-// a degenerate quad. The quirk here is that the two shared points are first
-// and last, not sequential.
-TEST(MathUtilTest, MapClippedQuadDuplicateTriangleWrapped) {
+// This takes a quad for which two points are identical and checks to make
+// sure we build a triangle. The quirk here is that the two shared points are
+// first and last, not sequential.
+TEST(MathUtilTest, MapClippedQuadDuplicatePointsWrapped) {
gfx::Transform transform;
transform.MakeIdentity();
- transform.ApplyPerspectiveDepth(50.0);
- transform.RotateAboutYAxis(89.0);
+ transform.RotateAboutYAxis(45.0);
- gfx::QuadF src_quad(gfx::PointF(-99.0f, -100.0f), gfx::PointF(0.0f, 100.0f),
- gfx::PointF(0.0f, -100.0f), gfx::PointF(-99.0f, -300.0f));
+ gfx::QuadF src_quad(gfx::PointF(-99.0f, -50.0f), gfx::PointF(0.0f, 100.0f),
+ gfx::PointF(0.0f, -100.0f), gfx::PointF(-99.0f, -50.0f));
gfx::Point3F clipped_quad[8];
int num_vertices_in_clipped_quad;
@@ -672,7 +695,7 @@ TEST(MathUtilTest, MapClippedQuadDuplicateQuad) {
transform.ApplyPerspectiveDepth(50.0);
transform.RotateAboutYAxis(89.0);
- gfx::QuadF src_quad(gfx::PointF(0.0f, 100.0f), gfx::PointF(400.0f, 0.0f),
+ gfx::QuadF src_quad(gfx::PointF(0.0f, -50.0f), gfx::PointF(400.0f, -50.0f),
gfx::PointF(0.0f, -100.0f), gfx::PointF(-99.0f, -300.0f));
gfx::Point3F clipped_quad[8];
@@ -681,7 +704,306 @@ TEST(MathUtilTest, MapClippedQuadDuplicateQuad) {
MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
&num_vertices_in_clipped_quad);
+ // If we include anything from w<0 space, it will produce positive y
+ // coordinates rather than negative ones.
+ for (int i = 0; i < num_vertices_in_clipped_quad; ++i) {
+ EXPECT_LE(clipped_quad[i].y(), 0);
+ }
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 5);
+}
+
+#define EXPECT_LT_LT(a, b, c) \
+ do { \
+ auto b_evaluated = b; \
+ EXPECT_LT(a, b_evaluated); \
+ EXPECT_LT(b_evaluated, c); \
+ } while (0)
+
+#define EXPECT_LE_LT(a, b, c) \
+ do { \
+ auto b_evaluated = b; \
+ EXPECT_LE(a, b_evaluated); \
+ EXPECT_LT(b_evaluated, c); \
+ } while (0)
+
+#define EXPECT_LT_LE(a, b, c) \
+ do { \
+ auto b_evaluated = b; \
+ EXPECT_LT(a, b_evaluated); \
+ EXPECT_LE(b_evaluated, c); \
+ } while (0)
+
+#define EXPECT_LE_LE(a, b, c) \
+ do { \
+ auto b_evaluated = b; \
+ EXPECT_LE(a, b_evaluated); \
+ EXPECT_LE(b_evaluated, c); \
+ } while (0)
+
+// Here we map and clip a quad with a point that disappears to infinity behind
+// us while staying finite in one dimension (i.e., x goes to 0 as w goes to 0,
+// and x' is constant along the edge).
+TEST(MathUtilTest, MapClippedQuadInfiniteInSomeDimensions) {
+ gfx::Transform transform;
+ transform.MakeIdentity();
+ transform.ApplyPerspectiveDepth(50.0);
+ transform.RotateAboutXAxis(89.0);
+
+ gfx::QuadF src_quad(gfx::PointF(0.0f, 0.0f), gfx::PointF(0.0f, 100.0f),
+ gfx::PointF(100.0f, 100.0f), gfx::PointF(100.0f, 0.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].z(), 0.0f);
+
+ EXPECT_EQ(clipped_quad[1].x(), 0.0f);
+ EXPECT_LT_LT(17000.0f, clipped_quad[1].y(), 18000.0f);
+ EXPECT_LT_LE(998000.0f, clipped_quad[1].z(), 1000000.0f);
+
+ EXPECT_LT_LE(998000.0f, clipped_quad[2].x(), 1000000.0f);
+ EXPECT_LT_LT(8500.0f, clipped_quad[2].y(), 9000.0f);
+ EXPECT_LT_LE(499000.0f, clipped_quad[2].z(), 500000.0f);
+
+ EXPECT_EQ(clipped_quad[3].x(), 100.0f);
+ EXPECT_EQ(clipped_quad[3].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[3].z(), 0.0f);
+}
+
+// Here we map and clip a quad with a point that disappears to infinity behind
+// us while staying finite in one dimension (i.e., x goes to 0 as w goes to 0,
+// and x' is constant along the edge). This differs from the previous test
+// in that the edge with constant x' is at 100 rather than 0.
+TEST(MathUtilTest, MapClippedQuadInfiniteInSomeDimensionsNonZero) {
+ gfx::Transform transform;
+ transform.MakeIdentity();
+ transform.Translate(100.0, 0.0);
+ transform.ApplyPerspectiveDepth(50.0);
+ transform.RotateAboutXAxis(89.0);
+ transform.Translate(-100.0, 0.0);
+
+ gfx::QuadF src_quad(gfx::PointF(0.0f, 0.0f), gfx::PointF(0.0f, 100.0f),
+ gfx::PointF(100.0f, 100.0f), gfx::PointF(100.0f, 0.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].z(), 0.0f);
+
+ EXPECT_LE_LT(-1000000.0f, clipped_quad[1].x(), -998000.0f);
+ EXPECT_LT_LT(8500.0f, clipped_quad[1].y(), 9000.0f);
+ EXPECT_LT_LE(499000.0f, clipped_quad[1].z(), 500000.0f);
+
+ EXPECT_EQ(clipped_quad[2].x(), 100.0f);
+ EXPECT_LT_LT(17000.0f, clipped_quad[2].y(), 18000.0f);
+ EXPECT_LT_LE(996000.0f, clipped_quad[2].z(), 1000000.0f);
+
+ EXPECT_EQ(clipped_quad[3].x(), 100.0f);
+ EXPECT_EQ(clipped_quad[3].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[3].z(), 0.0f);
+}
+
+// Test that planes that are parallel to the z axis (other than those going
+// through the origin!) just fall through to clipping by points.
+TEST(MathUtilTest, MapClippedQuadClampInvisiblePlane) {
+ gfx::Transform transform;
+
+ gfx::QuadF src_quad(gfx::PointF(0.0f, 0.0f), gfx::PointF(0.0f, 1000.0f),
+ gfx::PointF(1000.0f, 1000.0f),
+ gfx::PointF(1000.0f, 0.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ transform.MakeIdentity();
+ transform.Translate(100.0, 0.0);
+ transform.RotateAboutYAxis(90.0);
+ transform.Scale(10000.0f, 10000.0);
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 100.0f);
+ EXPECT_EQ(clipped_quad[0].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].z(), 0.0f);
+
+ EXPECT_EQ(clipped_quad[1].x(), 100.0f);
+ EXPECT_EQ(clipped_quad[1].y(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[1].z(), 0.0f);
+
+ EXPECT_EQ(clipped_quad[2].x(), 100.0f);
+ EXPECT_EQ(clipped_quad[2].y(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[2].z(), -1000000.0f);
+
+ EXPECT_EQ(clipped_quad[3].x(), 100.0f);
+ EXPECT_EQ(clipped_quad[3].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[3].z(), -1000000.0f);
+
+ transform.MakeIdentity();
+ transform.Translate(0.0, -50.0);
+ transform.RotateAboutXAxis(-90.0);
+ transform.Scale(10000.0f, 10000.0);
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].y(), -50.0f);
+ EXPECT_EQ(clipped_quad[0].z(), 0.0f);
+
+ EXPECT_EQ(clipped_quad[1].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[1].y(), -50.0f);
+ EXPECT_EQ(clipped_quad[1].z(), -1000000.0f);
+
+ EXPECT_EQ(clipped_quad[2].x(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[2].y(), -50.0f);
+ EXPECT_EQ(clipped_quad[2].z(), -1000000.0f);
+
+ EXPECT_EQ(clipped_quad[3].x(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[3].y(), -50.0f);
+ EXPECT_EQ(clipped_quad[3].z(), 0.0f);
+
+ transform.MakeIdentity();
+ transform.Translate(10.0, 10.0);
+ transform.Rotate(30.0);
+ transform.RotateAboutXAxis(90.0);
+ transform.Scale(10000.0, 10000.0);
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 10.0f);
+ EXPECT_EQ(clipped_quad[0].y(), 10.0f);
+ EXPECT_EQ(clipped_quad[0].z(), 0.0f);
+
+ EXPECT_EQ(clipped_quad[1].x(), 10.0f);
+ EXPECT_EQ(clipped_quad[1].y(), 10.0f);
+ EXPECT_EQ(clipped_quad[1].z(), 1000000.0f);
+
+ EXPECT_EQ(clipped_quad[2].x(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[2].y(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[2].z(), 1000000.0f);
+
+ EXPECT_EQ(clipped_quad[3].x(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[3].y(), 1000000.0f);
+ EXPECT_EQ(clipped_quad[3].z(), 0.0f);
+}
+
+// Test that when the plane passes too far from the origin, we bring it closer
+// before clamping coordinates.
+TEST(MathUtilTest, MapClippedQuadClampWholePlane) {
+ gfx::Transform transform;
+ transform.MakeIdentity();
+ transform.Scale3d(1000.0, 1000.0, 1000.0);
+ transform.Translate3d(0.0, 0.0, 10000.0);
+ transform.RotateAboutXAxis(-45.0);
+
+ gfx::QuadF src_quad(gfx::PointF(0.0f, 0.0f), gfx::PointF(0.0f, 10000.0f),
+ gfx::PointF(100.0f, 10000.0f),
+ gfx::PointF(100.0f, -10000.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].z(), 750000.0f);
+
+ EXPECT_EQ(clipped_quad[1].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[1].y(), 1000000.0f);
+ EXPECT_LE_LE(-250001.0f, clipped_quad[1].z(), -249999.0f);
+
+ EXPECT_LE_LE(14100.0f, clipped_quad[2].x(), 14200.0f);
+ EXPECT_EQ(clipped_quad[2].y(), 1000000.0f);
+ EXPECT_LE_LE(-250001.0f, clipped_quad[2].z(), -249999.0f);
+
+ EXPECT_LE_LE(3500.0f, clipped_quad[3].x(), 3600.0f);
+ EXPECT_LE_LE(-250001.0f, clipped_quad[3].y(), -249999.0f);
+ EXPECT_EQ(clipped_quad[3].z(), 1000000.0f);
+}
+
+// Like the previous test, but with a plane with large negative z.
+TEST(MathUtilTest, MapClippedQuadClampWholePlaneBelow) {
+ gfx::Transform transform;
+ transform.MakeIdentity();
+ transform.Scale3d(1000.0, 1000.0, 1000.0);
+ transform.Translate3d(0.0, 0.0, -5000.0);
+ transform.RotateAboutYAxis(30.0);
+
+ gfx::QuadF src_quad(gfx::PointF(0.0f, 0.0f), gfx::PointF(-10000.0f, 100.0f),
+ gfx::PointF(10000.0f, 100.0f),
+ gfx::PointF(10000.0f, 0.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ EXPECT_EQ(num_vertices_in_clipped_quad, 4);
+
+ EXPECT_EQ(clipped_quad[0].x(), 0.0f);
+ EXPECT_EQ(clipped_quad[0].y(), 0.0f);
+ EXPECT_LE_LE(-750001.0f, clipped_quad[0].z(), -750000.0f);
+
+ EXPECT_EQ(clipped_quad[1].x(), -1000000.0f);
+ EXPECT_LE_LE(11540.0f, clipped_quad[1].y(), 11550.0f);
+ EXPECT_LE_LE(-172660.0f, clipped_quad[1].z(), -172640.0f);
+
+ EXPECT_LE_LE(433000.0f, clipped_quad[2].x(), 433025.0f);
+ EXPECT_LT_LT(4999.9f, clipped_quad[2].y(), 5000.1f);
+ EXPECT_EQ(clipped_quad[2].z(), -1000000.0f);
+
+ EXPECT_LE_LE(433000.0f, clipped_quad[3].x(), 433025.0f);
+ EXPECT_EQ(clipped_quad[3].y(), 0.0f);
+ EXPECT_EQ(clipped_quad[3].z(), -1000000.0f);
+}
+
+TEST(MathUtilTest, MapClippedQuadInfiniteMatrix) {
+ // clang-format off
+ gfx::Transform transform(
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -100.0f, 0.0f, std::numeric_limits<float>::infinity(),
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ // clang-format on
+
+ gfx::QuadF src_quad(gfx::PointF(0.0f, 1.0f), gfx::PointF(1.0f, 1.0f),
+ gfx::PointF(1.0f, 2.0f), gfx::PointF(0.0f, 2.0f));
+
+ gfx::Point3F clipped_quad[8];
+ int num_vertices_in_clipped_quad;
+
+ MathUtil::MapClippedQuad3d(transform, src_quad, clipped_quad,
+ &num_vertices_in_clipped_quad);
+
+ // Nothing to test other than we don't fail DCHECK()s.
}
} // namespace
diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc
index 221ddad1c89..b2368ce5d07 100644
--- a/chromium/cc/base/switches.cc
+++ b/chromium/cc/base/switches.cc
@@ -97,6 +97,9 @@ 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";
+// Enables the resume method on animated images.
+const char kAnimatedImageResume[] = "animated-image-resume";
+
// Allows scaling clipped images in GpuImageDecodeCache. Note that this may
// cause color-bleeding.
// TODO(crbug.com/1157548): Remove this workaround flag once the underlying
diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h
index 299891a28bc..ba24bd67931 100644
--- a/chromium/cc/base/switches.h
+++ b/chromium/cc/base/switches.h
@@ -61,6 +61,8 @@ CC_BASE_EXPORT extern const char kUIEnableLayerLists[];
CC_BASE_EXPORT extern const char kEnableClippedImageScaling[];
+CC_BASE_EXPORT extern const char kAnimatedImageResume[];
+
// 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 deb55701417..3039e863289 100644
--- a/chromium/cc/base/tiling_data.cc
+++ b/chromium/cc/base/tiling_data.cc
@@ -7,8 +7,8 @@
#include <algorithm>
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/notreached.h"
-#include "base/numerics/ranges.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector2d.h"
@@ -82,7 +82,7 @@ int TilingData::TileXIndexFromSrcCoord(int src_position) const {
DCHECK_GT(max_texture_size_.width() - 2 * border_texels_, 0);
int x = (src_position - border_texels_) /
(max_texture_size_.width() - 2 * border_texels_);
- return base::ClampToRange(x, 0, num_tiles_x_ - 1);
+ return base::clamp(x, 0, num_tiles_x_ - 1);
}
int TilingData::TileYIndexFromSrcCoord(int src_position) const {
@@ -92,7 +92,7 @@ int TilingData::TileYIndexFromSrcCoord(int src_position) const {
DCHECK_GT(max_texture_size_.height() - 2 * border_texels_, 0);
int y = (src_position - border_texels_) /
(max_texture_size_.height() - 2 * border_texels_);
- return base::ClampToRange(y, 0, num_tiles_y_ - 1);
+ return base::clamp(y, 0, num_tiles_y_ - 1);
}
int TilingData::FirstBorderTileXIndexFromSrcCoord(int src_position) const {
@@ -102,7 +102,7 @@ int TilingData::FirstBorderTileXIndexFromSrcCoord(int src_position) const {
DCHECK_GT(max_texture_size_.width() - 2 * border_texels_, 0);
int inner_tile_size = max_texture_size_.width() - 2 * border_texels_;
int x = (src_position - 2 * border_texels_) / inner_tile_size;
- return base::ClampToRange(x, 0, num_tiles_x_ - 1);
+ return base::clamp(x, 0, num_tiles_x_ - 1);
}
int TilingData::FirstBorderTileYIndexFromSrcCoord(int src_position) const {
@@ -112,7 +112,7 @@ int TilingData::FirstBorderTileYIndexFromSrcCoord(int src_position) const {
DCHECK_GT(max_texture_size_.height() - 2 * border_texels_, 0);
int inner_tile_size = max_texture_size_.height() - 2 * border_texels_;
int y = (src_position - 2 * border_texels_) / inner_tile_size;
- return base::ClampToRange(y, 0, num_tiles_y_ - 1);
+ return base::clamp(y, 0, num_tiles_y_ - 1);
}
int TilingData::LastBorderTileXIndexFromSrcCoord(int src_position) const {
@@ -122,7 +122,7 @@ int TilingData::LastBorderTileXIndexFromSrcCoord(int src_position) const {
DCHECK_GT(max_texture_size_.width() - 2 * border_texels_, 0);
int inner_tile_size = max_texture_size_.width() - 2 * border_texels_;
int x = src_position / inner_tile_size;
- return base::ClampToRange(x, 0, num_tiles_x_ - 1);
+ return base::clamp(x, 0, num_tiles_x_ - 1);
}
int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const {
@@ -132,7 +132,7 @@ int TilingData::LastBorderTileYIndexFromSrcCoord(int src_position) const {
DCHECK_GT(max_texture_size_.height() - 2 * border_texels_, 0);
int inner_tile_size = max_texture_size_.height() - 2 * border_texels_;
int y = src_position / inner_tile_size;
- return base::ClampToRange(y, 0, num_tiles_y_ - 1);
+ return base::clamp(y, 0, num_tiles_y_ - 1);
}
IndexRect TilingData::TileAroundIndexRect(const gfx::Rect& center_rect) const {
diff --git a/chromium/cc/benchmarks/invalidation_benchmark.cc b/chromium/cc/benchmarks/invalidation_benchmark.cc
index 08402bdc4ac..b54ca5cbb88 100644
--- a/chromium/cc/benchmarks/invalidation_benchmark.cc
+++ b/chromium/cc/benchmarks/invalidation_benchmark.cc
@@ -8,6 +8,8 @@
#include <algorithm>
#include <limits>
+#include <memory>
+#include <utility>
#include "base/rand_util.h"
#include "base/values.h"
@@ -131,10 +133,11 @@ bool InvalidationBenchmark::ProcessMessage(std::unique_ptr<base::Value> value) {
// high quality, but they need to be identical in each run. Therefore, we use a
// LCG and keep the state locally in the benchmark.
float InvalidationBenchmark::LCGRandom() {
- const uint32_t a = 1664525;
- const uint32_t c = 1013904223;
+ constexpr uint32_t a = 1664525;
+ constexpr uint32_t c = 1013904223;
seed_ = a * seed_ + c;
- return static_cast<float>(seed_) / std::numeric_limits<uint32_t>::max();
+ return static_cast<float>(seed_) /
+ static_cast<float>(std::numeric_limits<uint32_t>::max());
}
} // namespace cc
diff --git a/chromium/cc/benchmarks/micro_benchmark_controller.cc b/chromium/cc/benchmarks/micro_benchmark_controller.cc
index 3c1b166ac47..07f8a0f4ac6 100644
--- a/chromium/cc/benchmarks/micro_benchmark_controller.cc
+++ b/chromium/cc/benchmarks/micro_benchmark_controller.cc
@@ -8,7 +8,7 @@
#include <string>
#include "base/callback.h"
-#include "base/stl_util.h"
+#include "base/containers/cxx20_erase.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "cc/benchmarks/invalidation_benchmark.h"
diff --git a/chromium/cc/benchmarks/micro_benchmark_controller_impl.cc b/chromium/cc/benchmarks/micro_benchmark_controller_impl.cc
index 56a83c7dc19..13624c1cf04 100644
--- a/chromium/cc/benchmarks/micro_benchmark_controller_impl.cc
+++ b/chromium/cc/benchmarks/micro_benchmark_controller_impl.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/callback.h"
-#include "base/stl_util.h"
+#include "base/containers/cxx20_erase.h"
#include "base/values.h"
#include "cc/trees/layer_tree_host_impl.h"
diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc
index 8095225c5be..1be5bac5396 100644
--- a/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc
+++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc
@@ -75,21 +75,24 @@ void RasterizeAndRecordBenchmark::DidUpdateLayers(
static_cast<int>(record_results_.paint_op_memory_usage));
results_->SetInteger("paint_op_count",
static_cast<int>(record_results_.paint_op_count));
- results_->SetDouble("record_time_ms", paint_benchmark_result.record_time_ms);
- results_->SetDouble("record_time_caching_disabled_ms",
- paint_benchmark_result.record_time_caching_disabled_ms);
- results_->SetDouble(
+ results_->SetDoubleKey("record_time_ms",
+ paint_benchmark_result.record_time_ms);
+ results_->SetDoubleKey(
+ "record_time_caching_disabled_ms",
+ paint_benchmark_result.record_time_caching_disabled_ms);
+ results_->SetDoubleKey(
"record_time_subsequence_caching_disabled_ms",
paint_benchmark_result.record_time_subsequence_caching_disabled_ms);
- results_->SetDouble(
+ results_->SetDoubleKey(
"record_time_partial_invalidation_ms",
paint_benchmark_result.record_time_partial_invalidation_ms);
- results_->SetDouble("record_time_small_invalidation_ms",
- paint_benchmark_result.record_time_small_invalidation_ms);
- results_->SetDouble(
+ results_->SetDoubleKey(
+ "record_time_small_invalidation_ms",
+ paint_benchmark_result.record_time_small_invalidation_ms);
+ results_->SetDoubleKey(
"raster_invalidation_and_convert_time_ms",
paint_benchmark_result.raster_invalidation_and_convert_time_ms);
- results_->SetDouble(
+ results_->SetDoubleKey(
"paint_artifact_compositor_update_time_ms",
paint_benchmark_result.paint_artifact_compositor_update_time_ms);
results_->SetInteger(
diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
index b4c365d128d..deebdaf6f73 100644
--- a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
+++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <limits>
#include <memory>
+#include <utility>
#include "base/timer/lap_timer.h"
#include "base/values.h"
@@ -130,8 +131,8 @@ class FixedInvalidationPictureLayerTilingClient
return base_client_->ScrollInteractionInProgress();
}
- bool DidCheckerboardQuad() const override {
- return base_client_->DidCheckerboardQuad();
+ bool CurrentScrollDidCheckerboardLargeArea() const override {
+ return base_client_->CurrentScrollDidCheckerboardLargeArea();
}
private:
@@ -166,8 +167,8 @@ void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
}
std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- result->SetDouble("rasterize_time_ms",
- rasterize_results_.total_best_time.InMillisecondsF());
+ result->SetDoubleKey("rasterize_time_ms",
+ rasterize_results_.total_best_time.InMillisecondsF());
result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized);
result->SetInteger("pixels_rasterized_with_non_solid_color",
rasterize_results_.pixels_rasterized_with_non_solid_color);
diff --git a/chromium/cc/input/browser_controls_offset_manager.cc b/chromium/cc/input/browser_controls_offset_manager.cc
index 65b4ec92d30..a7c2cd9746b 100644
--- a/chromium/cc/input/browser_controls_offset_manager.cc
+++ b/chromium/cc/input/browser_controls_offset_manager.cc
@@ -10,8 +10,8 @@
#include <utility>
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/numerics/ranges.h"
#include "cc/input/browser_controls_offset_manager_client.h"
#include "cc/trees/layer_tree_impl.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -443,7 +443,7 @@ gfx::Vector2dF BrowserControlsOffsetManager::ScrollBy(
float min_ratio = base_on_top_controls ? TopControlsMinShownRatio()
: BottomControlsMinShownRatio();
float normalized_shown_ratio =
- (base::ClampToRange(shown_ratio, min_ratio, 1.f) - min_ratio) /
+ (base::clamp(shown_ratio, min_ratio, 1.f) - min_ratio) /
(1.f - min_ratio);
// Even though the real shown ratios (shown height / total height) of the top
// and bottom controls can be different, they share the same
@@ -517,9 +517,9 @@ gfx::Vector2dF BrowserControlsOffsetManager::Animate(
// too low or too high |top_controls_min_height_offset_| values. So, we
// should clamp it to a valid range.
top_controls_min_height_offset_ =
- base::ClampToRange(top_controls_min_height_offset_ + top_offset_delta,
- top_min_height_offset_animation_range_->first,
- top_min_height_offset_animation_range_->second);
+ base::clamp(top_controls_min_height_offset_ + top_offset_delta,
+ top_min_height_offset_animation_range_->first,
+ top_min_height_offset_animation_range_->second);
// Ticking the animation might reset it if it's at the final value.
top_min_height_change_in_progress_ =
top_controls_animation_.IsInitialized();
@@ -528,10 +528,10 @@ gfx::Vector2dF BrowserControlsOffsetManager::Animate(
// The change in bottom offset may be larger than the min-height, resulting
// in too low or too high |bottom_controls_min_height_offset_| values. So,
// we should clamp it to a valid range.
- bottom_controls_min_height_offset_ = base::ClampToRange(
- bottom_controls_min_height_offset_ + bottom_offset_delta,
- bottom_min_height_offset_animation_range_->first,
- bottom_min_height_offset_animation_range_->second);
+ bottom_controls_min_height_offset_ =
+ base::clamp(bottom_controls_min_height_offset_ + bottom_offset_delta,
+ bottom_min_height_offset_animation_range_->first,
+ bottom_min_height_offset_animation_range_->second);
// Ticking the animation might reset it if it's at the final value.
bottom_min_height_change_in_progress_ =
bottom_controls_animation_.IsInitialized();
@@ -743,7 +743,7 @@ void BrowserControlsOffsetManager::Animation::SetBounds(float min, float max) {
}
absl::optional<float> BrowserControlsOffsetManager::Animation::Reset() {
- auto ret = jump_to_end_on_reset_ ? absl::make_optional(base::ClampToRange(
+ auto ret = jump_to_end_on_reset_ ? absl::make_optional(base::clamp(
stop_value_, min_value_, max_value_))
: absl::nullopt;
@@ -770,7 +770,7 @@ bool BrowserControlsOffsetManager::Animation::IsComplete(float value) {
}
float BrowserControlsOffsetManager::Animation::FinalValue() {
- return base::ClampToRange(stop_value_, min_value_, max_value_);
+ return base::clamp(stop_value_, min_value_, max_value_);
}
} // namespace cc
diff --git a/chromium/cc/input/browser_controls_offset_manager.h b/chromium/cc/input/browser_controls_offset_manager.h
index 1cfa756454b..8e03259efa1 100644
--- a/chromium/cc/input/browser_controls_offset_manager.h
+++ b/chromium/cc/input/browser_controls_offset_manager.h
@@ -12,6 +12,7 @@
#include "cc/input/browser_controls_state.h"
#include "cc/layers/layer_impl.h"
#include "cc/trees/browser_controls_params.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d_f.h"
diff --git a/chromium/cc/input/compositor_input_interfaces.h b/chromium/cc/input/compositor_input_interfaces.h
index d5bbaededda..dcbd420b2cc 100644
--- a/chromium/cc/input/compositor_input_interfaces.h
+++ b/chromium/cc/input/compositor_input_interfaces.h
@@ -65,6 +65,9 @@ class InputDelegateForCompositor {
// completed.
virtual void ScrollOffsetAnimationFinished() = 0;
+ // Called to inform the input handler when prefers-reduced-motion changes.
+ virtual void SetPrefersReducedMotion(bool prefers_reduced_motion) = 0;
+
// Returns true if we're currently in a "gesture" (user-initiated) scroll.
// That is, between a GestureScrollBegin and a GestureScrollEnd. Note, a
// GestureScrollEnd is deferred if the gesture ended but we're still
diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h
index 5460c76c716..e5e555b7ec6 100644
--- a/chromium/cc/input/input_handler.h
+++ b/chromium/cc/input/input_handler.h
@@ -106,6 +106,7 @@ class CC_EXPORT InputHandlerClient {
virtual void WillShutdown() = 0;
virtual void Animate(base::TimeTicks time) = 0;
virtual void ReconcileElasticOverscrollAndRootScroll() = 0;
+ virtual void SetPrefersReducedMotion(bool prefers_reduced_motion) = 0;
virtual void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -352,6 +353,7 @@ class CC_EXPORT InputHandler {
EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) = 0;
virtual ScrollElasticityHelper* CreateScrollElasticityHelper() = 0;
+ virtual void DestroyScrollElasticityHelper() = 0;
// Called by the single-threaded UI Compositor to get or set the scroll offset
// on the impl side. Returns false if |element_id| isn't in the active tree.
@@ -381,6 +383,9 @@ class CC_EXPORT InputHandler {
// being handled by the InputHandler or not.
virtual void NotifyInputEvent() = 0;
+ // Returns true if ScrollbarController is in the middle of a scroll operation.
+ virtual bool ScrollbarScrollIsActive() = 0;
+
protected:
virtual ~InputHandler() = default;
InputHandler() = default;
diff --git a/chromium/cc/input/main_thread_scrolling_reason.cc b/chromium/cc/input/main_thread_scrolling_reason.cc
index 0d0d0c2a57a..eacc3ec2838 100644
--- a/chromium/cc/input/main_thread_scrolling_reason.cc
+++ b/chromium/cc/input/main_thread_scrolling_reason.cc
@@ -4,7 +4,7 @@
#include "cc/input/main_thread_scrolling_reason.h"
-#include "base/stl_util.h"
+#include "base/containers/cxx20_erase.h"
#include "base/strings/string_util.h"
#include "base/trace_event/traced_value.h"
diff --git a/chromium/cc/input/scroll_snap_data.cc b/chromium/cc/input/scroll_snap_data.cc
index b2dc55798cb..9395015a8a4 100644
--- a/chromium/cc/input/scroll_snap_data.cc
+++ b/chromium/cc/input/scroll_snap_data.cc
@@ -10,8 +10,8 @@
#include <memory>
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/notreached.h"
-#include "base/numerics/ranges.h"
#include "cc/input/snap_selection_strategy.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -94,10 +94,10 @@ void SnapSearchResult::set_visible_range(const gfx::RangeF& range) {
}
void SnapSearchResult::Clip(float max_snap, float max_visible) {
- snap_offset_ = base::ClampToRange(snap_offset_, 0.0f, max_snap);
+ snap_offset_ = base::clamp(snap_offset_, 0.0f, max_snap);
visible_range_ =
- gfx::RangeF(base::ClampToRange(visible_range_.start(), 0.0f, max_visible),
- base::ClampToRange(visible_range_.end(), 0.0f, max_visible));
+ gfx::RangeF(base::clamp(visible_range_.start(), 0.0f, max_visible),
+ base::clamp(visible_range_.end(), 0.0f, max_visible));
}
void SnapSearchResult::Union(const SnapSearchResult& other) {
@@ -180,7 +180,7 @@ bool SnapContainerData::FindSnapPosition(
// we cannot always assume that the incoming value fits this criteria we
// clamp it to the bounds to ensure this variant.
SnapSearchResult initial_snap_position_y = {
- base::ClampToRange(base_position.y(), 0.f, max_position_.y()),
+ base::clamp(base_position.y(), 0.f, max_position_.y()),
gfx::RangeF(0, max_position_.x())};
selected_x = FindClosestValidArea(
SearchAxis::kX, strategy, initial_snap_position_y, active_element_id);
@@ -192,7 +192,7 @@ bool SnapContainerData::FindSnapPosition(
DCHECK(selected_y.has_value());
} else {
SnapSearchResult initial_snap_position_x = {
- base::ClampToRange(base_position.x(), 0.f, max_position_.x()),
+ base::clamp(base_position.x(), 0.f, max_position_.x()),
gfx::RangeF(0, max_position_.y())};
selected_y = FindClosestValidArea(
SearchAxis::kY, strategy, initial_snap_position_x, active_element_id);
diff --git a/chromium/cc/input/scroll_snap_data.h b/chromium/cc/input/scroll_snap_data.h
index d067aacdbef..7cc67a6dd7e 100644
--- a/chromium/cc/input/scroll_snap_data.h
+++ b/chromium/cc/input/scroll_snap_data.h
@@ -230,7 +230,7 @@ class CC_EXPORT SnapContainerData {
void AddSnapAreaData(SnapAreaData snap_area_data);
size_t size() const { return snap_area_list_.size(); }
- const SnapAreaData& at(int index) const { return snap_area_list_[index]; }
+ const SnapAreaData& at(size_t index) const { return snap_area_list_[index]; }
void set_scroll_snap_type(ScrollSnapType type) { scroll_snap_type_ = type; }
ScrollSnapType scroll_snap_type() const { return scroll_snap_type_; }
diff --git a/chromium/cc/input/scroll_state_data.cc b/chromium/cc/input/scroll_state_data.cc
index 3409421c5a2..97b5cf2f460 100644
--- a/chromium/cc/input/scroll_state_data.cc
+++ b/chromium/cc/input/scroll_state_data.cc
@@ -29,7 +29,9 @@ ScrollStateData::ScrollStateData()
is_scroll_chain_cut(false),
is_main_thread_hit_tested(false) {}
-ScrollStateData::ScrollStateData(const ScrollStateData& other) = default;
+ScrollStateData::ScrollStateData(const ScrollStateData&) = default;
+
+ScrollStateData& ScrollStateData::operator=(const ScrollStateData&) = default;
ElementId ScrollStateData::current_native_scrolling_element() const {
return current_native_scrolling_element_;
diff --git a/chromium/cc/input/scroll_state_data.h b/chromium/cc/input/scroll_state_data.h
index 94f1506d011..39fc235546e 100644
--- a/chromium/cc/input/scroll_state_data.h
+++ b/chromium/cc/input/scroll_state_data.h
@@ -17,6 +17,7 @@ class CC_EXPORT ScrollStateData {
public:
ScrollStateData();
ScrollStateData(const ScrollStateData& other);
+ ScrollStateData& operator=(const ScrollStateData& other);
// Scroll delta in viewport coordinates (DIP).
double delta_x;
diff --git a/chromium/cc/input/scroll_utils.cc b/chromium/cc/input/scroll_utils.cc
index af78599f472..c90c93a0db0 100644
--- a/chromium/cc/input/scroll_utils.cc
+++ b/chromium/cc/input/scroll_utils.cc
@@ -6,7 +6,6 @@
#include <algorithm>
-#include "base/numerics/ranges.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
diff --git a/chromium/cc/input/scrollbar_animation_controller.cc b/chromium/cc/input/scrollbar_animation_controller.cc
index ec851edea31..098d0419e4e 100644
--- a/chromium/cc/input/scrollbar_animation_controller.cc
+++ b/chromium/cc/input/scrollbar_animation_controller.cc
@@ -8,8 +8,8 @@
#include <memory>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/numerics/ranges.h"
#include "base/time/time.h"
#include "cc/trees/layer_tree_impl.h"
@@ -160,7 +160,7 @@ bool ScrollbarAnimationController::Animate(base::TimeTicks now) {
float ScrollbarAnimationController::AnimationProgressAtTime(
base::TimeTicks now) {
const base::TimeDelta delta = now - last_awaken_time_;
- return base::ClampToRange(float{delta / fade_duration_}, 0.0f, 1.0f);
+ return base::clamp(static_cast<float>(delta / fade_duration_), 0.0f, 1.0f);
}
void ScrollbarAnimationController::RunAnimationFrame(float progress) {
diff --git a/chromium/cc/input/scrollbar_controller.h b/chromium/cc/input/scrollbar_controller.h
index f2dc6003bf6..80f093255cb 100644
--- a/chromium/cc/input/scrollbar_controller.h
+++ b/chromium/cc/input/scrollbar_controller.h
@@ -12,9 +12,10 @@
#include "cc/input/scrollbar.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// High level documentation:
-// https://source.chromium.org/chromium/chromium/src/+/master:cc/input/README.md
+// https://source.chromium.org/chromium/chromium/src/+/main:cc/input/README.md
// Click scrolling.
// - A click is considered as a kMouseDown and a kMouseUp in quick succession.
diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning.cc b/chromium/cc/input/single_scrollbar_animation_controller_thinning.cc
index 75a458650f3..5288a8c5d3b 100644
--- a/chromium/cc/input/single_scrollbar_animation_controller_thinning.cc
+++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning.cc
@@ -6,8 +6,8 @@
#include <algorithm>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/numerics/ranges.h"
#include "base/time/time.h"
#include "cc/input/scrollbar_animation_controller.h"
#include "cc/layers/layer_impl.h"
@@ -99,7 +99,8 @@ float SingleScrollbarAnimationControllerThinning::AnimationProgressAtTime(
return 1.0f;
const base::TimeDelta delta = now - last_awaken_time_;
- return base::ClampToRange(float{delta / thinning_duration_}, 0.0f, 1.0f);
+ return base::clamp(static_cast<float>(delta / thinning_duration_), 0.0f,
+ 1.0f);
}
void SingleScrollbarAnimationControllerThinning::RunAnimationFrame(
diff --git a/chromium/cc/input/threaded_input_handler.cc b/chromium/cc/input/threaded_input_handler.cc
index cebc21a1f6a..872bf40dbc2 100644
--- a/chromium/cc/input/threaded_input_handler.cc
+++ b/chromium/cc/input/threaded_input_handler.cc
@@ -77,6 +77,7 @@ base::WeakPtr<InputHandler> ThreadedInputHandler::AsWeakPtr() const {
void ThreadedInputHandler::BindToClient(InputHandlerClient* client) {
DCHECK(input_handler_client_ == nullptr);
input_handler_client_ = client;
+ input_handler_client_->SetPrefersReducedMotion(prefers_reduced_motion_);
}
InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin(
@@ -871,6 +872,12 @@ ScrollElasticityHelper* ThreadedInputHandler::CreateScrollElasticityHelper() {
return scroll_elasticity_helper_.get();
}
+void ThreadedInputHandler::DestroyScrollElasticityHelper() {
+ // Remove any stretch before destroying helper.
+ scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF());
+ scroll_elasticity_helper_.reset();
+}
+
bool ThreadedInputHandler::GetScrollOffsetForLayer(ElementId element_id,
gfx::ScrollOffset* offset) {
ScrollTree& scroll_tree = GetScrollTree();
@@ -956,7 +963,8 @@ void ThreadedInputHandler::ScrollEndForSnapFling(bool did_finish) {
scroll_node->snap_container_data.has_value()) {
scroll_node->snap_container_data.value().SetTargetSnapAreaElementIds(
scroll_animating_snap_target_ids_);
- updated_snapped_elements_.insert(scroll_node->element_id);
+ updated_snapped_elements_[scroll_node->element_id] =
+ scroll_animating_snap_target_ids_;
SetNeedsCommit();
}
scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds();
@@ -981,7 +989,7 @@ void ThreadedInputHandler::ProcessCommitDeltas(
InnerViewportScrollNode() ? InnerViewportScrollNode()->element_id
: ElementId();
- base::flat_set<ElementId> snapped_elements;
+ base::flat_map<ElementId, TargetSnapAreaElementIds> snapped_elements;
updated_snapped_elements_.swap(snapped_elements);
// Scroll commit data is stored in the scroll tree so it has its own method
@@ -1106,7 +1114,8 @@ void ThreadedInputHandler::ScrollOffsetAnimationFinished() {
if (scroll_node && scroll_node->snap_container_data.has_value()) {
scroll_node->snap_container_data.value().SetTargetSnapAreaElementIds(
scroll_animating_snap_target_ids_);
- updated_snapped_elements_.insert(scroll_node->element_id);
+ updated_snapped_elements_[scroll_node->element_id] =
+ scroll_animating_snap_target_ids_;
SetNeedsCommit();
}
scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds();
@@ -1119,6 +1128,16 @@ void ThreadedInputHandler::ScrollOffsetAnimationFinished() {
}
}
+void ThreadedInputHandler::SetPrefersReducedMotion(
+ bool prefers_reduced_motion) {
+ if (prefers_reduced_motion_ == prefers_reduced_motion)
+ return;
+ prefers_reduced_motion_ = prefers_reduced_motion;
+
+ if (input_handler_client_)
+ input_handler_client_->SetPrefersReducedMotion(prefers_reduced_motion_);
+}
+
bool ThreadedInputHandler::IsCurrentlyScrolling() const {
return CurrentlyScrollingNode();
}
@@ -1294,7 +1313,7 @@ InputHandler::ScrollStatus ThreadedInputHandler::TryScroll(
"LayerImpl::tryScroll: Failed due to no scrolling layer");
scroll_status.thread = InputHandler::ScrollThread::SCROLL_ON_MAIN_THREAD;
scroll_status.main_thread_scrolling_reasons =
- MainThreadScrollingReason::kNonFastScrollableRegion;
+ MainThreadScrollingReason::kNoScrollingLayer;
return scroll_status;
}
@@ -2074,7 +2093,7 @@ bool ThreadedInputHandler::SnapAtScrollEnd(SnapReason reason) {
// The snap target will be set when the animation is completed.
scroll_animating_snap_target_ids_ = snap_target_ids;
} else if (data.SetTargetSnapAreaElementIds(snap_target_ids)) {
- updated_snapped_elements_.insert(scroll_node->element_id);
+ updated_snapped_elements_[scroll_node->element_id] = snap_target_ids;
SetNeedsCommit();
}
return did_animate;
@@ -2185,4 +2204,8 @@ gfx::Vector2dF ThreadedInputHandler::UserScrollableDelta(
return adjusted_delta;
}
+bool ThreadedInputHandler::ScrollbarScrollIsActive() {
+ return scrollbar_controller_->ScrollbarScrollIsActive();
+}
+
} // namespace cc
diff --git a/chromium/cc/input/threaded_input_handler.h b/chromium/cc/input/threaded_input_handler.h
index e327ee989d7..eb3b6d5c88b 100644
--- a/chromium/cc/input/threaded_input_handler.h
+++ b/chromium/cc/input/threaded_input_handler.h
@@ -91,6 +91,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler,
GetScopedEventMetricsMonitor(
EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) override;
ScrollElasticityHelper* CreateScrollElasticityHelper() override;
+ void DestroyScrollElasticityHelper() override;
bool GetScrollOffsetForLayer(ElementId element_id,
gfx::ScrollOffset* offset) override;
bool ScrollLayerTo(ElementId element_id,
@@ -102,6 +103,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler,
gfx::Vector2dF* out_target_position) override;
void ScrollEndForSnapFling(bool did_finish) override;
void NotifyInputEvent() override;
+ bool ScrollbarScrollIsActive() override;
// =========== InputDelegateForCompositor Interface - This section implements
// the interface that LayerTreeHostImpl uses to communicate with the input
@@ -117,6 +119,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler,
void DidUnregisterScrollbar(ElementId scroll_element_id,
ScrollbarOrientation orientation) override;
void ScrollOffsetAnimationFinished() override;
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override;
bool IsCurrentlyScrolling() const override;
ActivelyScrollingType GetActivelyScrollingType() const override;
@@ -390,7 +393,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler,
// A set of elements that scroll-snapped to a new target since the last
// begin main frame. The snap target ids of these elements will be sent to
// the main thread in the next begin main frame.
- base::flat_set<ElementId> updated_snapped_elements_;
+ base::flat_map<ElementId, TargetSnapAreaElementIds> updated_snapped_elements_;
ElementId scroll_element_id_mouse_currently_over_;
ElementId scroll_element_id_mouse_currently_captured_;
@@ -443,6 +446,8 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler,
bool has_scrolled_by_precisiontouchpad_ = false;
bool has_scrolled_by_scrollbar_ = false;
+ bool prefers_reduced_motion_ = false;
+
// Must be the last member to ensure this is destroyed first in the
// destruction order and invalidates all weak pointers.
base::WeakPtrFactory<ThreadedInputHandler> weak_factory_{this};
diff --git a/chromium/cc/layers/deadline_policy.cc b/chromium/cc/layers/deadline_policy.cc
index 2b343da4397..65f376ddbe5 100644
--- a/chromium/cc/layers/deadline_policy.cc
+++ b/chromium/cc/layers/deadline_policy.cc
@@ -6,7 +6,28 @@
#include <limits>
+#include "base/notreached.h"
+#include "base/strings/stringprintf.h"
+
namespace cc {
+namespace {
+
+const char* PolicyToString(DeadlinePolicy::Type type) {
+ switch (type) {
+ case DeadlinePolicy::Type::kUseExistingDeadline:
+ return "UseExistingDeadline";
+ case DeadlinePolicy::Type::kUseDefaultDeadline:
+ return "UseDefaultDeadline";
+ case DeadlinePolicy::Type::kUseSpecifiedDeadline:
+ return "UseSpecifiedDeadline";
+ case DeadlinePolicy::Type::kUseInfiniteDeadline:
+ return "UseInfiniteDeadline";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace
// static
DeadlinePolicy DeadlinePolicy::UseExistingDeadline() {
@@ -36,4 +57,10 @@ DeadlinePolicy::DeadlinePolicy(Type policy_type,
DeadlinePolicy::DeadlinePolicy(const DeadlinePolicy& other) = default;
+std::string DeadlinePolicy::ToString() const {
+ return base::StringPrintf("DeadlinePolicy(%s, %d)",
+ PolicyToString(policy_type_),
+ deadline_in_frames_.value_or(-1));
+}
+
} // namespace cc
diff --git a/chromium/cc/layers/deadline_policy.h b/chromium/cc/layers/deadline_policy.h
index 9a62c1fe2d4..57416c66e0d 100644
--- a/chromium/cc/layers/deadline_policy.h
+++ b/chromium/cc/layers/deadline_policy.h
@@ -6,6 +6,7 @@
#define CC_LAYERS_DEADLINE_POLICY_H_
#include <cstdint>
+#include <string>
#include "base/check.h"
#include "cc/cc_export.h"
@@ -58,6 +59,8 @@ class CC_EXPORT DeadlinePolicy {
return !(*this == other);
}
+ std::string ToString() const;
+
private:
explicit DeadlinePolicy(
Type policy_type,
diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc
index 289ff12cefb..e8f4bd8df42 100644
--- a/chromium/cc/layers/heads_up_display_layer_impl.cc
+++ b/chromium/cc/layers/heads_up_display_layer_impl.cc
@@ -55,6 +55,7 @@
#include "third_party/skia/include/core/SkFont.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "ui/gfx/geometry/point.h"
@@ -306,6 +307,8 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
} else if (gpu_raster) {
flags |= gpu::SHARED_IMAGE_USAGE_GLES2 |
gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
+ } else {
+ flags |= gpu::SHARED_IMAGE_USAGE_GLES2;
}
if (backing->overlay_candidate)
flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT;
@@ -379,7 +382,8 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
constexpr GLuint msaa_sample_count = -1;
constexpr bool can_use_lcd_text = true;
ri->BeginRasterCHROMIUM(background_color, needs_clear, msaa_sample_count,
- can_use_lcd_text, gfx::ColorSpace::CreateSRGB(),
+ gpu::raster::kNoMSAA, can_use_lcd_text,
+ gfx::ColorSpace::CreateSRGB(),
backing->mailbox.name);
gfx::Vector2dF post_translate(0.f, 0.f);
gfx::Vector2dF post_scale(1.f, 1.f);
@@ -510,11 +514,23 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture(
render_pass->quad_list.ReplaceExistingElement<viz::TextureDrawQuad>(
it);
+ // The acquired resource's size could be bigger than actually needed due
+ // to reuse. In this case, only use the part of the texture that is within
+ // the bounds.
+ gfx::PointF uv_bottom_right(1.f, 1.f);
+ if (in_flight_resource_.size() != internal_content_bounds_) {
+ uv_bottom_right.set_x(
+ static_cast<double>(internal_content_bounds_.width()) /
+ static_cast<double>(in_flight_resource_.size().width()));
+ uv_bottom_right.set_y(
+ static_cast<double>(internal_content_bounds_.height()) /
+ static_cast<double>(in_flight_resource_.size().height()));
+ }
const float vertex_opacity[] = {1.f, 1.f, 1.f, 1.f};
quad->SetNew(sqs, quad_rect, visible_rect, /*needs_blending=*/true,
resource_id, /*premultiplied_alpha=*/true,
/*uv_top_left=*/gfx::PointF(),
- /*uv_bottom_right=*/gfx::PointF(1.f, 1.f),
+ /*uv_bottom_right=*/uv_bottom_right,
/*background_color=*/SK_ColorTRANSPARENT, vertex_opacity,
/*flipped=*/false,
/*nearest_neighbor=*/false, /*secure_output_only=*/false,
diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc
index 2f6f6f8ecf3..03cb7303a34 100644
--- a/chromium/cc/layers/layer.cc
+++ b/chromium/cc/layers/layer.cc
@@ -349,9 +349,13 @@ void Layer::SetBounds(const gfx::Size& size) {
// Rounded corner clipping, bounds clipping and mask clipping can result in
// new areas of subtrees being exposed on a bounds change. Ensure the damaged
- // areas are updated.
+ // areas are updated. Also, if the layer subtree (rooted at this layer) is
+ // marked as capturable (via a valid SubtreeCaptureId), then the property tree
+ // needs rebuild so that |EffectNode::subtree_size| is updated with the new
+ // size of this layer.
if (!layer_tree_host_->IsUsingLayerLists()) {
- if (masks_to_bounds() || mask_layer() || HasRoundedCorner()) {
+ if (subtree_capture_id().is_valid() || masks_to_bounds() || mask_layer() ||
+ HasRoundedCorner()) {
SetSubtreePropertyChanged();
SetPropertyTreesNeedRebuild();
}
diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h
index 33918090136..db032e93d52 100644
--- a/chromium/cc/layers/layer.h
+++ b/chromium/cc/layers/layer.h
@@ -16,7 +16,6 @@
#include "base/auto_reset.h"
#include "base/callback.h"
#include "base/memory/ref_counted.h"
-#include "base/observer_list.h"
#include "cc/base/region.h"
#include "cc/benchmarks/micro_benchmark.h"
#include "cc/cc_export.h"
@@ -53,7 +52,7 @@ class PictureLayer;
// For tracing and debugging. The info will be attached to this layer's tracing
// output.
-struct LayerDebugInfo {
+struct CC_EXPORT LayerDebugInfo {
LayerDebugInfo();
LayerDebugInfo(const LayerDebugInfo&);
~LayerDebugInfo();
@@ -401,11 +400,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> {
// For layer tree mode only.
// Marks this layer as being scrollable and needing an associated scroll node,
- // and specifies the total size of the content to be scrolled (ie the max
- // scroll offsets. The size should be a union of the layer and its subtree, as
- // well as any layers for whom this layer is their scroll parent, and their
- // subtrees, when they are transformed into this layer's space. Thus
- // transforms of children affect the size of the |scroll_container_bounds|.
+ // and specifies the size of the container in which the scrolling contents are
+ // visible. (Use SetBounds to set the size of the content to be scrolled.)
// Once scrollable, a Layer cannot become un-scrollable.
void SetScrollable(const gfx::Size& scroll_container_bounds);
bool scrollable() const {
diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc
index 9596cbf7cbe..cda060711e4 100644
--- a/chromium/cc/layers/layer_impl_unittest.cc
+++ b/chromium/cc/layers/layer_impl_unittest.cc
@@ -6,7 +6,6 @@
#include <algorithm>
-#include "base/stl_util.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/layers/solid_color_scrollbar_layer_impl.h"
#include "cc/paint/filter_operation.h"
diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc
index 61b4890e82c..6ae8e295a23 100644
--- a/chromium/cc/layers/layer_unittest.cc
+++ b/chromium/cc/layers/layer_unittest.cc
@@ -1395,7 +1395,8 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) {
// layer does not abort either one.
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&ReceiveCopyOutputResultAtomic,
base::Unretained(&result_count)));
layer->RequestCopyOfOutput(std::move(request));
@@ -1404,7 +1405,8 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) {
CCTestSuite::RunUntilIdle();
EXPECT_EQ(0, result_count.load());
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&ReceiveCopyOutputResultAtomic,
base::Unretained(&result_count)));
layer->RequestCopyOfOutput(std::move(request));
@@ -1426,7 +1428,8 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) {
// the second request using |kArbitrarySourceId1| is made.
int did_receive_first_result_from_this_source = 0;
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&ReceiveCopyOutputResult,
&did_receive_first_result_from_this_source));
request->set_source(kArbitrarySourceId1);
@@ -1438,7 +1441,8 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) {
// Make a request from a different source.
int did_receive_result_from_different_source = 0;
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&ReceiveCopyOutputResult,
&did_receive_result_from_different_source));
request->set_source(kArbitrarySourceId2);
@@ -1450,7 +1454,8 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) {
// Make a request without specifying the source.
int did_receive_result_from_anonymous_source = 0;
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&ReceiveCopyOutputResult,
&did_receive_result_from_anonymous_source));
layer->RequestCopyOfOutput(std::move(request));
@@ -1461,7 +1466,8 @@ TEST_F(LayerTest, DedupesCopyOutputRequestsBySource) {
// Make the second request from |kArbitrarySourceId1|.
int did_receive_second_result_from_this_source = 0;
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&ReceiveCopyOutputResult,
&did_receive_second_result_from_this_source));
request->set_source(kArbitrarySourceId1);
diff --git a/chromium/cc/layers/picture_layer.h b/chromium/cc/layers/picture_layer.h
index 7b13db34e19..8cacd483c0a 100644
--- a/chromium/cc/layers/picture_layer.h
+++ b/chromium/cc/layers/picture_layer.h
@@ -51,7 +51,7 @@ class CC_EXPORT PictureLayer : public Layer {
ContentLayerClient* client() { return picture_layer_inputs_.client; }
- RecordingSource* GetRecordingSourceForTesting() {
+ RecordingSource* GetRecordingSourceForTesting() const {
return recording_source_.get();
}
diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc
index 767d3315604..6dceca33062 100644
--- a/chromium/cc/layers/picture_layer_impl.cc
+++ b/chromium/cc/layers/picture_layer_impl.cc
@@ -15,9 +15,9 @@
#include <utility>
#include "base/containers/contains.h"
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
-#include "base/numerics/ranges.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "base/trace_event/traced_value.h"
@@ -207,11 +207,6 @@ void PictureLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
viz::SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
- // If did_checkerboard_quad_ is set to true, don't set to false until the
- // scroll is completed.
- if (!ScrollInteractionInProgress())
- SetDidCheckerboardQuad(false);
-
if (raster_source_->IsSolidColor()) {
// TODO(979672): This is still hard-coded at 1.0. This has some history:
// - for crbug.com/769319, the contents scale was allowed to change, to
@@ -549,7 +544,6 @@ void PictureLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
append_quads_data->checkerboarded_no_recording_content_area +=
visible_geometry_area - checkerboarded_has_recording_area;
- SetDidCheckerboardQuad(true);
continue;
}
@@ -788,6 +782,8 @@ void PictureLayerImpl::UpdateRasterSource(
bool could_have_tilings = CanHaveTilings();
raster_source_.swap(raster_source);
+ raster_source_->set_debug_name(DebugName());
+
// Register images from the new raster source, if the recording was updated.
// TODO(khushalsagar): UMA the number of animated images in layer?
if (recording_updated)
@@ -1011,8 +1007,8 @@ bool PictureLayerImpl::ScrollInteractionInProgress() const {
ActivelyScrollingType::kNone;
}
-bool PictureLayerImpl::DidCheckerboardQuad() const {
- return did_checkerboard_quad_;
+bool PictureLayerImpl::CurrentScrollDidCheckerboardLargeArea() const {
+ return layer_tree_impl()->CurrentScrollDidCheckerboardLargeArea();
}
gfx::Rect PictureLayerImpl::GetEnclosingVisibleRectInTargetSpace() const {
@@ -1183,7 +1179,7 @@ float PictureLayerImpl::CalculateDirectlyCompositedImageRasterScale() const {
float min_scale = MinimumContentsScale();
float clamped_ideal_source_scale =
- base::ClampToRange(ideal_source_scale_key(), min_scale, max_scale);
+ base::clamp(ideal_source_scale_key(), min_scale, max_scale);
while (adjusted_raster_scale < clamped_ideal_source_scale)
adjusted_raster_scale *= 2.f;
@@ -1196,7 +1192,7 @@ float PictureLayerImpl::CalculateDirectlyCompositedImageRasterScale() const {
adjusted_raster_scale /= 2.f;
adjusted_raster_scale =
- base::ClampToRange(adjusted_raster_scale, min_scale, max_scale);
+ base::clamp(adjusted_raster_scale, min_scale, max_scale);
return adjusted_raster_scale;
}
@@ -1683,7 +1679,7 @@ bool PictureLayerImpl::CalculateRasterTranslation(
// a layer of size 10000px does not exceed 0.001px.
static constexpr float kPixelErrorThreshold = 0.001f;
static constexpr float kScaleErrorThreshold = kPixelErrorThreshold / 10000;
- auto is_raster_scale = [this](const SkMatrix44& matrix) -> bool {
+ auto is_raster_scale = [this](const skia::Matrix44& matrix) -> bool {
// The matrix has the X scale at (0,0), and the Y scale at (1,1).
return std::abs(matrix.getFloat(0, 0) - raster_contents_scale_.x()) <=
kScaleErrorThreshold &&
diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h
index c673c17c128..231830dec2f 100644
--- a/chromium/cc/layers/picture_layer_impl.h
+++ b/chromium/cc/layers/picture_layer_impl.h
@@ -80,7 +80,7 @@ class CC_EXPORT PictureLayerImpl
const PaintWorkletRecordMap& GetPaintWorkletRecords() const override;
bool IsDirectlyCompositedImage() const override;
bool ScrollInteractionInProgress() const override;
- bool DidCheckerboardQuad() const override;
+ bool CurrentScrollDidCheckerboardLargeArea() const override;
// ImageAnimationController::AnimationDriver overrides.
bool ShouldAnimate(PaintImage::Id paint_image_id) const override;
@@ -107,10 +107,6 @@ class CC_EXPORT PictureLayerImpl
void SetNearestNeighbor(bool nearest_neighbor);
- void SetDidCheckerboardQuad(bool did_checkerboard_quad) {
- did_checkerboard_quad_ = did_checkerboard_quad;
- }
-
void SetDirectlyCompositedImageSize(absl::optional<gfx::Size>);
size_t GPUMemoryUsageInBytes() const override;
@@ -291,9 +287,6 @@ class CC_EXPORT PictureLayerImpl
bool nearest_neighbor_ : 1;
- // Whether the layer did not have a draw quad during last AppendQuads call.
- bool did_checkerboard_quad_ : 1;
-
// This is set by UpdateRasterSource() on change of raster source size. It's
// used to recalculate raster scale for will-chagne:transform. It's reset to
// false after raster scale update.
diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc
index 6d0922a33e9..e34ad2457d3 100644
--- a/chromium/cc/layers/picture_layer_impl_unittest.cc
+++ b/chromium/cc/layers/picture_layer_impl_unittest.cc
@@ -12,8 +12,8 @@
#include <set>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/location.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/animation/animation_host.h"
#include "cc/base/math_util.h"
@@ -2145,7 +2145,6 @@ TEST_F(LegacySWPictureLayerImplTest, AppendQuadsDataForCheckerboard) {
EXPECT_EQ(17500, data.checkerboarded_no_recording_content_area);
EXPECT_EQ(22500, data.checkerboarded_needs_raster_content_area);
EXPECT_TRUE(active_layer()->only_used_low_res_last_append_quads());
- EXPECT_TRUE(active_layer()->DidCheckerboardQuad());
}
TEST_F(LegacySWPictureLayerImplTest, HighResRequiredWhenActiveAllReady) {
diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc
index 3fd239a4635..4ebb9da7dfa 100644
--- a/chromium/cc/layers/render_surface_impl.cc
+++ b/chromium/cc/layers/render_surface_impl.cc
@@ -160,6 +160,10 @@ viz::SubtreeCaptureId RenderSurfaceImpl::SubtreeCaptureId() const {
return OwningEffectNode()->subtree_capture_id;
}
+gfx::Size RenderSurfaceImpl::SubtreeSize() const {
+ return OwningEffectNode()->subtree_size;
+}
+
bool RenderSurfaceImpl::ShouldCacheRenderSurface() const {
return OwningEffectNode()->cache_render_surface;
}
@@ -391,6 +395,10 @@ RenderSurfaceImpl::CreateRenderPass() {
pass->backdrop_filter_bounds = BackdropFilterBounds();
pass->generate_mipmap = TrilinearFiltering();
pass->subtree_capture_id = SubtreeCaptureId();
+ // The subtree size may be slightly larger than our content rect during
+ // some animations, so we clamp it here.
+ pass->subtree_size = SubtreeSize();
+ pass->subtree_size.SetToMin(content_rect().size());
pass->cache_render_pass = ShouldCacheRenderSurface();
pass->has_damage_from_contributing_content =
HasDamageFromeContributingContent();
diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h
index 7d303a2f331..234feafb687 100644
--- a/chromium/cc/layers/render_surface_impl.h
+++ b/chromium/cc/layers/render_surface_impl.h
@@ -20,8 +20,10 @@
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/shared_quad_state.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/mask_filter_info.h"
#include "ui/gfx/transform.h"
@@ -176,8 +178,15 @@ class CC_EXPORT RenderSurfaceImpl {
bool HasCopyRequest() const;
+ // The capture identifier for this render surface and its originating effect
+ // node. If empty, this surface has not been selected as a subtree capture and
+ // is either a root surface or will not be rendered separately.
viz::SubtreeCaptureId SubtreeCaptureId() const;
+ // The size of this surface that should be used for cropping capture. If
+ // empty, the entire size of this surface should be used for capture.
+ gfx::Size SubtreeSize() const;
+
bool ShouldCacheRenderSurface() const;
// Returns true if it's required to copy the output of this surface (i.e. when
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc
index 3d9e48dc9a3..1a9faf0b7ee 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.cc
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc
@@ -6,7 +6,7 @@
#include <algorithm>
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/scroll_node.h"
@@ -211,10 +211,12 @@ gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRectWithThumbThicknessScale(
float track_length = TrackLength();
int thumb_length = ThumbLength();
int thumb_thickness = ThumbThickness();
- float maximum = scroll_layer_length() - clip_layer_length();
+ // TODO(crbug.com/1239770): This is a speculative fix.
+ float maximum = std::max(scroll_layer_length() - clip_layer_length(), 0.0f);
+ DCHECK(scroll_layer_length() >= clip_layer_length());
// With the length known, we can compute the thumb's position.
- float clamped_current_pos = base::ClampToRange(current_pos(), 0.0f, maximum);
+ float clamped_current_pos = base::clamp(current_pos(), 0.0f, maximum);
int thumb_offset = TrackStart();
if (maximum > 0) {
diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc
index d50707ec578..76f99c951fb 100644
--- a/chromium/cc/layers/surface_layer_impl.cc
+++ b/chromium/cc/layers/surface_layer_impl.cc
@@ -8,7 +8,7 @@
#include <algorithm>
#include <utility>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/traced_value.h"
#include "cc/debug/debug_colors.h"
diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc
index c5872526814..a5d2b601009 100644
--- a/chromium/cc/layers/texture_layer.cc
+++ b/chromium/cc/layers/texture_layer.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/cxx20_erase.h"
#include "base/location.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
diff --git a/chromium/cc/layers/texture_layer_impl.cc b/chromium/cc/layers/texture_layer_impl.cc
index ebe01e4df08..7bc545b6bcd 100644
--- a/chromium/cc/layers/texture_layer_impl.cc
+++ b/chromium/cc/layers/texture_layer_impl.cc
@@ -11,6 +11,7 @@
#include <utility>
#include <vector>
+#include "base/containers/cxx20_erase.h"
#include "base/logging.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_impl.h"
diff --git a/chromium/cc/layers/video_layer.cc b/chromium/cc/layers/video_layer.cc
index 1c656ecc11d..5ce684b2c45 100644
--- a/chromium/cc/layers/video_layer.cc
+++ b/chromium/cc/layers/video_layer.cc
@@ -10,13 +10,13 @@ namespace cc {
scoped_refptr<VideoLayer> VideoLayer::Create(
VideoFrameProvider* provider,
- media::VideoRotation video_rotation) {
- return base::WrapRefCounted(new VideoLayer(provider, video_rotation));
+ media::VideoTransformation transform) {
+ return base::WrapRefCounted(new VideoLayer(provider, transform));
}
VideoLayer::VideoLayer(VideoFrameProvider* provider,
- media::VideoRotation video_rotation)
- : provider_(provider), video_rotation_(video_rotation) {
+ media::VideoTransformation transform)
+ : provider_(provider), transform_(transform) {
SetMayContainVideo(true);
DCHECK(provider_);
}
@@ -25,7 +25,7 @@ VideoLayer::~VideoLayer() = default;
std::unique_ptr<LayerImpl> VideoLayer::CreateLayerImpl(
LayerTreeImpl* tree_impl) {
- return VideoLayerImpl::Create(tree_impl, id(), provider_, video_rotation_);
+ return VideoLayerImpl::Create(tree_impl, id(), provider_, transform_);
}
bool VideoLayer::Update() {
diff --git a/chromium/cc/layers/video_layer.h b/chromium/cc/layers/video_layer.h
index 45cacd34d0f..142bf20ac9f 100644
--- a/chromium/cc/layers/video_layer.h
+++ b/chromium/cc/layers/video_layer.h
@@ -5,6 +5,8 @@
#ifndef CC_LAYERS_VIDEO_LAYER_H_
#define CC_LAYERS_VIDEO_LAYER_H_
+#include <memory>
+
#include "base/callback.h"
#include "cc/cc_export.h"
#include "cc/layers/layer.h"
@@ -21,7 +23,7 @@ class VideoLayerImpl;
class CC_EXPORT VideoLayer : public Layer {
public:
static scoped_refptr<VideoLayer> Create(VideoFrameProvider* provider,
- media::VideoRotation video_rotation);
+ media::VideoTransformation transform);
VideoLayer(const VideoLayer&) = delete;
VideoLayer& operator=(const VideoLayer&) = delete;
@@ -34,14 +36,15 @@ class CC_EXPORT VideoLayer : public Layer {
void StopUsingProvider();
private:
- VideoLayer(VideoFrameProvider* provider, media::VideoRotation video_rotation);
+ VideoLayer(VideoFrameProvider* provider,
+ media::VideoTransformation transform);
~VideoLayer() override;
// This pointer is only for passing to VideoLayerImpl's constructor. It should
// never be dereferenced by this class.
VideoFrameProvider* provider_;
- media::VideoRotation video_rotation_;
+ media::VideoTransformation transform_;
};
} // namespace cc
diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc
index ba7d9dabd70..0c6087a4389 100644
--- a/chromium/cc/layers/video_layer_impl.cc
+++ b/chromium/cc/layers/video_layer_impl.cc
@@ -32,7 +32,7 @@ std::unique_ptr<VideoLayerImpl> VideoLayerImpl::Create(
LayerTreeImpl* tree_impl,
int id,
VideoFrameProvider* provider,
- media::VideoRotation video_rotation) {
+ media::VideoTransformation video_transform) {
DCHECK(tree_impl->task_runner_provider()->IsMainThreadBlocked());
DCHECK(tree_impl->task_runner_provider()->IsImplThread());
@@ -41,18 +41,17 @@ std::unique_ptr<VideoLayerImpl> VideoLayerImpl::Create(
provider, tree_impl->GetVideoFrameControllerClient());
return base::WrapUnique(new VideoLayerImpl(
- tree_impl, id, std::move(provider_client_impl), video_rotation));
+ tree_impl, id, std::move(provider_client_impl), video_transform));
}
VideoLayerImpl::VideoLayerImpl(
LayerTreeImpl* tree_impl,
int id,
scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl,
- media::VideoRotation video_rotation)
+ media::VideoTransformation video_transform)
: LayerImpl(tree_impl, id),
provider_client_impl_(std::move(provider_client_impl)),
- frame_(nullptr),
- video_rotation_(video_rotation) {
+ video_transform_(video_transform) {
set_may_contain_video(true);
}
@@ -72,7 +71,7 @@ VideoLayerImpl::~VideoLayerImpl() {
std::unique_ptr<LayerImpl> VideoLayerImpl::CreateLayerImpl(
LayerTreeImpl* tree_impl) {
return base::WrapUnique(new VideoLayerImpl(
- tree_impl, id(), provider_client_impl_, video_rotation_));
+ tree_impl, id(), provider_client_impl_, video_transform_));
}
void VideoLayerImpl::DidBecomeActive() {
@@ -126,32 +125,41 @@ bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
void VideoLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data) {
- DCHECK(frame_.get());
+ DCHECK(frame_);
gfx::Transform transform = DrawTransform();
+
// bounds() is in post-rotation space so quad rect in content space must be
// in pre-rotation space
gfx::Size rotated_size = bounds();
- switch (video_rotation_) {
+ // Prefer the frame level transform if set.
+ auto media_transform =
+ frame_->metadata().transformation.value_or(video_transform_);
+ switch (media_transform.rotation) {
case media::VIDEO_ROTATION_90:
rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
- transform.Rotate(90.0);
+ transform.RotateAboutZAxis(90.0);
transform.Translate(0.0, -rotated_size.height());
break;
case media::VIDEO_ROTATION_180:
- transform.Rotate(180.0);
+ transform.RotateAboutZAxis(180.0);
transform.Translate(-rotated_size.width(), -rotated_size.height());
break;
case media::VIDEO_ROTATION_270:
rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
- transform.Rotate(270.0);
+ transform.RotateAboutZAxis(270.0);
transform.Translate(-rotated_size.width(), 0);
break;
case media::VIDEO_ROTATION_0:
break;
}
+ if (media_transform.mirrored) {
+ transform.RotateAboutYAxis(180.0);
+ transform.Translate(-rotated_size.width(), 0);
+ }
+
gfx::Rect quad_rect(rotated_size);
Occlusion occlusion_in_video_space =
draw_properties()
diff --git a/chromium/cc/layers/video_layer_impl.h b/chromium/cc/layers/video_layer_impl.h
index 9727fd4625b..254621aaa4b 100644
--- a/chromium/cc/layers/video_layer_impl.h
+++ b/chromium/cc/layers/video_layer_impl.h
@@ -5,6 +5,7 @@
#ifndef CC_LAYERS_VIDEO_LAYER_IMPL_H_
#define CC_LAYERS_VIDEO_LAYER_IMPL_H_
+#include <memory>
#include <vector>
#include "cc/cc_export.h"
@@ -29,7 +30,7 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
LayerTreeImpl* tree_impl,
int id,
VideoFrameProvider* provider,
- media::VideoRotation video_rotation);
+ media::VideoTransformation video_transform);
VideoLayerImpl(const VideoLayerImpl&) = delete;
~VideoLayerImpl() override;
@@ -48,14 +49,17 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
gfx::ContentColorUsage GetContentColorUsage() const override;
void SetNeedsRedraw();
- media::VideoRotation video_rotation() const { return video_rotation_; }
+
+ media::VideoTransformation video_transform_for_testing() const {
+ return video_transform_;
+ }
private:
VideoLayerImpl(
LayerTreeImpl* tree_impl,
int id,
scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl,
- media::VideoRotation video_rotation);
+ media::VideoTransformation video_transform);
const char* LayerTypeAsString() const override;
@@ -63,7 +67,7 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl {
scoped_refptr<media::VideoFrame> frame_;
- media::VideoRotation video_rotation_;
+ media::VideoTransformation video_transform_;
std::unique_ptr<media::VideoResourceUpdater> updater_;
};
diff --git a/chromium/cc/metrics/average_lag_tracker.cc b/chromium/cc/metrics/average_lag_tracker.cc
index 05e7e41c3a1..3efacd5ed25 100644
--- a/chromium/cc/metrics/average_lag_tracker.cc
+++ b/chromium/cc/metrics/average_lag_tracker.cc
@@ -11,8 +11,7 @@
namespace cc {
-AverageLagTracker::AverageLagTracker(FinishTimeType finish_time_type)
- : finish_time_type_(finish_time_type) {}
+AverageLagTracker::AverageLagTracker() = default;
AverageLagTracker::~AverageLagTracker() = default;
void AverageLagTracker::AddScrollEventInFrame(const EventInfo& event_info) {
@@ -28,9 +27,7 @@ void AverageLagTracker::AddScrollEventInFrame(const EventInfo& event_info) {
}
std::string AverageLagTracker::GetAverageLagMetricName(EventType event) const {
- std::string metric_name = finish_time_type_ == FinishTimeType::GpuSwapBegin
- ? "AverageLag"
- : "AverageLagPresentation";
+ std::string metric_name = "AverageLagPresentation";
std::string event_name =
event == EventType::ScrollBegin ? "ScrollBegin" : "ScrollUpdate";
@@ -191,30 +188,52 @@ void AverageLagTracker::CalculateAndReportAverageLagUma(bool send_anyway) {
const float time_delta =
(frame_lag.frame_time - last_reported_time_).InMillisecondsF();
- const float scaled_lag = accumulated_lag_ / time_delta;
+ const float scaled_lag_with_prediction = accumulated_lag_ / time_delta;
+ const float scaled_lag_no_prediction =
+ accumulated_lag_no_prediction_ / time_delta;
+
base::UmaHistogramCounts1000(GetAverageLagMetricName(event_type),
- scaled_lag);
+ scaled_lag_with_prediction);
+ base::UmaHistogramCounts1000(
+ base::JoinString({GetAverageLagMetricName(event_type), "NoPrediction"},
+ "."),
+ scaled_lag_with_prediction);
+
+ const float lag_improvement =
+ scaled_lag_no_prediction - scaled_lag_with_prediction;
- const float prediction_effect =
- (accumulated_lag_no_prediction_ - accumulated_lag_) / time_delta;
// Log positive and negative prediction effects. ScrollBegin currently
// doesn't take prediction into account so don't log for it.
// Positive effect means that the prediction reduced the perceived lag,
// where negative means prediction made lag worse (most likely due to
// misprediction).
if (event_type == EventType::ScrollUpdate) {
- if (prediction_effect >= 0.f) {
+ if (lag_improvement >= 0.f) {
base::UmaHistogramCounts1000(
base::JoinString(
{GetAverageLagMetricName(event_type), "PredictionPositive"},
"."),
- prediction_effect);
+ lag_improvement);
} else {
base::UmaHistogramCounts1000(
base::JoinString(
{GetAverageLagMetricName(event_type), "PredictionNegative"},
"."),
- -prediction_effect);
+ -lag_improvement);
+ }
+
+ if (scaled_lag_no_prediction > 0) {
+ // How much of the original lag wasn't removed by prediction.
+ float remaining_lag_ratio =
+ scaled_lag_with_prediction / scaled_lag_no_prediction;
+
+ // Using custom bucket count for high precision on values in (0, 100).
+ // With 100 buckets, (0, 100) is mapped into 60 buckets.
+ base::UmaHistogramCustomCounts(
+ base::JoinString(
+ {GetAverageLagMetricName(event_type), "RemainingLagPercentage"},
+ "."),
+ 100 * remaining_lag_ratio, 1, 500, 100);
}
}
accumulated_lag_ = 0;
diff --git a/chromium/cc/metrics/average_lag_tracker.h b/chromium/cc/metrics/average_lag_tracker.h
index 3877a773eff..2a94b97163c 100644
--- a/chromium/cc/metrics/average_lag_tracker.h
+++ b/chromium/cc/metrics/average_lag_tracker.h
@@ -18,7 +18,6 @@ namespace cc {
// https://docs.google.com/document/d/1e8NuzPblIv2B9bz01oSj40rmlse7_PHq5oFS3lqz6N4/
class CC_EXPORT AverageLagTracker {
public:
- enum class FinishTimeType { GpuSwapBegin, PresentationFeedback };
enum class EventType { ScrollBegin, ScrollUpdate };
struct EventInfo {
@@ -48,7 +47,7 @@ class CC_EXPORT AverageLagTracker {
EventType event_type;
};
- explicit AverageLagTracker(FinishTimeType);
+ AverageLagTracker();
~AverageLagTracker();
// Disallow copy and assign.
@@ -107,10 +106,6 @@ class CC_EXPORT AverageLagTracker {
float LagForUnfinishedFrame(float rendered_accumulated_delta);
- // Time in the frame lifecycle that EventInfo::finish_timestamp represents
- // and defines which metric is tracked by this AverageLagTracker.
- const FinishTimeType finish_time_type_;
-
std::deque<LagAreaInFrame> frame_lag_infos_;
// Last scroll event's timestamp in the sequence, reset on ScrollBegin.
diff --git a/chromium/cc/metrics/average_lag_tracker_unittest.cc b/chromium/cc/metrics/average_lag_tracker_unittest.cc
index d836f75c759..9f011221b02 100644
--- a/chromium/cc/metrics/average_lag_tracker_unittest.cc
+++ b/chromium/cc/metrics/average_lag_tracker_unittest.cc
@@ -27,10 +27,7 @@ class AverageLagTrackerTest : public testing::Test {
const base::HistogramTester& histogram_tester() { return *histogram_tester_; }
void SetUp() override {
- average_lag_tracker_gpu_swap_ = std::make_unique<AverageLagTracker>(
- AverageLagTracker::FinishTimeType::GpuSwapBegin);
- average_lag_tracker_presentation_ = std::make_unique<AverageLagTracker>(
- AverageLagTracker::FinishTimeType::PresentationFeedback);
+ average_lag_tracker_ = std::make_unique<AverageLagTracker>();
}
void SyntheticTouchScrollBegin(base::TimeTicks event_time,
@@ -41,11 +38,7 @@ class AverageLagTrackerTest : public testing::Test {
0, delta, predicted_delta != 0 ? predicted_delta : delta, event_time,
AverageLagTracker::EventType::ScrollBegin);
event_info.finish_timestamp = frame_time;
-
- // Always add the events to both and test if they have the same behavior
- // regardless of the metrics names.
- average_lag_tracker_gpu_swap_->AddScrollEventInFrame(event_info);
- average_lag_tracker_presentation_->AddScrollEventInFrame(event_info);
+ average_lag_tracker_->AddScrollEventInFrame(event_info);
}
void SyntheticTouchScrollUpdate(base::TimeTicks event_time,
@@ -56,48 +49,46 @@ class AverageLagTrackerTest : public testing::Test {
0, delta, predicted_delta != 0 ? predicted_delta : delta, event_time,
AverageLagTracker::EventType::ScrollUpdate);
event_info.finish_timestamp = frame_time;
-
- average_lag_tracker_gpu_swap_->AddScrollEventInFrame(event_info);
- average_lag_tracker_presentation_->AddScrollEventInFrame(event_info);
+ average_lag_tracker_->AddScrollEventInFrame(event_info);
}
void CheckScrollBeginHistograms(int bucket_value, int count) {
EXPECT_THAT(histogram_tester().GetAllSamples(
- "Event.Latency.ScrollBegin.Touch.AverageLag"),
- ElementsAre(Bucket(bucket_value, count)));
- EXPECT_THAT(histogram_tester().GetAllSamples(
"Event.Latency.ScrollBegin.Touch.AverageLagPresentation"),
ElementsAre(Bucket(bucket_value, count)));
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Event.Latency.ScrollBegin.Touch."
+ "AverageLagPresentation.NoPrediction"),
+ ElementsAre(Bucket(bucket_value, count)));
}
void CheckScrollUpdateHistograms(int bucket_value, int count) {
EXPECT_THAT(histogram_tester().GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag"),
- ElementsAre(Bucket(bucket_value, count)));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
"Event.Latency.ScrollUpdate.Touch.AverageLagPresentation"),
ElementsAre(Bucket(bucket_value, count)));
- }
- void CheckPredictionPositiveHistograms(int bucket_value, int count) {
EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive"),
+ histogram_tester().GetAllSamples("Event.Latency.ScrollUpdate.Touch."
+ "AverageLagPresentation.NoPrediction"),
ElementsAre(Bucket(bucket_value, count)));
+ }
+ void CheckPredictionPositiveHistograms(int bucket_value, int count) {
EXPECT_THAT(histogram_tester().GetAllSamples(
"Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
"PredictionPositive"),
ElementsAre(Bucket(bucket_value, count)));
}
- void CheckPredictionNegativeHistograms(int bucket_value, int count) {
- EXPECT_THAT(
- histogram_tester().GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative"),
- ElementsAre(Bucket(bucket_value, count)));
+ void CheckRemainingLagPercentageHistograms(int bucket_value, int count) {
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
+ "RemainingLagPercentage"),
+ ElementsAre(Bucket(bucket_value, count)));
+ }
+ void CheckPredictionNegativeHistograms(int bucket_value, int count) {
EXPECT_THAT(histogram_tester().GetAllSamples(
"Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
"PredictionNegative"),
@@ -106,16 +97,14 @@ class AverageLagTrackerTest : public testing::Test {
void CheckScrollUpdateHistogramsTotalCount(int count) {
histogram_tester().ExpectTotalCount(
- "Event.Latency.ScrollUpdate.Touch.AverageLag", count);
- histogram_tester().ExpectTotalCount(
"Event.Latency.ScrollUpdate.Touch.AverageLagPresentation", count);
+ histogram_tester().ExpectTotalCount(
+ "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation.NoPrediction",
+ count);
}
void CheckPredictionPositiveHistogramsTotalCount(int count) {
histogram_tester().ExpectTotalCount(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive",
- count);
- histogram_tester().ExpectTotalCount(
"Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
"PredictionPositive",
count);
@@ -123,17 +112,13 @@ class AverageLagTrackerTest : public testing::Test {
void CheckPredictionNegativeHistogramsTotalCount(int count) {
histogram_tester().ExpectTotalCount(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative",
- count);
- histogram_tester().ExpectTotalCount(
"Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
"PredictionNegative",
count);
}
protected:
- std::unique_ptr<AverageLagTracker> average_lag_tracker_gpu_swap_;
- std::unique_ptr<AverageLagTracker> average_lag_tracker_presentation_;
+ std::unique_ptr<AverageLagTracker> average_lag_tracker_;
std::unique_ptr<base::HistogramTester> histogram_tester_;
};
@@ -190,6 +175,7 @@ TEST_F(AverageLagTrackerTest, OneSecondInterval) {
CheckScrollUpdateHistograms(9, 1);
CheckPredictionPositiveHistograms(0, 1);
CheckPredictionNegativeHistogramsTotalCount(0);
+ CheckRemainingLagPercentageHistograms(100 - 0, 1);
ResetHistograms();
@@ -202,6 +188,7 @@ TEST_F(AverageLagTrackerTest, OneSecondInterval) {
CheckScrollUpdateHistograms(8, 1);
CheckPredictionPositiveHistograms(0, 1);
CheckPredictionNegativeHistogramsTotalCount(0);
+ CheckRemainingLagPercentageHistograms(100 - 0, 1);
}
// Test the case that event's frame swap time is later than next event's
@@ -376,6 +363,7 @@ TEST_F(AverageLagTrackerTest, ScrollPrediction) {
CheckScrollUpdateHistograms(4, 1);
CheckPredictionPositiveHistograms(5, 1);
CheckPredictionNegativeHistogramsTotalCount(0);
+ CheckRemainingLagPercentageHistograms(100 * 4.375 / 9.375, 1);
}
// Test AverageLag with imperfect scroll prediction.
@@ -416,6 +404,7 @@ TEST_F(AverageLagTrackerTest, ImperfectScrollPrediction) {
// Positive effect of prediction = 4.3px
CheckPredictionPositiveHistograms(4, 1);
CheckPredictionNegativeHistogramsTotalCount(0);
+ CheckRemainingLagPercentageHistograms(100 * 5.075 / 9.375, 1);
}
TEST_F(AverageLagTrackerTest, NegativePredictionEffect) {
@@ -455,6 +444,9 @@ TEST_F(AverageLagTrackerTest, NegativePredictionEffect) {
// Negative effect of prediction = 11.25
CheckPredictionPositiveHistogramsTotalCount(0);
CheckPredictionNegativeHistograms(11, 1);
+
+ // 100 * 20.625 / 9.375 = 220 is logged into bucket 219.
+ CheckRemainingLagPercentageHistograms(219, 1);
}
TEST_F(AverageLagTrackerTest, NoPredictionEffect) {
diff --git a/chromium/cc/metrics/average_lag_tracking_manager.cc b/chromium/cc/metrics/average_lag_tracking_manager.cc
index efca9693ca7..9dc2c4e8027 100644
--- a/chromium/cc/metrics/average_lag_tracking_manager.cc
+++ b/chromium/cc/metrics/average_lag_tracking_manager.cc
@@ -88,11 +88,8 @@ void AverageLagTrackingManager::DidPresentCompositorFrame(
});
for (AverageLagTracker::EventInfo info : infos) {
- info.finish_timestamp = frame_details.swap_timings.swap_start;
- lag_tracker_gpu_swap_.AddScrollEventInFrame(info);
-
info.finish_timestamp = frame_details.presentation_feedback.timestamp;
- lag_tracker_presentation_.AddScrollEventInFrame(info);
+ lag_tracker_.AddScrollEventInFrame(info);
}
}
}
diff --git a/chromium/cc/metrics/average_lag_tracking_manager.h b/chromium/cc/metrics/average_lag_tracking_manager.h
index d694fe789ad..ba2e34f9b4b 100644
--- a/chromium/cc/metrics/average_lag_tracking_manager.h
+++ b/chromium/cc/metrics/average_lag_tracking_manager.h
@@ -48,17 +48,10 @@ class CC_EXPORT AverageLagTrackingManager {
void Clear();
private:
- // TODO(https://crbug.com/1101005): Remove GpuSwap implementation after M86.
- // Tracker for the AverageLag metrics that uses the gpu swap begin timing as
- // an approximation for the time the users sees the frame on the screen.
- AverageLagTracker lag_tracker_gpu_swap_{
- AverageLagTracker::FinishTimeType::GpuSwapBegin};
-
// Tracker for the AverageLagPresentation metrics that uses the presentation
// feedback time as an approximation for the time the users sees the frame on
// the screen.
- AverageLagTracker lag_tracker_presentation_{
- AverageLagTracker::FinishTimeType::PresentationFeedback};
+ AverageLagTracker lag_tracker_;
// List of events (vector) per frame (uint32_t |frame_token|) to submit to the
// lag trackers when DidPresentCompositorFrame is called for a |frame_token|.
diff --git a/chromium/cc/metrics/average_lag_tracking_manager_unittest.cc b/chromium/cc/metrics/average_lag_tracking_manager_unittest.cc
index 69931f0a010..10b296f2032 100644
--- a/chromium/cc/metrics/average_lag_tracking_manager_unittest.cc
+++ b/chromium/cc/metrics/average_lag_tracking_manager_unittest.cc
@@ -157,14 +157,6 @@ TEST_F(AverageLagTrackingManagerTest, OneSecondInterval) {
EXPECT_EQ(gpu_swap_time, MillisecondsToTimeTicks(1030));
EXPECT_EQ(presentation_time, MillisecondsToTimeTicks(1033));
- // ScrollBegin AverageLag are the area between the event original component
- // (time=15ms, delta=10px) to the gpu swap time (time=20ms, expect finger
- // position at delta=15px). The AverageLag scaled to 1 second is
- // (0.5*(10px+15px)*5ms)/5ms = 12.5px.
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollBegin.Touch.AverageLag"),
- ElementsAre(Bucket(12, 1)));
-
// Using the presentation time (25ms) instead of gpu swap (20ms) the expected
// finger position is delta = 16px. Then (0.5*(10px+18px)*10ms)/10ms = 14px.
// UmaHistogramCounts1000's binning will round it to 12.
@@ -172,21 +164,6 @@ TEST_F(AverageLagTrackingManagerTest, OneSecondInterval) {
"Event.Latency.ScrollBegin.Touch.AverageLagPresentation"),
ElementsAre(Bucket(14, 1)));
- // This ScrollUpdate AverageLag are calculated as the finger uniformly scroll
- // 10px each frame. For scroll up/down frame, the Lag at the last frame swap
- // is 5px, and Lag at this frame swap is 15px. For the one changing direction,
- // the Lag is from 5 to 10 and down to 5 again. So total LagArea is 99 * 100,
- // plus 75. the AverageLag in 1 second is 9.975px.
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag"),
- ElementsAre(Bucket(9, 1)));
- EXPECT_THAT(
- histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive"),
- ElementsAre(Bucket(0, 1)));
- histogram_tester_->ExpectTotalCount(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative", 0);
-
// As the presentation times are at 80% of the gap between 2 scroll events,
// the Lag Area between 2 frames is define by the trapezoids: (time=event-2,
// delta=8px), (time=event, delta=10px), (time=event+8, delta=18). This makes
@@ -209,28 +186,6 @@ TEST_F(AverageLagTrackingManagerTest, OneSecondInterval) {
0);
ResetHistograms();
-
- // Send another ScrollBegin to end the unfinished ScrollUpdate report.
- event_time += base::TimeDelta::FromMilliseconds(10);
- gpu_swap_time += base::TimeDelta::FromMilliseconds(10);
- presentation_time += base::TimeDelta::FromMilliseconds(10);
- evt = PrepareScrollEvent(AverageLagTracker::EventType::ScrollBegin,
- event_time, 1, scroll_delta);
- average_lag_tracking_manager_.CollectScrollEventsFromFrame(
- frame_id, std::vector<ui::LatencyInfo>{evt});
- average_lag_tracking_manager_.DidPresentCompositorFrame(
- frame_id, PrepareFrameDetails(gpu_swap_time, presentation_time));
-
- // The last ScrollUpdate's lag is 8.75px and truncated to 8.
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag"),
- ElementsAre(Bucket(8, 1)));
- EXPECT_THAT(
- histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive"),
- ElementsAre(Bucket(0, 1)));
- histogram_tester_->ExpectTotalCount(
- "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative", 0);
}
// This test creates 3 frames in order to check the submission of ScrollBegin
@@ -248,13 +203,6 @@ TEST_F(AverageLagTrackingManagerTest, MultipleEventsInSameFrame) {
}
// As the first frame is the ScrollBegin frame, the average lag is, using the
- // gpu swap time, 0.5*(10 + 40) * 30 / 30 = 25. But UmaHistogramCounts1000's
- // binning will round it to 23.
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollBegin.Touch.AverageLag"),
- ElementsAre(Bucket(23, 1)));
-
- // As the first frame is the ScrollBegin frame, the average lag is, using the
// presentation time, 0.5*(10 + 50) * 40 / 40 = 30. But
// UmaHistogramCounts1000's binning will round it to 29.
EXPECT_THAT(histogram_tester_->GetAllSamples(
@@ -264,16 +212,6 @@ TEST_F(AverageLagTrackingManagerTest, MultipleEventsInSameFrame) {
// Only the ScrollUpdate events from frame 2 are sent (as the frame 3 is
// waiting for the next frame for sumission).
// As there is a scroll update right at the same time as the frame submission,
- // using gpu swap time, frame 2 starts with 0 lag at 0.4s and finishes with
- // 100 at 1.4, thus: 0.5 * (0 + 100) / 2 = 50. It gets into the same bin as
- // 47.
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "Event.Latency.ScrollUpdate.Touch.AverageLag"),
- ElementsAre(Bucket(47, 1)));
-
- // Only the ScrollUpdate events from frame 2 are sent (as the frame 3 is
- // waiting for the next frame for sumission).
- // As there is a scroll update right at the same time as the frame submission,
// using presentation time, frame 2 starts with 10 lag at 0.5s and finishes
// with 110 at 1.5, thus: 0.5 * (10 + 110) / 2 = 60.
EXPECT_THAT(histogram_tester_->GetAllSamples(
diff --git a/chromium/cc/metrics/begin_main_frame_metrics.cc b/chromium/cc/metrics/begin_main_frame_metrics.cc
index 04b6d8bbf3d..effcada55c9 100644
--- a/chromium/cc/metrics/begin_main_frame_metrics.cc
+++ b/chromium/cc/metrics/begin_main_frame_metrics.cc
@@ -11,4 +11,7 @@ BeginMainFrameMetrics::BeginMainFrameMetrics() = default;
BeginMainFrameMetrics::BeginMainFrameMetrics(
const BeginMainFrameMetrics& other) = default;
+BeginMainFrameMetrics& BeginMainFrameMetrics::operator=(
+ const BeginMainFrameMetrics& other) = default;
+
} // namespace cc
diff --git a/chromium/cc/metrics/begin_main_frame_metrics.h b/chromium/cc/metrics/begin_main_frame_metrics.h
index 1f26384fc21..9514e622bd2 100644
--- a/chromium/cc/metrics/begin_main_frame_metrics.h
+++ b/chromium/cc/metrics/begin_main_frame_metrics.h
@@ -33,6 +33,7 @@ struct CC_EXPORT BeginMainFrameMetrics {
BeginMainFrameMetrics();
BeginMainFrameMetrics(const BeginMainFrameMetrics& other);
+ BeginMainFrameMetrics& operator=(const BeginMainFrameMetrics& other);
};
} // namespace cc
diff --git a/chromium/cc/metrics/compositor_frame_reporter.cc b/chromium/cc/metrics/compositor_frame_reporter.cc
index 7d2bd0fa57e..375696fa2bf 100644
--- a/chromium/cc/metrics/compositor_frame_reporter.cc
+++ b/chromium/cc/metrics/compositor_frame_reporter.cc
@@ -9,8 +9,8 @@
#include <string>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
@@ -147,7 +147,6 @@ constexpr const char* GetEventLatencyDispatchToCompositorBreakdownName(
NOTREACHED();
return nullptr;
}
- break;
case EventMetrics::DispatchStage::kRendererMainFinished:
switch (compositor_stage) {
case CompositorFrameReporter::StageType::
@@ -171,7 +170,6 @@ constexpr const char* GetEventLatencyDispatchToCompositorBreakdownName(
NOTREACHED();
return nullptr;
}
- break;
default:
NOTREACHED();
return nullptr;
@@ -1044,8 +1042,8 @@ void CompositorFrameReporter::ReportCompositorLatencyTraceEvents() const {
return;
if (IsDroppedFrameAffectingSmoothness()) {
- devtools_instrumentation::DidDropSmoothnessFrame(layer_tree_host_id_,
- args_.frame_time);
+ devtools_instrumentation::DidDropSmoothnessFrame(
+ layer_tree_host_id_, args_.frame_time, args_.frame_id.sequence_number);
}
const auto trace_track =
@@ -1274,6 +1272,12 @@ bool CompositorFrameReporter::IsDroppedFrameAffectingSmoothness() const {
return smooth_thread_ != SmoothThread::kSmoothNone;
}
+ // If the frame includes new main-thread update, even if it's for an earlier
+ // begin-frame, then do not count it as a dropped frame affecting smoothness.
+ if (is_accompanied_by_main_thread_update_) {
+ return false;
+ }
+
// If the frame was shown, but included only partial updates, then it hurt
// smoothness only if the main-thread is affecting smoothness (e.g. running an
// animation, or scroll etc.).
diff --git a/chromium/cc/metrics/compositor_frame_reporter.h b/chromium/cc/metrics/compositor_frame_reporter.h
index 8651f314175..188de0a9e9f 100644
--- a/chromium/cc/metrics/compositor_frame_reporter.h
+++ b/chromium/cc/metrics/compositor_frame_reporter.h
@@ -256,7 +256,9 @@ class CC_EXPORT CompositorFrameReporter {
void AddEventsMetrics(EventMetrics::List events_metrics);
EventMetrics::List TakeEventsMetrics();
- int stage_history_size_for_testing() const { return stage_history_.size(); }
+ size_t stage_history_size_for_testing() const {
+ return stage_history_.size();
+ }
void OnFinishImplFrame(base::TimeTicks timestamp);
void OnAbortBeginMainFrame(base::TimeTicks timestamp);
@@ -302,6 +304,12 @@ class CC_EXPORT CompositorFrameReporter {
return owned_partial_update_dependents_.size();
}
+ void set_is_accompanied_by_main_thread_update(
+ bool is_accompanied_by_main_thread_update) {
+ is_accompanied_by_main_thread_update_ =
+ is_accompanied_by_main_thread_update;
+ }
+
const viz::BeginFrameId& frame_id() const { return args_.frame_id; }
// Adopts |cloned_reporter|, i.e. keeps |cloned_reporter| alive until after
@@ -414,6 +422,9 @@ class CC_EXPORT CompositorFrameReporter {
DroppedFrameCounter* dropped_frame_counter_ = nullptr;
bool has_partial_update_ = false;
+ // If the submitted frame has update from main thread
+ bool is_accompanied_by_main_thread_update_ = false;
+
const SmoothThread smooth_thread_;
const int layer_tree_host_id_;
diff --git a/chromium/cc/metrics/compositor_frame_reporter_unittest.cc b/chromium/cc/metrics/compositor_frame_reporter_unittest.cc
index 63e046a5f00..0f885408da1 100644
--- a/chromium/cc/metrics/compositor_frame_reporter_unittest.cc
+++ b/chromium/cc/metrics/compositor_frame_reporter_unittest.cc
@@ -74,13 +74,12 @@ class CompositorFrameReporterTest : public testing::Test {
std::unique_ptr<EventMetrics> CreateEventMetrics(
ui::EventType type,
- absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type) {
+ absl::optional<EventMetrics::ScrollParams> scroll_params =
+ absl::nullopt) {
const base::TimeTicks event_time = AdvanceNowByMs(3);
AdvanceNowByMs(3);
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
- type, scroll_update_type, scroll_input_type, event_time,
- &test_tick_clock_);
+ type, scroll_params, event_time, &test_tick_clock_);
if (metrics) {
AdvanceNowByMs(3);
metrics->SetDispatchStageTimestamp(
@@ -133,30 +132,30 @@ TEST_F(CompositorFrameReporterTest, MainFrameAbortedReportingTest) {
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
Now());
- EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(0u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now());
- EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(1u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
- EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(2u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::
kSubmitCompositorFrameToPresentationCompositorFrame,
Now());
- EXPECT_EQ(3, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(3u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame, Now());
- EXPECT_EQ(4, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(4u, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount(
@@ -178,18 +177,18 @@ TEST_F(CompositorFrameReporterTest, ReplacedByNewReporterReportingTest) {
pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
Now());
- EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(0u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndCommitToActivation, Now());
- EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(1u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(2);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kReplacedByNewReporter,
Now());
- EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(2u, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
@@ -202,18 +201,18 @@ TEST_F(CompositorFrameReporterTest, SubmittedFrameReportingTest) {
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kActivation, Now());
- EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(0u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
- EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(1u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(2);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame, Now());
- EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(2u, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
@@ -238,18 +237,18 @@ TEST_F(CompositorFrameReporterTest, SubmittedDroppedFrameReportingTest) {
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now());
- EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(0u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
Now());
- EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(1u, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(2);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kDidNotPresentFrame,
Now());
- EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
+ EXPECT_EQ(2u, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount(
@@ -277,9 +276,9 @@ TEST_F(CompositorFrameReporterTest,
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_TOUCH_PRESSED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
+ CreateEventMetrics(ui::ET_TOUCH_PRESSED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
@@ -329,17 +328,23 @@ TEST_F(CompositorFrameReporterTest,
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.TouchPressed.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.TouchMoved.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.TouchMoved.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
@@ -353,15 +358,24 @@ TEST_F(CompositorFrameReporterTest,
EventLatencyScrollTotalForPresentedFrameReported) {
base::HistogramTester histogram_tester;
+ const bool kIsInertial = true;
+ const bool kIsNotInertial = false;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN, absl::nullopt,
- ui::ScrollInputType::kWheel),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN,
+ EventMetrics::ScrollParams(ui::ScrollInputType::kWheel,
+ kIsNotInertial)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kStarted,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kStarted)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kContinued,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
@@ -406,7 +420,10 @@ TEST_F(CompositorFrameReporterTest,
1},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 1},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin", 1},
- {"EventLatency.TotalLatency", 3},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatency", 1},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
+ 1},
+ {"EventLatency.TotalLatency", 4},
};
for (const auto& expected_count : expected_counts) {
histogram_tester.ExpectTotalCount(expected_count.name,
@@ -421,17 +438,29 @@ TEST_F(CompositorFrameReporterTest,
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.GestureScrollBegin.Wheel.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapBegin",
- (swap_begin_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[0]).InMicroseconds())},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
- (swap_begin_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[1]).InMicroseconds())},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
- (swap_begin_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[2]).InMicroseconds())},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatency",
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[3]).InMicroseconds())},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[3]).InMicroseconds())},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
@@ -446,9 +475,9 @@ TEST_F(CompositorFrameReporterTest,
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_TOUCH_PRESSED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
+ CreateEventMetrics(ui::ET_TOUCH_PRESSED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller.cc b/chromium/cc/metrics/compositor_frame_reporting_controller.cc
index 5cd49b99786..8ccda7ea94e 100644
--- a/chromium/cc/metrics/compositor_frame_reporting_controller.cc
+++ b/chromium/cc/metrics/compositor_frame_reporting_controller.cc
@@ -296,6 +296,8 @@ void CompositorFrameReportingController::DidSubmitCompositorFrame(
impl_reporter->AddEventsMetrics(
std::move(events_metrics.impl_event_metrics));
impl_reporter->set_has_missing_content(has_missing_content);
+ impl_reporter->set_is_accompanied_by_main_thread_update(
+ is_activated_frame_new);
submitted_compositor_frames_.emplace_back(frame_token,
std::move(impl_reporter));
}
diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc
index 351e0e236f3..30cf759aa00 100644
--- a/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc
+++ b/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -239,13 +239,12 @@ class CompositorFrameReportingControllerTest : public testing::Test {
std::unique_ptr<EventMetrics> CreateEventMetrics(
ui::EventType type,
- absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type) {
+ absl::optional<EventMetrics::ScrollParams> scroll_params =
+ absl::nullopt) {
const base::TimeTicks event_time = AdvanceNowByMs(10);
AdvanceNowByMs(10);
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
- type, scroll_update_type, scroll_input_type, event_time,
- &test_tick_clock_);
+ type, scroll_params, event_time, &test_tick_clock_);
if (metrics) {
AdvanceNowByMs(10);
metrics->SetDispatchStageTimestamp(
@@ -1123,9 +1122,9 @@ TEST_F(CompositorFrameReportingControllerTest,
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_TOUCH_PRESSED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
+ CreateEventMetrics(ui::ET_TOUCH_PRESSED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
@@ -1162,17 +1161,23 @@ TEST_F(CompositorFrameReportingControllerTest,
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.TouchPressed.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.TouchMoved.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.TouchMoved.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
@@ -1186,15 +1191,24 @@ TEST_F(CompositorFrameReportingControllerTest,
EventLatencyScrollTotalForPresentedFrameReported) {
base::HistogramTester histogram_tester;
+ const bool kIsInertial = true;
+ const bool kIsNotInertial = false;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN, absl::nullopt,
- ui::ScrollInputType::kWheel),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN,
+ EventMetrics::ScrollParams(ui::ScrollInputType::kWheel,
+ kIsNotInertial)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kStarted,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kStarted)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kContinued,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
@@ -1227,7 +1241,10 @@ TEST_F(CompositorFrameReportingControllerTest,
1},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 1},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin", 1},
- {"EventLatency.TotalLatency", 3},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatency", 1},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
+ 1},
+ {"EventLatency.TotalLatency", 4},
};
for (const auto& expected_count : expected_counts) {
histogram_tester.ExpectTotalCount(expected_count.name,
@@ -1242,17 +1259,29 @@ TEST_F(CompositorFrameReportingControllerTest,
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.GestureScrollBegin.Wheel.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapBegin",
- (swap_begin_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[0]).InMicroseconds())},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
- (swap_begin_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[1]).InMicroseconds())},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
- (swap_begin_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[2]).InMicroseconds())},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatency",
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[3]).InMicroseconds())},
+ {"EventLatency.InertialGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
+ static_cast<base::HistogramBase::Sample>(
+ (swap_begin_time - event_times[3]).InMicroseconds())},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
@@ -1267,9 +1296,9 @@ TEST_F(CompositorFrameReportingControllerTest,
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_TOUCH_PRESSED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
- CreateEventMetrics(ui::ET_TOUCH_MOVED, absl::nullopt, absl::nullopt),
+ CreateEventMetrics(ui::ET_TOUCH_PRESSED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
+ CreateEventMetrics(ui::ET_TOUCH_MOVED),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
@@ -1311,17 +1340,23 @@ TEST_F(CompositorFrameReportingControllerTest,
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.TouchPressed.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.TouchMoved.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.TouchMoved.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[0]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[0]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[1]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[1]).InMicroseconds())},
{"EventLatency.TotalLatency",
- (presentation_time - event_times[2]).InMicroseconds()},
+ static_cast<base::HistogramBase::Sample>(
+ (presentation_time - event_times[2]).InMicroseconds())},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
@@ -1365,7 +1400,7 @@ TEST_F(CompositorFrameReportingControllerTest,
// R2C has been presented, but it is blocked on R2M to know whether R2C
// contains partial update, or complete updates. So it is kept alive.
EXPECT_EQ(2u, dropped_counter_.total_frames());
- EXPECT_EQ(1u, dropped_counter_.total_main_dropped());
+ EXPECT_EQ(1u, dropped_counter_.total_partial());
EXPECT_EQ(1u, reporting_controller_.GetBlockingReportersCount());
EXPECT_EQ(1u, reporting_controller_.GetBlockedReportersCount());
@@ -1402,7 +1437,7 @@ TEST_F(CompositorFrameReportingControllerTest,
// At this point no frame has been completed, yet.
EXPECT_EQ(0u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// Start yet another frame that has impl-thread update and submit it, but with
// failed presentation. The reporter for this frame should become dependent of
@@ -1427,7 +1462,7 @@ TEST_F(CompositorFrameReportingControllerTest,
// At this point 1 frame has been completed and it's a dropped frame.
EXPECT_EQ(1u, dropped_counter_.total_frames());
- EXPECT_EQ(1u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(1u, dropped_counter_.total_dropped());
reporting_controller_.ResetReporters();
reporting_controller_.SetDroppedFrameCounter(nullptr);
@@ -1438,13 +1473,13 @@ TEST_F(CompositorFrameReportingControllerTest,
// Submit and present two compositor frames.
SimulatePresentCompositorFrame();
EXPECT_EQ(1u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
SimulatePresentCompositorFrame();
EXPECT_EQ(2u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// Now skip over a few frames, and submit + present another frame.
const uint32_t kSkipFrames = 5;
@@ -1452,8 +1487,8 @@ TEST_F(CompositorFrameReportingControllerTest,
IncrementCurrentId();
SimulatePresentCompositorFrame();
EXPECT_EQ(3u + kSkipFrames, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(kSkipFrames, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(kSkipFrames, dropped_counter_.total_dropped());
// Stop requesting frames, skip over a few frames, and submit + present
// another frame. There should no new dropped frames.
@@ -1463,8 +1498,8 @@ TEST_F(CompositorFrameReportingControllerTest,
IncrementCurrentId();
SimulatePresentCompositorFrame();
EXPECT_EQ(1u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
reporting_controller_.ResetReporters();
reporting_controller_.SetDroppedFrameCounter(nullptr);
@@ -1475,13 +1510,13 @@ TEST_F(CompositorFrameReportingControllerTest,
// Submit and present two compositor frames.
SimulatePresentCompositorFrame();
EXPECT_EQ(1u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
SimulatePresentCompositorFrame();
EXPECT_EQ(2u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// Now skip over a 101 frames (It should be ignored as it more than 100)
// and submit + present another frame.
@@ -1491,8 +1526,8 @@ TEST_F(CompositorFrameReportingControllerTest,
IncrementCurrentId();
SimulatePresentCompositorFrame();
EXPECT_EQ(3u + kSkipFramesActual, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(kSkipFramesActual, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(kSkipFramesActual, dropped_counter_.total_dropped());
}
TEST_F(CompositorFrameReportingControllerTest,
@@ -1512,7 +1547,7 @@ TEST_F(CompositorFrameReportingControllerTest,
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
reporting_controller_.DidNotProduceFrame(args_1.frame_id,
FrameSkippedReason::kWaitingOnMain);
@@ -1530,23 +1565,23 @@ TEST_F(CompositorFrameReportingControllerTest,
EXPECT_EQ(3u, reporting_controller_.GetBlockedReportersCount());
// All frames are waiting for the main frame
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
EXPECT_EQ(0u, dropped_counter_.total_frames());
reporting_controller_.BeginMainFrameAborted(
args_1.frame_id, CommitEarlyOutReason::FINISHED_NO_UPDATES);
reporting_controller_.DidNotProduceFrame(args_1.frame_id,
FrameSkippedReason::kNoDamage);
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// New reporters replace older reporters
reporting_controller_.WillBeginImplFrame(args_4);
reporting_controller_.WillBeginMainFrame(args_4);
EXPECT_EQ(4u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
}
TEST_F(CompositorFrameReportingControllerTest,
@@ -1559,13 +1594,13 @@ TEST_F(CompositorFrameReportingControllerTest,
// Submit and present two compositor frames.
SimulatePresentCompositorFrame();
EXPECT_EQ(1u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
SimulatePresentCompositorFrame();
EXPECT_EQ(2u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// Now skip over a few frames, and submit + present another frame.
const uint32_t kSkipFrames_1 = 5;
@@ -1573,8 +1608,8 @@ TEST_F(CompositorFrameReportingControllerTest,
IncrementCurrentId();
SimulatePresentCompositorFrame();
EXPECT_EQ(3u + kSkipFrames_1, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(kSkipFrames_1, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(kSkipFrames_1, dropped_counter_.total_dropped());
EXPECT_EQ(kSkipFrames_1, dropped_counter_.total_smoothness_dropped());
// Now skip over a few frames which are not affecting smoothness.
@@ -1586,9 +1621,8 @@ TEST_F(CompositorFrameReportingControllerTest,
SimulatePresentCompositorFrame(); // Present another frame.
EXPECT_EQ(4u + kSkipFrames_1 + kSkipFrames_2,
dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(kSkipFrames_1 + kSkipFrames_2,
- dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(kSkipFrames_1 + kSkipFrames_2, dropped_counter_.total_dropped());
EXPECT_EQ(kSkipFrames_1, dropped_counter_.total_smoothness_dropped());
// Now skip over a few frames more frames which are affecting smoothness.
@@ -1600,9 +1634,9 @@ TEST_F(CompositorFrameReportingControllerTest,
SimulatePresentCompositorFrame(); // Present another frame.
EXPECT_EQ(5u + kSkipFrames_1 + kSkipFrames_2 + kSkipFrames_3,
dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
EXPECT_EQ(kSkipFrames_1 + kSkipFrames_2 + kSkipFrames_3,
- dropped_counter_.total_compositor_dropped());
+ dropped_counter_.total_dropped());
EXPECT_EQ(kSkipFrames_1 + kSkipFrames_3,
dropped_counter_.total_smoothness_dropped());
}
@@ -1612,13 +1646,13 @@ TEST_F(CompositorFrameReportingControllerTest,
// Submit and present two compositor frames.
SimulatePresentCompositorFrame();
EXPECT_EQ(1u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
SimulatePresentCompositorFrame();
EXPECT_EQ(2u, dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// Now skip over a few frames, and submit + present another frame.
const uint32_t kTotalFrames = 5;
@@ -1629,9 +1663,8 @@ TEST_F(CompositorFrameReportingControllerTest,
SimulatePresentCompositorFrame();
EXPECT_EQ(3u + kTotalFrames - kThrottledFrames,
dropped_counter_.total_frames());
- EXPECT_EQ(0u, dropped_counter_.total_main_dropped());
- EXPECT_EQ(kTotalFrames - kThrottledFrames,
- dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_partial());
+ EXPECT_EQ(kTotalFrames - kThrottledFrames, dropped_counter_.total_dropped());
}
TEST_F(CompositorFrameReportingControllerTest,
@@ -1644,7 +1677,7 @@ TEST_F(CompositorFrameReportingControllerTest,
reporting_controller_.BeginMainFrameAborted(
current_id_, CommitEarlyOutReason::FINISHED_NO_UPDATES);
}
- EXPECT_EQ(0u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(0u, dropped_counter_.total_dropped());
// Start a few begin-main-frames, but abort the main-frames due to no damage.
for (int i = 0; i < 5; ++i) {
@@ -1656,7 +1689,7 @@ TEST_F(CompositorFrameReportingControllerTest,
SimulateSubmitCompositorFrame({});
}
SimulatePresentCompositorFrame();
- EXPECT_EQ(5u, dropped_counter_.total_compositor_dropped());
+ EXPECT_EQ(5u, dropped_counter_.total_dropped());
}
// Verifies that presentation feedbacks that arrive out of order are handled
@@ -1680,7 +1713,7 @@ TEST_F(CompositorFrameReportingControllerTest,
gfx::PresentationFeedback::kFailure};
reporting_controller_.DidPresentCompositorFrame(frame_token_2, details_2);
DCHECK_EQ(1u, dropped_counter_.total_frames());
- DCHECK_EQ(1u, dropped_counter_.total_compositor_dropped());
+ DCHECK_EQ(1u, dropped_counter_.total_dropped());
// Send a successful presentation feedback for frame 3. This should drop frame
// 1.
@@ -1688,7 +1721,53 @@ TEST_F(CompositorFrameReportingControllerTest,
details_3.presentation_feedback.timestamp = AdvanceNowByMs(10);
reporting_controller_.DidPresentCompositorFrame(frame_token_3, details_3);
DCHECK_EQ(3u, dropped_counter_.total_frames());
- DCHECK_EQ(2u, dropped_counter_.total_compositor_dropped());
+ DCHECK_EQ(2u, dropped_counter_.total_dropped());
+}
+
+TEST_F(CompositorFrameReportingControllerTest,
+ NewMainThreadUpdateNotReportedAsDropped) {
+ auto thread_type_main = FrameSequenceMetrics::ThreadType::kMain;
+ reporting_controller_.SetThreadAffectsSmoothness(thread_type_main,
+ /*affects_smoothness=*/true);
+ dropped_counter_.OnFcpReceived();
+
+ SimulateBeginMainFrame();
+ reporting_controller_.OnFinishImplFrame(current_id_);
+ reporting_controller_.DidSubmitCompositorFrame(1u, current_id_, {}, {},
+ /*has_missing_content=*/false);
+ viz::FrameTimingDetails details = {};
+ details.presentation_feedback.timestamp = AdvanceNowByMs(10);
+ reporting_controller_.DidPresentCompositorFrame(1u, details);
+ // Starts a new frame and submit it prior to commit
+
+ reporting_controller_.WillCommit();
+ reporting_controller_.DidCommit();
+
+ const auto previous_id = current_id_;
+
+ SimulateBeginMainFrame();
+ reporting_controller_.OnFinishImplFrame(current_id_);
+
+ // Starts a new frame and submit it prior to its commit, but the older frame
+ // has new updates which would be activated and submitted now.
+ reporting_controller_.WillActivate();
+ reporting_controller_.DidActivate();
+
+ reporting_controller_.DidSubmitCompositorFrame(
+ 1u, current_id_, previous_id, {}, /*has_missing_content=*/false);
+ details.presentation_feedback.timestamp = AdvanceNowByMs(10);
+ reporting_controller_.DidPresentCompositorFrame(1u, details);
+
+ reporting_controller_.WillCommit();
+ reporting_controller_.DidCommit();
+
+ SimulatePresentCompositorFrame();
+
+ // There are two frames with partial updates
+ EXPECT_EQ(2u, dropped_counter_.total_partial());
+ // Which one is accompanied with new main thread update so only one affects
+ // smoothness
+ EXPECT_EQ(1u, dropped_counter_.total_smoothness_dropped());
}
} // namespace
diff --git a/chromium/cc/metrics/compositor_timing_history.cc b/chromium/cc/metrics/compositor_timing_history.cc
index e8b1969dc2f..c8c2bb6a766 100644
--- a/chromium/cc/metrics/compositor_timing_history.cc
+++ b/chromium/cc/metrics/compositor_timing_history.cc
@@ -10,9 +10,9 @@
#include <utility>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "cc/debug/rendering_stats_instrumentation.h"
@@ -39,6 +39,9 @@ class CompositorTimingHistory::UMAReporter {
// Only the renderer would get the meaningful data.
virtual void AddDrawIntervalWithCustomPropertyAnimations(
base::TimeDelta duration) = 0;
+
+ virtual void AddImplFrameDeadlineType(
+ CompositorTimingHistory::DeadlineMode deadline_mode) = 0;
};
namespace {
@@ -323,6 +326,12 @@ class RendererUMAReporter : public CompositorTimingHistory::UMAReporter {
UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Renderer.DrawDuration",
duration);
}
+
+ void AddImplFrameDeadlineType(
+ CompositorTimingHistory::DeadlineMode deadline_mode) override {
+ UMA_HISTOGRAM_ENUMERATION("Scheduling.Renderer.DeadlineMode",
+ deadline_mode);
+ }
};
class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter {
@@ -360,6 +369,12 @@ class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter {
UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Browser.DrawDuration",
duration);
}
+
+ void AddImplFrameDeadlineType(
+ CompositorTimingHistory::DeadlineMode deadline_mode) override {
+ // The browser compositor scheduler is synchronous and only has None (or
+ // Blocked as edges cases) for deadline mode.
+ }
};
class NullUMAReporter : public CompositorTimingHistory::UMAReporter {
@@ -375,6 +390,8 @@ class NullUMAReporter : public CompositorTimingHistory::UMAReporter {
base::TimeDelta duration,
TreePriority priority) override {}
void AddDrawDuration(base::TimeDelta duration) override {}
+ void AddImplFrameDeadlineType(
+ CompositorTimingHistory::DeadlineMode deadline_mode) override {}
};
} // namespace
@@ -511,15 +528,6 @@ CompositorTimingHistory::BeginMainFrameQueueToActivateCriticalEstimate() const {
BeginMainFrameQueueDurationCriticalEstimate();
}
-base::TimeDelta
-CompositorTimingHistory::BeginMainFrameQueueToActivateNotCriticalEstimate()
- const {
- return BeginMainFrameStartToReadyToCommitDurationEstimate() +
- CommitDurationEstimate() + CommitToReadyToActivateDurationEstimate() +
- ActivateDurationEstimate() +
- BeginMainFrameQueueDurationNotCriticalEstimate();
-}
-
void CompositorTimingHistory::WillBeginImplFrame(
const viz::BeginFrameArgs& args,
base::TimeTicks now) {
@@ -729,12 +737,14 @@ void CompositorTimingHistory::DidDraw(bool used_new_active_tree,
// Emit a trace event to highlight a long time lapse between the draw times
// of back-to-back BeginImplFrames.
if (draw_interval > kDrawIntervalTraceThreshold) {
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
"latency", "Long Draw Interval",
- TRACE_ID_LOCAL(g_num_long_draw_intervals), draw_start_time_);
- TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
+ TRACE_ID_WITH_SCOPE("Long Draw Interval", g_num_long_draw_intervals),
+ draw_start_time_);
+ TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
"latency", "Long Draw Interval",
- TRACE_ID_LOCAL(g_num_long_draw_intervals), draw_end_time);
+ TRACE_ID_WITH_SCOPE("Long Draw Interval", g_num_long_draw_intervals),
+ draw_end_time);
g_num_long_draw_intervals++;
}
if (has_custom_property_animations &&
@@ -754,6 +764,11 @@ void CompositorTimingHistory::SetTreePriority(TreePriority priority) {
tree_priority_ = priority;
}
+void CompositorTimingHistory::RecordDeadlineMode(DeadlineMode deadline_mode) {
+ if (uma_reporter_)
+ uma_reporter_->AddImplFrameDeadlineType(deadline_mode);
+}
+
void CompositorTimingHistory::ClearHistory() {
TRACE_EVENT0("cc,benchmark", "CompositorTimingHistory::ClearHistory");
@@ -767,5 +782,4 @@ void CompositorTimingHistory::ClearHistory() {
activate_duration_history_.Clear();
draw_duration_history_.Clear();
}
-
} // namespace cc
diff --git a/chromium/cc/metrics/compositor_timing_history.h b/chromium/cc/metrics/compositor_timing_history.h
index 93fc2091905..8d01636964d 100644
--- a/chromium/cc/metrics/compositor_timing_history.h
+++ b/chromium/cc/metrics/compositor_timing_history.h
@@ -60,7 +60,6 @@ class CC_EXPORT CompositorTimingHistory {
base::TimeDelta BeginMainFrameStartToReadyToCommitCriticalEstimate() const;
base::TimeDelta BeginMainFrameStartToReadyToCommitNotCriticalEstimate() const;
base::TimeDelta BeginMainFrameQueueToActivateCriticalEstimate() const;
- base::TimeDelta BeginMainFrameQueueToActivateNotCriticalEstimate() const;
// State that affects when events should be expected/recorded/reported.
void SetRecordingEnabled(bool enabled);
@@ -87,18 +86,15 @@ class CC_EXPORT CompositorTimingHistory {
void WillInvalidateOnImplSide();
void SetTreePriority(TreePriority priority);
+ // Record the scheduler's deadline mode and send to UMA.
+ using DeadlineMode = SchedulerStateMachine::BeginImplFrameDeadlineMode;
+ void RecordDeadlineMode(DeadlineMode deadline_mode);
+
base::TimeTicks begin_main_frame_sent_time() const {
return begin_main_frame_sent_time_;
}
void ClearHistory();
- size_t begin_main_frame_start_to_ready_to_commit_sample_count() const {
- return begin_main_frame_start_to_ready_to_commit_duration_history_
- .sample_count();
- }
- size_t commit_to_ready_to_activate_sample_count() const {
- return commit_to_ready_to_activate_duration_history_.sample_count();
- }
protected:
void DidBeginMainFrame(base::TimeTicks begin_main_frame_end_time);
diff --git a/chromium/cc/metrics/dropped_frame_counter.cc b/chromium/cc/metrics/dropped_frame_counter.cc
index 339a3086528..21ab611d9b1 100644
--- a/chromium/cc/metrics/dropped_frame_counter.cc
+++ b/chromium/cc/metrics/dropped_frame_counter.cc
@@ -98,6 +98,11 @@ void DroppedFrameCounter::AddDroppedFrame() {
}
void DroppedFrameCounter::ResetPendingFrames(base::TimeTicks timestamp) {
+ // Start with flushing the frames in frame_sorter ignoring the currently
+ // pending frames (In other words calling NotifyFrameResult and update
+ // smoothness metrics tracked for all frames that have received their ack).
+ frame_sorter_.Reset();
+
// Before resetting the pending frames, update the measurements for the
// sliding windows.
if (!latest_sliding_window_start_.is_null()) {
@@ -119,6 +124,15 @@ void DroppedFrameCounter::ResetPendingFrames(base::TimeTicks timestamp) {
double percent_dropped_frame = std::min(
(dropped_frame_count_in_window_ * 100.0) / total_frames_in_window_,
100.0);
+ // TODO(jonross): we have divergent calculations for the sliding window
+ // between here and NotifyFrameResult. We should merge them to avoid
+ // inconsistencies in calculations. (https://crbug.com/1225307)
+ if (percent_dropped_frame > sliding_window_max_percent_dropped_) {
+ time_max_delta_ = args.frame_time - time_fcp_received_;
+ sliding_window_max_percent_dropped_ = percent_dropped_frame;
+ }
+ UpdateMaxPercentDroppedFrame(percent_dropped_frame);
+
sliding_window_histogram_.AddPercentDroppedFrame(percent_dropped_frame,
/*count=*/1);
}
@@ -141,7 +155,6 @@ void DroppedFrameCounter::ResetPendingFrames(base::TimeTicks timestamp) {
sliding_window_ = {};
latest_sliding_window_start_ = {};
latest_sliding_window_interval_ = {};
- frame_sorter_.Reset();
}
void DroppedFrameCounter::OnBeginFrame(const viz::BeginFrameArgs& args,
@@ -271,6 +284,7 @@ void DroppedFrameCounter::SetUkmSmoothnessDestination(
}
void DroppedFrameCounter::Reset() {
+ frame_sorter_.Reset();
total_frames_ = 0;
total_partial_ = 0;
total_dropped_ = 0;
@@ -285,7 +299,6 @@ void DroppedFrameCounter::Reset() {
latest_sliding_window_start_ = {};
sliding_window_histogram_.Clear();
ring_buffer_.Clear();
- frame_sorter_.Reset();
time_max_delta_ = {};
last_reported_metrics_ = {};
}
diff --git a/chromium/cc/metrics/dropped_frame_counter.h b/chromium/cc/metrics/dropped_frame_counter.h
index 218e1cf1c17..8e403e6c14e 100644
--- a/chromium/cc/metrics/dropped_frame_counter.h
+++ b/chromium/cc/metrics/dropped_frame_counter.h
@@ -51,8 +51,8 @@ class CC_EXPORT DroppedFrameCounter {
size_t frame_history_size() const { return ring_buffer_.BufferSize(); }
size_t total_frames() const { return total_frames_; }
- size_t total_compositor_dropped() const { return total_dropped_; }
- size_t total_main_dropped() const { return total_partial_; }
+ size_t total_dropped() const { return total_dropped_; }
+ size_t total_partial() const { return total_partial_; }
size_t total_smoothness_dropped() const { return total_smoothness_dropped_; }
uint32_t GetAverageThroughput() const;
diff --git a/chromium/cc/metrics/dropped_frame_counter_unittest.cc b/chromium/cc/metrics/dropped_frame_counter_unittest.cc
index c0a1f24da17..2e7b9012dc1 100644
--- a/chromium/cc/metrics/dropped_frame_counter_unittest.cc
+++ b/chromium/cc/metrics/dropped_frame_counter_unittest.cc
@@ -58,14 +58,15 @@ class DroppedFrameCounterTestBase : public LayerTreeTest {
// in slower machines, slower builds such as asan/tsan builds, etc.), since
// the test does not strictly control both threads and deadlines. Therefore,
// it is not possible to check for strict equality here.
- EXPECT_LE(expect_.min_dropped_main, dropped_main_);
- EXPECT_LE(expect_.min_dropped_compositor, dropped_compositor_);
+ EXPECT_LE(expect_.min_partial, partial_);
+ EXPECT_LE(expect_.min_dropped, dropped_);
EXPECT_LE(expect_.min_dropped_smoothness, dropped_smoothness_);
}
// Compositor thread function overrides:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (TestEnded())
return;
@@ -112,8 +113,8 @@ class DroppedFrameCounterTestBase : public LayerTreeTest {
DCHECK(dropped_frame_counter);
total_frames_ = dropped_frame_counter->total_frames();
- dropped_main_ = dropped_frame_counter->total_main_dropped();
- dropped_compositor_ = dropped_frame_counter->total_compositor_dropped();
+ partial_ = dropped_frame_counter->total_partial();
+ dropped_ = dropped_frame_counter->total_dropped();
dropped_smoothness_ = dropped_frame_counter->total_smoothness_dropped();
EndTest();
}
@@ -168,8 +169,8 @@ class DroppedFrameCounterTestBase : public LayerTreeTest {
// remains unchanged after that. So it is safe to read these fields from
// either threads.
struct TestExpectation {
- uint32_t min_dropped_main = 0;
- uint32_t min_dropped_compositor = 0;
+ uint32_t min_partial = 0;
+ uint32_t min_dropped = 0;
uint32_t min_dropped_smoothness = 0;
} expect_;
@@ -193,8 +194,8 @@ class DroppedFrameCounterTestBase : public LayerTreeTest {
// of frames have been processed. These fields are subsequently compared
// against the expectation after the test ends.
uint32_t total_frames_ = 0;
- uint32_t dropped_main_ = 0;
- uint32_t dropped_compositor_ = 0;
+ uint32_t partial_ = 0;
+ uint32_t dropped_ = 0;
uint32_t dropped_smoothness_ = 0;
bool skip_main_thread_next_frame_ = false;
@@ -208,8 +209,8 @@ class DroppedFrameCounterNoDropTest : public DroppedFrameCounterTestBase {
config_.animation_frames = 28;
config_.should_register_main_thread_animation = false;
- expect_.min_dropped_main = 0;
- expect_.min_dropped_compositor = 0;
+ expect_.min_partial = 0;
+ expect_.min_dropped = 0;
expect_.min_dropped_smoothness = 0;
}
};
@@ -226,7 +227,7 @@ class DroppedFrameCounterMainDropsNoSmoothness
config_.should_drop_main_every = 5;
config_.should_register_main_thread_animation = false;
- expect_.min_dropped_main = 5;
+ expect_.min_partial = 5;
expect_.min_dropped_smoothness = 0;
}
};
@@ -244,7 +245,7 @@ class DroppedFrameCounterMainDropsSmoothnessTest
config_.should_drop_main_every = 5;
config_.should_register_main_thread_animation = true;
- expect_.min_dropped_main = 5;
+ expect_.min_partial = 5;
expect_.min_dropped_smoothness = 5;
}
};
@@ -273,6 +274,15 @@ class DroppedFrameCounterTest : public testing::Test {
}
}
+ void SimulatePendingFrame(int repeat) {
+ for (int i = 0; i < repeat; i++) {
+ viz::BeginFrameArgs args_ = SimulateBeginFrameArgs();
+ dropped_frame_counter_.OnBeginFrame(args_, /*is_scroll_active=*/false);
+ sequence_number_++;
+ frame_time_ += interval_;
+ }
+ }
+
void AdvancetimeByIntervals(int interval_count) {
frame_time_ += interval_ * interval_count;
}
@@ -498,5 +508,97 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesThenHide) {
EXPECT_GT(histogram->GetPercentDroppedFramePercentile(0.97), 0u);
}
+// Tests that when ResetPendingFrames updates the sliding window, that the max
+// PercentDroppedFrames is also updated accordingly. (https://crbug.com/1225307)
+TEST_F(DroppedFrameCounterTest,
+ ResetPendingFramesUpdatesMaxPercentDroppedFrames) {
+ // This tests a scenario where gaps in frame production lead to having
+ // leftover frames in the sliding window for calculations of
+ // ResetPendingFrames.
+ //
+ // Testing for when those frames are sufficient to change the current maximum
+ // PercentDroppedFrames.
+ //
+ // This has been first seen in GpuCrash_InfoForDualHardwareGpus which forces
+ // a GPU crash. Introducing long periods of idle while the Renderer waits for
+ // a new GPU Process. (https://crbug.com/1164647)
+
+ // Set an interval that rounds up nicely with 1 second.
+ constexpr auto kInterval = base::TimeDelta::FromMilliseconds(10);
+ constexpr size_t kFps = base::TimeDelta::FromSeconds(1) / kInterval;
+ SetInterval(kInterval);
+
+ // One good frame
+ SimulateFrameSequence({false}, 1);
+ // Advance 1s so that when we process the first window, we go from having
+ // enough frames in the interval, to no longer having enough.
+ AdvancetimeByIntervals(kFps);
+
+ // The first frame should fill up the sliding window. It isn't dropped, so
+ // there should be 0 dropped frames. This will pop the first reported frame.
+ // The second frame is dropped, however we are now tracking less frames than
+ // the 1s window. So we won't use it in calculations yet.
+ SimulateFrameSequence({false, true}, 1);
+ EXPECT_EQ(dropped_frame_counter_.sliding_window_max_percent_dropped(), 0u);
+
+ // Advance 1s so that we will attempt to update the window when resetting the
+ // pending frames. The pending dropped frame above should be calculated here,
+ // and both the max and 95th percentile should be updated.
+ AdvancetimeByIntervals(kFps);
+ dropped_frame_counter_.ResetPendingFrames(GetNextFrameTime());
+
+ EXPECT_EQ(dropped_frame_counter_.sliding_window_max_percent_dropped(),
+ dropped_frame_counter_.SlidingWindow95PercentilePercentDropped());
+ EXPECT_GT(dropped_frame_counter_.sliding_window_max_percent_dropped(), 0u);
+}
+
+TEST_F(DroppedFrameCounterTest, ResetPendingFramesAccountingForPendingFrames) {
+ // Set an interval that rounds up nicely with 1 second.
+ constexpr auto kInterval = base::TimeDelta::FromMilliseconds(10);
+ constexpr size_t kFps = base::TimeDelta::FromSeconds(1) / kInterval;
+ SetInterval(kInterval);
+
+ // First 2 seconds with 20% dropped frames.
+ SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 2);
+
+ // Have a pending frame which would hold the frames in queue.
+ SimulatePendingFrame(1);
+
+ // One second with 40% dropped frames.
+ SimulateFrameSequence({false, false, false, true, true}, (kFps / 5));
+
+ // On the first 2 seconds are accounted for and pdf is 20%.
+ EXPECT_EQ(MaxPercentDroppedFrame(), 20);
+
+ dropped_frame_counter_.ResetPendingFrames(GetNextFrameTime());
+
+ // After resetting the pending frames, the pdf would be 40%.
+ EXPECT_EQ(MaxPercentDroppedFrame(), 40);
+}
+
+TEST_F(DroppedFrameCounterTest, Reset) {
+ // Set an interval that rounds up nicely with 1 second.
+ constexpr auto kInterval = base::TimeDelta::FromMilliseconds(10);
+ constexpr size_t kFps = base::TimeDelta::FromSeconds(1) / kInterval;
+ SetInterval(kInterval);
+
+ // First 2 seconds with 20% dropped frames.
+ SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 2);
+
+ // Have a pending frame which would hold the frames in queue.
+ SimulatePendingFrame(1);
+
+ // Another 2 seconds with 40% dropped frames.
+ SimulateFrameSequence({false, false, false, true, true}, (kFps / 5) * 2);
+
+ EXPECT_EQ(MaxPercentDroppedFrame(), 20u);
+
+ dropped_frame_counter_.Reset(); // Simulating gpu thread crash
+
+ // After reset the max percent dropped frame would be 0 and frames in queue
+ // behind the pending frame would not affect it.
+ EXPECT_EQ(MaxPercentDroppedFrame(), 0u);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/metrics/event_metrics.cc b/chromium/cc/metrics/event_metrics.cc
index f9ecfce0a7a..1989d690ac0 100644
--- a/chromium/cc/metrics/event_metrics.cc
+++ b/chromium/cc/metrics/event_metrics.cc
@@ -8,9 +8,9 @@
#include <utility>
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/time/default_tick_clock.h"
namespace cc {
@@ -20,6 +20,7 @@ constexpr struct {
EventMetrics::EventType metrics_event_type;
ui::EventType ui_event_type;
const char* name;
+ absl::optional<bool> scroll_is_inertial = absl::nullopt;
absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type =
absl::nullopt;
} kInterestingEvents[] = {
@@ -33,11 +34,12 @@ constexpr struct {
EVENT_TYPE(TouchPressed, ui::ET_TOUCH_PRESSED),
EVENT_TYPE(TouchReleased, ui::ET_TOUCH_RELEASED),
EVENT_TYPE(TouchMoved, ui::ET_TOUCH_MOVED),
- EVENT_TYPE(GestureScrollBegin, ui::ET_GESTURE_SCROLL_BEGIN),
+ EVENT_TYPE(GestureScrollBegin, ui::ET_GESTURE_SCROLL_BEGIN, false),
EVENT_TYPE(GestureScrollUpdate,
ui::ET_GESTURE_SCROLL_UPDATE,
+ false,
EventMetrics::ScrollUpdateType::kContinued),
- EVENT_TYPE(GestureScrollEnd, ui::ET_GESTURE_SCROLL_END),
+ EVENT_TYPE(GestureScrollEnd, ui::ET_GESTURE_SCROLL_END, false),
EVENT_TYPE(GestureDoubleTap, ui::ET_GESTURE_DOUBLE_TAP),
EVENT_TYPE(GestureLongPress, ui::ET_GESTURE_LONG_PRESS),
EVENT_TYPE(GestureLongTap, ui::ET_GESTURE_LONG_TAP),
@@ -49,11 +51,16 @@ constexpr struct {
EVENT_TYPE(GestureTwoFingerTap, ui::ET_GESTURE_TWO_FINGER_TAP),
EVENT_TYPE(FirstGestureScrollUpdate,
ui::ET_GESTURE_SCROLL_UPDATE,
+ false,
EventMetrics::ScrollUpdateType::kStarted),
EVENT_TYPE(MouseDragged, ui::ET_MOUSE_DRAGGED),
EVENT_TYPE(GesturePinchBegin, ui::ET_GESTURE_PINCH_BEGIN),
EVENT_TYPE(GesturePinchEnd, ui::ET_GESTURE_PINCH_END),
EVENT_TYPE(GesturePinchUpdate, ui::ET_GESTURE_PINCH_UPDATE),
+ EVENT_TYPE(InertialGestureScrollUpdate,
+ ui::ET_GESTURE_SCROLL_UPDATE,
+ true,
+ EventMetrics::ScrollUpdateType::kContinued),
#undef EVENT_TYPE
};
static_assert(base::size(kInterestingEvents) ==
@@ -65,12 +72,12 @@ constexpr struct {
ui::ScrollInputType ui_scroll_type;
const char* name;
} kScrollTypes[] = {
-#define SCROLL_TYPE(name, ui_type) \
- { EventMetrics::ScrollType::k##name, ui_type, #name }
- SCROLL_TYPE(Autoscroll, ui::ScrollInputType::kAutoscroll),
- SCROLL_TYPE(Scrollbar, ui::ScrollInputType::kScrollbar),
- SCROLL_TYPE(Touchscreen, ui::ScrollInputType::kTouchscreen),
- SCROLL_TYPE(Wheel, ui::ScrollInputType::kWheel),
+#define SCROLL_TYPE(name) \
+ { EventMetrics::ScrollType::k##name, ui::ScrollInputType::k##name, #name }
+ SCROLL_TYPE(Autoscroll),
+ SCROLL_TYPE(Scrollbar),
+ SCROLL_TYPE(Touchscreen),
+ SCROLL_TYPE(Wheel),
#undef SCROLL_TYPE
};
static_assert(base::size(kScrollTypes) ==
@@ -79,11 +86,19 @@ static_assert(base::size(kScrollTypes) ==
absl::optional<EventMetrics::EventType> ToInterestingEventType(
ui::EventType ui_event_type,
- absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type) {
+ const absl::optional<EventMetrics::ScrollParams>& scroll_params) {
+ absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type;
+ absl::optional<bool> scroll_is_inertial;
+ if (scroll_params) {
+ scroll_update_type = scroll_params->update_type;
+ scroll_is_inertial = scroll_params->is_inertial;
+ }
+
for (size_t i = 0; i < base::size(kInterestingEvents); i++) {
const auto& interesting_event = kInterestingEvents[i];
if (ui_event_type == interesting_event.ui_event_type &&
- scroll_update_type == interesting_event.scroll_update_type) {
+ scroll_update_type == interesting_event.scroll_update_type &&
+ scroll_is_inertial == interesting_event.scroll_is_inertial) {
EventMetrics::EventType metrics_event_type =
static_cast<EventMetrics::EventType>(i);
DCHECK_EQ(metrics_event_type, interesting_event.metrics_event_type);
@@ -94,12 +109,12 @@ absl::optional<EventMetrics::EventType> ToInterestingEventType(
}
absl::optional<EventMetrics::ScrollType> ToScrollType(
- const absl::optional<ui::ScrollInputType>& scroll_input_type) {
- if (!scroll_input_type)
+ const absl::optional<EventMetrics::ScrollParams>& scroll_params) {
+ if (!scroll_params)
return absl::nullopt;
for (size_t i = 0; i < base::size(kScrollTypes); i++) {
- if (*scroll_input_type == kScrollTypes[i].ui_scroll_type) {
+ if (scroll_params->input_type == kScrollTypes[i].ui_scroll_type) {
EventMetrics::ScrollType metrics_scroll_type =
static_cast<EventMetrics::ScrollType>(i);
DCHECK_EQ(metrics_scroll_type, kScrollTypes[i].metrics_scroll_type);
@@ -110,22 +125,49 @@ absl::optional<EventMetrics::ScrollType> ToScrollType(
return absl::nullopt;
}
+bool IsGestureScroll(ui::EventType type) {
+ return type == ui::ET_GESTURE_SCROLL_BEGIN ||
+ type == ui::ET_GESTURE_SCROLL_UPDATE ||
+ type == ui::ET_GESTURE_SCROLL_END;
+}
+
+bool IsGestureScrollUpdate(ui::EventType type) {
+ return type == ui::ET_GESTURE_SCROLL_UPDATE;
+}
+
} // namespace
+// EventMetrics::ScrollParams:
+
+EventMetrics::ScrollParams::ScrollParams(ui::ScrollInputType input_type,
+ bool is_inertial)
+ : input_type(input_type), is_inertial(is_inertial) {}
+
+EventMetrics::ScrollParams::ScrollParams(ui::ScrollInputType input_type,
+ bool is_inertial,
+ ScrollUpdateType update_type)
+ : input_type(input_type),
+ is_inertial(is_inertial),
+ update_type(update_type) {}
+
+EventMetrics::ScrollParams::ScrollParams(const ScrollParams&) = default;
+EventMetrics::ScrollParams& EventMetrics::ScrollParams::operator=(
+ const ScrollParams&) = default;
+
+// EventMetrics:
+
// static
std::unique_ptr<EventMetrics> EventMetrics::Create(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ absl::optional<ScrollParams> scroll_params,
base::TimeTicks timestamp) {
// TODO(crbug.com/1157090): We expect that `timestamp` is not null, but there
// seems to be some tests that are emitting events with null timestamp. We
// should investigate and try to fix those cases and add a `DCHECK` here to
// assert `timestamp` is not null.
- std::unique_ptr<EventMetrics> metrics =
- CreateInternal(type, scroll_update_type, scroll_input_type, timestamp,
- base::DefaultTickClock::GetInstance());
+ std::unique_ptr<EventMetrics> metrics = CreateInternal(
+ type, scroll_params, timestamp, base::DefaultTickClock::GetInstance());
if (!metrics)
return nullptr;
@@ -137,14 +179,13 @@ std::unique_ptr<EventMetrics> EventMetrics::Create(
// static
std::unique_ptr<EventMetrics> EventMetrics::CreateForTesting(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ absl::optional<ScrollParams> scroll_params,
base::TimeTicks timestamp,
const base::TickClock* tick_clock) {
DCHECK(!timestamp.is_null());
- std::unique_ptr<EventMetrics> metrics = CreateInternal(
- type, scroll_update_type, scroll_input_type, timestamp, tick_clock);
+ std::unique_ptr<EventMetrics> metrics =
+ CreateInternal(type, scroll_params, timestamp, tick_clock);
if (!metrics)
return nullptr;
@@ -156,12 +197,11 @@ std::unique_ptr<EventMetrics> EventMetrics::CreateForTesting(
// static
std::unique_ptr<EventMetrics> EventMetrics::CreateFromExisting(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ absl::optional<ScrollParams> scroll_params,
DispatchStage last_dispatch_stage,
const EventMetrics* existing) {
std::unique_ptr<EventMetrics> metrics = CreateInternal(
- type, scroll_update_type, scroll_input_type, base::TimeTicks(),
+ type, scroll_params, base::TimeTicks(),
existing ? existing->tick_clock_ : base::DefaultTickClock::GetInstance());
if (!metrics)
return nullptr;
@@ -187,21 +227,27 @@ std::unique_ptr<EventMetrics> EventMetrics::CreateFromExisting(
// static
std::unique_ptr<EventMetrics> EventMetrics::CreateInternal(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ const absl::optional<ScrollParams>& scroll_params,
base::TimeTicks timestamp,
const base::TickClock* tick_clock) {
- // `scroll_update_type` should be set for and only for
- // `ui::ET_GESTURE_SCROLL_UPDATE`.
- DCHECK(type == ui::ET_GESTURE_SCROLL_UPDATE && scroll_update_type ||
- type != ui::ET_GESTURE_SCROLL_UPDATE && !scroll_update_type);
+ // `scroll_params` should be set if and only if the event is a gesture scroll
+ // event.
+ DCHECK(IsGestureScroll(type) && scroll_params ||
+ !IsGestureScroll(type) && !scroll_params);
+
+ // `scroll_params->update_type` should be set if and only if the event is a
+ // gesture scroll update event.
+ DCHECK(IsGestureScrollUpdate(type) && scroll_params &&
+ scroll_params->update_type ||
+ !IsGestureScrollUpdate(type) &&
+ (!scroll_params || !scroll_params->update_type));
+
absl::optional<EventType> interesting_type =
- ToInterestingEventType(type, scroll_update_type);
+ ToInterestingEventType(type, scroll_params);
if (!interesting_type)
return nullptr;
- return base::WrapUnique(new EventMetrics(*interesting_type,
- ToScrollType(scroll_input_type),
- timestamp, tick_clock));
+ return base::WrapUnique(new EventMetrics(
+ *interesting_type, ToScrollType(scroll_params), timestamp, tick_clock));
}
EventMetrics::EventMetrics(EventType type,
@@ -249,6 +295,7 @@ bool EventMetrics::ShouldReportScrollingTotalLatency() const {
return type_ == EventType::kGestureScrollBegin ||
type_ == EventType::kGestureScrollEnd ||
type_ == EventType::kFirstGestureScrollUpdate ||
+ type_ == EventType::kInertialGestureScrollUpdate ||
type_ == EventType::kGestureScrollUpdate;
}
diff --git a/chromium/cc/metrics/event_metrics.h b/chromium/cc/metrics/event_metrics.h
index de1a3d77fbe..eceb2de2f5f 100644
--- a/chromium/cc/metrics/event_metrics.h
+++ b/chromium/cc/metrics/event_metrics.h
@@ -54,7 +54,8 @@ class CC_EXPORT EventMetrics {
kGesturePinchBegin,
kGesturePinchEnd,
kGesturePinchUpdate,
- kMaxValue = kGesturePinchUpdate,
+ kInertialGestureScrollUpdate,
+ kMaxValue = kInertialGestureScrollUpdate,
};
// Type of scroll events. This list should be in the same order as values of
@@ -86,19 +87,32 @@ class CC_EXPORT EventMetrics {
kMaxValue = kRendererMainFinished,
};
+ // Parameters to initialize an `EventMetrics` object for a scroll event.
+ struct CC_EXPORT ScrollParams {
+ ScrollParams(ui::ScrollInputType input_type, bool is_inertial);
+ ScrollParams(ui::ScrollInputType input_type,
+ bool is_inertial,
+ ScrollUpdateType update_type);
+
+ ScrollParams(const ScrollParams&);
+ ScrollParams& operator=(const ScrollParams&);
+
+ ui::ScrollInputType input_type;
+ bool is_inertial;
+ absl::optional<ScrollUpdateType> update_type;
+ };
+
// Returns a new instance if the event is of a type we are interested in.
// Otherwise, returns nullptr.
static std::unique_ptr<EventMetrics> Create(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ absl::optional<ScrollParams> scroll_params,
base::TimeTicks timestamp);
// Similar to `Create()` with an extra `base::TickClock` to use in tests.
static std::unique_ptr<EventMetrics> CreateForTesting(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ absl::optional<ScrollParams> scroll_params,
base::TimeTicks timestamp,
const base::TickClock* tick_clock);
@@ -110,8 +124,7 @@ class CC_EXPORT EventMetrics {
// new event is not an interesting one, return value would be nullptr.
static std::unique_ptr<EventMetrics> CreateFromExisting(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ absl::optional<ScrollParams> scroll_params,
DispatchStage last_dispatch_stage,
const EventMetrics* existing);
@@ -152,8 +165,7 @@ class CC_EXPORT EventMetrics {
private:
static std::unique_ptr<EventMetrics> CreateInternal(
ui::EventType type,
- absl::optional<ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type,
+ const absl::optional<ScrollParams>& scroll_params,
base::TimeTicks timestamp,
const base::TickClock* tick_clock);
diff --git a/chromium/cc/metrics/events_metrics_manager.cc b/chromium/cc/metrics/events_metrics_manager.cc
index 3de83e4ee64..72993dae887 100644
--- a/chromium/cc/metrics/events_metrics_manager.cc
+++ b/chromium/cc/metrics/events_metrics_manager.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/stl_util.h"
namespace cc {
diff --git a/chromium/cc/metrics/events_metrics_manager_unittest.cc b/chromium/cc/metrics/events_metrics_manager_unittest.cc
index d8fc6e47d25..0d0b6b90217 100644
--- a/chromium/cc/metrics/events_metrics_manager_unittest.cc
+++ b/chromium/cc/metrics/events_metrics_manager_unittest.cc
@@ -8,7 +8,7 @@
#include <vector>
#include "base/bind.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/test/simple_test_tick_clock.h"
#include "cc/metrics/event_metrics.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -56,8 +56,8 @@ class EventsMetricsManagerTest : public testing::Test {
test_tick_clock_.Advance(base::TimeDelta::FromMicroseconds(10));
base::TimeTicks event_time = test_tick_clock_.NowTicks();
test_tick_clock_.Advance(base::TimeDelta::FromMicroseconds(10));
- return EventMetrics::CreateForTesting(type, absl::nullopt, absl::nullopt,
- event_time, &test_tick_clock_);
+ return EventMetrics::CreateForTesting(type, absl::nullopt, event_time,
+ &test_tick_clock_);
}
EventsMetricsManager manager_;
diff --git a/chromium/cc/metrics/frame_sequence_metrics.cc b/chromium/cc/metrics/frame_sequence_metrics.cc
index 30259bd2a9c..3b92138019f 100644
--- a/chromium/cc/metrics/frame_sequence_metrics.cc
+++ b/chromium/cc/metrics/frame_sequence_metrics.cc
@@ -19,6 +19,36 @@
namespace cc {
+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(
+ FrameSequenceTrackerType sequence_type,
+ FrameSequenceMetrics::ThreadType reporting_thread_type,
+ FrameSequenceMetrics::ThreadType metrics_effective_thread_type) {
+ // For scrollbar/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::kScrollbarScroll ||
+ sequence_type == FrameSequenceTrackerType::kTouchScroll ||
+ sequence_type == FrameSequenceTrackerType::kWheelScroll)
+ return reporting_thread_type == metrics_effective_thread_type;
+
+ if (sequence_type == FrameSequenceTrackerType::kPinchZoom)
+ return reporting_thread_type ==
+ FrameSequenceMetrics::ThreadType::kCompositor;
+
+ return false;
+}
+
namespace {
// Avoid reporting any throughput metric for sequences that do not have a
@@ -58,43 +88,6 @@ std::string GetMissedDeadlineHistogramName(FrameSequenceTrackerType type,
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::kCanvasAnimation ||
- sequence_type == FrameSequenceTrackerType::kJSAnimation ||
- 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 scrollbar/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::kScrollbarScroll ||
- 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::kScrollbarScroll ||
sequence_type == FrameSequenceTrackerType::kTouchScroll ||
@@ -346,12 +339,16 @@ void FrameSequenceMetrics::ReportMetrics() {
if (jank_reporter_) {
if (jank_reporter_->thread_type() ==
FrameSequenceMetrics::ThreadType::kCompositor &&
- impl_throughput_.frames_expected >= kMinFramesForThroughputMetric)
+ impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) {
+ DCHECK_EQ(jank_reporter_->thread_type(), this->GetEffectiveThread());
jank_reporter_->ReportJankMetrics(impl_throughput_.frames_expected);
- else if (jank_reporter_->thread_type() ==
- FrameSequenceMetrics::ThreadType::kMain &&
- main_throughput_.frames_expected >= kMinFramesForThroughputMetric)
+ } else if (jank_reporter_->thread_type() ==
+ FrameSequenceMetrics::ThreadType::kMain &&
+ main_throughput_.frames_expected >=
+ kMinFramesForThroughputMetric) {
+ DCHECK_EQ(jank_reporter_->thread_type(), this->GetEffectiveThread());
jank_reporter_->ReportJankMetrics(main_throughput_.frames_expected);
+ }
}
// Reset the metrics that reach reporting threshold.
@@ -429,17 +426,6 @@ int FrameSequenceMetrics::ThroughputData::ReportDroppedFramePercentHistogram(
sequence_type == FrameSequenceTrackerType::kCanvasAnimation ||
sequence_type == FrameSequenceTrackerType::kJSAnimation);
- if (metrics->GetEffectiveThread() == thread_type) {
- 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));
- }
-
// 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.
@@ -447,7 +433,8 @@ int FrameSequenceMetrics::ThroughputData::ReportDroppedFramePercentHistogram(
const bool is_animation =
ShouldReportForAnimation(sequence_type, thread_type);
- const bool is_interaction = ShouldReportForInteraction(metrics, thread_type);
+ const bool is_interaction = ShouldReportForInteraction(
+ metrics->type(), thread_type, metrics->GetEffectiveThread());
ThroughputUkmReporter* const ukm_reporter = metrics->ukm_reporter();
@@ -518,7 +505,8 @@ int FrameSequenceMetrics::ThroughputData::
const bool is_animation =
ShouldReportForAnimation(sequence_type, thread_type);
- const bool is_interaction = ShouldReportForInteraction(metrics, thread_type);
+ const bool is_interaction = ShouldReportForInteraction(
+ metrics->type(), thread_type, metrics->GetEffectiveThread());
if (is_animation) {
TRACE_EVENT_INSTANT2(
diff --git a/chromium/cc/metrics/frame_sequence_metrics.h b/chromium/cc/metrics/frame_sequence_metrics.h
index 1de8184cad1..c051a27f5f8 100644
--- a/chromium/cc/metrics/frame_sequence_metrics.h
+++ b/chromium/cc/metrics/frame_sequence_metrics.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/trace_event/traced_value.h"
#include "cc/cc_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cc {
class ThroughputUkmReporter;
@@ -147,7 +146,7 @@ class CC_EXPORT FrameSequenceMetrics {
struct CustomReportData {
uint32_t frames_expected = 0;
uint32_t frames_produced = 0;
- uint32_t jank_count = 0;
+ int jank_count = 0;
};
using CustomReporter = base::OnceCallback<void(const CustomReportData& data)>;
// Sets reporter callback for kCustom typed sequence.
@@ -230,6 +229,14 @@ class CC_EXPORT FrameSequenceMetrics {
std::unique_ptr<JankMetrics> jank_reporter_;
};
+bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type,
+ FrameSequenceMetrics::ThreadType thread_type);
+
+bool ShouldReportForInteraction(
+ FrameSequenceTrackerType sequence_type,
+ FrameSequenceMetrics::ThreadType reporting_thread_type,
+ FrameSequenceMetrics::ThreadType metrics_effective_thread_type);
+
} // 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 983cc4a893c..f2bf7ee43ad 100644
--- a/chromium/cc/metrics/frame_sequence_metrics_unittest.cc
+++ b/chromium/cc/metrics/frame_sequence_metrics_unittest.cc
@@ -56,21 +56,6 @@ TEST(FrameSequenceMetricsTest, ScrollingThreadMergeMetrics) {
}
#endif // DCHECK_IS_ON()
-TEST(FrameSequenceMetricsTest, VideoReportsOnImplOnly) {
- base::HistogramTester histograms;
-
- FrameSequenceMetrics first(FrameSequenceTrackerType::kVideo, nullptr);
- first.impl_throughput().frames_expected = 120;
- first.impl_throughput().frames_produced = 80;
- first.impl_throughput().frames_ontime = 80;
- first.main_throughput().frames_expected = 0;
- first.main_throughput().frames_produced = 0;
- first.main_throughput().frames_ontime = 0;
- first.ReportMetrics();
- histograms.ExpectTotalCount("Graphics.Smoothness.FrameSequenceLength.Video",
- 1u);
-}
-
TEST(FrameSequenceMetricsTest, AllMetricsReported) {
base::HistogramTester histograms;
diff --git a/chromium/cc/metrics/frame_sequence_tracker.cc b/chromium/cc/metrics/frame_sequence_tracker.cc
index 474b2f0d36a..e72bd574646 100644
--- a/chromium/cc/metrics/frame_sequence_tracker.cc
+++ b/chromium/cc/metrics/frame_sequence_tracker.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/containers/contains.h"
+#include "base/containers/cxx20_erase.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
diff --git a/chromium/cc/metrics/frame_sequence_tracker.h b/chromium/cc/metrics/frame_sequence_tracker.h
index e76ff04f5b7..1630c711217 100644
--- a/chromium/cc/metrics/frame_sequence_tracker.h
+++ b/chromium/cc/metrics/frame_sequence_tracker.h
@@ -9,11 +9,9 @@
#include <sstream>
#include "base/containers/circular_deque.h"
-#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "cc/cc_export.h"
#include "cc/metrics/frame_sequence_metrics.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace gfx {
struct PresentationFeedback;
diff --git a/chromium/cc/metrics/frame_sequence_tracker_collection.cc b/chromium/cc/metrics/frame_sequence_tracker_collection.cc
index ed9f7bbf691..b6394a6360d 100644
--- a/chromium/cc/metrics/frame_sequence_tracker_collection.cc
+++ b/chromium/cc/metrics/frame_sequence_tracker_collection.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/containers/contains.h"
+#include "base/containers/cxx20_erase.h"
#include "base/memory/ptr_util.h"
#include "cc/metrics/compositor_frame_reporting_controller.h"
#include "cc/metrics/frame_sequence_tracker.h"
diff --git a/chromium/cc/metrics/frame_sequence_tracker_collection.h b/chromium/cc/metrics/frame_sequence_tracker_collection.h
index fdba36a0435..e3dc01d9af8 100644
--- a/chromium/cc/metrics/frame_sequence_tracker_collection.h
+++ b/chromium/cc/metrics/frame_sequence_tracker_collection.h
@@ -13,7 +13,6 @@
#include "base/containers/flat_map.h"
#include "cc/cc_export.h"
#include "cc/metrics/frame_sequence_metrics.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace gfx {
struct PresentationFeedback;
diff --git a/chromium/cc/metrics/frame_sequence_tracker_unittest.cc b/chromium/cc/metrics/frame_sequence_tracker_unittest.cc
index 908b0edd950..1cfa9f309e6 100644
--- a/chromium/cc/metrics/frame_sequence_tracker_unittest.cc
+++ b/chromium/cc/metrics/frame_sequence_tracker_unittest.cc
@@ -905,13 +905,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame2) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -934,13 +928,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame3) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -963,13 +951,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame4) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1033,13 +1015,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame7) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1062,13 +1038,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame8) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1091,13 +1061,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame9) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1153,13 +1117,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame12) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1182,13 +1140,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame13) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1204,13 +1156,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame14) {
// The tracker should have been removed from the removal_tracker_ list.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1240,13 +1186,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame15) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1269,13 +1209,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame16) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1298,13 +1232,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame17) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1328,13 +1256,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame18) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1357,13 +1279,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame19) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
@@ -1386,13 +1302,7 @@ TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame20) {
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
- std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
- // Impl thread reports 101 frames expected.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 1);
- // The main thread does not submit a report because it is not the effective
- // thread.
- EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 0);
- metric =
+ std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
diff --git a/chromium/cc/metrics/jank_metrics.cc b/chromium/cc/metrics/jank_metrics.cc
index 8922e14f484..3212403ab06 100644
--- a/chromium/cc/metrics/jank_metrics.cc
+++ b/chromium/cc/metrics/jank_metrics.cc
@@ -237,6 +237,29 @@ void JankMetrics::ReportJankMetrics(int frames_expected) {
GetJankHistogramName(tracker_type_, jank_thread_name), 1, 100, 101,
base::HistogramBase::kUmaTargetedHistogramFlag));
+ const bool is_animation =
+ ShouldReportForAnimation(tracker_type_, effective_thread_);
+
+ // Jank reporter's effective thread is guaranteed to be identical to that of
+ // the owning FrameSequenceMetrics instance.
+ const bool is_interaction = ShouldReportForInteraction(
+ tracker_type_, effective_thread_, effective_thread_);
+
+ if (is_animation) {
+ UMA_HISTOGRAM_PERCENTAGE("Graphics.Smoothness.Jank.AllAnimations",
+ jank_percent);
+ }
+
+ if (is_interaction) {
+ UMA_HISTOGRAM_PERCENTAGE("Graphics.Smoothness.Jank.AllInteractions",
+ jank_percent);
+ }
+
+ if (is_animation || is_interaction) {
+ UMA_HISTOGRAM_PERCENTAGE("Graphics.Smoothness.Jank.AllSequences",
+ jank_percent);
+ }
+
// Report the max staleness metrics
STATIC_HISTOGRAM_POINTER_GROUP(
GetMaxStaleHistogramName(tracker_type_),
diff --git a/chromium/cc/metrics/jank_metrics_unittest.cc b/chromium/cc/metrics/jank_metrics_unittest.cc
index dbc624e1ac5..86e7c3542ff 100644
--- a/chromium/cc/metrics/jank_metrics_unittest.cc
+++ b/chromium/cc/metrics/jank_metrics_unittest.cc
@@ -28,6 +28,12 @@ const base::TimeDelta kDefaultFrameInterval =
// This makes it easier to numerically distinguish sequence numbers versus
// frame tokens, which always start at 1.
const uint32_t kSequenceNumberStartsAt = 100u;
+
+const char* kAllSequencesMetricName = "Graphics.Smoothness.Jank.AllSequences";
+const char* kAllAnimationsMetricName = "Graphics.Smoothness.Jank.AllAnimations";
+const char* kAllInteractionsMetricName =
+ "Graphics.Smoothness.Jank.AllInteractions";
+
} // namespace
namespace cc {
@@ -158,6 +164,17 @@ TEST_F(JankMetricsTest, CompositorAnimationOneJankWithMildFluctuation) {
EXPECT_THAT(histogram_tester.GetAllSamples(metric),
testing::ElementsAre(base::Bucket(1, 1)));
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(1, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(1, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.CompositorAnimation";
const char* maxstale_metric =
@@ -206,6 +223,17 @@ TEST_F(JankMetricsTest, MainThreadAnimationOneJankWithNoUpdate) {
// No jank is reported for "Compositor"
histogram_tester.ExpectTotalCount(invalid_metric, 0u);
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(1, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(1, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.MainThreadAnimation";
const char* maxstale_metric =
@@ -248,6 +276,11 @@ TEST_F(JankMetricsTest, VideoManyJanksOver300ExpectedFrames) {
// No jank is reported for "Main"
histogram_tester.ExpectTotalCount(invalid_metric, 0u);
+ // Test all-sequence metrics. Videos are not counted into AllSequences.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 0u);
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.Video";
const char* maxstale_metric = "Graphics.Smoothness.MaxStale.Video";
@@ -289,6 +322,17 @@ TEST_F(JankMetricsTest, WheelScrollMainThreadNoJanksWithNoUpdates) {
histogram_tester.ExpectTotalCount(invalid_metric, 0u);
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(0, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
+
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllInteractionsMetricName),
+ testing::ElementsAre(base::Bucket(0, 1)));
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.WheelScroll";
const char* maxstale_metric = "Graphics.Smoothness.MaxStale.WheelScroll";
@@ -332,6 +376,17 @@ TEST_F(JankMetricsTest, WheelScrollCompositorTwoJanksWithLargeFluctuation) {
// No reporting for "Main".
histogram_tester.ExpectTotalCount(invalid_metric, 0u);
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(2, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
+
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllInteractionsMetricName),
+ testing::ElementsAre(base::Bucket(2, 1)));
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.WheelScroll";
const char* maxstale_metric = "Graphics.Smoothness.MaxStale.WheelScroll";
@@ -378,6 +433,17 @@ TEST_F(JankMetricsTest, TouchScrollCompositorThreadManyJanksLongLatency) {
histogram_tester.ExpectTotalCount(invalid_metric, 0u);
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(4, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
+
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllInteractionsMetricName),
+ testing::ElementsAre(base::Bucket(4, 1)));
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.TouchScroll";
const char* maxstale_metric = "Graphics.Smoothness.MaxStale.TouchScroll";
@@ -436,6 +502,17 @@ TEST_F(JankMetricsTest, RAFMergeJanks) {
histogram_tester.ExpectTotalCount(invalid_metric, 0u);
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
+ testing::ElementsAre(base::Bucket(6, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
+ EXPECT_THAT(histogram_tester.GetAllSamples(kAllAnimationsMetricName),
+ testing::ElementsAre(base::Bucket(6, 1)));
+
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
+
// Stale-frame metrics
const char* stale_metric = "Graphics.Smoothness.Stale.RAF";
const char* maxstale_metric = "Graphics.Smoothness.MaxStale.RAF";
@@ -472,6 +549,11 @@ TEST_F(JankMetricsTest, CustomNotReported) {
histogram_tester.ExpectTotalCount(
"Graphics.Smoothness.Jank.Compositor.Custom", 0u);
+ // Test all-sequence metrics.
+ histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 0u);
+ histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
+ histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
+
// Stale-frame metrics
histogram_tester.ExpectTotalCount("Graphics.Smoothness.Stale.Custom", 0u);
histogram_tester.ExpectTotalCount("Graphics.Smoothness.MaxStale.Custom", 0u);
diff --git a/chromium/cc/metrics/video_playback_roughness_reporter.cc b/chromium/cc/metrics/video_playback_roughness_reporter.cc
index 33ef9c517be..abc93c368b4 100644
--- a/chromium/cc/metrics/video_playback_roughness_reporter.cc
+++ b/chromium/cc/metrics/video_playback_roughness_reporter.cc
@@ -7,8 +7,8 @@
#include <algorithm>
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
#include "base/numerics/safe_conversions.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
@@ -60,7 +60,7 @@ void VideoPlaybackRoughnessReporter::FrameSubmitted(
FrameInfo info;
info.token = token;
info.decode_time = frame.metadata().decode_end_time;
- info.refresh_rate_hz = int{std::round(1.0 / render_interval.InSecondsF())};
+ info.refresh_rate_hz = base::ClampRound(render_interval.ToHz());
info.size = frame.natural_size();
info.intended_duration = frame.metadata().wallclock_frame_duration;
@@ -75,8 +75,7 @@ void VideoPlaybackRoughnessReporter::FrameSubmitted(
// Adjust frame window size to fit about 1 second of playback
const int win_size =
base::ClampRound(info.intended_duration.value().ToHz());
- frames_window_size_ =
- base::ClampToRange(win_size, kMinWindowSize, kMaxWindowSize);
+ frames_window_size_ = base::clamp(win_size, kMinWindowSize, kMaxWindowSize);
}
frames_.push_back(info);
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 3ac47e45d4f..f3f2fc5e416 100644
--- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc
+++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -199,7 +199,9 @@ void AsyncLayerTreeFrameSink::SubmitCompositorFrame(
"Event.Pipeline", TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_OUT, "step",
"SubmitHitTestData");
- power_mode_voter_.OnFrameProduced();
+
+ power_mode_voter_.OnFrameProduced(frame.render_pass_list.back()->damage_rect,
+ frame.device_scale_factor());
compositor_frame_sink_ptr_->SubmitCompositorFrame(
local_surface_id_, std::move(frame), std::move(hit_test_region_list), 0);
diff --git a/chromium/cc/paint/decoded_draw_image.cc b/chromium/cc/paint/decoded_draw_image.cc
index c570114ddf6..d03a42b2779 100644
--- a/chromium/cc/paint/decoded_draw_image.cc
+++ b/chromium/cc/paint/decoded_draw_image.cc
@@ -12,7 +12,7 @@ DecodedDrawImage::DecodedDrawImage(sk_sp<const SkImage> image,
sk_sp<SkColorFilter> dark_mode_color_filter,
const SkSize& src_rect_offset,
const SkSize& scale_adjustment,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
bool is_budgeted)
: image_(std::move(image)),
dark_mode_color_filter_(std::move(dark_mode_color_filter)),
@@ -22,7 +22,7 @@ DecodedDrawImage::DecodedDrawImage(sk_sp<const SkImage> image,
is_budgeted_(is_budgeted) {}
DecodedDrawImage::DecodedDrawImage(const gpu::Mailbox& mailbox,
- SkFilterQuality filter_quality)
+ PaintFlags::FilterQuality filter_quality)
: mailbox_(mailbox),
src_rect_offset_(SkSize::MakeEmpty()),
scale_adjustment_(SkSize::Make(1.f, 1.f)),
@@ -34,7 +34,7 @@ DecodedDrawImage::DecodedDrawImage(
sk_sp<SkColorFilter> dark_mode_color_filter,
const SkSize& src_rect_offset,
const SkSize& scale_adjustment,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
bool needs_mips,
bool is_budgeted)
: transfer_cache_entry_id_(transfer_cache_entry_id),
@@ -50,7 +50,7 @@ DecodedDrawImage::DecodedDrawImage()
nullptr,
SkSize::MakeEmpty(),
SkSize::Make(1.f, 1.f),
- kNone_SkFilterQuality,
+ PaintFlags::FilterQuality::kNone,
true) {}
DecodedDrawImage::DecodedDrawImage(const DecodedDrawImage&) = default;
diff --git a/chromium/cc/paint/decoded_draw_image.h b/chromium/cc/paint/decoded_draw_image.h
index a3b0e3a9fc9..8b52faeecd0 100644
--- a/chromium/cc/paint/decoded_draw_image.h
+++ b/chromium/cc/paint/decoded_draw_image.h
@@ -9,10 +9,10 @@
#include <cmath>
#include "cc/paint/paint_export.h"
+#include "cc/paint/paint_flags.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColorFilter.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSize.h"
@@ -30,14 +30,15 @@ class CC_PAINT_EXPORT DecodedDrawImage {
sk_sp<SkColorFilter> dark_mode_color_filter,
const SkSize& src_rect_offset,
const SkSize& scale_adjustment,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
bool is_budgeted);
- DecodedDrawImage(const gpu::Mailbox& mailbox, SkFilterQuality filter_quality);
+ DecodedDrawImage(const gpu::Mailbox& mailbox,
+ PaintFlags::FilterQuality filter_quality);
DecodedDrawImage(absl::optional<uint32_t> transfer_cache_entry_id,
sk_sp<SkColorFilter> dark_mode_color_filter,
const SkSize& src_rect_offset,
const SkSize& scale_adjustment,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
bool needs_mips,
bool is_budgeted);
DecodedDrawImage(const DecodedDrawImage& other);
@@ -57,7 +58,7 @@ class CC_PAINT_EXPORT DecodedDrawImage {
}
const SkSize& src_rect_offset() const { return src_rect_offset_; }
const SkSize& scale_adjustment() const { return scale_adjustment_; }
- SkFilterQuality filter_quality() const { return filter_quality_; }
+ PaintFlags::FilterQuality filter_quality() const { return filter_quality_; }
bool is_scale_adjustment_identity() const {
return std::abs(scale_adjustment_.width() - 1.f) < FLT_EPSILON &&
std::abs(scale_adjustment_.height() - 1.f) < FLT_EPSILON;
@@ -78,7 +79,7 @@ class CC_PAINT_EXPORT DecodedDrawImage {
sk_sp<SkColorFilter> dark_mode_color_filter_;
SkSize src_rect_offset_;
SkSize scale_adjustment_;
- SkFilterQuality filter_quality_;
+ PaintFlags::FilterQuality filter_quality_;
bool transfer_cache_entry_needs_mips_ = false;
bool is_budgeted_;
};
diff --git a/chromium/cc/paint/discardable_image_map.cc b/chromium/cc/paint/discardable_image_map.cc
index 2fd62e0aac7..72f23dcaa1c 100644
--- a/chromium/cc/paint/discardable_image_map.cc
+++ b/chromium/cc/paint/discardable_image_map.cc
@@ -166,7 +166,7 @@ class DiscardableImageGenerator {
void AddImageFromShader(const gfx::Rect& op_rect,
const PaintShader* shader,
const SkM44& ctm,
- SkFilterQuality filter_quality) {
+ PaintFlags::FilterQuality filter_quality) {
if (!shader || !shader->has_discardable_images())
return;
@@ -236,7 +236,7 @@ class DiscardableImageGenerator {
const SkRect& src_rect,
const gfx::Rect& image_rect,
const SkM44& matrix,
- SkFilterQuality filter_quality) {
+ PaintFlags::FilterQuality filter_quality) {
if (paint_image.IsTextureBacked())
return;
diff --git a/chromium/cc/paint/discardable_image_map_unittest.cc b/chromium/cc/paint/discardable_image_map_unittest.cc
index 1b217d8e9c3..6a4801872e3 100644
--- a/chromium/cc/paint/discardable_image_map_unittest.cc
+++ b/chromium/cc/paint/discardable_image_map_unittest.cc
@@ -373,7 +373,8 @@ TEST_F(DiscardableImageMapTest, PaintDestroyedWhileImageIsDrawn) {
// Check if SkNoDrawCanvas does not crash for large layers.
TEST_F(DiscardableImageMapTest, RestoreSavedBigLayers) {
PaintFlags flags;
- SkRect rect = SkRect::MakeWH(INT_MAX, INT_MAX);
+ SkRect rect =
+ SkRect::MakeWH(static_cast<float>(INT_MAX), static_cast<float>(INT_MAX));
scoped_refptr<DisplayItemList> display_list = new DisplayItemList;
display_list->StartPaint();
display_list->push<DrawRectOp>(rect, flags);
@@ -408,13 +409,13 @@ TEST_F(DiscardableImageMapTest, RestoreSavedTransformedLayers) {
CreateDiscardablePaintImage(gfx::Size(25, 25));
PaintImage discardable_image3 =
CreateDiscardablePaintImage(gfx::Size(25, 25));
- display_list->push<TranslateOp>(25, 25);
+ display_list->push<TranslateOp>(25.0f, 25.0f);
display_list->push<DrawImageOp>(discardable_image1, 0.f, 0.f);
display_list->push<SaveLayerOp>(nullptr, &paint);
- display_list->push<TranslateOp>(100, 100);
+ display_list->push<TranslateOp>(100.0f, 100.0f);
display_list->push<DrawImageOp>(discardable_image2, 0.f, 0.f);
display_list->push<RestoreOp>();
- display_list->push<TranslateOp>(0, 100);
+ display_list->push<TranslateOp>(0.0f, 100.0f);
display_list->push<DrawImageOp>(discardable_image3, 0.f, 0.f);
display_list->EndPaintOfUnpaired(visible_rect);
display_list->Finalize();
diff --git a/chromium/cc/paint/display_item_list.cc b/chromium/cc/paint/display_item_list.cc
index d0c4f52b0d4..932bee1c155 100644
--- a/chromium/cc/paint/display_item_list.cc
+++ b/chromium/cc/paint/display_item_list.cc
@@ -454,8 +454,8 @@ DisplayItemList::GetDirectlyCompositedImageResult(
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;
+ result.nearest_neighbor = draw_image_rect_op->flags.getFilterQuality() ==
+ PaintFlags::FilterQuality::kNone;
return result;
}
diff --git a/chromium/cc/paint/display_item_list.h b/chromium/cc/paint/display_item_list.h
index 498e2436969..7387417c7d4 100644
--- a/chromium/cc/paint/display_item_list.h
+++ b/chromium/cc/paint/display_item_list.h
@@ -18,6 +18,7 @@
#include "cc/paint/image_id.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_op_buffer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/cc/paint/display_item_list_unittest.cc b/chromium/cc/paint/display_item_list_unittest.cc
index 707ffc441e2..e781dfc6dc7 100644
--- a/chromium/cc/paint/display_item_list_unittest.cc
+++ b/chromium/cc/paint/display_item_list_unittest.cc
@@ -28,6 +28,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkSurface.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -74,18 +75,13 @@ class DisplayItemListTest : public testing::Test {
}
};
-#define EXPECT_TRACED_RECT(x, y, width, height, rect_list) \
- do { \
- ASSERT_EQ(4u, rect_list->GetSize()); \
- double d; \
- EXPECT_TRUE((rect_list)->GetDouble(0, &d)); \
- EXPECT_EQ(x, d); \
- EXPECT_TRUE((rect_list)->GetDouble(1, &d)); \
- EXPECT_EQ(y, d); \
- EXPECT_TRUE((rect_list)->GetDouble(2, &d)); \
- EXPECT_EQ(width, d); \
- EXPECT_TRUE((rect_list)->GetDouble(3, &d)); \
- EXPECT_EQ(height, d); \
+#define EXPECT_TRACED_RECT(x, y, width, height, rect_list) \
+ do { \
+ ASSERT_EQ(4u, rect_list->GetList().size()); \
+ EXPECT_EQ(x, rect_list->GetList()[0].GetIfDouble()); \
+ EXPECT_EQ(y, rect_list->GetList()[1].GetIfDouble()); \
+ EXPECT_EQ(width, rect_list->GetList()[2].GetIfDouble()); \
+ EXPECT_EQ(height, rect_list->GetList()[3].GetIfDouble()); \
} while (false)
// AddToValue should not crash if there are different numbers of visual_rect
@@ -371,7 +367,7 @@ TEST_F(DisplayItemListTest, FilterPairedRange) {
// below.
SkRect rect = SkRect::MakeWH(source_image.width(), source_image.height());
sk_sp<PaintFilter> image_filter = sk_make_sp<ImagePaintFilter>(
- source_image, rect, rect, kHigh_SkFilterQuality);
+ source_image, rect, rect, PaintFlags::FilterQuality::kHigh);
filters.Append(FilterOperation::CreateReferenceFilter(image_filter));
filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
gfx::RectF filter_bounds(10.f, 10.f, 50.f, 50.f);
@@ -1147,30 +1143,30 @@ TEST_F(DisplayItemListTest, AreaOfDrawText) {
auto text_blob2_area = text_blob2_size.width() * text_blob2_size.height();
sub_list->StartPaint();
- sub_list->push<DrawTextBlobOp>(text_blob1, 0, 0, PaintFlags());
+ sub_list->push<DrawTextBlobOp>(text_blob1, 0.0f, 0.0f, PaintFlags());
sub_list->EndPaintOfUnpaired(gfx::Rect());
auto record = sub_list->ReleaseAsRecord();
list->StartPaint();
list->push<SaveOp>();
- list->push<TranslateOp>(100, 100);
+ list->push<TranslateOp>(100.0f, 100.0f);
list->push<DrawRecordOp>(record);
list->push<RestoreOp>();
list->EndPaintOfUnpaired(gfx::Rect(gfx::Point(100, 100), text_blob1_size));
list->StartPaint();
list->push<SaveOp>();
- list->push<TranslateOp>(100, 400);
+ list->push<TranslateOp>(100.0f, 400.0f);
list->push<DrawRecordOp>(record);
list->push<RestoreOp>();
list->EndPaintOfUnpaired(gfx::Rect(gfx::Point(100, 400), text_blob1_size));
list->StartPaint();
- list->push<DrawTextBlobOp>(text_blob2, 10, 20, PaintFlags());
+ list->push<DrawTextBlobOp>(text_blob2, 10.0f, 20.0f, PaintFlags());
list->EndPaintOfUnpaired(gfx::Rect(text_blob2_size));
list->StartPaint();
- list->push<DrawTextBlobOp>(text_blob2, 400, 100, PaintFlags());
+ list->push<DrawTextBlobOp>(text_blob2, 400.0f, 100.0f, PaintFlags());
list->EndPaintOfUnpaired(gfx::Rect(gfx::Point(400, 100), text_blob2_size));
list->StartPaint();
diff --git a/chromium/cc/paint/draw_image.cc b/chromium/cc/paint/draw_image.cc
index 11b21e65077..d331bbb6fe3 100644
--- a/chromium/cc/paint/draw_image.cc
+++ b/chromium/cc/paint/draw_image.cc
@@ -30,7 +30,7 @@ bool ExtractScale(const SkM44& matrix, SkSize* scale) {
DrawImage::DrawImage()
: use_dark_mode_(false),
src_rect_(SkIRect::MakeXYWH(0, 0, 0, 0)),
- filter_quality_(kNone_SkFilterQuality),
+ filter_quality_(PaintFlags::FilterQuality::kNone),
scale_(SkSize::Make(1.f, 1.f)),
matrix_is_decomposable_(true) {}
@@ -39,14 +39,14 @@ DrawImage::DrawImage(PaintImage image)
use_dark_mode_(false),
src_rect_(
SkIRect::MakeXYWH(0, 0, paint_image_.width(), paint_image_.height())),
- filter_quality_(kNone_SkFilterQuality),
+ filter_quality_(PaintFlags::FilterQuality::kNone),
scale_(SkSize::Make(1.f, 1.f)),
matrix_is_decomposable_(true) {}
DrawImage::DrawImage(PaintImage image,
bool use_dark_mode,
const SkIRect& src_rect,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
const SkM44& matrix,
absl::optional<size_t> frame_index,
const absl::optional<gfx::ColorSpace>& color_space,
diff --git a/chromium/cc/paint/draw_image.h b/chromium/cc/paint/draw_image.h
index 02c13f66802..4f7d5f875c7 100644
--- a/chromium/cc/paint/draw_image.h
+++ b/chromium/cc/paint/draw_image.h
@@ -6,9 +6,9 @@
#define CC_PAINT_DRAW_IMAGE_H_
#include "cc/paint/paint_export.h"
+#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_image.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkM44.h"
#include "third_party/skia/include/core/SkRect.h"
@@ -29,7 +29,7 @@ class CC_PAINT_EXPORT DrawImage {
DrawImage(PaintImage image,
bool use_dark_mode,
const SkIRect& src_rect,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
const SkM44& matrix,
absl::optional<size_t> frame_index = absl::nullopt,
const absl::optional<gfx::ColorSpace>& color_space = absl::nullopt,
@@ -54,7 +54,7 @@ class CC_PAINT_EXPORT DrawImage {
bool use_dark_mode() const { return use_dark_mode_; }
const SkSize& scale() const { return scale_; }
const SkIRect& src_rect() const { return src_rect_; }
- SkFilterQuality filter_quality() const { return filter_quality_; }
+ PaintFlags::FilterQuality filter_quality() const { return filter_quality_; }
bool matrix_is_decomposable() const { return matrix_is_decomposable_; }
const gfx::ColorSpace& target_color_space() const {
DCHECK(target_color_space_.has_value());
@@ -73,7 +73,7 @@ class CC_PAINT_EXPORT DrawImage {
PaintImage paint_image_;
bool use_dark_mode_;
SkIRect src_rect_;
- SkFilterQuality filter_quality_;
+ PaintFlags::FilterQuality filter_quality_;
SkSize scale_;
bool matrix_is_decomposable_;
absl::optional<size_t> frame_index_;
diff --git a/chromium/cc/paint/filter_operation.cc b/chromium/cc/paint/filter_operation.cc
index dae02259d51..82d0b5c20cb 100644
--- a/chromium/cc/paint/filter_operation.cc
+++ b/chromium/cc/paint/filter_operation.cc
@@ -5,11 +5,11 @@
#include <stddef.h>
#include <algorithm>
+#include <utility>
#include "cc/paint/filter_operation.h"
-#include "base/numerics/ranges.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/trace_event/traced_value.h"
#include "base/values.h"
#include "cc/base/math_util.h"
@@ -39,6 +39,10 @@ bool FilterOperation::operator==(const FilterOperation& other) const {
return shape_ == other.shape_ && amount_ == other.amount_ &&
outer_threshold_ == other.outer_threshold_;
}
+ if (type_ == STRETCH) {
+ return amount_ == other.amount_ &&
+ outer_threshold_ == other.outer_threshold_;
+ }
return amount_ == other.amount_;
}
@@ -108,6 +112,19 @@ FilterOperation::FilterOperation(FilterType type, float amount, int inset)
}
FilterOperation::FilterOperation(FilterType type,
+ float amount,
+ float outer_threshold)
+ : type_(type),
+ amount_(amount),
+ outer_threshold_(outer_threshold),
+ drop_shadow_offset_(0, 0),
+ drop_shadow_color_(0),
+ zoom_inset_(0) {
+ DCHECK_EQ(type_, STRETCH);
+ memset(matrix_, 0, sizeof(matrix_));
+}
+
+FilterOperation::FilterOperation(FilterType type,
sk_sp<PaintFilter> image_filter)
: type_(type),
amount_(0),
@@ -187,6 +204,8 @@ static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) {
case FilterOperation::ALPHA_THRESHOLD:
return FilterOperation::CreateAlphaThresholdFilter(
FilterOperation::ShapeRects(), 1.f, 0.f);
+ case FilterOperation::STRETCH:
+ return FilterOperation::CreateStretchFilter(0.f, 0.f);
}
NOTREACHED();
return FilterOperation::CreateEmptyFilter();
@@ -200,12 +219,13 @@ static float ClampAmountForFilterType(float amount,
case FilterOperation::INVERT:
case FilterOperation::OPACITY:
case FilterOperation::ALPHA_THRESHOLD:
- return base::ClampToRange(amount, 0.f, 1.f);
+ return base::clamp(amount, 0.f, 1.f);
case FilterOperation::SATURATE:
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::BLUR:
case FilterOperation::DROP_SHADOW:
+ case FilterOperation::STRETCH:
return std::max(amount, 0.f);
case FilterOperation::ZOOM:
return std::max(amount, 1.f);
@@ -331,6 +351,10 @@ void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const {
}
value->EndArray();
} break;
+ case FilterOperation::STRETCH:
+ value->SetDouble("amount_x", amount_);
+ value->SetDouble("amount_y", outer_threshold_);
+ break;
}
}
diff --git a/chromium/cc/paint/filter_operation.h b/chromium/cc/paint/filter_operation.h
index c989741e2dd..02002920792 100644
--- a/chromium/cc/paint/filter_operation.h
+++ b/chromium/cc/paint/filter_operation.h
@@ -6,6 +6,7 @@
#define CC_PAINT_FILTER_OPERATION_H_
#include <memory>
+#include <utility>
#include <vector>
#include "base/check_op.h"
@@ -46,7 +47,8 @@ class CC_PAINT_EXPORT FilterOperation {
REFERENCE,
SATURATING_BRIGHTNESS, // Not used in CSS/SVG.
ALPHA_THRESHOLD, // Not used in CSS/SVG.
- FILTER_TYPE_LAST = ALPHA_THRESHOLD
+ STRETCH, // Not used in CSS/SVG.
+ FILTER_TYPE_LAST = STRETCH
};
FilterOperation();
@@ -64,7 +66,7 @@ class CC_PAINT_EXPORT FilterOperation {
}
float outer_threshold() const {
- DCHECK_EQ(type_, ALPHA_THRESHOLD);
+ DCHECK(type_ == ALPHA_THRESHOLD || type_ == STRETCH);
return outer_threshold_;
}
@@ -171,6 +173,10 @@ class CC_PAINT_EXPORT FilterOperation {
outer_threshold);
}
+ static FilterOperation CreateStretchFilter(float amount_x, float amount_y) {
+ return FilterOperation(STRETCH, amount_x, amount_y);
+ }
+
bool operator==(const FilterOperation& other) const;
bool operator!=(const FilterOperation& other) const {
@@ -191,7 +197,7 @@ class CC_PAINT_EXPORT FilterOperation {
}
void set_outer_threshold(float outer_threshold) {
- DCHECK_EQ(type_, ALPHA_THRESHOLD);
+ DCHECK(type_ == ALPHA_THRESHOLD || type_ == STRETCH);
outer_threshold_ = outer_threshold;
}
@@ -265,6 +271,8 @@ class CC_PAINT_EXPORT FilterOperation {
FilterOperation(FilterType type, float amount, int inset);
+ FilterOperation(FilterType type, float amount, float outer_threshold);
+
FilterOperation(FilterType type, sk_sp<PaintFilter> image_filter);
FilterOperation(FilterType type,
diff --git a/chromium/cc/paint/filter_operations.cc b/chromium/cc/paint/filter_operations.cc
index 2c7c2ae62e9..0e906ea8f1c 100644
--- a/chromium/cc/paint/filter_operations.cc
+++ b/chromium/cc/paint/filter_operations.cc
@@ -82,6 +82,7 @@ bool FilterOperations::HasFilterThatMovesPixels() const {
case FilterOperation::BLUR:
case FilterOperation::DROP_SHADOW:
case FilterOperation::ZOOM:
+ case FilterOperation::STRETCH:
return true;
case FilterOperation::REFERENCE:
// TODO(hendrikw): SkImageFilter needs a function that tells us if the
@@ -128,6 +129,10 @@ float FilterOperations::MaximumPixelMovement() const {
// the filter can move pixels. See crbug.com/523538 (sort of).
max_movement = fmax(max_movement, 100);
continue;
+ case FilterOperation::STRETCH:
+ max_movement =
+ fmax(max_movement, fmax(op.amount(), op.outer_threshold()));
+ continue;
case FilterOperation::OPACITY:
case FilterOperation::COLOR_MATRIX:
case FilterOperation::GRAYSCALE:
@@ -173,6 +178,7 @@ bool FilterOperations::HasFilterThatAffectsOpacity() const {
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::SATURATING_BRIGHTNESS:
+ case FilterOperation::STRETCH:
break;
}
}
diff --git a/chromium/cc/paint/filter_operations_unittest.cc b/chromium/cc/paint/filter_operations_unittest.cc
index a51ea0f82eb..54fe83569ae 100644
--- a/chromium/cc/paint/filter_operations_unittest.cc
+++ b/chromium/cc/paint/filter_operations_unittest.cc
@@ -116,7 +116,7 @@ TEST(FilterOperationsTest, MapRectCombineNonCommutative) {
scaleMatrix.setScale(2, 2);
ops.Append(
FilterOperation::CreateReferenceFilter(sk_make_sp<MatrixPaintFilter>(
- scaleMatrix, kNone_SkFilterQuality, nullptr)));
+ scaleMatrix, PaintFlags::FilterQuality::kNone, nullptr)));
EXPECT_EQ(gfx::Rect(200, 200, 20, 20),
ops.MapRect(gfx::Rect(10, 10), SkMatrix::I()));
@@ -135,7 +135,7 @@ TEST(FilterOperationsTest, MapRectReverseCombineNonCommutative) {
scaleMatrix.setScale(2, 2);
ops.Append(
FilterOperation::CreateReferenceFilter(sk_make_sp<MatrixPaintFilter>(
- scaleMatrix, kNone_SkFilterQuality, nullptr)));
+ scaleMatrix, PaintFlags::FilterQuality::kNone, nullptr)));
EXPECT_EQ(gfx::Rect(10, 10),
ops.MapRectReverse(gfx::Rect(200, 200, 20, 20), SkMatrix::I()));
diff --git a/chromium/cc/paint/image_provider.h b/chromium/cc/paint/image_provider.h
index 6657d45f5c9..7a44dd3b01b 100644
--- a/chromium/cc/paint/image_provider.h
+++ b/chromium/cc/paint/image_provider.h
@@ -10,7 +10,6 @@
#include "cc/paint/draw_image.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_op_buffer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cc {
class PaintImage;
diff --git a/chromium/cc/paint/oop_pixeltest.cc b/chromium/cc/paint/oop_pixeltest.cc
index cee28e58b02..841a91246cf 100644
--- a/chromium/cc/paint/oop_pixeltest.cc
+++ b/chromium/cc/paint/oop_pixeltest.cc
@@ -23,6 +23,7 @@
#include "cc/test/pixel_test_utils.h"
#include "cc/tiles/gpu_image_decode_cache.h"
#include "components/viz/test/test_in_process_context_provider.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_implementation.h"
@@ -178,11 +179,16 @@ class OopPixelTest : public testing::Test,
raster_implementation->WaitSyncTokenCHROMIUM(
sii->GenUnverifiedSyncToken().GetConstData());
+ // Assume legacy MSAA if sample count is positive.
+ gpu::raster::MsaaMode msaa_mode = options.msaa_sample_count > 0
+ ? gpu::raster::kMSAA
+ : gpu::raster::kNoMSAA;
+
if (options.preclear) {
raster_implementation->BeginRasterCHROMIUM(
options.preclear_color, /*needs_clear=*/options.preclear,
- options.msaa_sample_count, options.use_lcd_text, options.color_space,
- mailbox.name);
+ options.msaa_sample_count, msaa_mode, options.use_lcd_text,
+ options.color_space, mailbox.name);
raster_implementation->EndRasterCHROMIUM();
}
@@ -192,8 +198,8 @@ class OopPixelTest : public testing::Test,
// cleared, so set |needs_clear| to false here.
raster_implementation->BeginRasterCHROMIUM(
options.background_color, /*needs_clear=*/!options.preclear,
- options.msaa_sample_count, options.use_lcd_text, options.color_space,
- mailbox.name);
+ options.msaa_sample_count, msaa_mode, options.use_lcd_text,
+ options.color_space, mailbox.name);
size_t max_op_size_limit =
gpu::raster::RasterInterface::kDefaultMaxOpSizeHint;
raster_implementation->RasterCHROMIUM(
@@ -227,7 +233,10 @@ class OopPixelTest : public testing::Test,
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 gl_texture_id =
+ gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name);
+ gl->BeginSharedImageAccessDirectCHROMIUM(
+ gl_texture_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
GLuint fbo_id;
gl->GenFramebuffers(1, &fbo_id);
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_id);
@@ -241,9 +250,11 @@ class OopPixelTest : public testing::Test,
new unsigned char[width * height * 4]);
gl->ReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.get());
- gl->DeleteTextures(1, &gl_texture_id);
gl->DeleteFramebuffers(1, &fbo_id);
+ gl->EndSharedImageAccessDirectCHROMIUM(gl_texture_id);
+ gl->DeleteTextures(1, &gl_texture_id);
+
// Swizzle rgba->bgra
std::vector<SkPMColor> colors;
colors.reserve(width * height);
@@ -415,7 +426,9 @@ class OopImagePixelTest : public OopPixelTest,
public ::testing::WithParamInterface<bool> {
public:
bool UseTooLargeImage() { return GetParam(); }
- SkFilterQuality FilterQuality() { return kNone_SkFilterQuality; }
+ PaintFlags::FilterQuality FilterQuality() {
+ return PaintFlags::FilterQuality::kNone;
+ }
gfx::Size GetImageSize() {
const int kMaxSize = 20000;
@@ -1777,31 +1790,37 @@ class OopTextBlobPixelTest
const int sdk = base::android::BuildInfo::GetInstance()->sdk_int();
if (sdk <= base::android::SDK_VERSION_MARSHMALLOW) {
error_pixels_percentage = 10.f;
- max_abs_error = 16;
+ max_abs_error = 20;
} else {
// Newer OSes occasionally have smaller flakes when using the real GPU
error_pixels_percentage = 1.5f;
max_abs_error = 2;
}
-#elif defined(OS_MAC) || defined(OS_WIN)
- // Mac and Windows need very small tolerances only under complex transforms
- if (GetMatrixStrategy(GetParam()) == MatrixStrategy::kComplex) {
- error_pixels_percentage = 0.2f;
- max_abs_error = 2;
- }
#endif
- // Regardless of OS, perspective triggers path rendering for each glyph,
- // which produces its own set of pixel differences.
- if (GetMatrixStrategy(GetParam()) == MatrixStrategy::kPerspective) {
- error_pixels_percentage = 4.f;
- max_abs_error = 36;
+ // Many platforms need very small tolerances under complex transforms,
+ // and higher tolerances for perspective, since it triggers path rendering
+ // for each glyph. Additionally, record filters require higher tolerance
+ // because oop-r converts raster-at-scale to fixed-scale.
+ float avg_error = max_abs_error;
+ const bool is_record_filter =
+ GetTextBlobStrategy(GetParam()) == TextBlobStrategy::kRecordFilter;
+ if (GetMatrixStrategy(GetParam()) == MatrixStrategy::kComplex) {
+ error_pixels_percentage =
+ std::max(is_record_filter ? 12.f : 0.2f, error_pixels_percentage);
+ max_abs_error = std::max(is_record_filter ? 220 : 2, max_abs_error);
+ avg_error = std::max(is_record_filter ? 50.f : 2.f, avg_error);
+ } else if (GetMatrixStrategy(GetParam()) == MatrixStrategy::kPerspective) {
+ error_pixels_percentage =
+ std::max(is_record_filter ? 13.f : 4.f, error_pixels_percentage);
+ max_abs_error = std::max(is_record_filter ? 255 : 36, max_abs_error);
+ avg_error = std::max(is_record_filter ? 60.f : 36.f, avg_error);
}
FuzzyPixelComparator comparator(
/*discard_alpha=*/false,
/*error_pixels_percentage_limit=*/error_pixels_percentage,
/*small_error_pixels_percentage_limit=*/0.0f,
- /*avg_abs_error_limit=*/max_abs_error,
+ /*avg_abs_error_limit=*/avg_error,
/*max_abs_error_limit=*/max_abs_error,
/*small_error_threshold=*/0);
ExpectEquals(actual, expected, comparator);
@@ -1857,14 +1876,14 @@ class OopTextBlobPixelTest
filter = nullptr;
}
if (strategy == TextBlobStrategy::kDirect) {
- display_list->push<DrawTextBlobOp>(std::move(text_blob), 0u, kTextBlobY,
+ display_list->push<DrawTextBlobOp>(std::move(text_blob), 0.0f, kTextBlobY,
text_flags);
return;
}
// All remaining strategies add the DrawTextBlobOp to an inner paint record.
auto paint_record = sk_make_sp<PaintOpBuffer>();
- paint_record->push<DrawTextBlobOp>(std::move(text_blob), 0u, kTextBlobY,
+ paint_record->push<DrawTextBlobOp>(std::move(text_blob), 0.0f, kTextBlobY,
text_flags);
if (strategy == TextBlobStrategy::kDrawRecord) {
display_list->push<DrawRecordOp>(std::move(paint_record));
@@ -1900,7 +1919,7 @@ class OopTextBlobPixelTest
// Use bilerp sampling with the PaintRecord to help reduce max RGB error
// from pixel-snapping flakiness when using NN sampling.
- record_flags.setFilterQuality(kLow_SkFilterQuality);
+ record_flags.setFilterQuality(PaintFlags::FilterQuality::kLow);
// The text blob is embedded in a paint record, which is attached to the
// paint via a shader or image filter. Just draw a rect with the paint.
@@ -2025,7 +2044,7 @@ TEST_F(OopPixelTest, DrawTextMultipleRasterCHROMIUM) {
PaintFlags flags;
flags.setStyle(PaintFlags::kFill_Style);
flags.setColor(SK_ColorGREEN);
- display_item_list->push<DrawTextBlobOp>(BuildTextBlob(sk_typeface_1), 0u,
+ display_item_list->push<DrawTextBlobOp>(BuildTextBlob(sk_typeface_1), 0.0f,
kTextBlobY, flags);
display_item_list->EndPaintOfUnpaired(options.full_raster_rect);
display_item_list->Finalize();
@@ -2033,7 +2052,7 @@ TEST_F(OopPixelTest, DrawTextMultipleRasterCHROMIUM) {
// Create another list with a different typeface.
auto display_item_list_2 = base::MakeRefCounted<DisplayItemList>();
display_item_list_2->StartPaint();
- display_item_list_2->push<DrawTextBlobOp>(BuildTextBlob(sk_typeface_2), 0u,
+ display_item_list_2->push<DrawTextBlobOp>(BuildTextBlob(sk_typeface_2), 0.0f,
kTextBlobY, flags);
display_item_list_2->EndPaintOfUnpaired(options.full_raster_rect);
display_item_list_2->Finalize();
@@ -2066,7 +2085,7 @@ TEST_F(OopPixelTest, DrawTextBlobPersistentShaderCache) {
PaintFlags flags;
flags.setStyle(PaintFlags::kFill_Style);
flags.setColor(SK_ColorGREEN);
- display_item_list->push<DrawTextBlobOp>(BuildTextBlob(), 0u, kTextBlobY,
+ display_item_list->push<DrawTextBlobOp>(BuildTextBlob(), 0.0f, kTextBlobY,
flags);
display_item_list->EndPaintOfUnpaired(options.full_raster_rect);
display_item_list->Finalize();
diff --git a/chromium/cc/paint/paint_cache.h b/chromium/cc/paint/paint_cache.h
index 728df5a36f3..1d53dace843 100644
--- a/chromium/cc/paint/paint_cache.h
+++ b/chromium/cc/paint/paint_cache.h
@@ -7,6 +7,8 @@
#include <map>
#include <set>
+#include <utility>
+#include <vector>
#include "base/containers/mru_cache.h"
#include "base/containers/stack_container.h"
@@ -41,7 +43,8 @@ enum class PaintCacheEntryState : uint32_t {
kEmpty,
kCached,
kInlined,
- kLast = kInlined
+ kInlinedDoNotCache,
+ kLast = kInlinedDoNotCache
};
constexpr size_t PaintCacheDataTypeCount =
diff --git a/chromium/cc/paint/paint_cache_unittest.cc b/chromium/cc/paint/paint_cache_unittest.cc
index 1db78de82c7..60ab43062ec 100644
--- a/chromium/cc/paint/paint_cache_unittest.cc
+++ b/chromium/cc/paint/paint_cache_unittest.cc
@@ -4,7 +4,6 @@
#include "cc/paint/paint_cache.h"
-#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
diff --git a/chromium/cc/paint/paint_canvas.h b/chromium/cc/paint/paint_canvas.h
index 91626067d33..ec980047a91 100644
--- a/chromium/cc/paint/paint_canvas.h
+++ b/chromium/cc/paint/paint_canvas.h
@@ -12,7 +12,8 @@
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_image.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkTextBlob.h"
+
+class SkTextBlob;
namespace printing {
class MetafileSkia;
@@ -27,6 +28,8 @@ class SkottieWrapper;
class PaintFlags;
class PaintOpBuffer;
+enum class UsePaintCache { kDisabled = 0, kEnabled };
+
using PaintRecord = PaintOpBuffer;
// PaintCanvas is the cc/paint wrapper of SkCanvas. It has a more restricted
@@ -109,10 +112,17 @@ class CC_PAINT_EXPORT PaintCanvas {
virtual void clipPath(const SkPath& path,
SkClipOp op,
- bool do_anti_alias) = 0;
- void clipPath(const SkPath& path, SkClipOp op) { clipPath(path, op, false); }
+ bool do_anti_alias,
+ UsePaintCache) = 0;
+ void clipPath(const SkPath& path, SkClipOp op, bool do_anti_alias) {
+ clipPath(path, op, do_anti_alias, UsePaintCache::kEnabled);
+ }
+ void clipPath(const SkPath& path, SkClipOp op) {
+ clipPath(path, op, /*do_anti_alias=*/false, UsePaintCache::kEnabled);
+ }
void clipPath(const SkPath& path, bool do_anti_alias) {
- clipPath(path, SkClipOp::kIntersect, do_anti_alias);
+ clipPath(path, SkClipOp::kIntersect, do_anti_alias,
+ UsePaintCache::kEnabled);
}
virtual SkRect getLocalClipBounds() const = 0;
@@ -141,7 +151,12 @@ class CC_PAINT_EXPORT PaintCanvas {
SkScalar rx,
SkScalar ry,
const PaintFlags& flags) = 0;
- virtual void drawPath(const SkPath& path, const PaintFlags& flags) = 0;
+ virtual void drawPath(const SkPath& path,
+ const PaintFlags& flags,
+ UsePaintCache) = 0;
+ void drawPath(const SkPath& path, const PaintFlags& flags) {
+ drawPath(path, flags, UsePaintCache::kEnabled);
+ }
virtual void drawImage(const PaintImage& image,
SkScalar left,
SkScalar top,
diff --git a/chromium/cc/paint/paint_filter.cc b/chromium/cc/paint/paint_filter.cc
index 2982969f573..6df6898d3a8 100644
--- a/chromium/cc/paint/paint_filter.cc
+++ b/chromium/cc/paint/paint_filter.cc
@@ -4,19 +4,246 @@
#include "cc/paint/paint_filter.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/no_destructor.h"
+#include "build/build_config.h"
#include "cc/paint/filter_operations.h"
#include "cc/paint/paint_image_builder.h"
#include "cc/paint/paint_op_writer.h"
#include "cc/paint/paint_record.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkMath.h"
+#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
#include "third_party/skia/include/effects/SkPerlinNoiseShader.h"
+#include "third_party/skia/include/effects/SkRuntimeEffect.h"
+#include "third_party/skia/src/effects/imagefilters/SkRuntimeImageFilter.h"
namespace cc {
namespace {
const bool kHasNoDiscardableImages = false;
+#if defined(OS_ANDROID)
+struct StretchShaderUniforms {
+ // multiplier to apply to scale effect
+ float uMaxStretchIntensity;
+
+ // Maximum percentage to stretch beyond bounds of target
+ float uStretchAffectedDistX;
+ float uStretchAffectedDistY;
+
+ // Distance stretched as a function of the normalized overscroll times
+ // scale intensity
+ float uDistanceStretchedX;
+ float uDistanceStretchedY;
+ float uInverseDistanceStretchedX;
+ float uInverseDistanceStretchedY;
+ float uDistDiffX;
+
+ // Difference between the peak stretch amount and overscroll amount normalized
+ float uDistDiffY;
+
+ // Horizontal offset represented as a ratio of pixels divided by the target
+ // width
+ float uScrollX;
+ // Vertical offset represented as a ratio of pixels divided by the target
+ // height
+ float uScrollY;
+
+ // Normalized overscroll amount in the horizontal direction
+ float uOverscrollX;
+
+ // Normalized overscroll amount in the vertical direction
+ float uOverscrollY;
+ float viewportWidth; // target height in pixels
+ float viewportHeight; // target width in pixels
+
+ // uInterpolationStrength is the intensity of the interpolation.
+ // if uInterpolationStrength is 0, then the stretch is constant for all the
+ // uStretchAffectedDist. if uInterpolationStrength is 1, then stretch
+ // intensity is interpolated based on the pixel position in the
+ // uStretchAffectedDist area; The closer we are from the scroll anchor point,
+ // the more it stretches, and the other way around.
+ float uInterpolationStrength;
+};
+
+const char* kStretchShader = R"(
+ uniform shader uContentTexture;
+
+ // multiplier to apply to scale effect
+ uniform float uMaxStretchIntensity;
+
+ // Maximum percentage to stretch beyond bounds of target
+ uniform float uStretchAffectedDistX;
+ uniform float uStretchAffectedDistY;
+
+ // Distance stretched as a function of the normalized overscroll times
+ // scale intensity
+ uniform float uDistanceStretchedX;
+ uniform float uDistanceStretchedY;
+ uniform float uInverseDistanceStretchedX;
+ uniform float uInverseDistanceStretchedY;
+ uniform float uDistDiffX;
+
+ // Difference between the peak stretch amount and overscroll amount
+ // normalized
+ uniform float uDistDiffY;
+
+ // Horizontal offset represented as a ratio of pixels divided by the target
+ // width
+ uniform float uScrollX;
+ // Vertical offset represented as a ratio of pixels divided by the target
+ // height
+ uniform float uScrollY;
+
+ // Normalized overscroll amount in the horizontal direction
+ uniform float uOverscrollX;
+
+ // Normalized overscroll amount in the vertical direction
+ uniform float uOverscrollY;
+ uniform float viewportWidth; // target height in pixels
+ uniform float viewportHeight; // target width in pixels
+
+ // uInterpolationStrength is the intensity of the interpolation.
+ // if uInterpolationStrength is 0, then the stretch is constant for all the
+ // uStretchAffectedDist. if uInterpolationStrength is 1, then stretch
+ // intensity is interpolated based on the pixel position in the
+ // uStretchAffectedDist area; The closer we are from the scroll anchor
+ // point, the more it stretches, and the other way around.
+ uniform float uInterpolationStrength;
+
+ float easeInCubic(float t, float d) {
+ float tmp = t * d;
+ return tmp * tmp * tmp;
+ }
+
+ float computeOverscrollStart(
+ float inPos,
+ float overscroll,
+ float uStretchAffectedDist,
+ float uInverseStretchAffectedDist,
+ float distanceStretched,
+ float interpolationStrength
+ ) {
+ float offsetPos = uStretchAffectedDist - inPos;
+ float posBasedVariation = mix(
+ 1. ,easeInCubic(offsetPos, uInverseStretchAffectedDist),
+ interpolationStrength);
+ float stretchIntensity = overscroll * posBasedVariation;
+ return distanceStretched - (offsetPos / (1. + stretchIntensity));
+ }
+
+ float computeOverscrollEnd(
+ float inPos,
+ float overscroll,
+ float reverseStretchDist,
+ float uStretchAffectedDist,
+ float uInverseStretchAffectedDist,
+ float distanceStretched,
+ float interpolationStrength
+ ) {
+ float offsetPos = inPos - reverseStretchDist;
+ float posBasedVariation = mix(
+ 1. ,easeInCubic(offsetPos, uInverseStretchAffectedDist),
+ interpolationStrength);
+ float stretchIntensity = (-overscroll) * posBasedVariation;
+ return 1 - (distanceStretched - (offsetPos / (1. + stretchIntensity)));
+ }
+
+ // Prefer usage of return values over out parameters as it enables
+ // SKSL to properly inline method calls and works around potential GPU
+ // driver issues on Wembly. See b/182566543 for details
+ float computeOverscroll(
+ float inPos,
+ float overscroll,
+ float uStretchAffectedDist,
+ float uInverseStretchAffectedDist,
+ float distanceStretched,
+ float distanceDiff,
+ float interpolationStrength
+ ) {
+ float outPos = inPos;
+ if (overscroll > 0) {
+ if (inPos <= uStretchAffectedDist) {
+ outPos = computeOverscrollStart(
+ inPos,
+ overscroll,
+ uStretchAffectedDist,
+ uInverseStretchAffectedDist,
+ distanceStretched,
+ interpolationStrength
+ );
+ } else if (inPos >= distanceStretched) {
+ outPos = distanceDiff + inPos;
+ }
+ }
+ if (overscroll < 0) {
+ float stretchAffectedDist = 1. - uStretchAffectedDist;
+ if (inPos >= stretchAffectedDist) {
+ outPos = computeOverscrollEnd(
+ inPos,
+ overscroll,
+ stretchAffectedDist,
+ uStretchAffectedDist,
+ uInverseStretchAffectedDist,
+ distanceStretched,
+ interpolationStrength
+ );
+ } else if (inPos < stretchAffectedDist) {
+ outPos = -distanceDiff + inPos;
+ }
+ }
+ return outPos;
+ }
+
+ vec4 main(vec2 coord) {
+ // Normalize SKSL pixel coordinate into a unit vector
+ float inU = coord.x / viewportWidth;
+ float inV = coord.y / viewportHeight;
+ float outU;
+ float outV;
+ float stretchIntensity;
+ // Add the normalized scroll position within scrolling list
+ inU += uScrollX;
+ inV += uScrollY;
+ outU = inU;
+ outV = inV;
+ outU = computeOverscroll(
+ inU,
+ uOverscrollX,
+ uStretchAffectedDistX,
+ uInverseDistanceStretchedX,
+ uDistanceStretchedX,
+ uDistDiffX,
+ uInterpolationStrength
+ );
+ outV = computeOverscroll(
+ inV,
+ uOverscrollY,
+ uStretchAffectedDistY,
+ uInverseDistanceStretchedY,
+ uDistanceStretchedY,
+ uDistDiffY,
+ uInterpolationStrength
+ );
+ coord.x = outU * viewportWidth;
+ coord.y = outV * viewportHeight;
+ return sample(uContentTexture, coord);
+ })";
+
+static const float CONTENT_DISTANCE_STRETCHED = 1.f;
+static const float INTERPOLATION_STRENGTH_VALUE = 0.7f;
+
+sk_sp<SkRuntimeEffect> getStretchEffect() {
+ static base::NoDestructor<SkRuntimeEffect::Result> effect(
+ SkRuntimeEffect::MakeForShader(SkString(kStretchShader)));
+ return effect->effect;
+}
+#endif
+
bool AreFiltersEqual(const PaintFilter* one, const PaintFilter* two) {
if (!one || !two)
return !one && !two;
@@ -107,6 +334,8 @@ std::string PaintFilter::TypeToString(Type type) {
return "kLightingPoint";
case Type::kLightingSpot:
return "kLightingSpot";
+ case Type::kStretch:
+ return "kStretch";
}
NOTREACHED();
return "Unknown";
@@ -219,6 +448,9 @@ bool PaintFilter::operator==(const PaintFilter& other) const {
case Type::kLightingSpot:
return *static_cast<const LightingSpotPaintFilter*>(this) ==
static_cast<const LightingSpotPaintFilter&>(other);
+ case Type::kStretch:
+ return *static_cast<const StretchPaintFilter*>(this) ==
+ static_cast<const StretchPaintFilter&>(other);
}
NOTREACHED();
return true;
@@ -658,7 +890,7 @@ bool DisplacementMapEffectPaintFilter::operator==(
ImagePaintFilter::ImagePaintFilter(PaintImage image,
const SkRect& src_rect,
const SkRect& dst_rect,
- SkFilterQuality filter_quality)
+ PaintFlags::FilterQuality filter_quality)
: PaintFilter(kType, nullptr, !image.IsTextureBacked()),
image_(std::move(image)),
src_rect_(src_rect),
@@ -709,24 +941,90 @@ bool ImagePaintFilter::operator==(const ImagePaintFilter& other) const {
}
RecordPaintFilter::RecordPaintFilter(sk_sp<PaintRecord> record,
- const SkRect& record_bounds)
- : RecordPaintFilter(std::move(record), record_bounds, nullptr) {}
+ const SkRect& record_bounds,
+ const gfx::SizeF& raster_scale,
+ ScalingBehavior scaling_behavior)
+ : RecordPaintFilter(std::move(record),
+ record_bounds,
+ raster_scale,
+ scaling_behavior,
+ nullptr) {}
RecordPaintFilter::RecordPaintFilter(sk_sp<PaintRecord> record,
const SkRect& record_bounds,
+ const gfx::SizeF& raster_scale,
+ ScalingBehavior scaling_behavior,
ImageProvider* image_provider)
: PaintFilter(kType, nullptr, record->HasDiscardableImages()),
record_(std::move(record)),
- record_bounds_(record_bounds) {
- cached_sk_filter_ = SkImageFilters::Picture(
- ToSkPicture(record_, record_bounds_, image_provider));
+ record_bounds_(record_bounds),
+ raster_scale_(raster_scale),
+ scaling_behavior_(scaling_behavior) {
+ DCHECK(raster_scale_.width() > 0.f && raster_scale_.height() > 0.f);
+
+ sk_sp<SkPicture> picture =
+ ToSkPicture(record_, record_bounds_, image_provider);
+
+ if (scaling_behavior == ScalingBehavior::kRasterAtScale ||
+ record_bounds_.isEmpty()) {
+ cached_sk_filter_ = SkImageFilters::Picture(std::move(picture));
+ } else {
+ DCHECK(scaling_behavior == ScalingBehavior::kFixedScale);
+ // Convert the record to an image and then reference that in the filter DAG
+ int width = SkScalarCeilToInt(record_bounds.width());
+ int height = SkScalarCeilToInt(record_bounds.height());
+ auto image = SkImage::MakeFromPicture(
+ std::move(picture), SkISize::Make(width, height), nullptr, nullptr,
+ SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
+
+ // Must account for the raster scale when drawing the picture image,
+ SkRect src = SkRect::MakeWH(record_bounds.width(), record_bounds.height());
+ SkScalar inv_x = 1.f / raster_scale_.width();
+ SkScalar inv_y = 1.f / raster_scale_.height();
+ SkRect dst = {inv_x * src.fLeft, inv_y * src.fTop, inv_x * src.fRight,
+ inv_y * src.fBottom};
+
+ // Use Mitchell cubic filter, matching historic
+ // PaintFlags::FilterQuality::kHigh
+ SkSamplingOptions sampling(SkCubicResampler::Mitchell());
+ cached_sk_filter_ =
+ SkImageFilters::Image(std::move(image), src, dst, sampling);
+ }
}
RecordPaintFilter::~RecordPaintFilter() = default;
+sk_sp<RecordPaintFilter> RecordPaintFilter::CreateScaledPaintRecord(
+ const SkMatrix& ctm,
+ int max_texture_size) const {
+ // If this is already fixed scale, then this is already good to go, and if
+ // the bounds are empty the filter produces no output so keep it as-is.
+ if (scaling_behavior_ == ScalingBehavior::kFixedScale ||
+ record_bounds_.isEmpty()) {
+ return sk_ref_sp<RecordPaintFilter>(this);
+ }
+
+ // For creating a deserialized RecordPaintFilter, extract the scale factor at
+ // which it would have been rasterized at for the given ctm. This is modeled
+ // after PaintShader::CreateScaledPaintRecord.
+ SkRect scaled_record_bounds =
+ PaintRecord::GetFixedScaleBounds(ctm, record_bounds_, max_texture_size);
+ if (scaled_record_bounds.isEmpty())
+ return nullptr;
+
+ gfx::SizeF raster_scale = {
+ scaled_record_bounds.width() / record_bounds_.width(),
+ scaled_record_bounds.height() / record_bounds_.height()};
+
+ return sk_make_sp<RecordPaintFilter>(record_, scaled_record_bounds,
+ raster_scale,
+ ScalingBehavior::kFixedScale);
+}
+
size_t RecordPaintFilter::SerializedSize() const {
base::CheckedNumeric<size_t> total_size =
- BaseSerializedSize() + sizeof(record_bounds_);
+ BaseSerializedSize() + sizeof(record_bounds_) + sizeof(raster_scale_) +
+ sizeof(scaling_behavior_) + sizeof(bool);
total_size += PaintOpWriter::GetRecordSize(record_.get());
return total_size.ValueOrDefault(0u);
}
@@ -734,11 +1032,14 @@ size_t RecordPaintFilter::SerializedSize() const {
sk_sp<PaintFilter> RecordPaintFilter::SnapshotWithImagesInternal(
ImageProvider* image_provider) const {
return sk_sp<RecordPaintFilter>(
- new RecordPaintFilter(record_, record_bounds_, image_provider));
+ new RecordPaintFilter(record_, record_bounds_, raster_scale_,
+ scaling_behavior_, image_provider));
}
bool RecordPaintFilter::operator==(const RecordPaintFilter& other) const {
return !!record_ == !!other.record_ &&
+ scaling_behavior_ == other.scaling_behavior_ &&
+ raster_scale_ == other.raster_scale_ &&
PaintOp::AreSkRectsEqual(record_bounds_, other.record_bounds_);
}
@@ -964,7 +1265,7 @@ bool TurbulencePaintFilter::operator==(
ShaderPaintFilter::ShaderPaintFilter(sk_sp<PaintShader> shader,
uint8_t alpha,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
SkImageFilters::Dither dither,
const CropRect* crop_rect)
: PaintFilter(kType, crop_rect, shader->has_discardable_images()),
@@ -1028,7 +1329,7 @@ bool ShaderPaintFilter::operator==(const ShaderPaintFilter& other) const {
}
MatrixPaintFilter::MatrixPaintFilter(const SkMatrix& matrix,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
sk_sp<PaintFilter> input)
: PaintFilter(Type::kMatrix, nullptr, HasDiscardableImages(input)),
matrix_(matrix),
@@ -1251,4 +1552,78 @@ bool LightingSpotPaintFilter::operator==(
AreFiltersEqual(input_.get(), other.input_.get());
}
+StretchPaintFilter::StretchPaintFilter(SkScalar stretch_x,
+ SkScalar stretch_y,
+ SkScalar width,
+ SkScalar height,
+ sk_sp<PaintFilter> input,
+ const CropRect* crop_rect)
+ : PaintFilter(kType, crop_rect, HasDiscardableImages(input)),
+ stretch_x_(stretch_x),
+ stretch_y_(stretch_y),
+ width_(width),
+ height_(height),
+ input_(std::move(input)) {
+#if defined(OS_ANDROID)
+ float normOverScrollDistX = stretch_x_;
+ float normOverScrollDistY = stretch_y_;
+ float distanceStretchedX =
+ CONTENT_DISTANCE_STRETCHED / (1 + std::abs(normOverScrollDistX));
+ float distanceStretchedY =
+ CONTENT_DISTANCE_STRETCHED / (1 + std::abs(normOverScrollDistY));
+ float inverseDistanceStretchedX = 1.f / CONTENT_DISTANCE_STRETCHED;
+ float inverseDistanceStretchedY = 1.f / CONTENT_DISTANCE_STRETCHED;
+ float diffX = distanceStretchedX - CONTENT_DISTANCE_STRETCHED;
+ float diffY = distanceStretchedY - CONTENT_DISTANCE_STRETCHED;
+ StretchShaderUniforms uniforms;
+
+ uniforms.uInterpolationStrength = INTERPOLATION_STRENGTH_VALUE;
+ uniforms.uStretchAffectedDistX = CONTENT_DISTANCE_STRETCHED;
+ uniforms.uStretchAffectedDistY = CONTENT_DISTANCE_STRETCHED;
+ uniforms.uDistanceStretchedX = distanceStretchedX;
+ uniforms.uDistanceStretchedY = distanceStretchedY;
+ uniforms.uInverseDistanceStretchedX = inverseDistanceStretchedX;
+ uniforms.uInverseDistanceStretchedY = inverseDistanceStretchedY;
+ uniforms.uDistDiffX = diffX;
+ uniforms.uDistDiffY = diffY;
+ uniforms.uOverscrollX = normOverScrollDistX;
+ uniforms.uOverscrollY = normOverScrollDistY;
+ uniforms.uScrollX = 0;
+ uniforms.uScrollY = 0;
+ uniforms.viewportWidth = width;
+ uniforms.viewportHeight = height;
+ sk_sp<SkData> uniformVals = SkData::MakeWithCopy(&uniforms, sizeof(uniforms));
+ cached_sk_filter_ = SkMakeRuntimeImageFilter(getStretchEffect(), uniformVals,
+ GetSkFilter(input_.get()));
+#else // defined(OS_ANDROID)
+ // Stretch filter is only used on android and removed from other platforms
+ // to reduce size. See https://crbug.com/1226170.
+#endif // defined(OS_ANDROID)
+}
+
+StretchPaintFilter::~StretchPaintFilter() = default;
+
+size_t StretchPaintFilter::SerializedSize() const {
+ base::CheckedNumeric<size_t> total_size =
+ BaseSerializedSize() + sizeof(stretch_x_) + sizeof(stretch_y_) +
+ sizeof(width_) + sizeof(height_);
+ total_size += GetFilterSize(input_.get());
+ return total_size.ValueOrDefault(0u);
+}
+
+sk_sp<PaintFilter> StretchPaintFilter::SnapshotWithImagesInternal(
+ ImageProvider* image_provider) const {
+ return sk_make_sp<StretchPaintFilter>(stretch_x_, stretch_y_, width_, height_,
+ Snapshot(input_, image_provider),
+ crop_rect());
+}
+
+bool StretchPaintFilter::operator==(const StretchPaintFilter& other) const {
+ return PaintOp::AreEqualEvenIfNaN(stretch_x_, other.stretch_x_) &&
+ PaintOp::AreEqualEvenIfNaN(stretch_y_, other.stretch_y_) &&
+ PaintOp::AreEqualEvenIfNaN(width_, other.width_) &&
+ PaintOp::AreEqualEvenIfNaN(height_, other.height_) &&
+ AreFiltersEqual(input_.get(), other.input_.get());
+}
+
} // namespace cc
diff --git a/chromium/cc/paint/paint_filter.h b/chromium/cc/paint/paint_filter.h
index 019811fe024..3f11012035e 100644
--- a/chromium/cc/paint/paint_filter.h
+++ b/chromium/cc/paint/paint_filter.h
@@ -5,6 +5,8 @@
#ifndef CC_PAINT_PAINT_FILTER_H_
#define CC_PAINT_PAINT_FILTER_H_
+#include <string>
+
#include "base/check_op.h"
#include "base/containers/stack_container.h"
#include "base/stl_util.h"
@@ -56,8 +58,9 @@ class CC_PAINT_EXPORT PaintFilter : public SkRefCnt {
kLightingDistant,
kLightingPoint,
kLightingSpot,
- // Update the following if kLightingSpot is not the max anymore.
- kMaxValue = kLightingSpot
+ kStretch,
+ // Update the following if kStretch is not the max anymore.
+ kMaxValue = kStretch
};
enum class LightingType {
kDiffuse,
@@ -474,13 +477,13 @@ class CC_PAINT_EXPORT ImagePaintFilter final : public PaintFilter {
ImagePaintFilter(PaintImage image,
const SkRect& src_rect,
const SkRect& dst_rect,
- SkFilterQuality filter_quality);
+ PaintFlags::FilterQuality filter_quality);
~ImagePaintFilter() override;
const PaintImage& image() const { return image_; }
const SkRect& src_rect() const { return src_rect_; }
const SkRect& dst_rect() const { return dst_rect_; }
- SkFilterQuality filter_quality() const { return filter_quality_; }
+ PaintFlags::FilterQuality filter_quality() const { return filter_quality_; }
size_t SerializedSize() const override;
bool operator==(const ImagePaintFilter& other) const;
@@ -493,17 +496,33 @@ class CC_PAINT_EXPORT ImagePaintFilter final : public PaintFilter {
PaintImage image_;
SkRect src_rect_;
SkRect dst_rect_;
- SkFilterQuality filter_quality_;
+ PaintFlags::FilterQuality filter_quality_;
};
class CC_PAINT_EXPORT RecordPaintFilter final : public PaintFilter {
public:
static constexpr Type kType = Type::kPaintRecord;
- RecordPaintFilter(sk_sp<PaintRecord> record, const SkRect& record_bounds);
+
+ using ScalingBehavior = PaintShader::ScalingBehavior;
+
+ RecordPaintFilter(
+ sk_sp<PaintRecord> record,
+ const SkRect& record_bounds,
+ const gfx::SizeF& raster_scale = {1.f, 1.f},
+ ScalingBehavior scaling_behavior = ScalingBehavior::kRasterAtScale);
~RecordPaintFilter() override;
+ // Creates a fixed scale RecordPaintFilter for rasterization at the given
+ // |ctm|. |raster_scale| is set to the scale at which the underlying record
+ // should be rasterized when the paint filter is used.
+ // See PaintShader::CreateScaledPaintRecord.
+ sk_sp<RecordPaintFilter> CreateScaledPaintRecord(const SkMatrix& ctm,
+ int max_texture_size) const;
+
const sk_sp<PaintRecord>& record() const { return record_; }
SkRect record_bounds() const { return record_bounds_; }
+ gfx::SizeF raster_scale() const { return raster_scale_; }
+ ScalingBehavior scaling_behavior() const { return scaling_behavior_; }
size_t SerializedSize() const override;
bool operator==(const RecordPaintFilter& other) const;
@@ -515,10 +534,14 @@ class CC_PAINT_EXPORT RecordPaintFilter final : public PaintFilter {
private:
RecordPaintFilter(sk_sp<PaintRecord> record,
const SkRect& record_bounds,
+ const gfx::SizeF& raster_scale,
+ ScalingBehavior scaling_behavior,
ImageProvider* image_provider);
sk_sp<PaintRecord> record_;
SkRect record_bounds_;
+ gfx::SizeF raster_scale_; // ignored if scaling_behavior is kRasterAtScale
+ ScalingBehavior scaling_behavior_;
};
class CC_PAINT_EXPORT MergePaintFilter final : public PaintFilter {
@@ -679,7 +702,7 @@ class CC_PAINT_EXPORT ShaderPaintFilter final : public PaintFilter {
ShaderPaintFilter(sk_sp<PaintShader> shader,
uint8_t alpha,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
SkImageFilters::Dither dither,
const CropRect* crop_rect = nullptr);
@@ -687,7 +710,7 @@ class CC_PAINT_EXPORT ShaderPaintFilter final : public PaintFilter {
const PaintShader& shader() const { return *shader_; }
uint8_t alpha() const { return alpha_; }
- SkFilterQuality filter_quality() const { return filter_quality_; }
+ PaintFlags::FilterQuality filter_quality() const { return filter_quality_; }
SkImageFilters::Dither dither() const { return dither_; }
size_t SerializedSize() const override;
@@ -700,7 +723,7 @@ class CC_PAINT_EXPORT ShaderPaintFilter final : public PaintFilter {
private:
sk_sp<PaintShader> shader_;
uint8_t alpha_;
- SkFilterQuality filter_quality_;
+ PaintFlags::FilterQuality filter_quality_;
SkImageFilters::Dither dither_;
};
@@ -708,12 +731,12 @@ class CC_PAINT_EXPORT MatrixPaintFilter final : public PaintFilter {
public:
static constexpr Type kType = Type::kMatrix;
MatrixPaintFilter(const SkMatrix& matrix,
- SkFilterQuality filter_quality,
+ PaintFlags::FilterQuality filter_quality,
sk_sp<PaintFilter> input);
~MatrixPaintFilter() override;
const SkMatrix& matrix() const { return matrix_; }
- SkFilterQuality filter_quality() const { return filter_quality_; }
+ PaintFlags::FilterQuality filter_quality() const { return filter_quality_; }
const sk_sp<PaintFilter>& input() const { return input_; }
size_t SerializedSize() const override;
@@ -725,7 +748,7 @@ class CC_PAINT_EXPORT MatrixPaintFilter final : public PaintFilter {
private:
SkMatrix matrix_;
- SkFilterQuality filter_quality_;
+ PaintFlags::FilterQuality filter_quality_;
sk_sp<PaintFilter> input_;
};
@@ -861,6 +884,39 @@ class CC_PAINT_EXPORT LightingSpotPaintFilter final : public PaintFilter {
sk_sp<PaintFilter> input_;
};
+class CC_PAINT_EXPORT StretchPaintFilter final : public PaintFilter {
+ public:
+ static constexpr Type kType = Type::kStretch;
+ StretchPaintFilter(SkScalar stretch_x,
+ SkScalar stretch_y,
+ SkScalar width,
+ SkScalar height,
+ sk_sp<PaintFilter> input,
+ const CropRect* crop_rect = nullptr);
+ ~StretchPaintFilter() override;
+
+ const sk_sp<PaintFilter>& input() const { return input_; }
+
+ SkScalar stretch_x() const { return stretch_x_; }
+ SkScalar stretch_y() const { return stretch_y_; }
+ SkScalar width() const { return width_; }
+ SkScalar height() const { return height_; }
+
+ size_t SerializedSize() const override;
+ bool operator==(const StretchPaintFilter& other) const;
+
+ protected:
+ sk_sp<PaintFilter> SnapshotWithImagesInternal(
+ ImageProvider* image_provider) const override;
+
+ private:
+ SkScalar stretch_x_;
+ SkScalar stretch_y_;
+ SkScalar width_;
+ SkScalar height_;
+ sk_sp<PaintFilter> input_;
+};
+
} // namespace cc
#endif // CC_PAINT_PAINT_FILTER_H_
diff --git a/chromium/cc/paint/paint_filter_unittest.cc b/chromium/cc/paint/paint_filter_unittest.cc
index 8b84f2f53d5..ddb8ac02a52 100644
--- a/chromium/cc/paint/paint_filter_unittest.cc
+++ b/chromium/cc/paint/paint_filter_unittest.cc
@@ -38,7 +38,7 @@ sk_sp<PaintFilter> CreateTestFilter(PaintFilter::Type filter_type,
auto image_filter = sk_make_sp<ImagePaintFilter>(
image, SkRect::MakeWH(100.f, 100.f), SkRect::MakeWH(100.f, 100.f),
- kNone_SkFilterQuality);
+ PaintFlags::FilterQuality::kNone);
auto record = sk_make_sp<PaintOpBuffer>();
record->push<DrawImageOp>(image, 0.f, 0.f);
auto record_filter =
@@ -114,12 +114,12 @@ sk_sp<PaintFilter> CreateTestFilter(PaintFilter::Type filter_type,
return sk_make_sp<ShaderPaintFilter>(
PaintShader::MakeImage(image, SkTileMode::kClamp, SkTileMode::kClamp,
nullptr),
- /*alpha=*/255, kNone_SkFilterQuality, SkImageFilters::Dither::kNo,
- &crop_rect);
+ /*alpha=*/255, PaintFlags::FilterQuality::kNone,
+ SkImageFilters::Dither::kNo, &crop_rect);
}
case PaintFilter::Type::kMatrix:
- return sk_make_sp<MatrixPaintFilter>(SkMatrix::I(), kNone_SkFilterQuality,
- record_filter);
+ return sk_make_sp<MatrixPaintFilter>(
+ SkMatrix::I(), PaintFlags::FilterQuality::kNone, record_filter);
case PaintFilter::Type::kLightingDistant:
return sk_make_sp<LightingDistantPaintFilter>(
PaintFilter::LightingType::kDiffuse, SkPoint3::Make(0.1f, 0.2f, 0.3f),
@@ -133,6 +133,9 @@ sk_sp<PaintFilter> CreateTestFilter(PaintFilter::Type filter_type,
PaintFilter::LightingType::kDiffuse, SkPoint3::Make(0.1f, 0.2f, 0.3f),
SkPoint3::Make(0.4f, 0.5f, 0.6f), 0.1f, 0.2f, SK_ColorWHITE, 0.4f,
0.5f, 0.6f, image_filter, &crop_rect);
+ case PaintFilter::Type::kStretch:
+ return sk_make_sp<StretchPaintFilter>(0.1f, 0.2f, 100.f, 200.f,
+ image_filter, &crop_rect);
}
NOTREACHED();
return nullptr;
diff --git a/chromium/cc/paint/paint_flags.cc b/chromium/cc/paint/paint_flags.cc
index 5f4af712f04..8a83963b968 100644
--- a/chromium/cc/paint/paint_flags.cc
+++ b/chromium/cc/paint/paint_flags.cc
@@ -9,6 +9,7 @@
#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_op_buffer.h"
#include "cc/paint/paint_op_writer.h"
+#include "cc/paint/paint_shader.h"
namespace {
@@ -26,7 +27,8 @@ PaintFlags::PaintFlags() {
bitfields_.cap_type_ = SkPaint::kDefault_Cap;
bitfields_.join_type_ = SkPaint::kDefault_Join;
bitfields_.style_ = SkPaint::kFill_Style;
- bitfields_.filter_quality_ = SkFilterQuality::kNone_SkFilterQuality;
+ bitfields_.filter_quality_ =
+ static_cast<int>(PaintFlags::FilterQuality::kNone);
static_assert(sizeof(bitfields_) <= sizeof(bitfields_uint_),
"Too many bitfields");
@@ -59,6 +61,14 @@ void PaintFlags::setImageFilter(sk_sp<PaintFilter> filter) {
image_filter_ = std::move(filter);
}
+bool PaintFlags::ShaderIsOpaque() const {
+ return shader_->IsOpaque();
+}
+
+void PaintFlags::setShader(sk_sp<PaintShader> shader) {
+ shader_ = std::move(shader);
+}
+
bool PaintFlags::nothingToDraw() const {
// Duplicated from SkPaint to avoid having to construct an SkPaint to
// answer this question.
@@ -142,20 +152,19 @@ SkPaint PaintFlags::ToSkPaint() const {
paint.setStrokeCap(static_cast<SkPaint::Cap>(getStrokeCap()));
paint.setStrokeJoin(static_cast<SkPaint::Join>(getStrokeJoin()));
paint.setStyle(static_cast<SkPaint::Style>(getStyle()));
- paint.setFilterQuality(getFilterQuality());
return paint;
}
SkSamplingOptions PaintFlags::FilterQualityToSkSamplingOptions(
- SkFilterQuality filter_quality) {
+ PaintFlags::FilterQuality filter_quality) {
switch (filter_quality) {
- case SkFilterQuality::kHigh_SkFilterQuality:
- return SkSamplingOptions(SkCubicResampler::Mitchell());
- case SkFilterQuality::kMedium_SkFilterQuality:
+ case PaintFlags::FilterQuality::kHigh:
+ return SkSamplingOptions(SkCubicResampler::CatmullRom());
+ case PaintFlags::FilterQuality::kMedium:
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
- case SkFilterQuality::kLow_SkFilterQuality:
+ case PaintFlags::FilterQuality::kLow:
return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
- case SkFilterQuality::kNone_SkFilterQuality:
+ case PaintFlags::FilterQuality::kNone:
return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
default:
NOTREACHED();
diff --git a/chromium/cc/paint/paint_flags.h b/chromium/cc/paint/paint_flags.h
index 2e9ddc16ca1..9106bd55ef1 100644
--- a/chromium/cc/paint/paint_flags.h
+++ b/chromium/cc/paint/paint_flags.h
@@ -9,17 +9,18 @@
#include "base/compiler_specific.h"
#include "cc/paint/paint_export.h"
-#include "cc/paint/paint_shader.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
#include "third_party/skia/include/core/SkMaskFilter.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPathEffect.h"
+#include "third_party/skia/include/core/SkSamplingOptions.h"
class SkCanvas;
namespace cc {
class PaintFilter;
+class PaintShader;
class CC_PAINT_EXPORT PaintFlags {
public:
@@ -57,11 +58,19 @@ class CC_PAINT_EXPORT PaintFlags {
ALWAYS_INLINE void setAntiAlias(bool aa) { bitfields_.antialias_ = aa; }
ALWAYS_INLINE bool isDither() const { return bitfields_.dither_; }
ALWAYS_INLINE void setDither(bool dither) { bitfields_.dither_ = dither; }
- ALWAYS_INLINE void setFilterQuality(SkFilterQuality quality) {
- bitfields_.filter_quality_ = quality;
+
+ enum class FilterQuality {
+ kNone,
+ kLow,
+ kMedium,
+ kHigh,
+ kLast = kHigh,
+ };
+ ALWAYS_INLINE void setFilterQuality(FilterQuality quality) {
+ bitfields_.filter_quality_ = static_cast<int>(quality);
}
- ALWAYS_INLINE SkFilterQuality getFilterQuality() const {
- return static_cast<SkFilterQuality>(bitfields_.filter_quality_);
+ ALWAYS_INLINE FilterQuality getFilterQuality() const {
+ return static_cast<FilterQuality>(bitfields_.filter_quality_);
}
ALWAYS_INLINE bool useDarkModeForImage() const {
return bitfields_.use_dark_mode_for_image_;
@@ -118,11 +127,9 @@ class CC_PAINT_EXPORT PaintFlags {
// Returns whether the shader is opaque. Note that it is only valid to call
// this function if HasShader() returns true.
- ALWAYS_INLINE bool ShaderIsOpaque() const { return shader_->IsOpaque(); }
+ bool ShaderIsOpaque() const;
- ALWAYS_INLINE void setShader(sk_sp<PaintShader> shader) {
- shader_ = std::move(shader);
- }
+ void setShader(sk_sp<PaintShader> shader);
ALWAYS_INLINE const sk_sp<SkPathEffect>& getPathEffect() const {
return path_effect_;
@@ -170,7 +177,7 @@ class CC_PAINT_EXPORT PaintFlags {
}
static SkSamplingOptions FilterQualityToSkSamplingOptions(
- SkFilterQuality filter_quality);
+ FilterQuality filter_quality);
bool IsValid() const;
bool operator==(const PaintFlags& other) const;
diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc
index d42df94bfac..c382ee15e7d 100644
--- a/chromium/cc/paint/paint_op_buffer.cc
+++ b/chromium/cc/paint/paint_op_buffer.cc
@@ -4,10 +4,12 @@
#include "cc/paint/paint_op_buffer.h"
+#include <algorithm>
#include <memory>
#include <utility>
#include <vector>
+#include "base/stl_util.h"
#include "build/build_config.h"
#include "cc/paint/decoded_draw_image.h"
#include "cc/paint/display_item_list.h"
@@ -23,6 +25,7 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkSerialProcs.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
#include "third_party/skia/include/docs/SkPDFDocument.h"
#include "third_party/skia/include/gpu/GrRecordingContext.h"
#include "ui/gfx/skia_util.h"
@@ -31,15 +34,17 @@ namespace cc {
namespace {
// In a future CL, convert DrawImage to explicitly take sampling instead of
// quality
-SkFilterQuality sampling_to_quality(const SkSamplingOptions& sampling) {
+PaintFlags::FilterQuality sampling_to_quality(
+ const SkSamplingOptions& sampling) {
if (sampling.useCubic) {
- return kHigh_SkFilterQuality;
+ return PaintFlags::FilterQuality::kHigh;
}
if (sampling.mipmap != SkMipmapMode::kNone) {
- return kMedium_SkFilterQuality;
+ return PaintFlags::FilterQuality::kMedium;
}
- return sampling.filter == SkFilterMode::kLinear ? kLow_SkFilterQuality
- : kNone_SkFilterQuality;
+ return sampling.filter == SkFilterMode::kLinear
+ ? PaintFlags::FilterQuality::kLow
+ : PaintFlags::FilterQuality::kNone;
}
DrawImage CreateDrawImage(const PaintImage& image,
@@ -413,7 +418,7 @@ size_t ClipPathOp::Serialize(const PaintOp* base_op,
const SkM44& original_ctm) {
auto* op = static_cast<const ClipPathOp*>(base_op);
PaintOpWriter helper(memory, size, options);
- helper.Write(op->path);
+ helper.Write(op->path, op->use_cache);
helper.Write(op->op);
helper.Write(op->antialias);
return helper.size();
@@ -629,7 +634,7 @@ size_t DrawPathOp::Serialize(const PaintOp* base_op,
if (!flags_to_serialize)
flags_to_serialize = &op->flags;
helper.Write(*flags_to_serialize, current_ctm);
- helper.Write(op->path);
+ helper.Write(op->path, op->use_cache);
helper.Write(op->sk_path_fill_type);
return helper.size();
}
@@ -2432,7 +2437,7 @@ gfx::Rect PaintOp::ComputePaintRect(const PaintOp* op,
} else {
const PaintFlags* flags =
op->IsPaintOpWithFlags()
- ? &static_cast<const PaintOpWithFlags*>(op)->flags
+ ? &(static_cast<const PaintOpWithFlags*>(op)->flags)
: nullptr;
SkRect paint_rect = MapRect(ctm, op_rect);
if (flags) {
@@ -3009,6 +3014,45 @@ sk_sp<PaintOpBuffer> PaintOpBuffer::MakeFromMemory(
return buffer;
}
+// static
+SkRect PaintOpBuffer::GetFixedScaleBounds(const SkMatrix& ctm,
+ const SkRect& bounds,
+ int max_texture_size) {
+ SkSize scale;
+ if (!ctm.decomposeScale(&scale)) {
+ // Decomposition failed, use an approximation.
+ scale.set(SkScalarSqrt(ctm.getScaleX() * ctm.getScaleX() +
+ ctm.getSkewX() * ctm.getSkewX()),
+ SkScalarSqrt(ctm.getScaleY() * ctm.getScaleY() +
+ ctm.getSkewY() * ctm.getSkewY()));
+ }
+
+ SkScalar raster_width = bounds.width() * scale.width();
+ SkScalar raster_height = bounds.height() * scale.height();
+ SkScalar tile_area = raster_width * raster_height;
+ // Clamp the tile area to about 4M pixels, and per-dimension max texture size
+ // if it's provided.
+ static const SkScalar kMaxTileArea = 2048 * 2048;
+ SkScalar down_scale = 1.f;
+ if (tile_area > kMaxTileArea) {
+ down_scale = SkScalarSqrt(kMaxTileArea / tile_area);
+ }
+ if (max_texture_size > 0) {
+ // This only updates down_scale if the tile is larger than the texture size
+ // after ensuring its area is less than kMaxTileArea
+ down_scale = std::min(
+ down_scale, max_texture_size / std::max(raster_width, raster_height));
+ }
+
+ if (down_scale < 1.f) {
+ scale.set(down_scale * scale.width(), down_scale * scale.height());
+ }
+ return SkRect::MakeXYWH(
+ bounds.fLeft * scale.width(), bounds.fTop * scale.height(),
+ SkScalarCeilToInt(SkScalarAbs(scale.width() * bounds.width())),
+ SkScalarCeilToInt(SkScalarAbs(scale.height() * bounds.height())));
+}
+
void PaintOpBuffer::ReallocBuffer(size_t new_size) {
DCHECK_GE(new_size, used_);
std::unique_ptr<char, base::AlignedFreeDeleter> new_data(
diff --git a/chromium/cc/paint/paint_op_buffer.h b/chromium/cc/paint/paint_op_buffer.h
index aafee1295a1..777bffba80d 100644
--- a/chromium/cc/paint/paint_op_buffer.h
+++ b/chromium/cc/paint/paint_op_buffer.h
@@ -28,6 +28,7 @@
#include "cc/paint/paint_flags.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "ui/gfx/geometry/rect.h"
@@ -388,8 +389,15 @@ class CC_PAINT_EXPORT AnnotateOp final : public PaintOp {
class CC_PAINT_EXPORT ClipPathOp final : public PaintOp {
public:
static constexpr PaintOpType kType = PaintOpType::ClipPath;
- ClipPathOp(SkPath path, SkClipOp op, bool antialias)
- : PaintOp(kType), path(path), op(op), antialias(antialias) {}
+ ClipPathOp(SkPath path,
+ SkClipOp op,
+ bool antialias,
+ UsePaintCache use_paint_cache = UsePaintCache::kEnabled)
+ : PaintOp(kType),
+ path(path),
+ op(op),
+ antialias(antialias),
+ use_cache(use_paint_cache) {}
static void Raster(const ClipPathOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
@@ -402,6 +410,7 @@ class CC_PAINT_EXPORT ClipPathOp final : public PaintOp {
ThreadsafePath path;
SkClipOp op;
bool antialias;
+ UsePaintCache use_cache;
private:
ClipPathOp() : PaintOp(kType) {}
@@ -684,10 +693,13 @@ class CC_PAINT_EXPORT DrawPathOp final : public PaintOpWithFlags {
public:
static constexpr PaintOpType kType = PaintOpType::DrawPath;
static constexpr bool kIsDrawOp = true;
- DrawPathOp(const SkPath& path, const PaintFlags& flags)
+ DrawPathOp(const SkPath& path,
+ const PaintFlags& flags,
+ UsePaintCache use_paint_cache = UsePaintCache::kEnabled)
: PaintOpWithFlags(kType, flags),
path(path),
- sk_path_fill_type(static_cast<uint8_t>(path.getFillType())) {}
+ sk_path_fill_type(static_cast<uint8_t>(path.getFillType())),
+ use_cache(use_paint_cache) {}
static void RasterWithFlags(const DrawPathOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
@@ -704,6 +716,7 @@ class CC_PAINT_EXPORT DrawPathOp final : public PaintOpWithFlags {
// serialize/deserialize this value and set it on the SkPath before handing it
// to Skia.
uint8_t sk_path_fill_type;
+ UsePaintCache use_cache;
private:
DrawPathOp() : PaintOpWithFlags(kType) {}
@@ -1044,6 +1057,15 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
size_t input_size,
const PaintOp::DeserializeOptions& options);
+ // Given the |bounds| of a PaintOpBuffer that would be transformed by |ctm|
+ // when rendered, compute the bounds needed to raster the buffer at a fixed
+ // scale into an auxiliary image instead of rasterizing at scale dynamically.
+ // This is used to enforce scaling decisions made pre-serialization when
+ // rasterizing after deserializing the buffer.
+ static SkRect GetFixedScaleBounds(const SkMatrix& ctm,
+ const SkRect& bounds,
+ int max_texture_size = 0);
+
// Returns the size of the paint op buffer. That is, the number of ops
// contained in it.
size_t size() const { return op_count_; }
diff --git a/chromium/cc/paint/paint_op_buffer_serializer.cc b/chromium/cc/paint/paint_op_buffer_serializer.cc
index 12e8f8af1d8..1dc29cc96bf 100644
--- a/chromium/cc/paint/paint_op_buffer_serializer.cc
+++ b/chromium/cc/paint/paint_op_buffer_serializer.cc
@@ -76,11 +76,9 @@ void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer) {
SerializeBuffer(canvas.get(), buffer, nullptr);
}
-void PaintOpBufferSerializer::Serialize(
- const PaintOpBuffer* buffer,
- const gfx::Rect& playback_rect,
- const gfx::SizeF& post_scale,
- const SkMatrix& post_matrix_for_analysis) {
+void PaintOpBufferSerializer::Serialize(const PaintOpBuffer* buffer,
+ const gfx::Rect& playback_rect,
+ const gfx::SizeF& post_scale) {
std::unique_ptr<SkCanvas> canvas = MakeAnalysisCanvas(options_);
PlaybackParams params = MakeParams(canvas.get());
@@ -97,7 +95,6 @@ void PaintOpBufferSerializer::Serialize(
SerializeOp(canvas.get(), &scale_op, nullptr, params);
}
- canvas->concat(post_matrix_for_analysis);
SerializeBuffer(canvas.get(), buffer, nullptr);
}
diff --git a/chromium/cc/paint/paint_op_buffer_serializer.h b/chromium/cc/paint/paint_op_buffer_serializer.h
index ebd69c14ba1..9783440f25c 100644
--- a/chromium/cc/paint/paint_op_buffer_serializer.h
+++ b/chromium/cc/paint/paint_op_buffer_serializer.h
@@ -61,17 +61,14 @@ class CC_PAINT_EXPORT PaintOpBufferSerializer {
// generally be used for internal PaintOpBuffers that want to be sent as-is.
void Serialize(const PaintOpBuffer* buffer);
// Serialize the buffer with a scale and a playback rect. This should
- // generally be used for internal PaintOpBuffers in PaintShaders that have
- // a scale and a tiling, but don't want the clearing or other complicated
- // logic of the top level Serialize.
- // post_matrix_for_analysis adds a scale that is not added to the serialized
- // buffer, but used in analysis. This is required for cases that don't modify
- // the record during serialization, but need to send resources based on the
- // raster scale (mainly PaintRecord backed PaintFilters).
+ // generally be used for internal PaintOpBuffers in PaintShaders and
+ // PaintFilters that need to guarantee the nested buffer is rasterized at the
+ // specific scale to a separate image. This ensures that scale-dependent
+ // analysis made during serialization is consistent with analysis done during
+ // rasterization.
void Serialize(const PaintOpBuffer* buffer,
const gfx::Rect& playback_rect,
- const gfx::SizeF& post_scale,
- const SkMatrix& post_matrix_for_analysis);
+ const gfx::SizeF& post_scale);
bool valid() const { return valid_; }
diff --git a/chromium/cc/paint/paint_op_buffer_unittest.cc b/chromium/cc/paint/paint_op_buffer_unittest.cc
index a4084107699..3280a5de6a8 100644
--- a/chromium/cc/paint/paint_op_buffer_unittest.cc
+++ b/chromium/cc/paint/paint_op_buffer_unittest.cc
@@ -5,9 +5,10 @@
#include "cc/paint/paint_op_buffer.h"
#include <algorithm>
+
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "cc/paint/decoded_draw_image.h"
@@ -287,8 +288,8 @@ TEST(PaintOpBufferTest, SaveDrawTextBlobRestore) {
PaintFlags paint_flags;
EXPECT_TRUE(paint_flags.SupportsFoldingAlpha());
- buffer.push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()), 0, 0,
- paint_flags);
+ buffer.push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()), 0.0f,
+ 0.0f, paint_flags);
buffer.push<RestoreOp>();
SaveCountingCanvas canvas;
@@ -558,16 +559,19 @@ TEST(PaintOpBufferTest, SlowPaths) {
SkPath path;
path.addCircle(2, 2, 5);
EXPECT_TRUE(path.isConvex());
- buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, true);
+ buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, /*antialias=*/true,
+ UsePaintCache::kDisabled);
EXPECT_EQ(buffer->numSlowPaths(), 1);
// Concave paths are slow only when antialiased.
SkPath concave = path;
concave.addCircle(3, 4, 2);
EXPECT_FALSE(concave.isConvex());
- buffer->push<ClipPathOp>(concave, SkClipOp::kIntersect, true);
+ buffer->push<ClipPathOp>(concave, SkClipOp::kIntersect, /*antialias=*/true,
+ UsePaintCache::kDisabled);
EXPECT_EQ(buffer->numSlowPaths(), 2);
- buffer->push<ClipPathOp>(concave, SkClipOp::kIntersect, false);
+ buffer->push<ClipPathOp>(concave, SkClipOp::kIntersect, /*antialias=*/false,
+ UsePaintCache::kDisabled);
EXPECT_EQ(buffer->numSlowPaths(), 2);
// Drawing a record with slow paths into another adds the same
@@ -608,11 +612,13 @@ TEST(PaintOpBufferTest, NonAAPaint) {
path.addCircle(2, 2, 5);
// ClipPathOp with AA
- buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, true /* antialias */);
+ buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, /*antialias=*/true,
+ UsePaintCache::kDisabled);
EXPECT_FALSE(buffer->HasNonAAPaint());
// ClipPathOp without AA
- buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, false /* antialias */);
+ buffer->push<ClipPathOp>(path, SkClipOp::kIntersect, /*antialias=*/false,
+ UsePaintCache::kDisabled);
EXPECT_TRUE(buffer->HasNonAAPaint());
}
@@ -641,7 +647,7 @@ TEST(PaintOpBufferTest, NonAAPaint) {
SkPath path;
path.addCircle(2, 2, 5);
sub_buffer->push<ClipPathOp>(path, SkClipOp::kIntersect,
- false /* antialias */);
+ /*antialias=*/false, UsePaintCache::kDisabled);
EXPECT_TRUE(sub_buffer->HasNonAAPaint());
buffer->push<DrawRecordOp>(sub_buffer);
@@ -1144,7 +1150,7 @@ std::vector<PaintFlags> test_flags = {
flags.setStrokeCap(PaintFlags::kSquare_Cap);
flags.setStrokeJoin(PaintFlags::kBevel_Join);
flags.setStyle(PaintFlags::kStroke_Style);
- flags.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality);
+ flags.setFilterQuality(PaintFlags::FilterQuality::kMedium);
flags.setShader(PaintShader::MakeColor(SkColorSetARGB(1, 2, 3, 4)));
return flags;
}(),
@@ -1158,7 +1164,7 @@ std::vector<PaintFlags> test_flags = {
flags.setStrokeCap(PaintFlags::kRound_Cap);
flags.setStrokeJoin(PaintFlags::kRound_Join);
flags.setStyle(PaintFlags::kFill_Style);
- flags.setFilterQuality(SkFilterQuality::kHigh_SkFilterQuality);
+ flags.setFilterQuality(PaintFlags::FilterQuality::kHigh);
SkScalar intervals[] = {1.f, 1.f};
flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
@@ -1415,7 +1421,8 @@ void PushAnnotateOps(PaintOpBuffer* buffer) {
void PushClipPathOps(PaintOpBuffer* buffer) {
for (size_t i = 0; i < test_paths.size(); ++i) {
SkClipOp op = i % 3 ? SkClipOp::kDifference : SkClipOp::kIntersect;
- buffer->push<ClipPathOp>(test_paths[i], op, !!(i % 2));
+ buffer->push<ClipPathOp>(test_paths[i], op, /*antialias=*/!!(i % 2),
+ UsePaintCache::kDisabled);
}
ValidateOps<ClipPathOp>(buffer);
}
@@ -1530,7 +1537,8 @@ void PushDrawOvalOps(PaintOpBuffer* buffer) {
void PushDrawPathOps(PaintOpBuffer* buffer) {
size_t len = std::min(test_paths.size(), test_flags.size());
for (size_t i = 0; i < len; ++i)
- buffer->push<DrawPathOp>(test_paths[i], test_flags[i]);
+ buffer->push<DrawPathOp>(test_paths[i], test_flags[i],
+ UsePaintCache::kDisabled);
ValidateOps<DrawPathOp>(buffer);
}
@@ -1687,7 +1695,7 @@ void PushTranslateOps(PaintOpBuffer* buffer) {
void PushSetNodeIdOps(PaintOpBuffer* buffer) {
for (size_t i = 0; i < test_ids.size(); i++)
- buffer->push<SetNodeIdOp>(test_ids[i]);
+ buffer->push<SetNodeIdOp>(static_cast<int>(test_ids[i]));
ValidateOps<SetNodeIdOp>(buffer);
}
@@ -2458,13 +2466,15 @@ TEST(PaintOpBufferTest, ValidateSkClip) {
// Successful first op.
SkPath path;
- buffer.push<ClipPathOp>(path, SkClipOp::kMax_EnumValue, true);
+ buffer.push<ClipPathOp>(path, SkClipOp::kMax_EnumValue, /*antialias=*/true,
+ UsePaintCache::kDisabled);
// Bad other ops.
SkClipOp bad_clip = static_cast<SkClipOp>(
static_cast<uint32_t>(SkClipOp::kMax_EnumValue) + 1);
- buffer.push<ClipPathOp>(path, bad_clip, true);
+ buffer.push<ClipPathOp>(path, bad_clip, /*antialias=*/true,
+ UsePaintCache::kDisabled);
buffer.push<ClipRectOp>(test_rects[0], bad_clip, true);
buffer.push<ClipRRectOp>(test_rrects[0], bad_clip, false);
@@ -2799,7 +2809,7 @@ class MockImageProvider : public ImageProvider {
: fail_all_decodes_(fail_all_decodes) {}
MockImageProvider(std::vector<SkSize> src_rect_offset,
std::vector<SkSize> scale,
- std::vector<SkFilterQuality> quality)
+ std::vector<PaintFlags::FilterQuality> quality)
: src_rect_offset_(src_rect_offset), scale_(scale), quality_(quality) {}
~MockImageProvider() override = default;
@@ -2826,7 +2836,7 @@ class MockImageProvider : public ImageProvider {
private:
std::vector<SkSize> src_rect_offset_;
std::vector<SkSize> scale_;
- std::vector<SkFilterQuality> quality_;
+ std::vector<PaintFlags::FilterQuality> quality_;
size_t index_ = 0;
bool fail_all_decodes_ = false;
sk_sp<PaintRecord> record_;
@@ -2966,7 +2976,8 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImageRectTranslated) {
std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
- std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality};
+ std::vector<PaintFlags::FilterQuality> quality = {
+ PaintFlags::FilterQuality::kHigh};
MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
provider.SetRecord(paint_worklet_buffer);
@@ -2982,7 +2993,7 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImageRectTranslated) {
testing::StrictMock<MockCanvas> canvas;
testing::Sequence s;
- SkSamplingOptions sampling({1.0f / 3, 1.0f / 3});
+ SkSamplingOptions sampling({0, 1.0f / 2});
EXPECT_CALL(canvas, willSave()).InSequence(s);
EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
@@ -3012,7 +3023,8 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImageRectScaled) {
std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
- std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality};
+ std::vector<PaintFlags::FilterQuality> quality = {
+ PaintFlags::FilterQuality::kHigh};
MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
provider.SetRecord(paint_worklet_buffer);
@@ -3028,7 +3040,7 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImageRectScaled) {
testing::StrictMock<MockCanvas> canvas;
testing::Sequence s;
- SkSamplingOptions sampling({1.0f / 3, 1.0f / 3});
+ SkSamplingOptions sampling({0, 1.0f / 2});
EXPECT_CALL(canvas, willSave()).InSequence(s);
EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
@@ -3061,7 +3073,8 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImageRectClipped) {
std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
- std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality};
+ std::vector<PaintFlags::FilterQuality> quality = {
+ PaintFlags::FilterQuality::kHigh};
MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
provider.SetRecord(paint_worklet_buffer);
@@ -3077,7 +3090,7 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImageRectClipped) {
testing::StrictMock<MockCanvas> canvas;
testing::Sequence s;
- SkSamplingOptions sampling({1.0f / 3, 1.0f / 3});
+ SkSamplingOptions sampling({0, 1.0f / 2});
EXPECT_CALL(canvas, willSave()).InSequence(s);
EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
@@ -3100,8 +3113,9 @@ TEST(PaintOpBufferTest, ReplacesImagesFromProvider) {
std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f),
SkSize::Make(0.3f, 0.3f),
SkSize::Make(0.4f, 0.4f)};
- std::vector<SkFilterQuality> quality = {
- kHigh_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality};
+ std::vector<PaintFlags::FilterQuality> quality = {
+ PaintFlags::FilterQuality::kHigh, PaintFlags::FilterQuality::kMedium,
+ PaintFlags::FilterQuality::kHigh};
MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
PaintOpBuffer buffer;
@@ -3120,7 +3134,7 @@ TEST(PaintOpBufferTest, ReplacesImagesFromProvider) {
testing::StrictMock<MockCanvas> canvas;
testing::Sequence s;
- SkSamplingOptions sampling0({1.0f / 3, 1.0f / 3});
+ SkSamplingOptions sampling0({0, 1.0f / 2});
SkSamplingOptions sampling1(SkFilterMode::kLinear, SkMipmapMode::kLinear);
// Save/scale/image/restore from DrawImageop.
@@ -3191,7 +3205,8 @@ TEST(PaintOpBufferTest, DrawImageRectOpWithLooperWithImageProvider) {
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};
+ std::vector<PaintFlags::FilterQuality> quality = {
+ PaintFlags::FilterQuality::kHigh};
MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
buffer.Playback(&canvas, PlaybackParams(&image_provider));
}
@@ -3285,8 +3300,8 @@ TEST_P(PaintFilterSerializationTest, Basic) {
sk_sp<PaintFilter>{new TurbulencePaintFilter(
TurbulencePaintFilter::TurbulenceType::kFractalNoise, 3.3f, 4.4f, 2,
123, nullptr)},
- sk_sp<PaintFilter>{
- new MatrixPaintFilter(SkMatrix::I(), kHigh_SkFilterQuality, nullptr)},
+ sk_sp<PaintFilter>{new MatrixPaintFilter(
+ SkMatrix::I(), PaintFlags::FilterQuality::kHigh, nullptr)},
sk_sp<PaintFilter>{new LightingDistantPaintFilter(
PaintFilter::LightingType::kSpecular, SkPoint3::Make(1, 2, 3),
SK_ColorCYAN, 1.1f, 2.2f, 3.3f, nullptr)},
@@ -3300,7 +3315,7 @@ TEST_P(PaintFilterSerializationTest, Basic) {
sk_sp<PaintFilter>{
new ImagePaintFilter(CreateDiscardablePaintImage(gfx::Size(100, 100)),
SkRect::MakeWH(50, 50), SkRect::MakeWH(70, 70),
- kMedium_SkFilterQuality)}};
+ PaintFlags::FilterQuality::kMedium)}};
filters.emplace_back(new ComposePaintFilter(filters[0], filters[1]));
filters.emplace_back(
@@ -3313,6 +3328,12 @@ TEST_P(PaintFilterSerializationTest, Basic) {
filters.emplace_back(new RecordPaintFilter(
sk_sp<PaintRecord>{new PaintRecord}, SkRect::MakeXYWH(10, 15, 20, 25)));
+ // Use a non-identity ctm to confirm that RecordPaintFilters are converted
+ // from raster-at-scale to fixed scale properly.
+ float scale_x = 2.f;
+ float scale_y = 3.f;
+ SkM44 ctm = SkM44::Scale(scale_x, scale_y);
+
TestOptionsProvider options_provider;
for (size_t i = 0; i < filters.size(); ++i) {
SCOPED_TRACE(i);
@@ -3327,7 +3348,7 @@ TEST_P(PaintFilterSerializationTest, Basic) {
PaintOpWriter writer(memory.data(), memory.size(),
options_provider.serialize_options(), GetParam());
- writer.Write(filter.get(), SkM44());
+ writer.Write(filter.get(), ctm);
ASSERT_GT(writer.size(), 0u) << PaintFilter::TypeToString(filter->type());
sk_sp<PaintFilter> deserialized_filter;
@@ -3335,7 +3356,41 @@ TEST_P(PaintFilterSerializationTest, Basic) {
options_provider.deserialize_options(), GetParam());
reader.Read(&deserialized_filter);
ASSERT_TRUE(deserialized_filter);
- EXPECT_TRUE(*filter == *deserialized_filter);
+
+ if (filter->type() == PaintFilter::Type::kPaintRecord) {
+ // The filter's scaling behavior should be converted to kFixedScale so
+ // they are no longer equal.
+ ASSERT_EQ(deserialized_filter->type(), PaintFilter::Type::kPaintRecord);
+
+ const RecordPaintFilter& expected =
+ static_cast<const RecordPaintFilter&>(*filter);
+ const RecordPaintFilter& actual =
+ static_cast<const RecordPaintFilter&>(*deserialized_filter);
+
+ EXPECT_EQ(actual.scaling_behavior(),
+ RecordPaintFilter::ScalingBehavior::kFixedScale);
+
+ SkRect expected_bounds =
+ SkRect::MakeXYWH(scale_x * expected.record_bounds().x(),
+ scale_y * expected.record_bounds().y(),
+ scale_x * expected.record_bounds().width(),
+ scale_y * expected.record_bounds().height());
+ EXPECT_EQ(actual.record_bounds(), expected_bounds);
+ EXPECT_EQ(actual.raster_scale().width(), scale_x);
+ EXPECT_EQ(actual.raster_scale().height(), scale_y);
+
+ // And the first op in the deserialized filter's record should be a
+ // ScaleOp containing the extracted scale factors (if there's no
+ // security constraints that disable record serialization)
+ if (!GetParam()) {
+ const ScaleOp* scale = actual.record()->GetOpAtForTesting<ScaleOp>(0);
+ ASSERT_TRUE(scale);
+ EXPECT_EQ(scale->sx, scale_x);
+ EXPECT_EQ(scale->sy, scale_y);
+ }
+ } else {
+ EXPECT_TRUE(*filter == *deserialized_filter);
+ }
}
}
@@ -3519,7 +3574,7 @@ TEST(PaintOpBufferTest, SecurityConstrainedImageSerialization) {
auto image = CreateDiscardablePaintImage(gfx::Size(10, 10));
sk_sp<PaintFilter> filter = sk_make_sp<ImagePaintFilter>(
image, SkRect::MakeWH(10, 10), SkRect::MakeWH(10, 10),
- kLow_SkFilterQuality);
+ PaintFlags::FilterQuality::kLow);
const bool enable_security_constraints = true;
std::unique_ptr<char, base::AlignedFreeDeleter> memory(
@@ -3755,6 +3810,34 @@ TEST(PaintOpBufferTest, RecordShadersCachedSize) {
EXPECT_GT(shader_size, estimated_image_size);
}
+TEST(PaintOpBufferTest, RecordFilterSerializeScaledImages) {
+ auto record_buffer = sk_make_sp<PaintOpBuffer>();
+ record_buffer->push<DrawImageOp>(
+ CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f);
+
+ auto filter =
+ sk_make_sp<RecordPaintFilter>(record_buffer, SkRect::MakeWH(10.f, 10.f));
+ auto buffer = sk_make_sp<PaintOpBuffer>();
+ buffer->push<ScaleOp>(0.5f, 0.8f);
+ PaintFlags flags;
+ flags.setImageFilter(filter);
+ buffer->push<DrawRectOp>(SkRect::MakeWH(10.f, 10.f), flags);
+
+ std::unique_ptr<char, base::AlignedFreeDeleter> memory(
+ static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
+ PaintOpBuffer::PaintOpAlign)));
+ TestOptionsProvider options_provider;
+ SimpleBufferSerializer serializer(memory.get(),
+ PaintOpBuffer::kInitialBufferSize,
+ options_provider.serialize_options());
+ serializer.Serialize(buffer.get());
+
+ ASSERT_EQ(options_provider.decoded_images().size(), 1u);
+ auto scale = options_provider.decoded_images().at(0).scale();
+ EXPECT_EQ(scale.width(), 0.5f);
+ EXPECT_EQ(scale.height(), 0.8f);
+}
+
TEST(PaintOpBufferTest, TotalOpCount) {
auto record_buffer = sk_make_sp<PaintOpBuffer>();
auto sub_record_buffer = sk_make_sp<PaintOpBuffer>();
@@ -3810,8 +3893,8 @@ TEST(PaintOpBufferTest, HasDrawOpsAndHasDrawTextOps) {
buffer2->push<DrawRecordOp>(std::move(buffer1));
EXPECT_TRUE(buffer2->has_draw_ops());
EXPECT_FALSE(buffer2->has_draw_text_ops());
- buffer2->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()), 0,
- 0, PaintFlags());
+ buffer2->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()),
+ 0.0f, 0.0f, PaintFlags());
EXPECT_TRUE(buffer2->has_draw_ops());
EXPECT_TRUE(buffer2->has_draw_text_ops());
buffer2->push<DrawRectOp>(SkRect::MakeWH(4, 5), PaintFlags());
@@ -3849,14 +3932,14 @@ TEST(PaintOpBufferTest, HasEffectsPreventingLCDTextForSaveLayerAlpha) {
TEST(PaintOpBufferTest, NeedsAdditionalInvalidationForLCDText) {
auto buffer1 = sk_make_sp<PaintOpBuffer>();
- buffer1->push<SaveLayerAlphaOp>(nullptr, 100);
+ buffer1->push<SaveLayerAlphaOp>(nullptr, uint8_t{100});
EXPECT_FALSE(buffer1->has_draw_text_ops());
EXPECT_TRUE(buffer1->has_save_layer_alpha_ops());
EXPECT_FALSE(buffer1->has_effects_preventing_lcd_text_for_save_layer_alpha());
auto buffer2 = sk_make_sp<PaintOpBuffer>();
- buffer2->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()), 0,
- 0, PaintFlags());
+ buffer2->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()),
+ 0.0f, 0.0f, PaintFlags());
buffer2->push<SaveLayerOp>(nullptr, nullptr);
EXPECT_TRUE(buffer2->has_draw_ops());
EXPECT_FALSE(buffer2->has_save_layer_alpha_ops());
@@ -3879,7 +3962,7 @@ TEST(PaintOpBufferTest, NeedsAdditionalInvalidationForLCDText) {
}
{
buffer1->push<DrawTextBlobOp>(SkTextBlob::MakeFromString("abc", SkFont()),
- 0, 0, PaintFlags());
+ 0.0f, 0.0f, PaintFlags());
EXPECT_TRUE(buffer1->has_draw_text_ops());
EXPECT_TRUE(buffer1->has_save_layer_alpha_ops());
EXPECT_FALSE(
@@ -3917,4 +4000,41 @@ TEST(PaintOpBufferTest, SetMatrixOpWithNonIdentityPlaybackParams) {
}
}
+TEST(PaintOpBufferTest, PathCaching) {
+ SkPath path;
+ PaintFlags flags;
+
+ // Grow path large enough to trigger caching
+ path.moveTo(0, 0);
+ for (int x = 1; x < 100; ++x)
+ path.lineTo(x, x % 1);
+
+ TestOptionsProvider options_provider;
+
+ std::unique_ptr<char, base::AlignedFreeDeleter> memory(
+ static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize,
+ PaintOpBuffer::PaintOpAlign)));
+ auto buffer = sk_make_sp<PaintOpBuffer>();
+ buffer->push<DrawPathOp>(path, flags, UsePaintCache::kEnabled);
+ SimpleBufferSerializer serializer(memory.get(),
+ PaintOpBuffer::kInitialBufferSize,
+ options_provider.serialize_options());
+ serializer.Serialize(buffer.get());
+
+ EXPECT_TRUE(options_provider.client_paint_cache()->Get(
+ PaintCacheDataType::kPath, path.getGenerationID()));
+
+ auto deserialized_buffer =
+ PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(),
+ options_provider.deserialize_options());
+ ASSERT_TRUE(deserialized_buffer);
+ ASSERT_EQ(deserialized_buffer->size(), 1u);
+ ASSERT_EQ(deserialized_buffer->GetFirstOp()->GetType(),
+ PaintOpType::DrawPath);
+
+ SkPath cached_path;
+ EXPECT_TRUE(options_provider.service_paint_cache()->GetPath(
+ path.getGenerationID(), &cached_path));
+}
+
} // namespace cc
diff --git a/chromium/cc/paint/paint_op_helper_unittest.cc b/chromium/cc/paint/paint_op_helper_unittest.cc
index 3710ef041fe..e7f7fc93768 100644
--- a/chromium/cc/paint/paint_op_helper_unittest.cc
+++ b/chromium/cc/paint/paint_op_helper_unittest.cc
@@ -6,6 +6,7 @@
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_op_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
namespace cc {
namespace {
@@ -19,9 +20,12 @@ TEST(PaintOpHelper, AnnotateToString) {
}
TEST(PaintOpHelper, ClipPathToString) {
- ClipPathOp op(SkPath(), SkClipOp::kDifference, true);
+ ClipPathOp op(SkPath(), SkClipOp::kDifference, true,
+ UsePaintCache::kDisabled);
std::string str = PaintOpHelper::ToString(&op);
- EXPECT_EQ(str, "ClipPathOp(path=<SkPath>, op=kDifference, antialias=true)");
+ EXPECT_EQ(str,
+ "ClipPathOp(path=<SkPath>, op=kDifference, antialias=true, "
+ "use_cache=false)");
}
TEST(PaintOpHelper, ClipRectToString) {
@@ -156,7 +160,7 @@ TEST(PaintOpHelper, DrawOvalToString) {
TEST(PaintOpHelper, DrawPathToString) {
SkPath path;
- DrawPathOp op(path, PaintFlags());
+ DrawPathOp op(path, PaintFlags(), UsePaintCache::kDisabled);
std::string str = PaintOpHelper::ToString(&op);
EXPECT_EQ(str,
"DrawPathOp(path=<SkPath>, flags=[color=rgba(0, 0, 0, 255), "
@@ -167,7 +171,7 @@ TEST(PaintOpHelper, DrawPathToString) {
"shader=(nil), hasShader=false, shaderIsOpaque=false, "
"pathEffect=(nil), imageFilter=(nil), drawLooper=(nil), "
"isSimpleOpacity=true, supportsFoldingAlpha=true, isValid=true, "
- "hasDiscardableImages=false])");
+ "hasDiscardableImages=false], use_cache=false)");
}
TEST(PaintOpHelper, DrawRecordToString) {
diff --git a/chromium/cc/paint/paint_op_perftest.cc b/chromium/cc/paint/paint_op_perftest.cc
index 48777042fd7..9b06fc6cbc5 100644
--- a/chromium/cc/paint/paint_op_perftest.cc
+++ b/chromium/cc/paint/paint_op_perftest.cc
@@ -9,6 +9,7 @@
#include "base/timer/lap_timer.h"
#include "cc/paint/paint_op_buffer.h"
#include "cc/paint/paint_op_buffer_serializer.h"
+#include "cc/paint/paint_shader.h"
#include "cc/test/test_options_provider.h"
#include "testing/perf/perf_result_reporter.h"
#include "third_party/skia/include/core/SkMaskFilter.h"
diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc
index ddba7cb09f1..812e348a401 100644
--- a/chromium/cc/paint/paint_op_reader.cc
+++ b/chromium/cc/paint/paint_op_reader.cc
@@ -105,7 +105,7 @@ void PaintOpReader::ReadSimple(T* val) {
// Align everything to 4 bytes, as the writer does.
static constexpr size_t kAlign = 4;
- size_t size = base::bits::Align(sizeof(T), kAlign);
+ size_t size = base::bits::AlignUp(sizeof(T), kAlign);
if (remaining_bytes_ < size)
SetInvalid();
@@ -133,7 +133,7 @@ uint8_t* PaintOpReader::CopyScratchSpace(size_t bytes) {
}
template <typename T>
-void PaintOpReader::ReadFlattenable(sk_sp<T>* val) {
+void PaintOpReader::ReadFlattenable(sk_sp<T>* val, Factory<T> factory) {
size_t bytes = 0;
ReadSize(&bytes);
if (remaining_bytes_ < bytes)
@@ -144,9 +144,7 @@ void PaintOpReader::ReadFlattenable(sk_sp<T>* val) {
return;
auto* scratch = CopyScratchSpace(bytes);
- val->reset(static_cast<T*>(
- SkFlattenable::Deserialize(T::GetFlattenableType(), scratch, bytes)
- .release()));
+ val->reset(factory(scratch, bytes, nullptr).release());
if (!val)
SetInvalid();
@@ -227,7 +225,8 @@ void PaintOpReader::Read(SkPath* path) {
if (!options_.paint_cache->GetPath(path_id, path))
SetInvalid();
return;
- case PaintCacheEntryState::kInlined: {
+ case PaintCacheEntryState::kInlined:
+ case PaintCacheEntryState::kInlinedDoNotCache: {
size_t path_bytes = 0u;
ReadSize(&path_bytes);
if (path_bytes > remaining_bytes_)
@@ -243,7 +242,14 @@ void PaintOpReader::Read(SkPath* path) {
SetInvalid();
return;
}
- options_.paint_cache->PutPath(path_id, *path);
+ if (entry_state == PaintCacheEntryState::kInlined) {
+ options_.paint_cache->PutPath(path_id, *path);
+ } else {
+ // If we know that this path will only be drawn once, which is
+ // implied by kInlinedDoNotCache, we signal to skia that it should not
+ // do any caching either.
+ path->setIsVolatile(true);
+ }
memory_ += path_bytes;
remaining_bytes_ -= path_bytes;
return;
@@ -260,9 +266,9 @@ void PaintOpReader::Read(PaintFlags* flags) {
ReadSimple(&flags->bitfields_uint_);
- ReadFlattenable(&flags->path_effect_);
- ReadFlattenable(&flags->mask_filter_);
- ReadFlattenable(&flags->color_filter_);
+ ReadFlattenable(&flags->path_effect_, SkPathEffect::Deserialize);
+ ReadFlattenable(&flags->mask_filter_, SkMaskFilter::Deserialize);
+ ReadFlattenable(&flags->color_filter_, SkColorFilter::Deserialize);
if (enable_security_constraints_) {
size_t bytes = 0;
@@ -272,7 +278,7 @@ void PaintOpReader::Read(PaintFlags* flags) {
return;
}
} else {
- ReadFlattenable(&flags->draw_looper_);
+ ReadFlattenable(&flags->draw_looper_, SkDrawLooper::Deserialize);
}
Read(&flags->image_filter_);
@@ -725,7 +731,7 @@ void PaintOpReader::Read(scoped_refptr<SkottieWrapper>* skottie) {
#endif // !defined(OS_ANDROID)
void PaintOpReader::AlignMemory(size_t alignment) {
- size_t padding = base::bits::Align(memory_, alignment) - memory_;
+ size_t padding = base::bits::AlignUp(memory_, alignment) - memory_;
if (padding > remaining_bytes_)
SetInvalid();
@@ -847,6 +853,9 @@ void PaintOpReader::Read(sk_sp<PaintFilter>* filter) {
case PaintFilter::Type::kLightingSpot:
ReadLightingSpotPaintFilter(filter, crop_rect);
break;
+ case PaintFilter::Type::kStretch:
+ ReadStretchPaintFilter(filter, crop_rect);
+ break;
}
}
@@ -856,7 +865,7 @@ void PaintOpReader::ReadColorFilterPaintFilter(
sk_sp<SkColorFilter> color_filter;
sk_sp<PaintFilter> input;
- ReadFlattenable(&color_filter);
+ ReadFlattenable(&color_filter, SkColorFilter::Deserialize);
Read(&input);
if (!color_filter)
SetInvalid();
@@ -1074,7 +1083,7 @@ void PaintOpReader::ReadImagePaintFilter(
Read(&src_rect);
SkRect dst_rect;
Read(&dst_rect);
- SkFilterQuality quality;
+ PaintFlags::FilterQuality quality;
Read(&quality);
if (!valid_)
@@ -1086,13 +1095,37 @@ void PaintOpReader::ReadImagePaintFilter(
void PaintOpReader::ReadRecordPaintFilter(
sk_sp<PaintFilter>* filter,
const absl::optional<PaintFilter::CropRect>& crop_rect) {
- SkRect record_bounds;
+ bool has_filter = false;
+ ReadSimple(&has_filter);
+ if (!has_filter) {
+ *filter = nullptr;
+ return;
+ }
+
+ SkRect record_bounds = SkRect::MakeEmpty();
+ gfx::SizeF raster_scale = {0.f, 0.f};
+ PaintShader::ScalingBehavior scaling_behavior =
+ PaintShader::ScalingBehavior::kRasterAtScale;
sk_sp<PaintRecord> record;
- Read(&record_bounds);
+
+ ReadSimple(&record_bounds);
+ ReadSimple(&raster_scale);
+ if (raster_scale.width() <= 0.f || raster_scale.height() <= 0.f) {
+ SetInvalid();
+ return;
+ }
+
+ ReadSimple(&scaling_behavior);
+ if (!IsValidPaintShaderScalingBehavior(scaling_behavior)) {
+ SetInvalid();
+ return;
+ }
+
Read(&record);
if (!valid_)
return;
- filter->reset(new RecordPaintFilter(std::move(record), record_bounds));
+ filter->reset(new RecordPaintFilter(std::move(record), record_bounds,
+ raster_scale, scaling_behavior));
}
void PaintOpReader::ReadMergePaintFilter(
@@ -1198,7 +1231,7 @@ void PaintOpReader::ReadShaderPaintFilter(
sk_sp<PaintShader> shader;
uint8_t alpha = 255;
- SkFilterQuality quality = kNone_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
Dither dither = Dither::kNo;
Read(&shader);
@@ -1217,7 +1250,7 @@ void PaintOpReader::ReadMatrixPaintFilter(
sk_sp<PaintFilter>* filter,
const absl::optional<PaintFilter::CropRect>& crop_rect) {
SkMatrix matrix = SkMatrix::I();
- SkFilterQuality filter_quality = kNone_SkFilterQuality;
+ PaintFlags::FilterQuality filter_quality = PaintFlags::FilterQuality::kNone;
sk_sp<PaintFilter> input;
Read(&matrix);
@@ -1312,6 +1345,28 @@ void PaintOpReader::ReadLightingSpotPaintFilter(
base::OptionalOrNullptr(crop_rect)));
}
+void PaintOpReader::ReadStretchPaintFilter(
+ sk_sp<PaintFilter>* filter,
+ const absl::optional<PaintFilter::CropRect>& crop_rect) {
+ SkScalar stretch_x = 0.f;
+ SkScalar stretch_y = 0.f;
+ SkScalar width = 0.f;
+ SkScalar height = 0.f;
+ sk_sp<PaintFilter> input;
+
+ Read(&stretch_x);
+ Read(&stretch_y);
+ Read(&width);
+ Read(&height);
+ Read(&input);
+
+ if (!valid_)
+ return;
+ filter->reset(new StretchPaintFilter(stretch_x, stretch_y, width, height,
+ std::move(input),
+ base::OptionalOrNullptr(crop_rect)));
+}
+
size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) {
size_t size_bytes = 0;
ReadSize(&size_bytes);
diff --git a/chromium/cc/paint/paint_op_reader.h b/chromium/cc/paint/paint_op_reader.h
index eb3b7a9d5d7..7ed9abce3af 100644
--- a/chromium/cc/paint/paint_op_reader.h
+++ b/chromium/cc/paint/paint_op_reader.h
@@ -11,6 +11,7 @@
#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_op_writer.h"
#include "cc/paint/transfer_cache_deserialize_helper.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace gpu {
struct Mailbox;
@@ -94,8 +95,9 @@ class CC_PAINT_EXPORT PaintOpReader {
void Read(SkColorType* color_type) {
ReadEnum<SkColorType, kLastEnum_SkColorType>(color_type);
}
- void Read(SkFilterQuality* quality) {
- ReadEnum<SkFilterQuality, kLast_SkFilterQuality>(quality);
+ void Read(PaintFlags::FilterQuality* quality) {
+ ReadEnum<PaintFlags::FilterQuality, PaintFlags::FilterQuality::kLast>(
+ quality);
}
void Read(SkBlendMode* blend_mode) {
ReadEnum<SkBlendMode, SkBlendMode::kLastMode>(blend_mode);
@@ -129,7 +131,12 @@ class CC_PAINT_EXPORT PaintOpReader {
void ReadSimple(T* val);
template <typename T>
- void ReadFlattenable(sk_sp<T>* val);
+ using Factory = sk_sp<T> (*)(const void* data,
+ size_t size,
+ const SkDeserialProcs* procs);
+
+ template <typename T>
+ void ReadFlattenable(sk_sp<T>* val, Factory<T> factory);
template <typename Enum, Enum kMaxValue = Enum::kMaxValue>
void ReadEnum(Enum* enum_value) {
@@ -214,6 +221,9 @@ class CC_PAINT_EXPORT PaintOpReader {
void ReadLightingSpotPaintFilter(
sk_sp<PaintFilter>* filter,
const absl::optional<PaintFilter::CropRect>& crop_rect);
+ void ReadStretchPaintFilter(
+ sk_sp<PaintFilter>* filter,
+ const absl::optional<PaintFilter::CropRect>& crop_rect);
// Returns the size of the read record, 0 if error.
size_t Read(sk_sp<PaintRecord>* record);
diff --git a/chromium/cc/paint/paint_op_writer.cc b/chromium/cc/paint/paint_op_writer.cc
index f473abc18fe..53b5c8b574e 100644
--- a/chromium/cc/paint/paint_op_writer.cc
+++ b/chromium/cc/paint/paint_op_writer.cc
@@ -103,7 +103,7 @@ void PaintOpWriter::WriteSimple(const T& val) {
// to pre-align memory to the correct alignment.
// TODO(enne): maybe we should do this correctly and DCHECK alignment.
static constexpr size_t kAlign = 4;
- size_t size = base::bits::Align(sizeof(T), kAlign);
+ size_t size = base::bits::AlignUp(sizeof(T), kAlign);
EnsureBytes(size);
if (!valid_)
return;
@@ -173,12 +173,15 @@ void PaintOpWriter::Write(const SkRRect& rect) {
WriteSimple(rect);
}
-void PaintOpWriter::Write(const SkPath& path) {
+void PaintOpWriter::Write(const SkPath& path, UsePaintCache use_paint_cache) {
auto id = path.getGenerationID();
if (!options_.for_identifiability_study)
Write(id);
- if (options_.paint_cache->Get(PaintCacheDataType::kPath, id)) {
+ DCHECK(use_paint_cache == UsePaintCache::kEnabled ||
+ !options_.paint_cache->Get(PaintCacheDataType::kPath, id));
+ if (use_paint_cache == UsePaintCache::kEnabled &&
+ options_.paint_cache->Get(PaintCacheDataType::kPath, id)) {
Write(static_cast<uint32_t>(PaintCacheEntryState::kCached));
return;
}
@@ -190,7 +193,11 @@ void PaintOpWriter::Write(const SkPath& path) {
return;
}
- Write(static_cast<uint32_t>(PaintCacheEntryState::kInlined));
+ if (use_paint_cache == UsePaintCache::kEnabled) {
+ Write(static_cast<uint32_t>(PaintCacheEntryState::kInlined));
+ } else {
+ Write(static_cast<uint32_t>(PaintCacheEntryState::kInlinedDoNotCache));
+ }
uint64_t* bytes_to_skip = WriteSize(0u);
if (!valid_)
return;
@@ -201,7 +208,9 @@ void PaintOpWriter::Write(const SkPath& path) {
}
size_t bytes_written = path.writeToMemory(memory_);
DCHECK_EQ(bytes_written, bytes_required);
- options_.paint_cache->Put(PaintCacheDataType::kPath, id, bytes_written);
+ if (use_paint_cache == UsePaintCache::kEnabled) {
+ options_.paint_cache->Put(PaintCacheDataType::kPath, id, bytes_written);
+ }
*bytes_to_skip = bytes_written;
memory_ += bytes_written;
remaining_bytes_ -= bytes_written;
@@ -422,7 +431,7 @@ void PaintOpWriter::Write(const sk_sp<SkTextBlob>& blob) {
sk_sp<PaintShader> PaintOpWriter::TransformShaderIfNecessary(
const PaintShader* original,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
const SkM44& current_ctm,
uint32_t* paint_image_transfer_cache_entry_id,
gfx::SizeF* paint_record_post_scale,
@@ -467,7 +476,7 @@ void PaintOpWriter::Write(const SkM44& matrix) {
}
void PaintOpWriter::Write(const PaintShader* shader,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
const SkM44& current_ctm) {
sk_sp<PaintShader> transformed_shader;
uint32_t paint_image_transfer_cache_id = kInvalidImageTransferCacheEntryId;
@@ -534,8 +543,7 @@ void PaintOpWriter::Write(const PaintShader* shader,
const gfx::Rect playback_rect(
gfx::ToEnclosingRect(gfx::SkRectToRectF(shader->tile())));
- Write(shader->record_.get(), playback_rect, paint_record_post_scale,
- SkMatrix::I());
+ Write(shader->record_.get(), playback_rect, paint_record_post_scale);
} else {
DCHECK_EQ(shader->id_, PaintShader::kInvalidRecordShaderId);
Write(false);
@@ -585,7 +593,7 @@ void PaintOpWriter::AlignMemory(size_t alignment) {
// padding = (alignment - memory % alignment) % alignment;
// because alignment is a power of two. This doesn't use modulo operator
// however, since it can be slow.
- size_t padding = ((memory + alignment - 1) & ~(alignment - 1)) - memory;
+ size_t padding = base::bits::AlignUp(memory, alignment) - memory;
EnsureBytes(padding);
if (!valid_)
return;
@@ -684,6 +692,9 @@ void PaintOpWriter::Write(const PaintFilter* filter, const SkM44& current_ctm) {
case PaintFilter::Type::kLightingSpot:
Write(static_cast<const LightingSpotPaintFilter&>(*filter), current_ctm);
break;
+ case PaintFilter::Type::kStretch:
+ Write(static_cast<const StretchPaintFilter&>(*filter), current_ctm);
+ break;
}
}
@@ -793,18 +804,24 @@ void PaintOpWriter::Write(const ImagePaintFilter& filter,
void PaintOpWriter::Write(const RecordPaintFilter& filter,
const SkM44& current_ctm) {
- WriteSimple(filter.record_bounds());
+ // Convert to a fixed scale filter so that any content contained within
+ // the filter's PaintRecord is rasterized at the scale we use here for
+ // analysis (e.g. this ensures any contained text blobs will not be missing
+ // from the cache).
+ auto scaled_filter = filter.CreateScaledPaintRecord(
+ current_ctm.asM33(), options_.max_texture_size);
+ if (!scaled_filter) {
+ WriteSimple(false);
+ return;
+ }
- // The logic here to only use the scale component of the matrix during
- // analysis is for consistency with the rasterization of the filter later in
- // pipeline in skia. For every draw with a filter, SkCanvas creates a layer
- // for the draw and modifies the scale for these filters.
- // See SkCanvas::internalSaveLayer.
- SkMatrix mat = current_ctm.asM33();
- SkSize scale;
- if (!mat.isScaleTranslate() && mat.decomposeScale(&scale))
- mat = SkMatrix::Scale(scale.width(), scale.height());
- Write(filter.record().get(), gfx::Rect(), gfx::SizeF(1.f, 1.f), mat);
+ WriteSimple(true);
+ WriteSimple(scaled_filter->record_bounds());
+ WriteSimple(scaled_filter->raster_scale());
+ WriteSimple(scaled_filter->scaling_behavior());
+
+ Write(scaled_filter->record().get(), gfx::Rect(),
+ scaled_filter->raster_scale());
}
void PaintOpWriter::Write(const MergePaintFilter& filter,
@@ -897,10 +914,18 @@ void PaintOpWriter::Write(const LightingSpotPaintFilter& filter,
Write(filter.input().get(), current_ctm);
}
+void PaintOpWriter::Write(const StretchPaintFilter& filter,
+ const SkM44& current_ctm) {
+ WriteSimple(filter.stretch_x());
+ WriteSimple(filter.stretch_y());
+ WriteSimple(filter.width());
+ WriteSimple(filter.height());
+ Write(filter.input().get(), current_ctm);
+}
+
void PaintOpWriter::Write(const PaintRecord* record,
const gfx::Rect& playback_rect,
- const gfx::SizeF& post_scale,
- const SkMatrix& post_matrix_for_analysis) {
+ const gfx::SizeF& post_scale) {
AlignMemory(PaintOpBuffer::PaintOpAlign);
// We need to record how many bytes we will serialize, but we don't know this
@@ -920,18 +945,15 @@ void PaintOpWriter::Write(const PaintRecord* record,
return;
}
- // Nested records are used for picture shaders and filters which don't support
- // using lcd text. Make sure we disable it here to match this in the text
- // analysis canvas.
- PaintOp::SerializeOptions lcd_disabled_options(
- options_.image_provider, options_.transfer_cache, options_.paint_cache,
- options_.strike_server, options_.color_space,
- /*can_use_lcd_text=*/false, options_.context_supports_distance_field_text,
- options_.max_texture_size);
+ // Nested records are used for picture shaders and filters. These are always
+ // converted to a fixed scale mode (hence |post_scale|), which means they are
+ // first rendered offscreen via SkImage::MakeFromPicture. This inherently does
+ // not support lcd text, so reflect that in the serialization options.
+ PaintOp::SerializeOptions lcd_disabled_options = options_;
+ lcd_disabled_options.can_use_lcd_text = false;
SimpleBufferSerializer serializer(memory_, remaining_bytes_,
lcd_disabled_options);
- serializer.Serialize(record, playback_rect, post_scale,
- post_matrix_for_analysis);
+ serializer.Serialize(record, playback_rect, post_scale);
if (!serializer.valid()) {
valid_ = false;
diff --git a/chromium/cc/paint/paint_op_writer.h b/chromium/cc/paint/paint_op_writer.h
index b48378fb224..2e6fc5bfdd1 100644
--- a/chromium/cc/paint/paint_op_writer.h
+++ b/chromium/cc/paint/paint_op_writer.h
@@ -59,8 +59,7 @@ class CC_PAINT_EXPORT PaintOpWriter {
void Write(const SkRect& rect);
void Write(const SkIRect& rect);
void Write(const SkRRect& rect);
-
- void Write(const SkPath& path);
+ void Write(const SkPath& path, UsePaintCache);
void Write(const sk_sp<SkData>& data);
void Write(const SkColorSpace* data);
void Write(const SkSamplingOptions&);
@@ -76,7 +75,7 @@ class CC_PAINT_EXPORT PaintOpWriter {
// identically when text is involved.
void Write(const PaintFlags& flags, const SkM44& current_ctm);
void Write(const PaintShader* shader,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
const SkM44& current_ctm);
void Write(const PaintFilter* filter, const SkM44& current_ctm);
@@ -84,7 +83,9 @@ class CC_PAINT_EXPORT PaintOpWriter {
void Write(PaintCanvas::AnnotationType type) { WriteEnum(type); }
void Write(SkCanvas::SrcRectConstraint constraint) { WriteEnum(constraint); }
void Write(SkColorType color_type) { WriteEnum(color_type); }
- void Write(SkFilterQuality filter_quality) { WriteEnum(filter_quality); }
+ void Write(PaintFlags::FilterQuality filter_quality) {
+ WriteEnum(filter_quality);
+ }
void Write(SkBlendMode blend_mode) { WriteEnum(blend_mode); }
void Write(SkTileMode tile_mode) { WriteEnum(tile_mode); }
void Write(SkFilterMode filter_mode) { WriteEnum(filter_mode); }
@@ -161,11 +162,11 @@ class CC_PAINT_EXPORT PaintOpWriter {
const SkM44& current_ctm);
void Write(const LightingPointPaintFilter& filter, const SkM44& current_ctm);
void Write(const LightingSpotPaintFilter& filter, const SkM44& current_ctm);
+ void Write(const StretchPaintFilter& filter, const SkM44& current_ctm);
void Write(const PaintRecord* record,
const gfx::Rect& playback_rect,
- const gfx::SizeF& post_scale,
- const SkMatrix& post_matrix_for_analysis);
+ const gfx::SizeF& post_scale);
void Write(const SkRegion& region);
void WriteImage(const DecodedDrawImage& decoded_draw_image);
void WriteImage(uint32_t transfer_cache_entry_id, bool needs_mips);
@@ -174,7 +175,7 @@ class CC_PAINT_EXPORT PaintOpWriter {
void EnsureBytes(size_t required_bytes);
sk_sp<PaintShader> TransformShaderIfNecessary(
const PaintShader* original,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
const SkM44& current_ctm,
uint32_t* paint_image_transfer_cache_entry_id,
gfx::SizeF* paint_record_post_scale,
diff --git a/chromium/cc/paint/paint_recorder.h b/chromium/cc/paint/paint_recorder.h
index 57a62507c84..e9de25abdef 100644
--- a/chromium/cc/paint/paint_recorder.h
+++ b/chromium/cc/paint/paint_recorder.h
@@ -8,7 +8,6 @@
#include "base/compiler_specific.h"
#include "cc/paint/paint_record.h"
#include "cc/paint/record_paint_canvas.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cc {
diff --git a/chromium/cc/paint/paint_shader.cc b/chromium/cc/paint/paint_shader.cc
index 1d392729ec5..a0002f9fde1 100644
--- a/chromium/cc/paint/paint_shader.cc
+++ b/chromium/cc/paint/paint_shader.cc
@@ -4,7 +4,10 @@
#include "cc/paint/paint_shader.h"
+#include <utility>
+
#include "base/atomic_sequence_num.h"
+#include "base/stl_util.h"
#include "cc/paint/paint_image_builder.h"
#include "cc/paint/paint_op_writer.h"
#include "cc/paint/paint_record.h"
@@ -48,20 +51,6 @@ bool CompareMatrices(const SkMatrix& a,
return PaintOp::AreSkMatricesEqual(a_without_scale, b_without_scale);
}
-SkRect AdjustForMaxTextureSize(SkRect tile, int max_texture_size) {
- if (max_texture_size == 0)
- return tile;
-
- if (tile.width() < max_texture_size && tile.height() < max_texture_size)
- return tile;
-
- float down_scale = max_texture_size / std::max(tile.width(), tile.height());
- tile = SkRect::MakeXYWH(tile.x(), tile.y(),
- SkScalarFloorToScalar(tile.width() * down_scale),
- SkScalarFloorToScalar(tile.height() * down_scale));
- return tile;
-}
-
} // namespace
const PaintShader::RecordShaderId PaintShader::kInvalidRecordShaderId = -1;
@@ -244,8 +233,9 @@ bool PaintShader::has_discardable_images() const {
(record_ && record_->HasDiscardableImages());
}
-bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm,
- SkRect* tile_rect) const {
+bool PaintShader::GetClampedRasterizationTileRect(const SkMatrix& ctm,
+ int max_texture_size,
+ SkRect* tile_rect) const {
DCHECK_EQ(shader_type_, Type::kPaintRecord);
// If we are using a fixed scale, the record is rasterized with the original
@@ -259,34 +249,10 @@ bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm,
if (local_matrix_.has_value())
matrix.preConcat(local_matrix_.value());
- SkSize scale;
- if (!matrix.decomposeScale(&scale)) {
- // Decomposition failed, use an approximation.
- scale.set(SkScalarSqrt(matrix.getScaleX() * matrix.getScaleX() +
- matrix.getSkewX() * matrix.getSkewX()),
- SkScalarSqrt(matrix.getScaleY() * matrix.getScaleY() +
- matrix.getSkewY() * matrix.getSkewY()));
- }
-
- SkScalar tile_area =
- tile_.width() * tile_.height() * scale.width() * scale.height();
-
- // Clamp the tile size to about 4M pixels.
- // TODO(khushalsagar): We need to consider the max texture size as well.
- static const SkScalar kMaxTileArea = 2048 * 2048;
- if (tile_area > kMaxTileArea) {
- SkScalar clamp_scale = SkScalarSqrt(kMaxTileArea / tile_area);
- scale.set(clamp_scale, clamp_scale);
- }
-
- *tile_rect = SkRect::MakeXYWH(
- tile_.fLeft * scale.width(), tile_.fTop * scale.height(),
- SkScalarCeilToInt(SkScalarAbs(scale.width() * tile_.width())),
- SkScalarCeilToInt(SkScalarAbs(scale.height() * tile_.height())));
-
+ *tile_rect =
+ PaintRecord::GetFixedScaleBounds(matrix, tile_, max_texture_size);
if (tile_rect->isEmpty())
return false;
-
return true;
}
@@ -315,9 +281,8 @@ sk_sp<PaintShader> PaintShader::CreateScaledPaintRecord(
// Note that the scaling logic here is replicated from
// SkPictureShader::refBitmapShader.
SkRect tile_rect;
- if (!GetRasterizationTileRect(ctm, &tile_rect))
+ if (!GetClampedRasterizationTileRect(ctm, max_texture_size, &tile_rect))
return nullptr;
- tile_rect = AdjustForMaxTextureSize(tile_rect, max_texture_size);
sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord));
shader->record_ = record_;
@@ -356,10 +321,10 @@ sk_sp<PaintShader> PaintShader::CreatePaintWorkletRecord(
sk_sp<PaintShader> PaintShader::CreateDecodedImage(
const SkMatrix& ctm,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
ImageProvider* image_provider,
uint32_t* transfer_cache_entry_id,
- SkFilterQuality* raster_quality,
+ PaintFlags::FilterQuality* raster_quality,
bool* needs_mips,
gpu::Mailbox* mailbox) const {
DCHECK_EQ(shader_type_, Type::kImage);
@@ -413,7 +378,8 @@ sk_sp<PaintShader> PaintShader::CreateDecodedImage(
return PaintShader::MakeImage(decoded_paint_image, tx_, ty_, &final_matrix);
}
-sk_sp<SkShader> PaintShader::GetSkShader(SkFilterQuality quality) const {
+sk_sp<SkShader> PaintShader::GetSkShader(
+ PaintFlags::FilterQuality quality) const {
SkSamplingOptions sampling(
PaintFlags::FilterQualityToSkSamplingOptions(quality));
@@ -430,7 +396,6 @@ sk_sp<SkShader> PaintShader::GetSkShader(SkFilterQuality quality) const {
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), tx_, flags_,
base::OptionalOrNullptr(local_matrix_));
- break;
}
case Type::kRadialGradient:
return SkGradientShader::MakeRadial(
@@ -438,21 +403,18 @@ sk_sp<SkShader> PaintShader::GetSkShader(SkFilterQuality quality) const {
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), tx_, flags_,
base::OptionalOrNullptr(local_matrix_));
- break;
case Type::kTwoPointConicalGradient:
return SkGradientShader::MakeTwoPointConical(
start_point_, start_radius_, end_point_, end_radius_, colors_.data(),
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), tx_, flags_,
base::OptionalOrNullptr(local_matrix_));
- break;
case Type::kSweepGradient:
return SkGradientShader::MakeSweep(
center_.x(), center_.y(), colors_.data(),
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), tx_, start_degrees_, end_degrees_,
flags_, base::OptionalOrNullptr(local_matrix_));
- break;
case Type::kImage:
if (sk_cached_image_) {
return sk_cached_image_->makeShader(
@@ -467,7 +429,6 @@ sk_sp<SkShader> PaintShader::GetSkShader(SkFilterQuality quality) const {
return sk_cached_picture_->makeShader(
tx_, ty_, sampling.filter,
base::OptionalOrNullptr(local_matrix_), nullptr);
- break;
// For fixed scale, we create an image shader with an image backed by
// the picture.
case ScalingBehavior::kFixedScale: {
@@ -477,7 +438,6 @@ sk_sp<SkShader> PaintShader::GetSkShader(SkFilterQuality quality) const {
SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
return image->makeShader(tx_, ty_, sampling,
base::OptionalOrNullptr(local_matrix_));
- break;
}
}
break;
diff --git a/chromium/cc/paint/paint_shader.h b/chromium/cc/paint/paint_shader.h
index 54529f65cd8..dab47c4ad04 100644
--- a/chromium/cc/paint/paint_shader.h
+++ b/chromium/cc/paint/paint_shader.h
@@ -11,6 +11,7 @@
#include "base/stl_util.h"
#include "cc/paint/image_analysis_state.h"
#include "cc/paint/paint_export.h"
+#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_image.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkImage.h"
@@ -148,7 +149,10 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
return base::OptionalOrNullptr(tile_scale_);
}
const sk_sp<PaintRecord>& paint_record() const { return record_; }
- bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const;
+ bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const {
+ return GetClampedRasterizationTileRect(ctm, /*max_texture_size=*/0,
+ tile_rect);
+ }
SkTileMode tx() const { return tx_; }
SkTileMode ty() const { return ty_; }
@@ -184,7 +188,11 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
explicit PaintShader(Type type);
- sk_sp<SkShader> GetSkShader(SkFilterQuality quality) const;
+ bool GetClampedRasterizationTileRect(const SkMatrix& ctm,
+ int max_texture_size,
+ SkRect* tile_rect) const;
+
+ sk_sp<SkShader> GetSkShader(PaintFlags::FilterQuality quality) const;
// If the type needs a resolve skia object (e.g. SkImage or SkPicture), this
// will create and cache it internally. Most types do not need this, but it
@@ -208,13 +216,14 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
// |raster_quality| is set to the filter quality the shader should be
// rasterized with.
// Valid only for PaintImage backed shaders.
- sk_sp<PaintShader> CreateDecodedImage(const SkMatrix& ctm,
- SkFilterQuality requested_quality,
- ImageProvider* image_provider,
- uint32_t* transfer_cache_entry_id,
- SkFilterQuality* raster_quality,
- bool* needs_mips,
- gpu::Mailbox* mailbox) const;
+ sk_sp<PaintShader> CreateDecodedImage(
+ const SkMatrix& ctm,
+ PaintFlags::FilterQuality requested_quality,
+ ImageProvider* image_provider,
+ uint32_t* transfer_cache_entry_id,
+ PaintFlags::FilterQuality* raster_quality,
+ bool* needs_mips,
+ gpu::Mailbox* mailbox) const;
// Creates a paint record shader for worklet-backed images.
sk_sp<PaintShader> CreatePaintWorkletRecord(
diff --git a/chromium/cc/paint/paint_worklet_input.h b/chromium/cc/paint/paint_worklet_input.h
index efbccdfeb69..0af104f2a2f 100644
--- a/chromium/cc/paint/paint_worklet_input.h
+++ b/chromium/cc/paint/paint_worklet_input.h
@@ -29,6 +29,7 @@ class CC_PAINT_EXPORT PaintWorkletInput
public:
enum class NativePropertyType {
kBackgroundColor,
+ kClipPath,
kInvalid,
};
// Uniquely identifies a property from the animation system, so that a
@@ -88,6 +89,8 @@ class CC_PAINT_EXPORT PaintWorkletInput
using PropertyKeys = std::vector<PropertyKey>;
virtual const PropertyKeys& GetPropertyKeys() const = 0;
+ virtual bool IsCSSPaintWorkletInput() const = 0;
+
protected:
friend class base::RefCountedThreadSafe<PaintWorkletInput>;
virtual ~PaintWorkletInput() = default;
diff --git a/chromium/cc/paint/record_paint_canvas.cc b/chromium/cc/paint/record_paint_canvas.cc
index bdb735eede9..8349dd9e4a3 100644
--- a/chromium/cc/paint/record_paint_canvas.cc
+++ b/chromium/cc/paint/record_paint_canvas.cc
@@ -12,6 +12,7 @@
#include "cc/paint/paint_recorder.h"
#include "cc/paint/skottie_wrapper.h"
#include "third_party/skia/include/core/SkAnnotation.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"
namespace cc {
@@ -150,7 +151,8 @@ void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
void RecordPaintCanvas::clipPath(const SkPath& path,
SkClipOp op,
- bool antialias) {
+ bool antialias,
+ UsePaintCache use_paint_cache) {
if (!path.isInverseFillType() &&
GetCanvas()->getTotalMatrix().rectStaysRect()) {
// TODO(enne): do these cases happen? should the caller know that this isn't
@@ -172,7 +174,7 @@ void RecordPaintCanvas::clipPath(const SkPath& path,
}
}
- list_->push<ClipPathOp>(path, op, antialias);
+ list_->push<ClipPathOp>(path, op, antialias, use_paint_cache);
GetCanvas()->clipPath(path, op, antialias);
return;
}
@@ -257,8 +259,10 @@ void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
}
}
-void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
- list_->push<DrawPathOp>(path, flags);
+void RecordPaintCanvas::drawPath(const SkPath& path,
+ const PaintFlags& flags,
+ UsePaintCache use_paint_cache) {
+ list_->push<DrawPathOp>(path, flags, use_paint_cache);
}
void RecordPaintCanvas::drawImage(const PaintImage& image,
diff --git a/chromium/cc/paint/record_paint_canvas.h b/chromium/cc/paint/record_paint_canvas.h
index 3f35f5d15c3..c0aa89129fb 100644
--- a/chromium/cc/paint/record_paint_canvas.h
+++ b/chromium/cc/paint/record_paint_canvas.h
@@ -53,7 +53,10 @@ class CC_PAINT_EXPORT RecordPaintCanvas : public PaintCanvas {
void clipRect(const SkRect& rect, SkClipOp op, bool antialias) override;
void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) override;
- void clipPath(const SkPath& path, SkClipOp op, bool antialias) override;
+ void clipPath(const SkPath& path,
+ SkClipOp op,
+ bool antialias,
+ UsePaintCache use_paint_cache) override;
SkRect getLocalClipBounds() const override;
bool getLocalClipBounds(SkRect* bounds) const override;
SkIRect getDeviceClipBounds() const override;
@@ -77,7 +80,9 @@ class CC_PAINT_EXPORT RecordPaintCanvas : public PaintCanvas {
SkScalar rx,
SkScalar ry,
const PaintFlags& flags) override;
- void drawPath(const SkPath& path, const PaintFlags& flags) override;
+ void drawPath(const SkPath& path,
+ const PaintFlags& flags,
+ UsePaintCache use_paint_cache) override;
void drawImage(const PaintImage& image,
SkScalar left,
SkScalar top,
diff --git a/chromium/cc/paint/render_surface_filters.cc b/chromium/cc/paint/render_surface_filters.cc
index d8b243ee1a1..698af3ca0af 100644
--- a/chromium/cc/paint/render_surface_filters.cc
+++ b/chromium/cc/paint/render_surface_filters.cc
@@ -4,6 +4,7 @@
#include <stddef.h>
#include <algorithm>
+#include <utility>
#include "cc/paint/render_surface_filters.h"
@@ -294,6 +295,12 @@ sk_sp<PaintFilter> RenderSurfaceFilters::BuildImageFilter(
}
break;
}
+ case FilterOperation::STRETCH: {
+ image_filter = sk_make_sp<StretchPaintFilter>(
+ op.amount(), op.outer_threshold(), size.width(), size.height(),
+ std::move(image_filter));
+ break;
+ }
}
}
return image_filter;
diff --git a/chromium/cc/paint/scoped_raster_flags.cc b/chromium/cc/paint/scoped_raster_flags.cc
index 8bd3ce0640c..171b5514ae3 100644
--- a/chromium/cc/paint/scoped_raster_flags.cc
+++ b/chromium/cc/paint/scoped_raster_flags.cc
@@ -64,7 +64,7 @@ void ScopedRasterFlags::DecodeImageShader(const SkMatrix& ctm) {
}
uint32_t transfer_cache_entry_id = kInvalidImageTransferCacheEntryId;
- SkFilterQuality raster_quality = flags()->getFilterQuality();
+ PaintFlags::FilterQuality raster_quality = flags()->getFilterQuality();
bool transfer_cache_entry_needs_mips = false;
gpu::Mailbox mailbox;
auto decoded_shader = flags()->getShader()->CreateDecodedImage(
diff --git a/chromium/cc/paint/scoped_raster_flags.h b/chromium/cc/paint/scoped_raster_flags.h
index 3550c1181a5..792cbc19fdd 100644
--- a/chromium/cc/paint/scoped_raster_flags.h
+++ b/chromium/cc/paint/scoped_raster_flags.h
@@ -9,6 +9,7 @@
#include "cc/paint/decode_stashing_image_provider.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_flags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cc {
diff --git a/chromium/cc/paint/skia_paint_canvas.cc b/chromium/cc/paint/skia_paint_canvas.cc
index 0f1d38da3fe..34e9cf4f0f5 100644
--- a/chromium/cc/paint/skia_paint_canvas.cc
+++ b/chromium/cc/paint/skia_paint_canvas.cc
@@ -12,6 +12,7 @@
#include "cc/paint/skottie_wrapper.h"
#include "skia/ext/legacy_display_globals.h"
#include "third_party/skia/include/core/SkAnnotation.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
#include "third_party/skia/include/docs/SkPDFDocument.h"
namespace cc {
@@ -125,7 +126,8 @@ void SkiaPaintCanvas::clipRRect(const SkRRect& rrect,
void SkiaPaintCanvas::clipPath(const SkPath& path,
SkClipOp op,
- bool do_anti_alias) {
+ bool do_anti_alias,
+ UsePaintCache) {
canvas_->clipPath(path, op, do_anti_alias);
}
@@ -250,7 +252,9 @@ void SkiaPaintCanvas::drawRoundRect(const SkRect& rect,
FlushAfterDrawIfNeeded();
}
-void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
+void SkiaPaintCanvas::drawPath(const SkPath& path,
+ const PaintFlags& flags,
+ UsePaintCache) {
ScopedRasterFlags raster_flags(&flags, image_provider_,
canvas_->getTotalMatrix(), max_texture_size(),
255u);
diff --git a/chromium/cc/paint/skia_paint_canvas.h b/chromium/cc/paint/skia_paint_canvas.h
index bc7057a7248..d83020ced20 100644
--- a/chromium/cc/paint/skia_paint_canvas.h
+++ b/chromium/cc/paint/skia_paint_canvas.h
@@ -77,7 +77,10 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas {
void clipRRect(const SkRRect& rrect,
SkClipOp op,
bool do_anti_alias) override;
- void clipPath(const SkPath& path, SkClipOp op, bool do_anti_alias) override;
+ void clipPath(const SkPath& path,
+ SkClipOp op,
+ bool do_anti_alias,
+ UsePaintCache) override;
SkRect getLocalClipBounds() const override;
bool getLocalClipBounds(SkRect* bounds) const override;
SkIRect getDeviceClipBounds() const override;
@@ -101,7 +104,9 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas {
SkScalar rx,
SkScalar ry,
const PaintFlags& flags) override;
- void drawPath(const SkPath& path, const PaintFlags& flags) override;
+ void drawPath(const SkPath& path,
+ const PaintFlags& flags,
+ UsePaintCache) override;
void drawImage(const PaintImage& image,
SkScalar left,
SkScalar top,
diff --git a/chromium/cc/paint/solid_color_analyzer.h b/chromium/cc/paint/solid_color_analyzer.h
index e86ef17031e..71a0908a3f9 100644
--- a/chromium/cc/paint/solid_color_analyzer.h
+++ b/chromium/cc/paint/solid_color_analyzer.h
@@ -14,6 +14,7 @@
#include "ui/gfx/skia_util.h"
namespace cc {
+class PaintOpBuffer;
class CC_PAINT_EXPORT SolidColorAnalyzer {
public:
diff --git a/chromium/cc/paint/solid_color_analyzer_unittest.cc b/chromium/cc/paint/solid_color_analyzer_unittest.cc
index 49b3ce81f13..f05461af0ea 100644
--- a/chromium/cc/paint/solid_color_analyzer_unittest.cc
+++ b/chromium/cc/paint/solid_color_analyzer_unittest.cc
@@ -4,8 +4,8 @@
#include "cc/paint/solid_color_analyzer.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
#include "build/build_config.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_filter.h"
diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.cc b/chromium/cc/raster/gpu_raster_buffer_provider.cc
index ded0950475b..2af2773414f 100644
--- a/chromium/cc/raster/gpu_raster_buffer_provider.cc
+++ b/chromium/cc/raster/gpu_raster_buffer_provider.cc
@@ -78,10 +78,15 @@ static void RasterizeSourceOOP(
ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
}
+ // Assume legacy MSAA if sample count is positive.
+ gpu::raster::MsaaMode msaa_mode = playback_settings.msaa_sample_count > 0
+ ? gpu::raster::kMSAA
+ : gpu::raster::kNoMSAA;
+
ri->BeginRasterCHROMIUM(
raster_source->background_color(), mailbox_needs_clear,
- playback_settings.msaa_sample_count, playback_settings.use_lcd_text,
- color_space, mailbox->name);
+ playback_settings.msaa_sample_count, msaa_mode,
+ playback_settings.use_lcd_text, color_space, mailbox->name);
gfx::Vector2dF recording_to_raster_scale = transform.scale();
recording_to_raster_scale.Scale(1 / raster_source->recording_scale_factor());
gfx::Size content_size = raster_source->GetContentSize(transform.scale());
diff --git a/chromium/cc/raster/paint_worklet_image_provider.cc b/chromium/cc/raster/paint_worklet_image_provider.cc
index 040e6d18df7..059c842bd83 100644
--- a/chromium/cc/raster/paint_worklet_image_provider.cc
+++ b/chromium/cc/raster/paint_worklet_image_provider.cc
@@ -23,10 +23,13 @@ PaintWorkletImageProvider& PaintWorkletImageProvider::operator=(
ImageProvider::ScopedResult PaintWorkletImageProvider::GetPaintRecordResult(
scoped_refptr<PaintWorkletInput> input) {
- // The |records_| contains all known PaintWorkletInputs, whether they are
- // painted or not, so |input| should always exist in it.
auto it = records_.find(input);
- DCHECK(it != records_.end());
+ // In the DiscardableImageMap::GatherDiscardableImages(), a DrawImageRect can
+ // early exit the for loop if its paint rect is empty. In that case, the
+ // |records_| will not contain that PaintWorkletInput, and we should return
+ // an empty result.
+ if (it == records_.end())
+ return ImageProvider::ScopedResult();
return ImageProvider::ScopedResult(it->second.second);
}
diff --git a/chromium/cc/raster/playback_image_provider_unittest.cc b/chromium/cc/raster/playback_image_provider_unittest.cc
index fdb5f43c321..2d8d319db65 100644
--- a/chromium/cc/raster/playback_image_provider_unittest.cc
+++ b/chromium/cc/raster/playback_image_provider_unittest.cc
@@ -25,8 +25,8 @@ sk_sp<SkImage> CreateRasterImage() {
DecodedDrawImage CreateDecode() {
return DecodedDrawImage(CreateRasterImage(), nullptr, SkSize::MakeEmpty(),
- SkSize::Make(1.0f, 1.0f), kMedium_SkFilterQuality,
- true);
+ SkSize::Make(1.0f, 1.0f),
+ PaintFlags::FilterQuality::kMedium, true);
}
class MockDecodeCache : public StubDecodeCache {
@@ -79,12 +79,12 @@ TEST(PlaybackImageProviderTest, SkipsAllImages) {
.set_id(PaintImage::GetNextId())
.set_image(CreateRasterImage(), PaintImage::GetNextContentId())
.TakePaintImage(),
- false, rect, kMedium_SkFilterQuality, matrix)));
+ false, rect, PaintFlags::FilterQuality::kMedium, matrix)));
EXPECT_EQ(cache.images_decoded(), 0);
EXPECT_FALSE(provider.GetRasterContent(
CreateDiscardableDrawImage(gfx::Size(10, 10), nullptr, SkRect::Make(rect),
- kMedium_SkFilterQuality, matrix)));
+ PaintFlags::FilterQuality::kMedium, matrix)));
EXPECT_EQ(cache.images_decoded(), 0);
}
@@ -101,8 +101,8 @@ TEST(PlaybackImageProviderTest, SkipsSomeImages) {
SkIRect rect = SkIRect::MakeWH(10, 10);
SkM44 matrix = SkM44();
- EXPECT_FALSE(provider.GetRasterContent(
- DrawImage(skip_image, false, rect, kMedium_SkFilterQuality, matrix)));
+ EXPECT_FALSE(provider.GetRasterContent(DrawImage(
+ skip_image, false, rect, PaintFlags::FilterQuality::kMedium, matrix)));
EXPECT_EQ(cache.images_decoded(), 0);
}
@@ -117,8 +117,9 @@ TEST(PlaybackImageProviderTest, RefAndUnrefDecode) {
{
SkRect rect = SkRect::MakeWH(10, 10);
SkM44 matrix = SkM44();
- auto decode = provider.GetRasterContent(CreateDiscardableDrawImage(
- gfx::Size(10, 10), nullptr, rect, kMedium_SkFilterQuality, matrix));
+ auto decode = provider.GetRasterContent(
+ CreateDiscardableDrawImage(gfx::Size(10, 10), nullptr, rect,
+ PaintFlags::FilterQuality::kMedium, matrix));
EXPECT_TRUE(decode);
EXPECT_EQ(cache.refed_image_count(), 1);
}
@@ -145,7 +146,8 @@ TEST(PlaybackImageProviderTest, SwapsGivenFrames) {
SkIRect rect = SkIRect::MakeWH(10, 10);
SkM44 matrix = SkM44();
- DrawImage draw_image(image, false, rect, kMedium_SkFilterQuality, matrix);
+ DrawImage draw_image(image, false, rect, PaintFlags::FilterQuality::kMedium,
+ matrix);
provider.GetRasterContent(draw_image);
ASSERT_TRUE(cache.last_image().paint_image());
ASSERT_EQ(cache.last_image().paint_image(), image);
@@ -163,8 +165,9 @@ TEST(PlaybackImageProviderTest, BitmapImages) {
{
SkIRect rect = SkIRect::MakeWH(10, 10);
SkM44 matrix = SkM44();
- auto draw_image = DrawImage(CreateBitmapImage(gfx::Size(10, 10)), false,
- rect, kMedium_SkFilterQuality, matrix);
+ auto draw_image =
+ DrawImage(CreateBitmapImage(gfx::Size(10, 10)), false, rect,
+ PaintFlags::FilterQuality::kMedium, matrix);
auto decode = provider.GetRasterContent(draw_image);
EXPECT_TRUE(decode);
EXPECT_EQ(cache.refed_image_count(), 1);
@@ -184,8 +187,9 @@ TEST(PlaybackImageProviderTest, IgnoresImagesNotSupportedByCache) {
{
SkIRect rect = SkIRect::MakeWH(10, 10);
SkM44 matrix = SkM44();
- auto draw_image = DrawImage(CreateBitmapImage(gfx::Size(10, 10)), false,
- rect, kMedium_SkFilterQuality, matrix);
+ auto draw_image =
+ DrawImage(CreateBitmapImage(gfx::Size(10, 10)), false, rect,
+ PaintFlags::FilterQuality::kMedium, matrix);
auto decode = provider.GetRasterContent(draw_image);
EXPECT_TRUE(decode);
EXPECT_EQ(cache.refed_image_count(), 0);
diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc
index 0c371132a4b..9ba0950e799 100644
--- a/chromium/cc/raster/raster_buffer_provider_unittest.cc
+++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc
@@ -176,6 +176,7 @@ class RasterImplementationForOOPR
void BeginRasterCHROMIUM(GLuint sk_color,
GLboolean needs_clear,
GLuint msaa_sample_count,
+ gpu::raster::MsaaMode msaa_mode,
GLboolean can_use_lcd_text,
const gfx::ColorSpace& color_space,
const GLbyte* mailbox) override {}
diff --git a/chromium/cc/raster/raster_source.h b/chromium/cc/raster/raster_source.h
index 98b126da676..ca2aa3c9294 100644
--- a/chromium/cc/raster/raster_source.h
+++ b/chromium/cc/raster/raster_source.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <memory>
+#include <string>
#include <vector>
#include "base/containers/flat_map.h"
@@ -125,6 +126,9 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
size_t* max_op_size_hint() { return &max_op_size_hint_; }
+ void set_debug_name(const std::string& name) { debug_name_ = name; }
+ const std::string& debug_name() const { return debug_name_; }
+
protected:
// RecordingSource is the only class that can create a raster source.
friend class RecordingSource;
@@ -163,6 +167,8 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
const gfx::Size size_;
const int slow_down_raster_scale_factor_for_debug_;
const float recording_scale_factor_;
+ // Used for debugging and tracing.
+ std::string debug_name_;
};
} // namespace cc
diff --git a/chromium/cc/raster/task.cc b/chromium/cc/raster/task.cc
index 5a34ca86ad2..9fc91ffb6a6 100644
--- a/chromium/cc/raster/task.cc
+++ b/chromium/cc/raster/task.cc
@@ -4,6 +4,9 @@
#include "cc/raster/task.h"
+#include <ostream>
+#include <utility>
+
#include "base/check.h"
#include "base/notreached.h"
diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc
index 638db6c4e0c..805bf859f23 100644
--- a/chromium/cc/resources/resource_pool.cc
+++ b/chromium/cc/resources/resource_pool.cc
@@ -181,10 +181,12 @@ ResourcePool::PoolResource* ResourcePool::CreateResource(
ResourcePool::InUsePoolResource ResourcePool::AcquireResource(
const gfx::Size& size,
viz::ResourceFormat format,
- const gfx::ColorSpace& color_space) {
+ const gfx::ColorSpace& color_space,
+ const std::string& debug_name) {
PoolResource* resource = ReuseResource(size, format, color_space);
if (!resource)
resource = CreateResource(size, format, color_space);
+ resource->set_debug_name(debug_name);
return InUsePoolResource(resource, !!context_provider_);
}
@@ -204,7 +206,8 @@ ResourcePool::TryAcquireResourceForPartialRaster(
const gfx::Rect& new_invalidated_rect,
uint64_t previous_content_id,
gfx::Rect* total_invalidated_rect,
- const gfx::ColorSpace& raster_color_space) {
+ const gfx::ColorSpace& raster_color_space,
+ const std::string& debug_name) {
DCHECK(new_content_id);
DCHECK(previous_content_id);
*total_invalidated_rect = gfx::Rect();
@@ -266,10 +269,11 @@ ResourcePool::TryAcquireResourceForPartialRaster(
resource->format());
*total_invalidated_rect = resource->invalidated_rect();
- // Clear the invalidated rect and content ID on the resource being retunred.
+ // Clear the invalidated rect and content ID on the resource being returned.
// These will be updated when raster completes successfully.
resource->set_invalidated_rect(gfx::Rect());
resource->set_content_id(0);
+ resource->set_debug_name(debug_name);
return InUsePoolResource(resource, !!context_provider_);
}
@@ -624,8 +628,10 @@ void ResourcePool::PoolResource::OnMemoryDump(
bool is_free) const {
// Resource IDs are not process-unique, so log with the ResourcePool's unique
// tracing id.
- std::string dump_name = base::StringPrintf(
- "cc/tile_memory/provider_%d/resource_%zd", tracing_id, unique_id_);
+ const std::string dump_name = base::StringPrintf(
+ "cc/tile_memory/provider_%d/%s%sresource_%zd", tracing_id,
+ debug_name_.empty() ? "" : debug_name_.c_str(),
+ debug_name_.empty() ? "" : "/", unique_id_);
MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
// The importance value used here needs to be greater than the importance
diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h
index 248cd33d88b..134fb058b1b 100644
--- a/chromium/cc/resources/resource_pool.h
+++ b/chromium/cc/resources/resource_pool.h
@@ -10,6 +10,7 @@
#include <map>
#include <memory>
+#include <string>
#include <utility>
#include "base/containers/circular_deque.h"
@@ -24,7 +25,6 @@
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/shared_bitmap.h"
#include "gpu/command_buffer/common/sync_token.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
@@ -205,9 +205,11 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider {
ResourcePool& operator=(const ResourcePool&) = delete;
// Tries to reuse a resource. If none are available, makes a new one.
- InUsePoolResource AcquireResource(const gfx::Size& size,
- viz::ResourceFormat format,
- const gfx::ColorSpace& color_space);
+ InUsePoolResource AcquireResource(
+ const gfx::Size& size,
+ viz::ResourceFormat format,
+ const gfx::ColorSpace& color_space,
+ const std::string& debug_name = std::string());
// Tries to acquire the resource with |previous_content_id| for us in partial
// raster. If successful, this function will retun the invalidated rect which
@@ -217,7 +219,8 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider {
const gfx::Rect& new_invalidated_rect,
uint64_t previous_content_id,
gfx::Rect* total_invalidated_rect,
- const gfx::ColorSpace& raster_color_space);
+ const gfx::ColorSpace& raster_color_space,
+ const std::string& debug_name = std::string());
// Gives the InUsePoolResource a |resource_id_for_export()| in order to allow
// exporting of the resource to the display compositor. This must be called
@@ -322,6 +325,9 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider {
const viz::ClientResourceProvider* resource_provider,
bool is_free) const;
+ void set_debug_name(const std::string& name) { debug_name_ = name; }
+ const std::string& debug_name() const { return debug_name_; }
+
private:
const size_t unique_id_;
const gfx::Size size_;
@@ -348,6 +354,9 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider {
// out by ResourcePool, to be filled in by the client. Is destroyed on the
// compositor thread.
std::unique_ptr<SoftwareBacking> software_backing_;
+
+ // Used for debugging and tracing.
+ std::string debug_name_;
};
// Callback from the ResourceProvider to notify when an exported PoolResource
diff --git a/chromium/cc/resources/ui_resource_bitmap.cc b/chromium/cc/resources/ui_resource_bitmap.cc
index f63f5e38d7f..b4982dfdd0c 100644
--- a/chromium/cc/resources/ui_resource_bitmap.cc
+++ b/chromium/cc/resources/ui_resource_bitmap.cc
@@ -7,10 +7,13 @@
#include <stdint.h>
#include <memory>
+#include <utility>
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/numerics/checked_math.h"
+#include "build/build_config.h"
+#include "gpu/config/gpu_finch_features.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
@@ -71,9 +74,28 @@ size_t UIResourceBitmap::SizeInBytes() const {
UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) {
DCHECK(skbitmap.isImmutable());
- sk_sp<SkPixelRef> pixel_ref = sk_ref_sp(skbitmap.pixelRef());
- Create(std::move(pixel_ref), skbitmap.info(),
- SkColorTypeToUIResourceFormat(skbitmap.colorType()));
+ const SkBitmap* target = &skbitmap;
+#if defined(OS_ANDROID)
+ SkBitmap copy;
+ if (features::IsDrDcEnabled()) {
+ // TODO(vikassoni): Forcing everything to N32 while android backing cannot
+ // support some other formats.
+ if (skbitmap.colorType() != kN32_SkColorType) {
+ SkImageInfo new_info = skbitmap.info().makeColorType(kN32_SkColorType);
+ copy.allocPixels(new_info, new_info.minRowBytes());
+ SkCanvas copy_canvas(copy);
+ copy_canvas.drawImage(skbitmap.asImage(), 0, 0, SkSamplingOptions(),
+ nullptr);
+ copy.setImmutable();
+ target = &copy;
+ }
+ DCHECK_EQ(target->width(), target->rowBytesAsPixels());
+ DCHECK(target->isImmutable());
+ }
+#endif
+ sk_sp<SkPixelRef> pixel_ref = sk_ref_sp(target->pixelRef());
+ Create(std::move(pixel_ref), target->info(),
+ SkColorTypeToUIResourceFormat(target->colorType()));
}
UIResourceBitmap::UIResourceBitmap(const gfx::Size& size, bool is_opaque) {
diff --git a/chromium/cc/scheduler/begin_frame_tracker.cc b/chromium/cc/scheduler/begin_frame_tracker.cc
index ac085cb128b..ffeda4ce387 100644
--- a/chromium/cc/scheduler/begin_frame_tracker.cc
+++ b/chromium/cc/scheduler/begin_frame_tracker.cc
@@ -26,11 +26,12 @@ void BeginFrameTracker::Start(const viz::BeginFrameArgs& new_args) {
"location", location_string_);
// Trace this specific begin frame tracker Start/Finish times.
- TRACE_EVENT_COPY_ASYNC_BEGIN2(
+ TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN2(
TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
location_string_.c_str(),
- new_args.frame_time.since_origin().InMicroseconds(), "new args",
- new_args.AsValue(), "current args", current_args_.AsValue());
+ TRACE_ID_WITH_SCOPE(location_string_.c_str(),
+ new_args.frame_time.since_origin().InMicroseconds()),
+ "new args", new_args.AsValue(), "current args", current_args_.AsValue());
// Check the new viz::BeginFrameArgs are valid and monotonically increasing.
DCHECK(new_args.IsValid());
@@ -58,10 +59,12 @@ const viz::BeginFrameArgs& BeginFrameTracker::Current() const {
void BeginFrameTracker::Finish() {
DCHECK(!HasFinished()) << "Tried to finish an already finished frame";
current_finished_at_ = base::TimeTicks::Now();
- TRACE_EVENT_COPY_ASYNC_END0(
+ TRACE_EVENT_COPY_NESTABLE_ASYNC_END0(
TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
location_string_.c_str(),
- current_args_.frame_time.since_origin().InMicroseconds());
+ TRACE_ID_WITH_SCOPE(
+ location_string_.c_str(),
+ current_args_.frame_time.since_origin().InMicroseconds()));
}
const viz::BeginFrameArgs& BeginFrameTracker::Last() const {
@@ -83,6 +86,7 @@ base::TimeDelta BeginFrameTracker::Interval() const {
}
void BeginFrameTracker::AsProtozeroInto(
+ perfetto::EventContext& ctx,
base::TimeTicks now,
perfetto::protos::pbzero::BeginImplFrameArgs* state) const {
state->set_updated_at_us(current_updated_at_.since_origin().InMicroseconds());
@@ -91,11 +95,11 @@ void BeginFrameTracker::AsProtozeroInto(
if (HasFinished()) {
state->set_state(
perfetto::protos::pbzero::BeginImplFrameArgs::BEGIN_FRAME_FINISHED);
- current_args_.AsProtozeroInto(state->set_current_args());
+ current_args_.AsProtozeroInto(ctx, state->set_current_args());
} else {
state->set_state(
perfetto::protos::pbzero::BeginImplFrameArgs::BEGIN_FRAME_USING);
- current_args_.AsProtozeroInto(state->set_last_args());
+ current_args_.AsProtozeroInto(ctx, state->set_last_args());
}
base::TimeTicks frame_time = current_args_.frame_time;
diff --git a/chromium/cc/scheduler/begin_frame_tracker.h b/chromium/cc/scheduler/begin_frame_tracker.h
index c718ca39559..1165a0ca352 100644
--- a/chromium/cc/scheduler/begin_frame_tracker.h
+++ b/chromium/cc/scheduler/begin_frame_tracker.h
@@ -12,6 +12,7 @@
#include "components/viz/common/frame_sinks/begin_frame_args.h"
namespace perfetto {
+class EventContext;
namespace protos {
namespace pbzero {
class BeginImplFrameArgs;
@@ -71,6 +72,7 @@ class CC_EXPORT BeginFrameTracker {
base::TimeDelta Interval() const;
void AsProtozeroInto(
+ perfetto::EventContext& ctx,
base::TimeTicks now,
perfetto::protos::pbzero::BeginImplFrameArgs* dict) const;
diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc
index ccb984ddcff..a8ba4e2793f 100644
--- a/chromium/cc/scheduler/scheduler.cc
+++ b/chromium/cc/scheduler/scheduler.cc
@@ -554,31 +554,6 @@ void Scheduler::BeginImplFrameWithDeadline(const viz::BeginFrameArgs& args) {
state_machine_.set_should_defer_invalidation_for_fast_main_frame(
main_thread_response_expected_before_deadline);
- base::TimeDelta bmf_to_activate_estimate = bmf_to_activate_estimate_critical;
- if (!begin_main_frame_args_.on_critical_path) {
- bmf_to_activate_estimate =
- compositor_timing_history_
- ->BeginMainFrameQueueToActivateNotCriticalEstimate();
- }
- bool can_activate_before_deadline =
- CanBeginMainFrameAndActivateBeforeDeadline(adjusted_args,
- bmf_to_activate_estimate, now);
-
- if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) {
- TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
- TRACE_EVENT_SCOPE_THREAD);
- state_machine_.SetSkipNextBeginMainFrameToReduceLatency(true);
- } else if (ShouldRecoverImplLatency(adjusted_args,
- can_activate_before_deadline)) {
- TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
- TRACE_EVENT_SCOPE_THREAD);
- skipped_last_frame_to_reduce_latency_ = true;
- SendDidNotProduceFrame(args, FrameSkippedReason::kRecoverLatency);
- return;
- }
-
- skipped_last_frame_to_reduce_latency_ = false;
-
// A pipeline is activated if it's subscribed to BeginFrame callbacks. For the
// compositor this implies BeginImplFrames while for the main thread it would
// be BeginMainFrames.
@@ -788,6 +763,7 @@ void Scheduler::OnBeginImplFrameDeadline() {
// order to wait for more user-input before starting the next commit.
// * Creating a new OuputSurface will not occur during the deadline in
// order to allow the state machine to "settle" first.
+ compositor_timing_history_->RecordDeadlineMode(deadline_mode_);
if (!settings_.using_synchronous_renderer_compositor) {
compositor_timing_history_->WillFinishImplFrame(
state_machine_.needs_redraw());
@@ -869,7 +845,8 @@ void Scheduler::ProcessScheduledActions() {
action = state_machine_.NextAction();
TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
"SchedulerStateMachine", [this](perfetto::EventContext ctx) {
- this->AsProtozeroInto(ctx.event()->set_cc_scheduler_state());
+ this->AsProtozeroInto(ctx,
+ ctx.event()->set_cc_scheduler_state());
});
base::AutoReset<SchedulerStateMachine::Action> mark_inside_action(
&inside_action_, action);
@@ -956,6 +933,7 @@ void Scheduler::ProcessScheduledActions() {
}
void Scheduler::AsProtozeroInto(
+ perfetto::EventContext& ctx,
perfetto::protos::pbzero::ChromeCompositorSchedulerState* state) const {
base::TimeTicks now = Now();
@@ -967,8 +945,6 @@ void Scheduler::AsProtozeroInto(
state->set_pending_begin_frame_task(!pending_begin_frame_task_.IsCancelled());
state->set_skipped_last_frame_missed_exceeded_deadline(
skipped_last_frame_missed_exceeded_deadline_);
- state->set_skipped_last_frame_to_reduce_latency(
- skipped_last_frame_to_reduce_latency_);
state->set_inside_action(
SchedulerStateMachine::ActionToProtozeroEnum(inside_action_));
state->set_deadline_mode(
@@ -984,14 +960,15 @@ void Scheduler::AsProtozeroInto(
state->set_now_to_deadline_scheduled_at_delta_us(
(deadline_scheduled_at_ - Now()).InMicroseconds());
- begin_impl_frame_tracker_.AsProtozeroInto(now,
+ begin_impl_frame_tracker_.AsProtozeroInto(ctx, now,
state->set_begin_impl_frame_args());
BeginFrameObserverBase::AsProtozeroInto(
- state->set_begin_frame_observer_state());
+ ctx, state->set_begin_frame_observer_state());
if (begin_frame_source_) {
- begin_frame_source_->AsProtozeroInto(state->set_begin_frame_source_state());
+ begin_frame_source_->AsProtozeroInto(ctx,
+ state->set_begin_frame_source_state());
}
}
@@ -1001,89 +978,6 @@ void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() {
state_machine_.visible());
}
-bool Scheduler::ShouldRecoverMainLatency(
- const viz::BeginFrameArgs& args,
- bool can_activate_before_deadline) const {
- DCHECK(!settings_.using_synchronous_renderer_compositor);
-
- if (!settings_.enable_main_latency_recovery)
- return false;
-
- // The main thread is in a low latency mode and there's no need to recover.
- if (!state_machine_.main_thread_missed_last_deadline())
- return false;
-
- // When prioritizing impl thread latency, we currently put the
- // main thread in a high latency mode. Don't try to fight it.
- if (state_machine_.ImplLatencyTakesPriority())
- return false;
-
- // Ensure that we have data from at least one frame before attempting latency
- // recovery. This prevents skipping of frames during loading where the main
- // thread is likely slow but we assume it to be fast since we have no history.
- static const int kMinNumberOfSamplesBeforeLatencyRecovery = 1;
- if (compositor_timing_history_
- ->begin_main_frame_start_to_ready_to_commit_sample_count() <
- kMinNumberOfSamplesBeforeLatencyRecovery ||
- compositor_timing_history_->commit_to_ready_to_activate_sample_count() <
- kMinNumberOfSamplesBeforeLatencyRecovery) {
- return false;
- }
-
- return can_activate_before_deadline;
-}
-
-bool Scheduler::ShouldRecoverImplLatency(
- const viz::BeginFrameArgs& args,
- bool can_activate_before_deadline) const {
- DCHECK(!settings_.using_synchronous_renderer_compositor);
-
- if (!settings_.enable_impl_latency_recovery)
- return false;
-
- // Disable impl thread latency recovery when using the unthrottled
- // begin frame source since we will always get a BeginFrame before
- // the swap ack and our heuristics below will not work.
- if (begin_frame_source_ && !begin_frame_source_->IsThrottled())
- return false;
-
- // If we are swap throttled at the BeginFrame, that means the impl thread is
- // very likely in a high latency mode.
- bool impl_thread_is_likely_high_latency = state_machine_.IsDrawThrottled();
- if (!impl_thread_is_likely_high_latency)
- return false;
-
- // The deadline may be in the past if our draw time is too long.
- bool can_draw_before_deadline = args.frame_time < args.deadline;
-
- // When prioritizing impl thread latency, the deadline doesn't wait
- // for the main thread.
- if (state_machine_.ImplLatencyTakesPriority())
- return can_draw_before_deadline;
-
- // If we only have impl-side updates, the deadline doesn't wait for
- // the main thread.
- if (state_machine_.OnlyImplSideUpdatesExpected())
- return can_draw_before_deadline;
-
- // If we get here, we know the main thread is in a low-latency mode relative
- // to the impl thread. In this case, only try to also recover impl thread
- // latency if both the main and impl threads can run serially before the
- // deadline.
- return can_activate_before_deadline;
-}
-
-bool Scheduler::CanBeginMainFrameAndActivateBeforeDeadline(
- const viz::BeginFrameArgs& args,
- base::TimeDelta bmf_to_activate_estimate,
- base::TimeTicks now) const {
- // Check if the main thread computation and commit can be finished before the
- // impl thread's deadline.
- base::TimeTicks estimated_draw_time = now + bmf_to_activate_estimate;
-
- return estimated_draw_time < args.deadline;
-}
-
bool Scheduler::IsBeginMainFrameSent() const {
return state_machine_.begin_main_frame_state() ==
SchedulerStateMachine::BeginMainFrameState::SENT;
@@ -1095,7 +989,6 @@ viz::BeginFrameAck Scheduler::CurrentBeginFrameAckForActiveTree() const {
void Scheduler::ClearHistory() {
// Ensure we reset decisions based on history from the previous navigation.
- state_machine_.SetSkipNextBeginMainFrameToReduceLatency(false);
compositor_timing_history_->ClearHistory();
ProcessScheduledActions();
}
diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h
index 86f0c7bede6..082fcb53d21 100644
--- a/chromium/cc/scheduler/scheduler.h
+++ b/chromium/cc/scheduler/scheduler.h
@@ -250,6 +250,7 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase {
void SetMainThreadWantsBeginMainFrameNotExpected(bool new_state);
void AsProtozeroInto(
+ perfetto::EventContext& ctx,
perfetto::protos::pbzero::ChromeCompositorSchedulerState* state) const;
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
@@ -284,7 +285,6 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase {
bool observing_begin_frame_source_ = false;
bool skipped_last_frame_missed_exceeded_deadline_ = false;
- bool skipped_last_frame_to_reduce_latency_ = false;
std::unique_ptr<CompositorTimingHistory> compositor_timing_history_;
@@ -384,14 +384,6 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase {
void DrawForced();
void ProcessScheduledActions();
void UpdateCompositorTimingHistoryRecordingEnabled();
- bool ShouldRecoverMainLatency(const viz::BeginFrameArgs& args,
- bool can_activate_before_deadline) const;
- bool ShouldRecoverImplLatency(const viz::BeginFrameArgs& args,
- bool can_activate_before_deadline) const;
- bool CanBeginMainFrameAndActivateBeforeDeadline(
- const viz::BeginFrameArgs& args,
- base::TimeDelta bmf_to_activate_estimate,
- base::TimeTicks now) const;
void AdvanceCommitStateIfPossible();
void BeginImplFrameWithDeadline(const viz::BeginFrameArgs& args);
diff --git a/chromium/cc/scheduler/scheduler_settings.cc b/chromium/cc/scheduler/scheduler_settings.cc
index d63db2a646f..5e6338c0a0d 100644
--- a/chromium/cc/scheduler/scheduler_settings.cc
+++ b/chromium/cc/scheduler/scheduler_settings.cc
@@ -4,6 +4,8 @@
#include "cc/scheduler/scheduler_settings.h"
+#include <utility>
+
#include "base/trace_event/traced_value.h"
namespace cc {
@@ -25,10 +27,6 @@ SchedulerSettings::AsValue() const {
maximum_number_of_failed_draws_before_draw_is_forced);
state->SetBoolean("using_synchronous_renderer_compositor",
using_synchronous_renderer_compositor);
- state->SetBoolean("enable_impl_latency_recovery",
- enable_impl_latency_recovery);
- state->SetBoolean("enable_main_latency_recovery",
- enable_main_latency_recovery);
state->SetBoolean("wait_for_all_pipeline_stages_before_draw",
wait_for_all_pipeline_stages_before_draw);
return std::move(state);
diff --git a/chromium/cc/scheduler/scheduler_settings.h b/chromium/cc/scheduler/scheduler_settings.h
index 55ace0031ae..f852ca2a6e3 100644
--- a/chromium/cc/scheduler/scheduler_settings.h
+++ b/chromium/cc/scheduler/scheduler_settings.h
@@ -37,16 +37,10 @@ class CC_EXPORT SchedulerSettings {
// This is enabled for android-webview.
bool using_synchronous_renderer_compositor = false;
- // This is used to determine whether some begin-frames should be skipped
- // (either in the main-thread or the compositor-thread) if previous frames
- // have had high latency. It is disabled by default.
- bool enable_impl_latency_recovery = false;
- bool enable_main_latency_recovery = false;
-
// Turning this on effectively disables pipelining of compositor frame
// production stages by waiting for each stage to complete before producing
- // the frame. Turning this on also disables latency-recovery. This is enabled
- // for headless-mode and some tests, and disabled elsewhere by default.
+ // the frame. This is enabled for headless-mode and some tests, and disabled
+ // elsewhere by default.
bool wait_for_all_pipeline_stages_before_draw = false;
int maximum_number_of_failed_draws_before_draw_is_forced = 3;
diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc
index 8fc7ba939d7..0e49dca023e 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.cc
+++ b/chromium/cc/scheduler/scheduler_state_machine.cc
@@ -262,8 +262,6 @@ void SchedulerStateMachine::AsProtozeroInto(
critical_begin_main_frame_to_activate_is_fast_);
minor_state->set_main_thread_missed_last_deadline(
main_thread_missed_last_deadline_);
- minor_state->set_skip_next_begin_main_frame_to_reduce_latency(
- skip_next_begin_main_frame_to_reduce_latency_);
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_);
@@ -599,9 +597,6 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
if (IsDrawThrottled() && !just_submitted_in_deadline)
return false;
- if (skip_next_begin_main_frame_to_reduce_latency_)
- return false;
-
return true;
}
@@ -1041,13 +1036,6 @@ void SchedulerStateMachine::WillInvalidateLayerTreeFrameSink() {
current_frame_number_;
}
-void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency(
- bool skip) {
- TRACE_EVENT_INSTANT0("cc", "Scheduler: SkipNextBeginMainFrameToReduceLatency",
- TRACE_EVENT_SCOPE_THREAD);
- skip_next_begin_main_frame_to_reduce_latency_ = skip;
-}
-
bool SchedulerStateMachine::BeginFrameNeededForVideo() const {
return video_needs_begin_frames_;
}
@@ -1193,8 +1181,6 @@ void SchedulerStateMachine::OnBeginImplFrameIdle() {
// This is same as the old prepare tiles funnel behavior.
did_prepare_tiles_ = false;
- skip_next_begin_main_frame_to_reduce_latency_ = false;
-
// If a new or undrawn active tree is pending after the deadline,
// then the main thread is in a high latency mode.
main_thread_missed_last_deadline_ =
@@ -1359,14 +1345,6 @@ void SchedulerStateMachine::SetNeedsRedraw() {
needs_redraw_ = true;
}
-bool SchedulerStateMachine::OnlyImplSideUpdatesExpected() const {
- bool has_impl_updates = needs_redraw_ || needs_one_begin_impl_frame_;
- bool main_updates_expected =
- needs_begin_main_frame_ ||
- begin_main_frame_state_ != BeginMainFrameState::IDLE || has_pending_tree_;
- return has_impl_updates && !main_updates_expected;
-}
-
void SchedulerStateMachine::SetNeedsPrepareTiles() {
if (!needs_prepare_tiles_) {
TRACE_EVENT0("cc", "SchedulerStateMachine::SetNeedsPrepareTiles");
diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h
index 0f0705272da..70f8b8b2f1d 100644
--- a/chromium/cc/scheduler/scheduler_state_machine.h
+++ b/chromium/cc/scheduler/scheduler_state_machine.h
@@ -64,18 +64,25 @@ class CC_EXPORT SchedulerStateMachine {
BeginImplFrameState
BeginImplFrameStateToProtozeroEnum(BeginImplFrameState state);
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ // TODO(weiliangc): The histogram is used to understanding what type of
+ // deadline mode do we encounter in real world and is set to expire after
+ // 2022. The Enum can be changed after the histogram is removed.
// The scheduler uses a deadline to wait for main thread updates before
// submitting a compositor frame. BeginImplFrameDeadlineMode specifies when
// the deadline should run.
enum class BeginImplFrameDeadlineMode {
- NONE, // No deadline should be scheduled e.g. for synchronous compositor.
- IMMEDIATE, // Deadline should be scheduled to run immediately.
- REGULAR, // Deadline should be scheduled to run at the deadline provided by
- // in the BeginFrameArgs.
- LATE, // Deadline should be scheduled run when the next frame is expected
- // to arrive.
- BLOCKED, // Deadline should be blocked indefinitely until the next frame
- // arrives.
+ NONE = 0, // No deadline should be scheduled e.g. for synchronous
+ // compositor.
+ IMMEDIATE = 1, // Deadline should be scheduled to run immediately.
+ REGULAR = 2, // Deadline should be scheduled to run at the deadline
+ // provided by in the BeginFrameArgs.
+ LATE = 3, // Deadline should be scheduled run when the next frame is
+ // expected to arrive.
+ BLOCKED = 4, // Deadline should be blocked indefinitely until the next
+ // frame arrives.
+ kMaxValue = BLOCKED,
};
// TODO(nuskos): Update Scheduler::ScheduleBeginImplFrameDeadline event to
// used typed macros so we can remove this ToString function.
@@ -212,8 +219,6 @@ class CC_EXPORT SchedulerStateMachine {
return did_invalidate_layer_tree_frame_sink_;
}
- bool OnlyImplSideUpdatesExpected() const;
-
// Indicates that prepare-tiles is required. This guarantees another
// PrepareTiles will occur shortly (even if no redraw is required).
void SetNeedsPrepareTiles();
@@ -265,9 +270,6 @@ class CC_EXPORT SchedulerStateMachine {
// from NextAction if the client rejects the BeginMainFrame message.
void BeginMainFrameAborted(CommitEarlyOutReason reason);
- // Indicates production should be skipped to recover latency.
- void SetSkipNextBeginMainFrameToReduceLatency(bool skip);
-
// For Android WebView, resourceless software draws are allowed even when
// invisible.
void SetResourcelessSoftwareDraw(bool resourceless_draw);
@@ -453,7 +455,6 @@ class CC_EXPORT SchedulerStateMachine {
ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
bool critical_begin_main_frame_to_activate_is_fast_ = true;
bool main_thread_missed_last_deadline_ = false;
- bool skip_next_begin_main_frame_to_reduce_latency_ = false;
bool defer_begin_main_frame_ = false;
bool video_needs_begin_frames_ = false;
bool last_commit_had_no_updates_ = false;
diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc
index c3ae6947720..57bc2db1b0d 100644
--- a/chromium/cc/scheduler/scheduler_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_unittest.cc
@@ -414,9 +414,6 @@ class SchedulerTest : public testing::Test {
client_->set_scheduler(scheduler_.get());
scheduler_->SetBeginFrameSource(frame_source);
- // Use large estimates by default to avoid latency recovery in most tests.
- fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
-
return scheduler_.get();
}
@@ -581,8 +578,6 @@ class SchedulerTest : public testing::Test {
void AdvanceAndMissOneFrame();
void CheckMainFrameNotSkippedAfterLateCommit();
- void ImplFrameSkippedAfterLateAck(bool is_already_receiving_begin_frames,
- bool receive_ack_before_deadline);
void ImplFrameNotSkippedAfterLateAck();
void BeginFramesNotFromClient(BeginFrameSourceType bfs_type);
void BeginFramesNotFromClient_IsDrawThrottled(BeginFrameSourceType bfs_type);
@@ -1774,211 +1769,6 @@ TEST_F(SchedulerTest, MainFrameNotSkippedWhenNoTimingHistory) {
EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
}
-void SchedulerTest::ImplFrameSkippedAfterLateAck(
- bool is_already_receiving_begin_frames,
- bool receive_ack_before_deadline) {
- // To get into a high latency state, this test disables automatic swap acks.
- client_->SetAutomaticSubmitCompositorFrameAck(false);
-
- // Draw and swap for first BeginFrame
- client_->Reset();
- scheduler_->SetNeedsBeginMainFrame();
- scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- if (is_already_receiving_begin_frames) {
- EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
- } else {
- EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
- "ScheduledActionSendBeginMainFrame");
- }
-
- client_->Reset();
- scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
- scheduler_->NotifyReadyToCommit(nullptr);
- scheduler_->NotifyReadyToActivate();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
- "ScheduledActionDrawIfPossible");
-
- // Verify we skip every other frame if the swap ack consistently
- // comes back late.
- for (int i = 0; i < 10; i++) {
- // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
- // BeginImplFrame puts the impl thread in high latency mode.
- client_->Reset();
- scheduler_->SetNeedsBeginMainFrame();
- scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- // Verify that we skip the BeginImplFrame
- 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.
- client_->Reset();
- if (receive_ack_before_deadline) {
- // It shouldn't matter if the swap ack comes back before the deadline...
- scheduler_->DidReceiveCompositorFrameAck();
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- } else {
- // ... or after the deadline.
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- scheduler_->DidReceiveCompositorFrameAck();
- }
- EXPECT_NO_ACTION();
-
- // Verify that we start the next BeginImplFrame and continue normally
- // after having just skipped a BeginImplFrame.
- client_->Reset();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
-
- client_->Reset();
- scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
- scheduler_->NotifyReadyToCommit(nullptr);
- scheduler_->NotifyReadyToActivate();
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
- "ScheduledActionDrawIfPossible");
- }
-}
-
-TEST_F(SchedulerTest,
- ImplFrameSkippedAfterLateAck_FastEstimates_SubmitAckThenDeadline) {
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
- SetUpScheduler(EXTERNAL_BFS);
- fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
-
- bool is_already_receiving_begin_frames = false;
- bool receive_ack_before_deadline = true;
- EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
- receive_ack_before_deadline));
-}
-
-TEST_F(SchedulerTest,
- ImplFrameSkippedAfterLateAck_FastEstimates_DeadlineThenSubmitAck) {
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
- SetUpScheduler(EXTERNAL_BFS);
- fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
-
- bool is_already_receiving_begin_frames = false;
- bool receive_ack_before_deadline = false;
- EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
- receive_ack_before_deadline));
-}
-
-TEST_F(SchedulerTest,
- ImplFrameSkippedAfterLateAck_LongMainFrameQueueDurationNotCritical) {
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
- SetUpScheduler(EXTERNAL_BFS);
- fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
- fake_compositor_timing_history_
- ->SetBeginMainFrameQueueDurationNotCriticalEstimate(kSlowDuration);
-
- bool is_already_receiving_begin_frames = false;
- bool receive_ack_before_deadline = false;
- EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
- receive_ack_before_deadline));
-}
-
-TEST_F(SchedulerTest, ImplFrameSkippedAfterLateAck_ImplLatencyTakesPriority) {
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
- SetUpScheduler(EXTERNAL_BFS);
-
- // Even if every estimate related to the main thread is slow, we should
- // still expect to recover impl thread latency if the draw is fast and we
- // are in impl latency takes priority.
- client_->Reset();
- scheduler_->SetTreePrioritiesAndScrollState(
- SMOOTHNESS_TAKES_PRIORITY,
- ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER);
- fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
- fake_compositor_timing_history_->SetDrawDurationEstimate(kFastDuration);
- EXPECT_ACTIONS("AddObserver(this)");
-
- bool is_already_receiving_begin_frames = true;
- bool receive_ack_before_deadline = false;
- EXPECT_SCOPED(ImplFrameSkippedAfterLateAck(is_already_receiving_begin_frames,
- receive_ack_before_deadline));
-}
-
-TEST_F(SchedulerTest,
- ImplFrameSkippedAfterLateAck_OnlyImplSideUpdatesExpected) {
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
- // This tests that we recover impl thread latency when there are no commits.
- SetUpScheduler(EXTERNAL_BFS);
-
- // To get into a high latency state, this test disables automatic swap acks.
- client_->SetAutomaticSubmitCompositorFrameAck(false);
-
- // Even if every estimate related to the main thread is slow, we should
- // still expect to recover impl thread latency if there are no commits from
- // the main thread.
- fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
- fake_compositor_timing_history_->SetDrawDurationEstimate(kFastDuration);
-
- // Draw and swap for first BeginFrame
- client_->Reset();
- scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame");
-
- client_->Reset();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
-
- // Verify we skip every other frame if the swap ack consistently
- // comes back late.
- for (int i = 0; i < 10; i++) {
- // Not calling scheduler_->DidReceiveCompositorFrameAck() until after next
- // BeginImplFrame puts the impl thread in high latency mode.
- client_->Reset();
- scheduler_->SetNeedsRedraw();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- // Verify that we skip the BeginImplFrame
- 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.
- client_->Reset();
- scheduler_->DidReceiveCompositorFrameAck();
- EXPECT_NO_ACTION();
-
- // Verify that we start the next BeginImplFrame and continue normally
- // after having just skipped a BeginImplFrame.
- client_->Reset();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- EXPECT_ACTIONS("WillBeginImplFrame");
-
- client_->Reset();
- // Deadline should be immediate.
- EXPECT_TRUE(client_->IsInsideBeginImplFrame());
- task_runner_->RunUntilTime(task_runner_->NowTicks());
- EXPECT_FALSE(client_->IsInsideBeginImplFrame());
- EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
- }
-}
-
void SchedulerTest::ImplFrameNotSkippedAfterLateAck() {
// To get into a high latency state, this test disables automatic swap acks.
client_->SetAutomaticSubmitCompositorFrameAck(false);
@@ -2070,123 +1860,6 @@ TEST_F(SchedulerTest, ImplFrameNotSkippedAfterLateAck_DrawEstimateTooLong) {
EXPECT_SCOPED(ImplFrameNotSkippedAfterLateAck());
}
-TEST_F(SchedulerTest, MainFrameThenImplFrameSkippedAfterLateCommitAndLateAck) {
- // Latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
- scheduler_settings_.enable_main_latency_recovery = true;
- // Set up client with custom estimates.
- // This test starts off with expensive estimates to prevent latency recovery
- // initially, then lowers the estimates to enable it once both the main
- // and impl threads are in a high latency mode.
- SetUpScheduler(EXTERNAL_BFS);
- fake_compositor_timing_history_->SetAllEstimatesTo(kSlowDuration);
-
- // To get into a high latency state, this test disables automatic swap acks.
- client_->SetAutomaticSubmitCompositorFrameAck(false);
-
- // Impl thread hits deadline before commit finishes to make
- // MainThreadMissedLastDeadline true
- client_->Reset();
- scheduler_->SetNeedsBeginMainFrame();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- EXPECT_SCOPED(AdvanceFrame());
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
- scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
- scheduler_->NotifyReadyToCommit(nullptr);
- scheduler_->NotifyReadyToActivate();
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-
- EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
- "ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
- "ScheduledActionActivateSyncTree");
-
- // Draw and swap for first commit, start second commit.
- client_->Reset();
- scheduler_->SetNeedsBeginMainFrame();
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
- EXPECT_SCOPED(AdvanceFrame());
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
- scheduler_->NotifyReadyToCommit(nullptr);
- scheduler_->NotifyReadyToActivate();
-
- EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
- "ScheduledActionDrawIfPossible", "ScheduledActionCommit",
- "ScheduledActionActivateSyncTree");
-
- // Don't call scheduler_->DidReceiveCompositorFrameAck() until after next
- // frame
- // to put the impl thread in a high latency mode.
- client_->Reset();
- scheduler_->SetNeedsBeginMainFrame();
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
- EXPECT_SCOPED(AdvanceFrame());
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
-
- EXPECT_ACTIONS("WillBeginImplFrame");
- // Note: BeginMainFrame and swap are skipped here because of
- // swap ack backpressure, not because of latency recovery.
- EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
- EXPECT_FALSE(client_->HasAction("ScheduledActionDrawIfPossible"));
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-
- // Lower estimates so that the scheduler will attempt latency recovery.
- fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
-
- // Now that both threads are in a high latency mode, make sure we
- // skip the BeginMainFrame, then the BeginImplFrame, but not both
- // at the same time.
-
- // Verify we skip BeginMainFrame first.
- client_->Reset();
- // Previous commit request is still outstanding.
- EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
- EXPECT_TRUE(scheduler_->IsDrawThrottled());
- SendNextBeginFrame();
- EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
- scheduler_->DidReceiveCompositorFrameAck();
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
-
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
-
- // Verify we skip the BeginImplFrame second.
- client_->Reset();
- // Previous commit request is still outstanding.
- EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- scheduler_->DidReceiveCompositorFrameAck();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-
- EXPECT_NO_ACTION();
-
- // Then verify we operate in a low latency mode.
- client_->Reset();
- // Previous commit request is still outstanding.
- EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- SendNextBeginFrame();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
- scheduler_->NotifyReadyToCommit(nullptr);
- scheduler_->NotifyReadyToActivate();
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
- scheduler_->DidReceiveCompositorFrameAck();
- EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-
- EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
- "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
- "ScheduledActionDrawIfPossible");
-}
-
void SchedulerTest::BeginFramesNotFromClient(BeginFrameSourceType bfs_type) {
SetUpScheduler(bfs_type);
@@ -3918,55 +3591,6 @@ TEST_F(SchedulerTest, BeginFrameAckForFinishedImplFrame) {
client_->last_frame_skipped_reason());
}
-TEST_F(SchedulerTest, BeginFrameAckForSkippedImplFrame) {
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_impl_latency_recovery = true;
-
- SetUpScheduler(EXTERNAL_BFS);
-
- // To get into a high latency state, this test disables automatic swap acks.
- client_->SetAutomaticSubmitCompositorFrameAck(false);
- fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
-
- // Run a successful redraw that submits a compositor frame but doesn't receive
- // a swap ack. Verify that a viz::BeginFrameAck is sent for it.
- scheduler_->SetNeedsRedraw();
- client_->Reset();
-
- viz::BeginFrameArgs args = SendNextBeginFrame();
- EXPECT_ACTIONS("WillBeginImplFrame");
- EXPECT_TRUE(client_->IsInsideBeginImplFrame());
- EXPECT_TRUE(scheduler_->begin_frames_expected());
- client_->Reset();
-
- task_runner_->RunPendingTasks(); // Run posted deadline.
- EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
- EXPECT_FALSE(client_->IsInsideBeginImplFrame());
- EXPECT_TRUE(scheduler_->begin_frames_expected());
-
- // Successful draw caused damage.
- bool has_damage = true;
- EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
- client_->last_begin_frame_ack());
- client_->Reset();
-
- // Request another redraw that will be skipped because the swap ack is still
- // missing. Verify that a new viz::BeginFrameAck is sent.
- scheduler_->SetNeedsRedraw();
- client_->Reset();
-
- args = SendNextBeginFrame();
- EXPECT_NO_ACTION();
- EXPECT_FALSE(client_->IsInsideBeginImplFrame());
- EXPECT_TRUE(scheduler_->begin_frames_expected());
-
- // Skipped draw: no damage.
- has_damage = false;
- EXPECT_EQ(viz::BeginFrameAck(args, has_damage),
- client_->last_begin_frame_ack());
- client_->Reset();
-}
-
TEST_F(SchedulerTest, BeginFrameAckForBeginFrameBeforeLastDeadline) {
SetUpScheduler(EXTERNAL_BFS);
@@ -4326,37 +3950,6 @@ TEST_F(SchedulerTest, SynchronousCompositorImplSideInvalidation) {
EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
}
-TEST_F(SchedulerTest, DontSkipMainFrameAfterClearingHistory) {
- // Set up a fast estimate for the main frame and make it miss the deadline.
- scheduler_settings_.main_frame_before_activation_enabled = true;
- // Compositor thread latency recovery should be enabled for this test.
- scheduler_settings_.enable_main_latency_recovery = true;
- SetUpScheduler(EXTERNAL_BFS);
- fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
- client_->Reset();
- scheduler_->SetNeedsBeginMainFrame();
- EXPECT_SCOPED(AdvanceFrame());
- task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
- EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
- "ScheduledActionSendBeginMainFrame");
-
- // Now commit during the second frame, since the main thread missed the last
- // deadline but we have a fast estimate, we would want to skip the next main
- // frame.
- client_->Reset();
- EXPECT_SCOPED(AdvanceFrame());
- scheduler_->SetNeedsBeginMainFrame();
- scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
- scheduler_->NotifyReadyToCommit(nullptr);
- EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionCommit");
-
- // But during the commit, the history is cleared. So the main frame should not
- // be skipped.
- client_->Reset();
- scheduler_->ClearHistory();
- EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
-}
-
TEST_F(SchedulerTest, NoInvalidationForAnimateOnlyFrames) {
SetUpScheduler(EXTERNAL_BFS);
fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
@@ -4403,8 +3996,6 @@ TEST_F(SchedulerTest, SendEarlyDidNotProduceFrameIfIdle) {
TEST_F(SchedulerTest,
HighImplLatencyModePrioritizesMainFramesOverImplInvalidation) {
- scheduler_settings_.enable_main_latency_recovery = false;
- scheduler_settings_.enable_impl_latency_recovery = false;
SetUpScheduler(EXTERNAL_BFS);
fake_compositor_timing_history_->SetAllEstimatesTo(kFastDuration);
@@ -4469,6 +4060,7 @@ class SchedulerTestForPowerMode : public SchedulerTest {
~SchedulerTestForPowerMode() override {
DCHECK_EQ(this, current_test_);
current_test_ = nullptr;
+ power_mode_arbiter_.RemoveObserver(&observer_);
}
void AdvanceToArbiterSnapAfter(base::TimeDelta delay) {
diff --git a/chromium/cc/tiles/checker_image_tracker.cc b/chromium/cc/tiles/checker_image_tracker.cc
index 432201499c3..53d9df8a904 100644
--- a/chromium/cc/tiles/checker_image_tracker.cc
+++ b/chromium/cc/tiles/checker_image_tracker.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
namespace cc {
diff --git a/chromium/cc/tiles/checker_image_tracker.h b/chromium/cc/tiles/checker_image_tracker.h
index 5e336665055..76cdea7cac6 100644
--- a/chromium/cc/tiles/checker_image_tracker.h
+++ b/chromium/cc/tiles/checker_image_tracker.h
@@ -138,7 +138,7 @@ class CC_EXPORT CheckerImageTracker {
struct DecodeState {
DecodePolicy policy = DecodePolicy::SYNC;
bool use_dark_mode = false;
- SkFilterQuality filter_quality = kNone_SkFilterQuality;
+ PaintFlags::FilterQuality filter_quality = PaintFlags::FilterQuality::kNone;
SkSize scale = SkSize::MakeEmpty();
gfx::ColorSpace color_space;
size_t frame_index = PaintImage::kDefaultFrameIndex;
diff --git a/chromium/cc/tiles/checker_image_tracker_unittest.cc b/chromium/cc/tiles/checker_image_tracker_unittest.cc
index 4c8886087b8..feb731583e9 100644
--- a/chromium/cc/tiles/checker_image_tracker_unittest.cc
+++ b/chromium/cc/tiles/checker_image_tracker_unittest.cc
@@ -124,7 +124,7 @@ class CheckerImageTrackerTest : public testing::Test,
.set_decoding_mode(PaintImage::DecodingMode::kAsync)
.TakePaintImage(),
false, SkIRect::MakeWH(dimension, dimension),
- kNone_SkFilterQuality, SkM44(),
+ PaintFlags::FilterQuality::kNone, SkM44(),
PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
}
@@ -438,7 +438,7 @@ TEST_F(CheckerImageTrackerTest, CheckersOnlyStaticCompletedImages) {
.set_paint_image_generator(CreatePaintImageGenerator(image_size))
.TakePaintImage(),
false, SkIRect::MakeWH(image_size.width(), image_size.height()),
- kNone_SkFilterQuality, SkM44(), PaintImage::kDefaultFrameIndex,
+ PaintFlags::FilterQuality::kNone, SkM44(), PaintImage::kDefaultFrameIndex,
gfx::ColorSpace());
EXPECT_FALSE(
ShouldCheckerImage(completed_paint_image, WhichTree::PENDING_TREE));
@@ -470,7 +470,7 @@ TEST_F(CheckerImageTrackerTest, ChoosesMaxScaleAndQuality) {
gfx::ColorSpace());
DrawImage scaled_image2 =
DrawImage(image.paint_image(), false, image.src_rect(),
- kHigh_SkFilterQuality, SkM44::Scale(1.8f, 1.8f),
+ PaintFlags::FilterQuality::kHigh, SkM44::Scale(1.8f, 1.8f),
PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
std::vector<DrawImage> draw_images = {scaled_image1, scaled_image2};
@@ -481,7 +481,7 @@ TEST_F(CheckerImageTrackerTest, ChoosesMaxScaleAndQuality) {
EXPECT_EQ(image_controller_.decoded_images()[0].scale(),
SkSize::Make(1.8f, 1.8f));
EXPECT_EQ(image_controller_.decoded_images()[0].filter_quality(),
- kHigh_SkFilterQuality);
+ PaintFlags::FilterQuality::kHigh);
}
TEST_F(CheckerImageTrackerTest, DontCheckerMultiPartImages) {
diff --git a/chromium/cc/tiles/decoded_image_tracker.cc b/chromium/cc/tiles/decoded_image_tracker.cc
index 763f55239a3..41ec58bc47b 100644
--- a/chromium/cc/tiles/decoded_image_tracker.cc
+++ b/chromium/cc/tiles/decoded_image_tracker.cc
@@ -48,8 +48,9 @@ void DecodedImageTracker::QueueImageDecode(
// Queue the decode in the image controller, but switch out the callback for
// our own.
auto image_bounds = SkIRect::MakeWH(image.width(), image.height());
- DrawImage draw_image(image, false, image_bounds, kNone_SkFilterQuality,
- SkM44(), frame_index, target_color_space);
+ DrawImage draw_image(image, false, image_bounds,
+ PaintFlags::FilterQuality::kNone, SkM44(), frame_index,
+ target_color_space);
image_controller_->QueueImageDecode(
draw_image, base::BindOnce(&DecodedImageTracker::ImageDecodeFinished,
base::Unretained(this), std::move(callback),
diff --git a/chromium/cc/tiles/decoded_image_tracker_unittest.cc b/chromium/cc/tiles/decoded_image_tracker_unittest.cc
index 09f8c58b206..991394ca3b1 100644
--- a/chromium/cc/tiles/decoded_image_tracker_unittest.cc
+++ b/chromium/cc/tiles/decoded_image_tracker_unittest.cc
@@ -109,12 +109,13 @@ TEST_F(DecodedImageTrackerTest, Colorspace) {
// space differs then that image is not locked. Note that we use the high
// filter quality here, since it shouldn't matter and the checks should
// succeed anyway.
- DrawImage locked_draw_image(
- paint_image, false, SkIRect::MakeWH(1, 1), kHigh_SkFilterQuality, SkM44(),
- PaintImage::kDefaultFrameIndex, decoded_color_space);
+ DrawImage locked_draw_image(paint_image, false, SkIRect::MakeWH(1, 1),
+ PaintFlags::FilterQuality::kHigh, SkM44(),
+ PaintImage::kDefaultFrameIndex,
+ decoded_color_space);
EXPECT_TRUE(image_controller()->IsDrawImageLocked(locked_draw_image));
DrawImage srgb_draw_image(paint_image, false, SkIRect::MakeWH(1, 1),
- kHigh_SkFilterQuality, SkM44(),
+ PaintFlags::FilterQuality::kHigh, SkM44(),
PaintImage::kDefaultFrameIndex, srgb_color_space);
EXPECT_FALSE(image_controller()->IsDrawImageLocked(srgb_draw_image));
}
@@ -172,9 +173,11 @@ TEST_F(DecodedImageTrackerTest, ImageUsedInDraw) {
// Create dummy draw images for each:
DrawImage draw_image_1(paint_image_1, false, SkIRect::MakeWH(1, 1),
- kHigh_SkFilterQuality, SkM44(), 0, gfx::ColorSpace());
+ PaintFlags::FilterQuality::kHigh, SkM44(), 0,
+ gfx::ColorSpace());
DrawImage draw_image_2(paint_image_2, false, SkIRect::MakeWH(1, 1),
- kHigh_SkFilterQuality, SkM44(), 0, gfx::ColorSpace());
+ PaintFlags::FilterQuality::kHigh, SkM44(), 0,
+ gfx::ColorSpace());
// Both should be in the cache:
EXPECT_TRUE(image_controller()->IsDrawImageLocked(draw_image_1));
diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc
index e61eefa6f15..08259760367 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache.cc
+++ b/chromium/cc/tiles/gpu_image_decode_cache.cc
@@ -102,8 +102,10 @@ bool SkipImage(const DrawImage& draw_image) {
// Returns the filter quality to use for scaling the image to upload scale as
// well as for using when passing the decoded image to skia. Due to parity with
// SW and power impliciation, limit the filter quality to medium.
-SkFilterQuality CalculateDesiredFilterQuality(const DrawImage& draw_image) {
- return std::min(kMedium_SkFilterQuality, draw_image.filter_quality());
+PaintFlags::FilterQuality CalculateDesiredFilterQuality(
+ const DrawImage& draw_image) {
+ return std::min(PaintFlags::FilterQuality::kMedium,
+ draw_image.filter_quality());
}
// Calculates the scale factor which can be used to scale an image to a given
@@ -128,7 +130,7 @@ gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image,
bool ShouldGenerateMips(const DrawImage& draw_image,
int upload_scale_mip_level) {
// If filter quality is less than medium, don't generate mips.
- if (draw_image.filter_quality() < kMedium_SkFilterQuality)
+ if (draw_image.filter_quality() < PaintFlags::FilterQuality::kMedium)
return false;
gfx::Size base_size(draw_image.paint_image().width(),
@@ -235,7 +237,7 @@ bool DrawAndScaleImage(
SkISize::Make(paint_image.width(), paint_image.height()) ==
pixmap.bounds().size();
const bool is_nearest_neighbor =
- draw_image.filter_quality() == kNone_SkFilterQuality;
+ draw_image.filter_quality() == PaintFlags::FilterQuality::kNone;
SkImageInfo info = pixmap.info();
SkYUVAPixmapInfo yuva_pixmap_info;
if (do_yuv_decode) {
@@ -303,7 +305,7 @@ bool DrawAndScaleImage(
decode_info = info.makeWH(decode_size.width(), decode_size.height());
}
- const SkFilterQuality filter_quality =
+ const PaintFlags::FilterQuality filter_quality =
CalculateDesiredFilterQuality(draw_image);
const SkSamplingOptions sampling(
PaintFlags::FilterQualityToSkSamplingOptions(filter_quality));
@@ -477,9 +479,10 @@ size_t GpuImageDecodeCache::InUseCacheKeyHash::operator()(
const InUseCacheKey& cache_key) const {
return base::HashInts(
cache_key.target_color_space.GetHash(),
- base::HashInts(cache_key.frame_key.hash(),
- base::HashInts(cache_key.upload_scale_mip_level,
- cache_key.filter_quality)));
+ base::HashInts(
+ cache_key.frame_key.hash(),
+ base::HashInts(cache_key.upload_scale_mip_level,
+ static_cast<int>(cache_key.filter_quality))));
}
GpuImageDecodeCache::InUseCacheEntry::InUseCacheEntry(
@@ -838,7 +841,7 @@ GpuImageDecodeCache::ImageData::ImageData(
DecodedDataMode mode,
size_t size,
const gfx::ColorSpace& target_color_space,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
int upload_scale_mip_level,
bool needs_mips,
bool is_bitmap_backed,
@@ -2236,8 +2239,8 @@ void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image,
return;
}
- size_t image_width = uploaded_y_image->width();
- size_t image_height = uploaded_y_image->height();
+ int image_width = uploaded_y_image->width();
+ int image_height = uploaded_y_image->height();
uploaded_image = CreateImageFromYUVATexturesInternal(
uploaded_y_image.get(), uploaded_u_image.get(),
uploaded_v_image.get(), image_width, image_height,
@@ -2950,8 +2953,8 @@ sk_sp<SkImage> GpuImageDecodeCache::CreateImageFromYUVATexturesInternal(
const SkImage* uploaded_y_image,
const SkImage* uploaded_u_image,
const SkImage* uploaded_v_image,
- const size_t image_width,
- const size_t image_height,
+ const int image_width,
+ const int image_height,
const SkYUVAInfo::PlaneConfig yuva_plane_config,
const SkYUVAInfo::Subsampling yuva_subsampling,
const SkYUVColorSpace yuv_color_space,
@@ -3053,8 +3056,8 @@ void GpuImageDecodeCache::UpdateMipsIfNeeded(const DrawImage& draw_image,
return;
}
- size_t width = image_y_with_mips_owned->width();
- size_t height = image_y_with_mips_owned->height();
+ int width = image_y_with_mips_owned->width();
+ int height = image_y_with_mips_owned->height();
sk_sp<SkColorSpace> color_space =
SupportsColorSpaceConversion() &&
draw_image.target_color_space().IsValid()
diff --git a/chromium/cc/tiles/gpu_image_decode_cache.h b/chromium/cc/tiles/gpu_image_decode_cache.h
index 5c48f6f0047..edea739d938 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache.h
+++ b/chromium/cc/tiles/gpu_image_decode_cache.h
@@ -514,7 +514,7 @@ class CC_EXPORT GpuImageDecodeCache
DecodedDataMode mode,
size_t size,
const gfx::ColorSpace& target_color_space,
- SkFilterQuality quality,
+ PaintFlags::FilterQuality quality,
int upload_scale_mip_level,
bool needs_mips,
bool is_bitmap_backed,
@@ -530,7 +530,7 @@ class CC_EXPORT GpuImageDecodeCache
const DecodedDataMode mode;
const size_t size;
gfx::ColorSpace target_color_space;
- SkFilterQuality quality;
+ PaintFlags::FilterQuality quality;
int upload_scale_mip_level;
bool needs_mips = false;
bool is_bitmap_backed;
@@ -574,7 +574,7 @@ class CC_EXPORT GpuImageDecodeCache
PaintImage::FrameKey frame_key;
int upload_scale_mip_level;
- SkFilterQuality filter_quality;
+ PaintFlags::FilterQuality filter_quality;
gfx::ColorSpace target_color_space;
};
struct InUseCacheKeyHash {
@@ -641,8 +641,8 @@ class CC_EXPORT GpuImageDecodeCache
const SkImage* uploaded_y_image,
const SkImage* uploaded_u_image,
const SkImage* uploaded_v_image,
- const size_t image_width,
- const size_t image_height,
+ const int image_width,
+ const int image_height,
const SkYUVAInfo::PlaneConfig yuva_plane_config,
const SkYUVAInfo::Subsampling yuva_subsampling,
const SkYUVColorSpace yuva_color_space,
diff --git a/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc b/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc
index 37d76df12b9..6b43048a119 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc
+++ b/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc
@@ -113,7 +113,7 @@ TEST_P(GpuImageDecodeCachePerfTest, DecodeWithColorConversion) {
.set_id(PaintImage::GetNextId())
.set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
.TakePaintImage(),
- false, SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
+ false, SkIRect::MakeWH(1024, 2048), PaintFlags::FilterQuality::kMedium,
CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u,
gfx::ColorSpace::CreateXYZD50());
@@ -146,7 +146,7 @@ TEST_P(GpuImageDecodeCachePerfTestNoSw, DecodeWithMips) {
.set_id(PaintImage::GetNextId())
.set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
.TakePaintImage(),
- false, SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
+ false, SkIRect::MakeWH(1024, 2048), PaintFlags::FilterQuality::kMedium,
CreateMatrix(SkSize::Make(0.6f, 0.6f)), 0u, gfx::ColorSpace());
DecodedDrawImage decoded_image = cache_->GetDecodedImageForDraw(image);
@@ -175,7 +175,7 @@ TEST_P(GpuImageDecodeCachePerfTest, AcquireExistingImages) {
.set_id(PaintImage::GetNextId())
.set_image(CreateImage(1024, 2048), PaintImage::GetNextContentId())
.TakePaintImage(),
- false, SkIRect::MakeWH(1024, 2048), kMedium_SkFilterQuality,
+ false, SkIRect::MakeWH(1024, 2048), PaintFlags::FilterQuality::kMedium,
CreateMatrix(SkSize::Make(1.0f, 1.0f)), 0u,
gfx::ColorSpace::CreateXYZD50());
diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc
index 076be3aafa6..6c585a065a5 100644
--- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -493,7 +493,8 @@ class GpuImageDecodeCacheTest
const PaintImage& paint_image,
const SkM44& matrix = SkM44(),
gfx::ColorSpace* color_space = nullptr,
- SkFilterQuality filter_quality = kMedium_SkFilterQuality,
+ PaintFlags::FilterQuality filter_quality =
+ PaintFlags::FilterQuality::kMedium,
SkIRect* src_rect = nullptr,
size_t frame_index = PaintImage::kDefaultFrameIndex,
float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel,
@@ -517,7 +518,8 @@ class GpuImageDecodeCacheTest
const PaintImage& paint_image,
const SkM44& matrix = SkM44(),
gfx::ColorSpace* color_space = nullptr,
- SkFilterQuality filter_quality = kMedium_SkFilterQuality,
+ PaintFlags::FilterQuality filter_quality =
+ PaintFlags::FilterQuality::kMedium,
SkIRect* src_rect = nullptr,
size_t frame_index = PaintImage::kDefaultFrameIndex,
float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel) {
@@ -753,8 +755,9 @@ TEST_P(GpuImageDecodeCacheTest, GetTaskForImageLowerQuality) {
EXPECT_TRUE(result.need_unref);
EXPECT_TRUE(result.task);
- DrawImage another_draw_image = CreateDrawImageInternal(
- image, matrix, nullptr /* color_space */, kLow_SkFilterQuality);
+ DrawImage another_draw_image =
+ CreateDrawImageInternal(image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kLow);
ImageDecodeCache::TaskResult another_result = cache->GetTaskForImageAndRef(
another_draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(another_result.need_unref);
@@ -871,8 +874,9 @@ TEST_P(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) {
auto cache = CreateCache();
SkM44 matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f));
PaintImage first_image = CreatePaintImageInternal(GetNormalImageSize());
- DrawImage first_draw_image = CreateDrawImageInternal(
- first_image, matrix, nullptr /* color_space */, kLow_SkFilterQuality);
+ DrawImage first_draw_image =
+ CreateDrawImageInternal(first_image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kLow);
ImageDecodeCache::TaskResult first_result = cache->GetTaskForImageAndRef(
first_draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(first_result.need_unref);
@@ -883,8 +887,9 @@ TEST_P(GpuImageDecodeCacheTest, GetTaskForImageHigherQuality) {
cache->UnrefImage(first_draw_image);
- DrawImage second_draw_image = CreateDrawImageInternal(
- first_image, matrix, nullptr /* color_space */, kMedium_SkFilterQuality);
+ DrawImage second_draw_image =
+ CreateDrawImageInternal(first_image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kMedium);
ImageDecodeCache::TaskResult second_result = cache->GetTaskForImageAndRef(
second_draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(second_result.need_unref);
@@ -1173,8 +1178,8 @@ TEST_P(GpuImageDecodeCacheTest, GetHdrDecodedImageForDrawToHdr) {
constexpr float kCustomWhiteLevel = 200.f;
DrawImage draw_image = CreateDrawImageInternal(
image, CreateMatrix(SkSize::Make(0.5f, 0.5f)), &color_space,
- kMedium_SkFilterQuality, nullptr, PaintImage::kDefaultFrameIndex,
- kCustomWhiteLevel);
+ PaintFlags::FilterQuality::kMedium, nullptr,
+ PaintImage::kDefaultFrameIndex, kCustomWhiteLevel);
ImageDecodeCache::TaskResult result =
cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
EXPECT_EQ(draw_image.target_color_space(), color_space);
@@ -1316,9 +1321,9 @@ TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawLargerScale) {
auto cache = CreateCache();
PaintImage image = CreatePaintImageInternal(GetNormalImageSize());
- DrawImage draw_image =
- CreateDrawImageInternal(image, CreateMatrix(SkSize::Make(0.5f, 0.5f)),
- nullptr /* color_space */, kLow_SkFilterQuality);
+ DrawImage draw_image = CreateDrawImageInternal(
+ image, CreateMatrix(SkSize::Make(0.5f, 0.5f)), nullptr /* color_space */,
+ PaintFlags::FilterQuality::kLow);
ImageDecodeCache::TaskResult result =
cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(result.need_unref);
@@ -1366,8 +1371,9 @@ TEST_P(GpuImageDecodeCacheTest, GetDecodedImageForDrawHigherQuality) {
auto cache = CreateCache();
SkM44 matrix = CreateMatrix(SkSize::Make(0.5f, 0.5f));
PaintImage image = CreatePaintImageInternal(GetNormalImageSize());
- DrawImage draw_image = CreateDrawImageInternal(
- image, matrix, nullptr /* color_space */, kLow_SkFilterQuality);
+ DrawImage draw_image =
+ CreateDrawImageInternal(image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kLow);
ImageDecodeCache::TaskResult result =
cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(result.need_unref);
@@ -1446,9 +1452,9 @@ TEST_P(GpuImageDecodeCacheTest, GetLargeScaledDecodedImageForDraw) {
auto cache = CreateCache();
PaintImage image = CreatePaintImageForFallbackToRGB(
gfx::Size(GetLargeImageSize().width(), GetLargeImageSize().height() * 2));
- DrawImage draw_image =
- CreateDrawImageInternal(image, CreateMatrix(SkSize::Make(0.5f, 0.5f)),
- nullptr /* color_space */, kHigh_SkFilterQuality);
+ DrawImage draw_image = CreateDrawImageInternal(
+ image, CreateMatrix(SkSize::Make(0.5f, 0.5f)), nullptr /* color_space */,
+ PaintFlags::FilterQuality::kHigh);
ImageDecodeCache::TaskResult result =
cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(result.need_unref);
@@ -1468,7 +1474,8 @@ TEST_P(GpuImageDecodeCacheTest, GetLargeScaledDecodedImageForDraw) {
EXPECT_EQ(GetLargeImageSize().width(), decoded_draw_image.image()->width());
EXPECT_EQ(GetLargeImageSize().height(), decoded_draw_image.image()->height());
- EXPECT_EQ(decoded_draw_image.filter_quality(), kMedium_SkFilterQuality);
+ EXPECT_EQ(decoded_draw_image.filter_quality(),
+ PaintFlags::FilterQuality::kMedium);
EXPECT_FALSE(decoded_draw_image.image()->isTextureBacked());
EXPECT_TRUE_IF_NOT_USING_TRANSFER_CACHE(
@@ -1610,7 +1617,7 @@ TEST_P(GpuImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
DrawImage draw_image(image, false,
SkIRect::MakeXYWH(image.width() + 1, image.height() + 1,
image.width(), image.height()),
- kMedium_SkFilterQuality,
+ PaintFlags::FilterQuality::kMedium,
CreateMatrix(SkSize::Make(1.f, 1.f)),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -1635,7 +1642,7 @@ TEST_P(GpuImageDecodeCacheTest, CanceledTasksDoNotCountAgainstBudget) {
SkIRect src_rect = SkIRect::MakeXYWH(0, 0, image.width(), image.height());
DrawImage draw_image = CreateDrawImageInternal(
image, CreateMatrix(SkSize::Make(1.f, 1.f)), nullptr /* color_space */,
- kMedium_SkFilterQuality, &src_rect);
+ PaintFlags::FilterQuality::kMedium, &src_rect);
ImageDecodeCache::TaskResult result =
cache->GetTaskForImageAndRef(draw_image, ImageDecodeCache::TracingInfo());
@@ -1793,15 +1800,16 @@ TEST_P(GpuImageDecodeCacheTest, QualityCappedAtMedium) {
SkM44 matrix = CreateMatrix(SkSize::Make(0.4f, 0.4f));
// Create an image with kLow_FilterQuality.
- DrawImage low_draw_image = CreateDrawImageInternal(
- image, matrix, nullptr /* color_space */, kLow_SkFilterQuality);
+ DrawImage low_draw_image =
+ CreateDrawImageInternal(image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kLow);
ImageDecodeCache::TaskResult low_result = cache->GetTaskForImageAndRef(
low_draw_image, ImageDecodeCache::TracingInfo());
EXPECT_TRUE(low_result.need_unref);
EXPECT_TRUE(low_result.task);
- // Get the same image at kMedium_SkFilterQuality. We can't re-use low, so we
- // should get a new task/ref.
+ // Get the same image at PaintFlags::FilterQuality::kMedium. We can't re-use
+ // low, so we should get a new task/ref.
DrawImage medium_draw_image = CreateDrawImageInternal(image);
ImageDecodeCache::TaskResult medium_result = cache->GetTaskForImageAndRef(
medium_draw_image, ImageDecodeCache::TracingInfo());
@@ -1809,9 +1817,11 @@ TEST_P(GpuImageDecodeCacheTest, QualityCappedAtMedium) {
EXPECT_TRUE(medium_result.task.get());
EXPECT_FALSE(low_result.task.get() == medium_result.task.get());
- // Get the same image at kHigh_SkFilterQuality. We should re-use medium.
- DrawImage high_quality_draw_image = CreateDrawImageInternal(
- image, matrix, nullptr /* color_space */, kHigh_SkFilterQuality);
+ // Get the same image at PaintFlags::FilterQuality::kHigh. We should re-use
+ // medium.
+ DrawImage high_quality_draw_image =
+ CreateDrawImageInternal(image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kHigh);
ImageDecodeCache::TaskResult high_quality_result =
cache->GetTaskForImageAndRef(high_quality_draw_image,
ImageDecodeCache::TracingInfo());
@@ -1864,8 +1874,9 @@ TEST_P(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) {
auto cache = CreateCache();
PaintImage image = CreatePaintImageInternal(GetNormalImageSize());
SkM44 matrix = CreateMatrix(SkSize::Make(1.0f, 1.0f));
- DrawImage draw_image = CreateDrawImageInternal(
- image, matrix, nullptr /* color_space */, kLow_SkFilterQuality);
+ DrawImage draw_image =
+ CreateDrawImageInternal(image, matrix, nullptr /* color_space */,
+ PaintFlags::FilterQuality::kLow);
ImageDecodeCache::TaskResult result =
cache->GetOutOfRasterDecodeTaskForImageAndRef(draw_image);
@@ -1935,10 +1946,11 @@ TEST_P(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) {
DrawImage draw_image = CreateDrawImageInternal(image);
PaintImage image2 = CreatePaintImageInternal(GetNormalImageSize());
- DrawImage draw_image2(
- image2, false, SkIRect::MakeWH(image2.width(), image2.height()),
- kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(1.0f, 1.0f)),
- PaintImage::kDefaultFrameIndex, DefaultColorSpace());
+ DrawImage draw_image2(image2, false,
+ SkIRect::MakeWH(image2.width(), image2.height()),
+ PaintFlags::FilterQuality::kMedium,
+ CreateMatrix(SkSize::Make(1.0f, 1.0f)),
+ PaintImage::kDefaultFrameIndex, DefaultColorSpace());
// Add an image to the cache and un-ref it.
{
@@ -2141,7 +2153,7 @@ TEST_P(GpuImageDecodeCacheTest, CacheDecodesExpectedFrames) {
viz::ContextProvider::ScopedContextLock context_lock(context_provider());
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
image, false, SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(1.0f, 1.0f)), 1u, DefaultColorSpace());
@@ -2657,9 +2669,9 @@ TEST_P(GpuImageDecodeCacheTest, DecodeToScaleNoneQuality) {
.set_paint_image_generator(generator)
.TakePaintImage();
- DrawImage draw_image =
- CreateDrawImageInternal(paint_image, CreateMatrix(SkSize::Make(0.5, 0.5)),
- nullptr /* color_space */, kNone_SkFilterQuality);
+ DrawImage draw_image = CreateDrawImageInternal(
+ paint_image, CreateMatrix(SkSize::Make(0.5, 0.5)),
+ nullptr /* color_space */, PaintFlags::FilterQuality::kNone);
DecodedDrawImage decoded_image =
EnsureImageBacked(cache->GetDecodedImageForDraw(draw_image));
ASSERT_TRUE(decoded_image.image());
@@ -2678,7 +2690,7 @@ TEST_P(GpuImageDecodeCacheTest, DecodeToScaleNoneQuality) {
}
TEST_P(GpuImageDecodeCacheTest, BasicMips) {
- auto decode_and_check_mips = [this](SkFilterQuality filter_quality,
+ auto decode_and_check_mips = [this](PaintFlags::FilterQuality filter_quality,
SkSize scale, gfx::ColorSpace color_space,
bool should_have_mips) {
auto cache = CreateCache();
@@ -2726,22 +2738,23 @@ TEST_P(GpuImageDecodeCacheTest, BasicMips) {
};
// No scale == no mips.
- decode_and_check_mips(kMedium_SkFilterQuality, SkSize::Make(1.0f, 1.0f),
- DefaultColorSpace(), false);
+ decode_and_check_mips(PaintFlags::FilterQuality::kMedium,
+ SkSize::Make(1.0f, 1.0f), DefaultColorSpace(), false);
// Full mip level scale == no mips
- decode_and_check_mips(kMedium_SkFilterQuality, SkSize::Make(0.5f, 0.5f),
- DefaultColorSpace(), false);
+ decode_and_check_mips(PaintFlags::FilterQuality::kMedium,
+ SkSize::Make(0.5f, 0.5f), DefaultColorSpace(), false);
// Low filter quality == no mips
- decode_and_check_mips(kLow_SkFilterQuality, SkSize::Make(0.6f, 0.6f),
- DefaultColorSpace(), false);
+ decode_and_check_mips(PaintFlags::FilterQuality::kLow,
+ SkSize::Make(0.6f, 0.6f), DefaultColorSpace(), false);
// None filter quality == no mips
- decode_and_check_mips(kNone_SkFilterQuality, SkSize::Make(0.6f, 0.6f),
- DefaultColorSpace(), false);
+ decode_and_check_mips(PaintFlags::FilterQuality::kNone,
+ SkSize::Make(0.6f, 0.6f), DefaultColorSpace(), false);
// Medium filter quality == mips
- decode_and_check_mips(kMedium_SkFilterQuality, SkSize::Make(0.6f, 0.6f),
- DefaultColorSpace(), true);
+ decode_and_check_mips(PaintFlags::FilterQuality::kMedium,
+ SkSize::Make(0.6f, 0.6f), DefaultColorSpace(), true);
// Color conversion preserves mips
- decode_and_check_mips(kMedium_SkFilterQuality, SkSize::Make(0.6f, 0.6f),
+ decode_and_check_mips(PaintFlags::FilterQuality::kMedium,
+ SkSize::Make(0.6f, 0.6f),
gfx::ColorSpace::CreateXYZD50(), true);
}
@@ -2972,8 +2985,8 @@ TEST_P(GpuImageDecodeCacheTest,
// This test creates an image that will be YUV decoded and drawn at 80% scale.
// Because the final size is between mip levels, we expect the image to be
// decoded and uploaded at original size (mip level 0 for all planes) but to
- // have mips attached since kMedium_SkFilterQuality uses bilinear filtering
- // between mip levels.
+ // have mips attached since PaintFlags::FilterQuality::kMedium uses bilinear
+ // filtering between mip levels.
if (!do_yuv_decode_) {
// The YUV case may choose different mip levels between chroma and luma
// planes.
@@ -2981,7 +2994,8 @@ TEST_P(GpuImageDecodeCacheTest,
}
auto owned_cache = CreateCache();
auto decode_and_check_plane_sizes = [this, cache = owned_cache.get()]() {
- SkFilterQuality filter_quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality filter_quality =
+ PaintFlags::FilterQuality::kMedium;
SkSize requires_decode_at_original_scale = SkSize::Make(0.8f, 0.8f);
PaintImage image = CreatePaintImageInternal(GetNormalImageSize());
@@ -3041,8 +3055,8 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) {
// This test creates a high bit depth image that will be YUV decoded and drawn
// at 80% scale. Because the final size is between mip levels, we expect the
// image to be decoded and uploaded at original size (mip level 0 for all
- // planes) but to have mips attached since kMedium_SkFilterQuality uses
- // bilinear filtering between mip levels.
+ // planes) but to have mips attached since PaintFlags::FilterQuality::kMedium
+ // uses bilinear filtering between mip levels.
if (!do_yuv_decode_) {
// The YUV case may choose different mip levels between chroma and luma
// planes.
@@ -3057,7 +3071,8 @@ TEST_P(GpuImageDecodeCacheTest, HighBitDepthYUVDecoding) {
DataType::kUnorm8,
gfx::ColorSpace target_cs =
gfx::ColorSpace::CreateSRGB()) {
- SkFilterQuality filter_quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality filter_quality =
+ PaintFlags::FilterQuality::kMedium;
SkSize requires_decode_at_original_scale = SkSize::Make(0.8f, 0.8f);
// When we're targeting HDR output, select a reasonable HDR color space for
@@ -3271,7 +3286,8 @@ TEST_P(GpuImageDecodeCacheTest, ScaledYUVDecodeScaledDrawCorrectlyMipsPlanes) {
// Because the final size is between mip levels, we expect the image to be
// decoded and uploaded at half its original size (mip level 1 for Y plane but
// level 0 for chroma planes) and to have mips attached since
- // kMedium_SkFilterQuality uses bilinear filtering between mip levels.
+ // PaintFlags::FilterQuality::kMedium uses bilinear filtering between mip
+ // levels.
if (!do_yuv_decode_) {
// The YUV case may choose different mip levels between chroma and luma
// planes.
@@ -3282,7 +3298,8 @@ TEST_P(GpuImageDecodeCacheTest, ScaledYUVDecodeScaledDrawCorrectlyMipsPlanes) {
[this, cache = owned_cache.get()](
SkSize scaled_size,
const SkISize mipped_plane_sizes[SkYUVAInfo::kMaxPlanes]) {
- SkFilterQuality filter_quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality filter_quality =
+ PaintFlags::FilterQuality::kMedium;
gfx::Size image_size = GetNormalImageSize();
PaintImage image = CreatePaintImageInternal(image_size);
@@ -3478,7 +3495,7 @@ TEST_P(GpuImageDecodeCacheTest, DarkModeImageCacheSize) {
// Another draw image with smaller src rect for image1.
SkIRect src = SkIRect::MakeWH(10, 10);
DrawImage draw_image12 = CreateDrawImageWithDarkModeInternal(
- image1, SkM44(), nullptr, kMedium_SkFilterQuality, &src);
+ image1, SkM44(), nullptr, PaintFlags::FilterQuality::kMedium, &src);
ImageDecodeCache::TaskResult result12 = cache->GetTaskForImageAndRef(
draw_image12, ImageDecodeCache::TracingInfo());
GetImageAndDrawFinishedForDarkMode(cache.get(), draw_image12,
@@ -3573,9 +3590,9 @@ TEST_P(GpuImageDecodeCacheTest, ClippedAndScaledDrawImageRemovesCacheEntry) {
// Get task for clipped and scaled image.
auto clipped_rect = SkIRect::MakeWH(image.width() * 0.9f, image.height());
- DrawImage clipped_draw_image =
- CreateDrawImageInternal(image, CreateMatrix(SkSize::Make(0.5f, 0.5f)),
- nullptr, kMedium_SkFilterQuality, &clipped_rect);
+ DrawImage clipped_draw_image = CreateDrawImageInternal(
+ image, CreateMatrix(SkSize::Make(0.5f, 0.5f)), nullptr,
+ PaintFlags::FilterQuality::kMedium, &clipped_rect);
ImageDecodeCache::TaskResult clipped_result = cache->GetTaskForImageAndRef(
clipped_draw_image, ImageDecodeCache::TracingInfo());
@@ -3668,7 +3685,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration(
ImageType::kJPEG, subsampling_and_expected_data_size.first);
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()),
quality, CreateMatrix(SkSize::Make(0.75f, 0.75f)),
@@ -3708,7 +3725,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateXYZD50();
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(0.75f, 0.75f)),
@@ -3747,7 +3764,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateXYZD50();
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(0.75f, 0.75f)),
@@ -3795,7 +3812,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(1.0f, 1.0f)),
@@ -3818,7 +3835,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(0.5f, 0.5f)),
@@ -3843,7 +3860,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(0.75f, 0.75f)),
@@ -3893,7 +3910,7 @@ TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesTest,
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
ASSERT_TRUE(target_color_space.IsValid());
const PaintImage image = CreatePaintImageForDecodeAcceleration();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(0.75f, 0.75f)),
@@ -3936,7 +3953,7 @@ class GpuImageDecodeCacheWithAcceleratedDecodesFlagsTest
TEST_P(GpuImageDecodeCacheWithAcceleratedDecodesFlagsTest,
RequestAcceleratedDecodeSuccessfully) {
auto cache = CreateCache();
- const SkFilterQuality quality = kHigh_SkFilterQuality;
+ const PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
const gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
ASSERT_TRUE(target_color_space.IsValid());
diff --git a/chromium/cc/tiles/image_controller_unittest.cc b/chromium/cc/tiles/image_controller_unittest.cc
index 6fe0adb5ad6..07c0aa90923 100644
--- a/chromium/cc/tiles/image_controller_unittest.cc
+++ b/chromium/cc/tiles/image_controller_unittest.cc
@@ -242,14 +242,14 @@ int kDefaultTimeoutSeconds = 10;
DrawImage CreateDiscardableDrawImage(gfx::Size size) {
return DrawImage(CreateDiscardablePaintImage(size), false,
SkIRect::MakeWH(size.width(), size.height()),
- kNone_SkFilterQuality, SkM44(),
+ PaintFlags::FilterQuality::kNone, SkM44(),
PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
}
DrawImage CreateBitmapDrawImage(gfx::Size size) {
return DrawImage(CreateBitmapImage(size), false,
SkIRect::MakeWH(size.width(), size.height()),
- kNone_SkFilterQuality, SkM44(),
+ PaintFlags::FilterQuality::kNone, SkM44(),
PaintImage::kDefaultFrameIndex);
}
diff --git a/chromium/cc/tiles/image_decode_cache_utils.cc b/chromium/cc/tiles/image_decode_cache_utils.cc
index 4e16d1d60bb..b7a3b635eb4 100644
--- a/chromium/cc/tiles/image_decode_cache_utils.cc
+++ b/chromium/cc/tiles/image_decode_cache_utils.cc
@@ -17,13 +17,13 @@ namespace cc {
bool ImageDecodeCacheUtils::ScaleToHalfFloatPixmapUsingN32Intermediate(
const SkPixmap& source_pixmap,
SkPixmap* scaled_pixmap,
- SkFilterQuality filter_quality) {
+ PaintFlags::FilterQuality filter_quality) {
// Target pixmap should be half float backed.
DCHECK(scaled_pixmap->colorType() == kRGBA_F16_SkColorType);
// Filter quality should be medium or high. This is needed if the device
// (Android KitKat and lower) does not support mipmaps properly. Mipmaps are
// used only for medium and high filter qualities.
- DCHECK(filter_quality >= kMedium_SkFilterQuality);
+ DCHECK(filter_quality >= PaintFlags::FilterQuality::kMedium);
// Convert to kN32 color type if necessary
SkPixmap n32_pixmap = source_pixmap;
diff --git a/chromium/cc/tiles/image_decode_cache_utils.h b/chromium/cc/tiles/image_decode_cache_utils.h
index 12b21de039e..c8adfd1e92d 100644
--- a/chromium/cc/tiles/image_decode_cache_utils.h
+++ b/chromium/cc/tiles/image_decode_cache_utils.h
@@ -6,7 +6,7 @@
#define CC_TILES_IMAGE_DECODE_CACHE_UTILS_H_
#include "build/build_config.h"
-#include "third_party/skia/include/core/SkFilterQuality.h"
+#include "cc/paint/paint_flags.h"
#include "third_party/skia/include/core/SkPixmap.h"
#if defined(OS_ANDROID)
@@ -17,7 +17,7 @@ namespace cc {
class ImageDecodeCacheUtils {
public:
- static bool CanResizeF16Image(SkFilterQuality filter_quality) {
+ static bool CanResizeF16Image(PaintFlags::FilterQuality filter_quality) {
#if defined(OS_ANDROID)
// Return false on Android KitKat or lower if filter quality is medium or
// high (hence, mipmaps are used), return true otherwise. This is because
@@ -25,7 +25,7 @@ class ImageDecodeCacheUtils {
// these configs. crbug.com/876349
return (base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_LOLLIPOP) ||
- (filter_quality < kMedium_SkFilterQuality);
+ (filter_quality < PaintFlags::FilterQuality::kMedium);
#else
return true;
#endif
@@ -34,7 +34,7 @@ class ImageDecodeCacheUtils {
static bool ScaleToHalfFloatPixmapUsingN32Intermediate(
const SkPixmap& source_pixmap,
SkPixmap* scaled_pixmap,
- SkFilterQuality filter_quality);
+ PaintFlags::FilterQuality filter_quality);
};
} // namespace cc
diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc
index 11fdab5657c..2c36d79b565 100644
--- a/chromium/cc/tiles/picture_layer_tiling.cc
+++ b/chromium/cc/tiles/picture_layer_tiling.cc
@@ -13,11 +13,12 @@
#include "base/check_op.h"
#include "base/containers/flat_map.h"
+#include "base/cxx17_backports.h"
#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "cc/base/math_util.h"
+#include "cc/layers/picture_layer_impl.h"
#include "cc/raster/raster_source.h"
#include "cc/tiles/prioritized_tile.h"
#include "cc/tiles/tile.h"
@@ -905,7 +906,8 @@ PrioritizedTile PictureLayerTiling::MakePrioritizedTile(
// continue to rasterize the tile right now rather than for images only.
if (tile_priority.distance_to_visible <
max_skewport_extent_in_screen_space_ &&
- client_->ScrollInteractionInProgress() && client_->DidCheckerboardQuad())
+ client_->ScrollInteractionInProgress() &&
+ client_->CurrentScrollDidCheckerboardLargeArea())
process_for_images_only = false;
return PrioritizedTile(tile, this, tile_priority, IsTileOccluded(tile),
process_for_images_only,
@@ -931,9 +933,16 @@ TilePriority PictureLayerTiling::ComputePriorityForTile(
DCHECK_EQ(ComputePriorityRectTypeForTile(tile), priority_rect_type);
DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile);
- TilePriority::PriorityBin priority_bin = client_->HasValidTilePriorities()
- ? TilePriority::NOW
- : TilePriority::EVENTUALLY;
+ TilePriority::PriorityBin priority_bin;
+ if (client_->HasValidTilePriorities()) {
+ // Occluded tiles are given a lower PriorityBin to ensure they are evicted
+ // before non-occluded tiles.
+ priority_bin =
+ IsTileOccluded(tile) ? TilePriority::SOON : TilePriority::NOW;
+ } else {
+ priority_bin = TilePriority::EVENTUALLY;
+ }
+
switch (priority_rect_type) {
case VISIBLE_RECT:
case PENDING_VISIBLE_RECT:
diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h
index e651805b98a..18f1aeaf796 100644
--- a/chromium/cc/tiles/picture_layer_tiling.h
+++ b/chromium/cc/tiles/picture_layer_tiling.h
@@ -53,7 +53,7 @@ class CC_EXPORT PictureLayerTilingClient {
virtual const PaintWorkletRecordMap& GetPaintWorkletRecords() const = 0;
virtual bool IsDirectlyCompositedImage() const = 0;
virtual bool ScrollInteractionInProgress() const = 0;
- virtual bool DidCheckerboardQuad() const = 0;
+ virtual bool CurrentScrollDidCheckerboardLargeArea() const = 0;
protected:
virtual ~PictureLayerTilingClient() {}
diff --git a/chromium/cc/tiles/picture_layer_tiling_set.cc b/chromium/cc/tiles/picture_layer_tiling_set.cc
index 70a35e1a5bb..ce4b8dd914c 100644
--- a/chromium/cc/tiles/picture_layer_tiling_set.cc
+++ b/chromium/cc/tiles/picture_layer_tiling_set.cc
@@ -14,8 +14,8 @@
#include <vector>
#include "base/containers/contains.h"
+#include "base/containers/cxx20_erase.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "cc/raster/raster_source.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -714,8 +714,6 @@ PictureLayerTilingSet::CoverageIterator::operator++() {
tiling_iter_ = PictureLayerTiling::CoverageIterator(
set_->tilings_[current_tiling_].get(), coverage_scale_, last_rect);
}
-
- return *this;
}
PictureLayerTilingSet::CoverageIterator::operator bool() const {
diff --git a/chromium/cc/tiles/prioritized_tile.h b/chromium/cc/tiles/prioritized_tile.h
index 54538898271..38ca41dc30e 100644
--- a/chromium/cc/tiles/prioritized_tile.h
+++ b/chromium/cc/tiles/prioritized_tile.h
@@ -47,6 +47,8 @@ class CC_EXPORT PrioritizedTile {
void AsValueInto(base::trace_event::TracedValue* value) const;
+ const PictureLayerTiling* source_tiling() const { return source_tiling_; }
+
private:
Tile* tile_ = nullptr;
const PictureLayerTiling* source_tiling_ = nullptr;
diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc
index 5df593a29cf..45d3346d81e 100644
--- a/chromium/cc/tiles/software_image_decode_cache.cc
+++ b/chromium/cc/tiles/software_image_decode_cache.cc
@@ -129,10 +129,10 @@ SkSize GetScaleAdjustment(const SoftwareImageDecodeCache::CacheKey& key) {
// to do a bilinear interpolation. The exception to this is if the developer
// specified a pixelated effect, which results in a None filter quality (nearest
// neighbor).
-SkFilterQuality GetDecodedFilterQuality(
+PaintFlags::FilterQuality GetDecodedFilterQuality(
const SoftwareImageDecodeCache::CacheKey& key) {
- return key.is_nearest_neighbor() ? kNone_SkFilterQuality
- : kLow_SkFilterQuality;
+ return key.is_nearest_neighbor() ? PaintFlags::FilterQuality::kNone
+ : PaintFlags::FilterQuality::kLow;
}
} // namespace
@@ -415,8 +415,8 @@ SoftwareImageDecodeCache::DecodeImageIfNecessary(const CacheKey& key,
? SkIRect::MakeWH(paint_image.width(), paint_image.height())
: gfx::RectToSkIRect(key.src_rect());
DrawImage candidate_draw_image(
- paint_image, false, src_rect, kNone_SkFilterQuality, SkM44(),
- key.frame_key().frame_index(), key.target_color_space());
+ paint_image, false, src_rect, PaintFlags::FilterQuality::kNone,
+ SkM44(), key.frame_key().frame_index(), key.target_color_space());
candidate_key.emplace(CacheKey::FromDrawImage(
candidate_draw_image,
GetColorTypeForPaintImage(key.target_color_space(), paint_image)));
diff --git a/chromium/cc/tiles/software_image_decode_cache_perftest.cc b/chromium/cc/tiles/software_image_decode_cache_perftest.cc
index e51ed57f6e7..ce71e96fd5f 100644
--- a/chromium/cc/tiles/software_image_decode_cache_perftest.cc
+++ b/chromium/cc/tiles/software_image_decode_cache_perftest.cc
@@ -37,9 +37,9 @@ class SoftwareImageDecodeCachePerfTest : public testing::Test {
kTimeCheckInterval) {}
void RunFromImage() {
- SkFilterQuality qualities[] = {kNone_SkFilterQuality, kLow_SkFilterQuality,
- kMedium_SkFilterQuality,
- kHigh_SkFilterQuality};
+ PaintFlags::FilterQuality qualities[] = {
+ PaintFlags::FilterQuality::kNone, PaintFlags::FilterQuality::kLow,
+ PaintFlags::FilterQuality::kMedium, PaintFlags::FilterQuality::kHigh};
std::pair<SkIRect, SkIRect> image_rect_subrect[] = {
std::make_pair(SkIRect::MakeWH(100, 100), SkIRect::MakeWH(100, 100)),
std::make_pair(SkIRect::MakeWH(100, 100), SkIRect::MakeWH(50, 50)),
diff --git a/chromium/cc/tiles/software_image_decode_cache_unittest.cc b/chromium/cc/tiles/software_image_decode_cache_unittest.cc
index 8815ece97a5..72043edc560 100644
--- a/chromium/cc/tiles/software_image_decode_cache_unittest.cc
+++ b/chromium/cc/tiles/software_image_decode_cache_unittest.cc
@@ -52,7 +52,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyNoneQuality) {
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kNone_SkFilterQuality,
+ PaintFlags::FilterQuality::kNone,
CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -75,7 +75,7 @@ TEST(SoftwareImageDecodeCacheTest,
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kLow_SkFilterQuality,
+ PaintFlags::FilterQuality::kLow,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -94,7 +94,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropsToLowIfMipLevel0) {
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kMedium_SkFilterQuality,
+ PaintFlags::FilterQuality::kMedium,
CreateMatrix(SkSize::Make(0.75f, 0.75f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -114,7 +114,7 @@ TEST(SoftwareImageDecodeCacheTest, LowUnscalableFormatStaysLow) {
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kLow_SkFilterQuality,
+ PaintFlags::FilterQuality::kLow,
CreateMatrix(SkSize::Make(0.5f, 1.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -134,7 +134,7 @@ TEST(SoftwareImageDecodeCacheTest, HighUnscalableFormatBecomesLow) {
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kHigh_SkFilterQuality,
+ PaintFlags::FilterQuality::kHigh,
CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -154,7 +154,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityKeptLowIfUpscale) {
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kLow_SkFilterQuality,
+ PaintFlags::FilterQuality::kLow,
CreateMatrix(SkSize::Make(1.5f, 1.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -171,7 +171,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityKeptLowIfUpscale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -191,7 +191,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQuality) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfEnlarging) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -212,7 +212,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfEnlarging) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityDropToLowIfIdentity) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -234,7 +234,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyMediumQualityDropToLowIfNearlyIdentity) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -256,7 +256,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyMediumQualityDropToLowIfNearlyIdentity2) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -278,7 +278,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyMediumQualityDropToLowIfNotDecomposable) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = false;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -300,7 +300,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_5Scale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -321,7 +321,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_5Scale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_0cale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -342,7 +342,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt1_0cale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityAt0_75Scale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -363,7 +363,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyLowQualityAt0_75Scale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_5Scale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -383,7 +383,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_5Scale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_49Scale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -403,7 +403,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_49Scale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -423,7 +423,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_1Scale) {
TEST(SoftwareImageDecodeCacheTest, ImageKeyMediumQualityAt0_01Scale) {
PaintImage paint_image = CreatePaintImage(500, 200);
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
DrawImage draw_image(
paint_image, false,
@@ -444,7 +444,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyFullDowscalesDropsHighQualityToMedium) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -464,7 +464,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, ImageKeyUpscaleIsLowQuality) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -486,7 +486,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToMediumIfTooLarge) {
// Just over 64MB when scaled.
PaintImage paint_image = CreatePaintImage(4555, 2048);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
// At least one dimension should scale down, so that medium quality doesn't
// become low.
@@ -509,7 +509,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyHighQualityDropToLowIfNotDecomposable) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = false;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -530,7 +530,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, ImageKeyHighQualityDropToLowIfIdentity) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -552,7 +552,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyHighQualityDropToLowIfNearlyIdentity) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -574,7 +574,7 @@ TEST(SoftwareImageDecodeCacheTest,
ImageKeyHighQualityDropToLowIfNearlyIdentity2) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -614,7 +614,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyDownscaleMipLevelWithRounding) {
DrawImage draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kMedium_SkFilterQuality,
+ PaintFlags::FilterQuality::kMedium,
CreateMatrix(SkSize::Make(0.2f, 0.2f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
@@ -631,7 +631,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageKeyDownscaleMipLevelWithRounding) {
TEST(SoftwareImageDecodeCacheTest, OriginalDecodesAreEqual) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kNone_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
DrawImage draw_image(
paint_image, false,
@@ -669,7 +669,7 @@ TEST(SoftwareImageDecodeCacheTest, OriginalDecodesAreEqual) {
TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRect) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -690,7 +690,7 @@ TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRect) {
TEST(SoftwareImageDecodeCacheTest, ImageRectDoesNotContainSrcRectWithScale) {
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -712,7 +712,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImage) {
TestSoftwareImageDecodeCache cache;
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -744,7 +744,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageProcessUnrefCancel) {
TestSoftwareImageDecodeCache cache;
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(
paint_image, false,
@@ -779,7 +779,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) {
DrawImage high_quality_draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kHigh_SkFilterQuality,
+ PaintFlags::FilterQuality::kHigh,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
ImageDecodeCache::TaskResult high_quality_result =
@@ -791,7 +791,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentQuality) {
DrawImage none_quality_draw_image(
paint_image, false,
SkIRect::MakeWH(paint_image.width(), paint_image.height()),
- kNone_SkFilterQuality,
+ PaintFlags::FilterQuality::kNone,
CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable),
PaintImage::kDefaultFrameIndex, DefaultColorSpace());
ImageDecodeCache::TaskResult none_quality_result =
@@ -812,7 +812,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
TestSoftwareImageDecodeCache cache;
PaintImage paint_image = CreatePaintImage(100, 100);
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage half_size_draw_image(
paint_image, false,
@@ -846,7 +846,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageSameImageDifferentSize) {
TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage first_paint_image = CreatePaintImage(100, 100);
DrawImage first_draw_image(
@@ -889,7 +889,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageDifferentImage) {
TEST(SoftwareImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentColorSpace) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
gfx::ColorSpace color_space_a(gfx::ColorSpace::PrimaryID::XYZ_D50,
gfx::ColorSpace::TransferID::IEC61966_2_1);
@@ -941,7 +941,7 @@ TEST(SoftwareImageDecodeCacheTest, MAYBE_GetTaskForImageDifferentColorSpace) {
TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -971,7 +971,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyDecoded) {
TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyPrerolled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kLow_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1007,7 +1007,7 @@ TEST(SoftwareImageDecodeCacheTest, GetTaskForImageAlreadyPrerolled) {
TEST(SoftwareImageDecodeCacheTest, GetTaskForImageCanceledGetsNewTask) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1049,7 +1049,7 @@ TEST(SoftwareImageDecodeCacheTest,
GetTaskForImageCanceledWhileReffedGetsNewTask) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1090,7 +1090,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDraw) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1112,7 +1112,8 @@ TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDraw) {
EXPECT_EQ(50, decoded_draw_image.image()->height());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
@@ -1123,7 +1124,7 @@ TEST(SoftwareImageDecodeCacheTest,
GetDecodedImageForDrawWithNonContainedSrcRect) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1145,7 +1146,8 @@ TEST(SoftwareImageDecodeCacheTest,
EXPECT_EQ(35, decoded_draw_image.image()->height());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
@@ -1155,7 +1157,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1171,7 +1173,8 @@ TEST(SoftwareImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
EXPECT_EQ(50, decoded_draw_image.image()->height());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
@@ -1181,7 +1184,7 @@ TEST(SoftwareImageDecodeCacheTest,
GetDecodedImageForDrawAtRasterDecodeMultipleTimes) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1197,7 +1200,8 @@ TEST(SoftwareImageDecodeCacheTest,
EXPECT_EQ(50, decoded_draw_image.image()->height());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
EXPECT_FLOAT_EQ(0.5f, decoded_draw_image.scale_adjustment().height());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
DecodedDrawImage another_decoded_draw_image =
@@ -1212,7 +1216,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1236,7 +1240,7 @@ TEST(SoftwareImageDecodeCacheTest, ZeroSizedImagesAreSkipped) {
TEST(SoftwareImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1260,7 +1264,7 @@ TEST(SoftwareImageDecodeCacheTest, NonOverlappingSrcRectImagesAreSkipped) {
TEST(SoftwareImageDecodeCacheTest, LowQualityFilterIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kLow_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(
@@ -1290,7 +1294,7 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityFilterIsHandled) {
TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kLow_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80),
@@ -1311,7 +1315,8 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
// If we decoded the image and cached it, it would be stored in a different
// SkImage object.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
// Low quality will be upgraded to medium and mip-mapped.
EXPECT_FALSE(decoded_draw_image.is_scale_adjustment_identity());
EXPECT_EQ(0.5f, decoded_draw_image.scale_adjustment().width());
@@ -1324,7 +1329,7 @@ TEST(SoftwareImageDecodeCacheTest, LowQualityScaledSubrectIsHandled) {
TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kNone_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
PaintImage paint_image = CreatePaintImage(100, 100);
DrawImage draw_image(paint_image, false, SkIRect::MakeXYWH(10, 10, 80, 80),
@@ -1345,7 +1350,8 @@ TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) {
// If we decoded the image and cached it, it would be stored in a different
// SkImage object.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kNone_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kNone,
+ decoded_draw_image.filter_quality());
EXPECT_TRUE(decoded_draw_image.is_scale_adjustment_identity());
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
@@ -1355,7 +1361,7 @@ TEST(SoftwareImageDecodeCacheTest, NoneQualityScaledSubrectIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1376,7 +1382,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(500, decoded_draw_image.image()->width());
EXPECT_EQ(200, decoded_draw_image.image()->height());
@@ -1387,7 +1394,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt01_5ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1408,7 +1415,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(500, decoded_draw_image.image()->width());
EXPECT_EQ(200, decoded_draw_image.image()->height());
@@ -1419,7 +1427,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt1_0ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1440,7 +1448,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(500, decoded_draw_image.image()->width());
EXPECT_EQ(200, decoded_draw_image.image()->height());
@@ -1451,7 +1460,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_75ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1472,7 +1481,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(250, decoded_draw_image.image()->width());
EXPECT_EQ(100, decoded_draw_image.image()->height());
@@ -1483,7 +1493,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_5ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1504,7 +1514,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(250, decoded_draw_image.image()->width());
EXPECT_EQ(100, decoded_draw_image.image()->height());
@@ -1515,7 +1526,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_49ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1536,7 +1547,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(63, decoded_draw_image.image()->width());
EXPECT_EQ(25, decoded_draw_image.image()->height());
@@ -1547,7 +1559,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_1ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1568,7 +1580,8 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
EXPECT_TRUE(decoded_draw_image.image());
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image.filter_quality());
EXPECT_EQ(8, decoded_draw_image.image()->width());
EXPECT_EQ(4, decoded_draw_image.image()->height());
@@ -1579,7 +1592,7 @@ TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_01ScaleIsHandled) {
TEST(SoftwareImageDecodeCacheTest, MediumQualityAt0_001ScaleIsHandled) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image(
@@ -1604,7 +1617,7 @@ TEST(SoftwareImageDecodeCacheTest,
MediumQualityImagesAreTheSameAt0_5And0_49Scale) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
PaintImage paint_image = CreatePaintImage(500, 200);
DrawImage draw_image_50(
@@ -1638,8 +1651,10 @@ TEST(SoftwareImageDecodeCacheTest,
// Decoded image should not be lazy generated.
EXPECT_FALSE(decoded_draw_image_50.image()->isLazyGenerated());
EXPECT_FALSE(decoded_draw_image_49.image()->isLazyGenerated());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image_50.filter_quality());
- EXPECT_EQ(kLow_SkFilterQuality, decoded_draw_image_49.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image_50.filter_quality());
+ EXPECT_EQ(PaintFlags::FilterQuality::kLow,
+ decoded_draw_image_49.filter_quality());
EXPECT_EQ(250, decoded_draw_image_50.image()->width());
EXPECT_EQ(250, decoded_draw_image_49.image()->width());
EXPECT_EQ(100, decoded_draw_image_50.image()->height());
@@ -1656,7 +1671,7 @@ TEST(SoftwareImageDecodeCacheTest,
TEST(SoftwareImageDecodeCacheTest, ClearCache) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
for (int i = 0; i < 10; ++i) {
PaintImage paint_image = CreatePaintImage(100, 100);
@@ -1698,7 +1713,7 @@ TEST(SoftwareImageDecodeCacheTest, CacheDecodesExpectedFrames) {
.TakePaintImage();
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
DrawImage draw_image(image, false,
SkIRect::MakeWH(image.width(), image.height()), quality,
CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
@@ -1737,7 +1752,7 @@ TEST(SoftwareImageDecodeCacheTest, SizeSubrectingIsHandled) {
const int min_dimension = 4 * 1024 + 2;
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kLow_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
auto paint_image =
CreateDiscardablePaintImage(gfx::Size(min_dimension, min_dimension),
@@ -1771,7 +1786,7 @@ TEST(SoftwareImageDecodeCacheTest, EmptyTargetSizeDecode) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kLow_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kLow;
// Populate the cache with an original sized decode.
auto paint_image = CreateDiscardablePaintImage(
@@ -1798,7 +1813,7 @@ TEST(SoftwareImageDecodeCacheTest, EmptyTargetSizeDecode) {
TEST(SoftwareImageDecodeCacheTest, BitmapImageColorConverted) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateDisplayP3D65();
PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
@@ -1824,7 +1839,7 @@ TEST(SoftwareImageDecodeCacheTest, BitmapImageColorConverted) {
TEST(SoftwareImageDecodeCacheTest, BitmapImageNotColorConverted) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage paint_image = CreateBitmapImage(gfx::Size(100, 100));
DrawImage draw_image(
@@ -1842,7 +1857,7 @@ TEST(SoftwareImageDecodeCacheTest, BitmapImageNotColorConverted) {
TEST(SoftwareImageDecodeCacheTest, DISABLED_ContentIdCaching) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kHigh_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kHigh;
PaintImage::Id stable_id = 1001;
for (int i = 0; i < 10; ++i) {
@@ -1875,7 +1890,7 @@ TEST(SoftwareImageDecodeCacheTest, DISABLED_ContentIdCaching) {
TEST(SoftwareImageDecodeCacheTest, DecodeToScale) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
SkISize full_size = SkISize::Make(100, 100);
std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
@@ -1935,7 +1950,7 @@ TEST(SoftwareImageDecodeCacheTest, DecodeToScale) {
TEST(SoftwareImageDecodeCacheTest, DecodeToScaleSubrect) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kMedium;
SkISize full_size = SkISize::Make(100, 100);
std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
@@ -1972,7 +1987,7 @@ TEST(SoftwareImageDecodeCacheTest, DecodeToScaleSubrect) {
TEST(SoftwareImageDecodeCacheTest, DecodeToScaleNoneQuality) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
- SkFilterQuality quality = kNone_SkFilterQuality;
+ PaintFlags::FilterQuality quality = PaintFlags::FilterQuality::kNone;
SkISize full_size = SkISize::Make(100, 100);
std::vector<SkISize> supported_sizes = {SkISize::Make(25, 25),
@@ -2022,10 +2037,11 @@ TEST(SoftwareImageDecodeCacheTest, HdrDecodeToHdr) {
PaintImage::GetNextContentId())
.TakePaintImage();
- DrawImage draw_image(
- image, false, SkIRect::MakeWH(image.width(), image.height()),
- kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(0.5, 0.5), true),
- PaintImage::kDefaultFrameIndex, color_space);
+ DrawImage draw_image(image, false,
+ SkIRect::MakeWH(image.width(), image.height()),
+ PaintFlags::FilterQuality::kMedium,
+ CreateMatrix(SkSize::Make(0.5, 0.5), true),
+ PaintImage::kDefaultFrameIndex, color_space);
DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
EXPECT_EQ(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
@@ -2052,10 +2068,11 @@ TEST(SoftwareImageDecodeCacheTest, HdrDecodeToSdr) {
// Note: We use P3 here since software cache shouldn't be used when conversion
// to SRGB is needed.
auto raster_color_space = gfx::ColorSpace::CreateDisplayP3D65();
- DrawImage draw_image(
- image, false, SkIRect::MakeWH(image.width(), image.height()),
- kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(0.5, 0.5), true),
- PaintImage::kDefaultFrameIndex, raster_color_space);
+ DrawImage draw_image(image, false,
+ SkIRect::MakeWH(image.width(), image.height()),
+ PaintFlags::FilterQuality::kMedium,
+ CreateMatrix(SkSize::Make(0.5, 0.5), true),
+ PaintImage::kDefaultFrameIndex, raster_color_space);
DecodedDrawImage decoded_image = cache.GetDecodedImageForDraw(draw_image);
EXPECT_NE(decoded_image.image()->colorType(), kRGBA_F16_SkColorType);
diff --git a/chromium/cc/tiles/software_image_decode_cache_unittest_combinations.cc b/chromium/cc/tiles/software_image_decode_cache_unittest_combinations.cc
index 0e34fa5741c..0b1a639d72c 100644
--- a/chromium/cc/tiles/software_image_decode_cache_unittest_combinations.cc
+++ b/chromium/cc/tiles/software_image_decode_cache_unittest_combinations.cc
@@ -48,7 +48,8 @@ class BaseTest : public testing::Test {
src_rect.isEmpty()
? SkIRect::MakeWH(paint_image().width(), paint_image().height())
: src_rect,
- kMedium_SkFilterQuality, CreateMatrix(SkSize::Make(scale, scale), true),
+ PaintFlags::FilterQuality::kMedium,
+ CreateMatrix(SkSize::Make(scale, scale), true),
PaintImage::kDefaultFrameIndex, GetColorSpace());
}
diff --git a/chromium/cc/tiles/software_image_decode_cache_utils.cc b/chromium/cc/tiles/software_image_decode_cache_utils.cc
index e3198f2fd54..9b7bd63e741 100644
--- a/chromium/cc/tiles/software_image_decode_cache_utils.cc
+++ b/chromium/cc/tiles/software_image_decode_cache_utils.cc
@@ -149,7 +149,7 @@ SoftwareImageDecodeCacheUtils::GenerateCacheEntryFromCandidate(
DCHECK(!key.is_nearest_neighbor());
SkPixmap target_pixmap(target_info, target_pixels->data(),
target_info.minRowBytes());
- SkFilterQuality filter_quality = kMedium_SkFilterQuality;
+ PaintFlags::FilterQuality filter_quality = PaintFlags::FilterQuality::kMedium;
if (decoded_pixmap.colorType() == kRGBA_F16_SkColorType &&
!ImageDecodeCacheUtils::CanResizeF16Image(filter_quality)) {
result = ImageDecodeCacheUtils::ScaleToHalfFloatPixmapUsingN32Intermediate(
@@ -199,7 +199,8 @@ SoftwareImageDecodeCacheUtils::CacheKey::FromDrawImage(const DrawImage& image,
}
ProcessingType type = kOriginal;
- bool is_nearest_neighbor = image.filter_quality() == kNone_SkFilterQuality;
+ bool is_nearest_neighbor =
+ image.filter_quality() == PaintFlags::FilterQuality::kNone;
int mip_level = MipMapUtil::GetLevelForSize(src_rect.size(), target_size);
// If any of the following conditions hold, then use at most low filter
// quality and adjust the target size to match the original image:
@@ -289,6 +290,10 @@ SoftwareImageDecodeCacheUtils::CacheKey::CacheKey(
SoftwareImageDecodeCacheUtils::CacheKey::CacheKey(const CacheKey& other) =
default;
+SoftwareImageDecodeCacheUtils::CacheKey&
+SoftwareImageDecodeCacheUtils::CacheKey::operator=(const CacheKey& other) =
+ default;
+
std::string SoftwareImageDecodeCacheUtils::CacheKey::ToString() const {
std::ostringstream str;
str << "frame_key[" << frame_key_.ToString() << "]\ntype[";
diff --git a/chromium/cc/tiles/software_image_decode_cache_utils.h b/chromium/cc/tiles/software_image_decode_cache_utils.h
index 071f7d216a7..964aa832bb6 100644
--- a/chromium/cc/tiles/software_image_decode_cache_utils.h
+++ b/chromium/cc/tiles/software_image_decode_cache_utils.h
@@ -51,6 +51,7 @@ class SoftwareImageDecodeCacheUtils {
SkColorType color_type);
CacheKey(const CacheKey& other);
+ CacheKey& operator=(const CacheKey& other);
bool operator==(const CacheKey& other) const {
// The frame_key always has to be the same. However, after that all
diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc
index e409dd8851c..6f227fe9b7d 100644
--- a/chromium/cc/tiles/tile_manager.cc
+++ b/chromium/cc/tiles/tile_manager.cc
@@ -1207,9 +1207,11 @@ scoped_refptr<TileTask> TileManager::CreateRasterTask(
uint64_t resource_content_id = 0;
gfx::Rect invalidated_rect = tile->invalidated_content_rect();
if (UsePartialRaster(msaa_sample_count) && tile->invalidated_id()) {
+ const std::string& debug_name =
+ prioritized_tile.source_tiling()->raster_source()->debug_name();
resource = resource_pool_->TryAcquireResourceForPartialRaster(
tile->id(), tile->invalidated_content_rect(), tile->invalidated_id(),
- &invalidated_rect, raster_color_space);
+ &invalidated_rect, raster_color_space, debug_name);
}
bool partial_tile_decode = false;
@@ -1218,8 +1220,10 @@ scoped_refptr<TileTask> TileManager::CreateRasterTask(
DCHECK_EQ(format, resource.format());
partial_tile_decode = true;
} else {
- resource = resource_pool_->AcquireResource(tile->desired_texture_size(),
- format, raster_color_space);
+ const std::string& debug_name =
+ prioritized_tile.source_tiling()->raster_source()->debug_name();
+ resource = resource_pool_->AcquireResource(
+ tile->desired_texture_size(), format, raster_color_space, debug_name);
DCHECK(resource);
}
diff --git a/chromium/cc/tiles/tile_manager_perftest.cc b/chromium/cc/tiles/tile_manager_perftest.cc
index 07cd2aa57f2..86b7c6510e2 100644
--- a/chromium/cc/tiles/tile_manager_perftest.cc
+++ b/chromium/cc/tiles/tile_manager_perftest.cc
@@ -5,9 +5,9 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/cxx17_backports.h"
#include "base/lazy_instance.h"
#include "base/location.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/timer/lap_timer.h"
diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc
index b263d53826d..08f465750ba 100644
--- a/chromium/cc/tiles/tile_manager_unittest.cc
+++ b/chromium/cc/tiles/tile_manager_unittest.cc
@@ -14,6 +14,7 @@
#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/process_memory_dump.h"
#include "cc/layers/recording_source.h"
#include "cc/raster/raster_buffer.h"
#include "cc/raster/raster_source.h"
@@ -835,6 +836,43 @@ TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
EXPECT_EQ(all_tiles, new_content_tiles);
}
+// Verifies LayerDebugInfo::name ends up memory dumps.
+TEST_F(TileManagerTilePriorityQueueTest, DebugNameAppearsInMemoryDump) {
+ host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
+
+ gfx::Size layer_bounds(1000, 1000);
+
+ host_impl()->active_tree()->SetDeviceViewportRect(gfx::Rect(layer_bounds));
+
+ scoped_refptr<FakeRasterSource> pending_raster_source =
+ FakeRasterSource::CreateFilledWithText(layer_bounds);
+ SetupPendingTree(pending_raster_source);
+
+ auto* pending_child_layer = AddLayer<FakePictureLayerImpl>(
+ host_impl()->pending_tree(), pending_raster_source);
+ LayerDebugInfo debug_info;
+ debug_info.name = "debug-name";
+ pending_child_layer->UpdateDebugInfo(&debug_info);
+ pending_child_layer->SetDrawsContent(true);
+ CopyProperties(pending_layer(), pending_child_layer);
+
+ ActivateTree();
+ host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state());
+
+ base::trace_event::MemoryDumpArgs dump_args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ base::trace_event::ProcessMemoryDump memory_dump(dump_args);
+ host_impl()->resource_pool()->OnMemoryDump(dump_args, &memory_dump);
+ bool found_debug_name = false;
+ for (const auto& allocator_map_pair : memory_dump.allocator_dumps()) {
+ if (allocator_map_pair.first.find("debug-name") != std::string::npos) {
+ found_debug_name = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(found_debug_name);
+}
+
TEST_F(TileManagerTilePriorityQueueTest,
EvictionTilePriorityQueueWithOcclusion) {
host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(1));
@@ -1732,6 +1770,106 @@ TEST_F(TileManagerTest, ActivateAndDrawWhenOOM) {
}
}
+class TileManagerOcclusionTest : public TileManagerTest {
+ public:
+ LayerTreeSettings CreateSettings() override {
+ auto settings = TestLayerTreeHostBase::CreateSettings();
+ settings.create_low_res_tiling = true;
+ settings.use_occlusion_for_tile_prioritization = true;
+ return settings;
+ }
+
+ void PrepareTilesAndWaitUntilDone(
+ const GlobalStateThatImpactsTilePriority& state) {
+ base::RunLoop run_loop;
+ EXPECT_CALL(MockHostImpl(), NotifyAllTileTasksCompleted())
+ .WillOnce(testing::Invoke([&run_loop]() { run_loop.Quit(); }));
+ tile_manager()->PrepareTiles(state);
+ run_loop.Run();
+ tile_manager()->CheckForCompletedTasks();
+ }
+
+ TileManager* tile_manager() { return host_impl()->tile_manager(); }
+};
+
+TEST_F(TileManagerOcclusionTest, OccludedTileEvictedForVisibleTile) {
+ gfx::Size layer_bounds(256, 256);
+ host_impl()->active_tree()->SetDeviceViewportRect(gfx::Rect(layer_bounds));
+
+ SetupPendingTree(FakeRasterSource::CreateFilledWithText(layer_bounds));
+ const int initial_picture_id = pending_layer()->id();
+ ActivateTree();
+
+ GlobalStateThatImpactsTilePriority global_state =
+ host_impl()->global_tile_state();
+ const LayerTreeSettings settings = CreateSettings();
+ global_state.hard_memory_limit_in_bytes =
+ global_state.soft_memory_limit_in_bytes =
+ settings.default_tile_size.GetArea() * 4 + 1;
+
+ // Call PrepareTiles and wait for it to complete. It's necessary to wait for
+ // completion so that the resource is pushed to the tile, which is used
+ // in calculating eviction.
+ PrepareTilesAndWaitUntilDone(global_state);
+
+ // At this point the initial PictureLayerImpl should have a Tile with a
+ // resource.
+ {
+ PictureLayerImpl* initial_layer = static_cast<PictureLayerImpl*>(
+ host_impl()->active_tree()->LayerById(initial_picture_id));
+ ASSERT_NE(initial_layer, nullptr);
+ ASSERT_EQ(1u, initial_layer->picture_layer_tiling_set()->num_tilings());
+ std::vector<Tile*> initial_layer_tiles =
+ initial_layer->picture_layer_tiling_set()
+ ->tiling_at(0)
+ ->AllTilesForTesting();
+ ASSERT_EQ(1u, initial_layer_tiles.size());
+ EXPECT_TRUE(initial_layer_tiles[0]->draw_info().has_resource());
+ }
+
+ // Add another layer on top. As there is only enough memory for one tile,
+ // the top most tile should get a raster task and the bottom layer should
+ // not.
+ SetupPendingTree(FakeRasterSource::CreateFilledWithText(layer_bounds));
+
+ // Advance the frame to ensure PictureLayerTilingSet applies the occlusion to
+ // the PictureLayerTiling. The amount of time advanced doesn't matter.
+ host_impl()->AdvanceToNextFrame(base::TimeDelta::FromSeconds(2));
+
+ auto* picture_layer = AddLayer<FakePictureLayerImpl>(
+ host_impl()->pending_tree(),
+ FakeRasterSource::CreateFilledWithText(layer_bounds));
+ const int top_most_layer_id = picture_layer->id();
+ picture_layer->SetDrawsContent(true);
+ picture_layer->SetContentsOpaque(true);
+ CopyProperties(pending_layer(), picture_layer);
+ ActivateTree();
+ PrepareTilesAndWaitUntilDone(global_state);
+ {
+ PictureLayerImpl* initial_layer = static_cast<PictureLayerImpl*>(
+ host_impl()->active_tree()->LayerById(initial_picture_id));
+ ASSERT_NE(initial_layer, nullptr);
+ ASSERT_EQ(1u, initial_layer->picture_layer_tiling_set()->num_tilings());
+ std::vector<Tile*> initial_layer_tiles =
+ initial_layer->picture_layer_tiling_set()
+ ->tiling_at(0)
+ ->AllTilesForTesting();
+ ASSERT_EQ(1u, initial_layer_tiles.size());
+ EXPECT_FALSE(initial_layer_tiles[0]->draw_info().has_resource());
+
+ PictureLayerImpl* top_most_layer = static_cast<PictureLayerImpl*>(
+ host_impl()->active_tree()->LayerById(top_most_layer_id));
+ ASSERT_NE(top_most_layer, nullptr);
+ ASSERT_EQ(1u, top_most_layer->picture_layer_tiling_set()->num_tilings());
+ std::vector<Tile*> top_most_layer_tiles =
+ top_most_layer->picture_layer_tiling_set()
+ ->tiling_at(0)
+ ->AllTilesForTesting();
+ ASSERT_EQ(1u, top_most_layer_tiles.size());
+ EXPECT_TRUE(top_most_layer_tiles[0]->draw_info().has_resource());
+ }
+}
+
class PixelInspectTileManagerTest : public TileManagerTest {
public:
~PixelInspectTileManagerTest() override {
diff --git a/chromium/cc/trees/animated_paint_worklet_tracker.cc b/chromium/cc/trees/animated_paint_worklet_tracker.cc
index b312c24180d..58d51b838fa 100644
--- a/chromium/cc/trees/animated_paint_worklet_tracker.cc
+++ b/chromium/cc/trees/animated_paint_worklet_tracker.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/containers/cxx20_erase.h"
#include "cc/layers/picture_layer_impl.h"
namespace cc {
diff --git a/chromium/cc/trees/clip_expander.cc b/chromium/cc/trees/clip_expander.cc
index 02df3797a41..b4fbe772b47 100644
--- a/chromium/cc/trees/clip_expander.cc
+++ b/chromium/cc/trees/clip_expander.cc
@@ -14,6 +14,8 @@ ClipExpander::ClipExpander(int filter_effect_id)
ClipExpander::ClipExpander(const ClipExpander& other) = default;
+ClipExpander& ClipExpander::operator=(const ClipExpander& other) = default;
+
bool ClipExpander::operator==(const ClipExpander& other) const {
return target_effect_id_ == other.target_effect_id_;
}
diff --git a/chromium/cc/trees/clip_expander.h b/chromium/cc/trees/clip_expander.h
index 209477a2553..fef2ad5ecda 100644
--- a/chromium/cc/trees/clip_expander.h
+++ b/chromium/cc/trees/clip_expander.h
@@ -16,6 +16,7 @@ class CC_EXPORT ClipExpander {
public:
explicit ClipExpander(int filter_effect_id);
ClipExpander(const ClipExpander& other);
+ ClipExpander& operator=(const ClipExpander& other);
bool operator==(const ClipExpander& other) const;
diff --git a/chromium/cc/trees/compositor_commit_data.h b/chromium/cc/trees/compositor_commit_data.h
index 35a7d8e313a..4fb1482bb96 100644
--- a/chromium/cc/trees/compositor_commit_data.h
+++ b/chromium/cc/trees/compositor_commit_data.h
@@ -13,6 +13,7 @@
#include "cc/input/scroll_snap_data.h"
#include "cc/paint/element_id.h"
#include "cc/trees/layer_tree_host_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/transform.h"
diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc
index a97f44689a3..48332d88b20 100644
--- a/chromium/cc/trees/damage_tracker_unittest.cc
+++ b/chromium/cc/trees/damage_tracker_unittest.cc
@@ -1801,13 +1801,13 @@ TEST_F(DamageTrackerTest, DamageRectTooBig) {
SetCopyRequest(root);
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 0));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 0));
child1->SetBounds(gfx::Size(1, 1));
// Really far right.
- child2->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 100, 0));
+ child2->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 100), 0));
child2->SetBounds(gfx::Size(1, 1));
EmulateDrawingOneFrame(root, 1.f);
@@ -1838,13 +1838,13 @@ TEST_F(DamageTrackerTest, DamageRectTooBigWithFilter) {
SetBackdropFilter(root, filters);
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 0));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 0));
child1->SetBounds(gfx::Size(1, 1));
// Really far right.
- child2->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 100, 0));
+ child2->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 100), 0));
child2->SetBounds(gfx::Size(1, 1));
float device_scale_factor = 1.f;
@@ -1869,14 +1869,14 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) {
SetCopyRequest(root);
// Really far left.
- grand_child1_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 500, 0));
+ grand_child1_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 500), 0));
grand_child1_->SetBounds(gfx::Size(1, 1));
grand_child1_->SetDrawsContent(true);
// Really far right.
- grand_child2_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 500, 0));
+ grand_child2_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 500), 0));
grand_child2_->SetBounds(gfx::Size(1, 1));
grand_child2_->SetDrawsContent(true);
@@ -1959,14 +1959,14 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) {
SetBackdropFilter(child1_, filters);
// Really far left.
- grand_child1_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 500, 0));
+ grand_child1_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 500), 0));
grand_child1_->SetBounds(gfx::Size(1, 1));
grand_child1_->SetDrawsContent(true);
// Really far right.
- grand_child2_->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 500, 0));
+ grand_child2_->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 500), 0));
grand_child2_->SetBounds(gfx::Size(1, 1));
grand_child2_->SetDrawsContent(true);
@@ -2217,13 +2217,13 @@ TEST_F(DamageTrackerTest, DamageRectOnlyVisibleContentsMoveToOutside) {
origin_damage.Union(child2->visible_drawable_content_rect());
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 0));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 0));
child1->SetBounds(gfx::Size(1, 1));
// Really far right.
- child2->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::max() - 100, 0));
+ child2->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::max() - 100), 0));
child2->SetBounds(gfx::Size(1, 1));
EmulateDrawingOneFrame(root, 1.f);
@@ -2252,8 +2252,8 @@ TEST_F(DamageTrackerTest, DamageRectOnlyVisibleContentsLargeTwoContents) {
expected_damage.set_width(GetRenderSurface(root)->content_rect().width());
// Really far left.
- child1->SetOffsetToTransformParent(
- gfx::Vector2dF(std::numeric_limits<int>::min() + 100, 100));
+ child1->SetOffsetToTransformParent(gfx::Vector2dF(
+ static_cast<float>(std::numeric_limits<int>::min() + 100), 100));
child1->SetBounds(
gfx::Size(std::numeric_limits<int>::max(), child1->bounds().height()));
@@ -2263,7 +2263,7 @@ TEST_F(DamageTrackerTest, DamageRectOnlyVisibleContentsLargeTwoContents) {
gfx::Size(std::numeric_limits<int>::max(), child2->bounds().height()));
EmulateDrawingOneFrame(root, 1.f);
- // Above damages should be excludebe because they're outside of
+ // Above damages should be excluded because they're outside of
// the root surface.
gfx::Rect damage_rect;
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
diff --git a/chromium/cc/trees/de_jelly_state.h b/chromium/cc/trees/de_jelly_state.h
index 2f8be8f2a37..b62d1b0c6e2 100644
--- a/chromium/cc/trees/de_jelly_state.h
+++ b/chromium/cc/trees/de_jelly_state.h
@@ -7,8 +7,6 @@
#include <map>
-#include "base/containers/flat_map.h"
-#include "base/no_destructor.h"
#include "cc/cc_export.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/transform.h"
diff --git a/chromium/cc/trees/draw_properties_unittest.cc b/chromium/cc/trees/draw_properties_unittest.cc
index 4f1c15cf86c..f982efe46a1 100644
--- a/chromium/cc/trees/draw_properties_unittest.cc
+++ b/chromium/cc/trees/draw_properties_unittest.cc
@@ -3575,21 +3575,22 @@ TEST_F(DrawPropertiesTest, OpacityAnimatingOnPendingTree) {
active_child->effect_tree_index()));
}
-class TransformInteropTest : public DrawPropertiesTestBase,
- public testing::Test {
+class BackfaceVisibilityInteropTest : public DrawPropertiesTestBase,
+ public testing::Test {
public:
- TransformInteropTest() : DrawPropertiesTestBase(TransformInteropSettings()) {}
+ BackfaceVisibilityInteropTest()
+ : DrawPropertiesTestBase(BackfaceVisibilityInteropSettings()) {}
protected:
- LayerTreeSettings TransformInteropSettings() {
+ LayerTreeSettings BackfaceVisibilityInteropSettings() {
LayerListSettings settings;
- settings.enable_transform_interop = true;
+ settings.enable_backface_visibility_interop = true;
return settings;
}
};
-TEST_F(TransformInteropTest, BackfaceInvisibleTransform) {
+TEST_F(BackfaceVisibilityInteropTest, BackfaceInvisibleTransform) {
LayerImpl* root = root_layer();
root->SetDrawsContent(true);
LayerImpl* back_facing = AddLayer<LayerImpl>();
diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc
index b6c84a81c1d..5196b0189dd 100644
--- a/chromium/cc/trees/draw_property_utils.cc
+++ b/chromium/cc/trees/draw_property_utils.cc
@@ -12,11 +12,13 @@
#include "base/containers/adapters.h"
#include "base/containers/stack.h"
#include "base/logging.h"
+#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "cc/layers/draw_properties.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer.h"
+#include "cc/paint/filter_operation.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_impl.h"
@@ -1121,20 +1123,86 @@ void RecordRenderSurfaceReasonsForTracing(
void UpdateElasticOverscroll(
PropertyTrees* property_trees,
TransformNode* overscroll_elasticity_transform_node,
- const gfx::Vector2dF& elastic_overscroll) {
+ ElementId overscroll_elasticity_effect_element_id,
+ const gfx::Vector2dF& elastic_overscroll,
+ const ScrollNode* inner_viewport) {
+#if defined(OS_ANDROID)
+ // On android, elastic overscroll is implemented by stretching the content
+ // from the overscrolled edge.
+ if (!overscroll_elasticity_effect_element_id &&
+ !overscroll_elasticity_transform_node) {
+ DCHECK(elastic_overscroll.IsZero());
+ return;
+ }
+ if (overscroll_elasticity_effect_element_id) {
+ if (elastic_overscroll.IsZero() || !inner_viewport) {
+ property_trees->effect_tree.OnFilterAnimated(
+ overscroll_elasticity_effect_element_id, FilterOperations());
+ return;
+ }
+ // The inner viewport container size takes into account the size change as a
+ // result of the top controls, see ScrollTree::container_bounds.
+ gfx::Size scroller_size =
+ property_trees->scroll_tree.container_bounds(inner_viewport->id);
+
+ property_trees->effect_tree.OnFilterAnimated(
+ overscroll_elasticity_effect_element_id,
+ FilterOperations(
+ std::vector<FilterOperation>({FilterOperation::CreateStretchFilter(
+ -elastic_overscroll.x() / scroller_size.width(),
+ -elastic_overscroll.y() / scroller_size.height())})));
+ return;
+ }
+
+ // If there is no overscroll elasticity effect node, we apply a stretch
+ // transform.
+ overscroll_elasticity_transform_node->local.MakeIdentity();
+ overscroll_elasticity_transform_node->origin.SetPoint(0.f, 0.f, 0.f);
+ overscroll_elasticity_transform_node->to_screen_is_potentially_animated =
+ !elastic_overscroll.IsZero();
+
+ if (!elastic_overscroll.IsZero() && inner_viewport) {
+ // The inner viewport container size takes into account the size change as a
+ // result of the top controls, see ScrollTree::container_bounds.
+ gfx::Size scroller_size =
+ property_trees->scroll_tree.container_bounds(inner_viewport->id);
+
+ overscroll_elasticity_transform_node->local.Scale(
+ 1.f + std::abs(elastic_overscroll.x()) / scroller_size.width(),
+ 1.f + std::abs(elastic_overscroll.y()) / scroller_size.height());
+
+ // If overscrolling to the right, stretch from right.
+ if (elastic_overscroll.x() > 0.f) {
+ overscroll_elasticity_transform_node->origin.set_x(scroller_size.width());
+ }
+
+ // If overscrolling off the bottom, stretch from bottom.
+ if (elastic_overscroll.y() > 0.f) {
+ overscroll_elasticity_transform_node->origin.set_y(
+ scroller_size.height());
+ }
+ }
+ overscroll_elasticity_transform_node->needs_local_transform_update = true;
+ property_trees->transform_tree.set_needs_update(true);
+#else // defined(OS_ANDROID)
if (!overscroll_elasticity_transform_node) {
DCHECK(elastic_overscroll.IsZero());
return;
}
+ // On other platforms, we modify the translation offset to match the
+ // overscroll amount.
if (overscroll_elasticity_transform_node->scroll_offset ==
gfx::ScrollOffset(elastic_overscroll))
return;
overscroll_elasticity_transform_node->scroll_offset =
gfx::ScrollOffset(elastic_overscroll);
+
overscroll_elasticity_transform_node->needs_local_transform_update = true;
property_trees->transform_tree.set_needs_update(true);
+
+#endif // defined(OS_ANDROID)
}
void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list,
@@ -1215,7 +1283,6 @@ bool NodeMayContainBackdropBlurFilter(const EffectNode& node) {
default:
return false;
}
- return false;
}
#endif
@@ -1245,7 +1312,7 @@ bool CC_EXPORT LayerShouldBeSkippedForDrawPropertiesComputation(
if (!transform_node->node_and_ancestors_are_animated_or_invertible ||
!effect_node->is_drawn)
return true;
- if (layer->layer_tree_impl()->settings().enable_transform_interop) {
+ if (layer->layer_tree_impl()->settings().enable_backface_visibility_interop) {
return layer->should_check_backface_visibility() &&
IsLayerBackFaceVisible(layer, layer->transform_tree_index(),
property_trees);
@@ -1257,7 +1324,7 @@ bool CC_EXPORT LayerShouldBeSkippedForDrawPropertiesComputation(
bool CC_EXPORT IsLayerBackFaceVisible(LayerImpl* layer,
int transform_tree_index,
const PropertyTrees* property_trees) {
- if (layer->layer_tree_impl()->settings().enable_transform_interop) {
+ if (layer->layer_tree_impl()->settings().enable_backface_visibility_interop) {
return IsTransformToRootOf3DRenderingContextBackFaceVisible(
layer, transform_tree_index, property_trees);
} else {
@@ -1269,7 +1336,9 @@ bool CC_EXPORT IsLayerBackFaceVisible(LayerImpl* layer,
bool CC_EXPORT IsLayerBackFaceVisible(Layer* layer,
int transform_tree_index,
const PropertyTrees* property_trees) {
- if (layer->layer_tree_host()->GetSettings().enable_transform_interop) {
+ if (layer->layer_tree_host()
+ ->GetSettings()
+ .enable_backface_visibility_interop) {
return IsTransformToRootOf3DRenderingContextBackFaceVisible(
layer, transform_tree_index, property_trees);
} else {
@@ -1446,9 +1515,11 @@ void CalculateDrawProperties(
UpdatePageScaleFactor(property_trees,
layer_tree_impl->PageScaleTransformNode(),
layer_tree_impl->current_page_scale_factor());
- UpdateElasticOverscroll(property_trees,
- layer_tree_impl->OverscrollElasticityTransformNode(),
- layer_tree_impl->current_elastic_overscroll());
+ UpdateElasticOverscroll(
+ property_trees, layer_tree_impl->OverscrollElasticityTransformNode(),
+ layer_tree_impl->OverscrollElasticityEffectElementId(),
+ layer_tree_impl->current_elastic_overscroll(),
+ layer_tree_impl->InnerViewportScrollNode());
// Similarly, the device viewport and device transform are shared
// by both trees.
property_trees->clip_tree.SetViewportClip(
diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc
index bf2aa003a08..704f3ffa0d3 100644
--- a/chromium/cc/trees/effect_node.cc
+++ b/chromium/cc/trees/effect_node.cc
@@ -56,6 +56,7 @@ bool EffectNode::operator==(const EffectNode& other) const {
screen_space_opacity == other.screen_space_opacity &&
backdrop_filter_quality == other.backdrop_filter_quality &&
subtree_capture_id == other.subtree_capture_id &&
+ subtree_size == other.subtree_size &&
cache_render_surface == other.cache_render_surface &&
has_copy_request == other.has_copy_request &&
filters == other.filters &&
@@ -183,14 +184,16 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
}
value->SetString("blend_mode", SkBlendMode_Name(blend_mode));
value->SetString("subtree_capture_id", subtree_capture_id.ToString());
+ value->SetString("subtree_size", subtree_size.ToString());
value->SetBoolean("cache_render_surface", cache_render_surface);
value->SetBoolean("has_copy_request", has_copy_request);
- value->SetBoolean("double_sided", double_sided);
value->SetBoolean("hidden_by_backface_visibility",
hidden_by_backface_visibility);
+ value->SetBoolean("double_sided", double_sided);
value->SetBoolean("trilinear_filtering", trilinear_filtering);
value->SetBoolean("is_drawn", is_drawn);
value->SetBoolean("only_draws_visible_content", only_draws_visible_content);
+ value->SetBoolean("subtree_hidden", subtree_hidden);
value->SetBoolean("has_potential_filter_animation",
has_potential_filter_animation);
value->SetBoolean("has_potential_backdrop_filter_animation",
@@ -200,6 +203,7 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
value->SetBoolean("has_masking_child", has_masking_child);
value->SetBoolean("effect_changed", effect_changed);
value->SetBoolean("subtree_has_copy_request", subtree_has_copy_request);
+ value->SetBoolean("affected_by_backdrop_filter", affected_by_backdrop_filter);
value->SetString("render_surface_reason",
RenderSurfaceReasonToString(render_surface_reason));
value->SetInteger("transform_id", transform_id);
@@ -211,7 +215,6 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const {
closest_ancestor_with_copy_request_id);
value->SetInteger("closest_ancestor_being_captured_id",
closest_ancestor_being_captured_id);
- value->SetBoolean("affected_by_backdrop_filter", affected_by_backdrop_filter);
}
} // namespace cc
diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h
index 682befae955..36c0cfb9ad7 100644
--- a/chromium/cc/trees/effect_node.h
+++ b/chromium/cc/trees/effect_node.h
@@ -10,8 +10,10 @@
#include "cc/paint/element_id.h"
#include "cc/paint/filter_operations.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBlendMode.h"
#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/mask_filter_info.h"
#include "ui/gfx/rrect_f.h"
@@ -95,6 +97,7 @@ struct CC_EXPORT EffectNode {
gfx::Vector2dF surface_contents_scale;
viz::SubtreeCaptureId subtree_capture_id;
+ gfx::Size subtree_size;
bool cache_render_surface : 1;
bool has_copy_request : 1;
diff --git a/chromium/cc/trees/frame_rate_estimator_unittest.cc b/chromium/cc/trees/frame_rate_estimator_unittest.cc
index 03df3952a9b..9aa75eb03d1 100644
--- a/chromium/cc/trees/frame_rate_estimator_unittest.cc
+++ b/chromium/cc/trees/frame_rate_estimator_unittest.cc
@@ -4,7 +4,7 @@
#include "cc/trees/frame_rate_estimator.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.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"
diff --git a/chromium/cc/trees/image_animation_controller.h b/chromium/cc/trees/image_animation_controller.h
index 22776f886f9..361f1fbc512 100644
--- a/chromium/cc/trees/image_animation_controller.h
+++ b/chromium/cc/trees/image_animation_controller.h
@@ -20,7 +20,6 @@
#include "cc/paint/paint_image_generator.h"
#include "cc/tiles/tile_priority.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cc {
class PaintImage;
diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc
index 9a241b6ae4d..cf54a3665fe 100644
--- a/chromium/cc/trees/layer_tree_host.cc
+++ b/chromium/cc/trees/layer_tree_host.cc
@@ -25,7 +25,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -57,7 +56,9 @@
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/mobile_optimized_viewport_util.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/property_tree_builder.h"
#include "cc/trees/proxy_main.h"
#include "cc/trees/render_frame_metadata_observer.h"
@@ -67,6 +68,7 @@
#include "cc/trees/transform_node.h"
#include "cc/trees/tree_synchronizer.h"
#include "cc/trees/ukm_manager.h"
+#include "components/viz/common/features.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/tracing/public/cpp/perfetto/flow_event_utils.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
@@ -158,6 +160,35 @@ LayerTreeHost::LayerTreeHost(InitParams params, CompositorMode mode)
debug_state_.RecordRenderingStats());
}
+bool LayerTreeHost::IsMobileOptimized() const {
+ gfx::SizeF scrollable_viewport_size;
+ auto* inner_node =
+ property_trees()->scroll_tree.Node(viewport_property_ids_.inner_scroll);
+ if (!inner_node)
+ scrollable_viewport_size = gfx::SizeF();
+ else
+ scrollable_viewport_size = gfx::ScaleSize(
+ gfx::SizeF(inner_node->container_bounds),
+ 1.0f / (external_page_scale_factor_ * page_scale_factor()));
+
+ gfx::SizeF scrollable_size;
+ auto* scroll_node =
+ property_trees()->scroll_tree.Node(viewport_property_ids_.outer_scroll);
+ if (!scroll_node) {
+ DCHECK(!inner_node);
+ scrollable_size = gfx::SizeF();
+ } else {
+ const auto& scroll_tree = property_trees()->scroll_tree;
+ auto size = scroll_tree.scroll_bounds(scroll_node->id);
+ size.SetToMax(gfx::SizeF(scroll_tree.container_bounds(scroll_node->id)));
+ scrollable_size = size;
+ }
+
+ return util::IsMobileOptimized(
+ min_page_scale_factor(), max_page_scale_factor(), page_scale_factor(),
+ scrollable_viewport_size, scrollable_size, is_viewport_mobile_optimized_);
+}
+
void LayerTreeHost::InitializeThreaded(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
@@ -604,16 +635,22 @@ void LayerTreeHost::OnDeferMainFrameUpdatesChanged(bool defer_status) {
client_->OnDeferMainFrameUpdatesChanged(defer_status);
}
-void LayerTreeHost::StartDeferringCommits(base::TimeDelta timeout) {
- proxy_->StartDeferringCommits(timeout);
+bool LayerTreeHost::StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) {
+ return proxy_->StartDeferringCommits(timeout, reason);
}
void LayerTreeHost::StopDeferringCommits(PaintHoldingCommitTrigger trigger) {
proxy_->StopDeferringCommits(trigger);
}
-void LayerTreeHost::OnDeferCommitsChanged(bool defer_status) {
- client_->OnDeferCommitsChanged(defer_status);
+bool LayerTreeHost::IsDeferringCommits() const {
+ return proxy_->IsDeferringCommits();
+}
+
+void LayerTreeHost::OnDeferCommitsChanged(bool defer_status,
+ PaintHoldingReason reason) {
+ client_->OnDeferCommitsChanged(defer_status, reason);
}
DISABLE_CFI_PERF
@@ -641,6 +678,11 @@ void LayerTreeHost::SetNeedsCommit() {
events_metrics_manager_.SaveActiveEventMetrics();
}
+void LayerTreeHost::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ proxy_->SetTargetLocalSurfaceId(target_local_surface_id);
+}
+
bool LayerTreeHost::RequestedMainFramePendingForTesting() const {
return proxy_->RequestedAnimatePending();
}
@@ -749,7 +791,7 @@ bool LayerTreeHost::UpdateLayers() {
void LayerTreeHost::DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback) {
for (auto& callback : callbacks)
std::move(callback).Run(feedback);
@@ -974,7 +1016,7 @@ void LayerTreeHost::UpdateScrollOffsetFromImpl(
SetNeedsUpdateLayers();
}
- scroll_tree.NotifyDidScroll(id, new_offset, snap_target_ids);
+ scroll_tree.NotifyDidCompositorScroll(id, new_offset, snap_target_ids);
} else if (Layer* layer = LayerByElementId(id)) {
layer->SetScrollOffsetFromImplSide(layer->scroll_offset() + delta);
SetNeedsUpdateLayers();
@@ -1122,7 +1164,7 @@ bool LayerTreeHost::IsThreaded() const {
}
void LayerTreeHost::RequestPresentationTimeForNextFrame(
- PresentationTimeCallback callback) {
+ PresentationTimeCallbackBuffer::MainCallback callback) {
pending_presentation_time_callbacks_.push_back(std::move(callback));
}
@@ -1269,6 +1311,13 @@ void LayerTreeHost::SetViewportRectAndScale(
}
}
+ // If a new viz::LocalSurfaceId has been provided, and the viewport has
+ // changed, we need not begin new frames until it has activated.
+ if (previous_local_surface_id != local_surface_id_from_parent &&
+ device_viewport_rect_changed && features::IsSurfaceSyncThrottling()) {
+ SetTargetLocalSurfaceId(local_surface_id_from_parent);
+ }
+
if (device_viewport_rect_changed || painted_device_scale_factor_changed ||
device_scale_factor_changed) {
SetPropertyTreesNeedRebuild();
@@ -1381,6 +1430,13 @@ void LayerTreeHost::UpdateViewportIsMobileOptimized(
SetNeedsCommit();
}
+void LayerTreeHost::SetPrefersReducedMotion(bool prefers_reduced_motion) {
+ if (prefers_reduced_motion_ == prefers_reduced_motion)
+ return;
+ prefers_reduced_motion_ = prefers_reduced_motion;
+ SetNeedsCommit();
+}
+
void LayerTreeHost::SetExternalPageScaleFactor(
float page_scale_factor,
bool is_external_pinch_gesture_active) {
@@ -1692,6 +1748,7 @@ void LayerTreeHost::PushLayerTreeHostPropertiesTo(
host_impl->SetDebugState(debug_state_);
host_impl->SetVisualDeviceViewportSize(visual_device_viewport_size_);
host_impl->set_viewport_mobile_optimized(is_viewport_mobile_optimized_);
+ host_impl->SetPrefersReducedMotion(prefers_reduced_motion_);
}
Layer* LayerTreeHost::LayerByElementId(ElementId element_id) const {
diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h
index cefbb821f75..48b503c5ecf 100644
--- a/chromium/cc/trees/layer_tree_host.h
+++ b/chromium/cc/trees/layer_tree_host.h
@@ -41,12 +41,14 @@
#include "cc/metrics/frame_sequence_tracker.h"
#include "cc/metrics/web_vital_metrics.h"
#include "cc/paint/node_id.h"
+#include "cc/trees//presentation_time_callback_buffer.h"
#include "cc/trees/browser_controls_params.h"
#include "cc/trees/compositor_mode.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy.h"
#include "cc/trees/swap_promise.h"
#include "cc/trees/swap_promise_manager.h"
@@ -243,6 +245,12 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// synchronization.
virtual void SetNeedsCommit();
+ // Notifies that a new viz::LocalSurfaceId has been set, ahead of it becoming
+ // activated. Requests that the compositor thread does not produce new frames
+ // until it has activated.
+ virtual void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id);
+
// Returns true after SetNeedsAnimate(), SetNeedsUpdateLayers() or
// SetNeedsCommit(), until it is satisfied.
bool RequestedMainFramePendingForTesting() const;
@@ -267,13 +275,17 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// is the interval after which commits will restart if nothing stops
// deferring sooner. If multiple calls are made to StartDeferringCommits
// while deferal is active, the first timeout continues to apply.
- void StartDeferringCommits(base::TimeDelta timeout);
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason);
// Stop deferring commits immediately.
void StopDeferringCommits(PaintHoldingCommitTrigger);
+ // Returns true if commits are currently deferred.
+ bool IsDeferringCommits() const;
+
// Notification that the proxy started or stopped deferring commits.
- void OnDeferCommitsChanged(bool);
+ void OnDeferCommitsChanged(bool defer_status, PaintHoldingReason reason);
// Returns whether there are any outstanding ScopedDeferMainFrameUpdate,
// though commits may be deferred also when the local_surface_id_from_parent()
@@ -332,9 +344,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// Registers a callback that is run when the next frame successfully makes it
// to the screen (it's entirely possible some frames may be dropped between
// the time this is called and the callback is run).
- using PresentationTimeCallback =
- base::OnceCallback<void(const gfx::PresentationFeedback&)>;
- void RequestPresentationTimeForNextFrame(PresentationTimeCallback callback);
+ void RequestPresentationTimeForNextFrame(
+ PresentationTimeCallbackBuffer::MainCallback callback);
// Registers a callback that is run when any ongoing scroll-animation ends. If
// there are no ongoing animations, then the callback is run immediately.
@@ -351,6 +362,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
struct ViewportPropertyIds {
int overscroll_elasticity_transform = TransformTree::kInvalidNodeId;
+ ElementId overscroll_elasticity_effect;
int page_scale_transform = TransformTree::kInvalidNodeId;
int inner_scroll = ScrollTree::kInvalidNodeId;
int outer_clip = ClipTree::kInvalidNodeId;
@@ -429,6 +441,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void UpdateViewportIsMobileOptimized(bool is_viewport_mobile_optimized);
+ // Returns if the viewport is considered to be mobile optimized.
+ bool IsMobileOptimized() const;
+
+ void SetPrefersReducedMotion(bool prefers_reduced_motion);
+
void SetBrowserControlsParams(const BrowserControlsParams& params);
void SetBrowserControlsShownRatio(float top_ratio, float bottom_ratio);
@@ -621,7 +638,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
bool UpdateLayers();
void DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback);
// Called when the compositor completed page scale animation.
void DidCompletePageScaleAnimation();
@@ -900,6 +917,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// <meta name="viewport" content="initial-scale=1.0">
bool is_viewport_mobile_optimized_ = false;
+ bool prefers_reduced_motion_ = false;
bool have_scroll_event_handlers_ = false;
EventListenerProperties event_listener_properties_
[static_cast<size_t>(EventListenerClass::kLast) + 1];
@@ -951,7 +969,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// Presentation time callbacks requested for the next frame are initially
// added here.
- std::vector<PresentationTimeCallback> pending_presentation_time_callbacks_;
+ std::vector<PresentationTimeCallbackBuffer::MainCallback>
+ pending_presentation_time_callbacks_;
struct ScrollAnimationState {
ScrollAnimationState();
diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h
index f411eefcfa5..00f3e63fd42 100644
--- a/chromium/cc/trees/layer_tree_host_client.h
+++ b/chromium/cc/trees/layer_tree_host_client.h
@@ -11,6 +11,7 @@
#include "base/time/time.h"
#include "cc/input/browser_controls_state.h"
#include "cc/metrics/frame_sequence_tracker_collection.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/property_tree.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -119,8 +120,10 @@ class LayerTreeHostClient {
// Notification that the proxy started or stopped deferring main frame updates
virtual void OnDeferMainFrameUpdatesChanged(bool) = 0;
- // Notification that the proxy started or stopped deferring commits.
- virtual void OnDeferCommitsChanged(bool) = 0;
+ // Notification that the proxy started or stopped deferring commits. |reason|
+ // indicates why commits are/were deferred.
+ virtual void OnDeferCommitsChanged(bool defer_status,
+ PaintHoldingReason reason) = 0;
// Visual frame-based updates to the state of the LayerTreeHost are expected
// to happen only in calls to LayerTreeHostClient::UpdateLayerTreeHost, which
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index 78addb27c8e..63f61838cbf 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -93,6 +93,7 @@
#include "cc/trees/latency_info_swap_promise_monitor.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/mobile_optimized_viewport_util.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/presentation_time_callback_buffer.h"
#include "cc/trees/render_frame_metadata.h"
@@ -142,10 +143,11 @@ using ScrollThread = cc::InputHandler::ScrollThread;
namespace cc {
namespace {
-// Used to accommodate finite precision when comparing scaled viewport and
-// content widths. While this value may seem large, width=device-width on an N7
-// V1 saw errors of ~0.065 between computed window and content widths.
-const float kMobileViewportWidthEpsilon = 0.15f;
+// The threshold which determines at what point during a scroll, should the
+// tree priority change from SMOOTHNESS_TAKES_PRIORITY to
+// NEW_CONTENT_TAKES_PRIORITY. The threshold represents visible checkerboarded
+// area.
+const float kVisibleCheckerboardedThresholdForPreferNewContent = 0.3f;
// In BuildHitTestData we iterate all layers to find all layers that overlap
// OOPIFs, but when the number of layers is greater than
@@ -161,25 +163,13 @@ static_assert(kContainsSrgbCacheSize ==
gfx::DisplayColorSpaces::kConfigCount / 2,
"sRGB cache must match the size of DisplayColorSpaces");
-bool HasFixedPageScale(LayerTreeImpl* active_tree) {
- return active_tree->min_page_scale_factor() ==
- active_tree->max_page_scale_factor();
-}
-
-bool HasMobileViewport(LayerTreeImpl* active_tree) {
- float window_width_dip = active_tree->current_page_scale_factor() *
- active_tree->ScrollableViewportSize().width();
- float content_width_css = active_tree->ScrollableSize().width();
- return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
-}
-
bool IsMobileOptimized(LayerTreeImpl* active_tree) {
- bool has_mobile_viewport = HasMobileViewport(active_tree);
- bool has_fixed_page_scale = HasFixedPageScale(active_tree);
- return has_fixed_page_scale || has_mobile_viewport ||
- (base::FeatureList::IsEnabled(
- ::features::kRemoveMobileViewportDoubleTap) &&
- active_tree->viewport_mobile_optimized());
+ return util::IsMobileOptimized(active_tree->min_page_scale_factor(),
+ active_tree->max_page_scale_factor(),
+ active_tree->current_page_scale_factor(),
+ active_tree->ScrollableViewportSize(),
+ active_tree->ScrollableSize(),
+ active_tree->viewport_mobile_optimized());
}
viz::ResourceFormat TileRasterBufferFormat(
@@ -244,16 +234,16 @@ void ApplyFirstScrollTracking(const ui::LatencyInfo* latency,
return;
}
- // Construct a callback that, given presentation feedback, will report the
- // time span between the scroll input-event creation and the
+ // Construct a callback that, given a successful presentation timestamp, will
+ // report the time span between the scroll input-event creation and the
// presentation timestamp.
- LayerTreeHost::PresentationTimeCallback presentation_callback =
+ PresentationTimeCallbackBuffer::CompositorCallback presentation_callback =
base::BindOnce(
[](base::TimeTicks event_creation,
LayerTreeHostImpl* layer_tree_host_impl,
- const gfx::PresentationFeedback& feedback) {
+ base::TimeTicks presentation_timestamp) {
layer_tree_host_impl->DidObserveScrollDelay(
- feedback.timestamp - event_creation, event_creation);
+ presentation_timestamp - event_creation, event_creation);
},
creation_timestamp, impl);
@@ -334,6 +324,7 @@ void LayerTreeHostImpl::DidStartScroll() {
void LayerTreeHostImpl::DidEndScroll() {
scroll_affects_scroll_handler_ = false;
+ current_scroll_did_checkerboard_large_area_ = false;
}
void LayerTreeHostImpl::DidMouseLeave() {
@@ -1026,9 +1017,9 @@ void LayerTreeHostImpl::FrameData::AsValueInto(
}
if (quads_enabled) {
value->BeginArray("render_passes");
- for (size_t i = 0; i < render_passes.size(); ++i) {
+ for (const auto& render_pass : render_passes) {
value->BeginDictionary();
- render_passes[i]->AsValueInto(value);
+ render_pass->AsValueInto(value);
value->EndDictionary();
}
value->EndArray();
@@ -1290,6 +1281,9 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
layer->transform_tree_index(),
target_render_pass);
}
+ } else {
+ if (settings_.enable_compositing_based_throttling)
+ throttle_decider_.ProcessLayerNotToDraw(layer);
}
rendering_stats_instrumentation_->AddVisibleContentArea(
@@ -1331,6 +1325,18 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
append_quads_data.use_default_lower_bound_deadline;
}
+ if (total_visible_area > 0 &&
+ GetActivelyScrollingType() != ActivelyScrollingType::kNone) {
+ float visible_area_checkerboarded_ratio =
+ (checkerboarded_no_recording_content_area +
+ checkerboarded_needs_raster_content_area) /
+ total_visible_area;
+ if (visible_area_checkerboarded_ratio >
+ kVisibleCheckerboardedThresholdForPreferNewContent) {
+ SetCurrentScrollDidCheckerboardLargeArea();
+ }
+ }
+
// If CommitToActiveTree() is true, then we wait to draw until
// NotifyReadyToDraw. That means we're in as good shape as is possible now,
// so there's no reason to stop the draw now (and this is not supported by
@@ -1509,13 +1515,13 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
UMA_HISTOGRAM_CUSTOM_COUNTS(
base::StringPrintf("Compositing.%s.NumActiveLayers", client_name),
- base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
+ base::saturated_cast<int>(active_tree_->NumLayers()), 1, 1000, 20);
UMA_HISTOGRAM_CUSTOM_COUNTS(
base::StringPrintf("Compositing.%s.NumActivePictureLayers",
client_name),
base::saturated_cast<int>(active_tree_->picture_layers().size()), 1,
- 400, 20);
+ 1000, 20);
// TODO(pdr): Instead of skipping empty picture layers, maybe we should
// accumulate layer->GetRasterSource()->GetMemoryUsage() above and skip
@@ -1752,6 +1758,11 @@ void LayerTreeHostImpl::DidModifyTilePriorities() {
client_->SetNeedsPrepareTilesOnImplThread();
}
+void LayerTreeHostImpl::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ target_local_surface_id_ = target_local_surface_id;
+}
+
std::unique_ptr<RasterTilePriorityQueue> LayerTreeHostImpl::BuildRasterQueue(
TreePriority tree_priority,
RasterTilePriorityQueue::Type type) {
@@ -2041,8 +2052,14 @@ void LayerTreeHostImpl::DidReceiveCompositorFrameAck() {
void LayerTreeHostImpl::DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details) {
+ // Presentation callbacks registered on the compositor thread are expected to
+ // be called on the first successful presentation. So, if the presentation is
+ // failed, we only pop main thread callbacks at this point and leave
+ // compositor thread callbacks alone until a successful presentation.
+ const bool main_callbacks_only = details.presentation_feedback.failed();
PresentationTimeCallbackBuffer::PendingCallbacks activated_callbacks =
- presentation_time_callbacks_.PopPendingCallbacks(frame_token);
+ presentation_time_callbacks_.PopPendingCallbacks(frame_token,
+ main_callbacks_only);
// Send all tasks to the client so that it can decide which tasks
// should run on which thread.
@@ -2426,7 +2443,8 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) {
active_tree_->ResetAllChangeTracking();
active_tree_->set_has_ever_been_drawn(true);
- devtools_instrumentation::DidDrawFrame(id_);
+ devtools_instrumentation::DidDrawFrame(
+ id_, frame->begin_frame_ack.frame_id.sequence_number);
benchmark_instrumentation::IssueImplThreadRenderingStatsEvent(
rendering_stats_instrumentation_->TakeImplThreadRenderingStats());
@@ -2811,20 +2829,20 @@ void LayerTreeHostImpl::UpdateTreeResourcesForGpuRasterizationIfNeeded() {
SetRequiresHighResToDraw();
}
-void LayerTreeHostImpl::RegisterMainThreadPresentationTimeCallback(
+void LayerTreeHostImpl::RegisterMainThreadPresentationTimeCallbackForTesting(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback) {
- std::vector<LayerTreeHost::PresentationTimeCallback> as_vector;
- as_vector.emplace_back(std::move(callback));
+ PresentationTimeCallbackBuffer::MainCallback callback) {
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> as_vector;
+ as_vector.push_back(std::move(callback));
presentation_time_callbacks_.RegisterMainThreadPresentationCallbacks(
frame_token, std::move(as_vector));
}
void LayerTreeHostImpl::RegisterCompositorPresentationTimeCallback(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback) {
- std::vector<LayerTreeHost::PresentationTimeCallback> as_vector;
- as_vector.emplace_back(std::move(callback));
+ PresentationTimeCallbackBuffer::CompositorCallback callback) {
+ std::vector<PresentationTimeCallbackBuffer::CompositorCallback> as_vector;
+ as_vector.push_back(std::move(callback));
presentation_time_callbacks_.RegisterCompositorPresentationCallbacks(
frame_token, std::move(as_vector));
}
@@ -2834,11 +2852,27 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
current_begin_frame_tracker_.Start(args);
frame_trackers_.NotifyBeginImplFrame(args);
total_frame_counter_.OnBeginFrame(args);
- devtools_instrumentation::DidBeginFrame(id_, args.frame_time);
+ devtools_instrumentation::DidBeginFrame(id_, args.frame_time,
+ args.frame_id.sequence_number);
UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.AcceleratedSurfaceRefreshRate",
1 / args.interval.InSecondsF(), 0, 121, 122);
+ // When there is a |target_local_surface_id_|, we do not wish to begin
+ // producing Impl Frames for an older viz::LocalSurfaceId, as it will never
+ // be displayed.
+ //
+ // Once the Main thread has finished adjusting to the new visual properties,
+ // it will push the updated viz::LocalSurfaceId. Begin Impl Frame production
+ // if it has already become activated, or is on the |pending_tree| to be
+ // activated during this frame's production.
+ const viz::LocalSurfaceId& upcoming_lsid =
+ pending_tree() ? pending_tree()->local_surface_id_from_parent()
+ : active_tree()->local_surface_id_from_parent();
+ if (target_local_surface_id_.IsNewerThan(upcoming_lsid)) {
+ return false;
+ }
+
if (is_likely_to_require_a_draw_) {
// Optimistically schedule a draw. This will let us expect the tile manager
// to complete its work so that we can draw new tiles within the impl frame
@@ -3139,8 +3173,9 @@ void LayerTreeHostImpl::CreatePendingTree() {
pending_tree_fully_painted_ = false;
client_->OnCanDrawStateChanged(CanDraw());
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "PendingTree:waiting",
- TRACE_ID_LOCAL(pending_tree_.get()));
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "cc", "PendingTree:waiting", TRACE_ID_LOCAL(pending_tree_.get()),
+ "active_lsid", active_tree()->local_surface_id_from_parent().ToString());
}
void LayerTreeHostImpl::PushScrollbarOpacitiesFromActiveToPending() {
@@ -3174,8 +3209,10 @@ void LayerTreeHostImpl::PushScrollbarOpacitiesFromActiveToPending() {
void LayerTreeHostImpl::ActivateSyncTree() {
TRACE_EVENT0("cc,benchmark", "LayerTreeHostImpl::ActivateSyncTree()");
if (pending_tree_) {
- TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "PendingTree:waiting",
- TRACE_ID_LOCAL(pending_tree_.get()));
+ TRACE_EVENT_NESTABLE_ASYNC_END1(
+ "cc", "PendingTree:waiting", TRACE_ID_LOCAL(pending_tree_.get()),
+ "pending_lsid",
+ pending_tree_->local_surface_id_from_parent().ToString());
active_tree_->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync);
// In most cases, this will be reset in NotifyReadyToActivate, since we
@@ -3965,6 +4002,7 @@ float LayerTreeHostImpl::PageScaleFactor() const {
void LayerTreeHostImpl::BindToInputHandler(
std::unique_ptr<InputDelegateForCompositor> delegate) {
input_delegate_ = std::move(delegate);
+ input_delegate_->SetPrefersReducedMotion(prefers_reduced_motion_);
}
void LayerTreeHostImpl::SetVisualDeviceViewportSize(
@@ -3976,6 +4014,15 @@ gfx::Size LayerTreeHostImpl::VisualDeviceViewportSize() const {
return visual_device_viewport_size_;
}
+void LayerTreeHostImpl::SetPrefersReducedMotion(bool prefers_reduced_motion) {
+ if (prefers_reduced_motion_ == prefers_reduced_motion)
+ return;
+
+ prefers_reduced_motion_ = prefers_reduced_motion;
+ if (input_delegate_)
+ input_delegate_->SetPrefersReducedMotion(prefers_reduced_motion_);
+}
+
ScrollTree& LayerTreeHostImpl::GetScrollTree() const {
return active_tree_->property_trees()->scroll_tree;
}
@@ -4944,13 +4991,12 @@ void LayerTreeHostImpl::SetUkmSmoothnessDestination(
void LayerTreeHostImpl::NotifyDidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::CompositorCallback> callbacks,
const viz::FrameTimingDetails& details) {
frame_trackers_.NotifyFramePresented(frame_token,
details.presentation_feedback);
- for (LayerTreeHost::PresentationTimeCallback& callback : callbacks) {
- std::move(callback).Run(details.presentation_feedback);
- }
+ for (auto& callback : callbacks)
+ std::move(callback).Run(details.presentation_feedback.timestamp);
}
void LayerTreeHostImpl::AllocateLocalSurfaceId() {
diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h
index bf8b7a8a7bd..1d79f4bfaf2 100644
--- a/chromium/cc/trees/layer_tree_host_impl.h
+++ b/chromium/cc/trees/layer_tree_host_impl.h
@@ -403,6 +403,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
return is_viewport_mobile_optimized_;
}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion);
+
// Updates registered ElementIds present in |changed_list|. Call this after
// changing the property trees for the |changed_list| trees.
void UpdateElements(ElementListType changed_list);
@@ -601,27 +603,37 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
uint32_t next_frame_token() const { return *next_frame_token_; }
- // Buffers |callback| until a relevant frame swap ocurrs, at which point the
- // callback will be posted to run on the main thread. A frame swap is
- // considered relevant if the swapped frame's token is greater than or equal
- // to |frame_token|.
- void RegisterMainThreadPresentationTimeCallback(
+ // Buffers `callback` until a relevant presentation feedback arrives, at which
+ // point the callback will be posted to run on the main thread. A presentation
+ // feedback is considered relevant if the frame's token is greater than or
+ // equal to `frame_token`.
+ void RegisterMainThreadPresentationTimeCallbackForTesting(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback);
+ PresentationTimeCallbackBuffer::MainCallback callback);
- // Buffers |callback| until a relevant frame swap ocurrs, at which point the
- // callback will be run on the compositor thread. A frame swap is considered
- // relevant if the swapped frame's token is greater than or equal to
- // |frame_token|.
+ // Buffers `callback` until a relevant successful presentation occurs, at
+ // which point the callback will be run on the compositor thread. A successful
+ // presentation is considered relevant if the presented frame's token is
+ // greater than or equal to `frame_token`.
void RegisterCompositorPresentationTimeCallback(
uint32_t frame_token,
- LayerTreeHost::PresentationTimeCallback callback);
+ PresentationTimeCallbackBuffer::CompositorCallback callback);
virtual bool WillBeginImplFrame(const viz::BeginFrameArgs& args);
virtual void DidFinishImplFrame(const viz::BeginFrameArgs& args);
void DidNotProduceFrame(const viz::BeginFrameAck& ack,
FrameSkippedReason reason);
void DidModifyTilePriorities();
+ // Requests that we do not produce frames until the new viz::LocalSurfaceId
+ // has been activated.
+ void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id);
+ const viz::LocalSurfaceId& target_local_surface_id() const {
+ return target_local_surface_id_;
+ }
+ const viz::LocalSurfaceId& last_draw_local_surface_id() const {
+ return last_draw_local_surface_id_;
+ }
LayerTreeImpl* active_tree() { return active_tree_.get(); }
const LayerTreeImpl* active_tree() const { return active_tree_.get(); }
@@ -651,6 +663,12 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// See comment in equivalent ThreadedInputHandler method for what this means.
ActivelyScrollingType GetActivelyScrollingType() const;
bool ScrollAffectsScrollHandler() const;
+ bool CurrentScrollDidCheckerboardLargeArea() const {
+ return current_scroll_did_checkerboard_large_area_;
+ }
+ void SetCurrentScrollDidCheckerboardLargeArea() {
+ current_scroll_did_checkerboard_large_area_ = true;
+ }
void SetExternalPinchGestureActive(bool active);
void set_force_smooth_wheel_scrolling_for_testing(bool enabled) {
GetInputHandler().set_force_smooth_wheel_scrolling_for_testing(enabled);
@@ -820,7 +838,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// was presented.
void NotifyDidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::CompositorCallback> callbacks,
const viz::FrameTimingDetails& details);
CompositorFrameReportingController* compositor_frame_reporting_controller()
@@ -855,6 +873,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
return pending_raster_queries_.get();
}
+ base::flat_set<viz::FrameSinkId> GetFrameSinksToThrottleForTesting() const {
+ return throttle_decider_.ids();
+ }
+
protected:
LayerTreeHostImpl(
const LayerTreeSettings& settings,
@@ -1156,6 +1178,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// <meta name="viewport" content="initial-scale=1.0">
bool is_viewport_mobile_optimized_ = false;
+ bool prefers_reduced_motion_ = false;
+
std::unique_ptr<PendingTreeRasterDurationHistogramTimer>
pending_tree_raster_duration_timer_;
@@ -1183,6 +1207,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
viz::LocalSurfaceId last_draw_local_surface_id_;
base::flat_set<viz::SurfaceRange> last_draw_referenced_surfaces_;
absl::optional<RenderFrameMetadata> last_draw_render_frame_metadata_;
+ // The viz::LocalSurfaceId to unthrottle drawing for.
+ viz::LocalSurfaceId target_local_surface_id_;
viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_;
// Indicates the direction of the last vertical scroll of the root layer.
@@ -1220,6 +1246,11 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
// sophisticated since so it's not clear how much value it's still providing.
bool scroll_affects_scroll_handler_ = false;
+ // Whether at least 30% of the viewport at the time of draw was
+ // checkerboarded during a scroll. This bit can get set during a scroll and
+ // is sticky for the duration of the scroll.
+ bool current_scroll_did_checkerboard_large_area_ = false;
+
// Provides support for PaintWorklets which depend on input properties that
// are being animated by the compositor (aka 'animated' PaintWorklets).
// Responsible for storing animated custom property values and for
diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
index e937bb490aa..19a4006dd4a 100644
--- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc
@@ -264,7 +264,9 @@ class LayerTreeHostImplTest : public testing::Test,
uint32_t frame_token,
PresentationTimeCallbackBuffer::PendingCallbacks activated,
const viz::FrameTimingDetails& details) override {
- std::move(activated.main_thread_callbacks);
+ // We don't call main thread callbacks in this test.
+ activated.main_thread_callbacks.clear();
+
host_impl_->NotifyDidPresentCompositorFrameOnImplThread(
frame_token, std::move(activated.compositor_thread_callbacks), details);
}
@@ -891,6 +893,16 @@ class CommitToPendingTreeLayerTreeHostImplTest : public LayerTreeHostImplTest {
}
};
+class OccludedSurfaceThrottlingLayerTreeHostImplTest
+ : public LayerTreeHostImplTest {
+ public:
+ void SetUp() override {
+ LayerTreeSettings settings = DefaultSettings();
+ settings.enable_compositing_based_throttling = true;
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+ }
+};
+
// A test fixture for new animation timelines tests.
class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest {
public:
@@ -916,6 +928,7 @@ class TestInputHandlerClient : public InputHandlerClient {
void WillShutdown() override {}
void Animate(base::TimeTicks time) override {}
void ReconcileElasticOverscrollAndRootScroll() override {}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override {}
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -1679,10 +1692,8 @@ class LayerTreeHostImplTestInvokeMainThreadCallbacks
auto main_thread_callbacks = std::move(activated.main_thread_callbacks);
host_impl_->NotifyDidPresentCompositorFrameOnImplThread(
frame_token, std::move(activated.compositor_thread_callbacks), details);
- for (LayerTreeHost::PresentationTimeCallback& callback :
- main_thread_callbacks) {
+ for (auto& callback : main_thread_callbacks)
std::move(callback).Run(details.presentation_feedback);
- }
}
};
@@ -1692,25 +1703,27 @@ TEST_F(LayerTreeHostImplTestInvokeMainThreadCallbacks,
PresentationFeedbackCallbacksFire) {
bool compositor_thread_callback_fired = false;
bool main_thread_callback_fired = false;
- gfx::PresentationFeedback feedback_seen_by_compositor_thread_callback;
+ base::TimeTicks presentation_time_seen_by_compositor_thread_callback;
gfx::PresentationFeedback feedback_seen_by_main_thread_callback;
// Register a compositor-thread callback to run when the frame for
// |frame_token_1| gets presented.
constexpr uint32_t frame_token_1 = 1;
host_impl_->RegisterCompositorPresentationTimeCallback(
- frame_token_1, base::BindLambdaForTesting(
- [&](const gfx::PresentationFeedback& feedback) {
- compositor_thread_callback_fired = true;
- feedback_seen_by_compositor_thread_callback =
- feedback;
- }));
+ frame_token_1,
+ base::BindLambdaForTesting([&](base::TimeTicks presentation_timestamp) {
+ DCHECK(presentation_time_seen_by_compositor_thread_callback.is_null());
+ DCHECK(!presentation_timestamp.is_null());
+ compositor_thread_callback_fired = true;
+ presentation_time_seen_by_compositor_thread_callback =
+ presentation_timestamp;
+ }));
// Register a main-thread callback to run when the frame for |frame_token_2|
// gets presented.
constexpr uint32_t frame_token_2 = 2;
ASSERT_GT(frame_token_2, frame_token_1);
- host_impl_->RegisterMainThreadPresentationTimeCallback(
+ host_impl_->RegisterMainThreadPresentationTimeCallbackForTesting(
frame_token_2, base::BindLambdaForTesting(
[&](const gfx::PresentationFeedback& feedback) {
main_thread_callback_fired = true;
@@ -1723,8 +1736,8 @@ TEST_F(LayerTreeHostImplTestInvokeMainThreadCallbacks,
host_impl_->DidPresentCompositorFrame(frame_token_1, mock_details);
EXPECT_TRUE(compositor_thread_callback_fired);
- EXPECT_EQ(feedback_seen_by_compositor_thread_callback,
- mock_details.presentation_feedback);
+ EXPECT_EQ(presentation_time_seen_by_compositor_thread_callback,
+ mock_details.presentation_feedback.timestamp);
// Since |frame_token_2| is strictly greater than |frame_token_1|, the
// main-thread callback must remain queued for now.
@@ -3242,7 +3255,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollNodeWithoutScrollLayer) {
EXPECT_FALSE(status.needs_main_thread_hit_test);
} else {
EXPECT_EQ(ScrollThread::SCROLL_ON_MAIN_THREAD, status.thread);
- EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
+ EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer,
status.main_thread_scrolling_reasons);
}
}
@@ -3461,22 +3474,88 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest,
class MissingTilesLayer : public LayerImpl {
public:
- MissingTilesLayer(LayerTreeImpl* layer_tree_impl, int id)
- : LayerImpl(layer_tree_impl, id), has_missing_tiles_(true) {}
-
- void set_has_missing_tiles(bool has_missing_tiles) {
- has_missing_tiles_ = has_missing_tiles;
+ static std::unique_ptr<MissingTilesLayer> Create(LayerTreeImpl* tree_impl,
+ int id) {
+ return base::WrapUnique(new MissingTilesLayer(tree_impl, id));
}
+ MissingTilesLayer(LayerTreeImpl* layer_tree_impl, int id)
+ : LayerImpl(layer_tree_impl, id) {}
void AppendQuads(viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data) override {
- append_quads_data->num_missing_tiles += has_missing_tiles_;
+ append_quads_data->num_missing_tiles += 10;
+ append_quads_data->checkerboarded_no_recording_content_area += 200;
+ append_quads_data->checkerboarded_needs_raster_content_area += 200;
+ append_quads_data->visible_layer_area += 200;
}
-
- private:
- bool has_missing_tiles_;
};
+TEST_P(ScrollUnifiedLayerTreeHostImplTest,
+ CurrentScrollDidCheckerboardLargeArea) {
+ LayerTreeSettings settings = DefaultSettings();
+ CreateHostImpl(settings, CreateLayerTreeFrameSink());
+ host_impl_->active_tree()->PushPageScaleFromMainThread(1, 0.25f, 4);
+
+ const gfx::Size content_size(1000, 1000);
+ const gfx::Size viewport_size(500, 500);
+ SetupViewportLayersOuterScrolls(viewport_size, content_size);
+
+ LayerImpl* outer_scroll_layer = OuterViewportScrollLayer();
+ outer_scroll_layer->SetDrawsContent(true);
+ LayerImpl* inner_scroll_layer = InnerViewportScrollLayer();
+ inner_scroll_layer->SetDrawsContent(true);
+
+ // Add layer that draws content and has checkerboarded areas.
+ auto* scroll_layer = AddLayer<MissingTilesLayer>(host_impl_->active_tree());
+ CopyProperties(inner_scroll_layer, scroll_layer);
+ scroll_layer->SetBounds(gfx::Size(500, 500));
+ scroll_layer->SetDrawsContent(true);
+ scroll_layer->SetHitTestable(false);
+ host_impl_->active_tree()->SetElementIdsForTesting();
+
+ UpdateDrawProperties(host_impl_->active_tree());
+
+ DrawFrame();
+
+ // No scroll has taken place so this should be false.
+ EXPECT_FALSE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+
+ // Send scroll begin.
+ GetInputHandler().ScrollBegin(
+ BeginState(gfx::Point(250, 250), gfx::Vector2dF(),
+ ui::ScrollInputType::kTouchscreen)
+ .get(),
+ ui::ScrollInputType::kTouchscreen);
+
+ DrawFrame();
+
+ // Even though a ScrollBegin has been processed, we still don't consider the
+ // interaction to be "actively scrolling". Expect this to be false.
+ EXPECT_FALSE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+
+ gfx::ScrollOffset scroll_delta(0, 10);
+
+ // Send scroll update.
+ GetInputHandler().ScrollUpdate(
+ UpdateState(gfx::Point(10, 10),
+ gfx::ScrollOffsetToVector2dF(scroll_delta),
+ ui::ScrollInputType::kWheel)
+ .get());
+
+ host_impl_->SetFullViewportDamage();
+ DrawFrame();
+
+ // Now that a scroll update has been processed and the latest
+ // CalculateRenderPasses run has computed significant visible checkerboarding,
+ // expect this flag to be true.
+ EXPECT_TRUE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+
+ GetInputHandler().ScrollEnd();
+
+ // Expect state to be reset after a scroll end.
+ EXPECT_FALSE(host_impl_->CurrentScrollDidCheckerboardLargeArea());
+}
+
TEST_P(ScrollUnifiedLayerTreeHostImplTest, ImplPinchZoom) {
SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100));
DrawFrame();
@@ -11668,7 +11747,8 @@ TEST_P(LayerTreeHostImplTestWithRenderer, ShutdownReleasesContext) {
GetPropertyTrees(root)->effect_tree.AddCopyRequest(
root->effect_tree_index(),
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kNativeTextures,
base::BindOnce(&Helper::OnResult, base::Unretained(&helper),
copy_request_run_loop.QuitClosure())));
DrawFrame();
@@ -12017,7 +12097,7 @@ class LayerTreeHostImplWithBrowserControlsTest : public LayerTreeHostImplTest {
settings.commit_to_active_tree = false;
CreateHostImpl(settings, CreateLayerTreeFrameSink());
host_impl_->active_tree()->SetBrowserControlsParams(
- {top_controls_height_, 0, 0, 0, false, false});
+ {static_cast<float>(top_controls_height_), 0, 0, 0, false, false});
host_impl_->active_tree()->SetCurrentBrowserControlsShownRatio(1.f, 1.f);
}
@@ -18083,6 +18163,33 @@ TEST_F(UnifiedScrollingTest, CompositedWithSquashedLayerMutatesTransform) {
ScrollEnd();
}
+// Verifies that when a surface layer is occluded, its frame sink id will be
+// marked as qualified for throttling.
+TEST_F(OccludedSurfaceThrottlingLayerTreeHostImplTest,
+ ThrottleOccludedSurface) {
+ LayerTreeImpl* tree = host_impl_->active_tree();
+ gfx::Rect viewport_rect(0, 0, 800, 600);
+ auto* root = SetupRootLayer<LayerImpl>(tree, viewport_rect.size());
+
+ auto* occluded = AddLayer<SurfaceLayerImpl>(tree);
+ occluded->SetBounds(gfx::Size(400, 300));
+ occluded->SetDrawsContent(true);
+ viz::SurfaceId start = MakeSurfaceId(viz::FrameSinkId(1, 2), 1);
+ viz::SurfaceId end = MakeSurfaceId(viz::FrameSinkId(3, 4), 1);
+ occluded->SetRange(viz::SurfaceRange(start, end), 2u);
+ CopyProperties(root, occluded);
+
+ auto* occluder = AddLayer<SolidColorLayerImpl>(tree);
+ occluder->SetBounds(gfx::Size(400, 400));
+ occluder->SetDrawsContent(true);
+ occluder->SetContentsOpaque(true);
+ CopyProperties(root, occluder);
+
+ DrawFrame();
+ EXPECT_EQ(host_impl_->GetFrameSinksToThrottleForTesting(),
+ base::flat_set<viz::FrameSinkId>{end.frame_sink_id()});
+}
+
TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestSimple) {
SetupDefaultRootLayer(gfx::Size(100, 100));
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
index 98bb4f49eb5..5289f95ac8f 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -4,7 +4,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/paint/paint_image.h"
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
index d858c5bad32..19f076021e8 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -4,7 +4,7 @@
#include <stddef.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/picture_layer.h"
@@ -764,7 +764,7 @@ class LayerTreeHostMaskAsBlendingPixelTest
// ARM Windows, macOS, and Fuchsia has some pixels difference
// Affected tests: RotatedClippedCircle, RotatedClippedCircleUnderflow
// crbug.com/1030244, crbug.com/1048249, crbug.com/1128443
- percentage_pixels_error = 6.1f;
+ percentage_pixels_error = 6.2f;
average_error_allowed_in_bad_pixels = 5.f;
large_error_allowed = 20;
#else
diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
index f52003c1912..b734b02d11f 100644
--- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -66,14 +66,16 @@ class LayerTreeHostReadbackPixelTest
if (readback_type() == TestReadBackType::kBitmap) {
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostReadbackPixelTest::ReadbackResultAsBitmap,
base::Unretained(this)));
} else {
DCHECK_NE(renderer_type_, viz::RendererType::kSoftware);
request = std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kNativeTextures,
base::BindOnce(
&LayerTreeHostReadbackPixelTest::ReadbackResultAsTexture,
base::Unretained(this)));
@@ -114,17 +116,24 @@ class LayerTreeHostReadbackPixelTest
void ReadbackResultAsTexture(std::unique_ptr<viz::CopyOutputResult> result) {
EXPECT_TRUE(task_runner_provider()->IsMainThread());
- ASSERT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
-
- gpu::Mailbox mailbox = result->GetTextureResult()->mailbox;
- gpu::SyncToken sync_token = result->GetTextureResult()->sync_token;
+ ASSERT_FALSE(result->IsEmpty());
+ ASSERT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
+ ASSERT_EQ(result->destination(),
+ viz::CopyOutputResult::Destination::kNativeTextures);
+
+ gpu::Mailbox mailbox = result->GetTextureResult()->planes[0].mailbox;
+ gpu::SyncToken sync_token =
+ result->GetTextureResult()->planes[0].sync_token;
gfx::ColorSpace color_space = result->GetTextureResult()->color_space;
EXPECT_EQ(result->GetTextureResult()->color_space, output_color_space_);
- viz::ReleaseCallback release_callback = result->TakeTextureOwnership();
+
+ viz::CopyOutputResult::ReleaseCallbacks release_callbacks =
+ result->TakeTextureOwnership();
+ EXPECT_EQ(1u, release_callbacks.size());
SkBitmap bitmap =
CopyMailboxToBitmap(result->size(), mailbox, sync_token, color_space);
- std::move(release_callback).Run(gpu::SyncToken(), false);
+ std::move(release_callbacks[0]).Run(gpu::SyncToken(), false);
ReadbackResultAsBitmap(std::make_unique<viz::CopyOutputSkBitmapResult>(
result->rect(), std::move(bitmap)));
@@ -439,6 +448,7 @@ ReadbackTestConfig const kTestConfigs[] = {
#endif // BUILDFLAG(ENABLE_GL_BACKEND_TESTS)
#if BUILDFLAG(ENABLE_VULKAN_BACKEND_TESTS)
ReadbackTestConfig{viz::RendererType::kSkiaVk, TestReadBackType::kBitmap},
+ ReadbackTestConfig{viz::RendererType::kSkiaVk, TestReadBackType::kTexture},
#endif // BUILDFLAG(ENABLE_VULKAN_BACKEND_TESTS)
#if BUILDFLAG(ENABLE_DAWN_BACKEND_TESTS)
ReadbackTestConfig{viz::RendererType::kSkiaDawn, TestReadBackType::kBitmap},
diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc
index ff324688b0d..ee9668d3820 100644
--- a/chromium/cc/trees/layer_tree_host_unittest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest.cc
@@ -18,6 +18,7 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -59,12 +60,14 @@
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/swap_promise.h"
#include "cc/trees/swap_promise_manager.h"
#include "cc/trees/transform_node.h"
#include "components/ukm/test_ukm_recorder.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
@@ -651,7 +654,8 @@ class LayerTreeHostFreeContextResourcesOnDestroy
: public LayerTreeHostContextCacheTest {
public:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (!first_will_begin_impl_frame_)
return;
@@ -681,7 +685,8 @@ class LayerTreeHostCacheBehaviorOnLayerTreeFrameSinkRecreated
: public LayerTreeHostContextCacheTest {
public:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// This code is run once, to trigger recreation of our LayerTreeFrameSink.
if (test_state_ != TestState::INIT)
return;
@@ -2680,6 +2685,225 @@ class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest {
SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorChange);
+// Tests that when the LayerTreeHost has received an updated Viewport Rect and
+// viz::LocalSurfaceId that the Impl Frame does not begin until the new tree has
+// been either activated or pushed as the new pending tree.
+class LayerTreeHostTestViewportRectChangeBlockedMainThread
+ : public LayerTreeHostTest {
+ public:
+ LayerTreeHostTestViewportRectChangeBlockedMainThread() {
+ scoped_feature_list_.InitAndEnableFeature(features::kSurfaceSyncThrottling);
+ }
+
+ void SetupTree() override {
+ root_layer_ = Layer::Create();
+ root_layer_->SetBounds(initial_size_);
+
+ child_layer_ = FakePictureLayer::Create(&client_);
+ child_layer_->SetBounds(gfx::Size(10, 10));
+ root_layer_->AddChild(child_layer_);
+
+ layer_tree_host()->SetRootLayer(root_layer_);
+ LayerTreeHostTest::SetupTree();
+ client_.set_bounds(root_layer_->bounds());
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void StopDeferringCommits() { scoped_defer_main_frame_update_.reset(); }
+
+ void ChangeViewportRect() {
+ gfx::Rect rect = layer_tree_host()->device_viewport_rect();
+ rect.set_size(target_size_);
+ GenerateNewLocalSurfaceId();
+ target_local_surface_id_ = GetCurrentLocalSurfaceId();
+ layer_tree_host()->SetViewportRectAndScale(rect, 1.f,
+ GetCurrentLocalSurfaceId());
+ // Block Main to simulate it being busy with a long layout.
+ PostGetDeferMainFrameUpdateToMainThread(&scoped_defer_main_frame_update_);
+ }
+
+ void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
+ switch (host_impl->sync_tree()->source_frame_number()) {
+ case 0:
+ initial_local_surface_id_ = GetCurrentLocalSurfaceId();
+
+ // After we have committed the initial tree, enqueue the change to the
+ // viewport rect for the next stage of the test.
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &LayerTreeHostTestViewportRectChangeBlockedMainThread::
+ ChangeViewportRect,
+ base::Unretained(this)));
+ break;
+ }
+ }
+
+ void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case -1:
+ EXPECT_FALSE(host_impl->active_tree()
+ ->local_surface_id_from_parent()
+ .is_valid());
+ break;
+ case 0:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ // Main creates a new |target_local_surface_id_| and posts it back to
+ // the Compositor thread in ChangeViewportRect. However if it is
+ // possible for a new Impl frame to start before the queued setting of
+ // |target_local_surface_id_| has been processed. So ignore those.
+ //
+ // The |source_frame_number| will not advance until a new tree has
+ // been committed. Which will not occur until we've passed here and
+ // called StopDeferringCommits. If the test times out there there is a
+ // bug in syncing the id.
+ if (!host_impl->target_local_surface_id().is_valid())
+ return;
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->target_local_surface_id());
+ // On slower configurations more than one frame at the original
+ // |source_frame_number| can be triggered between when we begin allowing
+ // commits again, and before the commit occurs.
+ //
+ // If so do not attempt to re-unblock. Once we have stopped the blocking
+ // the first time, all subsequent Commit/Activate/BeginMainFramme will
+ // be allowed to continue as normal.
+ //
+ // When this occurs there will be a new pending tree. We also expect
+ // there to be damage now, to unblock impl frame production ahead of the
+ // upcoming activation. CC is already build around Activations that can
+ // arrive mid-frame. It does this by delaying non-immediate mode
+ // painting until either Activation arrives, or an internal deadline is
+ // hit.
+ //
+ // The normal flow is:
+ // Main hasn't committed yet, due to explicitly being blocked.
+ // BeginImplFrame - we don't have damage
+ // Main is unblocked by StopDeferringCommits
+ // Main commits
+ // Main activates
+ // BeginImplFrame has new active_tree and starts
+ //
+ // The slower flow is:
+ // Main hasn't committed yet, due to explicitly being blocked.
+ // BeginImplFrame - we don't want have damage
+ // Main is unblocked by StopDeferringCommits
+ // Main commits
+ // BeginImplFrame has new pending_tree and starts
+ // Main activates
+ // Impl receives activation
+ // Painting.
+ if (host_impl->pending_tree()) {
+ EXPECT_TRUE(has_damage);
+ return;
+ }
+ // When the |active_tree| in the LayerTreeHostImpl is behind the new
+ // |target_local_surface_id| that the LayerTreeHost is processing,
+ // there should be no damage.
+ EXPECT_FALSE(has_damage)
+ << "target " << target_local_surface_id_.ToString();
+ // Unblock the main thread now to allow for activation of the new
+ // surface.
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &LayerTreeHostTestViewportRectChangeBlockedMainThread::
+ StopDeferringCommits,
+ base::Unretained(this)));
+ break;
+ case 1:
+ // When the main thread has become unblocked and pushed the new tree,
+ // frame production should continue.
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->target_local_surface_id());
+ EXPECT_TRUE(has_damage);
+ break;
+ }
+ }
+
+ void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case -1:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->pending_tree()->local_surface_id_from_parent());
+ break;
+ case 0:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ // For single threaded compositing we will not have built a
+ // |pending_tree| yet.
+ if (host_impl->pending_tree()) {
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->pending_tree()->local_surface_id_from_parent());
+ }
+ break;
+ case 1:
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->active_tree()->local_surface_id_from_parent());
+ break;
+ }
+ }
+
+ DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result) override {
+ // The damage rect will be set before drawing.
+ gfx::Rect root_damage_rect = frame_data->render_passes.back()->damage_rect;
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case 0:
+ EXPECT_EQ(initial_size_, root_damage_rect.size());
+ break;
+ case 1:
+ EXPECT_EQ(target_size_, root_damage_rect.size());
+ PostSetNeedsRedrawToMainThread();
+ break;
+ }
+ return draw_result;
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
+ // The viz::LocalSurfaceId is not associated with a frame until it is drawn.
+ switch (host_impl->active_tree()->source_frame_number()) {
+ case 0:
+ EXPECT_EQ(initial_local_surface_id_,
+ host_impl->last_draw_local_surface_id());
+ break;
+ case 1:
+ EXPECT_EQ(target_local_surface_id_,
+ host_impl->last_draw_local_surface_id());
+ EndTest();
+ break;
+ }
+ }
+
+ private:
+ std::unique_ptr<ScopedDeferMainFrameUpdate> scoped_defer_main_frame_update_;
+
+ viz::LocalSurfaceId initial_local_surface_id_;
+ viz::LocalSurfaceId target_local_surface_id_;
+
+ const gfx::Size initial_size_ = {10, 20};
+ const gfx::Size target_size_ = {20, 30};
+
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> root_layer_;
+ scoped_refptr<Layer> child_layer_;
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// TODO(crbug.com/1223226): Disabled on Chrome OS due to flakiness.
+#if !defined(OS_CHROMEOS)
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostTestViewportRectChangeBlockedMainThread);
+#endif
+
class LayerTreeHostTestRasterColorSpaceChange : public LayerTreeHostTest {
public:
void SetupTree() override {
@@ -3154,7 +3378,8 @@ class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (impl->pending_tree())
frame_count_with_pending_tree_++;
@@ -3354,10 +3579,10 @@ class ViewportDeltasAppliedDuringPinch : public LayerTreeHostTest,
void AfterTest() override { EXPECT_TRUE(sent_gesture_); }
// ScrollCallbacks
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset& scroll_offset,
- const absl::optional<TargetSnapAreaElementIds>&
- snap_target_ids) override {
+ void DidCompositorScroll(ElementId element_id,
+ const gfx::ScrollOffset& scroll_offset,
+ const absl::optional<TargetSnapAreaElementIds>&
+ snap_target_ids) override {
last_scrolled_element_id_ = element_id;
last_scrolled_offset_ = scroll_offset;
}
@@ -3561,7 +3786,8 @@ class LayerTreeHostTestDeferMainFrameUpdate : public LayerTreeHostTest {
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Impl frames happen while commits are deferred.
num_will_begin_impl_frame_++;
switch (num_will_begin_impl_frame_) {
@@ -3819,7 +4045,8 @@ class LayerTreeHostTestAnimateOnlyBeginFrames
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_EQ(args.animate_only,
(begin_frame_count_ >= 2 && begin_frame_count_ <= 4));
}
@@ -3932,7 +4159,8 @@ class LayerTreeHostTestCompositeImmediatelyStateTransitions
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_EQ(current_state_, kStartedTest);
current_state_ = kStartedImplFrame;
@@ -5543,34 +5771,57 @@ class LayerTreeHostTestElasticOverscroll : public LayerTreeHostTest {
}
}
+ void VerifyOverscroll(const gfx::Vector2dF& stretch_amount,
+ const gfx::Transform& transform) {
+#if defined(OS_ANDROID)
+ gfx::Vector2dF scale = transform.Scale2d();
+ // On android, overscroll stretches the content. We don't assert the amount
+ // of stretch but there should be some stretch for overscroll and no stretch
+ // without it.
+ if (stretch_amount.x() == 0.f)
+ EXPECT_EQ(1.f, scale.x());
+ else
+ EXPECT_GT(scale.x(), 1.f);
+ if (stretch_amount.y() == 0.f)
+ EXPECT_EQ(1.f, scale.y());
+ else
+ EXPECT_GT(scale.y(), 1.f);
+#else // defined(OS_ANDROID)
+ gfx::Transform expected_draw_transform;
+ expected_draw_transform.Translate(-stretch_amount);
+ EXPECT_EQ(expected_draw_transform, transform);
+#endif // defined(OS_ANDROID)
+ }
+
void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
num_draws_++;
LayerImpl* content_layer_impl =
host_impl->active_tree()->LayerById(content_layer_id_);
- gfx::Transform expected_draw_transform;
switch (num_draws_) {
case 1:
// Initially, there's no overscroll.
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ VerifyOverscroll(gfx::Vector2dF(), content_layer_impl->DrawTransform());
// Begin overscrolling. This should be reflected in the draw transform
// the next time we draw.
scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF(5.f, 6.f));
break;
case 2:
- expected_draw_transform.Translate(-5.0, -6.0);
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ // We should have some overscroll.
+ VerifyOverscroll(gfx::Vector2dF(5.f, 6.f),
+ content_layer_impl->DrawTransform());
scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF(3.f, 2.f));
break;
case 3:
- expected_draw_transform.Translate(-3.0, -2.0);
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ VerifyOverscroll(gfx::Vector2dF(3.f, 2.f),
+ content_layer_impl->DrawTransform());
scroll_elasticity_helper_->SetStretchAmount(gfx::Vector2dF());
break;
case 4:
- EXPECT_EQ(expected_draw_transform, content_layer_impl->DrawTransform());
+ // In the final frame there is no more overscroll.
+ VerifyOverscroll(gfx::Vector2dF(), content_layer_impl->DrawTransform());
EndTest();
break;
default:
@@ -5746,8 +5997,8 @@ class LayerTreeHostTestBreakSwapPromise : public LayerTreeHostTest {
}
void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
- int frame = host_impl->active_tree()->source_frame_number();
- if (frame == 2) {
+ int frame_num = host_impl->active_tree()->source_frame_number();
+ if (frame_num == 2) {
EndTest();
}
}
@@ -6016,7 +6267,8 @@ class LayerTreeHostTestDeferSwapPromiseForVisibility
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (!sent_queue_request_) {
sent_queue_request_ = true;
MainThreadTaskRunner()->PostTask(
@@ -6472,7 +6724,8 @@ class LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_EQ(will_begin_impl_frame_count_, did_finish_impl_frame_count_);
EXPECT_FALSE(TestEnded());
will_begin_impl_frame_count_++;
@@ -6545,7 +6798,8 @@ class LayerTreeHostTestBeginMainFrameTimeIsAlsoImplTime
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
impl_frame_args_.push_back(args);
will_begin_impl_frame_count_++;
@@ -7938,7 +8192,8 @@ class LayerTreeHostTestBeginFrameAcks : public LayerTreeHostTest {
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
EXPECT_TRUE(args.IsValid());
current_begin_frame_args_ = args;
}
@@ -7999,8 +8254,8 @@ class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest {
image_ =
DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)), false,
- SkIRect::MakeWH(400, 400), kNone_SkFilterQuality, SkM44(),
- PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
+ SkIRect::MakeWH(400, 400), PaintFlags::FilterQuality::kNone,
+ SkM44(), PaintImage::kDefaultFrameIndex, gfx::ColorSpace());
auto callback = base::BindRepeating(
&LayerTreeHostTestQueueImageDecode::ImageDecodeFinished,
base::Unretained(this));
@@ -8350,8 +8605,9 @@ class LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw
}
};
-MULTI_THREAD_TEST_F(
- LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw);
+// TODO(crbug.com/1092110): Flaky on TSan bot.
+// MULTI_THREAD_TEST_F(
+// LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw);
class LayerTreeHostTestImageDecodingHints : public LayerTreeHostTest {
public:
@@ -9012,7 +9268,8 @@ class LayerTreeHostTestEventsMetrics : public LayerTreeHostTest {
tick_clock.Advance(base::TimeDelta::FromMicroseconds(10));
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kContinued, ui::ScrollInputType::kWheel,
+ EventMetrics::ScrollParams(ui::ScrollInputType::kWheel, false,
+ EventMetrics::ScrollUpdateType::kContinued),
event_time, &tick_clock);
DCHECK_NE(metrics, nullptr);
{
@@ -9051,7 +9308,8 @@ class LayerTreeHostTestKeepEventsMetricsForVisibility
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Skip if we have already received a begin-impl-frame and acted on it.
if (received_will_begin_impl_frame_)
return;
@@ -9117,7 +9375,8 @@ class LayerTreeHostTestKeepEventsMetricsForDeferredMainFrameUpdate
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Skip if we have already received a begin-impl-frame and acted on it.
if (received_will_begin_impl_frame_)
return;
@@ -9198,7 +9457,8 @@ class LayerTreeHostTestKeepEventsMetricsForDeferredCommit
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Skip if we have already received a begin-impl-frame and acted on it.
if (received_will_begin_impl_frame_)
return;
@@ -9240,7 +9500,9 @@ class LayerTreeHostTestKeepEventsMetricsForDeferredCommit
private:
void DeferCommitOnMain() {
- layer_tree_host()->StartDeferringCommits(base::TimeDelta::FromDays(1));
+ layer_tree_host()->StartDeferringCommits(
+ base::TimeDelta::FromDays(1),
+ PaintHoldingReason::kFirstContentfulPaint);
}
void PostDeferCommit() {
@@ -9276,7 +9538,8 @@ class LayerTreeHostTestIgnoreEventsMetricsForNoUpdate
: public LayerTreeHostTestEventsMetrics {
protected:
void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
// Continue only if we are waiting for the second frame's being-impl-frame.
// The first frame will end up in a commit which is not what we want.
if (state_ != State::kWaitingForSecondFrameBeginImpl)
@@ -9376,7 +9639,8 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest {
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
host_impl->dropped_frame_counter()->OnFcpReceived();
}
@@ -9421,7 +9685,8 @@ class LayerTreeHostUkmSmoothnessMemoryOwnership : public LayerTreeTest {
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
host_impl->dropped_frame_counter()->OnFcpReceived();
host_impl->SetNeedsCommit();
}
diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
index 1b528540583..356a8789575 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1033,7 +1033,8 @@ class LayerTreeHostPresentationDuringAnimation
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (host_impl->next_frame_token() >= 5)
host_impl->BlockNotifyReadyToActivateForTesting(false);
}
@@ -1125,7 +1126,8 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
host_impl->BlockNotifyReadyToActivateForTesting(
ShouldBlockActivation(host_impl));
}
@@ -1348,7 +1350,8 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers
}
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const viz::BeginFrameArgs& args) override {
+ const viz::BeginFrameArgs& args,
+ bool has_damage) override {
if (!host_impl->pending_tree() ||
host_impl->pending_tree()->source_frame_number() != 2)
return;
diff --git a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc
index 2423cef7446..747063b9b35 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc
@@ -8,6 +8,7 @@
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/transform_node.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
namespace cc {
namespace {
@@ -38,7 +39,9 @@ class FakeCaptureContentLayerClient : public FakeContentLayerClient {
display_list->StartPaint();
display_list->push<DrawTextBlobOp>(
SkTextBlob::MakeFromString(holder.text().data(), SkFont()),
- holder.rect().x(), holder.rect().y(), holder.node_id(), PaintFlags());
+ static_cast<float>(holder.rect().x()),
+ static_cast<float>(holder.rect().y()), holder.node_id(),
+ PaintFlags());
display_list->EndPaintOfUnpaired(holder.rect());
}
display_list->Finalize();
diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc
index 6358f0afb4b..cb7610f60f5 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_context.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc
@@ -6,7 +6,7 @@
#include <stdint.h>
#include "base/bind.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "build/build_config.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/layer_impl.h"
diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
index 5640d141a98..02c23624f96 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -95,7 +95,8 @@ class LayerTreeHostCopyRequestTestMultipleRequests
switch (frame) {
case 1:
child->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 0)));
@@ -113,18 +114,21 @@ class LayerTreeHostCopyRequestTestMultipleRequests
EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
child->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 1)));
root->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 2)));
grand_child->RequestCopyOfOutput(
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
CopyOutputCallback,
base::Unretained(this), 3)));
@@ -260,7 +264,8 @@ class LayerTreeHostCopyRequestCompletionCausesCommit
switch (frame) {
case 1:
layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(&LayerTreeHostCopyRequestCompletionCausesCommit::
CopyOutputCallback)));
break;
@@ -326,13 +331,15 @@ class LayerTreeHostCopyRequestTestLayerDestroyed
case 1:
main_destroyed_->RequestCopyOfOutput(std::make_unique<
viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
base::Unretained(this), &main_destroyed_event_)));
impl_destroyed_->RequestCopyOfOutput(std::make_unique<
viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
base::Unretained(this), &impl_destroyed_event_)));
@@ -437,7 +444,8 @@ class LayerTreeHostCopyRequestTestInHiddenSubtree
void AddCopyRequest(Layer* layer) {
layer->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
base::Unretained(this))));
@@ -563,7 +571,8 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
PostSetNeedsCommitToMainThread();
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
CopyOutputCallback,
@@ -670,7 +679,8 @@ class LayerTreeHostCopyRequestTestClippedOut
PostSetNeedsCommitToMainThread();
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
base::Unretained(this))));
@@ -733,7 +743,8 @@ class LayerTreeHostCopyRequestTestScaledLayer
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestScaledLayer::CopyOutputCallback,
base::Unretained(this)));
@@ -786,7 +797,8 @@ class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
void AddCopyRequest(Layer* layer) {
layer->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
base::Unretained(this))));
@@ -913,7 +925,9 @@ class LayerTreeHostCopyRequestTestDeleteSharedImage
std::unique_ptr<viz::CopyOutputResult> result) {
EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
- EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
+ EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
+ EXPECT_EQ(result->destination(),
+ viz::CopyOutputResult::Destination::kNativeTextures);
EXPECT_NE(result->GetTextureResult(), nullptr);
// Save the result for later.
@@ -926,7 +940,8 @@ class LayerTreeHostCopyRequestTestDeleteSharedImage
void InsertCopyRequest() {
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(&LayerTreeHostCopyRequestTestDeleteSharedImage::
ReceiveCopyRequestOutputAndCommit,
base::Unretained(this))));
@@ -1088,6 +1103,22 @@ class LayerTreeHostCopyRequestTestCountSharedImages
}
}
+ std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink(
+ const viz::RendererSettings& renderer_settings,
+ double refresh_rate,
+ scoped_refptr<viz::ContextProvider> compositor_context_provider,
+ scoped_refptr<viz::RasterContextProvider> worker_context_provider)
+ override {
+ // Since this test counts shared images and SkiaRenderer uses shared images
+ // for render passes, we need render pass allocation to be stable.
+ auto settings = renderer_settings;
+ settings.disable_render_pass_bypassing = true;
+ auto frame_sink = LayerTreeHostCopyRequestTest::CreateLayerTreeFrameSink(
+ settings, refresh_rate, std::move(compositor_context_provider),
+ std::move(worker_context_provider));
+ return frame_sink;
+ }
+
void DisplayDidDrawAndSwapOnThread() override {
auto* sii = display_context_provider_->SharedImageInterface();
switch (num_swaps_++) {
@@ -1135,7 +1166,8 @@ class LayerTreeHostCopyRequestTestCreatesSharedImage
void RequestCopy(Layer* layer) override {
// Request a normal texture copy. This should create a new shared image.
copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(
&LayerTreeHostCopyRequestTestCreatesSharedImage::CopyOutputCallback,
base::Unretained(this))));
@@ -1143,21 +1175,25 @@ class LayerTreeHostCopyRequestTestCreatesSharedImage
void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
EXPECT_FALSE(result->IsEmpty());
- EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA_TEXTURE);
+ EXPECT_EQ(result->format(), viz::CopyOutputResult::Format::RGBA);
+ EXPECT_EQ(result->destination(),
+ viz::CopyOutputResult::Destination::kNativeTextures);
ASSERT_NE(nullptr, result->GetTextureResult());
release_ = result->TakeTextureOwnership();
- EXPECT_TRUE(release_);
+ EXPECT_EQ(1u, release_.size());
}
void AfterTest() override {
- std::move(release_).Run(gpu::SyncToken(), false);
+ for (auto& release : release_) {
+ std::move(release).Run(gpu::SyncToken(), false);
+ }
// Except the copy to have made a new shared image.
EXPECT_EQ(num_shared_images_without_readback_ + 1,
num_shared_images_with_readback_);
}
- viz::ReleaseCallback release_;
+ viz::CopyOutputResult::ReleaseCallbacks release_;
};
INSTANTIATE_TEST_SUITE_P(
@@ -1216,7 +1252,8 @@ class LayerTreeHostCopyRequestTestDestroyBeforeCopy
// drawing to take place.
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
CopyOutputCallback,
base::Unretained(this)));
@@ -1308,7 +1345,8 @@ class LayerTreeHostCopyRequestTestShutdownBeforeCopy
// drawing to take place.
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputResult::Destination::kNativeTextures,
base::BindOnce(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::
CopyOutputCallback,
base::Unretained(this)));
@@ -1381,7 +1419,8 @@ class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest
// Send a copy request after the first commit.
if (layer_tree_host()->SourceFrameNumber() == 1) {
child_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>(
- viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ viz::CopyOutputRequest::ResultFormat::RGBA,
+ viz::CopyOutputRequest::ResultDestination::kSystemMemory,
base::BindOnce(
&LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest::
CopyOutputCallback,
diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
index 2d2993d1413..479801c7cb0 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc
@@ -337,7 +337,10 @@ class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
content_layer_ = FakePictureLayer::Create(&client_);
content_layer_->SetElementId(
LayerIdToElementIdForTesting(content_layer_->id()));
- content_layer_->SetScrollable(root_layer->bounds());
+
+ // The size of the container in which scrolling contents are visible need
+ // to be smaller than the bounds of the layer itself.
+ content_layer_->SetScrollable(gfx::Size(80, 180));
content_layer_->SetScrollOffset(gfx::ScrollOffset(10, 20));
content_layer_->SetBounds(gfx::Size(100, 200));
content_layer_->SetIsDrawable(true);
diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
index 5767d3784b2..3a4ecfab2da 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -87,10 +87,10 @@ class LayerTreeHostScrollTest : public LayerTreeTest, public ScrollCallbacks {
}
// ScrollCallbacks
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset& scroll_offset,
- const absl::optional<TargetSnapAreaElementIds>&
- snap_target_ids) override {
+ void DidCompositorScroll(ElementId element_id,
+ const gfx::ScrollOffset& scroll_offset,
+ const absl::optional<TargetSnapAreaElementIds>&
+ snap_target_ids) override {
// Simulates cc client (e.g Blink) behavior when handling impl-side scrolls.
SetScrollOffsetFromImplSide(layer_tree_host()->LayerByElementId(element_id),
scroll_offset);
@@ -621,11 +621,12 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
}
}
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset& offset,
- const absl::optional<TargetSnapAreaElementIds>&
- snap_target_ids) override {
- LayerTreeHostScrollTest::DidScroll(element_id, offset, snap_target_ids);
+ void DidCompositorScroll(ElementId element_id,
+ const gfx::ScrollOffset& offset,
+ const absl::optional<TargetSnapAreaElementIds>&
+ snap_target_ids) override {
+ LayerTreeHostScrollTest::DidCompositorScroll(element_id, offset,
+ snap_target_ids);
if (element_id == expected_scroll_layer_->element_id()) {
final_scroll_offset_ = CurrentScrollOffset(expected_scroll_layer_);
EXPECT_EQ(offset, final_scroll_offset_);
@@ -1094,7 +1095,6 @@ class SmoothScrollAnimationEndNotification : public LayerTreeHostScrollTest {
child_layer_ = Layer::Create();
child_layer_->SetElementId(
LayerIdToElementIdForTesting(child_layer_->id()));
- child_layer_->SetBounds(gfx::Size(110, 110));
child_layer_->SetIsDrawable(true);
child_layer_->SetHitTestable(true);
@@ -1111,11 +1111,11 @@ class SmoothScrollAnimationEndNotification : public LayerTreeHostScrollTest {
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void WillCommit() override {
+ if (TestEnded())
+ return;
// Keep the test committing (otherwise the early out for no update
// will stall the test).
- if (layer_tree_host()->SourceFrameNumber() < 2) {
- layer_tree_host()->SetNeedsCommit();
- }
+ layer_tree_host()->SetNeedsCommit();
}
void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
@@ -1767,6 +1767,8 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient {
}
}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override {}
+
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
@@ -1840,9 +1842,10 @@ class LayerTreeHostScrollTestLayerStructureChange
}
}
- void DidScroll(ElementId element_id,
- const gfx::ScrollOffset&,
- const absl::optional<TargetSnapAreaElementIds>&) override {
+ void DidCompositorScroll(
+ ElementId element_id,
+ const gfx::ScrollOffset&,
+ const absl::optional<TargetSnapAreaElementIds>&) override {
if (scroll_destroy_whole_tree_) {
layer_tree_host()->SetRootLayer(nullptr);
layer_tree_host()->property_trees()->clear();
@@ -2235,6 +2238,7 @@ class MockInputHandlerClient : public InputHandlerClient {
void WillShutdown() override {}
void Animate(base::TimeTicks) override {}
+ void SetPrefersReducedMotion(bool prefers_reduced_motion) override {}
void UpdateRootLayerStateForSynchronousInputHandler(
const gfx::ScrollOffset& total_scroll_offset,
const gfx::ScrollOffset& max_scroll_offset,
diff --git a/chromium/cc/trees/layer_tree_host_unittest_video.cc b/chromium/cc/trees/layer_tree_host_unittest_video.cc
index f69dc76d788..c7b664cb484 100644
--- a/chromium/cc/trees/layer_tree_host_unittest_video.cc
+++ b/chromium/cc/trees/layer_tree_host_unittest_video.cc
@@ -16,6 +16,9 @@
namespace cc {
namespace {
+constexpr auto kTestTransform =
+ media::VideoTransformation(media::VIDEO_ROTATION_90, /*mirrored=*/true);
+
// These tests deal with compositing video.
class LayerTreeHostVideoTest : public LayerTreeTest {};
@@ -28,7 +31,7 @@ class LayerTreeHostVideoTestSetNeedsDisplay
root->SetIsDrawable(true);
scoped_refptr<VideoLayer> video =
- VideoLayer::Create(&video_frame_provider_, media::VIDEO_ROTATION_90);
+ VideoLayer::Create(&video_frame_provider_, kTestTransform);
video->SetPosition(gfx::PointF(3.f, 3.f));
video->SetBounds(gfx::Size(4, 5));
video->SetIsDrawable(true);
@@ -74,7 +77,7 @@ class LayerTreeHostVideoTestSetNeedsDisplay
VideoLayerImpl* video = static_cast<VideoLayerImpl*>(
host_impl->active_tree()->LayerById(video_layer_id_));
- EXPECT_EQ(media::VIDEO_ROTATION_90, video->video_rotation());
+ EXPECT_EQ(kTestTransform, video->video_transform_for_testing());
if (num_draws_ == 0)
video->SetNeedsRedraw();
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index 8d78780435b..e923a3e0551 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -17,11 +17,11 @@
#include "base/containers/adapters.h"
#include "base/containers/contains.h"
+#include "base/cxx17_backports.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/json/json_writer.h"
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
#include "base/strings/stringprintf.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
@@ -108,8 +108,8 @@ std::pair<gfx::PointF, gfx::PointF> GetVisibleSelectionEndPoints(
const gfx::RectF& rect,
const gfx::PointF& top,
const gfx::PointF& bottom) {
- gfx::PointF start(base::ClampToRange(top.x(), rect.x(), rect.right()),
- base::ClampToRange(top.y(), rect.y(), rect.bottom()));
+ gfx::PointF start(base::clamp(top.x(), rect.x(), rect.right()),
+ base::clamp(top.y(), rect.y(), rect.bottom()));
gfx::PointF end =
start + gfx::Vector2dF(bottom.x() - top.x(), bottom.y() - top.y());
return {start, end};
@@ -805,15 +805,15 @@ void LayerTreeImpl::SetBackdropFilterMutated(
}
void LayerTreeImpl::AddPresentationCallbacks(
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks) {
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks) {
std::copy(std::make_move_iterator(callbacks.begin()),
std::make_move_iterator(callbacks.end()),
std::back_inserter(presentation_callbacks_));
}
-std::vector<LayerTreeHost::PresentationTimeCallback>
+std::vector<PresentationTimeCallbackBuffer::MainCallback>
LayerTreeImpl::TakePresentationCallbacks() {
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks;
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks;
callbacks.swap(presentation_callbacks_);
return callbacks;
}
@@ -1070,7 +1070,7 @@ bool LayerTreeImpl::ClampTopControlsShownRatio() {
host_impl_->browser_controls_manager()->TopControlsShownRatioRange();
}
return top_controls_shown_ratio_->SetCurrent(
- base::ClampToRange(ratio, range.first, range.second));
+ base::clamp(ratio, range.first, range.second));
}
bool LayerTreeImpl::ClampBottomControlsShownRatio() {
@@ -1083,7 +1083,7 @@ bool LayerTreeImpl::ClampBottomControlsShownRatio() {
host_impl_->browser_controls_manager()->BottomControlsShownRatioRange();
}
return bottom_controls_shown_ratio_->SetCurrent(
- base::ClampToRange(ratio, range.first, range.second));
+ base::clamp(ratio, range.first, range.second));
}
bool LayerTreeImpl::SetCurrentBrowserControlsShownRatio(float top_ratio,
@@ -1292,6 +1292,10 @@ const TransformNode* LayerTreeImpl::OverscrollElasticityTransformNode() const {
viewport_property_ids_.overscroll_elasticity_transform);
}
+ElementId LayerTreeImpl::OverscrollElasticityEffectElementId() const {
+ return viewport_property_ids_.overscroll_elasticity_effect;
+}
+
const TransformNode* LayerTreeImpl::PageScaleTransformNode() const {
return property_trees()->transform_tree.Node(
viewport_property_ids_.page_scale_transform);
diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h
index 708b0702807..6971fd0d614 100644
--- a/chromium/cc/trees/layer_tree_impl.h
+++ b/chromium/cc/trees/layer_tree_impl.h
@@ -284,8 +284,8 @@ class CC_EXPORT LayerTreeImpl {
gfx::ScrollOffset TotalMaxScrollOffset() const;
void AddPresentationCallbacks(
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks);
- std::vector<LayerTreeHost::PresentationTimeCallback>
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks);
+ std::vector<PresentationTimeCallbackBuffer::MainCallback>
TakePresentationCallbacks();
bool has_presentation_callbacks() const {
return !presentation_callbacks_.empty();
@@ -303,6 +303,7 @@ class CC_EXPORT LayerTreeImpl {
const_cast<const LayerTreeImpl*>(this)
->OverscrollElasticityTransformNode());
}
+ ElementId OverscrollElasticityEffectElementId() const;
const TransformNode* PageScaleTransformNode() const;
TransformNode* PageScaleTransformNode() {
return const_cast<TransformNode*>(
@@ -734,6 +735,10 @@ class CC_EXPORT LayerTreeImpl {
return host_impl_->GetActivelyScrollingType();
}
+ bool CurrentScrollDidCheckerboardLargeArea() {
+ return host_impl_->CurrentScrollDidCheckerboardLargeArea();
+ }
+
// These functions are used for plumbing DelegatedInkMetadata from blink
// through the compositor and into viz via a compositor frame. They should
// only be called after the JS API |updateInkTrailStartPoint| has been
@@ -917,7 +922,8 @@ class CC_EXPORT LayerTreeImpl {
// Display transform hint to tag frames generated from this tree.
gfx::OverlayTransform display_transform_hint_ = gfx::OVERLAY_TRANSFORM_NONE;
- std::vector<LayerTreeHost::PresentationTimeCallback> presentation_callbacks_;
+ std::vector<PresentationTimeCallbackBuffer::MainCallback>
+ presentation_callbacks_;
// Event metrics that are reported back from the main thread.
EventMetrics::List events_metrics_from_main_thread_;
diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc
index a132530bfaa..ff133afcada 100644
--- a/chromium/cc/trees/layer_tree_impl_unittest.cc
+++ b/chromium/cc/trees/layer_tree_impl_unittest.cc
@@ -4,7 +4,7 @@
#include "cc/trees/layer_tree_impl.h"
-#include "base/numerics/ranges.h"
+#include "base/cxx17_backports.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_raster_source.h"
@@ -23,8 +23,8 @@ std::pair<gfx::PointF, gfx::PointF> GetVisibleSelectionEndPoints(
const gfx::RectF& rect,
const gfx::PointF& top,
const gfx::PointF& bottom) {
- gfx::PointF start(base::ClampToRange(top.x(), rect.x(), rect.right()),
- base::ClampToRange(top.y(), rect.y(), rect.bottom()));
+ gfx::PointF start(base::clamp(top.x(), rect.x(), rect.right()),
+ base::clamp(top.y(), rect.y(), rect.bottom()));
gfx::PointF end =
start + gfx::Vector2dF(bottom.x() - top.x(), bottom.y() - top.y());
return {start, end};
diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc
index 2a13e654421..b8168bd5b9e 100644
--- a/chromium/cc/trees/layer_tree_settings.cc
+++ b/chromium/cc/trees/layer_tree_settings.cc
@@ -26,10 +26,6 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const {
main_frame_before_activation_enabled;
scheduler_settings.using_synchronous_renderer_compositor =
using_synchronous_renderer_compositor;
- scheduler_settings.enable_impl_latency_recovery =
- enable_impl_latency_recovery;
- scheduler_settings.enable_main_latency_recovery =
- enable_main_latency_recovery;
scheduler_settings.wait_for_all_pipeline_stages_before_draw =
wait_for_all_pipeline_stages_before_draw;
return scheduler_settings;
diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h
index 7fa2b4da8c8..e38646f8834 100644
--- a/chromium/cc/trees/layer_tree_settings.h
+++ b/chromium/cc/trees/layer_tree_settings.h
@@ -38,8 +38,6 @@ class CC_EXPORT LayerTreeSettings {
// When |enable_early_damage_check| is true, the early damage check is
// performed if one of the last |damaged_frame_limit| frames had no damage.
int damaged_frame_limit = 3;
- bool enable_impl_latency_recovery = false;
- bool enable_main_latency_recovery = false;
bool can_use_lcd_text = true;
bool gpu_rasterization_disabled = false;
int gpu_rasterization_msaa_sample_count = -1;
@@ -193,7 +191,7 @@ class CC_EXPORT LayerTreeSettings {
// When enabled, enforces new interoperable semantics for 3D transforms.
// See crbug.com/1008483.
- bool enable_transform_interop = false;
+ bool enable_backface_visibility_interop = false;
// Enables ThrottleDecider which produces a list of FrameSinkIds that are
// candidates for throttling.
diff --git a/chromium/cc/trees/mobile_optimized_viewport_util.cc b/chromium/cc/trees/mobile_optimized_viewport_util.cc
new file mode 100644
index 00000000000..2f70f27a70d
--- /dev/null
+++ b/chromium/cc/trees/mobile_optimized_viewport_util.cc
@@ -0,0 +1,41 @@
+// Copyright 2021 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/mobile_optimized_viewport_util.h"
+
+#include "base/feature_list.h"
+#include "cc/base/features.h"
+#include "ui/gfx/geometry/size_f.h"
+
+namespace cc {
+namespace util {
+namespace {
+// Used to accommodate finite precision when comparing scaled viewport and
+// content widths. While this value may seem large, width=device-width on an N7
+// V1 saw errors of ~0.065 between computed window and content widths.
+const float kMobileViewportWidthEpsilon = 0.15f;
+} // namespace
+
+bool IsMobileOptimized(float min_page_scale_factor,
+ float max_page_scale_factor,
+ float current_page_scale_factor,
+ gfx::SizeF scrollable_viewport_size,
+ gfx::SizeF scrollable_size,
+ bool viewport_meta_mobile_optimized) {
+ bool has_fixed_page_scale = min_page_scale_factor == max_page_scale_factor;
+
+ float window_width_dip =
+ current_page_scale_factor * scrollable_viewport_size.width();
+ float content_width_css = scrollable_size.width();
+ bool has_mobile_viewport =
+ content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
+
+ return has_mobile_viewport || has_fixed_page_scale ||
+ (base::FeatureList::IsEnabled(
+ ::features::kRemoveMobileViewportDoubleTap) &&
+ viewport_meta_mobile_optimized);
+}
+
+} // namespace util
+} // namespace cc
diff --git a/chromium/cc/trees/mobile_optimized_viewport_util.h b/chromium/cc/trees/mobile_optimized_viewport_util.h
new file mode 100644
index 00000000000..9bd59891aba
--- /dev/null
+++ b/chromium/cc/trees/mobile_optimized_viewport_util.h
@@ -0,0 +1,34 @@
+// Copyright 2021 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_MOBILE_OPTIMIZED_VIEWPORT_UTIL_H_
+#define CC_TREES_MOBILE_OPTIMIZED_VIEWPORT_UTIL_H_
+
+#include "ui/gfx/geometry/size_f.h"
+
+namespace cc {
+namespace util {
+
+// Returns whether the viewport should be considered mobile optimized,
+// not needing the double tap to zoom gesture.
+// Arguments:
+// min_page_scale_factor - the minimum page scale
+// max_page_scale_factor - the maximum page scale
+// current_page_scale_factor - current page scale
+// scrollable_viewport_size - the size of the user-visible scrolling viewport
+// in CSS layout coordinates
+// scrollable_size - the size of the root scrollable area in CSS layout
+// coordinates
+// viewport_meta_mobile_optimized - if the viewport meta tag is mobile
+// optimized
+bool IsMobileOptimized(float min_page_scale_factor,
+ float max_page_scale_factor,
+ float current_page_scale_factor,
+ gfx::SizeF scrollable_viewport_size,
+ gfx::SizeF scrollable_size,
+ bool viewport_meta_mobile_optimized);
+} // namespace util
+} // namespace cc
+
+#endif // CC_TREES_MOBILE_OPTIMIZED_VIEWPORT_UTIL_H_
diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc
index 91f8fefa627..0f9c92265c8 100644
--- a/chromium/cc/trees/occlusion_tracker.cc
+++ b/chromium/cc/trees/occlusion_tracker.cc
@@ -104,7 +104,7 @@ static SimpleEnclosedRegion TransformSurfaceOpaqueRegion(
// to each rect within |region| in order to transform the entire Region.
// TODO(danakj): Find a rect interior to each transformed quad.
- if (!transform.Preserves2dAxisAlignment())
+ if (!transform.NonDegeneratePreserves2dAxisAlignment())
return SimpleEnclosedRegion();
SimpleEnclosedRegion transformed_region;
@@ -371,7 +371,7 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) {
gfx::Transform draw_transform = layer->DrawTransform();
// TODO(danakj): Find a rect interior to each transformed quad.
- if (!draw_transform.Preserves2dAxisAlignment())
+ if (!draw_transform.NonDegeneratePreserves2dAxisAlignment())
return;
gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface(
diff --git a/chromium/cc/trees/occlusion_unittest.cc b/chromium/cc/trees/occlusion_unittest.cc
index e5b31e41193..a0c17bd881c 100644
--- a/chromium/cc/trees/occlusion_unittest.cc
+++ b/chromium/cc/trees/occlusion_unittest.cc
@@ -6,7 +6,7 @@
#include <stddef.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
diff --git a/chromium/cc/trees/paint_holding_commit_trigger.cc b/chromium/cc/trees/paint_holding_commit_trigger.cc
new file mode 100644
index 00000000000..daba1843c87
--- /dev/null
+++ b/chromium/cc/trees/paint_holding_commit_trigger.cc
@@ -0,0 +1,22 @@
+// Copyright 2021 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/paint_holding_commit_trigger.h"
+
+#include "base/notreached.h"
+
+namespace cc {
+
+PaintHoldingCommitTrigger ReasonToTimeoutTrigger(PaintHoldingReason reason) {
+ switch (reason) {
+ case PaintHoldingReason::kFirstContentfulPaint:
+ return PaintHoldingCommitTrigger::kTimeoutFCP;
+ case PaintHoldingReason::kDocumentTransition:
+ return PaintHoldingCommitTrigger::kTimeoutDocumentTransition;
+ }
+ NOTREACHED();
+ return PaintHoldingCommitTrigger::kTimeoutFCP;
+}
+
+} // namespace cc
diff --git a/chromium/cc/trees/paint_holding_commit_trigger.h b/chromium/cc/trees/paint_holding_commit_trigger.h
index b8828028019..5c9439d7f78 100644
--- a/chromium/cc/trees/paint_holding_commit_trigger.h
+++ b/chromium/cc/trees/paint_holding_commit_trigger.h
@@ -5,6 +5,8 @@
#ifndef CC_TREES_PAINT_HOLDING_COMMIT_TRIGGER_H_
#define CC_TREES_PAINT_HOLDING_COMMIT_TRIGGER_H_
+#include "cc/trees/paint_holding_reason.h"
+
namespace cc {
enum class PaintHoldingCommitTrigger {
@@ -18,13 +20,19 @@ enum class PaintHoldingCommitTrigger {
// The commit was triggered by first contentful paint (FCP)
kFirstContentfulPaint = 2,
// The commit was triggered by a timeout waiting for FCP
- kTimeout = 3,
+ kTimeoutFCP = 3,
// The timeout was never set, probably due to non-main frame
kNotDeferred = 4,
+ // The commit was triggered by a document transition start
+ kDocumentTransition = 5,
+ // The commit was triggered by a timeout waiting for document transition start
+ kTimeoutDocumentTransition = 6,
// Required for UMA enum
- kMaxValue = kNotDeferred
+ kMaxValue = kTimeoutDocumentTransition
};
+PaintHoldingCommitTrigger ReasonToTimeoutTrigger(PaintHoldingReason reason);
+
} // namespace cc
#endif // CC_TREES_PAINT_HOLDING_COMMIT_TRIGGER_H_
diff --git a/chromium/cc/trees/paint_holding_reason.h b/chromium/cc/trees/paint_holding_reason.h
new file mode 100644
index 00000000000..3e063246b4b
--- /dev/null
+++ b/chromium/cc/trees/paint_holding_reason.h
@@ -0,0 +1,21 @@
+// Copyright 2021 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_PAINT_HOLDING_REASON_H_
+#define CC_TREES_PAINT_HOLDING_REASON_H_
+
+namespace cc {
+
+enum class PaintHoldingReason {
+ // Deferred to allow a frame with contentful paint.
+ kFirstContentfulPaint,
+
+ // Deferred to allow the document to be updated asynchronously for a
+ // transition.
+ kDocumentTransition,
+};
+
+} // namespace cc
+
+#endif // CC_TREES_PAINT_HOLDING_REASON_H_
diff --git a/chromium/cc/trees/presentation_time_callback_buffer.cc b/chromium/cc/trees/presentation_time_callback_buffer.cc
index c6de964c244..7ae602bf330 100644
--- a/chromium/cc/trees/presentation_time_callback_buffer.cc
+++ b/chromium/cc/trees/presentation_time_callback_buffer.cc
@@ -7,6 +7,8 @@
#include <utility>
#include <vector>
+#include "components/viz/common/quads/compositor_frame_metadata.h"
+
namespace cc {
PresentationTimeCallbackBuffer::PresentationTimeCallbackBuffer() = default;
@@ -37,7 +39,7 @@ PresentationTimeCallbackBuffer::FrameTokenInfo::~FrameTokenInfo() = default;
void PresentationTimeCallbackBuffer::RegisterMainThreadPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks) {
+ std::vector<MainCallback> callbacks) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
FrameTokenInfo& frame_info = GetOrMakeRegistration(frame_token);
@@ -45,20 +47,16 @@ void PresentationTimeCallbackBuffer::RegisterMainThreadPresentationCallbacks(
auto& sink = frame_info.main_thread_callbacks;
sink.reserve(sink.size() + callbacks.size());
std::move(callbacks.begin(), callbacks.end(), std::back_inserter(sink));
-
- DCHECK_LE(frame_token_infos_.size(), 25u);
}
void PresentationTimeCallbackBuffer::RegisterCompositorPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks) {
+ std::vector<CompositorCallback> callbacks) {
// Splice the given |callbacks| onto the vector of existing callbacks.
- std::vector<LayerTreeHost::PresentationTimeCallback>& sink =
+ std::vector<CompositorCallback>& sink =
GetOrMakeRegistration(frame_token).compositor_thread_callbacks;
sink.reserve(sink.size() + callbacks.size());
std::move(callbacks.begin(), callbacks.end(), std::back_inserter(sink));
-
- DCHECK_LE(frame_token_infos_.size(), 25u);
}
PresentationTimeCallbackBuffer::PendingCallbacks::PendingCallbacks() = default;
@@ -70,29 +68,33 @@ PresentationTimeCallbackBuffer::PendingCallbacks::operator=(
PresentationTimeCallbackBuffer::PendingCallbacks::~PendingCallbacks() = default;
PresentationTimeCallbackBuffer::PendingCallbacks
-PresentationTimeCallbackBuffer::PopPendingCallbacks(uint32_t frame_token) {
+PresentationTimeCallbackBuffer::PopPendingCallbacks(uint32_t frame_token,
+ bool main_only) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
PendingCallbacks result;
- while (!frame_token_infos_.empty()) {
- auto info = frame_token_infos_.begin();
+ for (auto info = frame_token_infos_.begin();
+ info != frame_token_infos_.end();) {
if (viz::FrameTokenGT(info->token, frame_token))
break;
- // Collect the main-thread callbacks. It's the caller's job to post them to
- // the main thread.
std::move(info->main_thread_callbacks.begin(),
info->main_thread_callbacks.end(),
std::back_inserter(result.main_thread_callbacks));
-
- // Collect the compositor-thread callbacks. It's the caller's job to run
- // them on the compositor thread.
- std::move(info->compositor_thread_callbacks.begin(),
- info->compositor_thread_callbacks.end(),
- std::back_inserter(result.compositor_thread_callbacks));
-
- frame_token_infos_.erase(info);
+ info->main_thread_callbacks.clear();
+
+ const bool should_keep_callbacks =
+ main_only && !info->compositor_thread_callbacks.empty();
+
+ if (should_keep_callbacks) {
+ ++info;
+ } else {
+ std::move(info->compositor_thread_callbacks.begin(),
+ info->compositor_thread_callbacks.end(),
+ std::back_inserter(result.compositor_thread_callbacks));
+ info = frame_token_infos_.erase(info);
+ }
}
return result;
@@ -105,6 +107,7 @@ PresentationTimeCallbackBuffer::GetOrMakeRegistration(uint32_t frame_token) {
if (frame_token_infos_.empty() ||
viz::FrameTokenGT(frame_token, frame_token_infos_.back().token)) {
frame_token_infos_.emplace_back(frame_token);
+ DCHECK_LE(frame_token_infos_.size(), 25u);
}
// Registrations should use monotonically increasing frame tokens.
diff --git a/chromium/cc/trees/presentation_time_callback_buffer.h b/chromium/cc/trees/presentation_time_callback_buffer.h
index 820b8fc3767..ab36aa5bd22 100644
--- a/chromium/cc/trees/presentation_time_callback_buffer.h
+++ b/chromium/cc/trees/presentation_time_callback_buffer.h
@@ -6,9 +6,11 @@
#include <vector>
+#include "base/callback_forward.h"
#include "base/containers/circular_deque.h"
#include "base/sequence_checker.h"
-#include "cc/trees/layer_tree_host.h"
+#include "cc/cc_export.h"
+#include "ui/gfx/presentation_feedback.h"
namespace cc {
@@ -32,7 +34,15 @@ namespace cc {
// CC_EXPORT is only needed for testing.
class CC_EXPORT PresentationTimeCallbackBuffer {
public:
- using CallbackType = LayerTreeHost::PresentationTimeCallback;
+ // TODO(crbug.com/1199373): Compositor thread callbacks are only run for
+ // successful presentations and only need the presentation timestamp. On the
+ // other hand, main thread callbacks can be run on both successful and failed
+ // presentations and need a full `gfx::PresentationFeedback`. Conceptually,
+ // main thread callbacks should only be run for successful presentations, too,
+ // in which case the two callback signatures can be unified.
+ using MainCallback =
+ base::OnceCallback<void(const gfx::PresentationFeedback&)>;
+ using CompositorCallback = base::OnceCallback<void(base::TimeTicks)>;
PresentationTimeCallbackBuffer();
@@ -51,14 +61,14 @@ class CC_EXPORT PresentationTimeCallbackBuffer {
// main thread once they're popped.
void RegisterMainThreadPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks);
+ std::vector<MainCallback> callbacks);
// Buffers the given |callbacks| in preparation for a GPU frame swap at or
// after the given |frame_token|. Calling code invokes these callbacks on the
// compositor thread once they're popped.
void RegisterCompositorPresentationCallbacks(
uint32_t frame_token,
- std::vector<CallbackType> callbacks);
+ std::vector<CompositorCallback> callbacks);
// Structured return value for |PopPendingCallbacks|. CC_EXPORT is only
// needed for testing.
@@ -75,18 +85,19 @@ class CC_EXPORT PresentationTimeCallbackBuffer {
// Holds callbacks registered through
// |RegisterMainThreadPresentationCallbacks|.
- std::vector<CallbackType> main_thread_callbacks;
+ std::vector<MainCallback> main_thread_callbacks;
// Holds callbacks registered through
// |RegisterCompositorPresentationCallbacks|.
- std::vector<CallbackType> compositor_thread_callbacks;
+ std::vector<CompositorCallback> compositor_thread_callbacks;
};
- // Call this once the presentation for the given |frame_token| has completed.
+ // Call this once the presentation for the given `frame_token` has completed.
// Yields any pending callbacks that were registered against a frame token
- // that was less than or equal to the given |frame_token|. It is the caller's
+ // that was less than or equal to the given `frame_token`. If `main_only` is
+ // true, only callbacks for the main thread are returned. It is the caller's
// responsibility to run the callbacks on the right threads/sequences.
- PendingCallbacks PopPendingCallbacks(uint32_t frame_token);
+ PendingCallbacks PopPendingCallbacks(uint32_t frame_token, bool main_only);
private:
// Stores information needed once we get a response for a particular
@@ -104,10 +115,10 @@ class CC_EXPORT PresentationTimeCallbackBuffer {
uint32_t token;
// The callbacks to send back to the main thread.
- std::vector<CallbackType> main_thread_callbacks;
+ std::vector<MainCallback> main_thread_callbacks;
// The callbacks to invoke on the compositor thread.
- std::vector<CallbackType> compositor_thread_callbacks;
+ std::vector<CompositorCallback> compositor_thread_callbacks;
};
// Returns a reference to a |FrameTokenInfo| with the given |frame_token|.
diff --git a/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc b/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc
index 6b8aa1e0186..ee68a898f3c 100644
--- a/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc
+++ b/chromium/cc/trees/presentation_time_callback_buffer_unittest.cc
@@ -4,16 +4,18 @@
#include "cc/trees/presentation_time_callback_buffer.h"
+#include "base/bind.h"
+#include "base/callback.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
-std::vector<cc::PresentationTimeCallbackBuffer::CallbackType> GenerateCallbacks(
- int num_callbacks) {
- std::vector<cc::PresentationTimeCallbackBuffer::CallbackType> result;
+std::vector<cc::PresentationTimeCallbackBuffer::MainCallback>
+GenerateMainCallbacks(int num_callbacks) {
+ std::vector<cc::PresentationTimeCallbackBuffer::MainCallback> result;
while (num_callbacks-- > 0) {
- // PresentationTimeCallbackBuffer isn't supposed to invoke any callbacks.
+ // `PresentationTimeCallbackBuffer` isn't supposed to invoke any callbacks.
// We can check for that by passing callbacks which cause test failure.
result.push_back(base::BindOnce([](const gfx::PresentationFeedback&) {
FAIL() << "Callbacks should not be directly invoked by "
@@ -24,6 +26,22 @@ std::vector<cc::PresentationTimeCallbackBuffer::CallbackType> GenerateCallbacks(
return result;
}
+std::vector<cc::PresentationTimeCallbackBuffer::CompositorCallback>
+GenerateCompositorCallbacks(int num_callbacks) {
+ std::vector<cc::PresentationTimeCallbackBuffer::CompositorCallback> result;
+
+ while (num_callbacks-- > 0) {
+ // `PresentationTimeCallbackBuffer` isn't supposed to invoke any callbacks.
+ // We can check for that by passing callbacks which cause test failure.
+ result.push_back(base::BindOnce([](base::TimeTicks presentation_timestamp) {
+ FAIL() << "Callbacks should not be directly invoked by "
+ "PresentationTimeCallbackBuffer";
+ }));
+ }
+
+ return result;
+}
+
constexpr uint32_t kFrameToken1 = 234;
constexpr uint32_t kFrameToken2 = 345;
constexpr uint32_t kFrameToken3 = 456;
@@ -36,7 +54,7 @@ namespace cc {
TEST(PresentationTimeCallbackBufferTest, TestNoCallbacks) {
PresentationTimeCallbackBuffer buffer;
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
@@ -46,25 +64,25 @@ TEST(PresentationTimeCallbackBufferTest, TestOneMainThreadCallback) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
+ GenerateMainCallbacks(1));
// Make sure that popping early frame tokens doesn't return irrelevant
// entries.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
// Make sure that the buffer has removed the registration since the "pop".
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
@@ -73,26 +91,26 @@ TEST(PresentationTimeCallbackBufferTest, TestOneMainThreadCallback) {
TEST(PresentationTimeCallbackBufferTest, TestOneCompositorThreadCallback) {
PresentationTimeCallbackBuffer buffer;
- buffer.RegisterCompositorPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken2, GenerateCompositorCallbacks(1));
// Make sure that popping early frame tokens doesn't return irrelevant
// entries.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_EQ(result.compositor_thread_callbacks.size(), 1ull);
}
// Make sure that the buffer has removed the registration since the "pop".
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
@@ -102,27 +120,27 @@ TEST(PresentationTimeCallbackBufferTest, TestMixedCallbacks) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
- buffer.RegisterCompositorPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(1));
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken2, GenerateCompositorCallbacks(1));
// Make sure that popping early frame tokens doesn't return irrelevant
// entries.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken1);
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
EXPECT_EQ(result.compositor_thread_callbacks.size(), 1ull);
}
// Make sure that the buffer has removed the registrations since the "pop".
{
- auto result = buffer.PopPendingCallbacks(kFrameToken2);
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_thread_callbacks.empty());
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
@@ -133,19 +151,66 @@ TEST(PresentationTimeCallbackBufferTest, TestCallbackBatching) {
// Register one callback for frame1, two for frame2 and two for frame4.
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken1,
- GenerateCallbacks(1));
+ GenerateMainCallbacks(1));
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
- GenerateCallbacks(2));
+ GenerateMainCallbacks(2));
buffer.RegisterMainThreadPresentationCallbacks(kFrameToken4,
- GenerateCallbacks(2));
+ GenerateMainCallbacks(2));
// Pop callbacks up to and including frame3. Should be three in total; one
// from frame1 and two from frame2.
{
- auto result = buffer.PopPendingCallbacks(kFrameToken3);
+ auto result = buffer.PopPendingCallbacks(kFrameToken3, false);
EXPECT_EQ(result.main_thread_callbacks.size(), 3ull);
EXPECT_TRUE(result.compositor_thread_callbacks.empty());
}
}
+// Tests that popping callbacks for main thread only vs. for both main and
+// compositor threads works properly.
+TEST(PresentationTimeCallbackBufferTest, PopMainCallbacksOnly) {
+ PresentationTimeCallbackBuffer buffer;
+
+ // Register callbacks for main and compositor threads of 3 frames.
+ buffer.RegisterMainThreadPresentationCallbacks(kFrameToken1,
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken1, GenerateCompositorCallbacks(1));
+ buffer.RegisterMainThreadPresentationCallbacks(kFrameToken2,
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken2, GenerateCompositorCallbacks(1));
+ buffer.RegisterMainThreadPresentationCallbacks(kFrameToken3,
+ GenerateMainCallbacks(1));
+ buffer.RegisterCompositorPresentationCallbacks(
+ kFrameToken3, GenerateCompositorCallbacks(1));
+
+ // Pop only main thread callbacks up to and including frame1. The result
+ // should only contain 1 main thread callback of frame1 and no compositor
+ // thread callback.
+ {
+ auto result = buffer.PopPendingCallbacks(kFrameToken1, true);
+ EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
+ EXPECT_TRUE(result.compositor_thread_callbacks.empty());
+ }
+
+ // Pop only main thread callbacks up to and including frame2. The result
+ // should only contain 1 main thread callback of frame2 and no compositor
+ // thread callback.
+ {
+ auto result = buffer.PopPendingCallbacks(kFrameToken2, true);
+ EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
+ EXPECT_TRUE(result.compositor_thread_callbacks.empty());
+ }
+
+ // Pop both main and compositor thread callbacks up to and including frame3.
+ // The result should contain 1 main thread callback of frame3 and all 3
+ // compositor thread callbacks of the 3 frames.
+ {
+ auto result = buffer.PopPendingCallbacks(kFrameToken3, false);
+ EXPECT_EQ(result.main_thread_callbacks.size(), 1ull);
+ EXPECT_EQ(result.compositor_thread_callbacks.size(), 3ull);
+ }
+}
+
} // namespace cc
diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc
index 211e67ce70d..076797230cf 100644
--- a/chromium/cc/trees/property_tree.cc
+++ b/chromium/cc/trees/property_tree.cc
@@ -1495,7 +1495,8 @@ void ScrollTree::CollectScrollDeltas(
CompositorCommitData* commit_data,
ElementId inner_viewport_scroll_element_id,
bool use_fractional_deltas,
- const base::flat_set<ElementId>& snapped_elements) {
+ const base::flat_map<ElementId, TargetSnapAreaElementIds>&
+ snapped_elements) {
DCHECK(!property_trees()->is_main_thread);
TRACE_EVENT0("cc", "ScrollTree::CollectScrollDeltas");
for (auto map_entry : synced_scroll_offset_map_) {
@@ -1505,13 +1506,8 @@ void ScrollTree::CollectScrollDeltas(
ElementId id = map_entry.first;
absl::optional<TargetSnapAreaElementIds> snap_target_ids;
- if (snapped_elements.find(id) != snapped_elements.end()) {
- ScrollNode* scroll_node = FindNodeFromElementId(id);
- if (scroll_node && scroll_node->snap_container_data) {
- snap_target_ids = scroll_node->snap_container_data.value()
- .GetTargetSnapAreaElementIds();
- }
- }
+ if (snapped_elements.contains(id))
+ snap_target_ids = snapped_elements.at(id);
// Snap targets are set at the end of scroll offset animations (i.e when the
// animation state is updated to FINISHED). The state can be updated after
@@ -1724,13 +1720,15 @@ void ScrollTree::SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks) {
callbacks_ = std::move(callbacks);
}
-void ScrollTree::NotifyDidScroll(
+void ScrollTree::NotifyDidCompositorScroll(
ElementId scroll_element_id,
const gfx::ScrollOffset& scroll_offset,
const absl::optional<TargetSnapAreaElementIds>& snap_target_ids) {
DCHECK(property_trees()->is_main_thread);
- if (callbacks_)
- callbacks_->DidScroll(scroll_element_id, scroll_offset, snap_target_ids);
+ if (callbacks_) {
+ callbacks_->DidCompositorScroll(scroll_element_id, scroll_offset,
+ snap_target_ids);
+ }
}
void ScrollTree::NotifyDidChangeScrollbarsHidden(ElementId scroll_element_id,
diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h
index 13a73759d45..3ac68f86ee4 100644
--- a/chromium/cc/trees/property_tree.h
+++ b/chromium/cc/trees/property_tree.h
@@ -23,6 +23,7 @@
#include "cc/paint/filter_operations.h"
#include "cc/trees/mutator_host.h"
#include "cc/trees/sticky_position_constraint.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/transform.h"
@@ -57,12 +58,7 @@ class CC_EXPORT PropertyTree {
public:
PropertyTree();
PropertyTree(const PropertyTree& other) = delete;
-
- // These C++ special member functions cannot be implicit inline because
- // they are exported by CC_EXPORT. They will be instantiated in every
- // compilation units that included this header, and compilation can fail
- // because T may be incomplete.
- virtual ~PropertyTree();
+ ~PropertyTree();
PropertyTree<T>& operator=(const PropertyTree<T>&);
// Property tree node starts from index 0. See equivalent constants in
@@ -78,11 +74,11 @@ class CC_EXPORT PropertyTree {
int Insert(const T& tree_node, int parent_id);
T* Node(int i) {
- DCHECK(i < static_cast<int>(nodes_.size()));
+ CHECK_LT(i, static_cast<int>(nodes_.size()));
return i > kInvalidNodeId ? &nodes_[i] : nullptr;
}
const T* Node(int i) const {
- DCHECK(i < static_cast<int>(nodes_.size()));
+ CHECK_LT(i, static_cast<int>(nodes_.size()));
return i > kInvalidNodeId ? &nodes_[i] : nullptr;
}
@@ -95,7 +91,7 @@ class CC_EXPORT PropertyTree {
void clear();
size_t size() const { return nodes_.size(); }
- virtual void set_needs_update(bool needs_update) {
+ void set_needs_update(bool needs_update) {
needs_update_ = needs_update;
}
bool needs_update() const { return needs_update_; }
@@ -129,7 +125,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
// compilation units that included this header, and compilation can fail
// because TransformCachedNodeData may be incomplete.
TransformTree(const TransformTree&) = delete;
- ~TransformTree() final;
+ ~TransformTree();
TransformTree& operator=(const TransformTree&);
#if DCHECK_IS_ON()
@@ -155,7 +151,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> {
void UpdateNodeOrAncestorsWillChangeTransform(TransformNode* node,
TransformNode* parent_node);
- void set_needs_update(bool needs_update) final;
+ void set_needs_update(bool needs_update);
// We store the page scale factor on the transform tree so that it can be
// easily be retrieved and updated in UpdatePageScale.
@@ -288,7 +284,7 @@ class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {
class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
public:
EffectTree();
- ~EffectTree() final;
+ ~EffectTree();
EffectTree& operator=(const EffectTree& from);
@@ -385,9 +381,10 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
class ScrollCallbacks {
public:
// Called after the composited scroll offset changed.
- virtual void DidScroll(ElementId scroll_element_id,
- const gfx::ScrollOffset&,
- const absl::optional<TargetSnapAreaElementIds>&) = 0;
+ virtual void DidCompositorScroll(
+ ElementId scroll_element_id,
+ const gfx::ScrollOffset&,
+ const absl::optional<TargetSnapAreaElementIds>&) = 0;
// Called after the hidden status of composited scrollbars changed. Note that
// |scroll_element_id| is the element id of the scroll not of the scrollbars.
virtual void DidChangeScrollbarsHidden(ElementId scroll_element_id,
@@ -400,7 +397,7 @@ class ScrollCallbacks {
class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
public:
ScrollTree();
- ~ScrollTree() final;
+ ~ScrollTree();
ScrollTree& operator=(const ScrollTree& from);
@@ -449,10 +446,12 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
// Collects deltas for scroll changes on the impl thread that need to be
// reported to the main thread during the main frame. As such, should only be
// called on the impl thread side PropertyTrees.
- void CollectScrollDeltas(CompositorCommitData* commit_data,
- ElementId inner_viewport_scroll_element_id,
- bool use_fractional_deltas,
- const base::flat_set<ElementId>& snapped_elements);
+ void CollectScrollDeltas(
+ CompositorCommitData* commit_data,
+ ElementId inner_viewport_scroll_element_id,
+ bool use_fractional_deltas,
+ const base::flat_map<ElementId, TargetSnapAreaElementIds>&
+ snapped_elements);
// Applies deltas sent in the previous main frame onto the impl thread state.
// Should only be called on the impl thread side PropertyTrees.
@@ -502,7 +501,7 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
void SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks);
- void NotifyDidScroll(
+ void NotifyDidCompositorScroll(
ElementId scroll_element_id,
const gfx::ScrollOffset& scroll_offset,
const absl::optional<TargetSnapAreaElementIds>& snap_target_ids);
diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc
index 5bd4eeeae24..99083b30235 100644
--- a/chromium/cc/trees/property_tree_builder.cc
+++ b/chromium/cc/trees/property_tree_builder.cc
@@ -10,6 +10,7 @@
#include <memory>
#include <set>
#include <utility>
+#include <vector>
#include "base/auto_reset.h"
#include "cc/base/math_util.h"
@@ -26,6 +27,7 @@
#include "cc/trees/transform_node.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
namespace cc {
@@ -455,6 +457,23 @@ bool PropertyTreeBuilderContext::AddEffectNodeIfNeeded(
node->opacity = layer->opacity();
node->blend_mode = layer->blend_mode();
node->subtree_capture_id = layer->subtree_capture_id();
+
+ // Layers marked with a valid |subtree_capture_id| represent a subsection
+ // of the tree that should be rendered and copied as a separate render pass.
+ // Using the layer bounds as the subtree size here allows us to crop out
+ // undesired sections of the render pass, such as the shadow added by the
+ // shadow layer.
+ //
+ // If it becomes desirable to capture a different sub-rectangle of the render
+ // pass, a new custom size (or potentially rect) can be plumbed through the
+ // layer to here.
+ if (node->subtree_capture_id.is_valid()) {
+ // Layer bounds are specified in layer space, which excludes device and
+ // page scale factors. While the page scale can be ignored for subtree
+ // capture purposes, the device scale must be accounted for here.
+ node->subtree_size = gfx::ScaleToFlooredSize(
+ layer->bounds(), layer_tree_host_->device_scale_factor());
+ }
node->cache_render_surface = layer->cache_render_surface();
node->has_copy_request = layer->HasCopyRequest();
node->filters = layer->filters();
diff --git a/chromium/cc/trees/property_tree_builder_unittest.cc b/chromium/cc/trees/property_tree_builder_unittest.cc
index 2576916ed38..0b11f149d9f 100644
--- a/chromium/cc/trees/property_tree_builder_unittest.cc
+++ b/chromium/cc/trees/property_tree_builder_unittest.cc
@@ -356,8 +356,9 @@ TEST_F(PropertyTreeBuilderTest, VisibleRectWithClippingAndFilters) {
gfx::Transform vertical_flip;
vertical_flip.Scale(1, -1);
- sk_sp<PaintFilter> flip_filter = sk_make_sp<MatrixPaintFilter>(
- SkMatrix(vertical_flip.matrix()), kLow_SkFilterQuality, nullptr);
+ sk_sp<PaintFilter> flip_filter =
+ sk_make_sp<MatrixPaintFilter>(SkMatrix(vertical_flip.matrix()),
+ PaintFlags::FilterQuality::kLow, nullptr);
FilterOperations reflection_filter;
reflection_filter.Append(
FilterOperation::CreateReferenceFilter(sk_make_sp<XfermodePaintFilter>(
@@ -416,8 +417,9 @@ TEST_F(PropertyTreeBuilderTest, VisibleRectWithScalingClippingAndFilters) {
gfx::Transform vertical_flip;
vertical_flip.Scale(1, -1);
- sk_sp<PaintFilter> flip_filter = sk_make_sp<MatrixPaintFilter>(
- SkMatrix(vertical_flip.matrix()), kLow_SkFilterQuality, nullptr);
+ sk_sp<PaintFilter> flip_filter =
+ sk_make_sp<MatrixPaintFilter>(SkMatrix(vertical_flip.matrix()),
+ PaintFlags::FilterQuality::kLow, nullptr);
FilterOperations reflection_filter;
reflection_filter.Append(
FilterOperation::CreateReferenceFilter(sk_make_sp<XfermodePaintFilter>(
@@ -1827,5 +1829,32 @@ TEST_F(PropertyTreeBuilderTest,
kRoundedCorner4Radius * kDeviceScale);
}
+TEST_F(PropertyTreeBuilderTest, SubtreeSize) {
+ constexpr viz::SubtreeCaptureId kCaptureId{42};
+
+ auto parent = Layer::Create();
+ host()->SetRootLayer(parent);
+ auto child = Layer::Create();
+ parent->AddChild(child);
+ child->SetSubtreeCaptureId(kCaptureId);
+
+ // Layer has empty bounds.
+ Commit(1.1f);
+ EffectNode* node = GetEffectNode(child.get());
+ EXPECT_EQ((gfx::Size{}), node->subtree_size);
+ EXPECT_EQ(kCaptureId, node->subtree_capture_id);
+
+ // Layer has bounds, scaling is 1.
+ child->SetBounds(gfx::Size{1280, 720});
+ Commit(1.0f);
+ node = GetEffectNode(child.get());
+ EXPECT_EQ((gfx::Size{1280, 720}), node->subtree_size);
+
+ // Layer has bounds, scaling is 2.
+ Commit(2.0f);
+ node = GetEffectNode(child.get());
+ EXPECT_EQ((gfx::Size{2560, 1440}), node->subtree_size);
+}
+
} // namespace
} // namespace cc
diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h
index c927579ed7b..316fbd1a25e 100644
--- a/chromium/cc/trees/proxy.h
+++ b/chromium/cc/trees/proxy.h
@@ -14,8 +14,10 @@
#include "cc/cc_export.h"
#include "cc/input/browser_controls_state.h"
#include "cc/trees/paint_holding_commit_trigger.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/task_runner_provider.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "url/gurl.h"
@@ -48,6 +50,8 @@ class CC_EXPORT Proxy {
virtual void SetNeedsCommit() = 0;
virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;
virtual void SetNextCommitWaitsForActivation() = 0;
+ virtual void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) = 0;
// Returns true if an animate or commit has been requested, and hasn't
// completed yet.
@@ -61,11 +65,14 @@ class CC_EXPORT Proxy {
// but continues to update the document lifecycle in
// LayerTreeHost::BeginMainFrameUpdate. If multiple calls are made when
// deferal is active the first |timeout| continues to apply.
- virtual void StartDeferringCommits(base::TimeDelta timeout) = 0;
+ virtual bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) = 0;
// Immediately stop deferring commits.
virtual void StopDeferringCommits(PaintHoldingCommitTrigger) = 0;
+ virtual bool IsDeferringCommits() const = 0;
+
virtual bool CommitRequested() const = 0;
// Must be called before using the proxy.
diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc
index 726d6ff1233..2c8babc0eb0 100644
--- a/chromium/cc/trees/proxy_impl.cc
+++ b/chromium/cc/trees/proxy_impl.cc
@@ -187,6 +187,12 @@ void ProxyImpl::SetNeedsCommitOnImpl() {
SetNeedsCommitOnImplThread();
}
+void ProxyImpl::SetTargetLocalSurfaceIdOnImpl(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ DCHECK(IsImplThread());
+ host_impl_->SetTargetLocalSurfaceId(target_local_surface_id);
+}
+
void ProxyImpl::BeginMainFrameAbortedOnImpl(
CommitEarlyOutReason reason,
base::TimeTicks main_thread_start_time,
@@ -404,6 +410,7 @@ void ProxyImpl::RenewTreePriority() {
DCHECK(IsImplThread());
bool scroll_type_considered_interaction = false;
+ bool prefer_new_content = false;
bool non_scroll_interaction_in_progress =
host_impl_->IsPinchGestureActive() ||
host_impl_->page_scale_animation_active();
@@ -430,8 +437,14 @@ void ProxyImpl::RenewTreePriority() {
user_interaction_in_progress);
}
+ if (host_impl_->CurrentScrollDidCheckerboardLargeArea() &&
+ base::FeatureList::IsEnabled(
+ features::kPreferNewContentForCheckerboardedScrolls)) {
+ prefer_new_content = true;
+ }
+
// Schedule expiration if smoothness currently takes priority.
- if (user_interaction_in_progress)
+ if (user_interaction_in_progress && !prefer_new_content)
smoothness_priority_expiration_notifier_.Schedule();
// We use the same priority for both trees by default.
diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h
index 05eb84ed3eb..15f13db26b1 100644
--- a/chromium/cc/trees/proxy_impl.h
+++ b/chromium/cc/trees/proxy_impl.h
@@ -54,6 +54,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
void SetDeferBeginMainFrameOnImpl(bool defer_begin_main_frame) const;
void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
void SetNeedsCommitOnImpl();
+ void SetTargetLocalSurfaceIdOnImpl(
+ const viz::LocalSurfaceId& target_local_surface_id);
void BeginMainFrameAbortedOnImpl(
CommitEarlyOutReason reason,
base::TimeTicks main_thread_start_time,
diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc
index 6f1e341a730..735a814e1f5 100644
--- a/chromium/cc/trees/proxy_main.cc
+++ b/chromium/cc/trees/proxy_main.cc
@@ -22,6 +22,7 @@
#include "cc/trees/layer_tree_frame_sink.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy_impl.h"
#include "cc/trees/render_frame_metadata_observer.h"
#include "cc/trees/scoped_abort_remaining_swap_promises.h"
@@ -41,8 +42,7 @@ ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
deferred_final_pipeline_stage_(NO_PIPELINE_STAGE),
commit_waits_for_activation_(false),
started_(false),
- defer_main_frame_update_(false),
- defer_commits_(false) {
+ defer_main_frame_update_(false) {
TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
DCHECK(task_runner_provider_);
DCHECK(IsMainThread());
@@ -170,24 +170,10 @@ void ProxyMain::BeginMainFrame(
final_pipeline_stage_ = max_requested_pipeline_stage_;
max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
- // When we don't need to produce a CompositorFrame, there's also no need to
- // commit our updates. We still need to run layout and paint though, as it can
- // have side effects on page loading behavior.
- bool skip_commit = begin_main_frame_state->begin_frame_args.animate_only;
-
// If main frame updates and commits are deferred, skip the entire pipeline.
- bool skip_full_pipeline = defer_main_frame_update_;
-
- // We may have previously skipped paint and commit. If we should still skip it
- // now, and there was no intermediate request for a commit since the last
- // BeginMainFrame, we can skip the full pipeline.
- skip_full_pipeline |=
- skip_commit && final_pipeline_stage_ == NO_PIPELINE_STAGE;
-
- if (skip_full_pipeline) {
+ if (defer_main_frame_update_) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
TRACE_EVENT_SCOPE_THREAD);
-
// In this case, since the commit is deferred to a later time, gathered
// events metrics are not discarded so that they can be reported if the
// commit happens in the future.
@@ -215,9 +201,9 @@ void ProxyMain::BeginMainFrame(
// Check now if we should stop deferring commits due to a timeout. We
// may also stop deferring in layer_tree_host_->BeginMainFrame, but update
// the status at this point to keep scroll in sync.
- if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_)
- StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout);
- skip_commit |= defer_commits_;
+ if (IsDeferringCommits() && base::TimeTicks::Now() > commits_restart_time_)
+ StopDeferringCommits(ReasonToTimeoutTrigger(*paint_holding_reason_));
+ bool skip_commit = IsDeferringCommits();
if (!skip_commit) {
// Synchronizes scroll offsets and page scale deltas (for pinch zoom) from
@@ -264,7 +250,12 @@ void ProxyMain::BeginMainFrame(
// avoid committing right now, or we may be deferring commits but not
// deferring main frame updates. Either may have changed the status
// of the defer... flags, so re-evaluate skip_commit.
- skip_commit |= defer_main_frame_update_ || defer_commits_;
+ skip_commit |= defer_main_frame_update_ || IsDeferringCommits();
+
+ // When we don't need to produce a CompositorFrame, there's also no need to
+ // commit our updates. We still need to run layout and paint though, as it can
+ // have side effects on page loading behavior.
+ skip_commit |= begin_main_frame_state->begin_frame_args.animate_only;
if (skip_commit) {
current_pipeline_stage_ = NO_PIPELINE_STAGE;
@@ -317,7 +308,8 @@ void ProxyMain::BeginMainFrame(
layer_tree_host_->WillCommit();
devtools_instrumentation::ScopedCommitTrace commit_task(
- layer_tree_host_->GetId());
+ layer_tree_host_->GetId(),
+ begin_main_frame_state->begin_frame_args.frame_id.sequence_number);
current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
if (final_pipeline_stage_ < COMMIT_PIPELINE_STAGE) {
@@ -387,7 +379,7 @@ void ProxyMain::BeginMainFrame(
void ProxyMain::DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback) {
layer_tree_host_->DidPresentCompositorFrame(frame_token, std::move(callbacks),
feedback);
@@ -477,6 +469,15 @@ void ProxyMain::SetNextCommitWaitsForActivation() {
commit_waits_for_activation_ = true;
}
+void ProxyMain::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ DCHECK(IsMainThread());
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&ProxyImpl::SetTargetLocalSurfaceIdOnImpl,
+ base::Unretained(proxy_impl_.get()),
+ target_local_surface_id));
+}
+
bool ProxyMain::RequestedAnimatePending() {
return max_requested_pipeline_stage_ >= ANIMATE_PIPELINE_STAGE;
}
@@ -505,35 +506,43 @@ void ProxyMain::SetDeferMainFrameUpdate(bool defer_main_frame_update) {
defer_main_frame_update));
}
-void ProxyMain::StartDeferringCommits(base::TimeDelta timeout) {
+bool ProxyMain::StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) {
DCHECK(task_runner_provider_->IsMainThread());
// Do nothing if already deferring. The timeout remains as it was from when
// we most recently began deferring.
- if (defer_commits_)
- return;
+ if (IsDeferringCommits())
+ return false;
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "ProxyMain::SetDeferCommits",
TRACE_ID_LOCAL(this));
- defer_commits_ = true;
+ paint_holding_reason_ = reason;
commits_restart_time_ = base::TimeTicks::Now() + timeout;
// Notify dependent systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(true, reason);
+ return true;
}
void ProxyMain::StopDeferringCommits(PaintHoldingCommitTrigger trigger) {
- if (!defer_commits_)
+ if (!IsDeferringCommits())
return;
- defer_commits_ = false;
+ auto reason = *paint_holding_reason_;
+ paint_holding_reason_.reset();
UMA_HISTOGRAM_ENUMERATION("PaintHolding.CommitTrigger2", trigger);
commits_restart_time_ = base::TimeTicks();
TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "ProxyMain::SetDeferCommits",
TRACE_ID_LOCAL(this));
// Notify depended systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(false, reason);
+}
+
+bool ProxyMain::IsDeferringCommits() const {
+ DCHECK(IsMainThread());
+ return paint_holding_reason_.has_value();
}
bool ProxyMain::CommitRequested() const {
diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h
index 186de9d07b6..1157b1adcfb 100644
--- a/chromium/cc/trees/proxy_main.h
+++ b/chromium/cc/trees/proxy_main.h
@@ -11,6 +11,7 @@
#include "cc/cc_export.h"
#include "cc/input/browser_controls_state.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy.h"
#include "cc/trees/proxy_common.h"
@@ -58,7 +59,7 @@ class CC_EXPORT ProxyMain : public Proxy {
std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
void DidPresentCompositorFrame(
uint32_t frame_token,
- std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
+ std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks,
const gfx::PresentationFeedback& feedback);
void NotifyThroughputTrackerResults(CustomTrackerResults results);
void DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay,
@@ -85,10 +86,14 @@ class CC_EXPORT ProxyMain : public Proxy {
void SetNeedsCommit() override;
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
void SetNextCommitWaitsForActivation() override;
+ void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) override;
bool RequestedAnimatePending() override;
void SetDeferMainFrameUpdate(bool defer_main_frame_update) override;
- void StartDeferringCommits(base::TimeDelta timeout) override;
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) override;
void StopDeferringCommits(PaintHoldingCommitTrigger) override;
+ bool IsDeferringCommits() const override;
bool CommitRequested() const override;
void Start() override;
void Stop() override;
@@ -146,9 +151,9 @@ class CC_EXPORT ProxyMain : public Proxy {
bool started_;
// defer_main_frame_update_ will also cause commits to be deferred, regardless
- // of the setting for defer_commits_.
+ // of the setting for paint_holding_reason_.
bool defer_main_frame_update_;
- bool defer_commits_;
+ absl::optional<PaintHoldingReason> paint_holding_reason_;
// Only used when defer_commits_ is active and must be set in such cases.
base::TimeTicks commits_restart_time_;
diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h
index b178e47f83d..33c764c370a 100644
--- a/chromium/cc/trees/scroll_node.h
+++ b/chromium/cc/trees/scroll_node.h
@@ -11,6 +11,7 @@
#include "cc/input/scroll_snap_data.h"
#include "cc/paint/element_id.h"
#include "cc/paint/filter_operations.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
namespace base {
diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc
index a24ce56473e..3dfb23d7532 100644
--- a/chromium/cc/trees/single_thread_proxy.cc
+++ b/chromium/cc/trees/single_thread_proxy.cc
@@ -27,6 +27,7 @@
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/mutator_host.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/render_frame_metadata_observer.h"
#include "cc/trees/scoped_abort_remaining_swap_promises.h"
#include "components/power_scheduler/power_mode_arbiter.h"
@@ -56,7 +57,6 @@ SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
#endif
inside_draw_(false),
defer_main_frame_update_(false),
- defer_commits_(false),
animate_requested_(false),
update_layers_requested_(false),
commit_requested_(false),
@@ -194,7 +194,7 @@ void SingleThreadProxy::DoCommit(const viz::BeginFrameArgs& commit_args) {
layer_tree_host_->WillCommit();
devtools_instrumentation::ScopedCommitTrace commit_task(
- layer_tree_host_->GetId());
+ layer_tree_host_->GetId(), commit_args.frame_id.sequence_number);
// Commit immediately.
{
@@ -271,6 +271,13 @@ void SingleThreadProxy::SetNextCommitWaitsForActivation() {
DCHECK(task_runner_provider_->IsMainThread());
}
+void SingleThreadProxy::SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) {
+ if (!scheduler_on_impl_thread_)
+ return;
+ host_impl_->SetTargetLocalSurfaceId(target_local_surface_id);
+}
+
bool SingleThreadProxy::RequestedAnimatePending() {
return animate_requested_ || update_layers_requested_ || commit_requested_ ||
needs_impl_frame_;
@@ -303,36 +310,44 @@ void SingleThreadProxy::SetDeferMainFrameUpdate(bool defer_main_frame_update) {
scheduler_on_impl_thread_->SetDeferBeginMainFrame(defer_main_frame_update_);
}
-void SingleThreadProxy::StartDeferringCommits(base::TimeDelta timeout) {
+bool SingleThreadProxy::StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) {
DCHECK(task_runner_provider_->IsMainThread());
// Do nothing if already deferring. The timeout remains as it was from when
// we most recently began deferring.
- if (defer_commits_)
- return;
+ if (IsDeferringCommits())
+ return false;
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits",
TRACE_ID_LOCAL(this));
- defer_commits_ = true;
+ paint_holding_reason_ = reason;
commits_restart_time_ = base::TimeTicks::Now() + timeout;
// Notify dependent systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(true, reason);
+ return true;
}
void SingleThreadProxy::StopDeferringCommits(
PaintHoldingCommitTrigger trigger) {
- if (!defer_commits_)
+ if (!IsDeferringCommits())
return;
- defer_commits_ = false;
+ auto reason = *paint_holding_reason_;
+ paint_holding_reason_.reset();
commits_restart_time_ = base::TimeTicks();
UMA_HISTOGRAM_ENUMERATION("PaintHolding.CommitTrigger2", trigger);
TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits",
TRACE_ID_LOCAL(this));
// Notify dependent systems that the deferral status has changed.
- layer_tree_host_->OnDeferCommitsChanged(defer_commits_);
+ layer_tree_host_->OnDeferCommitsChanged(false, reason);
+}
+
+bool SingleThreadProxy::IsDeferringCommits() const {
+ DCHECK(task_runner_provider_->IsMainThread());
+ return paint_holding_reason_.has_value();
}
bool SingleThreadProxy::CommitRequested() const {
@@ -533,15 +548,13 @@ void SingleThreadProxy::DidPresentCompositorFrameOnImplThread(
uint32_t frame_token,
PresentationTimeCallbackBuffer::PendingCallbacks callbacks,
const viz::FrameTimingDetails& details) {
- std::vector<LayerTreeHost::PresentationTimeCallback> main_thread_callbacks =
- std::move(callbacks.main_thread_callbacks);
DebugScopedSetImplThread impl(task_runner_provider_);
host_impl_->NotifyDidPresentCompositorFrameOnImplThread(
frame_token, std::move(callbacks.compositor_thread_callbacks), details);
{
DebugScopedSetMainThread main(task_runner_provider_);
layer_tree_host_->DidPresentCompositorFrame(
- frame_token, std::move(main_thread_callbacks),
+ frame_token, std::move(callbacks.main_thread_callbacks),
details.presentation_feedback);
}
if (scheduler_on_impl_thread_) {
@@ -852,8 +865,8 @@ void SingleThreadProxy::BeginMainFrame(
// Check now if we should stop deferring commits. Do this before
// DoBeginMainFrame because the latter updates scroll offsets, which
// we should avoid if deferring commits.
- if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_)
- StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout);
+ if (IsDeferringCommits() && base::TimeTicks::Now() > commits_restart_time_)
+ StopDeferringCommits(ReasonToTimeoutTrigger(*paint_holding_reason_));
DoBeginMainFrame(begin_frame_args);
@@ -862,7 +875,7 @@ void SingleThreadProxy::BeginMainFrame(
// At this point the main frame may have deferred commits to avoid committing
// right now.
- if (defer_main_frame_update_ || defer_commits_ ||
+ if (defer_main_frame_update_ || IsDeferringCommits() ||
begin_frame_args.animate_only) {
TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit_InsideBeginMainFrame",
TRACE_EVENT_SCOPE_THREAD);
@@ -879,7 +892,7 @@ void SingleThreadProxy::DoBeginMainFrame(
const viz::BeginFrameArgs& begin_frame_args) {
// Only update scroll deltas if we are going to commit the frame, otherwise
// scroll offsets get confused.
- if (!defer_commits_) {
+ if (!IsDeferringCommits()) {
// The impl-side scroll deltas may be manipulated directly via the
// InputHandler on the UI thread and the scale deltas may change when they
// are clamped on the impl thread.
diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h
index c5d23a90a38..9d3c9f1864b 100644
--- a/chromium/cc/trees/single_thread_proxy.h
+++ b/chromium/cc/trees/single_thread_proxy.h
@@ -14,9 +14,11 @@
#include "base/time/time.h"
#include "cc/scheduler/scheduler.h"
#include "cc/trees/layer_tree_host_impl.h"
+#include "cc/trees/paint_holding_reason.h"
#include "cc/trees/proxy.h"
#include "cc/trees/task_runner_provider.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
namespace viz {
class BeginFrameSource;
@@ -53,10 +55,14 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void SetNeedsCommit() override;
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
void SetNextCommitWaitsForActivation() override;
+ void SetTargetLocalSurfaceId(
+ const viz::LocalSurfaceId& target_local_surface_id) override;
bool RequestedAnimatePending() override;
void SetDeferMainFrameUpdate(bool defer_main_frame_update) override;
- void StartDeferringCommits(base::TimeDelta timeout) override;
+ bool StartDeferringCommits(base::TimeDelta timeout,
+ PaintHoldingReason reason) override;
void StopDeferringCommits(PaintHoldingCommitTrigger) override;
+ bool IsDeferringCommits() const override;
bool CommitRequested() const override;
void Start() override;
void Stop() override;
@@ -204,7 +210,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
#endif
bool inside_draw_;
bool defer_main_frame_update_;
- bool defer_commits_;
+ absl::optional<PaintHoldingReason> paint_holding_reason_;
bool animate_requested_;
bool update_layers_requested_;
bool commit_requested_;
diff --git a/chromium/cc/trees/sticky_position_constraint.cc b/chromium/cc/trees/sticky_position_constraint.cc
index 19f4cabe0fe..bc163937dae 100644
--- a/chromium/cc/trees/sticky_position_constraint.cc
+++ b/chromium/cc/trees/sticky_position_constraint.cc
@@ -19,6 +19,9 @@ StickyPositionConstraint::StickyPositionConstraint()
StickyPositionConstraint::StickyPositionConstraint(
const StickyPositionConstraint& other) = default;
+StickyPositionConstraint& StickyPositionConstraint::operator=(
+ const StickyPositionConstraint& other) = default;
+
bool StickyPositionConstraint::operator==(
const StickyPositionConstraint& other) const {
return is_anchored_left == other.is_anchored_left &&
diff --git a/chromium/cc/trees/sticky_position_constraint.h b/chromium/cc/trees/sticky_position_constraint.h
index 3a6ac2408dc..94b016753b8 100644
--- a/chromium/cc/trees/sticky_position_constraint.h
+++ b/chromium/cc/trees/sticky_position_constraint.h
@@ -17,6 +17,7 @@ namespace cc {
struct CC_EXPORT StickyPositionConstraint {
StickyPositionConstraint();
StickyPositionConstraint(const StickyPositionConstraint& other);
+ StickyPositionConstraint& operator=(const StickyPositionConstraint& other);
bool is_anchored_left : 1;
bool is_anchored_right : 1;
diff --git a/chromium/cc/trees/throttle_decider.cc b/chromium/cc/trees/throttle_decider.cc
index 3ce286bc80b..f2f31cfa327 100644
--- a/chromium/cc/trees/throttle_decider.cc
+++ b/chromium/cc/trees/throttle_decider.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "cc/layers/surface_layer_impl.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/surface_range.h"
@@ -86,6 +87,14 @@ void ThrottleDecider::ProcessRenderPass(
id_to_pass_map_.emplace(render_pass.id, &render_pass);
}
+void ThrottleDecider::ProcessLayerNotToDraw(const LayerImpl* layer) {
+ if (layer->is_surface_layer()) {
+ const auto* surface_layer = static_cast<const SurfaceLayerImpl*>(layer);
+ if (surface_layer->range().IsValid())
+ ids_.insert(surface_layer->range().end().frame_sink_id());
+ }
+}
+
bool ThrottleDecider::HasThrottlingChanged() const {
return ids_ != last_ids_;
}
diff --git a/chromium/cc/trees/throttle_decider.h b/chromium/cc/trees/throttle_decider.h
index d41479a423c..eb1c3418f26 100644
--- a/chromium/cc/trees/throttle_decider.h
+++ b/chromium/cc/trees/throttle_decider.h
@@ -12,6 +12,7 @@
#include "components/viz/common/surfaces/frame_sink_id.h"
namespace cc {
+class LayerImpl;
// This class is used to decide if any frame sinks in a render pass list
// satisfies the compositing-based criteria to be throttled.
@@ -30,6 +31,9 @@ class CC_EXPORT ThrottleDecider {
// intersection calculation of surface/quad rects are confined to the render
// pass's constituent quads.
void ProcessRenderPass(const viz::CompositorRenderPass& render_pass);
+ // Process a layer that will not draw. This is only relevant for surface
+ // layers and checks if the embedded frame sink is qualified for throttling.
+ void ProcessLayerNotToDraw(const LayerImpl* layer);
bool HasThrottlingChanged() const;
const base::flat_set<viz::FrameSinkId>& ids() const { return ids_; }
diff --git a/chromium/cc/trees/transform_node.cc b/chromium/cc/trees/transform_node.cc
index 1c91fcae2fc..765b6fbf836 100644
--- a/chromium/cc/trees/transform_node.cc
+++ b/chromium/cc/trees/transform_node.cc
@@ -39,6 +39,8 @@ TransformNode::TransformNode()
TransformNode::TransformNode(const TransformNode&) = default;
+TransformNode& TransformNode::operator=(const TransformNode&) = default;
+
#if DCHECK_IS_ON()
bool TransformNode::operator==(const TransformNode& other) const {
return id == other.id && parent_id == other.parent_id &&
diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h
index 71d8e98f459..2e62467e4e5 100644
--- a/chromium/cc/trees/transform_node.h
+++ b/chromium/cc/trees/transform_node.h
@@ -23,6 +23,7 @@ namespace cc {
struct CC_EXPORT TransformNode {
TransformNode();
TransformNode(const TransformNode&);
+ TransformNode& operator=(const TransformNode&);
// The node index of this node in the transform tree node vector.
int id;
diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc
index 7a1d5b0def0..6b89b13c49f 100644
--- a/chromium/cc/trees/tree_synchronizer_unittest.cc
+++ b/chromium/cc/trees/tree_synchronizer_unittest.cc
@@ -662,9 +662,9 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) {
// Pull ScrollOffset delta for main thread, and change offset on main thread
std::unique_ptr<CompositorCommitData> commit_data(new CompositorCommitData());
- scroll_tree.CollectScrollDeltas(commit_data.get(), ElementId(),
- settings.commit_fractional_scroll_deltas,
- base::flat_set<ElementId>());
+ scroll_tree.CollectScrollDeltas(
+ commit_data.get(), ElementId(), settings.commit_fractional_scroll_deltas,
+ base::flat_map<ElementId, TargetSnapAreaElementIds>());
host_->proxy()->SetNeedsCommit();
host_->ApplyCompositorChanges(commit_data.get());
EXPECT_EQ(gfx::ScrollOffset(20, 30), scroll_layer->scroll_offset());
diff --git a/chromium/cc/trees/ukm_manager_unittest.cc b/chromium/cc/trees/ukm_manager_unittest.cc
index 4e36a6e2fd3..738de678558 100644
--- a/chromium/cc/trees/ukm_manager_unittest.cc
+++ b/chromium/cc/trees/ukm_manager_unittest.cc
@@ -142,13 +142,11 @@ class UkmManagerTest : public testing::Test {
std::unique_ptr<EventMetrics> CreateEventMetrics(
ui::EventType type,
- absl::optional<EventMetrics::ScrollUpdateType> scroll_update_type,
- absl::optional<ui::ScrollInputType> scroll_input_type) {
+ absl::optional<EventMetrics::ScrollParams> scroll_params) {
base::TimeTicks event_time = AdvanceNowByMs(10);
AdvanceNowByMs(10);
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
- type, scroll_update_type, scroll_input_type, event_time,
- &test_tick_clock_);
+ type, scroll_params, event_time, &test_tick_clock_);
if (metrics) {
AdvanceNowByMs(10);
metrics->SetDispatchStageTimestamp(
@@ -523,15 +521,24 @@ TEST_P(UkmManagerCompositorLatencyTest, CompositorLatency) {
}
TEST_F(UkmManagerTest, EventLatency) {
+ const bool kIsInertial = true;
+ const bool kIsNotInertial = false;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
- CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN, absl::nullopt,
- ui::ScrollInputType::kWheel),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN,
+ EventMetrics::ScrollParams(ui::ScrollInputType::kWheel,
+ kIsNotInertial)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kStarted,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kStarted)),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
- EventMetrics::ScrollUpdateType::kContinued,
- ui::ScrollInputType::kWheel),
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsNotInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
+ CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
+ EventMetrics::ScrollParams(
+ ui::ScrollInputType::kWheel, kIsInertial,
+ EventMetrics::ScrollUpdateType::kContinued)),
};
EXPECT_THAT(event_metrics_ptrs, ::testing::Each(::testing::NotNull()));
EventMetrics::List events_metrics(
@@ -609,7 +616,7 @@ TEST_F(UkmManagerTest, EventLatency) {
processed_viz_breakdown);
const auto& entries = test_ukm_recorder_->GetEntriesByName(kEventLatency);
- EXPECT_EQ(3u, entries.size());
+ EXPECT_EQ(4u, entries.size());
for (size_t i = 0; i < entries.size(); i++) {
const auto* entry = entries[i];
const auto* event_metrics = events_metrics[i].get();