diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-26 13:57:00 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-11-02 11:31:01 +0000 |
commit | 1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch) | |
tree | 8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/cc/trees | |
parent | 21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff) |
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/trees')
64 files changed, 1436 insertions, 426 deletions
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(); |