diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-12 09:13:00 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-16 09:58:26 +0000 |
commit | 03561cae90f1d99b5c54b1ef3be69f10e882b25e (patch) | |
tree | cc5f0958e823c044e7ae51cc0117fe51432abe5e /chromium/cc/trees | |
parent | fa98118a45f7e169f8846086dc2c22c49a8ba310 (diff) |
BASELINE: Update Chromium to 88.0.4324.208
Change-Id: I3ae87d23e4eff4b4a469685658740a213600c667
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc/trees')
36 files changed, 737 insertions, 399 deletions
diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc index b6f3dc9822d..48499b8b57e 100644 --- a/chromium/cc/trees/damage_tracker.cc +++ b/chromium/cc/trees/damage_tracker.cc @@ -441,7 +441,17 @@ void DamageTracker::AccumulateDamageFromRenderSurface( // The surface's old region is now exposed on the target surface, too. damage_for_this_update_.Union(old_surface_rect); + render_surface->set_can_use_cached_backdrop_filtered_result(false); } else { + // Check if current accumulated damage intersects the render surface. + gfx::Rect damage_on_target; + bool valid = damage_for_this_update_.GetAsRect(&damage_on_target); + if (valid && !damage_on_target.Intersects(surface_rect_in_target_space)) { + surfaces_with_backdrop_blur_filter.emplace_back( + std::make_pair(render_surface, surface_rect_in_target_space)); + } else { + render_surface->set_can_use_cached_backdrop_filtered_result(false); + } // Only the surface's damage_rect will damage the target surface. gfx::Rect damage_rect_in_local_space; bool is_valid_rect = render_surface->damage_tracker()->GetDamageRectIfValid( @@ -460,21 +470,6 @@ void DamageTracker::AccumulateDamageFromRenderSurface( } } - const FilterOperations& backdrop_filters = render_surface->BackdropFilters(); - if (!surface_is_new && - backdrop_filters.HasFilterOfType(FilterOperation::BLUR)) { - gfx::Rect damage_on_target; - bool valid = damage_for_this_update_.GetAsRect(&damage_on_target); - if (!valid || damage_on_target.Intersects(surface_rect_in_target_space)) { - render_surface->set_can_use_cached_backdrop_filtered_result(false); - } else { - surfaces_with_backdrop_blur_filter.push_back( - std::make_pair(render_surface, surface_rect_in_target_space)); - } - } else { - render_surface->set_can_use_cached_backdrop_filtered_result(false); - } - // True if any changes from contributing render surface. has_damage_from_contributing_content_ |= !damage_for_this_update_.IsEmpty(); } diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 3e4714170b6..4b9213336ec 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -2059,20 +2059,18 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result()); EmulateDrawingOneFrame(root); + // child1_'s render target has changed its surface property. EXPECT_FALSE( GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result()); // Let run for one update and there should be no damage left. - ClearDamageForAllSurfaces(root); EmulateDrawingOneFrame(root); EXPECT_TRUE( GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result()); // CASE 1.1: Setting a non-intersecting update rect on the root // doesn't invalidate child1_'s cached backdrop-filtered result. - // Damage rect at 0,0 20x20 (expanded to -6,-6 32x32) doesn't intersect - // 270,270 36x38. - ClearDamageForAllSurfaces(root); + // Damage rect at 0,0 20x20 doesn't intersect 270,270 36x38. root->UnionUpdateRect(gfx::Rect(0, 0, 20, 20)); EmulateDrawingOneFrame(root); EXPECT_TRUE( @@ -2080,8 +2078,7 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { // CASE 1.2: Setting an intersecting update rect on the root invalidates // child1_'s cached backdrop-filtered result. - // Damage rect at 260,260 20x20 (expanded to 254,254 32x32) intersects 270,270 - // 36x38. + // Damage rect at 260,260 20x20 intersects 270,270 36x38. ClearDamageForAllSurfaces(root); root->UnionUpdateRect(gfx::Rect(260, 260, 20, 20)); EmulateDrawingOneFrame(root); @@ -2113,7 +2110,6 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { ->can_use_cached_backdrop_filtered_result()); // Let run for one update and there should be no damage left. - ClearDamageForAllSurfaces(root); EmulateDrawingOneFrame(root); EXPECT_TRUE(GetRenderSurface(grand_child4_) ->can_use_cached_backdrop_filtered_result()); @@ -2121,7 +2117,6 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { // CASE 3.1: Adding a non-intersecting damage rect to a sibling layer under // the render surface with the backdrop filter doesn't invalidate cached // backdrop-filtered result. Damage rect on grand_child1_ at 302,302 1x1 - // expanded by a 6-pixel spread (296,296 13x13) // doesn't intersect 280,280 15x16. ClearDamageForAllSurfaces(root); grand_child1_->AddDamageRect(gfx::Rect(2, 2, 1.f, 1.f)); @@ -2132,7 +2127,6 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { // CASE 3.2: Adding an intersecting damage rect to a sibling layer under the // render surface with the backdrop filter invalidates cached // backdrop-filtered result. Damage rect on grand_child2_ at 290,290 1x1 - // expanded by a 6-pixel spread (284,284 13x13) // intersects 280,280 15x16. ClearDamageForAllSurfaces(root); grand_child2_->AddDamageRect(gfx::Rect(0, 0, 1.f, 1.f)); @@ -2151,8 +2145,8 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { ->damage_tracker() ->GetDamageRectIfValid(&damage_rect)); EXPECT_EQ(gfx::Rect(170, 170, 1.f, 1.f), damage_rect); - // Damage rect at 170,170 1x1 (expanded to 164,164 13x13) in render target - // local space doesn't intersect 180,180 15x16. + // Damage rect at 170,170 1x1 in render target local space doesn't intersect + // 180,180 15x16. EXPECT_TRUE(GetRenderSurface(grand_child4_) ->can_use_cached_backdrop_filtered_result()); @@ -2166,8 +2160,8 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { ->damage_tracker() ->GetDamageRectIfValid(&damage_rect)); EXPECT_EQ(gfx::Rect(170, 170, 11.f, 11.f), damage_rect); - // Damage rect at 170,170 11x11 (expanded to 164,164 23x23) in render target - // local space intersects 180,180 15x16 + // Damage rect at 170,170 11x11 in render target local space intersects + // 180,180 15x16 EXPECT_FALSE(GetRenderSurface(grand_child4_) ->can_use_cached_backdrop_filtered_result()); diff --git a/chromium/cc/trees/debug_rect_history.cc b/chromium/cc/trees/debug_rect_history.cc index f9aae396584..f2455eb24d3 100644 --- a/chromium/cc/trees/debug_rect_history.cc +++ b/chromium/cc/trees/debug_rect_history.cc @@ -7,6 +7,7 @@ #include <stddef.h> #include "base/memory/ptr_util.h" +#include "cc/base/features.h" #include "cc/base/math_util.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer_impl.h" @@ -161,24 +162,39 @@ void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) { } void DebugRectHistory::SaveWheelEventHandlerRects(LayerTreeImpl* tree_impl) { - EventListenerProperties event_properties = - tree_impl->event_listener_properties(EventListenerClass::kMouseWheel); - if (event_properties == EventListenerProperties::kNone || - event_properties == EventListenerProperties::kPassive) { - return; - } + // TODO(https://crbug.com/1136591): Need behavior confirmation. + // TODO(https://crbug.com/1136591): Need to check results in dev tools layer + // view. + if (base::FeatureList::IsEnabled(::features::kWheelEventRegions)) { + for (auto* layer : *tree_impl) { + const Region& region = layer->wheel_event_handler_region(); + for (gfx::Rect rect : region) { + debug_rects_.emplace_back( + DebugRect(WHEEL_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), rect))); + } + } + } else { + EventListenerProperties event_properties = + tree_impl->event_listener_properties(EventListenerClass::kMouseWheel); + if (event_properties == EventListenerProperties::kNone || + event_properties == EventListenerProperties::kPassive) { + return; + } - // Since the wheel event handlers property is on the entire layer tree just - // mark inner viewport if have listeners. - ScrollNode* inner_scroll = tree_impl->InnerViewportScrollNode(); - if (!inner_scroll) - return; - debug_rects_.push_back( - DebugRect(WHEEL_EVENT_HANDLER_RECT_TYPE, - MathUtil::MapEnclosingClippedRect( - tree_impl->property_trees()->transform_tree.ToScreen( - inner_scroll->transform_id), - gfx::Rect(inner_scroll->bounds)))); + // Since the wheel event handlers property is on the entire layer tree just + // mark inner viewport if have listeners. + ScrollNode* inner_scroll = tree_impl->InnerViewportScrollNode(); + if (!inner_scroll) + return; + debug_rects_.emplace_back( + DebugRect(WHEEL_EVENT_HANDLER_RECT_TYPE, + MathUtil::MapEnclosingClippedRect( + tree_impl->property_trees()->transform_tree.ToScreen( + inner_scroll->transform_id), + gfx::Rect(inner_scroll->bounds)))); + } } void DebugRectHistory::SaveScrollEventHandlerRects(LayerTreeImpl* tree_impl) { diff --git a/chromium/cc/trees/draw_properties_unittest.cc b/chromium/cc/trees/draw_properties_unittest.cc index 4335955fe9a..d461d6ae08d 100644 --- a/chromium/cc/trees/draw_properties_unittest.cc +++ b/chromium/cc/trees/draw_properties_unittest.cc @@ -12,7 +12,6 @@ #include "base/memory/ptr_util.h" #include "base/stl_util.h" -#include "base/test/scoped_feature_list.h" #include "cc/animation/animation.h" #include "cc/animation/animation_host.h" #include "cc/animation/animation_id_provider.h" @@ -8123,12 +8122,12 @@ TEST_F(DrawPropertiesTestWithLayerTree, RoundedCornerOnRenderSurface) { UpdateMainDrawProperties(); CommitAndActivate(); - EXPECT_FALSE( - GetRenderSurfaceImpl(child_1)->rounded_corner_bounds().IsEmpty()); - EXPECT_FALSE( - GetRenderSurfaceImpl(child_2)->rounded_corner_bounds().IsEmpty()); - EXPECT_FALSE( - GetRenderSurfaceImpl(child_3)->rounded_corner_bounds().IsEmpty()); + EXPECT_TRUE( + GetRenderSurfaceImpl(child_1)->mask_filter_info().HasRoundedCorners()); + EXPECT_TRUE( + GetRenderSurfaceImpl(child_2)->mask_filter_info().HasRoundedCorners()); + EXPECT_TRUE( + GetRenderSurfaceImpl(child_3)->mask_filter_info().HasRoundedCorners()); } } // namespace diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index 1e007fd3602..c2e79fc3b7e 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -706,27 +706,28 @@ ConditionalClip LayerClipRect(PropertyTrees* property_trees, LayerImpl* layer) { layer->clip_tree_index(), target_node->id); } -std::pair<gfx::RRectF, bool> GetRoundedCornerRRect( +std::pair<gfx::MaskFilterInfo, bool> GetMaskFilterInfoPair( const PropertyTrees* property_trees, int effect_tree_index, bool for_render_surface) { - static const std::pair<gfx::RRectF, bool> kEmptyRoundedCornerInfo( - gfx::RRectF(), false); + static const std::pair<gfx::MaskFilterInfo, bool> kEmptyMaskFilterInfoPair = + std::make_pair(gfx::MaskFilterInfo(), false); + const EffectTree* effect_tree = &property_trees->effect_tree; const EffectNode* effect_node = effect_tree->Node(effect_tree_index); const int target_id = effect_node->target_id; - // Return empty rrect if this node has a render surface but the function call - // was made for a non render surface. + // Return empty mask info if this node has a render surface but the function + // call was made for a non render surface. if (effect_node->HasRenderSurface() && !for_render_surface) - return kEmptyRoundedCornerInfo; + return kEmptyMaskFilterInfoPair; // Traverse the parent chain up to the render target to find a node which has // a rounded corner bounds set. const EffectNode* node = effect_node; bool found_rounded_corner = false; while (node) { - if (!node->rounded_corner_bounds.IsEmpty()) { + if (node->mask_filter_info.HasRoundedCorners()) { found_rounded_corner = true; break; } @@ -749,17 +750,17 @@ std::pair<gfx::RRectF, bool> GetRoundedCornerRRect( // While traversing up the parent chain we did not find any node with a // rounded corner. if (!node || !found_rounded_corner) - return kEmptyRoundedCornerInfo; + return kEmptyMaskFilterInfoPair; gfx::Transform to_target; if (!property_trees->GetToTarget(node->transform_id, target_id, &to_target)) - return kEmptyRoundedCornerInfo; + return kEmptyMaskFilterInfoPair; auto result = - std::make_pair(node->rounded_corner_bounds, node->is_fast_rounded_corner); + std::make_pair(node->mask_filter_info, node->is_fast_rounded_corner); - if (!to_target.TransformRRectF(&result.first)) - return kEmptyRoundedCornerInfo; + if (!result.first.Transform(to_target)) + return kEmptyMaskFilterInfoPair; return result; } @@ -839,9 +840,9 @@ void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); SetSurfaceDrawTransform(property_trees, render_surface); - render_surface->SetRoundedCornerRRect( - GetRoundedCornerRRect(property_trees, render_surface->EffectTreeIndex(), - /*for_render_surface*/ true) + render_surface->SetMaskFilterInfo( + GetMaskFilterInfoPair(property_trees, render_surface->EffectTreeIndex(), + /*for_render_surface=*/true) .first); render_surface->SetScreenSpaceTransform( property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( @@ -1142,12 +1143,12 @@ void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, layer, property_trees->transform_tree, property_trees->effect_tree); layer->draw_properties().screen_space_transform_is_animating = transform_node->to_screen_is_potentially_animated; - auto rounded_corner_info = - GetRoundedCornerRRect(property_trees, layer->effect_tree_index(), - /*from_render_surface*/ false); - layer->draw_properties().rounded_corner_bounds = rounded_corner_info.first; + auto mask_filter_info_pair = + GetMaskFilterInfoPair(property_trees, layer->effect_tree_index(), + /*from_render_surface=*/false); + layer->draw_properties().mask_filter_info = mask_filter_info_pair.first; layer->draw_properties().is_fast_rounded_corner = - rounded_corner_info.second; + mask_filter_info_pair.second; } // Compute effects and determine if render surfaces have contributing layers diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc index de8b74caf4a..fa07fea5b79 100644 --- a/chromium/cc/trees/effect_node.cc +++ b/chromium/cc/trees/effect_node.cc @@ -60,7 +60,7 @@ bool EffectNode::operator==(const EffectNode& other) const { backdrop_filters == other.backdrop_filters && backdrop_filter_bounds == other.backdrop_filter_bounds && backdrop_mask_element_id == other.backdrop_mask_element_id && - rounded_corner_bounds == other.rounded_corner_bounds && + mask_filter_info == other.mask_filter_info && is_fast_rounded_corner == other.is_fast_rounded_corner && node_or_ancestor_has_filters == other.node_or_ancestor_has_filters && affected_by_backdrop_filter == other.affected_by_backdrop_filter && @@ -158,12 +158,18 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { if (!backdrop_filters.IsEmpty()) value->SetString("backdrop_filters", backdrop_filters.ToString()); value->SetDouble("backdrop_filter_quality", backdrop_filter_quality); - value->SetBoolean("is_fast_rounded_corner", is_fast_rounded_corner); value->SetBoolean("node_or_ancestor_has_filters", node_or_ancestor_has_filters); - if (!rounded_corner_bounds.IsEmpty()) { - MathUtil::AddToTracedValue("rounded_corner_bounds", rounded_corner_bounds, + if (!mask_filter_info.IsEmpty()) { + MathUtil::AddToTracedValue("mask_filter_bounds", mask_filter_info.bounds(), value); + if (mask_filter_info.HasRoundedCorners()) { + MathUtil::AddCornerRadiiToTracedValue( + "mask_filter_rounded_corner_raii", + mask_filter_info.rounded_corner_bounds(), value); + value->SetBoolean("mask_filter_is_fast_rounded_corner", + is_fast_rounded_corner); + } } value->SetString("blend_mode", SkBlendMode_Name(blend_mode)); value->SetBoolean("cache_render_surface", cache_render_surface); diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index 4834773cd21..2a2541d123d 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -11,6 +11,7 @@ #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/gfx/mask_filter_info.h" #include "ui/gfx/rrect_f.h" namespace base { @@ -80,9 +81,10 @@ struct CC_EXPORT EffectNode { // image. ElementId backdrop_mask_element_id; - // Bounds of rounded corner rrect in the space of the transform node - // associated with this effect node. - gfx::RRectF rounded_corner_bounds; + // The mask filter information applied to this effect node. The coordinates of + // in the mask info is in the space of the transform node associated with this + // effect node. + gfx::MaskFilterInfo mask_filter_info; SkBlendMode blend_mode; diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 8e390b365f4..03e3c41c5e5 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -33,6 +33,7 @@ #include "base/trace_event/traced_value.h" #include "build/build_config.h" #include "cc/base/devtools_instrumentation.h" +#include "cc/base/features.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" #include "cc/debug/rendering_stats_instrumentation.h" @@ -46,6 +47,7 @@ #include "cc/metrics/ukm_smoothness_data.h" #include "cc/paint/paint_worklet_layer_painter.h" #include "cc/resources/ui_resource_manager.h" +#include "cc/tiles/raster_dark_mode_filter.h" #include "cc/trees/clip_node.h" #include "cc/trees/compositor_commit_data.h" #include "cc/trees/draw_property_utils.h" @@ -141,7 +143,8 @@ LayerTreeHost::LayerTreeHost(InitParams params, CompositorMode mode) id_(s_layer_tree_host_sequence_number.GetNext() + 1), task_graph_runner_(params.task_graph_runner), event_listener_properties_(), - mutator_host_(params.mutator_host) { + mutator_host_(params.mutator_host), + dark_mode_filter_(params.dark_mode_filter) { DCHECK(task_graph_runner_); DCHECK(!settings_.enable_checker_imaging || image_worker_task_runner_); @@ -252,8 +255,8 @@ SwapPromiseManager* LayerTreeHost::GetSwapPromiseManager() { std::unique_ptr<EventsMetricsManager::ScopedMonitor> LayerTreeHost::GetScopedEventMetricsMonitor( - std::unique_ptr<EventMetrics> event_metrics) { - return events_metrics_manager_.GetScopedMonitor(std::move(event_metrics)); + EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) { + return events_metrics_manager_.GetScopedMonitor(std::move(done_callback)); } void LayerTreeHost::ClearEventsMetrics() { @@ -477,7 +480,7 @@ void LayerTreeHost::UpdateDeferMainFrameUpdateInternal() { } bool LayerTreeHost::IsUsingLayerLists() const { - return settings_.use_layer_lists && !force_use_property_tree_builder_; + return settings_.use_layer_lists; } void LayerTreeHost::CommitComplete() { @@ -544,14 +547,15 @@ std::unique_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl( std::unique_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create( settings_, client, task_runner_provider_.get(), rendering_stats_instrumentation_.get(), task_graph_runner_, - std::move(mutator_host_impl), id_, std::move(image_worker_task_runner_), - scheduling_client_); + std::move(mutator_host_impl), dark_mode_filter_, id_, + std::move(image_worker_task_runner_), scheduling_client_); if (ukm_recorder_factory_) { host_impl->InitializeUkm(ukm_recorder_factory_->CreateRecorder()); ukm_recorder_factory_.reset(); } task_graph_runner_ = nullptr; + dark_mode_filter_ = nullptr; compositor_delegate_weak_ptr_ = host_impl->AsWeakPtr(); return host_impl; } @@ -691,12 +695,13 @@ void LayerTreeHost::LayoutAndUpdateLayers() { UpdateLayers(); } -void LayerTreeHost::Composite(base::TimeTicks frame_begin_time, bool raster) { +void LayerTreeHost::CompositeForTest(base::TimeTicks frame_begin_time, + bool raster) { DCHECK(IsSingleThreaded()); // This function is only valid when not using the scheduler. DCHECK(!settings_.single_thread_proxy_scheduler); SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get()); - proxy->CompositeImmediately(frame_begin_time, raster); + proxy->CompositeImmediatelyForTest(frame_begin_time, raster); // IN-TEST } bool LayerTreeHost::UpdateLayers() { @@ -1153,20 +1158,9 @@ void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { // This flag is sticky until a new tree comes along. gpu_rasterization_histogram_recorded_ = false; - force_use_property_tree_builder_ = false; - SetNeedsFullTreeSync(); } -void LayerTreeHost::SetNonBlinkManagedRootLayer( - scoped_refptr<Layer> root_layer) { - SetRootLayer(std::move(root_layer)); - - DCHECK(!root_layer || root_layer_->children().empty()); - if (IsUsingLayerLists() && root_layer_) - force_use_property_tree_builder_ = true; -} - void LayerTreeHost::RegisterViewportPropertyIds( const ViewportPropertyIds& ids) { DCHECK(IsUsingLayerLists()); @@ -1223,7 +1217,8 @@ void LayerTreeHost::SetEventListenerProperties( // Thus when it changes, we want to request every layer to push properties // and recompute its wheel event handler region, since the computation is // done in PushPropertiesTo. - if (event_class == EventListenerClass::kMouseWheel) { + if (event_class == EventListenerClass::kMouseWheel && + !base::FeatureList::IsEnabled(::features::kWheelEventRegions)) { bool new_property_is_blocking = properties == EventListenerProperties::kBlocking || properties == EventListenerProperties::kBlockingAndPassive; diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index c528a84e40b..e5e66fa7cc6 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -37,7 +37,6 @@ #include "cc/layers/layer_collections.h" #include "cc/layers/layer_list_iterator.h" #include "cc/metrics/begin_main_frame_metrics.h" -#include "cc/metrics/event_metrics.h" #include "cc/metrics/events_metrics_manager.h" #include "cc/metrics/frame_sequence_tracker.h" #include "cc/paint/node_id.h" @@ -65,6 +64,7 @@ struct PresentationFeedback; namespace cc { +class RasterDarkModeFilter; class HeadsUpDisplayLayer; class Layer; class LayerTreeHostImpl; @@ -110,6 +110,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { LayerTreeSettings const* settings = nullptr; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner; MutatorHost* mutator_host = nullptr; + RasterDarkModeFilter* dark_mode_filter = nullptr; // The image worker task runner is used to schedule image decodes. The // compositor thread may make sync calls to this thread, analogous to the @@ -183,7 +184,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { SwapPromiseManager* GetSwapPromiseManager(); std::unique_ptr<EventsMetricsManager::ScopedMonitor> - GetScopedEventMetricsMonitor(std::unique_ptr<EventMetrics> event_metrics); + GetScopedEventMetricsMonitor( + EventsMetricsManager::ScopedMonitor::DoneCallback done_callback); void ClearEventsMetrics(); size_t saved_events_metrics_count_for_testing() const { @@ -281,7 +283,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Synchronously performs a complete main frame update, commit and compositor // frame. Used only in single threaded mode when the compositor's internal // scheduling is disabled. - void Composite(base::TimeTicks frame_begin_time, bool raster); + void CompositeForTest(base::TimeTicks frame_begin_time, bool raster); // Requests a redraw (compositor frame) for the given rect. void SetNeedsRedrawRect(const gfx::Rect& damage_rect); @@ -341,14 +343,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { Layer* root_layer() { return root_layer_.get(); } const Layer* root_layer() const { return root_layer_.get(); } - // Sets the root layer which is not managed by blink, and we will initialize - // its paint properties using PropertyTreeBuilder. For ui::Compositor, because - // for now we always use PropertyTreeBulder, this function is equivalent to - // SetRootLayer(). - // TODO(crbug.com/925855): This is temporary. Eventually we should let the - // caller inform blink about the layer and remove the function. - void SetNonBlinkManagedRootLayer(scoped_refptr<Layer> root_layer); - struct ViewportPropertyIds { int overscroll_elasticity_transform = TransformTree::kInvalidNodeId; int page_scale_transform = TransformTree::kInvalidNodeId; @@ -911,15 +905,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // for every layer during property tree building. bool has_copy_request_ = false; - // When settings_.use_layer_lists is true, paint properties are generated by - // blink and we don't use PropertyTreeBuilder, except that the root layer - // is set by SetNonBlinkManagedRootLayer(). - // TODO(crbug.com/925855): Remove this field when removing - // SetNonBlinkManagedRootLayer(). - bool force_use_property_tree_builder_ = false; - MutatorHost* mutator_host_; + RasterDarkModeFilter* dark_mode_filter_; + std::vector<std::pair<PaintImage, base::OnceCallback<void(bool)>>> queued_image_decodes_; std::unordered_map<int, base::OnceCallback<void(bool)>> diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index a97a40874fb..5a804d2f009 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -66,6 +66,16 @@ constexpr ManipulationInfo kManipulationInfoTouch = 1 << 1; constexpr ManipulationInfo kManipulationInfoPrecisionTouchPad = 1 << 2; constexpr ManipulationInfo kManipulationInfoPinchZoom = 1 << 3; +struct PaintBenchmarkResult { + double record_time_ms = 0; + double record_time_caching_disabled_ms = 0; + double record_time_subsequence_caching_disabled_ms = 0; + double record_time_partial_invalidation_ms = 0; + double raster_invalidation_and_convert_time_ms = 0; + double paint_artifact_compositor_update_time_ms = 0; + size_t painter_memory_usage = 0; +}; + // A LayerTreeHost is bound to a LayerTreeHostClient. The main rendering // loop (in ProxyMain or SingleThreadProxy) calls methods on the // LayerTreeHost, which then handles them and also calls into the equivalent @@ -172,6 +182,9 @@ class LayerTreeHostClient { virtual std::unique_ptr<BeginMainFrameMetrics> GetBeginMainFrameMetrics() = 0; virtual void NotifyThroughputTrackerResults(CustomTrackerResults results) = 0; + virtual void RunPaintBenchmark(int repeat_count, + PaintBenchmarkResult& result) {} + protected: virtual ~LayerTreeHostClient() = default; }; diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index bb7ff971823..9efdf67d48c 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -149,6 +149,13 @@ const float kMobileViewportWidthEpsilon = 0.15f; // kHitTestAsk after the threshold is reached. const size_t kAssumeOverlapThreshold = 100; +// gfx::DisplayColorSpaces stores up to 3 different color spaces. This should be +// updated to match any size changes in DisplayColorSpaces. +constexpr size_t kContainsSrgbCacheSize = 3; +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(); @@ -365,12 +372,13 @@ std::unique_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create( RenderingStatsInstrumentation* rendering_stats_instrumentation, TaskGraphRunner* task_graph_runner, std::unique_ptr<MutatorHost> mutator_host, + RasterDarkModeFilter* dark_mode_filter, int id, scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, LayerTreeHostSchedulingClient* scheduling_client) { return base::WrapUnique(new LayerTreeHostImpl( settings, client, task_runner_provider, rendering_stats_instrumentation, - task_graph_runner, std::move(mutator_host), id, + task_graph_runner, std::move(mutator_host), dark_mode_filter, id, std::move(image_worker_task_runner), scheduling_client)); } @@ -381,6 +389,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( RenderingStatsInstrumentation* rendering_stats_instrumentation, TaskGraphRunner* task_graph_runner, std::unique_ptr<MutatorHost> mutator_host, + RasterDarkModeFilter* dark_mode_filter, int id, scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, LayerTreeHostSchedulingClient* scheduling_client) @@ -408,6 +417,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( memory_history_(MemoryHistory::Create()), debug_rect_history_(DebugRectHistory::Create()), mutator_host_(std::move(mutator_host)), + dark_mode_filter_(dark_mode_filter), rendering_stats_instrumentation_(rendering_stats_instrumentation), micro_benchmark_controller_(this), task_graph_runner_(task_graph_runner), @@ -422,7 +432,8 @@ LayerTreeHostImpl::LayerTreeHostImpl( frame_trackers_(settings.single_thread_proxy_scheduler, compositor_frame_reporting_controller_.get()), lcd_text_metrics_reporter_(LCDTextMetricsReporter::CreateIfNeeded(this)), - frame_rate_estimator_(GetTaskRunner()) { + frame_rate_estimator_(GetTaskRunner()), + contains_srgb_cache_(kContainsSrgbCacheSize) { DCHECK(mutator_host_); mutator_host_->SetMutatorHostClient(this); mutator_events_ = mutator_host_->CreateEvents(); @@ -610,7 +621,7 @@ void LayerTreeHostImpl::CommitComplete() { if (mutator_host_->CurrentFrameHadRAF()) frame_trackers_.StartSequence(FrameSequenceTrackerType::kRAF); if (mutator_host_->HasCanvasInvalidation()) - frame_trackers_.StartSequence(FrameSequenceTrackerType::kCanvas); + frame_trackers_.StartSequence(FrameSequenceTrackerType::kCanvasAnimation); if (mutator_host_->HasJSAnimation()) frame_trackers_.StartSequence(FrameSequenceTrackerType::kJSAnimation); @@ -976,8 +987,8 @@ LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor( std::unique_ptr<EventsMetricsManager::ScopedMonitor> LayerTreeHostImpl::GetScopedEventMetricsMonitor( - std::unique_ptr<EventMetrics> event_metrics) { - return events_metrics_manager_.GetScopedMonitor(std::move(event_metrics)); + EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) { + return events_metrics_manager_.GetScopedMonitor(std::move(done_callback)); } void LayerTreeHostImpl::NotifyInputEvent() { @@ -1050,9 +1061,9 @@ static void AppendQuadsToFillScreen( viz::SharedQuadState* shared_quad_state = target_render_pass->CreateAndAppendSharedQuadState(); shared_quad_state->SetAll(gfx::Transform(), root_target_rect, - root_target_rect, gfx::RRectF(), root_target_rect, - false, are_contents_opaque, opacity, - SkBlendMode::kSrcOver, sorting_context_id); + root_target_rect, gfx::MaskFilterInfo(), + root_target_rect, false, are_contents_opaque, + opacity, SkBlendMode::kSrcOver, sorting_context_id); for (gfx::Rect screen_space_rect : fill_region) { gfx::Rect visible_screen_space_rect = screen_space_rect; @@ -1795,6 +1806,29 @@ gfx::ColorSpace LayerTreeHostImpl::GetRasterColorSpace( if (result.IsHDR() && content_color_usage != gfx::ContentColorUsage::kHDR) return gfx::ColorSpace::CreateDisplayP3D65(); + // The raster color space should contain sRGB to avoid artifacts during + // rasterization. + if (!CheckColorSpaceContainsSrgb(result)) + return srgb; + + return result; +} + +bool LayerTreeHostImpl::CheckColorSpaceContainsSrgb( + const gfx::ColorSpace& color_space) const { + constexpr gfx::ColorSpace srgb = gfx::ColorSpace::CreateSRGB(); + + // Color spaces without a custom primary matrix are cheap to compute, so the + // cache can be bypassed. + if (color_space.GetPrimaryID() != gfx::ColorSpace::PrimaryID::CUSTOM) + return color_space.Contains(srgb); + + auto it = contains_srgb_cache_.Get(color_space); + if (it != contains_srgb_cache_.end()) + return it->second; + + bool result = color_space.Contains(srgb); + contains_srgb_cache_.Put(color_space, result); return result; } @@ -1843,6 +1877,10 @@ int LayerTreeHostImpl::GetMSAASampleCountForRaster( return RequestedMSAASampleCount(); } +bool LayerTreeHostImpl::HasPendingTree() { + return pending_tree_ != nullptr; +} + void LayerTreeHostImpl::NotifyReadyToActivate() { // The TileManager may call this method while the pending tree is still being // painted, as it isn't aware of the ongoing paint. We shouldn't tell the @@ -2019,8 +2057,8 @@ void LayerTreeHostImpl::LogAverageLagEvents( } void LayerTreeHostImpl::NotifyThroughputTrackerResults( - CustomTrackerResults results) { - client_->NotifyThroughputTrackerResults(std::move(results)); + const CustomTrackerResults& results) { + client_->NotifyThroughputTrackerResults(results); } void LayerTreeHostImpl::DidNotNeedBeginFrame() { @@ -2142,8 +2180,11 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { } if (GetDrawMode() == DRAW_MODE_RESOURCELESS_SOFTWARE) { + // TODO(savella) : Change to check for ActivelyScrollingType::kNone + const bool actively_scrolling = + GetActivelyScrollingType() == ActivelyScrollingType::kPrecise; metadata.is_resourceless_software_draw_with_scroll_or_animation = - IsActivelyPrecisionScrolling() || mutator_host_->NeedsTickAnimations(); + actively_scrolling || mutator_host_->NeedsTickAnimations(); } const base::flat_set<viz::SurfaceRange>& referenced_surfaces = @@ -2172,6 +2213,7 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { if (std::unique_ptr<viz::DelegatedInkMetadata> delegated_ink_metadata = active_tree_->take_delegated_ink_metadata()) { + delegated_ink_metadata->set_frame_time(CurrentBeginFrameArgs().frame_time); TRACE_EVENT_INSTANT1( "cc", "Delegated Ink Metadata set on compositor frame metadata", TRACE_EVENT_SCOPE_THREAD, "ink metadata", @@ -2342,7 +2384,7 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { if (!mutator_host_->NextFrameHasPendingRAF()) frame_trackers_.StopSequence(FrameSequenceTrackerType::kRAF); if (!mutator_host_->HasCanvasInvalidation()) - frame_trackers_.StopSequence(FrameSequenceTrackerType::kCanvas); + frame_trackers_.StopSequence(FrameSequenceTrackerType::kCanvasAnimation); if (!mutator_host_->HasJSAnimation()) frame_trackers_.StopSequence(FrameSequenceTrackerType::kJSAnimation); @@ -2959,6 +3001,8 @@ void LayerTreeHostImpl::DidLoseLayerTreeFrameSink() { has_valid_layer_tree_frame_sink_ = false; client_->DidLoseLayerTreeFrameSinkOnImplThread(); lag_tracking_manager_.Clear(); + + dropped_frame_counter_.ResetFrameSorter(); } bool LayerTreeHostImpl::OnlyExpandTopControlsAtPageTop() const { @@ -2995,10 +3039,10 @@ bool LayerTreeHostImpl::IsPinchGestureActive() const { return GetInputHandler().pinch_gesture_active(); } -bool LayerTreeHostImpl::IsActivelyPrecisionScrolling() const { +ActivelyScrollingType LayerTreeHostImpl::GetActivelyScrollingType() const { if (!input_delegate_) - return false; - return input_delegate_->IsActivelyPrecisionScrolling(); + return ActivelyScrollingType::kNone; + return input_delegate_->GetActivelyScrollingType(); } bool LayerTreeHostImpl::ScrollAffectsScrollHandler() const { @@ -3327,7 +3371,7 @@ void LayerTreeHostImpl::CreateTileManagerResources() { viz::ResourceFormatToClosestSkColorType(/*gpu_compositing=*/true, tile_format), settings_.decoded_image_working_set_budget_bytes, max_texture_size_, - paint_image_generator_client_id_); + paint_image_generator_client_id_, dark_mode_filter_); } else { bool gpu_compositing = !!layer_tree_frame_sink_->context_provider(); image_decode_cache_ = std::make_unique<SoftwareImageDecodeCache>( diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index c0c6166c5f6..eee1d46bc15 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,6 +17,7 @@ #include "base/callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/containers/mru_cache.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/shared_memory_mapping.h" #include "base/optional.h" @@ -25,6 +26,7 @@ #include "cc/base/synced_property.h" #include "cc/benchmarks/micro_benchmark_controller_impl.h" #include "cc/cc_export.h" +#include "cc/input/actively_scrolling_type.h" #include "cc/input/browser_controls_offset_manager_client.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar_animation_controller.h" @@ -84,8 +86,10 @@ struct FrameTimingDetails; namespace cc { +enum class ActivelyScrollingType; class BrowserControlsOffsetManager; class CompositorFrameReportingController; +class RasterDarkModeFilter; class DebugRectHistory; class EvictionTilePriorityQueue; class DroppedFrameCounter; @@ -179,6 +183,11 @@ class LayerTreeHostImplClient { base::TimeDelta first_scroll_delay, base::TimeTicks first_scroll_timestamp) = 0; + // Returns true if the client is currently compositing synchronously. This is + // only true in tests, but some behavior needs to be synchronized in non-test + // code as a result. + virtual bool IsInSynchronousComposite() const = 0; + protected: virtual ~LayerTreeHostImplClient() = default; }; @@ -258,6 +267,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, RenderingStatsInstrumentation* rendering_stats_instrumentation, TaskGraphRunner* task_graph_runner, std::unique_ptr<MutatorHost> mutator_host, + RasterDarkModeFilter* dark_mode_filter, int id, scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, LayerTreeHostSchedulingClient* scheduling_client); @@ -280,7 +290,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, std::unique_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency); std::unique_ptr<EventsMetricsManager::ScopedMonitor> - GetScopedEventMetricsMonitor(std::unique_ptr<EventMetrics> event_metrics); + GetScopedEventMetricsMonitor( + EventsMetricsManager::ScopedMonitor::DoneCallback done_callback); void NotifyInputEvent(); // BrowserControlsOffsetManagerClient implementation. @@ -490,6 +501,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, int GetMSAASampleCountForRaster( const scoped_refptr<DisplayItemList>& display_list) override; + bool HasPendingTree() override; + // ScrollbarAnimationControllerClient implementation. void PostDelayedScrollbarAnimationTask(base::OnceClosure task, base::TimeDelta delay) override; @@ -612,7 +625,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // LayerTreeHostImpl's interface. bool IsPinchGestureActive() const; // See comment in equivalent ThreadedInputHandler method for what this means. - bool IsActivelyPrecisionScrolling() const; + ActivelyScrollingType GetActivelyScrollingType() const; bool ScrollAffectsScrollHandler() const; void SetExternalPinchGestureActive(bool active); void set_force_smooth_wheel_scrolling_for_testing(bool enabled) { @@ -800,6 +813,11 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, return &dropped_frame_counter_; } + // Returns true if the client is currently compositing synchronously. + bool IsInSynchronousComposite() const { + return client_->IsInSynchronousComposite(); + } + protected: LayerTreeHostImpl( const LayerTreeSettings& settings, @@ -808,6 +826,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, RenderingStatsInstrumentation* rendering_stats_instrumentation, TaskGraphRunner* task_graph_runner, std::unique_ptr<MutatorHost> mutator_host, + RasterDarkModeFilter* dark_mode_filter, int id, scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, LayerTreeHostSchedulingClient* scheduling_client); @@ -934,7 +953,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, const viz::FrameTimingDetails& details); // Notifies client about the custom tracker results. - void NotifyThroughputTrackerResults(CustomTrackerResults results); + void NotifyThroughputTrackerResults(const CustomTrackerResults& results); + + // Wrapper for checking and updating |contains_srgb_cache_|. + bool CheckColorSpaceContainsSrgb(const gfx::ColorSpace& color_space) const; // Once bound, this instance owns the InputHandler. However, an InputHandler // need not be bound so this should be null-checked before dereferencing. @@ -1052,6 +1074,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, std::unique_ptr<MutatorHost> mutator_host_; std::unique_ptr<MutatorEvents> mutator_events_; std::set<VideoFrameController*> video_frame_controllers_; + RasterDarkModeFilter* const dark_mode_filter_; // Map from scroll element ID to scrollbar animation controller. // There is one animation controller per pair of overlay scrollbars. @@ -1178,6 +1201,12 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, base::WritableSharedMemoryMapping ukm_smoothness_mapping_; + // Cache for the results of calls to gfx::ColorSpace::Contains() on sRGB. This + // computation is deterministic for a given color space, can be called + // multiple times per frame, and incurs a non-trivial cost. + // mutable because |contains_srgb_cache_| is accessed in a const method. + mutable base::MRUCache<gfx::ColorSpace, bool> contains_srgb_cache_; + // Must be the last member to ensure this is destroyed first in the // destruction order and invalidates all weak pointers. base::WeakPtrFactory<LayerTreeHostImpl> weak_factory_{this}; diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index 120265911b3..a9c0a3e8e39 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -12,14 +12,14 @@ #include "base/base_switches.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/location.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/run_loop.h" -#include "base/test/bind_test_util.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -273,6 +273,7 @@ class LayerTreeHostImplTest : public testing::Test, base::TimeTicks first_scroll_timestamp) override { first_scroll_observed++; } + bool IsInSynchronousComposite() const override { return false; } void set_reduce_memory_result(bool reduce_memory_result) { reduce_memory_result_ = reduce_memory_result; } @@ -291,7 +292,7 @@ class LayerTreeHostImplTest : public testing::Test, host_impl_ = LayerTreeHostImpl::Create( settings, this, &task_runner_provider_, &stats_instrumentation_, &task_graph_runner_, - AnimationHost::CreateForTesting(ThreadInstance::IMPL), 0, + AnimationHost::CreateForTesting(ThreadInstance::IMPL), nullptr, 0, image_worker_ ? image_worker_->task_runner() : nullptr, nullptr); InputHandler::Create(static_cast<CompositorDelegateForInput&>(*host_impl_)); layer_tree_frame_sink_ = std::move(layer_tree_frame_sink); @@ -1262,16 +1263,12 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) { EXPECT_TRUE(did_request_commit_); } -// Ensure correct semantics for the IsActivelyPrecisionScrolling method. This +// Ensure correct semantics for the GetActivelyScrollingType method. This // method is used to determine scheduler policy so it wants to report true only // when real scrolling is occurring (i.e. the compositor is consuming scroll -// delta, the page isn't handling the events itself). We also only consider -// this signal for non-animated scrolls. This is partially historical but also -// makes some sense since touchscreen/high-precision touchpad scrolling has a -// physical metaphor (movement sticks to finger) so smoothness should be -// prioritized. +// delta, the page isn't handling the events itself). TEST_P(ScrollUnifiedLayerTreeHostImplTest, - ActivelyTouchScrollingOnlyAfterScrollMovement) { + ActivelyScrollingOnlyAfterScrollMovement) { SetupViewportLayersOuterScrolls(gfx::Size(50, 50), gfx::Size(100, 100)); DrawFrame(); @@ -1286,29 +1283,33 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kNone); // There is no extent upwards so the scroll won't consume any delta. GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), gfx::Vector2d(0, -10), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kNone); // This should scroll so ensure the bit flips to true. GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_TRUE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kPrecise); GetInputHandler().ScrollEnd(); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kNone); } ASSERT_EQ(10, CurrentScrollOffset(OuterViewportScrollLayer()).y()); - // Ensure an animated wheel scroll doesn't cause the bit to flip even when - // scrolling occurs. + // Ensure an animated wheel scroll only causes the bit to flip when enabling + // smoothness mode (i.e. the value of GetParam().animate); { InputHandler::ScrollStatus status = GetInputHandler().ScrollBegin( BeginState(gfx::Point(), gfx::Vector2dF(0, 10), @@ -1316,11 +1317,13 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, status.thread); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kNone); GetInputHandler().ScrollUpdate( AnimatedUpdateState(gfx::Point(), gfx::Vector2dF(0, 10)).get()); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kAnimated); base::TimeTicks cur_time = base::TimeTicks() + base::TimeDelta::FromMilliseconds(100); @@ -1339,18 +1342,22 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // The animation is setup in the first frame so tick at least twice to // actually animate it. ANIMATE(0); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kAnimated); ANIMATE(200); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kAnimated); ANIMATE(1000); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kAnimated); #undef ANIMATE ASSERT_EQ(20, CurrentScrollOffset(OuterViewportScrollLayer()).y()); GetInputHandler().ScrollEnd(); - EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + EXPECT_EQ(host_impl_->GetActivelyScrollingType(), + ActivelyScrollingType::kNone); } } @@ -4942,6 +4949,7 @@ class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl { rendering_stats_instrumentation, task_graph_runner, AnimationHost::CreateForTesting(ThreadInstance::IMPL), + nullptr, 0, nullptr, nullptr) {} @@ -5404,32 +5412,6 @@ TEST_P(LayerTreeHostImplTestMultiScrollable, EXPECT_FALSE(animation_task_.is_null()); } -TEST_P(LayerTreeHostImplTestMultiScrollable, ScrollbarFlashWhenMouseEnter) { - LayerTreeSettings settings = DefaultSettings(); - settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); - settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); - settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY; - settings.scrollbar_flash_when_mouse_enter = true; - - SetUpLayers(settings); - - EXPECT_EQ(scrollbar_1_->Opacity(), 0); - EXPECT_EQ(scrollbar_2_->Opacity(), 0); - - // Scroll should flash when mouse enter. - GetInputHandler().MouseMoveAt(gfx::Point(1, 1)); - - EXPECT_TRUE(scrollbar_1_->Opacity()); - EXPECT_FALSE(scrollbar_2_->Opacity()); - EXPECT_FALSE(animation_task_.is_null()); - - GetInputHandler().MouseMoveAt(gfx::Point(51, 51)); - - EXPECT_TRUE(scrollbar_1_->Opacity()); - EXPECT_TRUE(scrollbar_2_->Opacity()); - EXPECT_FALSE(animation_task_.is_null()); -} - TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollHitTestOnScrollbar) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); @@ -10849,8 +10831,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PartialSwapReceivesDamageRect) { LayerTreeHostImpl::Create( settings, this, &task_runner_provider_, &stats_instrumentation_, &task_graph_runner_, - AnimationHost::CreateForTesting(ThreadInstance::IMPL), 0, nullptr, - nullptr); + AnimationHost::CreateForTesting(ThreadInstance::IMPL), nullptr, 0, + nullptr, nullptr); layer_tree_host_impl->SetVisible(true); layer_tree_host_impl->InitializeFrameSink(layer_tree_frame_sink.get()); @@ -11298,8 +11280,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, MemoryLimits) { host_impl_ = LayerTreeHostImpl::Create( settings, this, &task_runner_provider_, &stats_instrumentation_, &task_graph_runner_, - AnimationHost::CreateForTesting(ThreadInstance::IMPL), 0, nullptr, - nullptr); + AnimationHost::CreateForTesting(ThreadInstance::IMPL), nullptr, 0, + nullptr, nullptr); InputHandler::Create(static_cast<CompositorDelegateForInput&>(*host_impl_)); // Gpu compositing. @@ -11557,8 +11539,14 @@ class FrameSinkClient : public TestLayerTreeFrameSinkClient { scoped_refptr<viz::ContextProvider> display_context_provider) : display_context_provider_(std::move(display_context_provider)) {} - std::unique_ptr<viz::SkiaOutputSurface> CreateDisplaySkiaOutputSurface() - override { + std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController> + CreateDisplayController() override { + // In this implementation, no output surface has a real gpu thread, and + // there is no overlay support. + return nullptr; + } + std::unique_ptr<viz::SkiaOutputSurface> CreateDisplaySkiaOutputSurface( + viz::DisplayCompositorMemoryAndTaskController*) override { return viz::FakeSkiaOutputSurface::Create3d( std::move(display_context_provider_)); } @@ -14067,20 +14055,21 @@ TEST_F(LayerTreeHostImplTest, FrameCounterReset) { dropped_frame_counter->AddGoodFrame(); EXPECT_EQ(dropped_frame_counter->total_frames(), 1u); - dropped_frame_counter->AddDroppedFrameAffectingSmoothness(); - // FCP not received, so the total_smoothness_dropped_ won't increase. - EXPECT_EQ(dropped_frame_counter->total_smoothness_dropped(), 0u); - auto interval = base::TimeDelta::FromMilliseconds(16); base::TimeTicks now = base::TimeTicks::Now(); auto deadline = now + interval; viz::BeginFrameArgs args = viz::BeginFrameArgs::Create( - BEGINFRAME_FROM_HERE, 1u /*source_id*/, 1u /*sequence_number*/, now, + BEGINFRAME_FROM_HERE, 1u /*source_id*/, 2u /*sequence_number*/, now, deadline, interval, viz::BeginFrameArgs::NORMAL); + + dropped_frame_counter->OnEndFrame(args, true); + // FCP not received, so the total_smoothness_dropped_ won't increase. + EXPECT_EQ(dropped_frame_counter->total_smoothness_dropped(), 0u); + BeginMainFrameMetrics begin_frame_metrics; begin_frame_metrics.should_measure_smoothness = true; host_impl_->ReadyToCommit(args, &begin_frame_metrics); - dropped_frame_counter->AddDroppedFrameAffectingSmoothness(); + dropped_frame_counter->OnEndFrame(args, true); EXPECT_EQ(dropped_frame_counter->total_smoothness_dropped(), 1u); total_frame_counter->set_total_frames_for_testing(1u); @@ -15862,8 +15851,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, host_impl_ = LayerTreeHostImpl::Create( DefaultSettings(), this, &task_runner_provider_, &stats_instrumentation_, &task_graph_runner_, - AnimationHost::CreateForTesting(ThreadInstance::IMPL), 0, nullptr, - nullptr); + AnimationHost::CreateForTesting(ThreadInstance::IMPL), nullptr, 0, + nullptr, nullptr); InputHandler::Create(static_cast<CompositorDelegateForInput&>(*host_impl_)); host_impl_->SetVisible(true); @@ -18110,8 +18099,8 @@ TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlapRoundedCorners) { // Add rounded corners to the layer, which are unable to be hit tested by the // simple quad-based logic. - CreateEffectNode(rounded_frame_layer).rounded_corner_bounds = - gfx::RRectF(25, 25, 50, 50, 5); + CreateEffectNode(rounded_frame_layer).mask_filter_info = + gfx::MaskFilterInfo(gfx::RRectF(25, 25, 50, 50, 5)); UpdateDrawProperties(host_impl_->active_tree()); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc index 9100d9ea5b9..496bdbf6da9 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc @@ -202,7 +202,7 @@ class LayerTreeHostBlendingPixelTest SkBitmap expected; expected.allocN32Pixels(width, height); - SkCanvas canvas(expected); + SkCanvas canvas(expected, SkSurfaceProps{}); canvas.clear(SK_ColorWHITE); canvas.drawImage(surface->makeImageSnapshot(), 0, 0); @@ -306,7 +306,7 @@ TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithRoot) { SkBitmap expected; expected.allocN32Pixels(kRootWidth, kRootHeight); - SkCanvas canvas(expected); + SkCanvas canvas(expected, SkSurfaceProps{}); canvas.drawColor(kCSSOrange); SkPaint paint; paint.setBlendMode(current_blend_mode()); @@ -337,7 +337,7 @@ TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithBackdropFilter) { SkBitmap expected; expected.allocN32Pixels(kRootWidth, kRootHeight); - SkCanvas canvas(expected); + SkCanvas canvas(expected, SkSurfaceProps{}); SkiaPaintCanvas paint_canvas(&canvas); PaintFlags grayscale; grayscale.setColor(kCSSOrange); @@ -379,7 +379,7 @@ TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithTransparent) { SkBitmap expected; expected.allocN32Pixels(kRootWidth, kRootHeight); - SkCanvas canvas(expected); + SkCanvas canvas(expected, SkSurfaceProps{}); canvas.drawColor(kCSSOrange); SkPaint paint; paint.setBlendMode(current_blend_mode()); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc index 880ec0a5bf5..3687e59cfa0 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -175,11 +175,11 @@ TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRadius) { float percentage_pixels_large_error = 1.09f; // 436px / (200*200) float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 1; + int large_error_allowed = 2; int small_error_allowed = 0; - // Windows using Dawn D3D12 has 2982 pixels off by 1. + // Windows using Dawn D3D12 has 4044 pixels off by max of 2. if (use_d3d12()) - percentage_pixels_large_error = 1.864f; // 2982px / (400*400) + percentage_pixels_large_error = 2.5275f; // 4044px / (400*400) pixel_comparator_.reset(new FuzzyPixelComparator( true, // discard_alpha percentage_pixels_large_error, percentage_pixels_small_error, @@ -365,8 +365,10 @@ INSTANTIATE_TEST_SUITE_P(PixelResourceTest, ::testing::ValuesIn(viz::GetGpuRendererTypes()), ::testing::PrintToStringParamName()); +// TODO(michaelludwig): Re-enable after Skia roll and update expected images. +// See skbug.com/9545 TEST_P(LayerTreeHostBlurFiltersPixelTestGPULayerList, - BackdropFilterBlurOffAxis) { + DISABLED_BackdropFilterBlurOffAxis) { #if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) // Windows has 116 pixels off by at most 2: crbug.com/225027 diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index 95c904ca35e..63b1f719917 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -58,12 +58,10 @@ class MaskContentLayerClient : public ContentLayerClient { ~MaskContentLayerClient() override = default; bool FillsBoundsCompletely() const override { return false; } - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting picture_control) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { auto display_list = base::MakeRefCounted<DisplayItemList>(); display_list->StartPaint(); @@ -193,12 +191,10 @@ class SolidColorEmptyMaskContentLayerClient : public ContentLayerClient { ~SolidColorEmptyMaskContentLayerClient() override = default; bool FillsBoundsCompletely() const override { return false; } - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting picture_control) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { // Intentionally return a solid color, empty mask display list. This // is a situation where all content should be masked out. auto display_list = base::MakeRefCounted<DisplayItemList>(); @@ -332,8 +328,7 @@ TEST_P(LayerTreeHostMaskPixelTestWithLayerList, ImageMaskWithEffect) { sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(50, 50); SkCanvas* canvas = surface->getCanvas(); scoped_refptr<DisplayItemList> mask_display_list = - mask_client.PaintContentsToDisplayList( - ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); + mask_client.PaintContentsToDisplayList(); mask_display_list->Raster(canvas); FakeContentLayerClient layer_client; @@ -361,8 +356,7 @@ TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) { SkCanvas* canvas = surface->getCanvas(); MaskContentLayerClient client(mask_bounds); scoped_refptr<DisplayItemList> mask_display_list = - client.PaintContentsToDisplayList( - ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); + client.PaintContentsToDisplayList(); mask_display_list->Raster(canvas); FakeContentLayerClient mask_client; @@ -447,10 +441,8 @@ class CheckerContentLayerClient : public ContentLayerClient { : bounds_(bounds), color_(color), vertical_(vertical) {} ~CheckerContentLayerClient() override = default; bool FillsBoundsCompletely() const override { return false; } - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting picture_control) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { auto display_list = base::MakeRefCounted<DisplayItemList>(); display_list->StartPaint(); @@ -496,10 +488,8 @@ class CircleContentLayerClient : public ContentLayerClient { : bounds_(bounds) {} ~CircleContentLayerClient() override = default; bool FillsBoundsCompletely() const override { return false; } - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } gfx::Rect PaintableRegion() override { return gfx::Rect(bounds_); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting picture_control) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { auto display_list = base::MakeRefCounted<DisplayItemList>(); display_list->StartPaint(); @@ -724,12 +714,10 @@ class StaticPictureLayer : private ContentLayerClient, public PictureLayer { } gfx::Rect PaintableRegion() override { return gfx::Rect(bounds()); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { return display_list_; } bool FillsBoundsCompletely() const override { return false; } - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } protected: explicit StaticPictureLayer(scoped_refptr<DisplayItemList> display_list) diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index 0cc4f38d0e1..d837df92f79 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -5,6 +5,7 @@ #include <stddef.h> #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer.h" #include "cc/paint/display_item_list.h" @@ -48,6 +49,18 @@ class LayerTreeHostTilesPixelTest target->RequestCopyOfOutput(CreateCopyOutputRequest()); } + void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override { + // Issue a GL finish before preparing tiles to ensure resources become + // available for use in a timely manner. Needed for the one-copy path. + viz::RasterContextProvider* context_provider = + host_impl->layer_tree_frame_sink()->worker_context_provider(); + if (!context_provider) + return; + + viz::RasterContextProvider::ScopedRasterContextLock lock(context_provider); + lock.RasterInterface()->Finish(); + } + base::FilePath ref_file_; std::unique_ptr<SkBitmap> result_bitmap_; bool use_partial_raster_ = false; @@ -59,8 +72,7 @@ class BlueYellowClient : public ContentLayerClient { : size_(size), blue_top_(true) {} gfx::Rect PaintableRegion() override { return gfx::Rect(size_); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting painting_status) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { auto display_list = base::MakeRefCounted<DisplayItemList>(); display_list->StartPaint(); @@ -88,7 +100,6 @@ class BlueYellowClient : public ContentLayerClient { } bool FillsBoundsCompletely() const override { return true; } - size_t GetApproximateUnsharedMemoryUsage() const override { return 0; } void set_blue_top(bool b) { blue_top_ = b; } @@ -131,21 +142,81 @@ class LayerTreeHostTilesTestPartialInvalidation } } - void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override { - // Issue a GL finish before preparing tiles to ensure resources become - // available for use in a timely manner. Needed for the one-copy path. - viz::RasterContextProvider* context_provider = - host_impl->layer_tree_frame_sink()->worker_context_provider(); - if (!context_provider) - return; + protected: + BlueYellowClient client_; + scoped_refptr<PictureLayer> picture_layer_; +}; - viz::RasterContextProvider::ScopedRasterContextLock lock(context_provider); - lock.RasterInterface()->Finish(); +class PrimaryColorClient : public ContentLayerClient { + public: + explicit PrimaryColorClient(const gfx::Size& size) : size_(size) {} + + gfx::Rect PaintableRegion() override { return gfx::Rect(size_); } + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { + // When painted, the DisplayItemList should produce blocks of red, green, + // and blue to test primary color reproduction. + auto display_list = base::MakeRefCounted<DisplayItemList>(); + + display_list->StartPaint(); + + int w = size_.width() / 3; + gfx::Rect red_rect(0, 0, w, size_.height()); + gfx::Rect green_rect(w, 0, w, size_.height()); + gfx::Rect blue_rect(w * 2, 0, w, size_.height()); + + PaintFlags flags; + flags.setStyle(PaintFlags::kFill_Style); + + flags.setColor(SK_ColorRED); + display_list->push<DrawRectOp>(gfx::RectToSkRect(red_rect), flags); + flags.setColor(SK_ColorGREEN); + display_list->push<DrawRectOp>(gfx::RectToSkRect(green_rect), flags); + flags.setColor(SK_ColorBLUE); + display_list->push<DrawRectOp>(gfx::RectToSkRect(blue_rect), flags); + + display_list->EndPaintOfUnpaired(PaintableRegion()); + display_list->Finalize(); + return display_list; + } + + bool FillsBoundsCompletely() const override { return true; } + + private: + gfx::Size size_; +}; + +class LayerTreeHostTilesTestRasterColorSpace + : public LayerTreeHostTilesPixelTest { + public: + LayerTreeHostTilesTestRasterColorSpace() + : client_(gfx::Size(150, 150)), + picture_layer_(PictureLayer::Create(&client_)) { + picture_layer_->SetBounds(gfx::Size(150, 150)); + picture_layer_->SetIsDrawable(true); + } + + void SetColorSpace(const gfx::ColorSpace& color_space) { + color_space_ = color_space; + } + + void WillBeginTest() override { + LayerTreeHostTilesPixelTest::WillBeginTest(); + DCHECK(color_space_.IsValid()); + layer_tree_host()->SetDisplayColorSpaces( + gfx::DisplayColorSpaces(color_space_)); + } + + void DidCommitAndDrawFrame() override { + if (layer_tree_host()->SourceFrameNumber() == 1) { + Finish(); + DoReadback(); + } } protected: - BlueYellowClient client_; + PrimaryColorClient client_; scoped_refptr<PictureLayer> picture_layer_; + gfx::ColorSpace color_space_; }; std::vector<RasterTestConfig> const kTestCases = { @@ -169,7 +240,7 @@ INSTANTIATE_TEST_SUITE_P(All, ::testing::ValuesIn(kTestCases), ::testing::PrintToStringParamName()); -#if defined(OS_CHROMEOS) || defined(MEMORY_SANITIZER) || \ +#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(MEMORY_SANITIZER) || \ defined(ADDRESS_SANITIZER) || defined(OS_FUCHSIA) // TODO(crbug.com/1045521): Flakes on all slower bots. #define MAYBE_PartialRaster DISABLED_PartialRaster @@ -216,7 +287,7 @@ INSTANTIATE_TEST_SUITE_P(All, #if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(THREAD_SANITIZER) // Flaky on Linux TSAN. https://crbug.com/707711 #define MAYBE_PartialRaster DISABLED_PartialRaster -#elif defined(OS_CHROMEOS) || defined(MEMORY_SANITIZER) || \ +#elif BUILDFLAG(IS_CHROMEOS_ASH) || defined(MEMORY_SANITIZER) || \ defined(ADDRESS_SANITIZER) || defined(OS_FUCHSIA) // TODO(crbug.com/1045521): Flakes on all slower bots. #define MAYBE_PartialRaster DISABLED_PartialRaster @@ -237,6 +308,49 @@ TEST_P(LayerTreeHostTilesTestPartialInvalidationMultiThread, FullRaster) { base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); } +INSTANTIATE_TEST_SUITE_P(All, + LayerTreeHostTilesTestRasterColorSpace, + ::testing::ValuesIn(kTestCases), + ::testing::PrintToStringParamName()); + +// These tests verify that no artifacts are introduced when the color space for +// rasterization doesn't contain the primary colors of sRGB. +// See crbug.com/1073962 for more details. +TEST_P(LayerTreeHostTilesTestRasterColorSpace, sRGB) { + SetColorSpace(gfx::ColorSpace::CreateSRGB()); + + RunPixelTest(picture_layer_, + base::FilePath(FILE_PATH_LITERAL("primary_colors.png"))); +} + +TEST_P(LayerTreeHostTilesTestRasterColorSpace, GenericRGB) { + SetColorSpace(gfx::ColorSpace(gfx::ColorSpace::PrimaryID::APPLE_GENERIC_RGB, + gfx::ColorSpace::TransferID::GAMMA18)); + + RunPixelTest(picture_layer_, + base::FilePath(FILE_PATH_LITERAL("primary_colors.png"))); +} + +TEST_P(LayerTreeHostTilesTestRasterColorSpace, CustomColorSpace) { + // Create a color space with a different blue point. + SkColorSpacePrimaries primaries; + skcms_Matrix3x3 to_XYZD50; + primaries.fRX = 0.640f; + primaries.fRY = 0.330f; + primaries.fGX = 0.300f; + primaries.fGY = 0.600f; + primaries.fBX = 0.130f; + primaries.fBY = 0.080f; + primaries.fWX = 0.3127f; + primaries.fWY = 0.3290f; + primaries.toXYZD50(&to_XYZD50); + SetColorSpace(gfx::ColorSpace::CreateCustom( + to_XYZD50, gfx::ColorSpace::TransferID::IEC61966_2_1)); + + RunPixelTest(picture_layer_, + base::FilePath(FILE_PATH_LITERAL("primary_colors.png"))); +} + // This test doesn't work on Vulkan because on our hardware we can't render to // RGBA4444 format using either SwiftShader or native Vulkan. See // crbug.com/987278 for details diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 0bd998b5544..163146ca91e 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -11,7 +11,7 @@ #include "base/auto_reset.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" @@ -2897,13 +2897,6 @@ MULTI_THREAD_BLOCKNOTIFY_TEST_F( // its damage is preserved until the next time it is drawn. class LayerTreeHostTestUndrawnLayersDamageLater : public LayerTreeHostTest { public: - void InitializeSettings(LayerTreeSettings* settings) override { - // If we don't set the minimum contents scale, it's harder to verify whether - // the damage we get is correct. For other scale amounts, please see - // LayerTreeHostTestDamageWithScale. - settings->minimum_contents_scale = 1.f; - } - void SetupTree() override { root_layer_ = FakePictureLayer::Create(&client_); root_layer_->SetIsDrawable(true); @@ -3751,15 +3744,17 @@ SINGLE_AND_MULTI_THREAD_TEST_F( // updates, i.e. abort commits after the paint stage and only request layer // tree updates for layout. // -// The tests sends four Begin(Main)Frames in sequence: three animate_only -// Begin(Main)Frames followed by a normal Begin(Main)Frame. The first three -// should result in aborted commits, whereas the last one should complete the +// The tests sends five Begin(Main)Frames in sequence: four animate_only +// Begin(Main)Frames followed by a normal Begin(Main)Frame. The first frame +// has animate_only force to false by CompositorFrameSinkSupport, since it +// needs a complete frame to assure surface activation. Frames 2-4 should +// result in aborted commits, whereas the last one should complete the // previously aborted commits. // -// Between BeginMainFrames 2 and 3, the client also requests a new commit -// (SetNeedsCommit), but not between BeginMainFrames 1 and 2. In multi-threaded +// Between BeginMainFrames 3 and 4, the client also requests a new commit +// (SetNeedsCommit), but not between BeginMainFrames 1-3. In multi-threaded // mode, ProxyMain will run the animate pipeline stage only for BeginMainFrames -// 1 and 3, as no new commit was requested between 1 and 2. +// 2 and 4, as no new commit was requested between 2 and 3. // // The test uses the full-pipeline mode to ensure that each BeginFrame also // incurs a BeginMainFrame. @@ -3816,31 +3811,52 @@ class LayerTreeHostTestAnimateOnlyBeginFrames void DidSendBeginMainFrameOnThread(LayerTreeHostImpl* host_impl) override { ++sent_begin_main_frame_count_; - EXPECT_EQ(begin_frame_count_, sent_begin_main_frame_count_); + EXPECT_GE(begin_frame_count_, sent_begin_main_frame_count_); + } + + void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, + const viz::BeginFrameArgs& args) override { + EXPECT_EQ(args.animate_only, + (begin_frame_count_ >= 2 && begin_frame_count_ <= 4)); } void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) override { + EXPECT_LE(sent_begin_main_frame_count_, begin_frame_count_); if (begin_frame_count_ < 3) { - if (begin_frame_count_ == 2) { - // Request another commit before sending the third BeginMainFrame. - PostSetNeedsCommitToMainThread(); - } - // Send another animation_only BeginFrame. PostIssueBeginFrame(true); } else if (begin_frame_count_ == 3) { + MainThreadTaskRunner()->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&LayerTreeHostTestAnimateOnlyBeginFrames:: + SetNeedsCommitOnMainThread, + base::Unretained(this)), + base::BindOnce( + &LayerTreeHostTestAnimateOnlyBeginFrames::PostIssueBeginFrame, + base::Unretained(this), true)); + } else if (begin_frame_count_ == 4) { PostIssueBeginFrame(false); } } + void SetNeedsCommitOnMainThread() { layer_tree_host()->SetNeedsCommit(); } + void UpdateLayerTreeHost() override { ++update_layer_tree_host_count_; } - void DidCommit() override { + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { + if (begin_frame_count_ == 1) + host_impl->NotifyReadyToDraw(); + ++commit_count_; + // First commit is due to first frame having animate_only forced to false + // in ordser to create the surface. + if (commit_count_ == 1) + return; + // Fourth BeginMainFrame should lead to commit. - EXPECT_EQ(4, begin_frame_count_); - EXPECT_EQ(4, sent_begin_main_frame_count_); + EXPECT_EQ(5, begin_frame_count_); + EXPECT_EQ(3, sent_begin_main_frame_count_); EndTest(); } @@ -3850,23 +3866,15 @@ class LayerTreeHostTestAnimateOnlyBeginFrames } void AfterTest() override { - EXPECT_EQ(1, commit_count_); - EXPECT_EQ(4, begin_frame_count_); - EXPECT_EQ(4, sent_begin_main_frame_count_); - - if (HasImplThread()) { - // ProxyMain aborts the second BeginMainFrame before running the animate - // pipeline stage, since no further updates were made since the first one. - // Thus, we expect not to be called for the second BeginMainFrame. - EXPECT_EQ(3, will_begin_main_frame_count_); - EXPECT_EQ(3, update_layer_tree_host_count_); - } else { - EXPECT_EQ(4, will_begin_main_frame_count_); - EXPECT_EQ(4, update_layer_tree_host_count_); - } + EXPECT_EQ(2, commit_count_); + EXPECT_EQ(5, begin_frame_count_); + EXPECT_EQ(3, sent_begin_main_frame_count_); + + EXPECT_EQ(3, will_begin_main_frame_count_); + EXPECT_EQ(3, update_layer_tree_host_count_); // The final commit should not have been aborted. - EXPECT_EQ(1, ready_to_commit_count_); + EXPECT_EQ(2, ready_to_commit_count_); } protected: @@ -6726,7 +6734,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise new TestSwapPromise(&swap_promise_result_[0])); layer_tree_host()->GetSwapPromiseManager()->QueueSwapPromise( std::move(swap_promise0)); - layer_tree_host()->Composite(base::TimeTicks::Now(), raster); + layer_tree_host()->CompositeForTest(base::TimeTicks::Now(), raster); // Fail to swap (no damage) if not reclaiming resources from the Display. std::unique_ptr<SwapPromise> swap_promise1( @@ -6734,7 +6742,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise layer_tree_host()->GetSwapPromiseManager()->QueueSwapPromise( std::move(swap_promise1)); layer_tree_host()->SetNeedsCommit(); - layer_tree_host()->Composite(base::TimeTicks::Now(), raster); + layer_tree_host()->CompositeForTest(base::TimeTicks::Now(), raster); // Fail to draw (not visible). std::unique_ptr<SwapPromise> swap_promise2( @@ -6743,7 +6751,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise std::move(swap_promise2)); layer_tree_host()->SetNeedsDisplayOnAllLayers(); layer_tree_host()->SetVisible(false); - layer_tree_host()->Composite(base::TimeTicks::Now(), raster); + layer_tree_host()->CompositeForTest(base::TimeTicks::Now(), raster); EndTest(); } @@ -7985,7 +7993,7 @@ class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest { return; first_ = false; - image_ = DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)), + image_ = DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)), false, SkIRect::MakeWH(400, 400), kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex, gfx::ColorSpace()); @@ -8911,6 +8919,7 @@ class LayerTreeHostTestDelegatedInkMetadataOnAndOff void DrawLayersOnThread(LayerTreeHostImpl* impl) override { if (expected_metadata_.has_value()) { + EXPECT_EQ(metadata_frame_time_, impl->CurrentBeginFrameArgs().frame_time); // Now try again with no metadata to confirm everything is cleared out. expected_metadata_.reset(); } @@ -8927,6 +8936,11 @@ class LayerTreeHostTestDelegatedInkMetadataOnAndOff EXPECT_EQ(expected_metadata_->presentation_area(), actual_metadata->presentation_area()); EXPECT_EQ(expected_metadata_->timestamp(), actual_metadata->timestamp()); + + // Record the frame time from the metadata so we can confirm that it + // matches the LayerTreeHostImpl's frame time in DrawLayersOnThread. + EXPECT_GT(actual_metadata->frame_time(), base::TimeTicks::Min()); + metadata_frame_time_ = actual_metadata->frame_time(); } else { EXPECT_FALSE(had_delegated_ink_metadata); EXPECT_FALSE(actual_metadata); @@ -8949,6 +8963,7 @@ class LayerTreeHostTestDelegatedInkMetadataOnAndOff FakeContentLayerClient client_; scoped_refptr<Layer> layer_; bool set_needs_display_ = true; + base::TimeTicks metadata_frame_time_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDelegatedInkMetadataOnAndOff); @@ -8984,12 +8999,23 @@ class LayerTreeHostTestEventsMetrics : public LayerTreeHostTest { private: void SimulateEventOnMain() { - auto scoped_event_monitor = - layer_tree_host()->GetScopedEventMetricsMonitor(EventMetrics::Create( - ui::ET_GESTURE_SCROLL_UPDATE, - EventMetrics::ScrollUpdateType::kContinued, base::TimeTicks::Now(), - ui::ScrollInputType::kWheel)); - layer_tree_host()->SetNeedsAnimate(); + std::unique_ptr<EventMetrics> metrics = EventMetrics::Create( + ui::ET_GESTURE_SCROLL_UPDATE, + EventMetrics::ScrollUpdateType::kContinued, base::TimeTicks::Now(), + ui::ScrollInputType::kWheel); + { + auto done_callback = base::BindOnce( + [](std::unique_ptr<EventMetrics> metrics, bool handled) { + std::unique_ptr<EventMetrics> result = + handled ? std::move(metrics) : nullptr; + return result; + }, + std::move(metrics)); + auto scoped_event_monitor = + layer_tree_host()->GetScopedEventMetricsMonitor( + std::move(done_callback)); + layer_tree_host()->SetNeedsAnimate(); + } EXPECT_SCOPED(VerifyMainSavedEventsMetricsCountOnMain(1)); } @@ -9344,7 +9370,7 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest { } // Mark every frame as a dropped frame affecting smoothness. - host_impl->dropped_frame_counter()->AddDroppedFrameAffectingSmoothness(); + host_impl->dropped_frame_counter()->OnEndFrame(viz::BeginFrameArgs(), true); host_impl->SetNeedsRedraw(); --frames_counter_; } @@ -9390,7 +9416,7 @@ class LayerTreeHostUkmSmoothnessMemoryOwnership : public LayerTreeTest { } // Mark every frame as a dropped frame affecting smoothness. - host_impl->dropped_frame_counter()->AddDroppedFrameAffectingSmoothness(); + host_impl->dropped_frame_counter()->OnEndFrame(viz::BeginFrameArgs(), true); host_impl->SetNeedsRedraw(); --frames_counter_; } 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 785d8265fa6..c7bf7b5b3cf 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc @@ -32,8 +32,7 @@ class FakeCaptureContentLayerClient : public FakeContentLayerClient { holders_.push_back(holder); } - scoped_refptr<DisplayItemList> PaintContentsToDisplayList( - PaintingControlSetting painting_control) override { + scoped_refptr<DisplayItemList> PaintContentsToDisplayList() override { auto display_list = base::MakeRefCounted<DisplayItemList>(); for (auto& holder : holders_) { display_list->StartPaint(); diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index 9df178c8b29..b679607a722 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -468,8 +468,8 @@ class MultipleCompositeDoesNotCreateLayerTreeFrameSink } void BeginTest() override { - layer_tree_host()->Composite(TicksFromMicroseconds(1), false); - layer_tree_host()->Composite(TicksFromMicroseconds(2), false); + layer_tree_host()->CompositeForTest(TicksFromMicroseconds(1), false); + layer_tree_host()->CompositeForTest(TicksFromMicroseconds(2), false); } void DidInitializeLayerTreeFrameSink() override { EXPECT_TRUE(false); } @@ -510,12 +510,12 @@ class FailedCreateDoesNotCreateExtraLayerTreeFrameSink void BeginTest() override { // First composite tries to create a surface. - layer_tree_host()->Composite(TicksFromMicroseconds(1), false); + layer_tree_host()->CompositeForTest(TicksFromMicroseconds(1), false); EXPECT_EQ(num_requests_, 2); EXPECT_TRUE(has_failed_); // Second composite should not request or fail. - layer_tree_host()->Composite(TicksFromMicroseconds(2), false); + layer_tree_host()->CompositeForTest(TicksFromMicroseconds(2), false); EXPECT_EQ(num_requests_, 2); EndTest(); } @@ -561,7 +561,7 @@ class LayerTreeHostContextTestCommitAfterDelayedLayerTreeFrameSink } void BeginTest() override { - layer_tree_host()->Composite(TicksFromMicroseconds(1), false); + layer_tree_host()->CompositeForTest(TicksFromMicroseconds(1), false); } void ScheduleComposite() override { @@ -594,7 +594,7 @@ class LayerTreeHostContextTestAvoidUnnecessaryComposite void BeginTest() override { in_composite_ = true; - layer_tree_host()->Composite(TicksFromMicroseconds(1), false); + layer_tree_host()->CompositeForTest(TicksFromMicroseconds(1), false); in_composite_ = false; } diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index 108efa6939a..d6fbf463ba1 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -187,8 +187,16 @@ TEST_P(LayerTreeHostCopyRequestTestMultipleRequests, Test) { // which causes callbacks for sync queries to be sent in reverse order. class LayerTreeHostCopyRequestTestMultipleRequestsOutOfOrder : public LayerTreeHostCopyRequestTestMultipleRequests { + std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController> + CreateDisplayControllerOnThread() override { + // In this implementation, none of the output surface has a real gpu thread, + // and there is no overlay support. + return nullptr; + } + std::unique_ptr<viz::SkiaOutputSurface> - CreateDisplaySkiaOutputSurfaceOnThread() override { + CreateDisplaySkiaOutputSurfaceOnThread( + viz::DisplayCompositorMemoryAndTaskController*) override { auto skia_output_surface = viz::FakeSkiaOutputSurface::Create3d(); skia_output_surface->SetOutOfOrderCallbacks(true); return skia_output_surface; @@ -824,8 +832,15 @@ TEST_P(LayerTreeHostTestAsyncTwoReadbacksWithoutDraw, Test) { class LayerTreeHostCopyRequestTestDeleteSharedImage : public LayerTreeHostCopyRequestTest { protected: + std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController> + CreateDisplayControllerOnThread() override { + // In this implementation, none of the output surface has a real gpu thread, + // and there is no overlay support. + return nullptr; + } std::unique_ptr<viz::SkiaOutputSurface> - CreateDisplaySkiaOutputSurfaceOnThread() override { + CreateDisplaySkiaOutputSurfaceOnThread( + viz::DisplayCompositorMemoryAndTaskController*) override { display_context_provider_ = viz::TestContextProvider::Create(); display_context_provider_->BindToCurrentThread(); return viz::FakeSkiaOutputSurface::Create3d(display_context_provider_); @@ -967,8 +982,15 @@ TEST_P(LayerTreeHostCopyRequestTestDeleteSharedImage, Test) { class LayerTreeHostCopyRequestTestCountSharedImages : public LayerTreeHostCopyRequestTest { protected: + std::unique_ptr<viz::DisplayCompositorMemoryAndTaskController> + CreateDisplayControllerOnThread() override { + // In this implementation, none of the output surface has a real gpu thread, + // and there is no overlay support. + return nullptr; + } std::unique_ptr<viz::SkiaOutputSurface> - CreateDisplaySkiaOutputSurfaceOnThread() override { + CreateDisplaySkiaOutputSurfaceOnThread( + viz::DisplayCompositorMemoryAndTaskController*) override { display_context_provider_ = viz::TestContextProvider::Create(); display_context_provider_->BindToCurrentThread(); return viz::FakeSkiaOutputSurface::Create3d(display_context_provider_); diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index 256ab69ea1a..cb9d1d174d5 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -559,7 +559,7 @@ void LayerTreeImpl::PushPropertyTreesTo(LayerTreeImpl* target_tree) { target_tree->SetPropertyTrees(&property_trees_); - std::vector<EventMetrics> events_metrics; + EventMetrics::List events_metrics; events_metrics.swap(events_metrics_from_main_thread_); target_tree->AppendEventsMetricsFromMainThread(std::move(events_metrics)); } @@ -2629,16 +2629,17 @@ LayerTreeImpl::TakePendingPageScaleAnimation() { } void LayerTreeImpl::AppendEventsMetricsFromMainThread( - std::vector<EventMetrics> events_metrics) { + EventMetrics::List events_metrics) { events_metrics_from_main_thread_.reserve( events_metrics_from_main_thread_.size() + events_metrics.size()); events_metrics_from_main_thread_.insert( - events_metrics_from_main_thread_.end(), events_metrics.begin(), - events_metrics.end()); + events_metrics_from_main_thread_.end(), + std::make_move_iterator(events_metrics.begin()), + std::make_move_iterator(events_metrics.end())); } -std::vector<EventMetrics> LayerTreeImpl::TakeEventsMetrics() { - std::vector<EventMetrics> main_event_metrics_result; +EventMetrics::List LayerTreeImpl::TakeEventsMetrics() { + EventMetrics::List main_event_metrics_result; main_event_metrics_result.swap(events_metrics_from_main_thread_); return main_event_metrics_result; } diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 024a56c721f..b1638ab1490 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -658,9 +658,8 @@ class CC_EXPORT LayerTreeImpl { std::unique_ptr<PendingPageScaleAnimation> pending_animation); std::unique_ptr<PendingPageScaleAnimation> TakePendingPageScaleAnimation(); - void AppendEventsMetricsFromMainThread( - std::vector<EventMetrics> events_metrics); - std::vector<EventMetrics> TakeEventsMetrics(); + void AppendEventsMetricsFromMainThread(EventMetrics::List events_metrics); + EventMetrics::List TakeEventsMetrics(); // Requests that we force send RenderFrameMetadata with the next frame. void RequestForceSendMetadata() { force_send_metadata_request_ = true; } @@ -726,6 +725,10 @@ class CC_EXPORT LayerTreeImpl { return host_impl_->DrawTransform(); } + bool IsInSynchronousComposite() const { + return host_impl_->IsInSynchronousComposite(); + } + // 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 @@ -892,7 +895,7 @@ class CC_EXPORT LayerTreeImpl { std::vector<LayerTreeHost::PresentationTimeCallback> presentation_callbacks_; // Event metrics that are reported back from the main thread. - std::vector<EventMetrics> events_metrics_from_main_thread_; + EventMetrics::List events_metrics_from_main_thread_; std::unique_ptr<viz::DelegatedInkMetadata> delegated_ink_metadata_; }; diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index e5a58655788..3d411412c72 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -59,12 +59,10 @@ class CC_EXPORT LayerTreeSettings { base::TimeDelta scrollbar_fade_duration; base::TimeDelta scrollbar_thinning_duration; bool scrollbar_flash_after_any_scroll_update = false; - bool scrollbar_flash_when_mouse_enter = false; SkColor solid_color_scrollbar_color = SK_ColorWHITE; base::TimeDelta scroll_animation_duration_for_testing; bool timeout_and_draw_when_animation_checkerboards = true; bool layers_always_allowed_lcd_text = false; - float minimum_contents_scale = 0.0625f; float low_res_contents_scale_factor = 0.25f; float top_controls_show_threshold = 0.5f; float top_controls_hide_threshold = 0.5f; diff --git a/chromium/cc/trees/occlusion_tracker.cc b/chromium/cc/trees/occlusion_tracker.cc index 7a6bf2068f6..b3ed41e48f5 100644 --- a/chromium/cc/trees/occlusion_tracker.cc +++ b/chromium/cc/trees/occlusion_tracker.cc @@ -350,7 +350,7 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) { if (layer->Is3dSorted()) return; - if (!layer->draw_properties().rounded_corner_bounds.IsEmpty()) + if (!layer->draw_properties().mask_filter_info.IsEmpty()) return; SimpleEnclosedRegion opaque_layer_region = layer->VisibleOpaqueRegion(); diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index c2dafbd27dd..ebe12ad0073 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -924,8 +924,8 @@ class OcclusionTrackerTestFilters : public OcclusionTrackerTest { filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); GetEffectNode(opacity_layer)->filters = filters; - CreateEffectNode(rounded_corner_layer).rounded_corner_bounds = - gfx::RRectF(1, 2, 3, 4, 5, 6); + CreateEffectNode(rounded_corner_layer).mask_filter_info = + gfx::MaskFilterInfo(gfx::RRectF(1, 2, 3, 4, 5, 6)); this->CalcDrawEtc(); EXPECT_TRUE(rounded_corner_layer->contributes_to_drawn_render_surface()); diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index a4a770d1948..d9da2f91bcc 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -344,6 +344,11 @@ gfx::Vector2dF TransformTree::StickyPositionOffset(TransformNode* node) { gfx::Vector2dF ancestor_sticky_box_offset; if (sticky_data->nearest_node_shifting_sticky_box != TransformTree::kInvalidNodeId) { + // TODO(crbug.com/1128479): Investigate why there would be an invalid index + // passed in. Early return for now. + if (sticky_data->nearest_node_shifting_sticky_box >= + static_cast<int>(property_trees()->transform_tree.size())) + return gfx::Vector2dF(); const StickyPositionNodeData* ancestor_sticky_data = GetStickyPositionData(sticky_data->nearest_node_shifting_sticky_box); DCHECK(ancestor_sticky_data); @@ -354,6 +359,11 @@ gfx::Vector2dF TransformTree::StickyPositionOffset(TransformNode* node) { gfx::Vector2dF ancestor_containing_block_offset; if (sticky_data->nearest_node_shifting_containing_block != TransformTree::kInvalidNodeId) { + // TODO(crbug.com/1128479): Investigate why there would be an invalid index + // passed in. Early return for now. + if (sticky_data->nearest_node_shifting_containing_block >= + static_cast<int>(property_trees()->transform_tree.size())) + return gfx::Vector2dF(); const StickyPositionNodeData* ancestor_sticky_data = GetStickyPositionData( sticky_data->nearest_node_shifting_containing_block); DCHECK(ancestor_sticky_data); @@ -1137,7 +1147,7 @@ bool EffectTree::HitTestMayBeAffectedByMask(int effect_id) const { const EffectNode* effect_node = Node(effect_id); for (; effect_node->id != kContentsRootNodeId; effect_node = Node(effect_node->parent_id)) { - if (!effect_node->rounded_corner_bounds.IsEmpty() || + if (!effect_node->mask_filter_info.IsEmpty() || effect_node->has_masking_child) return true; } diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index ab2eb2f52d1..d0f5851130c 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -7,7 +7,9 @@ #include <stddef.h> #include <map> +#include <memory> #include <set> +#include <utility> #include "base/auto_reset.h" #include "cc/base/math_util.h" @@ -165,10 +167,6 @@ bool LayerClipsSubtree(Layer* layer) { !layer->clip_rect().IsEmpty(); } -gfx::RRectF RoundedCornerBounds(Layer* layer) { - return gfx::RRectF(layer->EffectiveClipRect(), layer->corner_radii()); -} - void PropertyTreeBuilderContext::AddClipNodeIfNeeded( const DataForRecursion& data_from_ancestor, Layer* layer, @@ -491,7 +489,8 @@ bool PropertyTreeBuilderContext::AddEffectNodeIfNeeded( // This is currently in the local space of the layer and hence in an invalid // space. Once we have the associated transform node for this effect node, // we will update this to the transform node's coordinate space. - node->rounded_corner_bounds = RoundedCornerBounds(layer); + node->mask_filter_info = + gfx::MaskFilterInfo(layer->EffectiveClipRect(), layer->corner_radii()); node->is_fast_rounded_corner = layer->is_fast_rounded_corner(); } @@ -557,7 +556,8 @@ bool PropertyTreeBuilderContext::UpdateRenderSurfaceIfNeeded( EffectNode* effect_node = effect_tree_.Node(data_for_children->effect_tree_parent); - const bool has_rounded_corner = !effect_node->rounded_corner_bounds.IsEmpty(); + const bool has_rounded_corner = + effect_node->mask_filter_info.HasRoundedCorners(); // Having a rounded corner should trigger a transform node. if (has_rounded_corner) diff --git a/chromium/cc/trees/property_tree_builder_unittest.cc b/chromium/cc/trees/property_tree_builder_unittest.cc index 243de4063b5..c824607608b 100644 --- a/chromium/cc/trees/property_tree_builder_unittest.cc +++ b/chromium/cc/trees/property_tree_builder_unittest.cc @@ -859,7 +859,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // Since this effect node has no descendants that draw and no descendant that // has a rounded corner, it does not need a render surface. const EffectNode* effect_node = GetEffectNode(rounded_corner_layer_1.get()); - gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_1 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), kRoundedCorner1Radius); @@ -869,7 +870,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // Since this node has descendants with roudned corners, it needs a render // surface. It also has 2 descendants that draw. effect_node = GetEffectNode(rounded_corner_layer_2.get()); - gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_2 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), kRoundedCorner2Radius); @@ -879,7 +881,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // Since this node has a descendant that has a rounded corner, it will trigger // the creation of a render surface. effect_node = GetEffectNode(rounded_corner_layer_3.get()); - gfx::RRectF rounded_corner_bounds_3 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_3 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_3.GetSimpleRadius(), kRoundedCorner3Radius); @@ -889,7 +892,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // Since this node has no descendants that draw nor any descendant that has a // rounded corner, it does not need a render surface. effect_node = GetEffectNode(rounded_corner_layer_4.get()); - gfx::RRectF rounded_corner_bounds_4 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_4 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_4.GetSimpleRadius(), kRoundedCorner4Radius); @@ -918,7 +922,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // scale factor is 1.6 thus giving the target space origin of [24, 24]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_rrect_1 = - rounded_corner_layer_1_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_1_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_rrect_1.rect(), bounds_in_target_space); @@ -931,13 +936,16 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // scale factor is 1.6 thus giving the target space origin of [64, 64]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_2 = - rounded_corner_layer_2_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_2_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_2.IsEmpty()); bounds_in_target_space = kRoundedCornerLayer2Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_2 = - rounded_corner_layer_2_impl->render_target()->rounded_corner_bounds(); + rounded_corner_layer_2_impl->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_2.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_2.GetSimpleRadius(), kRoundedCorner2Radius * kDeviceScale); @@ -948,7 +956,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // device scale factor is 1.6 thus giving the target space origin of [64, 88]. // The corner radius is also scaled by a factor of 1.6 * transform scale. const gfx::RRectF actual_self_rrect_3 = - rounded_corner_layer_3_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_3_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_3.IsEmpty()); bounds_in_target_space = kRoundedCornerLayer3Bound; @@ -960,7 +969,9 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { bounds_in_target_space.set_size(transformed_size); const gfx::RRectF actual_render_target_rrect_3 = - rounded_corner_layer_3_impl->render_target()->rounded_corner_bounds(); + rounded_corner_layer_3_impl->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_3.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_3.GetSimpleRadius(), kRoundedCorner3Radius * kDeviceScale * kRoundedCorner3Scale); @@ -972,7 +983,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBounds) { // rigin of [3.2, 3.2]. // The corner radius is also scaled by a factor of 3.2. const gfx::RRectF actual_rrect_4 = - rounded_corner_layer_4_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_4_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer4Bound; bounds_in_target_space.Scale(kDeviceScale * kRoundedCorner3Scale); EXPECT_EQ(actual_rrect_4.rect(), bounds_in_target_space); @@ -1042,7 +1054,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsInterveningRenderTarget) { // that has a rounded corner before the render surface, it does not need a // render surface. const EffectNode* effect_node = GetEffectNode(rounded_corner_layer_1.get()); - gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_1 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), kRoundedCorner1Radius); @@ -1052,7 +1065,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsInterveningRenderTarget) { // Since this effect node has no descendants that draw and no descendant that // has a rounded corner, it does not need a render surface. effect_node = GetEffectNode(rounded_corner_layer_2.get()); - gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_2 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), kRoundedCorner2Radius); @@ -1077,7 +1091,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsInterveningRenderTarget) { // scale factor is 1.6 thus giving the target space origin of [96, 0]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_rrect_1 = - rounded_corner_layer_1_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_1_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_rrect_1.rect(), bounds_in_target_space); @@ -1088,7 +1103,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsInterveningRenderTarget) { // The render target for this layer is |render_surface|. // The offset from the origin of the render target is [0, 0]. const gfx::RRectF actual_rrect_2 = - rounded_corner_layer_2_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_2_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer2Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_rrect_2.rect(), bounds_in_target_space); @@ -1157,7 +1173,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsSiblingRenderTarget) { // Since this effect node has 1 descendant with a rounded corner without a // render surface along the chain, it need a render surface. const EffectNode* effect_node = GetEffectNode(rounded_corner_layer_1.get()); - gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_1 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), kRoundedCorner1Radius); @@ -1167,7 +1184,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsSiblingRenderTarget) { // Since this effect node has no descendants that draw and no descendant that // has a rounded corner, it does not need a render surface. effect_node = GetEffectNode(rounded_corner_layer_2.get()); - gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_2 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), kRoundedCorner2Radius); @@ -1192,13 +1210,16 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsSiblingRenderTarget) { // scale factor is 1.6 thus giving the target space origin of [0, 96]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_1 = - rounded_corner_layer_1_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_1_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_1.IsEmpty()); gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_1 = - rounded_corner_layer_1_impl->render_target()->rounded_corner_bounds(); + rounded_corner_layer_1_impl->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_1.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_1.GetSimpleRadius(), kRoundedCorner1Radius * kDeviceScale); @@ -1207,7 +1228,8 @@ TEST_F(PropertyTreeBuilderTest, RoundedCornerBoundsSiblingRenderTarget) { // The render target for this layer is |render_surface|. // The offset from the origin of the render target is [0, 0]. const gfx::RRectF actual_rrect_2 = - rounded_corner_layer_2_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_2_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer2Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_rrect_2.rect(), bounds_in_target_space); @@ -1297,7 +1319,8 @@ TEST_F(PropertyTreeBuilderTest, FastRoundedCornerDoesNotTriggerRenderSurface) { // surface even though it has 2 layers in the subtree that draws content. const EffectNode* effect_node = GetEffectNode(fast_rounded_corner_layer.get()); - gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_1 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_TRUE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), @@ -1307,7 +1330,8 @@ TEST_F(PropertyTreeBuilderTest, FastRoundedCornerDoesNotTriggerRenderSurface) { // Since this node has 2 descendants that draw, it will have a rounded corner. effect_node = GetEffectNode(rounded_corner_layer.get()); - gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_2 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), @@ -1336,7 +1360,8 @@ TEST_F(PropertyTreeBuilderTest, FastRoundedCornerDoesNotTriggerRenderSurface) { // The offset from the origin of the render target is [0, 0] and the device // scale factor is 1.6. const gfx::RRectF actual_rrect_1 = - fast_rounded_corner_layer_impl->draw_properties().rounded_corner_bounds; + fast_rounded_corner_layer_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_rrect_1.rect(), bounds_in_target_space); @@ -1347,9 +1372,9 @@ TEST_F(PropertyTreeBuilderTest, FastRoundedCornerDoesNotTriggerRenderSurface) { // This should have the same rounded corner boudns as fast rounded corner // layer. const gfx::RRectF layer_1_rrect = - layer_1_impl->draw_properties().rounded_corner_bounds; + layer_1_impl->draw_properties().mask_filter_info.rounded_corner_bounds(); const gfx::RRectF layer_2_rrect = - layer_2_impl->draw_properties().rounded_corner_bounds; + layer_2_impl->draw_properties().mask_filter_info.rounded_corner_bounds(); EXPECT_EQ(actual_rrect_1, layer_1_rrect); EXPECT_EQ(actual_rrect_1, layer_2_rrect); @@ -1359,13 +1384,16 @@ TEST_F(PropertyTreeBuilderTest, FastRoundedCornerDoesNotTriggerRenderSurface) { // scale factor is 1.6 thus giving the target space origin of [64, 64]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_2 = - rounded_corner_layer_impl->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_2.IsEmpty()); bounds_in_target_space = kRoundedCornerLayer2Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_2 = - rounded_corner_layer_impl->render_target()->rounded_corner_bounds(); + rounded_corner_layer_impl->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_2.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_2.GetSimpleRadius(), kRoundedCorner2Radius * kDeviceScale); @@ -1373,9 +1401,9 @@ TEST_F(PropertyTreeBuilderTest, FastRoundedCornerDoesNotTriggerRenderSurface) { // Layer 3 and layer 4 should have no rounded corner bounds set as their // parent is a render surface. const gfx::RRectF layer_3_rrect = - layer_3_impl->draw_properties().rounded_corner_bounds; + layer_3_impl->draw_properties().mask_filter_info.rounded_corner_bounds(); const gfx::RRectF layer_4_rrect = - layer_4_impl->draw_properties().rounded_corner_bounds; + layer_4_impl->draw_properties().mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(layer_3_rrect.IsEmpty()); EXPECT_TRUE(layer_4_rrect.IsEmpty()); } @@ -1462,7 +1490,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer has a descendant that has rounded corner, this node will // require a render surface. const EffectNode* effect_node = GetEffectNode(rounded_corner_layer_1.get()); - gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_1 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), @@ -1473,7 +1502,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer has no descendant with rounded corner or drawable, it will // not have a render surface. effect_node = GetEffectNode(fast_rounded_corner_layer_2.get()); - gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_2 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_TRUE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), @@ -1484,7 +1514,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer has 1 descendant with a rounded corner, it should have a // render surface. effect_node = GetEffectNode(rounded_corner_layer_3.get()); - gfx::RRectF rounded_corner_bounds_3 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_3 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_3.GetSimpleRadius(), @@ -1494,7 +1525,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer no descendants, it would no thave a render pass. effect_node = GetEffectNode(rounded_corner_layer_4.get()); - gfx::RRectF rounded_corner_bounds_4 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_4 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_4.GetSimpleRadius(), @@ -1523,13 +1555,16 @@ TEST_F(PropertyTreeBuilderTest, // The offset from the origin of the render target is [5, 5] and the device // scale factor is 1.6 giving a total offset of [8, 8]. const gfx::RRectF actual_self_rrect_1 = - rounded_corner_layer_impl_1->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl_1->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_1.IsEmpty()); gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_1 = - rounded_corner_layer_impl_1->render_target()->rounded_corner_bounds(); + rounded_corner_layer_impl_1->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_1.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_1.GetSimpleRadius(), kRoundedCorner1Radius * kDeviceScale); @@ -1539,7 +1574,8 @@ TEST_F(PropertyTreeBuilderTest, // The offset from the origin of the render target is [0, 0] and the device // scale factor is 1.6. The corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_2 = - fast_rounded_corner_layer_impl_2->draw_properties().rounded_corner_bounds; + fast_rounded_corner_layer_impl_2->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer2Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_self_rrect_2.rect(), bounds_in_target_space); @@ -1552,13 +1588,16 @@ TEST_F(PropertyTreeBuilderTest, // scale factor is 1.6 thus giving the target space origin of [64, 64]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_3 = - rounded_corner_layer_impl_3->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl_3->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_3.IsEmpty()); bounds_in_target_space = kRoundedCornerLayer3Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_3 = - rounded_corner_layer_impl_3->render_target()->rounded_corner_bounds(); + rounded_corner_layer_impl_3->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_3.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_3.GetSimpleRadius(), kRoundedCorner3Radius * kDeviceScale); @@ -1569,7 +1608,8 @@ TEST_F(PropertyTreeBuilderTest, // scale factor is 1.6 thus giving the target space origin of [48, 0]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_4 = - rounded_corner_layer_impl_4->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl_4->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer4Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_self_rrect_4.rect(), bounds_in_target_space); @@ -1658,7 +1698,8 @@ TEST_F(PropertyTreeBuilderTest, // surface. const EffectNode* effect_node = GetEffectNode(fast_rounded_corner_layer_1.get()); - gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_1 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_TRUE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), @@ -1669,7 +1710,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer has no descendant with rounded corner or drawable, it will // not have a render surface. effect_node = GetEffectNode(rounded_corner_layer_1.get()); - gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_2 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), @@ -1680,7 +1722,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer has a descendant with rounded corner, it should have a // render surface. effect_node = GetEffectNode(rounded_corner_layer_2.get()); - gfx::RRectF rounded_corner_bounds_3 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_3 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_3.GetSimpleRadius(), @@ -1690,7 +1733,8 @@ TEST_F(PropertyTreeBuilderTest, // Since this layer has no descendant, it does not need a render surface. effect_node = GetEffectNode(rounded_corner_layer_3.get()); - gfx::RRectF rounded_corner_bounds_4 = effect_node->rounded_corner_bounds; + gfx::RRectF rounded_corner_bounds_4 = + effect_node->mask_filter_info.rounded_corner_bounds(); EXPECT_FALSE(effect_node->HasRenderSurface()); EXPECT_FALSE(effect_node->is_fast_rounded_corner); EXPECT_FLOAT_EQ(rounded_corner_bounds_4.GetSimpleRadius(), @@ -1719,14 +1763,16 @@ TEST_F(PropertyTreeBuilderTest, // The offset from the origin of the render target is [5, 5] and the device // scale factor is 1.6. const gfx::RRectF actual_self_rrect_1 = - fast_rounded_corner_layer_impl_1->draw_properties().rounded_corner_bounds; + fast_rounded_corner_layer_impl_1->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_1.IsEmpty()); gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_1 = fast_rounded_corner_layer_impl_1->render_target() - ->rounded_corner_bounds(); + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_1.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_1.GetSimpleRadius(), kRoundedCorner1Radius * kDeviceScale); @@ -1736,7 +1782,8 @@ TEST_F(PropertyTreeBuilderTest, // The offset from the origin of the render target is [0, 0] and the device // scale factor is 1.6. The corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_2 = - rounded_corner_layer_impl_1->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl_1->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer2Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_self_rrect_2.rect(), bounds_in_target_space); @@ -1749,13 +1796,16 @@ TEST_F(PropertyTreeBuilderTest, // scale factor is 1.6 thus giving the target space origin of [8, 8]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_3 = - rounded_corner_layer_impl_2->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl_2->draw_properties() + .mask_filter_info.rounded_corner_bounds(); EXPECT_TRUE(actual_self_rrect_3.IsEmpty()); bounds_in_target_space = kRoundedCornerLayer3Bound; bounds_in_target_space.Scale(kDeviceScale); const gfx::RRectF actual_render_target_rrect_3 = - rounded_corner_layer_impl_2->render_target()->rounded_corner_bounds(); + rounded_corner_layer_impl_2->render_target() + ->mask_filter_info() + .rounded_corner_bounds(); EXPECT_EQ(actual_render_target_rrect_3.rect(), bounds_in_target_space); EXPECT_FLOAT_EQ(actual_render_target_rrect_3.GetSimpleRadius(), kRoundedCorner3Radius * kDeviceScale); @@ -1766,7 +1816,8 @@ TEST_F(PropertyTreeBuilderTest, // scale factor is 1.6 thus giving the target space origin of [0, 8]. The // corner radius is also scaled by a factor of 1.6. const gfx::RRectF actual_self_rrect_4 = - rounded_corner_layer_impl_3->draw_properties().rounded_corner_bounds; + rounded_corner_layer_impl_3->draw_properties() + .mask_filter_info.rounded_corner_bounds(); bounds_in_target_space = kRoundedCornerLayer4Bound; bounds_in_target_space.Scale(kDeviceScale); EXPECT_EQ(actual_self_rrect_4.rect(), bounds_in_target_space); diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index eefabd96dfb..13cccd11026 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -16,6 +16,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "cc/base/devtools_instrumentation.h" +#include "cc/base/features.h" #include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/input/browser_controls_offset_manager.h" #include "cc/metrics/compositor_timing_history.h" @@ -78,6 +79,7 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this); const LayerTreeSettings& settings = layer_tree_host->GetSettings(); send_compositor_frame_ack_ = settings.send_compositor_frame_ack; + last_raster_priority_ = SAME_PRIORITY_FOR_BOTH_TREES; SchedulerSettings scheduler_settings(settings.ToSchedulerSettings()); @@ -244,6 +246,10 @@ void ProxyImpl::RequestBeginMainFrameNotExpected(bool new_state) { scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(new_state); } +bool ProxyImpl::IsInSynchronousComposite() const { + return false; +} + void ProxyImpl::NotifyReadyToCommitOnImpl( CompletionEvent* completion, LayerTreeHost* layer_tree_host, @@ -385,10 +391,28 @@ bool ProxyImpl::IsBeginMainFrameExpected() { void ProxyImpl::RenewTreePriority() { DCHECK(IsImplThread()); - const bool user_interaction_in_progress = + + bool scroll_type_considered_interaction = false; + bool non_scroll_interaction_in_progress = host_impl_->IsPinchGestureActive() || - host_impl_->page_scale_animation_active() || - host_impl_->IsActivelyPrecisionScrolling(); + host_impl_->page_scale_animation_active(); + + ActivelyScrollingType actively_scrolling_type = + host_impl_->GetActivelyScrollingType(); + + switch (actively_scrolling_type) { + case ActivelyScrollingType::kNone: + break; + case ActivelyScrollingType::kPrecise: + scroll_type_considered_interaction = true; + break; + case ActivelyScrollingType::kAnimated: + scroll_type_considered_interaction = base::FeatureList::IsEnabled( + features::kSchedulerSmoothnessForAnimatedScrolls); + } + + bool user_interaction_in_progress = + non_scroll_interaction_in_progress || scroll_type_considered_interaction; if (host_impl_->ukm_manager()) { host_impl_->ukm_manager()->SetUserInteractionInProgress( @@ -400,11 +424,19 @@ void ProxyImpl::RenewTreePriority() { smoothness_priority_expiration_notifier_.Schedule(); // We use the same priority for both trees by default. - TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES; + TreePriority scheduler_tree_priority = SAME_PRIORITY_FOR_BOTH_TREES; + TreePriority raster_tree_priority = SAME_PRIORITY_FOR_BOTH_TREES; // Smoothness takes priority if we have an expiration for it scheduled. - if (smoothness_priority_expiration_notifier_.HasPendingNotification()) - tree_priority = SMOOTHNESS_TAKES_PRIORITY; + if (smoothness_priority_expiration_notifier_.HasPendingNotification()) { + scheduler_tree_priority = SMOOTHNESS_TAKES_PRIORITY; + if (non_scroll_interaction_in_progress || + actively_scrolling_type == ActivelyScrollingType::kPrecise || + last_raster_priority_ == SMOOTHNESS_TAKES_PRIORITY) + raster_tree_priority = SMOOTHNESS_TAKES_PRIORITY; + } + + last_raster_priority_ = raster_tree_priority; // New content always takes priority when ui resources have been evicted. if (host_impl_->active_tree()->GetDeviceViewport().size().IsEmpty() || @@ -413,10 +445,10 @@ void ProxyImpl::RenewTreePriority() { // tree might be freed. We need to set RequiresHighResToDraw to ensure that // high res tiles will be required to activate pending tree. host_impl_->SetRequiresHighResToDraw(); - tree_priority = NEW_CONTENT_TAKES_PRIORITY; + scheduler_tree_priority = raster_tree_priority = NEW_CONTENT_TAKES_PRIORITY; } - host_impl_->SetTreePriority(tree_priority); + host_impl_->SetTreePriority(raster_tree_priority); // Only put the scheduler in impl latency prioritization mode if we don't // have a scroll listener. This gives the scroll listener a better chance of @@ -426,7 +458,7 @@ void ProxyImpl::RenewTreePriority() { host_impl_->ScrollAffectsScrollHandler() ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER; - scheduler_->SetTreePrioritiesAndScrollState(tree_priority, + scheduler_->SetTreePrioritiesAndScrollState(scheduler_tree_priority, scroll_handler_state); } diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index e8578e8abf9..815935a5d41 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -6,6 +6,7 @@ #define CC_TREES_PROXY_IMPL_H_ #include <memory> +#include <vector> #include "base/memory/weak_ptr.h" #include "cc/base/completion_event.h" @@ -148,6 +149,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, base::TimeTicks time) override; void FrameIntervalUpdated(base::TimeDelta interval) override {} bool HasCustomPropertyAnimations() const override; + bool IsInSynchronousComposite() const override; DrawResult DrawInternal(bool forced_draw); @@ -176,6 +178,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, bool send_compositor_frame_ack_; + TreePriority last_raster_priority_; + TaskRunnerProvider* task_runner_provider_; DelayedUniqueNotifier smoothness_priority_expiration_notifier_; diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 62247ad3dbf..f2050b82334 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -557,9 +557,15 @@ void SingleThreadProxy::RequestBeginMainFrameNotExpected(bool new_state) { } } -void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time, - bool raster) { - TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately"); +bool SingleThreadProxy::IsInSynchronousComposite() const { + return inside_synchronous_composite_; +} + +void SingleThreadProxy::CompositeImmediatelyForTest( + base::TimeTicks frame_begin_time, + bool raster) { + TRACE_EVENT0("cc,benchmark", + "SingleThreadProxy::CompositeImmediatelyForTest"); DCHECK(task_runner_provider_->IsMainThread()); #if DCHECK_IS_ON() DCHECK(!inside_impl_frame_); diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index b65b1069041..8b0960dbd4f 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -6,6 +6,8 @@ #define CC_TREES_SINGLE_THREAD_PROXY_H_ #include <limits> +#include <memory> +#include <vector> #include "base/cancelable_callback.h" #include "base/time/time.h" @@ -138,6 +140,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void NotifyPaintWorkletStateChange( Scheduler::PaintWorkletState state) override; void NotifyThroughputTrackerResults(CustomTrackerResults results) override; + bool IsInSynchronousComposite() const override; void RequestNewLayerTreeFrameSink(); @@ -151,7 +154,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, // Called by the legacy path where RenderWidget does the scheduling. // Rasterization of tiles is only performed when |raster| is true. - void CompositeImmediately(base::TimeTicks frame_begin_time, bool raster); + void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time, + bool raster); protected: SingleThreadProxy(LayerTreeHost* layer_tree_host, diff --git a/chromium/cc/trees/ukm_manager.cc b/chromium/cc/trees/ukm_manager.cc index 348e4b66656..b3761e46d3d 100644 --- a/chromium/cc/trees/ukm_manager.cc +++ b/chromium/cc/trees/ukm_manager.cc @@ -116,6 +116,8 @@ void UkmManager::RecordThroughputUKM( CASE_FOR_MAIN_THREAD_TRACKER(TouchScroll); CASE_FOR_MAIN_THREAD_TRACKER(Video); CASE_FOR_MAIN_THREAD_TRACKER(WheelScroll); + CASE_FOR_MAIN_THREAD_TRACKER(CanvasAnimation); + CASE_FOR_MAIN_THREAD_TRACKER(JSAnimation); #undef CASE_FOR_MAIN_THREAD_TRACKER default: NOTREACHED(); @@ -261,6 +263,8 @@ void UkmManager::RecordCompositorLatencyUKM( CASE_FOR_TRACKER(TouchScroll); CASE_FOR_TRACKER(Video); CASE_FOR_TRACKER(WheelScroll); + CASE_FOR_TRACKER(CanvasAnimation); + CASE_FOR_TRACKER(JSAnimation); #undef CASE_FOR_TRACKER default: NOTREACHED(); @@ -272,23 +276,24 @@ void UkmManager::RecordCompositorLatencyUKM( } void UkmManager::RecordEventLatencyUKM( - const std::vector<EventMetrics>& events_metrics, + const EventMetrics::List& events_metrics, const std::vector<CompositorFrameReporter::StageData>& stage_history, const viz::FrameTimingDetails& viz_breakdown) const { using StageType = CompositorFrameReporter::StageType; - for (const EventMetrics& event_metrics : events_metrics) { + for (const auto& event_metrics : events_metrics) { ukm::builders::Graphics_Smoothness_EventLatency builder(source_id_); - builder.SetEventType(static_cast<int64_t>(event_metrics.type())); + builder.SetEventType(static_cast<int64_t>(event_metrics->type())); - if (event_metrics.scroll_type()) { + if (event_metrics->scroll_type()) { builder.SetScrollInputType( - static_cast<int64_t>(*event_metrics.scroll_type())); + static_cast<int64_t>(*event_metrics->scroll_type())); if (!viz_breakdown.swap_timings.is_null()) { builder.SetTotalLatencyToSwapBegin( - (viz_breakdown.swap_timings.swap_start - event_metrics.time_stamp()) + (viz_breakdown.swap_timings.swap_start - + event_metrics->time_stamp()) .InMicroseconds()); } } @@ -301,7 +306,7 @@ void UkmManager::RecordEventLatencyUKM( auto stage_it = std::find_if( stage_history.begin(), stage_history.end(), [&event_metrics](const CompositorFrameReporter::StageData& stage) { - return stage.start_time > event_metrics.time_stamp(); + return stage.start_time > event_metrics->time_stamp(); }); // TODO(crbug.com/1079116): Ideally, at least the start time of // SubmitCompositorFrameToPresentationCompositorFrame stage should be @@ -314,13 +319,13 @@ void UkmManager::RecordEventLatencyUKM( continue; builder.SetBrowserToRendererCompositor( - (stage_it->start_time - event_metrics.time_stamp()).InMicroseconds()); + (stage_it->start_time - event_metrics->time_stamp()).InMicroseconds()); for (; stage_it != stage_history.end(); ++stage_it) { // Total latency is calculated since the event timestamp. const base::TimeTicks start_time = stage_it->stage_type == StageType::kTotalLatency - ? event_metrics.time_stamp() + ? event_metrics->time_stamp() : stage_it->start_time; switch (stage_it->stage_type) { diff --git a/chromium/cc/trees/ukm_manager.h b/chromium/cc/trees/ukm_manager.h index c4e3e833c65..b51147f71c3 100644 --- a/chromium/cc/trees/ukm_manager.h +++ b/chromium/cc/trees/ukm_manager.h @@ -60,7 +60,7 @@ class CC_EXPORT UkmManager { const viz::FrameTimingDetails& viz_breakdown) const; void RecordEventLatencyUKM( - const std::vector<EventMetrics>& events_metrics, + const EventMetrics::List& events_metrics, const std::vector<CompositorFrameReporter::StageData>& stage_history, const viz::FrameTimingDetails& viz_breakdown) const; diff --git a/chromium/cc/trees/ukm_manager_unittest.cc b/chromium/cc/trees/ukm_manager_unittest.cc index a00d6826cba..6449021af38 100644 --- a/chromium/cc/trees/ukm_manager_unittest.cc +++ b/chromium/cc/trees/ukm_manager_unittest.cc @@ -360,8 +360,9 @@ TEST_F(UkmManagerTest, EventLatency) { event_time, ui::ScrollInputType::kWheel), }; EXPECT_THAT(event_metrics_ptrs, ::testing::Each(::testing::NotNull())); - std::vector<EventMetrics> events_metrics = { - *event_metrics_ptrs[0], *event_metrics_ptrs[1], *event_metrics_ptrs[2]}; + EventMetrics::List events_metrics( + std::make_move_iterator(std::begin(event_metrics_ptrs)), + std::make_move_iterator(std::end(event_metrics_ptrs))); const base::TimeTicks begin_impl_time = (now += base::TimeDelta::FromMicroseconds(10)); @@ -418,7 +419,7 @@ TEST_F(UkmManagerTest, EventLatency) { EXPECT_EQ(3u, entries.size()); for (size_t i = 0; i < entries.size(); i++) { const auto* entry = entries[i]; - const auto* event_metrics = event_metrics_ptrs[i].get(); + const auto* event_metrics = events_metrics[i].get(); EXPECT_NE(ukm::kInvalidSourceId, entry->source_id); test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, GURL(kTestUrl)); |