diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-02-04 17:20:24 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-02-12 08:15:25 +0000 |
commit | 8fa0776f1f79e91fc9c0b9c1ba11a0a29c05196b (patch) | |
tree | 788d8d7549712682703a0310ca4a0f0860d4802b /chromium/cc | |
parent | 606d85f2a5386472314d39923da28c70c60dc8e7 (diff) |
BASELINE: Update Chromium to 98.0.4758.90
Change-Id: Ib7c41539bf8a8e0376bd639f27d68294de90f3c8
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc')
370 files changed, 10231 insertions, 5987 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn index 3234a484465..bf49b8433d4 100644 --- a/chromium/cc/BUILD.gn +++ b/chromium/cc/BUILD.gn @@ -128,6 +128,10 @@ cc_component("cc") { "layers/scrollbar_layer_base.h", "layers/scrollbar_layer_impl_base.cc", "layers/scrollbar_layer_impl_base.h", + "layers/shared_element_layer.cc", + "layers/shared_element_layer.h", + "layers/shared_element_layer_impl.cc", + "layers/shared_element_layer_impl.h", "layers/solid_color_layer.cc", "layers/solid_color_layer.h", "layers/solid_color_layer_impl.cc", @@ -180,6 +184,8 @@ cc_component("cc") { "metrics/event_metrics.h", "metrics/events_metrics_manager.cc", "metrics/events_metrics_manager.h", + "metrics/frame_info.cc", + "metrics/frame_info.h", "metrics/frame_sequence_metrics.cc", "metrics/frame_sequence_metrics.h", "metrics/frame_sequence_tracker.cc", @@ -201,6 +207,7 @@ cc_component("cc") { "metrics/throughput_ukm_reporter.h", "metrics/total_frame_counter.cc", "metrics/total_frame_counter.h", + "metrics/ukm_smoothness_data.cc", "metrics/ukm_smoothness_data.h", "metrics/video_playback_roughness_reporter.cc", "metrics/video_playback_roughness_reporter.h", @@ -335,6 +342,8 @@ cc_component("cc") { "trees/clip_expander.h", "trees/clip_node.cc", "trees/clip_node.h", + "trees/commit_state.cc", + "trees/commit_state.h", "trees/compositor_commit_data.cc", "trees/compositor_commit_data.h", "trees/compositor_mode.h", @@ -412,8 +421,6 @@ cc_component("cc") { "trees/swap_promise.h", "trees/swap_promise_manager.cc", "trees/swap_promise_manager.h", - "trees/swap_promise_monitor.cc", - "trees/swap_promise_monitor.h", "trees/target_property.cc", "trees/target_property.h", "trees/task_runner_provider.cc", @@ -428,6 +435,7 @@ cc_component("cc") { "trees/ukm_manager.h", "trees/viewport_layers.cc", "trees/viewport_layers.h", + "trees/viewport_property_ids.h", ] public_deps = [ @@ -453,6 +461,7 @@ cc_component("cc") { "//services/metrics/public/cpp:ukm_builders", "//services/metrics/public/mojom", "//services/tracing/public/cpp:cpp", + "//ui/base:features", "//ui/events:events_base", "//ui/gfx", "//ui/gfx/animation/keyframe", @@ -475,6 +484,8 @@ cc_test_static_library("test_support") { "test/fake_compositor_frame_reporting_controller.h", "test/fake_content_layer_client.cc", "test/fake_content_layer_client.h", + "test/fake_frame_info.cc", + "test/fake_frame_info.h", "test/fake_impl_task_runner_provider.h", "test/fake_layer_tree_frame_sink.cc", "test/fake_layer_tree_frame_sink.h", @@ -527,7 +538,6 @@ cc_test_static_library("test_support") { "test/fake_ui_resource_layer_tree_host_impl.h", "test/fake_video_frame_provider.cc", "test/fake_video_frame_provider.h", - "test/geometry_test_utils.h", "test/layer_test_common.cc", "test/layer_test_common.h", "test/layer_tree_impl_test_base.cc", @@ -540,6 +550,9 @@ cc_test_static_library("test_support") { "test/layer_tree_pixel_test.h", "test/layer_tree_test.cc", "test/layer_tree_test.h", + "test/lottie_test_data.h", + "test/mock_latency_info_swap_promise_monitor.cc", + "test/mock_latency_info_swap_promise_monitor.h", "test/mock_layer_tree_mutator.cc", "test/mock_layer_tree_mutator.h", "test/mock_mutator_host.cc", @@ -717,6 +730,7 @@ cc_test("cc_unittests") { "metrics/compositor_timing_history_unittest.cc", "metrics/dropped_frame_counter_unittest.cc", "metrics/events_metrics_manager_unittest.cc", + "metrics/frame_info_unittest.cc", "metrics/frame_sequence_metrics_unittest.cc", "metrics/frame_sequence_tracker_unittest.cc", "metrics/frame_sorter_unittest.cc", @@ -822,9 +836,14 @@ cc_test("cc_unittests") { "test/run_all_unittests.cc", ] - if (!is_android) { + if (skia_support_skottie) { data = [ "//components/viz/test/data/" ] - sources += [ "paint/skottie_transfer_cache_entry_unittest.cc" ] + sources += [ + "paint/skottie_mru_resource_provider_unittest.cc", + "paint/skottie_resource_metadata_unittest.cc", + "paint/skottie_transfer_cache_entry_unittest.cc", + "paint/skottie_wrapper_unittest.cc", + ] } deps = [ @@ -851,6 +870,7 @@ cc_test("cc_unittests") { "//media", "//mojo/core/embedder", "//mojo/public/cpp/bindings", + "//skia:buildflags", "//skia:skcms", "//testing/gmock", "//testing/gtest", diff --git a/chromium/cc/DEPS b/chromium/cc/DEPS index dc197834bf6..6602a1c69a4 100644 --- a/chromium/cc/DEPS +++ b/chromium/cc/DEPS @@ -36,9 +36,12 @@ include_rules = [ "+third_party/khronos/GLES2/gl2ext.h", "+third_party/libyuv", "+third_party/skia/include", + "+third_party/skia/modules/skottie/include", + "+third_party/skia/modules/skresources/include", "+third_party/skia/src/core/SkRemoteGlyphCache.h", "+third_party/skia/src/effects/imagefilters/SkRuntimeImageFilter.h", "+third_party/perfetto/protos/perfetto/trace/track_event", + "+ui/base", "+ui/events/types", "+ui/latency", "+ui/gfx", diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py index a3a40eda5ef..63191ca5c1f 100644 --- a/chromium/cc/PRESUBMIT.py +++ b/chromium/cc/PRESUBMIT.py @@ -278,30 +278,6 @@ def CheckForUseOfWrongClock(input_api, else: return [] -def CheckForDisallowMacros(input_api, output_api, allowlist=CC_SOURCE_FILES, - denylist=None): - denylist = tuple(denylist or input_api.DEFAULT_FILES_TO_SKIP) - source_file_filter = lambda x: input_api.FilterSourceFile(x, allowlist, - denylist) - - disallow_macro_files = [] - - for f in input_api.AffectedSourceFiles(source_file_filter): - contents = input_api.ReadFile(f, 'rb') - # DISALLOW macros are not allowed, use deleted constructors instead. - if re.search(r"\bDISALLOW_COPY\(", contents) or \ - re.search(r"\bDISALLOW_ASSIGN\(", contents) or \ - re.search(r"\bDISALLOW_COPY_AND_ASSIGN\(", contents) or \ - re.search(r"\bDISALLOW_IMPLICIT_CONSTRUCTORS\(", contents): - disallow_macro_files.append(f.LocalPath()) - - if disallow_macro_files: - return [output_api.PresubmitError( - 'The following files use DISALLOW* macros. In cc, please use deleted ' - 'constructors/operators instead.', - items=disallow_macro_files)] - return [] - def CheckChangeOnUpload(input_api, output_api): results = [] results += CheckAsserts(input_api, output_api) @@ -313,5 +289,4 @@ def CheckChangeOnUpload(input_api, output_api): results += CheckNamespace(input_api, output_api) results += CheckForUseOfWrongClock(input_api, output_api) results += FindUselessIfdefs(input_api, output_api) - results += CheckForDisallowMacros(input_api, output_api) return results diff --git a/chromium/cc/animation/animation.cc b/chromium/cc/animation/animation.cc index 34af25da509..3b1dced3c26 100644 --- a/chromium/cc/animation/animation.cc +++ b/chromium/cc/animation/animation.cc @@ -26,15 +26,13 @@ scoped_refptr<Animation> Animation::Create(int id) { return base::WrapRefCounted(new Animation(id)); } -Animation::Animation(int id) : Animation(id, nullptr) {} - -Animation::Animation(int id, std::unique_ptr<KeyframeEffect> keyframe_effect) - : animation_host_(), animation_timeline_(), animation_delegate_(), id_(id) { +Animation::Animation(int id) + : animation_host_(), + animation_timeline_(), + animation_delegate_(), + id_(id), + keyframe_effect_(std::make_unique<KeyframeEffect>(this)) { DCHECK(id_); - if (!keyframe_effect) - keyframe_effect = std::make_unique<KeyframeEffect>(this); - - keyframe_effect_ = std::move(keyframe_effect); } Animation::~Animation() { @@ -91,6 +89,11 @@ void Animation::AttachElementInternal(ElementId element_id) { RegisterAnimation(); } +void Animation::SetKeyframeEffectForTesting( + std::unique_ptr<KeyframeEffect> effect) { + keyframe_effect_ = std::move(effect); +} + void Animation::DetachElement() { DCHECK(keyframe_effect_->has_attached_element()); @@ -216,8 +219,12 @@ void Animation::DelegateAnimationEvent(const AnimationEvent& event) { } } -bool Animation::AffectsCustomProperty() const { - return keyframe_effect_->AffectsCustomProperty(); +bool Animation::RequiresInvalidation() const { + return keyframe_effect_->RequiresInvalidation(); +} + +bool Animation::AffectsNativeProperty() const { + return keyframe_effect_->AffectsNativeProperty(); } void Animation::SetNeedsCommit() { diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h index 90ade7a56a1..4d5d07ef17f 100644 --- a/chromium/cc/animation/animation.h +++ b/chromium/cc/animation/animation.h @@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation_export.h" @@ -116,7 +117,12 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { // to be dispatched. void DispatchAndDelegateAnimationEvent(const AnimationEvent& event); - bool AffectsCustomProperty() const; + // Returns true if this animation effects pending tree, such as a custom + // property animation with paint worklet. + bool RequiresInvalidation() const; + // Returns true if this animation effects active tree, such as a transform + // animation. + bool AffectsNativeProperty() const; void SetNeedsPushProperties(); @@ -135,6 +141,8 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { virtual bool IsWorkletAnimation() const; + void SetKeyframeEffectForTesting(std::unique_ptr<KeyframeEffect>); + private: friend class base::RefCounted<Animation>; @@ -149,12 +157,11 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { protected: explicit Animation(int id); - Animation(int id, std::unique_ptr<KeyframeEffect>); virtual ~Animation(); - AnimationHost* animation_host_; - AnimationTimeline* animation_timeline_; - AnimationDelegate* animation_delegate_; + raw_ptr<AnimationHost> animation_host_; + raw_ptr<AnimationTimeline> animation_timeline_; + raw_ptr<AnimationDelegate> animation_delegate_; int id_; std::unique_ptr<KeyframeEffect> keyframe_effect_; diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc index e6f4a9d2da6..509cf983f6d 100644 --- a/chromium/cc/animation/animation_host.cc +++ b/chromium/cc/animation/animation_host.cc @@ -8,6 +8,7 @@ #include <memory> #include <utility> +#include "base/auto_reset.h" #include "base/bind.h" #include "base/callback.h" #include "base/containers/contains.h" @@ -280,9 +281,13 @@ void AnimationHost::SetNeedsPushProperties() { mutator_host_client_->SetMutatorsNeedCommit(); } -void AnimationHost::PushPropertiesTo(MutatorHost* mutator_host_impl) { +void AnimationHost::PushPropertiesTo(MutatorHost* mutator_host_impl, + const PropertyTrees& property_trees) { auto* host_impl = static_cast<AnimationHost*>(mutator_host_impl); + base::AutoReset<const PropertyTrees*> properties(&property_trees_, + &property_trees); + // Update animation counts and whether raf was requested. These explicitly // do not request push properties and are pushed as part of the next commit // when it happens as requesting a commit leads to performance issues: @@ -334,6 +339,9 @@ void AnimationHost::RemoveTimelinesFromImplThread( } void AnimationHost::PushPropertiesToImplThread(AnimationHost* host_impl) { + base::AutoReset<const PropertyTrees*> properties(&host_impl->property_trees_, + property_trees_); + // Sync all animations with impl thread to create ElementAnimations. This // needs to happen before the element animations are synced below. for (auto& kv : id_to_timeline_map_) { @@ -372,6 +380,12 @@ AnimationHost::GetElementAnimationsForElementId(ElementId element_id) const { return iter == element_to_animations_map_.end() ? nullptr : iter->second; } +gfx::PointF AnimationHost::GetScrollOffsetForAnimation( + ElementId element_id) const { + DCHECK(property_trees_); + return property_trees_->scroll_tree.current_scroll_offset(element_id); +} + void AnimationHost::SetScrollAnimationDurationForTesting( base::TimeDelta duration) { ScrollOffsetAnimationCurve::SetAnimationDurationForTesting(duration); @@ -691,8 +705,8 @@ bool AnimationHost::HasTickingKeyframeModelForTesting( void AnimationHost::ImplOnlyAutoScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, float autoscroll_velocity, base::TimeDelta animation_start_offset) { DCHECK(scroll_offset_animations_impl_); @@ -703,8 +717,8 @@ void AnimationHost::ImplOnlyAutoScrollAnimationCreate( void AnimationHost::ImplOnlyScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, base::TimeDelta delayed_by, base::TimeDelta animation_start_offset) { DCHECK(scroll_offset_animations_impl_); @@ -715,7 +729,7 @@ void AnimationHost::ImplOnlyScrollAnimationCreate( bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget( const gfx::Vector2dF& scroll_delta, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& max_scroll_offset, base::TimeTicks frame_monotonic_time, base::TimeDelta delayed_by) { DCHECK(scroll_offset_animations_impl_); @@ -821,9 +835,16 @@ size_t AnimationHost::MainThreadAnimationsCount() const { return main_thread_animations_count_; } -bool AnimationHost::HasCustomPropertyAnimations() const { +bool AnimationHost::HasInvalidationAnimation() const { + for (const auto& it : ticking_animations_) + if (it->RequiresInvalidation()) + return true; + return false; +} + +bool AnimationHost::HasNativePropertyAnimation() const { for (const auto& it : ticking_animations_) - if (it->AffectsCustomProperty()) + if (it->AffectsNativeProperty()) return true; return false; } diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h index ea2c6275434..027d822e0d4 100644 --- a/chromium/cc/animation/animation_host.h +++ b/chromium/cc/animation/animation_host.h @@ -9,6 +9,7 @@ #include <unordered_map> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" @@ -17,6 +18,7 @@ #include "cc/trees/mutator_host.h" #include "cc/trees/mutator_host_client.h" #include "ui/gfx/geometry/box_f.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -68,6 +70,8 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, scoped_refptr<ElementAnimations> GetElementAnimationsForElementId( ElementId element_id) const; + gfx::PointF GetScrollOffsetForAnimation(ElementId element_id) const; + // Parent LayerTreeHost or LayerTreeHostImpl. MutatorHostClient* mutator_host_client() { return mutator_host_client_; } const MutatorHostClient* mutator_host_client() const { @@ -98,7 +102,8 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator) override; - void PushPropertiesTo(MutatorHost* host_impl) override; + void PushPropertiesTo(MutatorHost* host_impl, + const PropertyTrees& property_trees) override; void SetScrollAnimationDurationForTesting(base::TimeDelta duration) override; bool NeedsTickAnimations() const override; @@ -159,22 +164,21 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, void ImplOnlyAutoScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, float autoscroll_velocity, base::TimeDelta animation_start_offset) override; void ImplOnlyScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, base::TimeDelta delayed_by, base::TimeDelta animation_start_offset) override; - bool ImplOnlyScrollAnimationUpdateTarget( - const gfx::Vector2dF& scroll_delta, - const gfx::Vector2dF& max_scroll_offset, - base::TimeTicks frame_monotonic_time, - base::TimeDelta delayed_by) override; + bool ImplOnlyScrollAnimationUpdateTarget(const gfx::Vector2dF& scroll_delta, + const gfx::PointF& max_scroll_offset, + base::TimeTicks frame_monotonic_time, + base::TimeDelta delayed_by) override; void ScrollAnimationAbort() override; @@ -199,7 +203,12 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, std::unique_ptr<MutatorOutputState> output_state) override; size_t MainThreadAnimationsCount() const override; - bool HasCustomPropertyAnimations() const override; + // Returns true if there is any animation that affects pending tree, such as + // custom property animations via paint worklet. + bool HasInvalidationAnimation() const override; + // Returns true if there is any animation that affects active tree, such as + // transform animation. + bool HasNativePropertyAnimation() const override; bool CurrentFrameHadRAF() const override; bool NextFrameHasPendingRAF() const override; PendingThroughputTrackerInfos TakePendingThroughputTrackerInfos() override; @@ -250,7 +259,10 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, std::unordered_map<int, scoped_refptr<AnimationTimeline>>; IdToTimelineMap id_to_timeline_map_; - MutatorHostClient* mutator_host_client_; + raw_ptr<MutatorHostClient> mutator_host_client_; + + // This is only non-null within the call scope of PushPropertiesTo(). + const PropertyTrees* property_trees_ = nullptr; // Exactly one of scroll_offset_animations_ and scroll_offset_animations_impl_ // will be non-null for a given AnimationHost instance (the former if diff --git a/chromium/cc/animation/animation_host_perftest.cc b/chromium/cc/animation/animation_host_perftest.cc index faf7a36daa6..537a64527f5 100644 --- a/chromium/cc/animation/animation_host_perftest.cc +++ b/chromium/cc/animation/animation_host_perftest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/raw_ptr.h" #include "cc/animation/animation_host.h" #include "base/threading/thread_task_runner_handle.h" @@ -119,12 +120,13 @@ class AnimationHostPerfTest : public testing::Test { } void DoTest(const std::string& test_name) { + PropertyTrees property_trees; timer_.Reset(); do { // Invalidate dirty flags. SetAllTimelinesNeedPushProperties(); SetAllAnimationsNeedPushProperties(); - host()->PushPropertiesTo(host_impl()); + host()->PushPropertiesTo(host_impl(), property_trees); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -139,7 +141,7 @@ class AnimationHostPerfTest : public testing::Test { std::unique_ptr<AnimationHost> animation_host_; std::unique_ptr<FakeLayerTreeHost> layer_tree_host_; scoped_refptr<Layer> root_layer_; - LayerImpl* root_layer_impl_; + raw_ptr<LayerImpl> root_layer_impl_; scoped_refptr<AnimationTimeline> all_animations_timeline_; int first_timeline_id_; diff --git a/chromium/cc/animation/animation_host_unittest.cc b/chromium/cc/animation/animation_host_unittest.cc index e9a9d85f9e6..231773923d8 100644 --- a/chromium/cc/animation/animation_host_unittest.cc +++ b/chromium/cc/animation/animation_host_unittest.cc @@ -43,7 +43,7 @@ class AnimationHostTest : public AnimationTimelinesTest { host_->AddAnimationTimeline(timeline_); timeline_->AttachAnimation(worklet_animation_); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); timeline_impl_ = host_impl_->GetTimelineById(timeline_id_); worklet_animation_impl_ = ToWorkletAnimation(timeline_impl_->GetAnimationById(cc_id)); @@ -77,20 +77,20 @@ TEST_F(AnimationHostTest, SyncTimelinesAddRemove) { EXPECT_FALSE(host_impl->GetTimelineById(timeline_id)); - host->PushPropertiesTo(host_impl.get()); + host->PushPropertiesTo(host_impl.get(), client_.GetPropertyTrees()); scoped_refptr<AnimationTimeline> timeline_impl = host_impl->GetTimelineById(timeline_id); EXPECT_TRUE(timeline_impl); EXPECT_EQ(timeline_impl->id(), timeline_id); - host->PushPropertiesTo(host_impl.get()); + host->PushPropertiesTo(host_impl.get(), client_.GetPropertyTrees()); EXPECT_EQ(timeline_impl, host_impl->GetTimelineById(timeline_id)); host->RemoveAnimationTimeline(timeline.get()); EXPECT_FALSE(timeline->animation_host()); - host->PushPropertiesTo(host_impl.get()); + host->PushPropertiesTo(host_impl.get(), client_.GetPropertyTrees()); EXPECT_FALSE(host_impl->GetTimelineById(timeline_id)); EXPECT_FALSE(timeline_impl->animation_host()); @@ -114,7 +114,7 @@ TEST_F(AnimationHostTest, ImplOnlyTimeline) { host->AddAnimationTimeline(timeline.get()); host_impl->AddAnimationTimeline(timeline_impl.get()); - host->PushPropertiesTo(host_impl.get()); + host->PushPropertiesTo(host_impl.get(), client_.GetPropertyTrees()); EXPECT_TRUE(host->GetTimelineById(timeline_id1)); EXPECT_TRUE(host_impl->GetTimelineById(timeline_id2)); @@ -124,14 +124,14 @@ TEST_F(AnimationHostTest, ImplOnlyScrollAnimationUpdateTargetIfDetached) { client_.RegisterElementId(element_id_, ElementListType::ACTIVE); client_impl_.RegisterElementId(element_id_, ElementListType::PENDING); - gfx::Vector2dF target_offset(0., 2.); - gfx::Vector2dF current_offset(0., 1.); + gfx::PointF target_offset(0., 2.); + gfx::PointF current_offset(0., 1.); host_impl_->ImplOnlyScrollAnimationCreate(element_id_, target_offset, current_offset, base::TimeDelta(), base::TimeDelta()); gfx::Vector2dF scroll_delta(0, 0.5); - gfx::Vector2dF max_scroll_offset(0., 3.); + gfx::PointF max_scroll_offset(0., 3.); base::TimeTicks time; @@ -172,7 +172,7 @@ TEST_F(AnimationHostTest, FastLayerTreeMutatorUpdateTakesEffectInSameFrame) { [this, local_time]() { this->SetOutputState(local_time); })); // Push the opacity animation to the impl thread. - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); host_impl_->ActivateAnimations(nullptr); // Ticking host should cause layer tree mutator to update output state which @@ -206,7 +206,7 @@ TEST_F(AnimationHostTest, LayerTreeMutatorsIsMutatedWithCorrectInputState) { AddOpacityTransitionToAnimation(worklet_animation_.get(), duration, start_opacity, end_opacity, true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); host_impl_->ActivateAnimations(nullptr); EXPECT_CALL(*mock_mutator, MutateRef(_)); @@ -231,7 +231,7 @@ TEST_F(AnimationHostTest, LayerTreeMutatorsIsMutatedOnlyWhenInputChanges) { AddOpacityTransitionToAnimation(worklet_animation_.get(), duration, start_opacity, end_opacity, true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); host_impl_->ActivateAnimations(nullptr); EXPECT_CALL(*mock_mutator, MutateRef(_)).Times(1); @@ -291,7 +291,7 @@ void CreateScrollingNodeForElement(ElementId element_id, void SetScrollOffset(PropertyTrees* property_trees, ElementId element_id, - gfx::Vector2dF offset) { + gfx::PointF offset) { // Update both scroll and transform trees property_trees->scroll_tree.SetScrollOffset(element_id, offset); TransformNode* transform_node = @@ -317,14 +317,14 @@ TEST_F(AnimationHostTest, LayerTreeMutatorUpdateReflectsScrollAnimations) { CreateScrollingNodeForElement(element_id, &property_trees); // Set an initial scroll value. - SetScrollOffset(&property_trees, element_id, gfx::Vector2dF(10, 10)); + SetScrollOffset(&property_trees, element_id, gfx::PointF(10, 10)); scoped_refptr<MockAnimation> mock_scroll_animation( new MockAnimation(animation_id1)); EXPECT_CALL(*mock_scroll_animation, Tick(_)) .WillOnce(InvokeWithoutArgs([&]() { // Scroll to 20% of the max value. - SetScrollOffset(&property_trees, element_id, gfx::Vector2dF(20, 20)); + SetScrollOffset(&property_trees, element_id, gfx::PointF(20, 20)); })); // Ensure scroll animation is ticking. @@ -398,7 +398,7 @@ TEST_F(AnimationHostTest, TickScrollLinkedAnimation) { KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY); auto& scroll_tree = property_trees.scroll_tree; - SetScrollOffset(&property_trees, element_id_, gfx::Vector2dF(0, 20)); + SetScrollOffset(&property_trees, element_id_, gfx::PointF(0, 20)); EXPECT_TRUE(host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree, false)); @@ -425,7 +425,7 @@ TEST_F(AnimationHostTest, PushPropertiesToImpl) { EXPECT_FALSE(host_impl->HasCanvasInvalidation()); EXPECT_FALSE(host_impl->HasJSAnimation()); - host->PushPropertiesTo(host_impl.get()); + host->PushPropertiesTo(host_impl.get(), client_.GetPropertyTrees()); EXPECT_TRUE(host_impl->HasCanvasInvalidation()); EXPECT_TRUE(host_impl->HasJSAnimation()); } @@ -447,7 +447,7 @@ TEST_F(AnimationHostTest, ScrollTimelineOffsetUpdatedByScrollAnimation) { EXPECT_CALL(*mock_scroll_animation, Tick(_)) .WillOnce(InvokeWithoutArgs([&]() { // Scroll to 20% of the max value. - SetScrollOffset(&property_trees, element_id_, gfx::Vector2dF(0, 20)); + SetScrollOffset(&property_trees, element_id_, gfx::PointF(0, 20)); })); // Ensure scroll animation is ticking. diff --git a/chromium/cc/animation/animation_timeline.h b/chromium/cc/animation/animation_timeline.h index 3f23c39416c..c38edc03819 100644 --- a/chromium/cc/animation/animation_timeline.h +++ b/chromium/cc/animation/animation_timeline.h @@ -9,6 +9,7 @@ #include <unordered_map> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/animation/animation_export.h" @@ -87,7 +88,7 @@ class CC_ANIMATION_EXPORT AnimationTimeline void EraseAnimation(scoped_refptr<Animation> animation); int id_; - AnimationHost* animation_host_; + raw_ptr<AnimationHost> animation_host_; bool needs_push_properties_; // Impl-only AnimationTimeline has no main thread instance and lives on diff --git a/chromium/cc/animation/animation_unittest.cc b/chromium/cc/animation/animation_unittest.cc index 4f7d5dcb618..9f62ffc7d00 100644 --- a/chromium/cc/animation/animation_unittest.cc +++ b/chromium/cc/animation/animation_unittest.cc @@ -15,6 +15,7 @@ #include "cc/animation/keyframe_effect.h" #include "cc/test/animation_test_common.h" #include "cc/test/animation_timelines_test_common.h" +#include "cc/trees/property_tree.h" namespace cc { namespace { @@ -38,7 +39,7 @@ TEST_F(AnimationTest, AttachDetachLayerIfTimelineAttached) { EXPECT_TRUE(timeline_->needs_push_properties()); EXPECT_FALSE(animation_->keyframe_effect()->needs_push_properties()); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); EXPECT_FALSE(GetImplKeyframeEffectForLayerId(element_id_)); @@ -59,7 +60,7 @@ TEST_F(AnimationTest, AttachDetachLayerIfTimelineAttached) { EXPECT_EQ(animation_->keyframe_effect()->element_id(), element_id_); CheckKeyframeEffectTimelineNeedsPushProperties(true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); EXPECT_EQ(animation_impl_->keyframe_effect(), GetImplKeyframeEffectForLayerId(element_id_)); @@ -73,7 +74,7 @@ TEST_F(AnimationTest, AttachDetachLayerIfTimelineAttached) { EXPECT_FALSE(animation_->keyframe_effect()->element_id()); CheckKeyframeEffectTimelineNeedsPushProperties(true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); EXPECT_FALSE(GetImplKeyframeEffectForLayerId(element_id_)); EXPECT_FALSE(animation_impl_->element_animations()); @@ -86,7 +87,7 @@ TEST_F(AnimationTest, AttachDetachLayerIfTimelineAttached) { EXPECT_FALSE(animation_->keyframe_effect()->element_id()); EXPECT_TRUE(timeline_->needs_push_properties()); EXPECT_FALSE(animation_->keyframe_effect()->needs_push_properties()); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); CheckKeyframeEffectTimelineNeedsPushProperties(false); } @@ -121,6 +122,95 @@ TEST_F(AnimationTest, AttachDetachTimelineIfLayerAttached) { EXPECT_TRUE(animation_->keyframe_effect()->needs_push_properties()); } +TEST_F(AnimationTest, HaveInvalidationAndNativePropertyAnimations) { + client_.RegisterElementId(element_id_, ElementListType::ACTIVE); + client_impl_.RegisterElementId(element_id_, ElementListType::PENDING); + client_impl_.RegisterElementId(element_id_, ElementListType::ACTIVE); + + host_->AddAnimationTimeline(timeline_); + + timeline_->AttachAnimation(animation_); + animation_->AttachElement(element_id_); + CheckKeyframeEffectTimelineNeedsPushProperties(true); + + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); + CheckKeyframeEffectTimelineNeedsPushProperties(false); + + const float start_value = .7f; + const float end_value = .3f; + + const float start_opacity = .7f; + const float end_opacity = .3f; + const double duration = 1.; + + AddAnimatedCustomPropertyToAnimation(animation_.get(), duration, start_value, + end_value); + AddOpacityTransitionToAnimation(animation_.get(), duration, start_opacity, + end_opacity, false); + CheckKeyframeEffectTimelineNeedsPushProperties(true); + + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); + CheckKeyframeEffectTimelineNeedsPushProperties(false); + EXPECT_TRUE(host_->HasInvalidationAnimation()); + EXPECT_TRUE(host_->HasNativePropertyAnimation()); +} + +TEST_F(AnimationTest, HasInvalidationAnimation) { + client_.RegisterElementId(element_id_, ElementListType::ACTIVE); + client_impl_.RegisterElementId(element_id_, ElementListType::PENDING); + client_impl_.RegisterElementId(element_id_, ElementListType::ACTIVE); + + host_->AddAnimationTimeline(timeline_); + + timeline_->AttachAnimation(animation_); + animation_->AttachElement(element_id_); + CheckKeyframeEffectTimelineNeedsPushProperties(true); + + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); + CheckKeyframeEffectTimelineNeedsPushProperties(false); + + const float start_value = .7f; + const float end_value = .3f; + const double duration = 1.; + + AddAnimatedCustomPropertyToAnimation(animation_.get(), duration, start_value, + end_value); + CheckKeyframeEffectTimelineNeedsPushProperties(true); + + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); + CheckKeyframeEffectTimelineNeedsPushProperties(false); + EXPECT_TRUE(host_->HasInvalidationAnimation()); + EXPECT_FALSE(host_->HasNativePropertyAnimation()); +} + +TEST_F(AnimationTest, HasNativePropertyAnimation) { + client_.RegisterElementId(element_id_, ElementListType::ACTIVE); + client_impl_.RegisterElementId(element_id_, ElementListType::PENDING); + client_impl_.RegisterElementId(element_id_, ElementListType::ACTIVE); + + host_->AddAnimationTimeline(timeline_); + + timeline_->AttachAnimation(animation_); + animation_->AttachElement(element_id_); + CheckKeyframeEffectTimelineNeedsPushProperties(true); + + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); + CheckKeyframeEffectTimelineNeedsPushProperties(false); + + const float start_opacity = .7f; + const float end_opacity = .3f; + const double duration = 1.; + + AddOpacityTransitionToAnimation(animation_.get(), duration, start_opacity, + end_opacity, false); + CheckKeyframeEffectTimelineNeedsPushProperties(true); + + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); + CheckKeyframeEffectTimelineNeedsPushProperties(false); + EXPECT_FALSE(host_->HasInvalidationAnimation()); + EXPECT_TRUE(host_->HasNativePropertyAnimation()); +} + TEST_F(AnimationTest, PropertiesMutate) { client_.RegisterElementId(element_id_, ElementListType::ACTIVE); client_impl_.RegisterElementId(element_id_, ElementListType::PENDING); @@ -132,7 +222,7 @@ TEST_F(AnimationTest, PropertiesMutate) { animation_->AttachElement(element_id_); CheckKeyframeEffectTimelineNeedsPushProperties(true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); CheckKeyframeEffectTimelineNeedsPushProperties(false); const float start_opacity = .7f; @@ -160,7 +250,7 @@ TEST_F(AnimationTest, PropertiesMutate) { end_invert); CheckKeyframeEffectTimelineNeedsPushProperties(true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); CheckKeyframeEffectTimelineNeedsPushProperties(false); EXPECT_FALSE(client_.IsPropertyMutated(element_id_, ElementListType::ACTIVE, @@ -261,7 +351,7 @@ TEST_F(AnimationTest, AttachTwoAnimationsToOneLayer) { AddAnimatedTransformToAnimation(animation2.get(), duration, transform_x, transform_y); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); host_impl_->ActivateAnimations(nullptr); EXPECT_FALSE(delegate1.started()); @@ -343,7 +433,7 @@ TEST_F(AnimationTest, AddRemoveAnimationToNonAttachedAnimation) { ->HasAnyAnimationTargetingProperty(TargetProperty::OPACITY)); EXPECT_TRUE(animation_->keyframe_effect()->needs_push_properties()); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); EXPECT_FALSE(client_.IsPropertyMutated(element_id_, ElementListType::ACTIVE, TargetProperty::OPACITY)); @@ -408,7 +498,7 @@ TEST_F(AnimationTest, SwitchToLayer) { timeline_->AttachAnimation(animation_); animation_->AttachElement(element_id_); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); timeline_impl_ = host_impl_->GetTimelineById(timeline_id_); EXPECT_TRUE(timeline_impl_); @@ -430,7 +520,7 @@ TEST_F(AnimationTest, SwitchToLayer) { EXPECT_EQ(animation_impl_->keyframe_effect()->element_id(), element_id_); CheckKeyframeEffectTimelineNeedsPushProperties(false); - const ElementId new_element_id(NextTestLayerId()); + const ElementId new_element_id(element_id_.GetStableId() + 1); animation_->DetachElement(); animation_->AttachElement(new_element_id); @@ -440,7 +530,7 @@ TEST_F(AnimationTest, SwitchToLayer) { EXPECT_EQ(animation_->keyframe_effect()->element_id(), new_element_id); CheckKeyframeEffectTimelineNeedsPushProperties(true); - host_->PushPropertiesTo(host_impl_); + host_->PushPropertiesTo(host_impl_, client_.GetPropertyTrees()); EXPECT_EQ(animation_impl_->keyframe_effect(), GetImplKeyframeEffectForLayerId(new_element_id)); diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc index 98b8204dfd1..00602a4f8b9 100644 --- a/chromium/cc/animation/element_animations.cc +++ b/chromium/cc/animation/element_animations.cc @@ -288,7 +288,7 @@ void ElementAnimations::OnTransformAnimated( } void ElementAnimations::OnScrollOffsetAnimated( - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, int target_property_id, gfx::KeyframeModel* keyframe_model) { if (KeyframeModelAffectsActiveElements(keyframe_model)) @@ -533,7 +533,7 @@ void ElementAnimations::OnTransformAnimated( void ElementAnimations::OnScrollOffsetAnimated( ElementListType list_type, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, gfx::KeyframeModel* keyframe_model) { ElementId target_element_id = CalculateTargetElementId(this, keyframe_model); DCHECK(target_element_id); @@ -543,14 +543,10 @@ void ElementAnimations::OnScrollOffsetAnimated( target_element_id, list_type, scroll_offset); } -gfx::Vector2dF ElementAnimations::ScrollOffsetForAnimation() const { - if (animation_host_) { - DCHECK(animation_host_->mutator_host_client()); - return animation_host_->mutator_host_client()->GetScrollOffsetForAnimation( - element_id()); - } - - return gfx::Vector2dF(); +gfx::PointF ElementAnimations::ScrollOffsetForAnimation() const { + if (animation_host_) + return animation_host_->GetScrollOffsetForAnimation(element_id()); + return gfx::PointF(); } PropertyToElementIdMap ElementAnimations::GetPropertyToElementIdMap() const { diff --git a/chromium/cc/animation/element_animations.h b/chromium/cc/animation/element_animations.h index 50728fe23fd..d08d1bf6fed 100644 --- a/chromium/cc/animation/element_animations.h +++ b/chromium/cc/animation/element_animations.h @@ -5,6 +5,7 @@ #ifndef CC_ANIMATION_ELEMENT_ANIMATIONS_H_ #define CC_ANIMATION_ELEMENT_ANIMATIONS_H_ +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "cc/animation/animation_export.h" @@ -16,8 +17,8 @@ #include "cc/trees/target_property.h" #include "ui/gfx/animation/keyframe/animation_curve.h" #include "ui/gfx/animation/keyframe/target_property.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/transform.h" -#include "ui/gfx/geometry/vector2d_f.h" namespace gfx { class TransformOperations; @@ -151,11 +152,11 @@ class CC_ANIMATION_EXPORT ElementAnimations void OnTransformAnimated(const gfx::TransformOperations& operations, int target_property_id, gfx::KeyframeModel* keyframe_model) override; - void OnScrollOffsetAnimated(const gfx::Vector2dF& scroll_offset, + void OnScrollOffsetAnimated(const gfx::PointF& scroll_offset, int target_property_id, gfx::KeyframeModel* keyframe_model) override; - gfx::Vector2dF ScrollOffsetForAnimation() const; + gfx::PointF ScrollOffsetForAnimation() const; // Returns a map of target property to the ElementId for that property, for // KeyframeEffects associated with this ElementAnimations. @@ -202,7 +203,7 @@ class CC_ANIMATION_EXPORT ElementAnimations const gfx::Transform& transform, gfx::KeyframeModel* keyframe_model); void OnScrollOffsetAnimated(ElementListType list_type, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, gfx::KeyframeModel* keyframe_model); static gfx::TargetProperties GetPropertiesMaskForAnimationState(); @@ -216,7 +217,7 @@ class CC_ANIMATION_EXPORT ElementAnimations gfx::KeyframeModel* keyframe_model) const; base::ObserverList<KeyframeEffect>::Unchecked keyframe_effects_list_; - AnimationHost* animation_host_; + raw_ptr<AnimationHost> animation_host_; ElementId element_id_; bool has_element_in_active_list_; diff --git a/chromium/cc/animation/element_animations_unittest.cc b/chromium/cc/animation/element_animations_unittest.cc index 2ed0501b03d..d68ba6199cf 100644 --- a/chromium/cc/animation/element_animations_unittest.cc +++ b/chromium/cc/animation/element_animations_unittest.cc @@ -22,6 +22,7 @@ #include "cc/test/animation_timelines_test_common.h" #include "ui/gfx/animation/keyframe/keyframed_animation_curve.h" #include "ui/gfx/geometry/box_f.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform_operations.h" namespace cc { @@ -257,11 +258,11 @@ TEST_F(ElementAnimationsTest, EXPECT_FALSE( animation_impl_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET)); - gfx::Vector2dF initial_value(100.f, 300.f); - gfx::Vector2dF provider_initial_value(150.f, 300.f); - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF initial_value(100.f, 300.f); + gfx::PointF provider_initial_value(150.f, 300.f); + gfx::PointF target_value(300.f, 200.f); - client_impl_.SetScrollOffsetForAnimation(provider_initial_value); + client_.SetScrollOffsetForAnimation(provider_initial_value, element_id_); // Animation with initial value set. std::unique_ptr<ScrollOffsetAnimationCurve> curve_fixed( @@ -278,7 +279,7 @@ TEST_F(ElementAnimationsTest, animation_impl_->keyframe_effect() ->GetKeyframeModelById(animation1_id) ->curve()); - EXPECT_VECTOR2DF_EQ(initial_value, scroll_curve->GetValue(base::TimeDelta())); + EXPECT_POINTF_EQ(initial_value, scroll_curve->GetValue(base::TimeDelta())); animation_->RemoveKeyframeModel(animation1_id); // Animation without initial value set. @@ -295,8 +296,8 @@ TEST_F(ElementAnimationsTest, animation_impl_->keyframe_effect() ->GetKeyframeModelById(animation2_id) ->curve()); - EXPECT_VECTOR2DF_EQ(provider_initial_value, - scroll_curve->GetValue(base::TimeDelta())); + EXPECT_POINTF_EQ(provider_initial_value, + scroll_curve->GetValue(base::TimeDelta())); animation_->RemoveKeyframeModel(animation2_id); } @@ -888,8 +889,8 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransition) { auto events = CreateEventsForTesting(); - gfx::Vector2dF initial_value(100.f, 300.f); - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF initial_value(100.f, 300.f); + gfx::PointF target_value(300.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -900,7 +901,7 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransition) { keyframe_model->set_needs_synchronized_start_time(true); animation_->AddKeyframeModel(std::move(keyframe_model)); - client_impl_.SetScrollOffsetForAnimation(initial_value); + client_.SetScrollOffsetForAnimation(initial_value, element_id_); PushProperties(); animation_impl_->ActivateKeyframeModels(); EXPECT_TRUE(animation_impl_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET)); @@ -929,26 +930,26 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransition) { animation_->Tick(kInitialTickTime + duration / 2); animation_->UpdateState(true, nullptr); EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel()); - EXPECT_VECTOR2DF_EQ( - gfx::Vector2dF(200.f, 250.f), + EXPECT_POINTF_EQ( + gfx::PointF(200.f, 250.f), client_.GetScrollOffset(element_id_, ElementListType::ACTIVE)); animation_impl_->Tick(kInitialTickTime + duration / 2); animation_impl_->UpdateState(true, events.get()); - EXPECT_VECTOR2DF_EQ( - gfx::Vector2dF(200.f, 250.f), + EXPECT_POINTF_EQ( + gfx::PointF(200.f, 250.f), client_impl_.GetScrollOffset(element_id_, ElementListType::ACTIVE)); animation_impl_->Tick(kInitialTickTime + duration); animation_impl_->UpdateState(true, events.get()); - EXPECT_VECTOR2DF_EQ(target_value, client_impl_.GetScrollOffset( - element_id_, ElementListType::ACTIVE)); + EXPECT_POINTF_EQ(target_value, client_impl_.GetScrollOffset( + element_id_, ElementListType::ACTIVE)); EXPECT_FALSE(animation_impl_->keyframe_effect()->HasTickingKeyframeModel()); animation_->Tick(kInitialTickTime + duration); animation_->UpdateState(true, nullptr); - EXPECT_VECTOR2DF_EQ(target_value, client_.GetScrollOffset( - element_id_, ElementListType::ACTIVE)); + EXPECT_POINTF_EQ(target_value, client_.GetScrollOffset( + element_id_, ElementListType::ACTIVE)); EXPECT_FALSE(animation_->keyframe_effect()->HasTickingKeyframeModel()); } @@ -959,8 +960,8 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransitionOnImplOnly) { auto events = CreateEventsForTesting(); - gfx::Vector2dF initial_value(100.f, 300.f); - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF initial_value(100.f, 300.f); + gfx::PointF target_value(300.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -984,14 +985,14 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransitionOnImplOnly) { animation_impl_->Tick(kInitialTickTime + duration / 2); animation_impl_->UpdateState(true, events.get()); - EXPECT_VECTOR2DF_EQ( - gfx::Vector2dF(200.f, 250.f), + EXPECT_POINTF_EQ( + gfx::PointF(200.f, 250.f), client_impl_.GetScrollOffset(element_id_, ElementListType::ACTIVE)); animation_impl_->Tick(kInitialTickTime + duration); animation_impl_->UpdateState(true, events.get()); - EXPECT_VECTOR2DF_EQ(target_value, client_impl_.GetScrollOffset( - element_id_, ElementListType::ACTIVE)); + EXPECT_POINTF_EQ(target_value, client_impl_.GetScrollOffset( + element_id_, ElementListType::ACTIVE)); EXPECT_FALSE(animation_impl_->keyframe_effect()->HasTickingKeyframeModel()); } @@ -1008,8 +1009,8 @@ TEST_F(ElementAnimationsTest, UpdateStateWithoutAnimate) { // Add first scroll offset animation. AddScrollOffsetAnimationToAnimation(animation_impl_.get(), - gfx::Vector2dF(100.f, 300.f), - gfx::Vector2dF(100.f, 200.f)); + gfx::PointF(100.f, 300.f), + gfx::PointF(100.f, 200.f)); // Calling UpdateState after Animate should promote the animation to running // state. @@ -1026,8 +1027,8 @@ TEST_F(ElementAnimationsTest, UpdateStateWithoutAnimate) { // Add second scroll offset animation. AddScrollOffsetAnimationToAnimation(animation_impl_.get(), - gfx::Vector2dF(100.f, 200.f), - gfx::Vector2dF(100.f, 100.f)); + gfx::PointF(100.f, 200.f), + gfx::PointF(100.f, 100.f)); // Calling UpdateState without Animate should NOT promote the animation to // running state. @@ -1042,8 +1043,8 @@ TEST_F(ElementAnimationsTest, UpdateStateWithoutAnimate) { EXPECT_EQ(KeyframeModel::RUNNING, animation_impl_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET) ->run_state()); - EXPECT_VECTOR2DF_EQ( - gfx::Vector2dF(100.f, 200.f), + EXPECT_POINTF_EQ( + gfx::PointF(100.f, 200.f), client_impl_.GetScrollOffset(element_id_, ElementListType::ACTIVE)); } @@ -1061,8 +1062,8 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransitionNoImplProvider) { auto events = CreateEventsForTesting(); - gfx::Vector2dF initial_value(500.f, 100.f); - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF initial_value(500.f, 100.f); + gfx::PointF target_value(300.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -1073,7 +1074,7 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransitionNoImplProvider) { keyframe_model->set_needs_synchronized_start_time(true); animation_->AddKeyframeModel(std::move(keyframe_model)); - client_.SetScrollOffsetForAnimation(initial_value); + client_.SetScrollOffsetForAnimation(initial_value, element_id_); PushProperties(); animation_impl_->ActivateKeyframeModels(); EXPECT_TRUE(animation_impl_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET)); @@ -1092,8 +1093,8 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransitionNoImplProvider) { EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel()); EXPECT_EQ(initial_value, client_.GetScrollOffset(element_id_, ElementListType::ACTIVE)); - EXPECT_EQ(gfx::Vector2dF(), client_impl_.GetScrollOffset( - element_id_, ElementListType::PENDING)); + EXPECT_EQ(gfx::PointF(), client_impl_.GetScrollOffset( + element_id_, ElementListType::PENDING)); animation_impl_->Tick(kInitialTickTime); @@ -1110,26 +1111,26 @@ TEST_F(ElementAnimationsTest, ScrollOffsetTransitionNoImplProvider) { animation_->Tick(kInitialTickTime + duration / 2); animation_->UpdateState(true, nullptr); EXPECT_TRUE(animation_->keyframe_effect()->HasTickingKeyframeModel()); - EXPECT_VECTOR2DF_EQ( - gfx::Vector2dF(400.f, 150.f), + EXPECT_POINTF_EQ( + gfx::PointF(400.f, 150.f), client_.GetScrollOffset(element_id_, ElementListType::ACTIVE)); animation_impl_->Tick(kInitialTickTime + duration / 2); animation_impl_->UpdateState(true, events.get()); - EXPECT_VECTOR2DF_EQ( - gfx::Vector2dF(400.f, 150.f), + EXPECT_POINTF_EQ( + gfx::PointF(400.f, 150.f), client_impl_.GetScrollOffset(element_id_, ElementListType::PENDING)); animation_impl_->Tick(kInitialTickTime + duration); animation_impl_->UpdateState(true, events.get()); - EXPECT_VECTOR2DF_EQ(target_value, client_impl_.GetScrollOffset( - element_id_, ElementListType::PENDING)); + EXPECT_POINTF_EQ(target_value, client_impl_.GetScrollOffset( + element_id_, ElementListType::PENDING)); EXPECT_FALSE(animation_impl_->keyframe_effect()->HasTickingKeyframeModel()); animation_->Tick(kInitialTickTime + duration); animation_->UpdateState(true, nullptr); - EXPECT_VECTOR2DF_EQ(target_value, client_.GetScrollOffset( - element_id_, ElementListType::ACTIVE)); + EXPECT_POINTF_EQ(target_value, client_.GetScrollOffset( + element_id_, ElementListType::ACTIVE)); EXPECT_FALSE(animation_->keyframe_effect()->HasTickingKeyframeModel()); } @@ -1141,7 +1142,7 @@ TEST_F(ElementAnimationsTest, ScrollOffsetRemovalClearsScrollDelta) { auto events = CreateEventsForTesting(); // First test the 1-argument version of RemoveKeyframeModel. - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF target_value(300.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -1264,8 +1265,8 @@ TEST_F(ElementAnimationsTest, TestAnimationDelegate delegate; animation_impl_->set_animation_delegate(&delegate); - gfx::Vector2dF initial_value(100.f, 300.f); - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF initial_value(100.f, 300.f); + gfx::PointF target_value(300.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -2070,8 +2071,8 @@ TEST_F(ElementAnimationsTest, ImplThreadTakeoverAnimationGetsDeleted) { // Add impl-only scroll offset animation. const int keyframe_model_id = 1; - gfx::Vector2dF initial_value(100.f, 300.f); - gfx::Vector2dF target_value(300.f, 200.f); + gfx::PointF initial_value(100.f, 300.f); + gfx::PointF target_value(300.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); diff --git a/chromium/cc/animation/filter_animation_curve_unittest.cc b/chromium/cc/animation/filter_animation_curve_unittest.cc index 2fc9b4b4343..0daa51397bb 100644 --- a/chromium/cc/animation/filter_animation_curve_unittest.cc +++ b/chromium/cc/animation/filter_animation_curve_unittest.cc @@ -6,13 +6,11 @@ #include <memory> -#include "cc/test/geometry_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/animation/tween.h" #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/transform_operations.h" -#include "ui/gfx/test/gfx_util.h" namespace cc { namespace { diff --git a/chromium/cc/animation/keyframe_effect.cc b/chromium/cc/animation/keyframe_effect.cc index 50f8cd5990a..def46c0848a 100644 --- a/chromium/cc/animation/keyframe_effect.cc +++ b/chromium/cc/animation/keyframe_effect.cc @@ -407,10 +407,25 @@ bool KeyframeEffect::HasTickingKeyframeModel() const { return false; } -bool KeyframeEffect::AffectsCustomProperty() const { - for (const auto& it : keyframe_models()) - if (it->TargetProperty() == TargetProperty::CSS_CUSTOM_PROPERTY) +bool KeyframeEffect::RequiresInvalidation() const { + for (const auto& it : keyframe_models()) { + if (it->TargetProperty() == TargetProperty::NATIVE_PROPERTY || + it->TargetProperty() == TargetProperty::CSS_CUSTOM_PROPERTY) { return true; + } + } + return false; +} + +bool KeyframeEffect::AffectsNativeProperty() const { + for (const auto& it : keyframe_models()) { + // TODO(crbug.com/1257778): include the SCROLL_OFFSET here so that we won't + // create a compositor animation frame sequence tracker when there is a + // composited scroll. + if (it->TargetProperty() != TargetProperty::CSS_CUSTOM_PROPERTY && + it->TargetProperty() != TargetProperty::NATIVE_PROPERTY) + return true; + } return false; } @@ -585,7 +600,7 @@ void KeyframeEffect::PushNewKeyframeModelsToImplThread( !ScrollOffsetAnimationCurve::ToScrollOffsetAnimationCurve( keyframe_model->curve()) ->HasSetInitialValue()) { - gfx::Vector2dF current_scroll_offset; + gfx::PointF current_scroll_offset; if (keyframe_effect_impl->HasElementInActiveList()) { current_scroll_offset = keyframe_effect_impl->ScrollOffsetForAnimation(); @@ -1013,7 +1028,7 @@ bool KeyframeEffect::HasElementInActiveList() const { return element_animations_->has_element_in_active_list(); } -gfx::Vector2dF KeyframeEffect::ScrollOffsetForAnimation() const { +gfx::PointF KeyframeEffect::ScrollOffsetForAnimation() const { DCHECK(has_bound_element_animations()); return element_animations_->ScrollOffsetForAnimation(); } diff --git a/chromium/cc/animation/keyframe_effect.h b/chromium/cc/animation/keyframe_effect.h index d76b282912a..ab77c96da5d 100644 --- a/chromium/cc/animation/keyframe_effect.h +++ b/chromium/cc/animation/keyframe_effect.h @@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation_events.h" @@ -20,7 +21,7 @@ #include "cc/trees/target_property.h" #include "ui/gfx/animation/keyframe/keyframe_effect.h" #include "ui/gfx/geometry/box_f.h" -#include "ui/gfx/geometry/vector2d_f.h" +#include "ui/gfx/geometry/point_f.h" namespace cc { @@ -109,7 +110,8 @@ class CC_ANIMATION_EXPORT KeyframeEffect : public gfx::KeyframeEffect { // nor aborted. bool HasTickingKeyframeModel() const; - bool AffectsCustomProperty() const; + bool RequiresInvalidation() const; + bool AffectsNativeProperty() const; bool HasNonDeletedKeyframeModel() const; @@ -168,7 +170,7 @@ class CC_ANIMATION_EXPORT KeyframeEffect : public gfx::KeyframeEffect { void MarkFinishedKeyframeModels(base::TimeTicks monotonic_time); bool HasElementInActiveList() const; - gfx::Vector2dF ScrollOffsetForAnimation() const; + gfx::PointF ScrollOffsetForAnimation() const; void GenerateEvent(AnimationEvents* events, const KeyframeModel& keyframe_model, AnimationEvent::Type type, @@ -178,7 +180,7 @@ class CC_ANIMATION_EXPORT KeyframeEffect : public gfx::KeyframeEffect { const KeyframeModel& keyframe_model, base::TimeTicks monotonic_time); - Animation* animation_; + raw_ptr<Animation> animation_; ElementId element_id_; diff --git a/chromium/cc/animation/scroll_offset_animation_curve.cc b/chromium/cc/animation/scroll_offset_animation_curve.cc index e86e3e635b7..3b3d328dc12 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve.cc +++ b/chromium/cc/animation/scroll_offset_animation_curve.cc @@ -6,6 +6,7 @@ #include <algorithm> #include <cmath> +#include <ostream> #include <utility> #include "base/check_op.h" @@ -81,9 +82,9 @@ std::unique_ptr<TimingFunction> ImpulseCurveWithInitialSlope(double slope) { return CubicBezierTimingFunction::Create(x1, y1, x2, y2); } -bool IsNewTargetInOppositeDirection(const gfx::Vector2dF& current_position, - const gfx::Vector2dF& old_target, - const gfx::Vector2dF& new_target) { +bool IsNewTargetInOppositeDirection(const gfx::PointF& current_position, + const gfx::PointF& old_target, + const gfx::PointF& new_target) { gfx::Vector2dF old_delta = old_target - current_position; gfx::Vector2dF new_delta = new_target - current_position; @@ -132,7 +133,7 @@ absl::optional<double> ScrollOffsetAnimationCurve::animation_duration_for_testing_; ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, AnimationType animation_type, absl::optional<DurationBehavior> duration_behavior) : target_value_(target_value), @@ -157,7 +158,7 @@ ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve( } ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, std::unique_ptr<TimingFunction> timing_function, AnimationType animation_type, absl::optional<DurationBehavior> duration_behavior) @@ -276,7 +277,7 @@ base::TimeDelta ScrollOffsetAnimationCurve::ImpulseSegmentDuration( } void ScrollOffsetAnimationCurve::SetInitialValue( - const gfx::Vector2dF& initial_value, + const gfx::PointF& initial_value, base::TimeDelta delayed_by, float velocity) { initial_value_ = initial_value; @@ -296,7 +297,7 @@ void ScrollOffsetAnimationCurve::ApplyAdjustment( target_value_ = target_value_ + adjustment; } -gfx::Vector2dF ScrollOffsetAnimationCurve::GetValue(base::TimeDelta t) const { +gfx::PointF ScrollOffsetAnimationCurve::GetValue(base::TimeDelta t) const { const base::TimeDelta duration = total_animation_duration_ - last_retarget_; t -= last_retarget_; @@ -306,10 +307,10 @@ gfx::Vector2dF ScrollOffsetAnimationCurve::GetValue(base::TimeDelta t) const { return initial_value_; const double progress = timing_function_->GetValue(t / duration); - return gfx::Vector2dF(gfx::Tween::FloatValueBetween( - progress, initial_value_.x(), target_value_.x()), - gfx::Tween::FloatValueBetween( - progress, initial_value_.y(), target_value_.y())); + return gfx::PointF(gfx::Tween::FloatValueBetween(progress, initial_value_.x(), + target_value_.x()), + gfx::Tween::FloatValueBetween(progress, initial_value_.y(), + target_value_.y())); } base::TimeDelta ScrollOffsetAnimationCurve::Duration() const { @@ -368,9 +369,8 @@ double ScrollOffsetAnimationCurve::CalculateVelocity(base::TimeDelta t) { return slope * (MaximumDimension(delta) / duration.InSecondsF()); } -void ScrollOffsetAnimationCurve::UpdateTarget( - base::TimeDelta t, - const gfx::Vector2dF& new_target) { +void ScrollOffsetAnimationCurve::UpdateTarget(base::TimeDelta t, + const gfx::PointF& new_target) { DCHECK_NE(animation_type_, AnimationType::kLinear) << "UpdateTarget is not supported on linear scroll animations."; @@ -398,7 +398,7 @@ void ScrollOffsetAnimationCurve::UpdateTarget( return; } - gfx::Vector2dF current_position = GetValue(t); + gfx::PointF current_position = GetValue(t); gfx::Vector2dF new_delta = new_target - current_position; // We are already at or very close to the new target. Stop animating. diff --git a/chromium/cc/animation/scroll_offset_animation_curve.h b/chromium/cc/animation/scroll_offset_animation_curve.h index ec3448b57b2..c0ae9697f7e 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve.h +++ b/chromium/cc/animation/scroll_offset_animation_curve.h @@ -8,10 +8,12 @@ #include <memory> #include "base/gtest_prod_util.h" +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/animation/animation_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/animation/keyframe/animation_curve.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_f.h" namespace gfx { @@ -34,7 +36,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve public: ~Target() = default; - virtual void OnScrollOffsetAnimated(const gfx::Vector2dF& value, + virtual void OnScrollOffsetAnimated(const gfx::PointF& value, int target_property_id, gfx::KeyframeModel* keyframe_model) = 0; }; @@ -83,22 +85,22 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve delete; // Sets the initial offset and velocity (in pixels per second). - void SetInitialValue(const gfx::Vector2dF& initial_value, + void SetInitialValue(const gfx::PointF& initial_value, base::TimeDelta delayed_by = base::TimeDelta(), float velocity = 0); bool HasSetInitialValue() const; - gfx::Vector2dF GetValue(base::TimeDelta t) const; - gfx::Vector2dF target_value() const { return target_value_; } + gfx::PointF GetValue(base::TimeDelta t) const; + gfx::PointF target_value() const { return target_value_; } // Updates the current curve to aim at a new target, starting at time t // relative to the start of the animation. The duration is recomputed based // on the animation type the curve was constructed with. The timing function // is modified to preserve velocity at t. - void UpdateTarget(base::TimeDelta t, const gfx::Vector2dF& new_target); + void UpdateTarget(base::TimeDelta t, const gfx::PointF& new_target); // Shifts the entire curve by a delta without affecting its shape or timing. // Used for scroll anchoring adjustments that happen during scroll animations - // (see blink::ScrollAnimator::AdjustAnimationAndSetScrollOffset). + // (see blink::ScrollAnimator::AdjustAnimation). void ApplyAdjustment(const gfx::Vector2dF& adjustment); // AnimationCurve implementation @@ -124,11 +126,11 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve // |duration_behavior| should be provided if (and only if) |animation_type| is // kEaseInOut. ScrollOffsetAnimationCurve( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, AnimationType animation_type, absl::optional<DurationBehavior> duration_behavior = absl::nullopt); ScrollOffsetAnimationCurve( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, std::unique_ptr<gfx::TimingFunction> timing_function, AnimationType animation_type, absl::optional<DurationBehavior> duration_behavior); @@ -146,8 +148,8 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve // Returns the velocity at time t in units of pixels per second. double CalculateVelocity(base::TimeDelta t); - gfx::Vector2dF initial_value_; - gfx::Vector2dF target_value_; + gfx::PointF initial_value_; + gfx::PointF target_value_; base::TimeDelta total_animation_duration_; // Time from animation start to most recent UpdateTarget. @@ -163,7 +165,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve static absl::optional<double> animation_duration_for_testing_; - Target* target_ = nullptr; + raw_ptr<Target> target_ = nullptr; }; } // namespace cc diff --git a/chromium/cc/animation/scroll_offset_animation_curve_factory.cc b/chromium/cc/animation/scroll_offset_animation_curve_factory.cc index 34c8912fa5e..a0bb33f597e 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve_factory.cc +++ b/chromium/cc/animation/scroll_offset_animation_curve_factory.cc @@ -32,7 +32,7 @@ ScrollOffsetAnimationCurve::DurationBehavior GetDurationBehaviorFromScrollType( // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateAnimation( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, ScrollType scroll_type) { if (scroll_type == ScrollType::kAutoScroll) return CreateLinearAnimation(target_value); @@ -47,7 +47,7 @@ ScrollOffsetAnimationCurveFactory::CreateAnimation( // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, ScrollOffsetAnimationCurve::DurationBehavior duration_behavior) { return CreateEaseInOutAnimation(target_value, duration_behavior); } @@ -55,21 +55,21 @@ ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateLinearAnimationForTesting( - const gfx::Vector2dF& target_value) { + const gfx::PointF& target_value) { return CreateLinearAnimation(target_value); } // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateImpulseAnimationForTesting( - const gfx::Vector2dF& target_value) { + const gfx::PointF& target_value) { return CreateImpulseAnimation(target_value); } // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimation( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, ScrollOffsetAnimationCurve::DurationBehavior duration_behavior) { return base::WrapUnique(new ScrollOffsetAnimationCurve( target_value, ScrollOffsetAnimationCurve::AnimationType::kEaseInOut, @@ -79,7 +79,7 @@ ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimation( // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateLinearAnimation( - const gfx::Vector2dF& target_value) { + const gfx::PointF& target_value) { return base::WrapUnique(new ScrollOffsetAnimationCurve( target_value, ScrollOffsetAnimationCurve::AnimationType::kLinear)); } @@ -87,7 +87,7 @@ ScrollOffsetAnimationCurveFactory::CreateLinearAnimation( // static std::unique_ptr<ScrollOffsetAnimationCurve> ScrollOffsetAnimationCurveFactory::CreateImpulseAnimation( - const gfx::Vector2dF& target_value) { + const gfx::PointF& target_value) { return base::WrapUnique(new ScrollOffsetAnimationCurve( target_value, ScrollOffsetAnimationCurve::AnimationType::kImpulse, ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA)); diff --git a/chromium/cc/animation/scroll_offset_animation_curve_factory.h b/chromium/cc/animation/scroll_offset_animation_curve_factory.h index 4278133c324..8814f4b5985 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve_factory.h +++ b/chromium/cc/animation/scroll_offset_animation_curve_factory.h @@ -15,31 +15,31 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurveFactory { enum class ScrollType { kProgrammatic, kKeyboard, kMouseWheel, kAutoScroll }; static std::unique_ptr<ScrollOffsetAnimationCurve> CreateAnimation( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, ScrollType scroll_type); static std::unique_ptr<ScrollOffsetAnimationCurve> CreateEaseInOutAnimationForTesting( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, ScrollOffsetAnimationCurve::DurationBehavior duration_behavior = ScrollOffsetAnimationCurve::DurationBehavior::DELTA_BASED); static std::unique_ptr<ScrollOffsetAnimationCurve> - CreateLinearAnimationForTesting(const gfx::Vector2dF& target_value); + CreateLinearAnimationForTesting(const gfx::PointF& target_value); static std::unique_ptr<ScrollOffsetAnimationCurve> - CreateImpulseAnimationForTesting(const gfx::Vector2dF& target_value); + CreateImpulseAnimationForTesting(const gfx::PointF& target_value); private: static std::unique_ptr<ScrollOffsetAnimationCurve> CreateEaseInOutAnimation( - const gfx::Vector2dF& target_value, + const gfx::PointF& target_value, ScrollOffsetAnimationCurve::DurationBehavior duration_hint); static std::unique_ptr<ScrollOffsetAnimationCurve> CreateLinearAnimation( - const gfx::Vector2dF& target_value); + const gfx::PointF& target_value); static std::unique_ptr<ScrollOffsetAnimationCurve> CreateImpulseAnimation( - const gfx::Vector2dF& target_value); + const gfx::PointF& target_value); }; } // namespace cc diff --git a/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc b/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc index e917ec9f8b1..8101c436d6b 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc +++ b/chromium/cc/animation/scroll_offset_animation_curve_unittest.cc @@ -5,9 +5,9 @@ #include "cc/animation/scroll_offset_animation_curve.h" #include "cc/animation/scroll_offset_animation_curve_factory.h" -#include "cc/test/geometry_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/animation/keyframe/timing_function.h" +#include "ui/gfx/geometry/test/geometry_util.h" using DurationBehavior = cc::ScrollOffsetAnimationCurve::DurationBehavior; @@ -24,7 +24,7 @@ constexpr double halfway_through_default_impulse_curve = 0.874246; } // namespace TEST(ScrollOffsetAnimationCurveTest, DeltaBasedDuration) { - gfx::Vector2dF target_value(100.f, 200.f); + gfx::PointF target_value(100.f, 200.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -33,41 +33,41 @@ TEST(ScrollOffsetAnimationCurveTest, DeltaBasedDuration) { EXPECT_DOUBLE_EQ(0.0, curve->Duration().InSecondsF()); // x decreases, y stays the same. - curve->SetInitialValue(gfx::Vector2dF(136.f, 200.f)); + curve->SetInitialValue(gfx::PointF(136.f, 200.f)); EXPECT_DOUBLE_EQ(0.1, curve->Duration().InSecondsF()); // x increases, y stays the same. - curve->SetInitialValue(gfx::Vector2dF(19.f, 200.f)); + curve->SetInitialValue(gfx::PointF(19.f, 200.f)); EXPECT_DOUBLE_EQ(0.15, curve->Duration().InSecondsF()); // x stays the same, y decreases. - curve->SetInitialValue(gfx::Vector2dF(100.f, 344.f)); + curve->SetInitialValue(gfx::PointF(100.f, 344.f)); EXPECT_DOUBLE_EQ(0.2, curve->Duration().InSecondsF()); // x stays the same, y increases. - curve->SetInitialValue(gfx::Vector2dF(100.f, 191.f)); + curve->SetInitialValue(gfx::PointF(100.f, 191.f)); EXPECT_DOUBLE_EQ(0.05, curve->Duration().InSecondsF()); // x decreases, y decreases. - curve->SetInitialValue(gfx::Vector2dF(32500.f, 500.f)); + curve->SetInitialValue(gfx::PointF(32500.f, 500.f)); EXPECT_DOUBLE_EQ(0.7, curve->Duration().InSecondsF()); // x decreases, y increases. - curve->SetInitialValue(gfx::Vector2dF(150.f, 119.f)); + curve->SetInitialValue(gfx::PointF(150.f, 119.f)); EXPECT_DOUBLE_EQ(0.15, curve->Duration().InSecondsF()); // x increases, y decreases. - curve->SetInitialValue(gfx::Vector2dF(0.f, 14600.f)); + curve->SetInitialValue(gfx::PointF(0.f, 14600.f)); EXPECT_DOUBLE_EQ(0.7, curve->Duration().InSecondsF()); // x increases, y increases. - curve->SetInitialValue(gfx::Vector2dF(95.f, 191.f)); + curve->SetInitialValue(gfx::PointF(95.f, 191.f)); EXPECT_DOUBLE_EQ(0.05, curve->Duration().InSecondsF()); } TEST(ScrollOffsetAnimationCurveTest, GetValue) { - gfx::Vector2dF initial_value(2.f, 40.f); - gfx::Vector2dF target_value(10.f, 20.f); + gfx::PointF initial_value(2.f, 40.f); + gfx::PointF target_value(10.f, 20.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -79,24 +79,24 @@ TEST(ScrollOffsetAnimationCurveTest, GetValue) { EXPECT_EQ(duration, curve->Duration()); - EXPECT_VECTOR2DF_EQ(initial_value, curve->GetValue(base::Seconds(-1.0))); - EXPECT_VECTOR2DF_EQ(initial_value, curve->GetValue(base::TimeDelta())); - EXPECT_VECTOR2DF_NEAR(gfx::Vector2dF(6.f, 30.f), - curve->GetValue(duration * 0.5f), 0.00025); - EXPECT_VECTOR2DF_EQ(target_value, curve->GetValue(duration)); - EXPECT_VECTOR2DF_EQ(target_value, - curve->GetValue(duration + base::Seconds(1.0))); + EXPECT_POINTF_EQ(initial_value, curve->GetValue(base::Seconds(-1.0))); + EXPECT_POINTF_EQ(initial_value, curve->GetValue(base::TimeDelta())); + EXPECT_POINTF_NEAR(gfx::PointF(6.f, 30.f), curve->GetValue(duration * 0.5f), + 0.00025); + EXPECT_POINTF_EQ(target_value, curve->GetValue(duration)); + EXPECT_POINTF_EQ(target_value, + curve->GetValue(duration + base::Seconds(1.0))); // Verify that GetValue takes the timing function into account. - gfx::Vector2dF value = curve->GetValue(duration * 0.25f); + gfx::PointF value = curve->GetValue(duration * 0.25f); EXPECT_NEAR(3.0333f, value.x(), 0.0002f); EXPECT_NEAR(37.4168f, value.y(), 0.0002f); } // Verify that a clone behaves exactly like the original. TEST(ScrollOffsetAnimationCurveTest, Clone) { - gfx::Vector2dF initial_value(2.f, 40.f); - gfx::Vector2dF target_value(10.f, 20.f); + gfx::PointF initial_value(2.f, 40.f); + gfx::PointF target_value(10.f, 20.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value)); @@ -110,24 +110,23 @@ TEST(ScrollOffsetAnimationCurveTest, Clone) { ScrollOffsetAnimationCurve* cloned_curve = ScrollOffsetAnimationCurve::ToScrollOffsetAnimationCurve(clone.get()); - EXPECT_VECTOR2DF_EQ(initial_value, - cloned_curve->GetValue(base::Seconds(-1.0))); - EXPECT_VECTOR2DF_EQ(initial_value, cloned_curve->GetValue(base::TimeDelta())); - EXPECT_VECTOR2DF_NEAR(gfx::Vector2dF(6.f, 30.f), - cloned_curve->GetValue(duration * 0.5f), 0.00025); - EXPECT_VECTOR2DF_EQ(target_value, cloned_curve->GetValue(duration)); - EXPECT_VECTOR2DF_EQ(target_value, - cloned_curve->GetValue(duration + base::Seconds(1.f))); + EXPECT_POINTF_EQ(initial_value, cloned_curve->GetValue(base::Seconds(-1.0))); + EXPECT_POINTF_EQ(initial_value, cloned_curve->GetValue(base::TimeDelta())); + EXPECT_POINTF_NEAR(gfx::PointF(6.f, 30.f), + cloned_curve->GetValue(duration * 0.5f), 0.00025); + EXPECT_POINTF_EQ(target_value, cloned_curve->GetValue(duration)); + EXPECT_POINTF_EQ(target_value, + cloned_curve->GetValue(duration + base::Seconds(1.f))); // Verify that the timing function was cloned correctly. - gfx::Vector2dF value = cloned_curve->GetValue(duration * 0.25f); + gfx::PointF value = cloned_curve->GetValue(duration * 0.25f); EXPECT_NEAR(3.0333f, value.x(), 0.0002f); EXPECT_NEAR(37.4168f, value.y(), 0.0002f); } TEST(ScrollOffsetAnimationCurveTest, EaseInOutUpdateTarget) { - gfx::Vector2dF initial_value(0.f, 0.f); - gfx::Vector2dF target_value(0.f, 3600.f); + gfx::PointF initial_value(0.f, 0.f); + gfx::PointF target_value(0.f, 3600.f); double duration = kConstantDuration / kDurationDivisor; std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( @@ -138,7 +137,7 @@ TEST(ScrollOffsetAnimationCurveTest, EaseInOutUpdateTarget) { 0.0002f); EXPECT_NEAR(3600.0, curve->GetValue(base::Seconds(duration)).y(), 0.0002f); - curve->UpdateTarget(base::Seconds(duration / 2), gfx::Vector2dF(0.0, 9900.0)); + curve->UpdateTarget(base::Seconds(duration / 2), gfx::PointF(0.0, 9900.0)); EXPECT_NEAR(duration * 1.5, curve->Duration().InSecondsF(), 0.0002f); EXPECT_NEAR(1800.0, curve->GetValue(base::Seconds(duration / 2.0)).y(), @@ -147,7 +146,7 @@ TEST(ScrollOffsetAnimationCurveTest, EaseInOutUpdateTarget) { EXPECT_NEAR(9900.0, curve->GetValue(base::Seconds(duration * 1.5)).y(), 0.0002f); - curve->UpdateTarget(base::Seconds(duration), gfx::Vector2dF(0.0, 7200.0)); + curve->UpdateTarget(base::Seconds(duration), gfx::PointF(0.0, 7200.0)); // A closer target at high velocity reduces the duration. EXPECT_NEAR(duration * 1.0794, curve->Duration().InSecondsF(), 0.0002f); @@ -157,8 +156,8 @@ TEST(ScrollOffsetAnimationCurveTest, EaseInOutUpdateTarget) { } TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTarget) { - gfx::Vector2dF initial_value(0.f, 0.f); - gfx::Vector2dF initial_target_value(0.f, 3600.f); + gfx::PointF initial_value(0.f, 0.f); + gfx::PointF initial_target_value(0.f, 3600.f); gfx::Vector2dF initial_delta = initial_target_value - initial_value; std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateImpulseAnimationForTesting( @@ -176,10 +175,10 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTarget) { 0.0002f); base::TimeDelta time_of_update = initial_duration / 2; - gfx::Vector2dF distance_halfway_through_initial_animation = + gfx::PointF distance_halfway_through_initial_animation = curve->GetValue(time_of_update); - gfx::Vector2dF new_target_value(0.f, 9900.f); + gfx::PointF new_target_value(0.f, 9900.f); curve->UpdateTarget(time_of_update, new_target_value); gfx::Vector2dF new_delta = @@ -207,11 +206,12 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTarget) { } TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTargetSwitchDirections) { - gfx::Vector2dF initial_value(0.f, 0.f); - gfx::Vector2dF initial_target_value(0.f, 200.f); - double initial_duration = ScrollOffsetAnimationCurve::ImpulseSegmentDuration( - initial_target_value, base::TimeDelta()) - .InSecondsF(); + gfx::PointF initial_value(0.f, 0.f); + gfx::PointF initial_target_value(0.f, 200.f); + double initial_duration = + ScrollOffsetAnimationCurve::ImpulseSegmentDuration( + initial_target_value.OffsetFromOrigin(), base::TimeDelta()) + .InSecondsF(); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateImpulseAnimationForTesting( @@ -224,9 +224,9 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTargetSwitchDirections) { // Animate back to 0. This should force the new curve's initial velocity to be // 0, so the default curve will be generated. - gfx::Vector2dF updated_initial_value = gfx::Vector2dF( + gfx::PointF updated_initial_value( 0, initial_target_value.y() * halfway_through_default_impulse_curve); - gfx::Vector2dF updated_target(0.f, 0.f); + gfx::PointF updated_target(0.f, 0.f); curve->UpdateTarget(base::Seconds(initial_duration / 2), updated_target); EXPECT_NEAR(initial_target_value.y() * halfway_through_default_impulse_curve, @@ -235,11 +235,11 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTargetSwitchDirections) { // Once the impulse style curve is updated, it turns to an ease-in ease-out // type curve. - double updated_duration = - curve - ->EaseInOutBoundedSegmentDuration( - updated_initial_value, base::TimeDelta(), base::TimeDelta()) - .InSecondsF(); + double updated_duration = curve + ->EaseInOutBoundedSegmentDuration( + updated_initial_value.OffsetFromOrigin(), + base::TimeDelta(), base::TimeDelta()) + .InSecondsF(); EXPECT_NEAR(updated_initial_value.y() * 0.5, curve ->GetValue(base::Seconds(initial_duration / 2.0 + @@ -256,28 +256,28 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTargetSwitchDirections) { TEST(ScrollOffsetAnimationCurveTest, InverseDeltaDuration) { std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(0.f, 100.f), DurationBehavior::INVERSE_DELTA)); + gfx::PointF(0.f, 100.f), DurationBehavior::INVERSE_DELTA)); - curve->SetInitialValue(gfx::Vector2dF()); + curve->SetInitialValue(gfx::PointF()); double smallDeltaDuration = curve->Duration().InSecondsF(); - curve->UpdateTarget(base::Seconds(0.01f), gfx::Vector2dF(0.f, 300.f)); + curve->UpdateTarget(base::Seconds(0.01f), gfx::PointF(0.f, 300.f)); double mediumDeltaDuration = curve->Duration().InSecondsF(); - curve->UpdateTarget(base::Seconds(0.01f), gfx::Vector2dF(0.f, 500.f)); + curve->UpdateTarget(base::Seconds(0.01f), gfx::PointF(0.f, 500.f)); double largeDeltaDuration = curve->Duration().InSecondsF(); EXPECT_GT(smallDeltaDuration, mediumDeltaDuration); EXPECT_GT(mediumDeltaDuration, largeDeltaDuration); - curve->UpdateTarget(base::Seconds(0.01f), gfx::Vector2dF(0.f, 5000.f)); + curve->UpdateTarget(base::Seconds(0.01f), gfx::PointF(0.f, 5000.f)); EXPECT_EQ(largeDeltaDuration, curve->Duration().InSecondsF()); } TEST(ScrollOffsetAnimationCurveTest, LinearAnimation) { // Testing autoscroll downwards for a scroller of length 1000px. - gfx::Vector2dF current_offset(0.f, 0.f); - gfx::Vector2dF target_offset(0.f, 1000.f); + gfx::PointF current_offset(0.f, 0.f); + gfx::PointF target_offset(0.f, 1000.f); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateLinearAnimationForTesting( target_offset)); @@ -288,13 +288,13 @@ TEST(ScrollOffsetAnimationCurveTest, LinearAnimation) { EXPECT_FLOAT_EQ(1.25f, curve->Duration().InSecondsF()); // Test scrolling down from half way. - current_offset = gfx::Vector2dF(0.f, 500.f); + current_offset = gfx::PointF(0.f, 500.f); curve->SetInitialValue(current_offset, base::TimeDelta(), autoscroll_velocity); EXPECT_FLOAT_EQ(0.625f, curve->Duration().InSecondsF()); // Test scrolling down when max_offset is reached. - current_offset = gfx::Vector2dF(0.f, 1000.f); + current_offset = gfx::PointF(0.f, 1000.f); curve->SetInitialValue(current_offset, base::TimeDelta(), autoscroll_velocity); EXPECT_FLOAT_EQ(0.f, curve->Duration().InSecondsF()); @@ -304,9 +304,9 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseDuration) { // The duration of an impulse-style curve in milliseconds is simply 1.5x the // scroll distance in physical pixels, with a minimum of 200ms and a maximum // of 500ms. - gfx::Vector2dF small_delta = gfx::Vector2dF(0.f, 100.f); - gfx::Vector2dF moderate_delta = gfx::Vector2dF(0.f, 250.f); - gfx::Vector2dF large_delta = gfx::Vector2dF(0.f, 400.f); + gfx::Vector2dF small_delta(0.f, 100.f); + gfx::Vector2dF moderate_delta(0.f, 250.f); + gfx::Vector2dF large_delta(0.f, 400.f); base::TimeDelta duration = ScrollOffsetAnimationCurve::ImpulseSegmentDuration( small_delta, base::TimeDelta()); @@ -324,29 +324,29 @@ TEST(ScrollOffsetAnimationCurveTest, ImpulseDuration) { TEST(ScrollOffsetAnimationCurveTest, CurveWithDelay) { std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(0.f, 100.f), DurationBehavior::INVERSE_DELTA)); + gfx::PointF(0.f, 100.f), DurationBehavior::INVERSE_DELTA)); double duration_in_seconds = kInverseDeltaMaxDuration / kDurationDivisor; double delay_in_seconds = 0.02; double curve_duration = duration_in_seconds - delay_in_seconds; - curve->SetInitialValue(gfx::Vector2dF(), base::Seconds(delay_in_seconds)); + curve->SetInitialValue(gfx::PointF(), base::Seconds(delay_in_seconds)); EXPECT_NEAR(curve_duration, curve->Duration().InSecondsF(), 0.0002f); - curve->UpdateTarget(base::Seconds(0.01f), gfx::Vector2dF(0.f, 500.f)); + curve->UpdateTarget(base::Seconds(0.01f), gfx::PointF(0.f, 500.f)); EXPECT_GT(curve_duration, curve->Duration().InSecondsF()); - EXPECT_EQ(gfx::Vector2dF(0.f, 500.f), curve->target_value()); + EXPECT_EQ(gfx::PointF(0.f, 500.f), curve->target_value()); } TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) { DurationBehavior duration_hint = DurationBehavior::INVERSE_DELTA; std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(0.f, 100.f), duration_hint)); - curve->SetInitialValue(gfx::Vector2dF(), base::Seconds(0.2)); + gfx::PointF(0.f, 100.f), duration_hint)); + curve->SetInitialValue(gfx::PointF(), base::Seconds(0.2)); EXPECT_EQ(0.f, curve->Duration().InSecondsF()); // Re-targeting when animation duration is 0. - curve->UpdateTarget(base::Seconds(-0.01), gfx::Vector2dF(0.f, 300.f)); + curve->UpdateTarget(base::Seconds(-0.01), gfx::PointF(0.f, 300.f)); double duration = ScrollOffsetAnimationCurve::EaseInOutSegmentDuration( gfx::Vector2dF(0.f, 200.f), duration_hint, base::Seconds(0.01)) @@ -355,14 +355,14 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) { // Re-targeting before last_retarget_, the difference should be accounted for // in duration. - curve->UpdateTarget(base::Seconds(-0.01), gfx::Vector2dF(0.f, 500.f)); + curve->UpdateTarget(base::Seconds(-0.01), gfx::PointF(0.f, 500.f)); duration = ScrollOffsetAnimationCurve::EaseInOutSegmentDuration( gfx::Vector2dF(0.f, 500.f), duration_hint, base::Seconds(0.01)) .InSecondsF(); EXPECT_EQ(duration, curve->Duration().InSecondsF()); - EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.f, 500.f), - curve->GetValue(base::Seconds(1.0))); + EXPECT_POINTF_EQ(gfx::PointF(0.f, 500.f), + curve->GetValue(base::Seconds(1.0))); } // This test verifies that if the last segment duration is zero, ::UpdateTarget @@ -371,37 +371,37 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) { DurationBehavior duration_hint = DurationBehavior::INVERSE_DELTA; std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(0.f, 100.f), duration_hint)); + gfx::PointF(0.f, 100.f), duration_hint)); double duration_in_seconds = kInverseDeltaMaxDuration / kDurationDivisor; double delay_in_seconds = 0.02; double curve_duration = duration_in_seconds - delay_in_seconds; - curve->SetInitialValue(gfx::Vector2dF(), base::Seconds(delay_in_seconds)); + curve->SetInitialValue(gfx::PointF(), base::Seconds(delay_in_seconds)); EXPECT_NEAR(curve_duration, curve->Duration().InSecondsF(), 0.0002f); // Re-target 1, this should set last_retarget_ to 0.05. gfx::Vector2dF new_delta = - gfx::Vector2dF(0.f, 200.f) - curve->GetValue(base::Seconds(0.05)); + gfx::PointF(0.f, 200.f) - curve->GetValue(base::Seconds(0.05)); double expected_duration = ScrollOffsetAnimationCurve::EaseInOutSegmentDuration( new_delta, duration_hint, base::TimeDelta()) .InSecondsF() + 0.05; - curve->UpdateTarget(base::Seconds(0.05), gfx::Vector2dF(0.f, 200.f)); + curve->UpdateTarget(base::Seconds(0.05), gfx::PointF(0.f, 200.f)); EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f); // Re-target 2, this should set total_animation_duration to t, which is // last_retarget_. This is what would cause the DCHECK failure in // crbug.com/645317. - curve->UpdateTarget(base::Seconds(-0.145), gfx::Vector2dF(0.f, 300.f)); + curve->UpdateTarget(base::Seconds(-0.145), gfx::PointF(0.f, 300.f)); EXPECT_NEAR(0.05, curve->Duration().InSecondsF(), 0.0002f); // Re-target 3, this should set total_animation_duration based on new_delta. - new_delta = gfx::Vector2dF(0.f, 500.f) - curve->GetValue(base::Seconds(0.05)); + new_delta = gfx::PointF(0.f, 500.f) - curve->GetValue(base::Seconds(0.05)); expected_duration = ScrollOffsetAnimationCurve::EaseInOutSegmentDuration( new_delta, duration_hint, base::Seconds(0.15)) .InSecondsF(); - curve->UpdateTarget(base::Seconds(-0.1), gfx::Vector2dF(0.f, 500.f)); + curve->UpdateTarget(base::Seconds(-0.1), gfx::PointF(0.f, 500.f)); EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f); } diff --git a/chromium/cc/animation/scroll_offset_animations.h b/chromium/cc/animation/scroll_offset_animations.h index 3d2e33b174e..fa72a954739 100644 --- a/chromium/cc/animation/scroll_offset_animations.h +++ b/chromium/cc/animation/scroll_offset_animations.h @@ -7,6 +7,7 @@ #include <unordered_map> +#include "base/memory/raw_ptr.h" #include "cc/animation/scroll_offset_animations_impl.h" #include "cc/trees/mutator_host_client.h" @@ -54,7 +55,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimations { std::unordered_map<ElementId, ScrollOffsetAnimationUpdate, ElementIdHash>; ElementToUpdateMap element_to_update_map_; - AnimationHost* animation_host_; + raw_ptr<AnimationHost> animation_host_; }; } // namespace cc diff --git a/chromium/cc/animation/scroll_offset_animations_impl.cc b/chromium/cc/animation/scroll_offset_animations_impl.cc index 0926b73553e..b3f217ac787 100644 --- a/chromium/cc/animation/scroll_offset_animations_impl.cc +++ b/chromium/cc/animation/scroll_offset_animations_impl.cc @@ -39,8 +39,8 @@ ScrollOffsetAnimationsImpl::~ScrollOffsetAnimationsImpl() { void ScrollOffsetAnimationsImpl::AutoScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, float autoscroll_velocity, base::TimeDelta animation_start_offset) { std::unique_ptr<ScrollOffsetAnimationCurve> curve = @@ -55,8 +55,8 @@ void ScrollOffsetAnimationsImpl::AutoScrollAnimationCreate( void ScrollOffsetAnimationsImpl::MouseWheelScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, base::TimeDelta delayed_by, base::TimeDelta animation_start_offset) { std::unique_ptr<ScrollOffsetAnimationCurve> curve = @@ -92,7 +92,7 @@ void ScrollOffsetAnimationsImpl::ScrollAnimationCreateInternal( bool ScrollOffsetAnimationsImpl::ScrollAnimationUpdateTarget( const gfx::Vector2dF& scroll_delta, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& max_scroll_offset, base::TimeTicks frame_monotonic_time, base::TimeDelta delayed_by) { DCHECK(scroll_offset_animation_); @@ -117,8 +117,8 @@ bool ScrollOffsetAnimationsImpl::ScrollAnimationUpdateTarget( ScrollOffsetAnimationCurve::ToScrollOffsetAnimationCurve( keyframe_model->curve()); - gfx::Vector2dF new_target = curve->target_value() + scroll_delta; - new_target.SetToMax(gfx::Vector2dF()); + gfx::PointF new_target = curve->target_value() + scroll_delta; + new_target.SetToMax(gfx::PointF()); new_target.SetToMin(max_scroll_offset); // TODO(ymalik): KeyframeModel::TrimTimeToCurrentIteration should probably diff --git a/chromium/cc/animation/scroll_offset_animations_impl.h b/chromium/cc/animation/scroll_offset_animations_impl.h index acadbaa7296..e637b3eb7a9 100644 --- a/chromium/cc/animation/scroll_offset_animations_impl.h +++ b/chromium/cc/animation/scroll_offset_animations_impl.h @@ -7,6 +7,7 @@ #include <memory> +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/scroll_offset_animation_curve.h" @@ -35,8 +36,8 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationsImpl delete; void AutoScrollAnimationCreate(ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, float autoscroll_velocity, base::TimeDelta animation_start_offset); @@ -44,13 +45,13 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationsImpl // animation. |animation_start_offset| causes us to start the animation // partway through. void MouseWheelScrollAnimationCreate(ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, base::TimeDelta delayed_by, base::TimeDelta animation_start_offset); bool ScrollAnimationUpdateTarget(const gfx::Vector2dF& scroll_delta, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& max_scroll_offset, base::TimeTicks frame_monotonic_time, base::TimeDelta delayed_by); @@ -89,7 +90,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationsImpl void ReattachScrollOffsetAnimationIfNeeded(ElementId element_id); - AnimationHost* animation_host_; + raw_ptr<AnimationHost> animation_host_; scoped_refptr<AnimationTimeline> scroll_offset_timeline_; // We have just one animation for impl-only scroll offset animations. diff --git a/chromium/cc/animation/scroll_timeline.cc b/chromium/cc/animation/scroll_timeline.cc index 3c3eb51bfe2..f8d24815f2f 100644 --- a/chromium/cc/animation/scroll_timeline.cc +++ b/chromium/cc/animation/scroll_timeline.cc @@ -11,8 +11,8 @@ #include "cc/animation/worklet_animation.h" #include "cc/trees/property_tree.h" #include "cc/trees/scroll_node.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size.h" -#include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -97,13 +97,11 @@ absl::optional<base::TimeTicks> ScrollTimeline::CurrentTime( const ScrollNode* scroll_node = scroll_tree.FindNodeFromElementId(scroller_id); - gfx::Vector2dF offset = - scroll_tree.GetPixelSnappedScrollOffset(scroll_node->id); + gfx::PointF offset = scroll_tree.GetPixelSnappedScrollOffset(scroll_node->id); DCHECK_GE(offset.x(), 0); DCHECK_GE(offset.y(), 0); - gfx::Vector2dF scroll_dimensions = - scroll_tree.MaxScrollOffset(scroll_node->id); + gfx::PointF scroll_dimensions = scroll_tree.MaxScrollOffset(scroll_node->id); double max_offset = IsVertical(direction_) ? scroll_dimensions.y() : scroll_dimensions.x(); diff --git a/chromium/cc/animation/scroll_timeline_unittest.cc b/chromium/cc/animation/scroll_timeline_unittest.cc index 0ce18291d15..2e5c21a5bc6 100644 --- a/chromium/cc/animation/scroll_timeline_unittest.cc +++ b/chromium/cc/animation/scroll_timeline_unittest.cc @@ -11,7 +11,7 @@ #include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/geometry/vector2d_f.h" +#include "ui/gfx/geometry/point_f.h" namespace cc { @@ -26,7 +26,7 @@ static constexpr double time_error_ms = 0.001; void SetScrollOffset(PropertyTrees* property_trees, ElementId scroller_id, - gfx::Vector2dF offset) { + gfx::PointF offset) { // Update both scroll and transform trees property_trees->scroll_tree.SetScrollOffset(scroller_id, offset); TransformNode* transform_node = @@ -121,14 +121,14 @@ TEST_F(ScrollTimelineTest, BasicCurrentTimeCalculations) { scroller_id(), ScrollTimeline::ScrollRight, scroll_offsets); // Unscrolled, both timelines should read a current time of 0. - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF()); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF()); EXPECT_SCROLL_TIMELINE_TIME_NEAR( 0, vertical_timeline->CurrentTime(scroll_tree(), false)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( 0, horizontal_timeline->CurrentTime(scroll_tree(), false)); // Now do some scrolling and make sure that the ScrollTimelines update. - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(75, 50)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(75, 50)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( 0.5 * ScrollTimeline::kScrollTimelineDurationMs, @@ -158,44 +158,44 @@ TEST_F(ScrollTimelineTest, MultipleScrollOffsetsCurrentTimeCalculations) { // Scale necessary to convert absolute unit times to progress based values double scale = ScrollTimeline::kScrollTimelineDurationMs / scroll_size; - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF()); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF()); EXPECT_SCROLL_TIMELINE_TIME_NEAR( (offset + p) * w * scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); p = (70.0 - 0.0) / (100.0 - 0.0); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 70)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 70)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( (offset + p) * w * scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); offset = 1; p = 0; - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 100)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 100)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( (offset + p) * w * scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); p = (150.0 - 100.0) / (250.0 - 100.0); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 150)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 150)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( (offset + p) * w * scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); offset = 2; p = 0; - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 250)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 250)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( (offset + p) * w * scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); p = (350.0 - 250.0) / (400.0 - 250.0); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 350)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 350)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( (offset + p) * w * scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 400)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 400)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( ScrollTimeline::kScrollTimelineDurationMs, vertical_timeline->CurrentTime(scroll_tree(), false)); @@ -212,7 +212,7 @@ TEST_F(ScrollTimelineTest, OverlappingScrollOffsets) { scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); // Offset is less than start offset ==> current time is 0. - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 300)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 300)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( 0, vertical_timeline->CurrentTime(scroll_tree(), false)); @@ -220,7 +220,7 @@ TEST_F(ScrollTimelineTest, OverlappingScrollOffsets) { double scale = ScrollTimeline::kScrollTimelineDurationMs / scroll_size; // Offset is greater than end offset ==> current time is 100%. - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 360)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 360)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( scroll_size * scale, vertical_timeline->CurrentTime(scroll_tree(), false)); @@ -230,7 +230,7 @@ TEST_F(ScrollTimelineTest, OverlappingScrollOffsets) { vertical_timeline = ScrollTimeline::Create( scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 100)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 100)); // Scroll offset is 25% of [0, 400) range, which maps to [0% 50%) of the // entire scroll range. EXPECT_SCROLL_TIMELINE_TIME_NEAR( @@ -242,7 +242,7 @@ TEST_F(ScrollTimelineTest, OverlappingScrollOffsets) { vertical_timeline = ScrollTimeline::Create( scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 300)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 300)); // Scroll offset is 75% of [0, 400) range, which maps to [50% 100%) of the // entire scroll range. EXPECT_SCROLL_TIMELINE_TIME_NEAR( @@ -277,7 +277,7 @@ TEST_F(ScrollTimelineTest, ActiveTimeIsSetOnlyAfterPromotion) { double halfwayY = scroll_size / 2.; double expectedTime = 0.5 * ScrollTimeline::kScrollTimelineDurationMs; - SetScrollOffset(&pending_tree, scroller_id, gfx::Vector2dF(0, halfwayY)); + SetScrollOffset(&pending_tree, scroller_id, gfx::PointF(0, halfwayY)); scoped_refptr<ScrollTimeline> main_timeline = ScrollTimeline::Create( scroller_id, ScrollTimeline::ScrollDown, scroll_offsets); @@ -314,7 +314,7 @@ TEST_F(ScrollTimelineTest, CurrentTimeIsAdjustedForPixelSnapping) { scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create( scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 50)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 50)); // For simplicity emulate snapping by directly setting snap_amount of // transform node. @@ -340,24 +340,24 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesStartScrollOffset) { // Unscrolled, the timeline should read a current time of 0 since the current // offset (0) will be less than the startScrollOffset. - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF()); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF()); EXPECT_SCROLL_TIMELINE_TIME_NEAR(0, timeline->CurrentTime(scroll_tree(), false)); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 19)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 19)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(0, timeline->CurrentTime(scroll_tree(), false)); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 20)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 20)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(0, timeline->CurrentTime(scroll_tree(), false)); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 50)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 50)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( CalculateCurrentTime(50, start_scroll_offset, scroll_size), timeline->CurrentTime(scroll_tree(), false)); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 200)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 200)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( CalculateCurrentTime(200, start_scroll_offset, scroll_size), timeline->CurrentTime(scroll_tree(), false)); @@ -373,23 +373,23 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesEndScrollOffset) { scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, scroll_size)); + gfx::PointF(0, scroll_size)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs, timeline->CurrentTime(scroll_tree(), false)); SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, scroll_size - 20)); + gfx::PointF(0, scroll_size - 20)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs, timeline->CurrentTime(scroll_tree(), false)); SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, scroll_size - 50)); + gfx::PointF(0, scroll_size - 50)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( CalculateCurrentTime(scroll_size - 50, 0, end_scroll_offset), timeline->CurrentTime(scroll_tree(), false)); SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, scroll_size - 200)); + gfx::PointF(0, scroll_size - 200)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( CalculateCurrentTime(scroll_size - 200, 0, end_scroll_offset), timeline->CurrentTime(scroll_tree(), false)); @@ -405,7 +405,7 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesCombinedStartAndEndScrollOffset) { scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create( scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, scroll_size - 150)); + gfx::PointF(0, scroll_size - 150)); EXPECT_SCROLL_TIMELINE_TIME_NEAR( CalculateCurrentTime(scroll_size - 150, start_scroll_offset, end_scroll_offset), @@ -418,7 +418,7 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesEqualStartAndEndScrollOffset) { scroll_offsets.push_back(20); scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create( scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 150)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 150)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs, timeline->CurrentTime(scroll_tree(), false)); @@ -431,11 +431,11 @@ TEST_F(ScrollTimelineTest, scroll_offsets.push_back(10); scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create( scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 40)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 40)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(0, timeline->CurrentTime(scroll_tree(), false)); - SetScrollOffset(&property_trees(), scroller_id(), gfx::Vector2dF(0, 150)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::PointF(0, 150)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs, timeline->CurrentTime(scroll_tree(), false)); @@ -455,19 +455,19 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesScrollOffsets) { // Before the start_scroll_offset the current time should be 0 SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, start_scroll_offset - 10)); + gfx::PointF(0, start_scroll_offset - 10)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(0, timeline->CurrentTime(scroll_tree(), false)); // At the end_scroll_offset the current time should be 100% SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, end_scroll_offset)); + gfx::PointF(0, end_scroll_offset)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs, timeline->CurrentTime(scroll_tree(), false)); // After the end_scroll_offset the current time should be 100% SetScrollOffset(&property_trees(), scroller_id(), - gfx::Vector2dF(0, end_scroll_offset + 10)); + gfx::PointF(0, end_scroll_offset + 10)); EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs, timeline->CurrentTime(scroll_tree(), false)); } diff --git a/chromium/cc/animation/worklet_animation.cc b/chromium/cc/animation/worklet_animation.cc index e1b9aadc01b..72fec0eb1c6 100644 --- a/chromium/cc/animation/worklet_animation.cc +++ b/chromium/cc/animation/worklet_animation.cc @@ -23,25 +23,7 @@ WorkletAnimation::WorkletAnimation( std::unique_ptr<AnimationOptions> options, std::unique_ptr<AnimationEffectTimings> effect_timings, bool is_controlling_instance) - : WorkletAnimation(cc_animation_id, - worklet_animation_id, - name, - playback_rate, - std::move(options), - std::move(effect_timings), - is_controlling_instance, - nullptr) {} - -WorkletAnimation::WorkletAnimation( - int cc_animation_id, - WorkletAnimationId worklet_animation_id, - const std::string& name, - double playback_rate, - std::unique_ptr<AnimationOptions> options, - std::unique_ptr<AnimationEffectTimings> effect_timings, - bool is_controlling_instance, - std::unique_ptr<KeyframeEffect> effect) - : Animation(cc_animation_id, std::move(effect)), + : Animation(cc_animation_id), worklet_animation_id_(worklet_animation_id), name_(name), playback_rate_(playback_rate), diff --git a/chromium/cc/animation/worklet_animation.h b/chromium/cc/animation/worklet_animation.h index 73c1c25f7e1..e21d2f5e819 100644 --- a/chromium/cc/animation/worklet_animation.h +++ b/chromium/cc/animation/worklet_animation.h @@ -5,6 +5,9 @@ #ifndef CC_ANIMATION_WORKLET_ANIMATION_H_ #define CC_ANIMATION_WORKLET_ANIMATION_H_ +#include <memory> +#include <string> + #include "base/gtest_prod_util.h" #include "base/time/time.h" #include "cc/animation/animation.h" @@ -15,10 +18,6 @@ namespace cc { -namespace { -FORWARD_DECLARE_TEST(WorkletAnimationTest, NonImplInstanceDoesNotTickKeyframe); -} // namespace - class AnimationOptions; class AnimationEffectTimings; @@ -79,17 +78,6 @@ class CC_ANIMATION_EXPORT WorkletAnimation final : public Animation { void ReleasePendingTreeLock() { has_pending_tree_lock_ = false; } private: - FRIEND_TEST_ALL_PREFIXES(WorkletAnimationTest, - NonImplInstanceDoesNotTickKeyframe); - WorkletAnimation(int cc_animation_id, - WorkletAnimationId worklet_animation_id, - const std::string& name, - double playback_rate, - std::unique_ptr<AnimationOptions> options, - std::unique_ptr<AnimationEffectTimings> effect_timings, - bool is_controlling_instance, - std::unique_ptr<KeyframeEffect> effect); - ~WorkletAnimation() override; // Returns the current time to be passed into the underlying AnimationWorklet. diff --git a/chromium/cc/animation/worklet_animation_unittest.cc b/chromium/cc/animation/worklet_animation_unittest.cc index bf854ed7c36..e3755ce5031 100644 --- a/chromium/cc/animation/worklet_animation_unittest.cc +++ b/chromium/cc/animation/worklet_animation_unittest.cc @@ -70,14 +70,13 @@ class MockScrollTimeline : public ScrollTimeline { }; TEST_F(WorkletAnimationTest, NonImplInstanceDoesNotTickKeyframe) { + scoped_refptr<WorkletAnimation> worklet_animation = WrapRefCounted( + new WorkletAnimation(1, worklet_animation_id_, "test_name", 1, nullptr, + nullptr, false /* not impl instance*/)); std::unique_ptr<MockKeyframeEffect> effect = - std::make_unique<MockKeyframeEffect>(worklet_animation_.get()); + std::make_unique<MockKeyframeEffect>(worklet_animation.get()); MockKeyframeEffect* mock_effect = effect.get(); - - scoped_refptr<WorkletAnimation> worklet_animation = - WrapRefCounted(new WorkletAnimation( - 1, worklet_animation_id_, "test_name", 1, nullptr, nullptr, - false /* not impl instance*/, std::move(effect))); + worklet_animation->SetKeyframeEffectForTesting(std::move(effect)); EXPECT_CALL(*mock_effect, Tick(_)).Times(0); diff --git a/chromium/cc/base/delayed_unique_notifier.cc b/chromium/cc/base/delayed_unique_notifier.cc index 49470c0220f..a618b257ad1 100644 --- a/chromium/cc/base/delayed_unique_notifier.cc +++ b/chromium/cc/base/delayed_unique_notifier.cc @@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/location.h" -#include "base/sequenced_task_runner.h" +#include "base/task/sequenced_task_runner.h" namespace cc { diff --git a/chromium/cc/base/delayed_unique_notifier.h b/chromium/cc/base/delayed_unique_notifier.h index 21c40d0acec..a5b3685ca72 100644 --- a/chromium/cc/base/delayed_unique_notifier.h +++ b/chromium/cc/base/delayed_unique_notifier.h @@ -6,6 +6,7 @@ #define CC_BASE_DELAYED_UNIQUE_NOTIFIER_H_ #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "cc/base/base_export.h" @@ -58,7 +59,7 @@ class CC_BASE_EXPORT DelayedUniqueNotifier { THREAD_CHECKER(thread_checker_); - base::SequencedTaskRunner* const task_runner_; + const raw_ptr<base::SequencedTaskRunner> task_runner_; const base::RepeatingClosure closure_; const base::TimeDelta delay_; diff --git a/chromium/cc/base/devtools_instrumentation.cc b/chromium/cc/base/devtools_instrumentation.cc index 79c321ae344..4691ec20dc4 100644 --- a/chromium/cc/base/devtools_instrumentation.cc +++ b/chromium/cc/base/devtools_instrumentation.cc @@ -39,6 +39,7 @@ const char kLayerId[] = "layerId"; const char kLayerTreeId[] = "layerTreeId"; const char kPixelRefId[] = "pixelRefId"; const char kFrameSequenceNumber[] = "frameSeqId"; +const char kHasPartialUpdate[] = "hasPartialUpdate"; const char kImageUploadTask[] = "ImageUploadTask"; const char kImageDecodeTask[] = "ImageDecodeTask"; diff --git a/chromium/cc/base/devtools_instrumentation.h b/chromium/cc/base/devtools_instrumentation.h index 6e95db6c756..86de7ba5d3a 100644 --- a/chromium/cc/base/devtools_instrumentation.h +++ b/chromium/cc/base/devtools_instrumentation.h @@ -35,6 +35,7 @@ CC_BASE_EXPORT extern const char kLayerId[]; CC_BASE_EXPORT extern const char kLayerTreeId[]; CC_BASE_EXPORT extern const char kPixelRefId[]; CC_BASE_EXPORT extern const char kFrameSequenceNumber[]; +CC_BASE_EXPORT extern const char kHasPartialUpdate[]; CC_BASE_EXPORT extern const char kImageDecodeTask[]; CC_BASE_EXPORT extern const char kBeginFrame[]; @@ -206,12 +207,14 @@ inline void CC_BASE_EXPORT DidRequestMainThreadFrame(int layer_tree_host_id) { inline void CC_BASE_EXPORT DidDropSmoothnessFrame(int layer_tree_host_id, base::TimeTicks dropped_frame_timestamp, - uint64_t sequence_number) { + uint64_t sequence_number, + bool has_partial_update) { TRACE_EVENT_INSTANT(internal::CategoryName::kTimelineFrame, perfetto::StaticString(internal::kDroppedFrame), dropped_frame_timestamp, internal::kLayerTreeId, layer_tree_host_id, internal::kFrameSequenceNumber, - sequence_number); + sequence_number, internal::kHasPartialUpdate, + has_partial_update); } inline std::unique_ptr<base::trace_event::ConvertableToTraceFormat> diff --git a/chromium/cc/base/features.cc b/chromium/cc/base/features.cc index eea90717aa6..d6834560836 100644 --- a/chromium/cc/base/features.cc +++ b/chromium/cc/base/features.cc @@ -48,9 +48,6 @@ const base::Feature kScrollUnification{"ScrollUnification", const base::Feature kSchedulerSmoothnessForAnimatedScrolls{ "SmoothnessModeForAnimatedScrolls", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kWheelEventRegions{"WheelEventRegions", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kHudDisplayForPerformanceMetrics{ "HudDisplayForPerformanceMetrics", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -61,4 +58,11 @@ const base::Feature kPreferNewContentForCheckerboardedScrolls{ "PreferNewContentForCheckerboardedScrolls", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDurationEstimatesInCompositorTimingHistory{ + "DurationEstimatesInCompositorTimingHistory", + base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kSlidingWindowForDroppedFrameCounter{ + "SlidingWindowForDroppedFrameCounter", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features diff --git a/chromium/cc/base/features.h b/chromium/cc/base/features.h index 652d5f88f57..6df0037ae3a 100644 --- a/chromium/cc/base/features.h +++ b/chromium/cc/base/features.h @@ -34,12 +34,6 @@ CC_BASE_EXPORT extern const base::Feature kScrollUnification; CC_BASE_EXPORT extern const base::Feature kSchedulerSmoothnessForAnimatedScrolls; -// When enabled, cc's layers support region-based wheel event hit-testing rather -// than only supporting flagging all layers, or no layers, as having blocking -// wheel event listeners. -// https://docs.google.com/document/d/1ar4WhVnLA-fmw6atgP-23iq-ys_NfFoGb3LA5AgaylA/edit?usp=sharing -CC_BASE_EXPORT extern const base::Feature kWheelEventRegions; - // When enabled, cc will show blink's Web-Vital metrics inside its heads up // display. CC_BASE_EXPORT extern const base::Feature kHudDisplayForPerformanceMetrics; @@ -53,6 +47,16 @@ CC_BASE_EXPORT extern const base::Feature kJankInjectionAblationFeature; CC_BASE_EXPORT extern const base::Feature kPreferNewContentForCheckerboardedScrolls; +// When enabled, CompositorTimingHistory will directly record the timing history +// that is used to calculate main thread timing estimates, and use the +// percentile of sum of different stages instead of the sum of percentiles. +CC_BASE_EXPORT extern const base::Feature + kDurationEstimatesInCompositorTimingHistory; + +// When enabled, DroppedFrameCounter will use an adjusted sliding window +// interval specified by field trial params. +CC_BASE_EXPORT extern const base::Feature kSlidingWindowForDroppedFrameCounter; + } // namespace features #endif // CC_BASE_FEATURES_H_ diff --git a/chromium/cc/base/list_container.h b/chromium/cc/base/list_container.h index dd0478d2729..25af557d3e7 100644 --- a/chromium/cc/base/list_container.h +++ b/chromium/cc/base/list_container.h @@ -8,6 +8,7 @@ #include <stddef.h> #include <memory> +#include <utility> #include "base/check.h" #include "cc/base/list_container_helper.h" @@ -26,6 +27,8 @@ namespace cc { template <class BaseElementType> class ListContainer { public: + using value_type = const BaseElementType*; + // This constructor reserves the requested memory up front so only single // allocation is needed. When num_of_elements_to_reserve_for is zero, use the // default size. diff --git a/chromium/cc/base/list_container_helper.cc b/chromium/cc/base/list_container_helper.cc index 1e5a35030b3..319f0d6c0b7 100644 --- a/chromium/cc/base/list_container_helper.cc +++ b/chromium/cc/base/list_container_helper.cc @@ -262,6 +262,9 @@ class ListContainerHelper::CharAllocator { size_t last_list_index_; // This is equivalent to |storage_[last_list_index_]|. + // + // `last_list_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). InnerList* last_list_; }; diff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h index 7fc3bcebc56..1b34ca790ae 100644 --- a/chromium/cc/base/list_container_helper.h +++ b/chromium/cc/base/list_container_helper.h @@ -36,8 +36,14 @@ class CC_BASE_EXPORT ListContainerHelper final { // This class points to a certain position inside memory of // CharAllocator. It is a base class for ListContainer iterators. struct CC_BASE_EXPORT PositionInCharAllocator { + // `ptr_to_container` is not a raw_ptr<...> for performance reasons (based + // on analysis of sampling profiler data and tab_search:top100:2020). CharAllocator* ptr_to_container; + size_t vector_index; + + // `item_iterator` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). char* item_iterator; PositionInCharAllocator(const PositionInCharAllocator& other); diff --git a/chromium/cc/base/list_container_unittest.cc b/chromium/cc/base/list_container_unittest.cc index c2975adcc49..5ce75f1676b 100644 --- a/chromium/cc/base/list_container_unittest.cc +++ b/chromium/cc/base/list_container_unittest.cc @@ -10,6 +10,7 @@ #include <vector> #include "base/cxx17_backports.h" +#include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -1168,7 +1169,7 @@ class InstanceCounter { } private: - int* counter_; + raw_ptr<int> counter_; }; TEST(ListContainerTest, RemoveLastDestruction) { diff --git a/chromium/cc/base/math_util.cc b/chromium/cc/base/math_util.cc index 93df9889a2a..c4a9048a8fa 100644 --- a/chromium/cc/base/math_util.cc +++ b/chromium/cc/base/math_util.cc @@ -29,16 +29,19 @@ namespace cc { static HomogeneousCoordinate ProjectHomogeneousPoint( const gfx::Transform& transform, const gfx::PointF& p) { - SkScalar z = - -(transform.matrix().get(2, 0) * p.x() + - transform.matrix().get(2, 1) * p.y() + transform.matrix().get(2, 3)) / - transform.matrix().get(2, 2); - + SkScalar m22 = transform.matrix().get(2, 2); // In this case, the layer we are trying to project onto is perpendicular to // ray (point p and z-axis direction) that we are trying to project. This // happens when the layer is rotated so that it is infinitesimally thin, or // when it is co-planar with the camera origin -- i.e. when the layer is // invisible anyway. + if (!std::isnormal(m22)) + return HomogeneousCoordinate(0.0, 0.0, 0.0, 1.0); + SkScalar z = + -(transform.matrix().get(2, 0) * p.x() + + transform.matrix().get(2, 1) * p.y() + transform.matrix().get(2, 3)) / + m22; + // Same underlying condition as the previous early return. if (!std::isfinite(z)) return HomogeneousCoordinate(0.0, 0.0, 0.0, 1.0); diff --git a/chromium/cc/base/math_util_unittest.cc b/chromium/cc/base/math_util_unittest.cc index 8e03825888f..ad719570c6d 100644 --- a/chromium/cc/base/math_util_unittest.cc +++ b/chromium/cc/base/math_util_unittest.cc @@ -9,12 +9,12 @@ #include <cmath> #include <limits> -#include "cc/test/geometry_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform.h" namespace cc { @@ -145,8 +145,7 @@ TEST(MathUtilTest, EnclosingClippedRectUsesCorrectInitialBounds) { // Due to floating point math in ComputeClippedPointForEdge this result // is fairly imprecise. 0.15f was empirically determined. - EXPECT_RECT_NEAR( - gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), result, 0.15f); + EXPECT_RECTF_NEAR(gfx::RectF(-100, -100, 90, 90), result, 0.15f); } TEST(MathUtilTest, EnclosingClippedRectHandlesSmallPositiveW) { @@ -200,8 +199,7 @@ TEST(MathUtilTest, EnclosingRectOfVerticesUsesCorrectInitialBounds) { gfx::RectF result = MathUtil::ComputeEnclosingRectOfVertices(vertices, num_vertices); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(gfx::PointF(-100, -100), gfx::SizeF(90, 90)), - result); + EXPECT_RECTF_EQ(gfx::RectF(-100, -100, 90, 90), result); } TEST(MathUtilTest, SmallestAngleBetweenVectors) { @@ -236,15 +234,15 @@ TEST(MathUtilTest, VectorProjection) { gfx::Vector2dF test_vector(0.3f, 0.7f); // Orthogonal vectors project to a zero vector. - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(x, y)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(y, x)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(x, y)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 0), MathUtil::ProjectVector(y, x)); // Projecting a vector onto the orthonormal basis gives the corresponding // component of the vector. - EXPECT_VECTOR_EQ(gfx::Vector2dF(test_vector.x(), 0), - MathUtil::ProjectVector(test_vector, x)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, test_vector.y()), - MathUtil::ProjectVector(test_vector, y)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(test_vector.x(), 0), + MathUtil::ProjectVector(test_vector, x)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, test_vector.y()), + MathUtil::ProjectVector(test_vector, y)); // Finally check than an arbitrary vector projected to another one gives a // vector parallel to the second vector. diff --git a/chromium/cc/base/rtree.h b/chromium/cc/base/rtree.h index 3fd1fafb913..56353472209 100644 --- a/chromium/cc/base/rtree.h +++ b/chromium/cc/base/rtree.h @@ -15,6 +15,7 @@ #include <vector> #include "base/check_op.h" +#include "base/memory/raw_ptr.h" #include "base/numerics/clamped_math.h" #include "ui/gfx/geometry/rect.h" @@ -105,7 +106,7 @@ class RTree { // valid index pointing to an element in the vector that was used to build // this rtree. When the level is not 0, it's an internal node and it has a // valid subtree pointer. - Node<U>* subtree; + raw_ptr<Node<U>> subtree; U payload; gfx::Rect bounds; @@ -319,9 +320,9 @@ void RTree<T>::Search(const gfx::Rect& query, if (num_data_elements_ == 0) return; if (!has_valid_bounds_) { - SearchRecursiveFallback(root_.subtree, query, results, rects); + SearchRecursiveFallback(root_.subtree.get(), query, results, rects); } else if (query.Intersects(root_.bounds)) { - SearchRecursive(root_.subtree, query, results, rects); + SearchRecursive(root_.subtree.get(), query, results, rects); } } @@ -332,9 +333,9 @@ void RTree<T>::SearchRefs(const gfx::Rect& query, if (num_data_elements_ == 0) return; if (!has_valid_bounds_) { - SearchRefsRecursiveFallback(root_.subtree, query, results); + SearchRefsRecursiveFallback(root_.subtree.get(), query, results); } else if (query.Intersects(root_.bounds)) { - SearchRefsRecursive(root_.subtree, query, results); + SearchRefsRecursive(root_.subtree.get(), query, results); } } @@ -350,7 +351,7 @@ void RTree<T>::SearchRecursive(Node<T>* node, if (rects) rects->push_back(node->children[i].bounds); } else { - SearchRecursive(node->children[i].subtree, query, results, rects); + SearchRecursive(node->children[i].subtree.get(), query, results, rects); } } } @@ -365,7 +366,7 @@ void RTree<T>::SearchRefsRecursive(Node<T>* node, if (node->level == 0) results->push_back(&node->children[i].payload); else - SearchRefsRecursive(node->children[i].subtree, query, results); + SearchRefsRecursive(node->children[i].subtree.get(), query, results); } } } @@ -385,7 +386,7 @@ void RTree<T>::SearchRecursiveFallback(Node<T>* node, rects->push_back(node->children[i].bounds); } } else { - SearchRecursive(node->children[i].subtree, query, results, rects); + SearchRecursive(node->children[i].subtree.get(), query, results, rects); } } } @@ -400,7 +401,7 @@ void RTree<T>::SearchRefsRecursiveFallback( if (query.Intersects(node->children[i].bounds)) results->push_back(&node->children[i].payload); } else { - SearchRefsRecursive(node->children[i].subtree, query, results); + SearchRefsRecursive(node->children[i].subtree.get(), query, results); } } } @@ -415,7 +416,7 @@ template <typename T> std::map<T, gfx::Rect> RTree<T>::GetAllBoundsForTracing() const { std::map<T, gfx::Rect> results; if (num_data_elements_ > 0) - GetAllBoundsRecursive(root_.subtree, &results); + GetAllBoundsRecursive(root_.subtree.get(), &results); return results; } @@ -426,7 +427,7 @@ void RTree<T>::GetAllBoundsRecursive(Node<T>* node, if (node->level == 0) (*results)[node->children[i].payload] = node->children[i].bounds; else - GetAllBoundsRecursive(node->children[i].subtree, results); + GetAllBoundsRecursive(node->children[i].subtree.get(), results); } } diff --git a/chromium/cc/base/spiral_iterator_unittest.cc b/chromium/cc/base/spiral_iterator_unittest.cc index 30804ee9423..e6ee5e5b67b 100644 --- a/chromium/cc/base/spiral_iterator_unittest.cc +++ b/chromium/cc/base/spiral_iterator_unittest.cc @@ -8,7 +8,6 @@ #include <vector> #include "cc/base/tiling_data.h" -#include "cc/test/geometry_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { diff --git a/chromium/cc/base/synced_property.h b/chromium/cc/base/synced_property.h index 6b8b91ebaf8..f5173bcdb68 100644 --- a/chromium/cc/base/synced_property.h +++ b/chromium/cc/base/synced_property.h @@ -24,16 +24,16 @@ namespace cc { template <typename T> class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { public: - SyncedProperty() : clobber_active_value_(false) {} + using BaseT = typename T::BaseType; + using DeltaT = typename T::DeltaType; // Returns the canonical value for the specified tree, including the sum of // all deltas. The pending tree should use this for activation purposes and // the active tree should use this for drawing. - typename T::ValueType Current(bool is_active_tree) const { + BaseT Current(bool is_active_tree) const { if (is_active_tree) - return active_base_.Combine(active_delta_).get(); - else - return pending_base_.Combine(PendingDelta()).get(); + return T::ApplyDelta(active_base_, active_delta_); + return T::ApplyDelta(pending_base_, PendingDelta()); } // Sets the value on the impl thread, due to an impl-thread-originating @@ -41,9 +41,9 @@ class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { // impl-thread-only information at first, and will get pulled back to the main // thread on the next call of PullDeltaToMainThread (which happens right // before the commit). - bool SetCurrent(typename T::ValueType current) { - T delta = T(current).InverseCombine(active_base_); - if (active_delta_.get() == delta.get()) + bool SetCurrent(BaseT current) { + DeltaT delta = T::DeltaBetweenBases(current, active_base_); + if (active_delta_ == delta) return false; active_delta_ = delta; @@ -52,22 +52,22 @@ class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { // Returns the difference between the last value that was committed and // activated from the main thread, and the current total value. - typename T::ValueType Delta() const { return active_delta_.get(); } + DeltaT Delta() const { return active_delta_; } // Returns the latest active tree delta and also makes a note that this value // was sent to the main thread. - typename T::ValueType PullDeltaForMainThread() { + DeltaT PullDeltaForMainThread() { reflected_delta_in_main_tree_ = PendingDelta(); - return reflected_delta_in_main_tree_.get(); + return reflected_delta_in_main_tree_; } // Push the latest value from the main thread onto pending tree-associated // state. Returns true if pushing the value results in different values // between the main layer tree and the pending tree. - bool PushMainToPending(typename T::ValueType main_thread_value) { + bool PushMainToPending(BaseT main_thread_value) { reflected_delta_in_pending_tree_ = reflected_delta_in_main_tree_; - reflected_delta_in_main_tree_ = T::Identity(); - pending_base_ = T(main_thread_value); + reflected_delta_in_main_tree_ = T::IdentityDelta(); + pending_base_ = main_thread_value; return Current(false) != main_thread_value; } @@ -84,15 +84,15 @@ class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { // active tree computes state using this value which is not computed on the // pending tree and not pushed during activation (aka scrollbar geometries). bool PushPendingToActive() { - typename T::ValueType pending_value_before_push = Current(false); - typename T::ValueType active_value_before_push = Current(true); + BaseT pending_value_before_push = Current(false); + BaseT active_value_before_push = Current(true); active_base_ = pending_base_; active_delta_ = PendingDelta(); - reflected_delta_in_pending_tree_ = T::Identity(); + reflected_delta_in_pending_tree_ = T::IdentityDelta(); clobber_active_value_ = false; - typename T::ValueType current_active_value = Current(true); + BaseT current_active_value = Current(true); return pending_value_before_push != current_active_value || active_value_before_push != current_active_value; } @@ -100,97 +100,81 @@ class SyncedProperty : public base::RefCounted<SyncedProperty<T>> { // This simulates the consequences of the sent value getting committed and // activated. void AbortCommit() { - pending_base_ = pending_base_.Combine(reflected_delta_in_main_tree_); - active_base_ = active_base_.Combine(reflected_delta_in_main_tree_); - active_delta_ = active_delta_.InverseCombine(reflected_delta_in_main_tree_); - reflected_delta_in_main_tree_ = T::Identity(); + pending_base_ = T::ApplyDelta(pending_base_, reflected_delta_in_main_tree_); + active_base_ = T::ApplyDelta(active_base_, reflected_delta_in_main_tree_); + active_delta_ = + T::DeltaBetweenDeltas(active_delta_, reflected_delta_in_main_tree_); + reflected_delta_in_main_tree_ = T::IdentityDelta(); } // Values as last pushed to the pending or active tree respectively, with no // impl-thread delta applied. - typename T::ValueType PendingBase() const { return pending_base_.get(); } - typename T::ValueType ActiveBase() const { return active_base_.get(); } + BaseT PendingBase() const { return pending_base_; } + BaseT ActiveBase() const { return active_base_; } // The new delta we would use if we decide to activate now. This delta // excludes the amount that we know is reflected in the pending tree. - T PendingDelta() const { + DeltaT PendingDelta() const { if (clobber_active_value_) - return T::Identity(); - return active_delta_.InverseCombine(reflected_delta_in_pending_tree_); + return T::IdentityDelta(); + + return T::DeltaBetweenDeltas(active_delta_, + reflected_delta_in_pending_tree_); } void set_clobber_active_value() { clobber_active_value_ = true; } private: + friend class base::RefCounted<SyncedProperty<T>>; + ~SyncedProperty() = default; + // Value last committed to the pending tree. - T pending_base_; + BaseT pending_base_ = T::IdentityBase(); // Value last committed to the active tree on the last activation. - T active_base_; + BaseT active_base_ = T::IdentityBase(); // The difference between |active_base_| and the user-perceived value. - T active_delta_; + DeltaT active_delta_ = T::IdentityDelta(); // The value sent to the main thread on the last BeginMainFrame. This is // always identity outside of the BeginMainFrame to (aborted)commit interval. - T reflected_delta_in_main_tree_; + DeltaT reflected_delta_in_main_tree_ = T::IdentityDelta(); // The value that was sent to the main thread for BeginMainFrame for the // current pending tree. This is always identity outside of the // BeginMainFrame to activation interval. - T reflected_delta_in_pending_tree_; + DeltaT reflected_delta_in_pending_tree_ = T::IdentityDelta(); // When true the pending delta is always identity so that it does not change // and will clobber the active value on push. - bool clobber_active_value_; - - friend class base::RefCounted<SyncedProperty<T>>; - ~SyncedProperty() {} + bool clobber_active_value_ = false; }; // SyncedProperty's delta-based conflict resolution logic makes sense for any // mathematical group. In practice, there are two that are useful: -// 1. Numbers/vectors with addition and identity = 0 (like scroll offsets) -// 2. Real numbers with multiplication and identity = 1 (like page scale) +// 1. Numbers/classes with addition and subtraction operations, and +// identity = constructor() (like gfx::Vector2dF for scroll offset and +// scroll delta) +// 2. Real numbers with multiplication and division operations, and +// identity = 1 (like page scale) -template <class V> +template <typename BaseT, typename DeltaT = BaseT> class AdditionGroup { public: - typedef V ValueType; - - AdditionGroup() : value_(Identity().get()) {} - explicit AdditionGroup(V value) : value_(value) {} - - V& get() { return value_; } - const V& get() const { return value_; } - - static AdditionGroup<V> Identity() { return AdditionGroup(V()); } // zero - AdditionGroup<V> Combine(AdditionGroup<V> p) const { - return AdditionGroup<V>(value_ + p.value_); - } - AdditionGroup<V> InverseCombine(AdditionGroup<V> p) const { - return AdditionGroup<V>(value_ - p.value_); - } - - private: - V value_; + using BaseType = BaseT; + using DeltaType = DeltaT; + static constexpr BaseT IdentityBase() { return BaseT(); } + static constexpr DeltaT IdentityDelta() { return DeltaT(); } + static BaseT ApplyDelta(BaseT v, DeltaT delta) { return v + delta; } + static DeltaT DeltaBetweenBases(BaseT v1, BaseT v2) { return v1 - v2; } + static DeltaT DeltaBetweenDeltas(DeltaT d1, DeltaT d2) { return d1 - d2; } }; class ScaleGroup { public: - typedef float ValueType; - - ScaleGroup() : value_(Identity().get()) {} - explicit ScaleGroup(float value) : value_(value) {} - - float& get() { return value_; } - const float& get() const { return value_; } - - static ScaleGroup Identity() { return ScaleGroup(1.f); } - ScaleGroup Combine(ScaleGroup p) const { - return ScaleGroup(value_ * p.value_); - } - ScaleGroup InverseCombine(ScaleGroup p) const { - return ScaleGroup(value_ / p.value_); - } - - private: - float value_; + using BaseType = float; + using DeltaType = float; + static constexpr float IdentityBase() { return 1.f; } + static constexpr float IdentityDelta() { return 1.f; } + static float ApplyDelta(float v, float delta) { return v * delta; } + static float DeltaBetweenBases(float v1, float v2) { return v1 / v2; } + static float DeltaBetweenDeltas(float d1, float d2) { return d1 / d2; } }; } // namespace cc diff --git a/chromium/cc/base/tiling_data_unittest.cc b/chromium/cc/base/tiling_data_unittest.cc index 71935a6c533..3f652bf26ab 100644 --- a/chromium/cc/base/tiling_data_unittest.cc +++ b/chromium/cc/base/tiling_data_unittest.cc @@ -9,7 +9,6 @@ #include <algorithm> #include <vector> -#include "cc/test/geometry_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { diff --git a/chromium/cc/base/unique_notifier.cc b/chromium/cc/base/unique_notifier.cc index 48dcc37108a..cebe8efef7e 100644 --- a/chromium/cc/base/unique_notifier.cc +++ b/chromium/cc/base/unique_notifier.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/location.h" -#include "base/sequenced_task_runner.h" +#include "base/task/sequenced_task_runner.h" namespace cc { diff --git a/chromium/cc/base/unique_notifier.h b/chromium/cc/base/unique_notifier.h index 2366b611b68..426f129fb1c 100644 --- a/chromium/cc/base/unique_notifier.h +++ b/chromium/cc/base/unique_notifier.h @@ -6,6 +6,7 @@ #define CC_BASE_UNIQUE_NOTIFIER_H_ #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "cc/base/base_export.h" @@ -41,7 +42,7 @@ class CC_BASE_EXPORT UniqueNotifier { void Notify(); // TODO(dcheng): How come this doesn't need to hold a ref to the task runner? - base::SequencedTaskRunner* const task_runner_; + const raw_ptr<base::SequencedTaskRunner> task_runner_; const base::RepeatingClosure closure_; // Lock should be held before modifying |notification_pending_|. diff --git a/chromium/cc/base/unique_notifier_unittest.cc b/chromium/cc/base/unique_notifier_unittest.cc index c331e567fa5..a6637399ea4 100644 --- a/chromium/cc/base/unique_notifier_unittest.cc +++ b/chromium/cc/base/unique_notifier_unittest.cc @@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/cc/benchmarks/micro_benchmark.cc b/chromium/cc/benchmarks/micro_benchmark.cc index 8c8687394e5..7522a0b8a91 100644 --- a/chromium/cc/benchmarks/micro_benchmark.cc +++ b/chromium/cc/benchmarks/micro_benchmark.cc @@ -9,7 +9,7 @@ #include "base/callback.h" #include "base/check.h" #include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/values.h" #include "cc/benchmarks/micro_benchmark_impl.h" diff --git a/chromium/cc/benchmarks/micro_benchmark_controller.cc b/chromium/cc/benchmarks/micro_benchmark_controller.cc index 0a941be152a..e703f5f8304 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller.cc +++ b/chromium/cc/benchmarks/micro_benchmark_controller.cc @@ -87,8 +87,9 @@ bool MicroBenchmarkController::SendMessage(int id, base::Value message) { return (*it)->ProcessMessage(std::move(message)); } -void MicroBenchmarkController::ScheduleImplBenchmarks( - LayerTreeHostImpl* host_impl) { +std::vector<std::unique_ptr<MicroBenchmarkImpl>> +MicroBenchmarkController::CreateImplBenchmarks() const { + std::vector<std::unique_ptr<MicroBenchmarkImpl>> result; for (const auto& benchmark : benchmarks_) { std::unique_ptr<MicroBenchmarkImpl> benchmark_impl; if (!benchmark->ProcessedForBenchmarkImpl()) { @@ -97,8 +98,9 @@ void MicroBenchmarkController::ScheduleImplBenchmarks( } if (benchmark_impl.get()) - host_impl->ScheduleMicroBenchmark(std::move(benchmark_impl)); + result.push_back(std::move(benchmark_impl)); } + return result; } void MicroBenchmarkController::DidUpdateLayers() { diff --git a/chromium/cc/benchmarks/micro_benchmark_controller.h b/chromium/cc/benchmarks/micro_benchmark_controller.h index c4fc548e600..f8257390990 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller.h +++ b/chromium/cc/benchmarks/micro_benchmark_controller.h @@ -10,6 +10,7 @@ #include <vector> #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "cc/benchmarks/micro_benchmark.h" namespace base { @@ -20,7 +21,7 @@ class Value; namespace cc { class LayerTreeHost; -class LayerTreeHostImpl; + class CC_EXPORT MicroBenchmarkController { public: explicit MicroBenchmarkController(LayerTreeHost* host); @@ -38,13 +39,13 @@ class CC_EXPORT MicroBenchmarkController { // Returns true if the message was successfully delivered and handled. bool SendMessage(int id, base::Value message); - void ScheduleImplBenchmarks(LayerTreeHostImpl* host_impl); + std::vector<std::unique_ptr<MicroBenchmarkImpl>> CreateImplBenchmarks() const; private: void CleanUpFinishedBenchmarks(); int GetNextIdAndIncrement(); - LayerTreeHost* host_; + raw_ptr<LayerTreeHost> host_; std::vector<std::unique_ptr<MicroBenchmark>> benchmarks_; static int next_id_; scoped_refptr<base::SingleThreadTaskRunner> main_controller_task_runner_; diff --git a/chromium/cc/benchmarks/micro_benchmark_controller_impl.h b/chromium/cc/benchmarks/micro_benchmark_controller_impl.h index fc1b91c673e..1f99fc9cc2f 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller_impl.h +++ b/chromium/cc/benchmarks/micro_benchmark_controller_impl.h @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/benchmarks/micro_benchmark_impl.h" namespace cc { @@ -29,7 +30,7 @@ class CC_EXPORT MicroBenchmarkControllerImpl { private: void CleanUpFinishedBenchmarks(); - LayerTreeHostImpl* host_; + raw_ptr<LayerTreeHostImpl> host_; std::vector<std::unique_ptr<MicroBenchmarkImpl>> benchmarks_; }; diff --git a/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc b/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc index 83902e9578c..f0d0f5effef 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc +++ b/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc @@ -128,11 +128,12 @@ TEST_F(MicroBenchmarkControllerTest, BenchmarkImplRan) { base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); - // Schedule impl benchmarks. In production code, this is run in commit. - layer_tree_host_->GetMicroBenchmarkController()->ScheduleImplBenchmarks( - layer_tree_host_impl_.get()); - - // Now complete the commit (as if on the impl thread). + // Scheduling benchmarks on the impl thread is usually done during + // LayerTreeHostImpl::FinishCommit(). + for (auto& benchmark : layer_tree_host_->GetMicroBenchmarkController() + ->CreateImplBenchmarks()) { + layer_tree_host_impl_->ScheduleMicroBenchmark(std::move(benchmark)); + } layer_tree_host_impl_->CommitComplete(); // Make sure all posted messages run. diff --git a/chromium/cc/benchmarks/micro_benchmark_impl.cc b/chromium/cc/benchmarks/micro_benchmark_impl.cc index 91164fd659e..6e70c8c099b 100644 --- a/chromium/cc/benchmarks/micro_benchmark_impl.cc +++ b/chromium/cc/benchmarks/micro_benchmark_impl.cc @@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/location.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/values.h" namespace cc { diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark.h b/chromium/cc/benchmarks/rasterize_and_record_benchmark.h index da021c8ddd3..8059abece43 100644 --- a/chromium/cc/benchmarks/rasterize_and_record_benchmark.h +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark.h @@ -12,8 +12,9 @@ #include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/values.h" #include "cc/benchmarks/micro_benchmark_controller.h" #include "cc/layers/recording_source.h" @@ -52,7 +53,7 @@ class RasterizeAndRecordBenchmark : public MicroBenchmark { // The following is used in DCHECKs. bool main_thread_benchmark_done_; - LayerTreeHost* layer_tree_host_; + raw_ptr<LayerTreeHost> layer_tree_host_; base::WeakPtrFactory<RasterizeAndRecordBenchmark> weak_ptr_factory_{this}; }; diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc index 9ac01785116..49f5a447e14 100644 --- a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc @@ -11,6 +11,7 @@ #include <memory> #include <utility> +#include "base/memory/raw_ptr.h" #include "base/timer/lap_timer.h" #include "base/values.h" #include "cc/layers/layer_impl.h" @@ -134,7 +135,7 @@ class FixedInvalidationPictureLayerTilingClient } private: - PictureLayerTilingClient* base_client_; + raw_ptr<PictureLayerTilingClient> base_client_; Region invalidation_; }; @@ -196,6 +197,9 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { return; } + if (layer->ShouldAdjustRasterScale()) + layer->RecalculateRasterScales(); + int text_pixels = layer->GetRasterSource()->GetDisplayItemList()->AreaOfDrawText( layer->visible_layer_rect()); @@ -218,13 +222,14 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) { settings.skewport_extrapolation_limit_in_screen_pixels, settings.max_preraster_distance_in_screen_pixels); - PictureLayerTiling* tiling = - tiling_set->AddTiling(gfx::AxisTransform2d(), layer->GetRasterSource()); + PictureLayerTiling* tiling = tiling_set->AddTiling( + gfx::AxisTransform2d(layer->raster_contents_scale_, {}), + layer->GetRasterSource()); tiling->set_resolution(HIGH_RESOLUTION); tiling->CreateAllTilesForTesting(); RasterSource* raster_source = tiling->raster_source().get(); - for (PictureLayerTiling::CoverageIterator it(tiling, 1.f, - layer->visible_layer_rect()); + for (PictureLayerTiling::CoverageIterator it( + tiling, tiling->contents_scale_key(), layer->visible_layer_rect()); it; ++it) { DCHECK(*it); diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h index e2d21fe1f85..987b8c80b48 100644 --- a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.h @@ -7,7 +7,7 @@ #include <stddef.h> -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "cc/benchmarks/micro_benchmark_impl.h" #include "cc/raster/lcd_text_disallowed_reason.h" diff --git a/chromium/cc/benchmarks/unittest_only_benchmark.cc b/chromium/cc/benchmarks/unittest_only_benchmark.cc index 622280b0d0e..41409e9e359 100644 --- a/chromium/cc/benchmarks/unittest_only_benchmark.cc +++ b/chromium/cc/benchmarks/unittest_only_benchmark.cc @@ -8,7 +8,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/values.h" #include "cc/benchmarks/unittest_only_benchmark_impl.h" #include "third_party/abseil-cpp/absl/types/optional.h" diff --git a/chromium/cc/benchmarks/unittest_only_benchmark.h b/chromium/cc/benchmarks/unittest_only_benchmark.h index 3e63e004c9a..b17710be1ac 100644 --- a/chromium/cc/benchmarks/unittest_only_benchmark.h +++ b/chromium/cc/benchmarks/unittest_only_benchmark.h @@ -8,7 +8,7 @@ #include <memory> #include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "cc/benchmarks/micro_benchmark.h" namespace cc { diff --git a/chromium/cc/benchmarks/unittest_only_benchmark_impl.cc b/chromium/cc/benchmarks/unittest_only_benchmark_impl.cc index d3dc343e931..d194f1ef339 100644 --- a/chromium/cc/benchmarks/unittest_only_benchmark_impl.cc +++ b/chromium/cc/benchmarks/unittest_only_benchmark_impl.cc @@ -6,7 +6,7 @@ #include <utility> -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/values.h" namespace cc { diff --git a/chromium/cc/cc.gni b/chromium/cc/cc.gni index 4f1ba6ad82e..d731f680dbc 100644 --- a/chromium/cc/cc.gni +++ b/chromium/cc/cc.gni @@ -7,7 +7,6 @@ import("//testing/test.gni") cc_remove_configs = [] cc_add_configs = [ "//build/config:precompiled_headers", - "//build/config/compiler:noshadowing", "//build/config/compiler:wexit_time_destructors", ] diff --git a/chromium/cc/document_transition/document_transition_request.cc b/chromium/cc/document_transition/document_transition_request.cc index 0d7704f791a..6edeb57d55b 100644 --- a/chromium/cc/document_transition/document_transition_request.cc +++ b/chromium/cc/document_transition/document_transition_request.cc @@ -12,6 +12,7 @@ #include <vector> #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/memory/ptr_util.h" #include "cc/document_transition/document_transition_shared_element_id.h" #include "components/viz/common/quads/compositor_frame_transition_directive.h" @@ -26,6 +27,10 @@ std::string TypeToString(viz::CompositorFrameTransitionDirective::Type type) { return "kSave"; case viz::CompositorFrameTransitionDirective::Type::kAnimate: return "kAnimate"; + case viz::CompositorFrameTransitionDirective::Type::kAnimateRenderer: + return "kAnimateRenderer"; + case viz::CompositorFrameTransitionDirective::Type::kRelease: + return "kRelease"; } return "<unknown>"; } @@ -87,6 +92,20 @@ DocumentTransitionRequest::CreateStart(uint32_t document_tag, document_tag, shared_element_count, std::move(commit_callback))); } +// static +std::unique_ptr<DocumentTransitionRequest> +DocumentTransitionRequest::CreateAnimateRenderer(uint32_t document_tag) { + return base::WrapUnique( + new DocumentTransitionRequest(Type::kAnimateRenderer, document_tag)); +} + +// static +std::unique_ptr<DocumentTransitionRequest> +DocumentTransitionRequest::CreateRelease(uint32_t document_tag) { + return base::WrapUnique( + new DocumentTransitionRequest(Type::kRelease, document_tag)); +} + DocumentTransitionRequest::DocumentTransitionRequest( Effect effect, uint32_t document_tag, @@ -112,12 +131,19 @@ DocumentTransitionRequest::DocumentTransitionRequest( commit_callback_(std::move(commit_callback)), sequence_id_(s_next_sequence_id_++) {} +DocumentTransitionRequest::DocumentTransitionRequest(Type type, + uint32_t document_tag) + : type_(type), + document_tag_(document_tag), + shared_element_count_(0u), + commit_callback_(base::DoNothing()), + sequence_id_(s_next_sequence_id_++) {} + DocumentTransitionRequest::~DocumentTransitionRequest() = default; viz::CompositorFrameTransitionDirective DocumentTransitionRequest::ConstructDirective( - const std::map<DocumentTransitionSharedElementId, - viz::CompositorRenderPassId>& + const std::map<DocumentTransitionSharedElementId, SharedElementInfo>& shared_element_render_pass_id_map) const { std::vector<viz::CompositorFrameTransitionDirective::SharedElement> shared_elements(shared_element_count_); @@ -134,12 +160,13 @@ DocumentTransitionRequest::ConstructDirective( shared_element_render_pass_id_map.begin(), shared_element_render_pass_id_map.end(), [this, i](const std::pair<const DocumentTransitionSharedElementId, - viz::CompositorRenderPassId>& value) { + SharedElementInfo>& value) { return value.first.Matches(document_tag_, i); }); if (it == shared_element_render_pass_id_map.end()) continue; - shared_elements[i].render_pass_id = it->second; + shared_elements[i].render_pass_id = it->second.render_pass_id; + shared_elements[i].shared_element_resource_id = it->second.resource_id; } return viz::CompositorFrameTransitionDirective( sequence_id_, type_, effect_, root_config_, std::move(shared_elements)); @@ -153,4 +180,7 @@ std::string DocumentTransitionRequest::ToString() const { return str.str(); } +DocumentTransitionRequest::SharedElementInfo::SharedElementInfo() = default; +DocumentTransitionRequest::SharedElementInfo::~SharedElementInfo() = default; + } // namespace cc diff --git a/chromium/cc/document_transition/document_transition_request.h b/chromium/cc/document_transition/document_transition_request.h index d0ef15b84a8..4d114b366a2 100644 --- a/chromium/cc/document_transition/document_transition_request.h +++ b/chromium/cc/document_transition/document_transition_request.h @@ -42,6 +42,14 @@ class CC_EXPORT DocumentTransitionRequest { uint32_t shared_element_count, base::OnceClosure commit_callback); + // Creates a Type::kAnimateRenderer type of request. + static std::unique_ptr<DocumentTransitionRequest> CreateAnimateRenderer( + uint32_t document_tag); + + // Creates a Type::kRelease type of request. + static std::unique_ptr<DocumentTransitionRequest> CreateRelease( + uint32_t document_tag); + DocumentTransitionRequest(DocumentTransitionRequest&) = delete; ~DocumentTransitionRequest(); @@ -55,12 +63,18 @@ class CC_EXPORT DocumentTransitionRequest { return std::move(commit_callback_); } + struct CC_EXPORT SharedElementInfo { + SharedElementInfo(); + ~SharedElementInfo(); + + viz::CompositorRenderPassId render_pass_id; + viz::SharedElementResourceId resource_id; + }; // This constructs a viz directive. Note that repeated calls to this function // would create a new sequence id for the directive, which means it would be // processed again by viz. viz::CompositorFrameTransitionDirective ConstructDirective( - const std::map<DocumentTransitionSharedElementId, - viz::CompositorRenderPassId>& + const std::map<DocumentTransitionSharedElementId, SharedElementInfo>& shared_element_render_pass_id_map) const; // Returns the sequence id for this request. @@ -77,9 +91,10 @@ class CC_EXPORT DocumentTransitionRequest { TransitionConfig root_config, std::vector<TransitionConfig> shared_element_config, base::OnceClosure commit_callback); - explicit DocumentTransitionRequest(uint32_t document_tag, - uint32_t shared_element_count, - base::OnceClosure commit_callback); + DocumentTransitionRequest(uint32_t document_tag, + uint32_t shared_element_count, + base::OnceClosure commit_callback); + DocumentTransitionRequest(Type type, uint32_t document_tag); const Type type_; const Effect effect_ = Effect::kNone; diff --git a/chromium/cc/input/browser_controls_offset_manager.h b/chromium/cc/input/browser_controls_offset_manager.h index 21d762304cc..ab5448abe55 100644 --- a/chromium/cc/input/browser_controls_offset_manager.h +++ b/chromium/cc/input/browser_controls_offset_manager.h @@ -8,6 +8,7 @@ #include <memory> #include <utility> +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/input/browser_controls_state.h" #include "cc/layers/layer_impl.h" @@ -130,7 +131,7 @@ class CC_EXPORT BrowserControlsOffsetManager { void SetBottomMinHeightOffsetAnimationRange(float from, float to); // The client manages the lifecycle of this. - BrowserControlsOffsetManagerClient* client_; + raw_ptr<BrowserControlsOffsetManagerClient> client_; BrowserControlsState permitted_state_; diff --git a/chromium/cc/input/browser_controls_offset_manager_client.h b/chromium/cc/input/browser_controls_offset_manager_client.h index 4a4842daa12..eb257641bfc 100644 --- a/chromium/cc/input/browser_controls_offset_manager_client.h +++ b/chromium/cc/input/browser_controls_offset_manager_client.h @@ -6,7 +6,7 @@ #define CC_INPUT_BROWSER_CONTROLS_OFFSET_MANAGER_CLIENT_H_ namespace gfx { -class Vector2dF; +class PointF; } namespace cc { @@ -21,7 +21,7 @@ class CC_EXPORT BrowserControlsOffsetManagerClient { float bottom_ratio) = 0; virtual float CurrentTopControlsShownRatio() const = 0; virtual float CurrentBottomControlsShownRatio() const = 0; - virtual gfx::Vector2dF ViewportScrollOffset() const = 0; + virtual gfx::PointF ViewportScrollOffset() const = 0; virtual void DidChangeBrowserControlsPosition() = 0; virtual bool OnlyExpandTopControlsAtPageTop() const = 0; virtual bool HaveRootScrollNode() const = 0; diff --git a/chromium/cc/input/browser_controls_offset_manager_unittest.cc b/chromium/cc/input/browser_controls_offset_manager_unittest.cc index 8761164dc43..ce295d29eff 100644 --- a/chromium/cc/input/browser_controls_offset_manager_unittest.cc +++ b/chromium/cc/input/browser_controls_offset_manager_unittest.cc @@ -38,7 +38,7 @@ class MockBrowserControlsOffsetManagerClient browser_controls_show_threshold_(browser_controls_show_threshold), browser_controls_hide_threshold_(browser_controls_hide_threshold) { active_tree_ = std::make_unique<LayerTreeImpl>( - &host_impl_, new SyncedProperty<ScaleGroup>, new SyncedBrowserControls, + &host_impl_, new SyncedScale, new SyncedBrowserControls, new SyncedBrowserControls, new SyncedElasticOverscroll); root_scroll_layer_ = LayerImpl::Create(active_tree_.get(), 1); } @@ -72,7 +72,7 @@ class MockBrowserControlsOffsetManagerClient return browser_controls_params_.only_expand_top_controls_at_page_top; } - gfx::Vector2dF ViewportScrollOffset() const override { + gfx::PointF ViewportScrollOffset() const override { return viewport_scroll_offset_; } @@ -121,12 +121,12 @@ class MockBrowserControlsOffsetManagerClient } void SetViewportScrollOffset(float x, float y) { - viewport_scroll_offset_ = gfx::Vector2dF(x, y); + viewport_scroll_offset_ = gfx::PointF(x, y); } void ScrollVerticallyBy(float dy) { gfx::Vector2dF viewport_scroll_delta = manager()->ScrollBy({0.f, dy}); - viewport_scroll_offset_.Add(viewport_scroll_delta); + viewport_scroll_offset_ += viewport_scroll_delta; } private: @@ -144,7 +144,7 @@ class MockBrowserControlsOffsetManagerClient float top_controls_shown_ratio_; float browser_controls_show_threshold_; float browser_controls_hide_threshold_; - gfx::Vector2dF viewport_scroll_offset_; + gfx::PointF viewport_scroll_offset_; }; TEST(BrowserControlsOffsetManagerTest, EnsureScrollThresholdApplied) { diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h index 8f14d393e90..4216f355229 100644 --- a/chromium/cc/input/input_handler.h +++ b/chromium/cc/input/input_handler.h @@ -17,15 +17,15 @@ #include "cc/input/touch_action.h" #include "cc/metrics/events_metrics_manager.h" #include "cc/paint/element_id.h" -#include "cc/trees/swap_promise_monitor.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "ui/events/types/scroll_input_type.h" #include "ui/events/types/scroll_types.h" +#include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/geometry/vector2d_f.h" namespace gfx { class Point; class SizeF; -class Vector2dF; } // namespace gfx namespace ui { @@ -35,6 +35,7 @@ class LatencyInfo; namespace cc { class CompositorDelegateForInput; +class LatencyInfoSwapPromiseMonitor; class ScrollElasticityHelper; enum class PointerResultType { kUnhandled = 0, kScrollbarScroll }; @@ -64,7 +65,7 @@ struct CC_EXPORT InputHandlerPointerResult { // instead of the input handler performing it as a part of handling the // pointer event (due to the latency attribution that happens at the // InputHandlerProxy level). - gfx::Vector2dF scroll_offset; + gfx::Vector2dF scroll_delta; // Used to determine which scroll_node needs to be scrolled. The primary // purpose of this is to avoid hit testing for gestures that already know @@ -92,7 +93,7 @@ struct CC_EXPORT InputHandlerScrollResult { // physical pixels depending on the use-zoom-for-dsf flag. If the currently // scrolling node is the viewport, this would be the sum of the scroll offsets // of the inner and outer node, representing the visual scroll offset. - gfx::Vector2dF current_visual_offset; + gfx::PointF current_visual_offset; }; class CC_EXPORT InputHandlerClient { @@ -107,8 +108,8 @@ class CC_EXPORT InputHandlerClient { virtual void ReconcileElasticOverscrollAndRootScroll() = 0; virtual void SetPrefersReducedMotion(bool prefers_reduced_motion) = 0; virtual void UpdateRootLayerStateForSynchronousInputHandler( - const gfx::Vector2dF& total_scroll_offset, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& total_scroll_offset, + const gfx::PointF& max_scroll_offset, const gfx::SizeF& scrollable_size, float page_scale_factor, float min_page_scale_factor, @@ -213,6 +214,13 @@ class CC_EXPORT InputHandler { // detected a case where it cannot reliably target a scroll node and needs // the main thread to perform a hit test. bool needs_main_thread_hit_test = false; + + // Used only in scroll unification. Tells the caller that we have performed + // the scroll (i.e. updated the offset in the scroll tree) on the compositor + // thread, but we will need a main thread lifecycle update + commit before + // the user will see the new pixels (for example, because the scroller does + // not have a composited layer). + bool needs_main_thread_repaint = false; }; enum class TouchStartOrMoveEventListenerType { @@ -296,7 +304,7 @@ class CC_EXPORT InputHandler { // input handler by the application (outside of input event handling). Offset // is expected in "content/page coordinates". virtual void SetSynchronousInputHandlerRootScrollOffset( - const gfx::Vector2dF& root_content_offset) = 0; + const gfx::PointF& root_content_offset) = 0; virtual void PinchGestureBegin() = 0; virtual void PinchGestureUpdate(float magnify_delta, @@ -330,12 +338,12 @@ class CC_EXPORT InputHandler { EventListenerTypeForTouchStartOrMoveAt(const gfx::Point& viewport_point, TouchAction* out_touch_action) = 0; - // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped - // LatencyInfoSwapPromiseMonitor. During the life time of the - // LatencyInfoSwapPromiseMonitor, if SetNeedsRedraw() or SetNeedsRedrawRect() - // is called on LayerTreeHostImpl, the original latency info will be turned - // into a LatencyInfoSwapPromise. - virtual std::unique_ptr<SwapPromiseMonitor> + // Calling `CreateLatencyInfoSwapPromiseMonitor()` to get a scoped + // `LatencyInfoSwapPromiseMonitor`. During the life time of the + // `LatencyInfoSwapPromiseMonitor`, if `SetNeedsRedraw()` or + // `SetNeedsRedrawRect()` is called on `LayerTreeHostImpl`, the original + // latency info will be turned into a `LatencyInfoSwapPromise`. + virtual std::unique_ptr<LatencyInfoSwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) = 0; // Returns a new instance of `EventsMetricsManager::ScopedMonitor` to monitor @@ -357,9 +365,9 @@ class CC_EXPORT InputHandler { // Called by the single-threaded UI Compositor to get or set the scroll offset // on the impl side. Returns false if |element_id| isn't in the active tree. virtual bool GetScrollOffsetForLayer(ElementId element_id, - gfx::Vector2dF* offset) = 0; + gfx::PointF* offset) = 0; virtual bool ScrollLayerTo(ElementId element_id, - const gfx::Vector2dF& offset) = 0; + const gfx::PointF& offset) = 0; virtual bool ScrollingShouldSwitchtoMainThread() = 0; @@ -371,8 +379,8 @@ class CC_EXPORT InputHandler { // Returns false if their is no position to snap to. virtual bool GetSnapFlingInfoAndSetAnimatingSnapTarget( const gfx::Vector2dF& natural_displacement_in_viewport, - gfx::Vector2dF* initial_offset, - gfx::Vector2dF* target_offset) = 0; + gfx::PointF* initial_offset, + gfx::PointF* target_offset) = 0; // |did_finish| is true if the animation reached its target position (i.e. // it wasn't aborted). diff --git a/chromium/cc/input/main_thread_scrolling_reason.h b/chromium/cc/input/main_thread_scrolling_reason.h index 0378bdac161..38444ca4ef2 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.h +++ b/chromium/cc/input/main_thread_scrolling_reason.h @@ -30,20 +30,26 @@ struct CC_EXPORT MainThreadScrollingReason { // value 0, so the 0th bit should never be used. // See also blink::RecordScrollReasonsMetric(). - // Non-transient scrolling reasons. + // Non-transient scrolling reasons. These are set on the ScrollNode. kHasBackgroundAttachmentFixedObjects = 1 << 1, kThreadedScrollingDisabled = 1 << 3, - // Style-related scrolling on main reasons. - // These *AndLCDText reasons are due to subpixel text rendering which can - // only be applied by blending glyphs with the background at a specific - // screen position; transparency and transforms break this. + // Style-related scrolling on main reasons. Subpixel (LCD) text rendering + // requires blending glyphs with the background at a specific screen + // position; transparency and transforms break this. + // These are only reported by the main-thread scroll gesture event codepath. + // After scroll unification, we report kNoScrollingLayer instead. kNonCompositedReasonsFirst = 18, kNotOpaqueForTextAndLCDText = 1 << 19, kCantPaintScrollingBackgroundAndLCDText = 1 << 20, kNonCompositedReasonsLast = 23, - // Transient scrolling reasons. These are computed for each scroll begin. + // Transient scrolling reasons. These are computed for each scroll gesture. + // When computed inside ScrollBegin, these prevent the InputHandler from + // reporting a status with SCROLL_ON_IMPL_THREAD. In other cases, the + // InputHandler is scrolling "on impl", but we report a transient main + // thread scrolling reason to UMA when we determine that some other aspect + // of handling the scroll has been (or will be) blocked on the main thread. kScrollbarScrolling = 1 << 4, kNonFastScrollableRegion = 1 << 6, kFailedHitTest = 1 << 8, diff --git a/chromium/cc/input/page_scale_animation.cc b/chromium/cc/input/page_scale_animation.cc index 5da12d9c79c..37e07c5102a 100644 --- a/chromium/cc/input/page_scale_animation.cc +++ b/chromium/cc/input/page_scale_animation.cc @@ -43,7 +43,7 @@ namespace cc { using base::TimeTicks; std::unique_ptr<PageScaleAnimation> PageScaleAnimation::Create( - const gfx::Vector2dF& start_scroll_offset, + const gfx::PointF& start_scroll_offset, float start_page_scale_factor, const gfx::SizeF& viewport_size, const gfx::SizeF& root_layer_size) { @@ -52,11 +52,10 @@ std::unique_ptr<PageScaleAnimation> PageScaleAnimation::Create( viewport_size, root_layer_size)); } -PageScaleAnimation::PageScaleAnimation( - const gfx::Vector2dF& start_scroll_offset, - float start_page_scale_factor, - const gfx::SizeF& viewport_size, - const gfx::SizeF& root_layer_size) +PageScaleAnimation::PageScaleAnimation(const gfx::PointF& start_scroll_offset, + float start_page_scale_factor, + const gfx::SizeF& viewport_size, + const gfx::SizeF& root_layer_size) : start_page_scale_factor_(start_page_scale_factor), target_page_scale_factor_(0.f), start_scroll_offset_(start_scroll_offset), @@ -69,7 +68,7 @@ PageScaleAnimation::PageScaleAnimation( PageScaleAnimation::~PageScaleAnimation() = default; -void PageScaleAnimation::ZoomTo(const gfx::Vector2dF& target_scroll_offset, +void PageScaleAnimation::ZoomTo(const gfx::PointF& target_scroll_offset, float target_page_scale_factor, double duration) { target_page_scale_factor_ = target_page_scale_factor; @@ -89,7 +88,7 @@ void PageScaleAnimation::ZoomTo(const gfx::Vector2dF& target_scroll_offset, start_anchor_ = target_anchor_; } -void PageScaleAnimation::ZoomWithAnchor(const gfx::Vector2dF& anchor, +void PageScaleAnimation::ZoomWithAnchor(const gfx::PointF& anchor, float target_page_scale_factor, double duration) { start_anchor_ = anchor; @@ -140,11 +139,11 @@ void PageScaleAnimation::InferTargetAnchorFromScrollOffsets() { } void PageScaleAnimation::ClampTargetScrollOffset() { - gfx::Vector2dF max_scroll_offset = + gfx::PointF max_scroll_offset = gfx::PointAtOffsetFromOrigin( gfx::RectF(root_layer_size_).bottom_right() - - gfx::RectF(gfx::SizeF(TargetViewportSize())).bottom_right(); + gfx::RectF(gfx::SizeF(TargetViewportSize())).bottom_right()); target_scroll_offset_.SetToMin(max_scroll_offset); - target_scroll_offset_.SetToMax(gfx::Vector2dF()); + target_scroll_offset_.SetToMax(gfx::PointF()); } gfx::SizeF PageScaleAnimation::StartViewportSize() const { @@ -168,8 +167,7 @@ void PageScaleAnimation::StartAnimation(base::TimeTicks time) { start_time_ = time; } -gfx::Vector2dF PageScaleAnimation::ScrollOffsetAtTime( - base::TimeTicks time) const { +gfx::PointF PageScaleAnimation::ScrollOffsetAtTime(base::TimeTicks time) const { DCHECK(!start_time_.is_null()); return ScrollOffsetAt(InterpAtTime(time)); } @@ -194,7 +192,7 @@ float PageScaleAnimation::InterpAtTime(base::TimeTicks monotonic_time) const { return static_cast<float>(timing_function_.Solve(normalized_time)); } -gfx::Vector2dF PageScaleAnimation::ScrollOffsetAt(float interp) const { +gfx::PointF PageScaleAnimation::ScrollOffsetAt(float interp) const { if (interp <= 0.f) return start_scroll_offset_; if (interp >= 1.f) @@ -203,9 +201,11 @@ gfx::Vector2dF PageScaleAnimation::ScrollOffsetAt(float interp) const { return AnchorAt(interp) - ViewportRelativeAnchorAt(interp); } -gfx::Vector2dF PageScaleAnimation::AnchorAt(float interp) const { +gfx::PointF PageScaleAnimation::AnchorAt(float interp) const { // Interpolate from start to target anchor in absolute space. - return InterpolateBetween(start_anchor_, target_anchor_, interp); + return gfx::PointAtOffsetFromOrigin( + InterpolateBetween(start_anchor_.OffsetFromOrigin(), + target_anchor_.OffsetFromOrigin(), interp)); } gfx::Vector2dF PageScaleAnimation::ViewportRelativeAnchorAt( diff --git a/chromium/cc/input/page_scale_animation.h b/chromium/cc/input/page_scale_animation.h index be4515a2c1e..0087e91b313 100644 --- a/chromium/cc/input/page_scale_animation.h +++ b/chromium/cc/input/page_scale_animation.h @@ -10,8 +10,9 @@ #include "base/time/time.h" #include "cc/cc_export.h" #include "ui/gfx/geometry/cubic_bezier.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_f.h" -#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -19,7 +20,7 @@ namespace cc { // Used in the CC to pass around a scale animation that hasn't yet been // initialized. struct PendingPageScaleAnimation { - PendingPageScaleAnimation(const gfx::Vector2d& target_offset, + PendingPageScaleAnimation(const gfx::Point& target_offset, bool use_anchor, float scale, const base::TimeDelta& duration) @@ -27,7 +28,7 @@ struct PendingPageScaleAnimation { use_anchor(use_anchor), scale(scale), duration(duration) {} - gfx::Vector2d target_offset; + gfx::Point target_offset; bool use_anchor; float scale; base::TimeDelta duration; @@ -45,7 +46,7 @@ class CC_EXPORT PageScaleAnimation { public: // Construct with the state at the beginning of the animation. static std::unique_ptr<PageScaleAnimation> Create( - const gfx::Vector2dF& start_scroll_offset, + const gfx::PointF& start_scroll_offset, float start_page_scale_factor, const gfx::SizeF& viewport_size, const gfx::SizeF& root_layer_size); @@ -59,7 +60,7 @@ class CC_EXPORT PageScaleAnimation { // immediately after construction to set the final scroll and page scale. // Zoom while explicitly specifying the top-left scroll position. - void ZoomTo(const gfx::Vector2dF& target_scroll_offset, + void ZoomTo(const gfx::PointF& target_scroll_offset, float target_page_scale_factor, double duration); @@ -67,7 +68,7 @@ class CC_EXPORT PageScaleAnimation { // at the same position on the physical display throughout the animation, // unless the edges of the root layer are hit. The anchor is specified // as an offset from the content layer. - void ZoomWithAnchor(const gfx::Vector2dF& anchor, + void ZoomWithAnchor(const gfx::PointF& anchor, float target_page_scale_factor, double duration); @@ -78,7 +79,7 @@ class CC_EXPORT PageScaleAnimation { // Call these functions while the animation is in progress to output the // current state. - gfx::Vector2dF ScrollOffsetAtTime(base::TimeTicks time) const; + gfx::PointF ScrollOffsetAtTime(base::TimeTicks time) const; float PageScaleFactorAtTime(base::TimeTicks time) const; bool IsAnimationCompleteAtTime(base::TimeTicks time) const; @@ -87,11 +88,11 @@ class CC_EXPORT PageScaleAnimation { base::TimeTicks start_time() const { return start_time_; } base::TimeDelta duration() const { return duration_; } base::TimeTicks end_time() const { return start_time_ + duration_; } - gfx::Vector2dF target_scroll_offset() const { return target_scroll_offset_; } + gfx::PointF target_scroll_offset() const { return target_scroll_offset_; } float target_page_scale_factor() const { return target_page_scale_factor_; } protected: - PageScaleAnimation(const gfx::Vector2dF& start_scroll_offset, + PageScaleAnimation(const gfx::PointF& start_scroll_offset, float start_page_scale_factor, const gfx::SizeF& viewport_size, const gfx::SizeF& root_layer_size); @@ -105,18 +106,18 @@ class CC_EXPORT PageScaleAnimation { gfx::SizeF TargetViewportSize() const; float InterpAtTime(base::TimeTicks time) const; gfx::SizeF ViewportSizeAt(float interp) const; - gfx::Vector2dF ScrollOffsetAt(float interp) const; - gfx::Vector2dF AnchorAt(float interp) const; + gfx::PointF ScrollOffsetAt(float interp) const; + gfx::PointF AnchorAt(float interp) const; gfx::Vector2dF ViewportRelativeAnchorAt(float interp) const; float PageScaleFactorAt(float interp) const; float start_page_scale_factor_; float target_page_scale_factor_; - gfx::Vector2dF start_scroll_offset_; - gfx::Vector2dF target_scroll_offset_; + gfx::PointF start_scroll_offset_; + gfx::PointF target_scroll_offset_; - gfx::Vector2dF start_anchor_; - gfx::Vector2dF target_anchor_; + gfx::PointF start_anchor_; + gfx::PointF target_anchor_; gfx::SizeF viewport_size_; gfx::SizeF root_layer_size_; diff --git a/chromium/cc/input/scroll_elasticity_helper.cc b/chromium/cc/input/scroll_elasticity_helper.cc index f51cce2753a..8f35f64ac80 100644 --- a/chromium/cc/input/scroll_elasticity_helper.cc +++ b/chromium/cc/input/scroll_elasticity_helper.cc @@ -4,6 +4,7 @@ #include "cc/input/scroll_elasticity_helper.h" +#include "base/memory/raw_ptr.h" #include "cc/layers/layer_impl.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" @@ -20,13 +21,13 @@ class ScrollElasticityHelperImpl : public ScrollElasticityHelper { gfx::Vector2dF StretchAmount() const override; gfx::Size ScrollBounds() const override; void SetStretchAmount(const gfx::Vector2dF& stretch_amount) override; - gfx::Vector2dF ScrollOffset() const override; - gfx::Vector2dF MaxScrollOffset() const override; + gfx::PointF ScrollOffset() const override; + gfx::PointF MaxScrollOffset() const override; void ScrollBy(const gfx::Vector2dF& delta) override; void RequestOneBeginFrame() override; private: - LayerTreeHostImpl* host_impl_; + raw_ptr<LayerTreeHostImpl> host_impl_; }; ScrollElasticityHelperImpl::ScrollElasticityHelperImpl( @@ -65,11 +66,11 @@ void ScrollElasticityHelperImpl::SetStretchAmount( host_impl_->SetFullViewportDamage(); } -gfx::Vector2dF ScrollElasticityHelperImpl::ScrollOffset() const { +gfx::PointF ScrollElasticityHelperImpl::ScrollOffset() const { return host_impl_->active_tree()->TotalScrollOffset(); } -gfx::Vector2dF ScrollElasticityHelperImpl::MaxScrollOffset() const { +gfx::PointF ScrollElasticityHelperImpl::MaxScrollOffset() const { return host_impl_->active_tree()->TotalMaxScrollOffset(); } diff --git a/chromium/cc/input/scroll_elasticity_helper.h b/chromium/cc/input/scroll_elasticity_helper.h index cf66a018c13..16aa4a8360f 100644 --- a/chromium/cc/input/scroll_elasticity_helper.h +++ b/chromium/cc/input/scroll_elasticity_helper.h @@ -6,6 +6,7 @@ #define CC_INPUT_SCROLL_ELASTICITY_HELPER_H_ #include "cc/cc_export.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -61,8 +62,8 @@ class CC_EXPORT ScrollElasticityHelper { virtual void SetStretchAmount(const gfx::Vector2dF& stretch_amount) = 0; // Functions for the scrolling of the root scroll layer. - virtual gfx::Vector2dF ScrollOffset() const = 0; - virtual gfx::Vector2dF MaxScrollOffset() const = 0; + virtual gfx::PointF ScrollOffset() const = 0; + virtual gfx::PointF MaxScrollOffset() const = 0; virtual void ScrollBy(const gfx::Vector2dF& delta) = 0; // Requests that another frame happens for the controller to continue ticking diff --git a/chromium/cc/input/scroll_snap_data.cc b/chromium/cc/input/scroll_snap_data.cc index e309e78a49e..bdf9ed53d3a 100644 --- a/chromium/cc/input/scroll_snap_data.cc +++ b/chromium/cc/input/scroll_snap_data.cc @@ -58,7 +58,7 @@ void SetOrUpdateResult(const SnapSearchResult& candidate, } const absl::optional<SnapSearchResult>& ClosestSearchResult( - const gfx::Vector2dF reference_point, + const gfx::PointF reference_point, SearchAxis axis, const absl::optional<SnapSearchResult>& a, const absl::optional<SnapSearchResult>& b) { @@ -108,22 +108,22 @@ void SnapSearchResult::Union(const SnapSearchResult& other) { } SnapContainerData::SnapContainerData() - : proximity_range_(gfx::Vector2dF(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max())) {} + : proximity_range_(gfx::PointF(std::numeric_limits<float>::max(), + std::numeric_limits<float>::max())) {} SnapContainerData::SnapContainerData(ScrollSnapType type) : scroll_snap_type_(type), - proximity_range_(gfx::Vector2dF(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max())) {} + proximity_range_(gfx::PointF(std::numeric_limits<float>::max(), + std::numeric_limits<float>::max())) {} SnapContainerData::SnapContainerData(ScrollSnapType type, const gfx::RectF& rect, - const gfx::Vector2dF& max) + const gfx::PointF& max) : scroll_snap_type_(type), rect_(rect), max_position_(max), - proximity_range_(gfx::Vector2dF(std::numeric_limits<float>::max(), - std::numeric_limits<float>::max())) {} + proximity_range_(gfx::PointF(std::numeric_limits<float>::max(), + std::numeric_limits<float>::max())) {} SnapContainerData::SnapContainerData(const SnapContainerData& other) = default; @@ -143,14 +143,14 @@ void SnapContainerData::AddSnapAreaData(SnapAreaData snap_area_data) { bool SnapContainerData::FindSnapPosition( const SnapSelectionStrategy& strategy, - gfx::Vector2dF* snap_position, + gfx::PointF* snap_position, TargetSnapAreaElementIds* target_element_ids, const ElementId& active_element_id) const { *target_element_ids = TargetSnapAreaElementIds(); if (scroll_snap_type_.is_none) return false; - gfx::Vector2dF base_position = strategy.base_position(); + gfx::PointF base_position = strategy.base_position(); SnapAxis axis = scroll_snap_type_.axis; bool should_snap_on_x = strategy.ShouldSnapOnX() && (axis == SnapAxis::kX || axis == SnapAxis::kBoth); @@ -262,7 +262,7 @@ bool SnapContainerData::FindSnapPosition( // of the corridors. bool SnapContainerData::FindSnapPositionForMutualSnap( const SnapSelectionStrategy& strategy, - gfx::Vector2dF* snap_position) const { + gfx::PointF* snap_position) const { DCHECK(strategy.ShouldSnapOnX() && strategy.ShouldSnapOnY()); bool found = false; gfx::Vector2dF smallest_distance(std::numeric_limits<float>::max(), diff --git a/chromium/cc/input/scroll_snap_data.h b/chromium/cc/input/scroll_snap_data.h index 03554295c96..f5ab4780cb1 100644 --- a/chromium/cc/input/scroll_snap_data.h +++ b/chromium/cc/input/scroll_snap_data.h @@ -198,7 +198,7 @@ class CC_EXPORT SnapContainerData { explicit SnapContainerData(ScrollSnapType type); SnapContainerData(ScrollSnapType type, const gfx::RectF& rect, - const gfx::Vector2dF& max); + const gfx::PointF& max); SnapContainerData(const SnapContainerData& other); SnapContainerData(SnapContainerData&& other); ~SnapContainerData(); @@ -221,7 +221,7 @@ class CC_EXPORT SnapContainerData { // Returns true if a snap position was found. bool FindSnapPosition(const SnapSelectionStrategy& strategy, - gfx::Vector2dF* snap_position, + gfx::PointF* snap_position, TargetSnapAreaElementIds* target_element_ids, const ElementId& active_element_id = ElementId()) const; @@ -239,13 +239,13 @@ class CC_EXPORT SnapContainerData { void set_rect(const gfx::RectF& rect) { rect_ = rect; } gfx::RectF rect() const { return rect_; } - void set_max_position(gfx::Vector2dF position) { max_position_ = position; } - gfx::Vector2dF max_position() const { return max_position_; } + void set_max_position(gfx::PointF position) { max_position_ = position; } + gfx::PointF max_position() const { return max_position_; } - void set_proximity_range(const gfx::Vector2dF& range) { + void set_proximity_range(const gfx::PointF& range) { proximity_range_ = range; } - gfx::Vector2dF proximity_range() const { return proximity_range_; } + gfx::PointF proximity_range() const { return proximity_range_; } private: // Finds the best SnapArea candidate that's optimal for the given selection @@ -278,7 +278,7 @@ class CC_EXPORT SnapContainerData { const ElementId& active_element_id) const; bool FindSnapPositionForMutualSnap(const SnapSelectionStrategy& strategy, - gfx::Vector2dF* snap_position) const; + gfx::PointF* snap_position) const; // Finds the snap area associated with the target snap area element id for the // given axis. @@ -311,11 +311,11 @@ class CC_EXPORT SnapContainerData { // The maximal scroll position of the SnapContainer, in the same coordinate // with blink's scroll position. - gfx::Vector2dF max_position_; + gfx::PointF max_position_; // A valid snap position should be within the |proximity_range_| of the // current offset on the snapping axis. - gfx::Vector2dF proximity_range_; + gfx::PointF proximity_range_; // The SnapAreaData for the snap areas in this snap container. When a scroll // happens, we iterate through the snap_area_list to find the best snap diff --git a/chromium/cc/input/scroll_snap_data_unittest.cc b/chromium/cc/input/scroll_snap_data_unittest.cc index 7fa0976fe7f..6c759cdbb86 100644 --- a/chromium/cc/input/scroll_snap_data_unittest.cc +++ b/chromium/cc/input/scroll_snap_data_unittest.cc @@ -18,14 +18,14 @@ class ScrollSnapDataTest : public testing::Test { TEST_F(ScrollSnapDataTest, StartAlignmentCalculation) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(10, 10, 200, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(10, 10, 200, 300), gfx::PointF(600, 800)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 150, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(0, 0), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(0, 0), true, true); EXPECT_TRUE( @@ -39,14 +39,14 @@ TEST_F(ScrollSnapDataTest, StartAlignmentCalculation) { TEST_F(ScrollSnapDataTest, CenterAlignmentCalculation) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(10, 10, 200, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(10, 10, 200, 300), gfx::PointF(600, 800)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kCenter), gfx::RectF(100, 150, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(0, 0), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(0, 0), true, true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -59,14 +59,14 @@ TEST_F(ScrollSnapDataTest, CenterAlignmentCalculation) { TEST_F(ScrollSnapDataTest, EndAlignmentCalculation) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(10, 10, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(10, 10, 200, 200), gfx::PointF(600, 800)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kEnd), gfx::RectF(150, 200, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(0, 0), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(0, 0), true, true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -79,14 +79,14 @@ TEST_F(ScrollSnapDataTest, EndAlignmentCalculation) { TEST_F(ScrollSnapDataTest, UnreachableSnapPositionCalculation) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(100, 100)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(100, 100)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kEnd, SnapAlignment::kStart), gfx::RectF(200, 0, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(50, 50), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(50, 50), true, true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -102,7 +102,7 @@ TEST_F(ScrollSnapDataTest, UnreachableSnapPositionCalculation) { TEST_F(ScrollSnapDataTest, FindsClosestSnapPositionIndependently) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), gfx::RectF(80, 0, 150, 150), false, ElementId(10)); @@ -116,10 +116,10 @@ TEST_F(ScrollSnapDataTest, FindsClosestSnapPositionIndependently) { container.AddSnapAreaData(snap_y_only); container.AddSnapAreaData(snap_on_both); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(100, 100), - true, true); + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(100, 100), true, + true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); EXPECT_EQ(80, snap_position.x()); @@ -131,7 +131,7 @@ TEST_F(ScrollSnapDataTest, FindsClosestSnapPositionIndependently) { TEST_F(ScrollSnapDataTest, FindsClosestSnapPositionOnAxisValueBoth) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), gfx::RectF(80, 0, 150, 150), false, ElementId(10)); @@ -145,9 +145,9 @@ TEST_F(ScrollSnapDataTest, FindsClosestSnapPositionOnAxisValueBoth) { container.AddSnapAreaData(snap_x_only); container.AddSnapAreaData(snap_y_only); container.AddSnapAreaData(snap_on_both); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(40, 120), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(40, 120), true, true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -160,7 +160,7 @@ TEST_F(ScrollSnapDataTest, FindsClosestSnapPositionOnAxisValueBoth) { TEST_F(ScrollSnapDataTest, DoesNotSnapOnNonScrolledAxis) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), gfx::RectF(80, 0, 150, 150), false, ElementId(10)); @@ -170,10 +170,10 @@ TEST_F(ScrollSnapDataTest, DoesNotSnapOnNonScrolledAxis) { container.AddSnapAreaData(snap_x_only); container.AddSnapAreaData(snap_y_only); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(100, 100), - true, false); + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(100, 100), true, + false); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); EXPECT_EQ(80, snap_position.x()); @@ -185,7 +185,7 @@ TEST_F(ScrollSnapDataTest, DoesNotSnapOnNonScrolledAxis) { TEST_F(ScrollSnapDataTest, DoesNotSnapOnNonVisibleAreas) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData snap_x_only( ScrollSnapAlign(SnapAlignment::kNone, SnapAlignment::kStart), gfx::RectF(300, 400, 100, 100), false, ElementId(10)); @@ -195,9 +195,9 @@ TEST_F(ScrollSnapDataTest, DoesNotSnapOnNonVisibleAreas) { container.AddSnapAreaData(snap_x_only); container.AddSnapAreaData(snap_y_only); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(0, 0), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(0, 0), true, true); EXPECT_FALSE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -207,7 +207,7 @@ TEST_F(ScrollSnapDataTest, DoesNotSnapOnNonVisibleAreas) { TEST_F(ScrollSnapDataTest, SnapOnClosestAxisFirstIfVisibilityConflicts) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); // Both the areas are currently visible. // However, if we snap to them on x and y independently, none is visible after @@ -227,9 +227,9 @@ TEST_F(ScrollSnapDataTest, SnapOnClosestAxisFirstIfVisibilityConflicts) { container.AddSnapAreaData(snap_y1); container.AddSnapAreaData(snap_y2); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(0, 0), true, + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(0, 0), true, true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -242,17 +242,17 @@ TEST_F(ScrollSnapDataTest, SnapOnClosestAxisFirstIfVisibilityConflicts) { TEST_F(ScrollSnapDataTest, DoesNotSnapToPositionsOutsideProximityRange) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); - container.set_proximity_range(gfx::Vector2dF(50, 50)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); + container.set_proximity_range(gfx::PointF(50, 50)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(80, 160, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = - SnapSelectionStrategy::CreateForEndPosition(gfx::Vector2dF(100, 100), - true, true); + SnapSelectionStrategy::CreateForEndPosition(gfx::PointF(100, 100), true, + true); EXPECT_TRUE( container.FindSnapPosition(*strategy, &snap_position, &target_elements)); @@ -268,15 +268,15 @@ TEST_F(ScrollSnapDataTest, DoesNotSnapToPositionsOutsideProximityRange) { TEST_F(ScrollSnapDataTest, MandatoryReturnsToCurrentIfNoValidAreaForward) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(2000, 2000)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(2000, 2000)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(600, 0, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> direction_strategy = SnapSelectionStrategy::CreateForDirection( - gfx::Vector2dF(600, 0), gfx::Vector2dF(5, 0), + gfx::PointF(600, 0), gfx::Vector2dF(5, 0), false /* use_fractional_deltas */); EXPECT_TRUE(container.FindSnapPosition(*direction_strategy, &snap_position, &target_elements)); @@ -290,7 +290,7 @@ TEST_F(ScrollSnapDataTest, MandatoryReturnsToCurrentIfNoValidAreaForward) { std::unique_ptr<SnapSelectionStrategy> end_direction_strategy = SnapSelectionStrategy::CreateForEndAndDirection( - gfx::Vector2dF(600, 0), gfx::Vector2dF(15, 15), + gfx::PointF(600, 0), gfx::Vector2dF(15, 15), false /* use_fractional_deltas */); EXPECT_TRUE(container.FindSnapPosition(*end_direction_strategy, &snap_position, &target_elements)); @@ -316,15 +316,15 @@ TEST_F(ScrollSnapDataTest, MandatoryReturnsToCurrentIfNoValidAreaForward) { TEST_F(ScrollSnapDataTest, MandatorySnapsBackwardIfNoValidAreaForward) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(2000, 2000)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(2000, 2000)); SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(600, 0, 100, 100), false, ElementId(10)); container.AddSnapAreaData(area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> direction_strategy = SnapSelectionStrategy::CreateForDirection( - gfx::Vector2dF(650, 0), gfx::Vector2dF(5, 0), + gfx::PointF(650, 0), gfx::Vector2d(5, 0), false /* use_fractional_deltas */); EXPECT_TRUE(container.FindSnapPosition(*direction_strategy, &snap_position, &target_elements)); @@ -338,7 +338,7 @@ TEST_F(ScrollSnapDataTest, MandatorySnapsBackwardIfNoValidAreaForward) { std::unique_ptr<SnapSelectionStrategy> end_direction_strategy = SnapSelectionStrategy::CreateForEndAndDirection( - gfx::Vector2dF(650, 10), gfx::Vector2dF(15, 15), + gfx::PointF(650, 10), gfx::Vector2d(15, 15), false /* use_fractional_deltas */); EXPECT_TRUE(container.FindSnapPosition(*end_direction_strategy, &snap_position, &target_elements)); @@ -364,7 +364,7 @@ TEST_F(ScrollSnapDataTest, MandatorySnapsBackwardIfNoValidAreaForward) { TEST_F(ScrollSnapDataTest, ShouldNotPassScrollSnapStopAlwaysElement) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(2000, 2000)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(2000, 2000)); SnapAreaData must_snap_1(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(200, 0, 100, 100), true, ElementId(10)); SnapAreaData must_snap_2(ScrollSnapAlign(SnapAlignment::kStart), @@ -375,11 +375,11 @@ TEST_F(ScrollSnapDataTest, ShouldNotPassScrollSnapStopAlwaysElement) { container.AddSnapAreaData(must_snap_1); container.AddSnapAreaData(must_snap_2); container.AddSnapAreaData(closer_to_target); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> end_direction_strategy = SnapSelectionStrategy::CreateForEndAndDirection( - gfx::Vector2dF(0, 0), gfx::Vector2dF(600, 0), + gfx::PointF(0, 0), gfx::Vector2d(600, 0), false /* use_fractional_deltas */); EXPECT_TRUE(container.FindSnapPosition(*end_direction_strategy, @@ -397,7 +397,7 @@ TEST_F(ScrollSnapDataTest, ShouldNotPassScrollSnapStopAlwaysElement) { TEST_F(ScrollSnapDataTest, SnapStopAlwaysOverridesCoveringSnapArea) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(600, 800)); SnapAreaData stop_area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 0, 100, 100), true, ElementId(10)); SnapAreaData covering_area(ScrollSnapAlign(SnapAlignment::kStart), @@ -406,10 +406,10 @@ TEST_F(ScrollSnapDataTest, SnapStopAlwaysOverridesCoveringSnapArea) { container.AddSnapAreaData(stop_area); container.AddSnapAreaData(covering_area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = SnapSelectionStrategy::CreateForEndAndDirection( - gfx::Vector2dF(0, 0), gfx::Vector2dF(300, 0), + gfx::PointF(0, 0), gfx::Vector2d(300, 0), false /* use_fractional_deltas */); // The fling is from (0, 0) to (300, 0), and the destination would make @@ -427,15 +427,15 @@ TEST_F(ScrollSnapDataTest, SnapStopAlwaysOverridesCoveringSnapArea) { TEST_F(ScrollSnapDataTest, SnapStopAlwaysInReverseDirection) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData stop_area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 0, 100, 100), true, ElementId(10)); container.AddSnapAreaData(stop_area); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> strategy = SnapSelectionStrategy::CreateForEndAndDirection( - gfx::Vector2dF(150, 0), gfx::Vector2dF(200, 0), + gfx::PointF(150, 0), gfx::Vector2d(200, 0), false /* use_fractional_deltas */); // The fling is from (150, 0) to (350, 0), but the snap position is in the @@ -452,7 +452,7 @@ TEST_F(ScrollSnapDataTest, SnapStopAlwaysInReverseDirection) { TEST_F(ScrollSnapDataTest, SnapStopAlwaysNotInterferingWithDirectionStrategy) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData closer_area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 0, 1, 1), false, ElementId(10)); SnapAreaData stop_area(ScrollSnapAlign(SnapAlignment::kStart), @@ -462,12 +462,12 @@ TEST_F(ScrollSnapDataTest, SnapStopAlwaysNotInterferingWithDirectionStrategy) { // The DirectionStrategy should always choose the first snap position // regardless its scroll-snap-stop value. - gfx::Vector2dF snap_position; + gfx::PointF snap_position; std::unique_ptr<SnapSelectionStrategy> direction_strategy = SnapSelectionStrategy::CreateForDirection( - gfx::Vector2dF(90, 0), gfx::Vector2dF(50, 0), + gfx::PointF(90, 0), gfx::Vector2d(50, 0), false /* use_fractional_deltas */); - snap_position = gfx::Vector2dF(); + snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*direction_strategy, &snap_position, &target_elements)); EXPECT_EQ(100, snap_position.x()); @@ -479,7 +479,7 @@ TEST_F(ScrollSnapDataTest, SnapStopAlwaysNotInterferingWithDirectionStrategy) { TEST_F(ScrollSnapDataTest, SnapToOneTargetElementOnX) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData closer_area_x(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 0, 1, 1), false, ElementId(10)); @@ -498,9 +498,9 @@ TEST_F(ScrollSnapDataTest, SnapToOneTargetElementOnX) { // should snap to the target for the x-axis. However, since the target is not // set for the y-axis, the target on the y-axis should be closer_area_y. std::unique_ptr<SnapSelectionStrategy> target_element_strategy = - SnapSelectionStrategy::CreateForTargetElement(gfx::Vector2dF(0, 0)); + SnapSelectionStrategy::CreateForTargetElement(gfx::PointF(0, 0)); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*target_element_strategy, &snap_position, &target_elements)); @@ -513,7 +513,7 @@ TEST_F(ScrollSnapDataTest, SnapToOneTargetElementOnX) { TEST_F(ScrollSnapDataTest, SnapToOneTargetElementOnY) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 200, 300), gfx::PointF(600, 800)); SnapAreaData closer_area_y(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(0, 100, 1, 1), false, ElementId(10)); @@ -532,9 +532,9 @@ TEST_F(ScrollSnapDataTest, SnapToOneTargetElementOnY) { // should snap to the target for the y-axis. However, since the target is not // set for the x-axis, the target on the x-axis should be closer_area_x. std::unique_ptr<SnapSelectionStrategy> target_element_strategy = - SnapSelectionStrategy::CreateForTargetElement(gfx::Vector2dF(0, 0)); + SnapSelectionStrategy::CreateForTargetElement(gfx::PointF(0, 0)); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*target_element_strategy, &snap_position, &target_elements)); @@ -547,7 +547,7 @@ TEST_F(ScrollSnapDataTest, SnapToOneTargetElementOnY) { TEST_F(ScrollSnapDataTest, SnapToTwoTargetElementsMutualVisible) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 300, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData target_area_x(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 200, 1, 1), false, ElementId(10)); @@ -565,9 +565,9 @@ TEST_F(ScrollSnapDataTest, SnapToTwoTargetElementsMutualVisible) { // The container should snap to both target areas since they are mutually // visible, while ignoring the snap area that is closest to the scroll offset. std::unique_ptr<SnapSelectionStrategy> target_element_strategy = - SnapSelectionStrategy::CreateForTargetElement(gfx::Vector2dF(0, 0)); + SnapSelectionStrategy::CreateForTargetElement(gfx::PointF(0, 0)); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*target_element_strategy, &snap_position, &target_elements)); @@ -580,7 +580,7 @@ TEST_F(ScrollSnapDataTest, SnapToTwoTargetElementsMutualVisible) { TEST_F(ScrollSnapDataTest, SnapToTwoTargetElementsNotMutualVisible) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 300, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData target_area_x(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(100, 500, 1, 1), false, ElementId(10)); @@ -600,9 +600,9 @@ TEST_F(ScrollSnapDataTest, SnapToTwoTargetElementsNotMutualVisible) { // closer to the scroll offset, and then snap to the closest mutually visible // snap area on the other axis. std::unique_ptr<SnapSelectionStrategy> target_element_strategy = - SnapSelectionStrategy::CreateForTargetElement(gfx::Vector2dF(10, 0)); + SnapSelectionStrategy::CreateForTargetElement(gfx::PointF(10, 0)); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*target_element_strategy, &snap_position, &target_elements)); @@ -615,7 +615,7 @@ TEST_F(ScrollSnapDataTest, SnapToTwoTargetElementsNotMutualVisible) { TEST_F(ScrollSnapDataTest, SnapToFocusedElementHorizontal) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kX, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 300, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData snapped_area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(0, 0, 100, 100), false, ElementId(10)); SnapAreaData focused_area(ScrollSnapAlign(SnapAlignment::kStart), @@ -624,11 +624,11 @@ TEST_F(ScrollSnapDataTest, SnapToFocusedElementHorizontal) { container.AddSnapAreaData(focused_area); // Initially both snap areas are horizontally aligned with the snap position. - gfx::Vector2dF origin(0, 0); + gfx::PointF origin(0, 0); std::unique_ptr<SnapSelectionStrategy> strategy = SnapSelectionStrategy::CreateForTargetElement(origin); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*strategy, &snap_position, &target_elements, ElementId(20))); EXPECT_EQ(0, snap_position.x()); @@ -647,7 +647,7 @@ TEST_F(ScrollSnapDataTest, SnapToFocusedElementHorizontal) { TEST_F(ScrollSnapDataTest, SnapToFocusedElementVertical) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kY, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 300, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData snapped_area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(0, 0, 100, 100), false, ElementId(10)); SnapAreaData focused_area(ScrollSnapAlign(SnapAlignment::kStart), @@ -656,11 +656,11 @@ TEST_F(ScrollSnapDataTest, SnapToFocusedElementVertical) { container.AddSnapAreaData(focused_area); // Initially both snap areas are vertically aligned with the snap position. - gfx::Vector2dF origin(0, 0); + gfx::PointF origin(0, 0); std::unique_ptr<SnapSelectionStrategy> strategy = SnapSelectionStrategy::CreateForTargetElement(origin); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*strategy, &snap_position, &target_elements, ElementId(20))); EXPECT_EQ(0, snap_position.y()); @@ -679,7 +679,7 @@ TEST_F(ScrollSnapDataTest, SnapToFocusedElementVertical) { TEST_F(ScrollSnapDataTest, SnapToFocusedElementBoth) { SnapContainerData container( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 300, 300), gfx::Vector2dF(600, 800)); + gfx::RectF(0, 0, 300, 300), gfx::PointF(600, 800)); SnapAreaData snapped_area(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(0, 0, 100, 100), false, ElementId(10)); SnapAreaData focused_area(ScrollSnapAlign(SnapAlignment::kStart), @@ -688,11 +688,11 @@ TEST_F(ScrollSnapDataTest, SnapToFocusedElementBoth) { container.AddSnapAreaData(focused_area); // Initially both snap areas are coincident with the snap position. - gfx::Vector2dF origin(0, 0); + gfx::PointF origin(0, 0); std::unique_ptr<SnapSelectionStrategy> strategy = SnapSelectionStrategy::CreateForTargetElement(origin); - gfx::Vector2dF snap_position = gfx::Vector2dF(); + gfx::PointF snap_position = gfx::PointF(); EXPECT_TRUE(container.FindSnapPosition(*strategy, &snap_position, &target_elements, ElementId(20))); EXPECT_EQ(0, snap_position.x()); diff --git a/chromium/cc/input/scroll_state.h b/chromium/cc/input/scroll_state.h index 9ac9020f91c..f2a07c97548 100644 --- a/chromium/cc/input/scroll_state.h +++ b/chromium/cc/input/scroll_state.h @@ -7,8 +7,6 @@ #include "cc/cc_export.h" #include "cc/input/scroll_state_data.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { diff --git a/chromium/cc/input/scrollbar_animation_controller.h b/chromium/cc/input/scrollbar_animation_controller.h index d60e375d09c..5306f0870de 100644 --- a/chromium/cc/input/scrollbar_animation_controller.h +++ b/chromium/cc/input/scrollbar_animation_controller.h @@ -8,6 +8,7 @@ #include <memory> #include "base/cancelable_callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -134,7 +135,7 @@ class CC_EXPORT ScrollbarAnimationController { void ApplyOpacityToScrollbars(float opacity); - ScrollbarAnimationControllerClient* client_; + raw_ptr<ScrollbarAnimationControllerClient> client_; base::TimeTicks last_awaken_time_; diff --git a/chromium/cc/input/scrollbar_animation_controller_unittest.cc b/chromium/cc/input/scrollbar_animation_controller_unittest.cc index cae00b12d3e..611ea7b216e 100644 --- a/chromium/cc/input/scrollbar_animation_controller_unittest.cc +++ b/chromium/cc/input/scrollbar_animation_controller_unittest.cc @@ -4,8 +4,10 @@ #include "cc/input/scrollbar_animation_controller.h" +#include <utility> + +#include "base/memory/raw_ptr.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/trees/layer_tree_impl.h" #include "testing/gmock/include/gmock/gmock.h" @@ -53,7 +55,7 @@ class MockScrollbarAnimationControllerClient private: base::OnceClosure start_fade_; base::TimeDelta delay_; - LayerTreeHostImpl* host_impl_; + raw_ptr<LayerTreeHostImpl> host_impl_; }; class ScrollbarAnimationControllerAuraOverlayTest @@ -143,10 +145,10 @@ class ScrollbarAnimationControllerAuraOverlayTest } std::unique_ptr<ScrollbarAnimationController> scrollbar_controller_; - LayerImpl* clip_layer_; - LayerImpl* scroll_layer_; - SolidColorScrollbarLayerImpl* v_scrollbar_layer_; - SolidColorScrollbarLayerImpl* h_scrollbar_layer_; + raw_ptr<LayerImpl> clip_layer_; + raw_ptr<LayerImpl> scroll_layer_; + raw_ptr<SolidColorScrollbarLayerImpl> v_scrollbar_layer_; + raw_ptr<SolidColorScrollbarLayerImpl> h_scrollbar_layer_; NiceMock<MockScrollbarAnimationControllerClient> client_; }; @@ -170,7 +172,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, AppearOnResize) { // Make the Layer non-scrollable, scrollbar disappears. clip_layer_->SetBounds(gfx::Size(200, 200)); - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(200, 200); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 200); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); scrollbar_controller_->DidScrollUpdate(); @@ -178,7 +180,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, AppearOnResize) { // Make the layer scrollable, scrollbar appears again. clip_layer_->SetBounds(gfx::Size(100, 100)); - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(100, 100); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 100); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); scrollbar_controller_->DidScrollUpdate(); @@ -195,7 +197,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, HideOnResize) { // Shrink along X axis, horizontal scrollbar should appear. clip_layer_->SetBounds(gfx::Size(100, 200)); EXPECT_EQ(gfx::Size(100, 200), clip_layer_->bounds()); - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(100, 200); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); @@ -206,7 +208,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, HideOnResize) { // should disappear. clip_layer_->SetBounds(gfx::Size(200, 100)); EXPECT_EQ(gfx::Size(200, 100), clip_layer_->bounds()); - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(200, 100); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); @@ -1348,8 +1350,8 @@ class ScrollbarAnimationControllerAndroidTest } std::unique_ptr<ScrollbarAnimationController> scrollbar_controller_; - LayerImpl* scroll_layer_; - SolidColorScrollbarLayerImpl* scrollbar_layer_; + raw_ptr<LayerImpl> scroll_layer_; + raw_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_; base::OnceClosure start_fade_; base::TimeDelta delay_; @@ -1412,7 +1414,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { EXPECT_EQ(ScrollbarOrientation::HORIZONTAL, scrollbar_layer_->orientation()); // Shrink along X axis, horizontal scrollbar should appear. - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(100, 200); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); @@ -1421,7 +1423,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { // Shrink along Y axis and expand along X, horizontal scrollbar // should disappear. - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(200, 100); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); @@ -1435,7 +1437,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) { EXPECT_EQ(ScrollbarOrientation::VERTICAL, scrollbar_layer_->orientation()); // Shrink along X axis, vertical scrollbar should remain invisible. - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(100, 200); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); @@ -1443,7 +1445,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) { EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); // Shrink along Y axis and expand along X, vertical scrollbar should appear. - GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(200, 100); + GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100); scroll_layer_->UpdateScrollable(); UpdateActiveTreeDrawProperties(); @@ -1454,7 +1456,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) { TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableHorz) { EXPECT_EQ(ScrollbarOrientation::HORIZONTAL, scrollbar_layer_->orientation()); - GetScrollNode(scroll_layer_)->user_scrollable_horizontal = false; + GetScrollNode(scroll_layer_.get())->user_scrollable_horizontal = false; UpdateActiveTreeDrawProperties(); scrollbar_controller_->DidScrollUpdate(); @@ -1464,7 +1466,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableHorz) { TEST_F(ScrollbarAnimationControllerAndroidTest, ShowOnUserNonScrollableVert) { EXPECT_EQ(ScrollbarOrientation::HORIZONTAL, scrollbar_layer_->orientation()); - GetScrollNode(scroll_layer_)->user_scrollable_vertical = false; + GetScrollNode(scroll_layer_.get())->user_scrollable_vertical = false; UpdateActiveTreeDrawProperties(); scrollbar_controller_->DidScrollUpdate(); @@ -1475,7 +1477,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableVert) { EXPECT_EQ(ScrollbarOrientation::VERTICAL, scrollbar_layer_->orientation()); - GetScrollNode(scroll_layer_)->user_scrollable_vertical = false; + GetScrollNode(scroll_layer_.get())->user_scrollable_vertical = false; UpdateActiveTreeDrawProperties(); scrollbar_controller_->DidScrollUpdate(); @@ -1486,7 +1488,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, ShowOnUserNonScrollableHorz) { EXPECT_EQ(ScrollbarOrientation::VERTICAL, scrollbar_layer_->orientation()); - GetScrollNode(scroll_layer_)->user_scrollable_horizontal = false; + GetScrollNode(scroll_layer_.get())->user_scrollable_horizontal = false; UpdateActiveTreeDrawProperties(); scrollbar_controller_->DidScrollUpdate(); diff --git a/chromium/cc/input/scrollbar_controller.cc b/chromium/cc/input/scrollbar_controller.cc index bd18c87469c..52a2ae95093 100644 --- a/chromium/cc/input/scrollbar_controller.cc +++ b/chromium/cc/input/scrollbar_controller.cc @@ -104,7 +104,7 @@ InputHandlerPointerResult ScrollbarController::HandlePointerDown( GetScrollbarPartFromPointerDown(position_in_widget); const bool perform_jump_click_on_track = scrollbar->JumpOnTrackClick() != jump_key_modifier; - scroll_result.scroll_offset = GetScrollOffsetForScrollbarPart( + scroll_result.scroll_delta = GetScrollDeltaForScrollbarPart( scrollbar_part, perform_jump_click_on_track); last_known_pointer_position_ = position_in_widget; scrollbar_scroll_is_active_ = true; @@ -127,18 +127,18 @@ InputHandlerPointerResult ScrollbarController::HandlePointerDown( // from the track during a thumb drag. Additionally, if a thumb drag is // being initiated *after* a jump click, scroll_position_at_start_ needs // to account for that. - const float jump_click_thumb_drag_offset = + const float jump_click_thumb_drag_delta = scrollbar->orientation() == ScrollbarOrientation::HORIZONTAL - ? scroll_result.scroll_offset.x() - : scroll_result.scroll_offset.y(); + ? scroll_result.scroll_delta.x() + : scroll_result.scroll_delta.y(); drag_state_->scroll_position_at_start_ = scrollbar->current_pos() + - (perform_jump_click_on_track ? jump_click_thumb_drag_offset : 0); + (perform_jump_click_on_track ? jump_click_thumb_drag_delta : 0); drag_state_->scroller_length_at_previous_move = scrollbar->scroll_layer_length(); } - if (!scroll_result.scroll_offset.IsZero() && !perform_jump_click_on_track) { + if (!scroll_result.scroll_delta.IsZero() && !perform_jump_click_on_track) { // Thumb drag is the only scrollbar manipulation that cannot produce an // autoscroll. All other interactions like clicking on arrows/trackparts // have the potential of initiating an autoscroll (if held down for long @@ -148,7 +148,7 @@ InputHandlerPointerResult ScrollbarController::HandlePointerDown( std::make_unique<base::CancelableOnceClosure>(base::BindOnce( &ScrollbarController::StartAutoScrollAnimation, base::Unretained(this), - InitialDeltaToAutoscrollVelocity(scroll_result.scroll_offset), + InitialDeltaToAutoscrollVelocity(scroll_result.scroll_delta), scrollbar_part)); layer_tree_host_impl_->GetTaskRunner()->PostDelayedTask( FROM_HERE, cancelable_autoscroll_task_->callback(), @@ -232,7 +232,7 @@ ui::ScrollGranularity ScrollbarController::Granularity( return ui::ScrollGranularity::kScrollByPixel; } -float ScrollbarController::GetScrollDeltaForAbsoluteJump() const { +float ScrollbarController::GetScrollDistanceForAbsoluteJump() const { layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); bool clipped = false; @@ -261,12 +261,13 @@ float ScrollbarController::GetScrollDeltaForAbsoluteJump() const { ? thumb_rect.y() : thumb_rect.x(); - const float delta = + const float distance = round(std::abs(desired_thumb_origin - current_thumb_origin)); - return delta * GetScrollerToScrollbarRatio() * GetPageScaleFactorForScroll(); + return distance * GetScrollerToScrollbarRatio() * + GetPageScaleFactorForScroll(); } -float ScrollbarController::GetScrollDeltaForDragPosition( +float ScrollbarController::GetScrollDistanceForDragPosition( const gfx::PointF pointer_position_in_widget) const { const ScrollbarLayerImplBase* scrollbar = ScrollbarLayer(); // Convert the move position to scrollbar layer relative for comparison with @@ -282,14 +283,14 @@ float ScrollbarController::GetScrollDeltaForDragPosition( : scrollbar_relative_position.x() - drag_state_->drag_origin.x(); const float new_offset = pointer_delta * GetScrollerToScrollbarRatio(); - float scroll_delta = drag_state_->scroll_position_at_start_ + new_offset - - scrollbar->current_pos(); + float distance = drag_state_->scroll_position_at_start_ + new_offset - + scrollbar->current_pos(); // The scroll delta computed is layer relative. In order to scroll the // correct amount, we have to convert the delta to be unscaled (i.e. multiply // by the page scale factor), as GSU deltas are always unscaled. - scroll_delta *= GetPageScaleFactorForScroll(); - return scroll_delta; + distance *= GetPageScaleFactorForScroll(); + return distance; } // Performs hit test and prepares scroll deltas that will be used by GSU. @@ -320,7 +321,7 @@ InputHandlerPointerResult ScrollbarController::HandlePointerMove( const float delta = scrollbar->current_pos() - drag_state_->scroll_position_at_start_; scroll_result.scroll_units = ui::ScrollGranularity::kScrollByPrecisePixel; - scroll_result.scroll_offset = + scroll_result.scroll_delta = scrollbar->orientation() == ScrollbarOrientation::VERTICAL ? gfx::Vector2dF(0, -delta) : gfx::Vector2dF(-delta, 0); @@ -342,10 +343,10 @@ InputHandlerPointerResult ScrollbarController::HandlePointerMove( // valid ScrollNode. DCHECK(target_node); - float delta = GetScrollDeltaForDragPosition(position_in_widget); + float distance = GetScrollDistanceForDragPosition(position_in_widget); if (drag_state_->scroller_length_at_previous_move != scrollbar->scroll_layer_length()) { - drag_state_->scroller_displacement = delta; + drag_state_->scroller_displacement = distance; drag_state_->scroller_length_at_previous_move = scrollbar->scroll_layer_length(); @@ -356,23 +357,23 @@ InputHandlerPointerResult ScrollbarController::HandlePointerMove( // scroller expands while a thumb drag is in progress. return scroll_result; } - delta -= drag_state_->scroller_displacement; + distance -= drag_state_->scroller_displacement; // If scroll_offset can't be consumed, there's no point in continuing on. - const gfx::Vector2dF scroll_offset(scrollbar->orientation() == - ScrollbarOrientation::VERTICAL - ? gfx::Vector2dF(0, delta) - : gfx::Vector2dF(delta, 0)); - const gfx::Vector2dF clamped_scroll_offset = - ComputeClampedDelta(*target_node, scroll_offset); - - if (clamped_scroll_offset.IsZero()) + const gfx::Vector2dF scroll_delta = + scrollbar->orientation() == ScrollbarOrientation::VERTICAL + ? gfx::Vector2dF(0, distance) + : gfx::Vector2dF(distance, 0); + const gfx::Vector2dF clamped_scroll_delta = + ComputeClampedDelta(*target_node, scroll_delta); + + if (clamped_scroll_delta.IsZero()) return scroll_result; // Thumb drags have more granularity and are purely dependent on the pointer // movement. Hence we use kPrecisePixel when dragging the thumb. scroll_result.scroll_units = ui::ScrollGranularity::kScrollByPrecisePixel; - scroll_result.scroll_offset = clamped_scroll_offset; + scroll_result.scroll_delta = clamped_scroll_delta; drag_processed_for_current_frame_ = true; return scroll_result; @@ -546,13 +547,13 @@ void ScrollbarController::RecomputeAutoscrollStateIfNeeded() { // Helper to calculate the autoscroll velocity. float ScrollbarController::InitialDeltaToAutoscrollVelocity( - gfx::Vector2dF scroll_offset) const { + gfx::Vector2dF scroll_delta) const { DCHECK(captured_scrollbar_metadata_.has_value()); - const float scroll_delta = + const float delta = ScrollbarLayer()->orientation() == ScrollbarOrientation::VERTICAL - ? scroll_offset.y() - : scroll_offset.x(); - return scroll_delta * kAutoscrollMultiplier; + ? scroll_delta.y() + : scroll_delta.x(); + return delta * kAutoscrollMultiplier; } void ScrollbarController::StartAutoScrollAnimation( @@ -579,17 +580,18 @@ void ScrollbarController::StartAutoScrollAnimation( layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); float scroll_layer_length = scrollbar->scroll_layer_length(); - gfx::Vector2dF current_offset = + gfx::PointF current_offset = scroll_tree.current_scroll_offset(scroll_node->element_id); // Determine the max offset for the scroll based on the scrolling direction. // Negative scroll velocity indicates backwards scrolling whereas a positive // value indicates forwards scrolling. - const float target_offset = velocity < 0 ? 0 : scroll_layer_length; - const gfx::Vector2dF target_offset_vector = + const float target_offset_in_orientation = + velocity < 0 ? 0 : scroll_layer_length; + const gfx::PointF target_offset_2d = scrollbar->orientation() == ScrollbarOrientation::VERTICAL - ? gfx::Vector2dF(current_offset.x(), target_offset) - : gfx::Vector2dF(target_offset, current_offset.y()); + ? gfx::PointF(current_offset.x(), target_offset_in_orientation) + : gfx::PointF(target_offset_in_orientation, current_offset.y()); autoscroll_state_ = AutoScrollState(); autoscroll_state_->velocity = velocity; @@ -601,7 +603,7 @@ void ScrollbarController::StartAutoScrollAnimation( layer_tree_host_impl_->mutator_host()->ScrollAnimationAbort(); layer_tree_host_impl_->AutoScrollAnimationCreate( - *scroll_node, target_offset_vector, std::abs(velocity)); + *scroll_node, target_offset_2d, std::abs(velocity)); } // Performs hit test and prepares scroll deltas that will be used by GSE. @@ -659,7 +661,7 @@ float ScrollbarController::GetViewportLength() const { return length / GetPageScaleFactorForScroll(); } -float ScrollbarController::GetScrollDeltaForPercentBasedScroll() const { +float ScrollbarController::GetScrollDistanceForPercentBasedScroll() const { const ScrollbarLayerImplBase* scrollbar = ScrollbarLayer(); const ScrollNode* scroll_node = @@ -687,7 +689,7 @@ float ScrollbarController::GetPageScaleFactorForScroll() const { return layer_tree_host_impl_->active_tree()->page_scale_factor_for_scroll(); } -float ScrollbarController::GetScrollDeltaForScrollbarPart( +float ScrollbarController::GetScrollDistanceForScrollbarPart( const ScrollbarPart scrollbar_part, const bool jump_key_modifier) const { float scroll_delta = 0; @@ -696,7 +698,7 @@ float ScrollbarController::GetScrollDeltaForScrollbarPart( case ScrollbarPart::BACK_BUTTON: case ScrollbarPart::FORWARD_BUTTON: if (layer_tree_host_impl_->settings().percent_based_scrolling) { - scroll_delta = GetScrollDeltaForPercentBasedScroll(); + scroll_delta = GetScrollDistanceForPercentBasedScroll(); } else { scroll_delta = kPixelsPerLineStep * ScreenSpaceScaleFactor(); } @@ -704,7 +706,7 @@ float ScrollbarController::GetScrollDeltaForScrollbarPart( case ScrollbarPart::BACK_TRACK: case ScrollbarPart::FORWARD_TRACK: { if (jump_key_modifier) { - scroll_delta = GetScrollDeltaForAbsoluteJump(); + scroll_delta = GetScrollDistanceForAbsoluteJump(); break; } // TODO(savella) Use snapport length instead of viewport length to match @@ -787,33 +789,33 @@ gfx::Rect ScrollbarController::GetRectForScrollbarPart( return gfx::Rect(0, 0); } -// Determines the scroll offsets based on the ScrollbarPart and the scrollbar -// orientation. -gfx::Vector2dF ScrollbarController::GetScrollOffsetForScrollbarPart( +// Determines the scroll delta as a gfx::Vector2dF based on the ScrollbarPart +// and the scrollbar orientation. +gfx::Vector2dF ScrollbarController::GetScrollDeltaForScrollbarPart( const ScrollbarPart scrollbar_part, const bool jump_key_modifier) const { const ScrollbarLayerImplBase* scrollbar = ScrollbarLayer(); - float scroll_delta = - GetScrollDeltaForScrollbarPart(scrollbar_part, jump_key_modifier); + float distance = + GetScrollDistanceForScrollbarPart(scrollbar_part, jump_key_modifier); // See CreateScrollStateForGesture for more information on how these values // will be interpreted. if (scrollbar_part == ScrollbarPart::BACK_BUTTON) { return scrollbar->orientation() == ScrollbarOrientation::VERTICAL - ? gfx::Vector2dF(0, -scroll_delta) // Up arrow - : gfx::Vector2dF(-scroll_delta, 0); // Left arrow + ? gfx::Vector2dF(0, -distance) // Up arrow + : gfx::Vector2dF(-distance, 0); // Left arrow } else if (scrollbar_part == ScrollbarPart::FORWARD_BUTTON) { return scrollbar->orientation() == ScrollbarOrientation::VERTICAL - ? gfx::Vector2dF(0, scroll_delta) // Down arrow - : gfx::Vector2dF(scroll_delta, 0); // Right arrow + ? gfx::Vector2dF(0, distance) // Down arrow + : gfx::Vector2dF(distance, 0); // Right arrow } else if (scrollbar_part == ScrollbarPart::BACK_TRACK) { return scrollbar->orientation() == ScrollbarOrientation::VERTICAL - ? gfx::Vector2dF(0, -scroll_delta) // Track click up - : gfx::Vector2dF(-scroll_delta, 0); // Track click left + ? gfx::Vector2dF(0, -distance) // Track click up + : gfx::Vector2dF(-distance, 0); // Track click left } else if (scrollbar_part == ScrollbarPart::FORWARD_TRACK) { return scrollbar->orientation() == ScrollbarOrientation::VERTICAL - ? gfx::Vector2dF(0, scroll_delta) // Track click down - : gfx::Vector2dF(scroll_delta, 0); // Track click right + ? gfx::Vector2dF(0, distance) // Track click down + : gfx::Vector2dF(distance, 0); // Track click right } return gfx::Vector2dF(0, 0); diff --git a/chromium/cc/input/scrollbar_controller.h b/chromium/cc/input/scrollbar_controller.h index 82f0d8dc8b1..7556db794c4 100644 --- a/chromium/cc/input/scrollbar_controller.h +++ b/chromium/cc/input/scrollbar_controller.h @@ -8,6 +8,7 @@ #include <memory> #include "base/gtest_prod_util.h" +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar.h" @@ -116,6 +117,8 @@ // animation with the new scroller length is kicked off. namespace cc { +class LayerTreeHostImpl; + // This class is responsible for hit testing composited scrollbars, event // handling and creating gesture scroll deltas. class CC_EXPORT ScrollbarController { @@ -216,17 +219,12 @@ class CC_EXPORT ScrollbarController { float ScreenSpaceScaleFactor() const; // Helper to convert scroll offset to autoscroll velocity. - float InitialDeltaToAutoscrollVelocity(gfx::Vector2dF scroll_offset) const; + float InitialDeltaToAutoscrollVelocity(gfx::Vector2dF scroll_delta) const; // Returns the hit tested ScrollbarPart based on the position_in_widget. ScrollbarPart GetScrollbarPartFromPointerDown( const gfx::PointF position_in_widget) const; - // Returns scroll offsets based on which ScrollbarPart was hit tested. - gfx::Vector2dF GetScrollOffsetForScrollbarPart( - const ScrollbarPart scrollbar_part, - const bool jump_key_modifier) const; - // Clamps |scroll_delta| based on the available scrollable amount of // |target_node|. The returned delta includes the page scale factor and is // appropriate for use directly as a delta for GSU. @@ -237,8 +235,15 @@ class CC_EXPORT ScrollbarController { gfx::Rect GetRectForScrollbarPart(const ScrollbarPart scrollbar_part) const; LayerImpl* GetLayerHitByPoint(const gfx::PointF position_in_widget) const; - float GetScrollDeltaForScrollbarPart(const ScrollbarPart scrollbar_part, - const bool jump_key_modifier) const; + + // Returns scroll delta as Vector2dF based on which ScrollbarPart was hit + // tested. + gfx::Vector2dF GetScrollDeltaForScrollbarPart( + const ScrollbarPart scrollbar_part, + const bool jump_key_modifier) const; + // Returns scroll delta in the direction of the scrollbar's orientation. + float GetScrollDistanceForScrollbarPart(const ScrollbarPart scrollbar_part, + const bool jump_key_modifier) const; // Makes position_in_widget relative to the scrollbar. gfx::PointF GetScrollbarRelativePosition(const gfx::PointF position_in_widget, @@ -255,14 +260,14 @@ class CC_EXPORT ScrollbarController { // Shift (or "Option" in case of Mac) + click is expected to do a non-animated // jump to a certain offset. - float GetScrollDeltaForAbsoluteJump() const; + float GetScrollDistanceForAbsoluteJump() const; // Determines if the delta needs to be animated. ui::ScrollGranularity Granularity(const ScrollbarPart scrollbar_part, bool jump_key_modifier) const; - // Calculates the delta based on position_in_widget and drag_origin. - float GetScrollDeltaForDragPosition( + // Calculates the distance based on position_in_widget and drag_origin. + float GetScrollDistanceForDragPosition( const gfx::PointF pointer_position_in_widget) const; // Returns the ratio of the scroller length to the scrollbar length. This is @@ -271,14 +276,14 @@ class CC_EXPORT ScrollbarController { float GetViewportLength() const; - // Returns the pixel delta for a percent-based scroll of the scrollbar - float GetScrollDeltaForPercentBasedScroll() const; + // Returns the pixel distance for a percent-based scroll of the scrollbar + float GetScrollDistanceForPercentBasedScroll() const; // Returns the page scale factor (i.e. pinch zoom factor). This is relevant // for root viewport scrollbar scrolling. float GetPageScaleFactorForScroll() const; - LayerTreeHostImpl* layer_tree_host_impl_; + raw_ptr<LayerTreeHostImpl> layer_tree_host_impl_; // Used to safeguard against firing GSE without firing GSB and GSU. For // example, if mouse is pressed outside the scrollbar but released after diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning.h b/chromium/cc/input/single_scrollbar_animation_controller_thinning.h index 6f9d03db8f1..44eef269f1a 100644 --- a/chromium/cc/input/single_scrollbar_animation_controller_thinning.h +++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning.h @@ -7,6 +7,7 @@ #include <memory> +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" @@ -83,7 +84,7 @@ class CC_EXPORT SingleScrollbarAnimationControllerThinning { float max_value); void ApplyThumbThicknessScale(float thumb_thickness_scale); - ScrollbarAnimationControllerClient* client_; + raw_ptr<ScrollbarAnimationControllerClient> client_; base::TimeTicks last_awaken_time_; bool is_animating_; diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc index 42e8d68965a..78df3c94a54 100644 --- a/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc +++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc @@ -4,8 +4,8 @@ #include "cc/input/single_scrollbar_animation_controller_thinning.h" +#include "base/memory/raw_ptr.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/trees/layer_tree_impl.h" #include "testing/gmock/include/gmock/gmock.h" @@ -46,7 +46,7 @@ class MockSingleScrollbarAnimationControllerClient MOCK_METHOD0(DidChangeScrollbarVisibility, void()); private: - LayerTreeHostImpl* host_impl_; + raw_ptr<LayerTreeHostImpl> host_impl_; }; class SingleScrollbarAnimationControllerThinningTest @@ -93,7 +93,7 @@ class SingleScrollbarAnimationControllerThinningTest std::unique_ptr<SingleScrollbarAnimationControllerThinning> scrollbar_controller_; - SolidColorScrollbarLayerImpl* scrollbar_layer_; + raw_ptr<SolidColorScrollbarLayerImpl> scrollbar_layer_; NiceMock<MockSingleScrollbarAnimationControllerClient> client_; }; diff --git a/chromium/cc/input/snap_fling_controller.cc b/chromium/cc/input/snap_fling_controller.cc index 2a985d4a169..0813f90d33d 100644 --- a/chromium/cc/input/snap_fling_controller.cc +++ b/chromium/cc/input/snap_fling_controller.cc @@ -4,6 +4,7 @@ #include "cc/input/snap_fling_controller.h" +#include <utility> #include "cc/input/snap_fling_curve.h" namespace cc { @@ -49,7 +50,7 @@ bool SnapFlingController::HandleGestureScrollUpdate( gfx::Vector2dF ending_displacement = SnapFlingCurve::EstimateDisplacement(info.delta); - gfx::Vector2dF target_offset, start_offset; + gfx::PointF target_offset, start_offset; if (!client_->GetSnapFlingInfoAndSetAnimatingSnapTarget( ending_displacement, &start_offset, &target_offset)) { state_ = State::kIgnored; @@ -78,7 +79,7 @@ void SnapFlingController::Animate(base::TimeTicks time) { return; } gfx::Vector2dF snapped_delta = curve_->GetScrollDelta(time); - gfx::Vector2dF current_offset = client_->ScrollByForSnapFling(snapped_delta); + gfx::PointF current_offset = client_->ScrollByForSnapFling(snapped_delta); curve_->UpdateCurrentOffset(current_offset); client_->RequestAnimationForSnapFling(); } diff --git a/chromium/cc/input/snap_fling_controller.h b/chromium/cc/input/snap_fling_controller.h index 42658970558..91460e648e9 100644 --- a/chromium/cc/input/snap_fling_controller.h +++ b/chromium/cc/input/snap_fling_controller.h @@ -7,8 +7,10 @@ #include <memory> +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -25,9 +27,9 @@ class SnapFlingClient { public: virtual bool GetSnapFlingInfoAndSetAnimatingSnapTarget( const gfx::Vector2dF& natural_displacement, - gfx::Vector2dF* out_initial_position, - gfx::Vector2dF* out_target_position) const = 0; - virtual gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) = 0; + gfx::PointF* out_initial_position, + gfx::PointF* out_target_position) const = 0; + virtual gfx::PointF ScrollByForSnapFling(const gfx::Vector2dF& delta) = 0; virtual void ScrollEndForSnapFling(bool did_finish) = 0; virtual void RequestAnimationForSnapFling() = 0; }; @@ -98,7 +100,7 @@ class CC_EXPORT SnapFlingController { void SetActiveStateForTest() { state_ = State::kActive; } - SnapFlingClient* client_; + raw_ptr<SnapFlingClient> client_; State state_ = State::kIdle; std::unique_ptr<SnapFlingCurve> curve_; }; diff --git a/chromium/cc/input/snap_fling_controller_unittest.cc b/chromium/cc/input/snap_fling_controller_unittest.cc index e269be2f874..737e32bf79d 100644 --- a/chromium/cc/input/snap_fling_controller_unittest.cc +++ b/chromium/cc/input/snap_fling_controller_unittest.cc @@ -4,6 +4,8 @@ #include "cc/input/snap_fling_controller.h" +#include <utility> + #include "cc/input/snap_fling_curve.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,19 +18,17 @@ class MockSnapFlingClient : public SnapFlingClient { public: MOCK_CONST_METHOD3(GetSnapFlingInfoAndSetAnimatingSnapTarget, bool(const gfx::Vector2dF& natural_displacement, - gfx::Vector2dF* initial_offset, - gfx::Vector2dF* target_offset)); + gfx::PointF* initial_offset, + gfx::PointF* target_offset)); MOCK_METHOD1(ScrollEndForSnapFling, void(bool)); MOCK_METHOD0(RequestAnimationForSnapFling, void()); - MOCK_METHOD1(ScrollByForSnapFling, gfx::Vector2dF(const gfx::Vector2dF&)); + MOCK_METHOD1(ScrollByForSnapFling, gfx::PointF(const gfx::Vector2dF&)); }; class MockSnapFlingCurve : public SnapFlingCurve { public: MockSnapFlingCurve() - : SnapFlingCurve(gfx::Vector2dF(), - gfx::Vector2dF(0, 100), - base::TimeTicks()) {} + : SnapFlingCurve(gfx::PointF(), gfx::PointF(0, 100), base::TimeTicks()) {} MOCK_CONST_METHOD0(IsFinished, bool()); MOCK_METHOD1(GetScrollDelta, gfx::Vector2dF(base::TimeTicks)); }; @@ -77,10 +77,9 @@ TEST_F(SnapFlingControllerTest, CreatesAndAnimatesCurveOnFirstInertialGSU) { EXPECT_CALL(mock_client_, GetSnapFlingInfoAndSetAnimatingSnapTarget( testing::_, testing::_, testing::_)) - .WillOnce( - testing::DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)), - testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)), - testing::Return(true))); + .WillOnce(testing::DoAll(testing::SetArgPointee<1>(gfx::PointF(0, 0)), + testing::SetArgPointee<2>(gfx::PointF(0, 100)), + testing::Return(true))); EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1); EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(1); EXPECT_TRUE(controller_->HandleGestureScrollUpdate(gsu)); diff --git a/chromium/cc/input/snap_fling_curve.cc b/chromium/cc/input/snap_fling_curve.cc index 789de15ebda..8ca9c179e12 100644 --- a/chromium/cc/input/snap_fling_curve.cc +++ b/chromium/cc/input/snap_fling_curve.cc @@ -57,8 +57,8 @@ gfx::Vector2dF SnapFlingCurve::EstimateDisplacement( return destination; } -SnapFlingCurve::SnapFlingCurve(const gfx::Vector2dF& start_offset, - const gfx::Vector2dF& target_offset, +SnapFlingCurve::SnapFlingCurve(const gfx::PointF& start_offset, + const gfx::PointF& target_offset, base::TimeTicks first_gsu_time) : start_offset_(start_offset), total_displacement_(target_offset - start_offset), @@ -104,7 +104,7 @@ gfx::Vector2dF SnapFlingCurve::GetScrollDelta(base::TimeTicks time_stamp) { return new_displacement - current_displacement_; } -void SnapFlingCurve::UpdateCurrentOffset(const gfx::Vector2dF& current_offset) { +void SnapFlingCurve::UpdateCurrentOffset(const gfx::PointF& current_offset) { current_displacement_ = current_offset - start_offset_; } diff --git a/chromium/cc/input/snap_fling_curve.h b/chromium/cc/input/snap_fling_curve.h index 4aad8d1ef70..cd96e2bbe94 100644 --- a/chromium/cc/input/snap_fling_curve.h +++ b/chromium/cc/input/snap_fling_curve.h @@ -18,8 +18,8 @@ class CC_EXPORT SnapFlingCurve { public: // Creates the curve based on the start offset, target offset, and the first // inertial GSU's time_stamp. - SnapFlingCurve(const gfx::Vector2dF& start_offset, - const gfx::Vector2dF& target_offset, + SnapFlingCurve(const gfx::PointF& start_offset, + const gfx::PointF& target_offset, base::TimeTicks first_gsu_time); virtual ~SnapFlingCurve(); @@ -33,7 +33,7 @@ class CC_EXPORT SnapFlingCurve { // Updates |current_displacement_|. This sync is necessary because the node // might be scrolled by other calls and the scrolls might be clamped. - void UpdateCurrentOffset(const gfx::Vector2dF& current_offset); + void UpdateCurrentOffset(const gfx::PointF& current_offset); // Returns true if the scroll has arrived at the snap destination. virtual bool IsFinished() const; @@ -45,7 +45,7 @@ class CC_EXPORT SnapFlingCurve { double GetCurrentCurveDistance(base::TimeDelta current_time); // The initial scroll offset of the scroller. - const gfx::Vector2dF start_offset_; + const gfx::PointF start_offset_; // The total displacement to the snap position. const gfx::Vector2dF total_displacement_; diff --git a/chromium/cc/input/snap_fling_curve_unittest.cc b/chromium/cc/input/snap_fling_curve_unittest.cc index 3682ded6657..62b77163bac 100644 --- a/chromium/cc/input/snap_fling_curve_unittest.cc +++ b/chromium/cc/input/snap_fling_curve_unittest.cc @@ -10,17 +10,17 @@ namespace cc { namespace test { TEST(SnapFlingCurveTest, CurveInitialization) { - SnapFlingCurve active_curve(gfx::Vector2dF(100, 100), - gfx::Vector2dF(500, 500), base::TimeTicks()); + SnapFlingCurve active_curve(gfx::PointF(100, 100), gfx::PointF(500, 500), + base::TimeTicks()); EXPECT_FALSE(active_curve.IsFinished()); - SnapFlingCurve finished_curve(gfx::Vector2dF(100, 100), - gfx::Vector2dF(100, 100), base::TimeTicks()); + SnapFlingCurve finished_curve(gfx::PointF(100, 100), gfx::PointF(100, 100), + base::TimeTicks()); EXPECT_TRUE(finished_curve.IsFinished()); } TEST(SnapFlingCurveTest, AdvanceHalfwayThrough) { - SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500), + SnapFlingCurve curve(gfx::PointF(100, 100), gfx::PointF(500, 500), base::TimeTicks()); base::TimeDelta duration = curve.duration(); gfx::Vector2dF delta1 = @@ -36,12 +36,12 @@ TEST(SnapFlingCurveTest, AdvanceHalfwayThrough) { EXPECT_EQ(delta1, delta2); EXPECT_FALSE(curve.IsFinished()); - curve.UpdateCurrentOffset(gfx::Vector2dF(100, 100) + delta1); + curve.UpdateCurrentOffset(gfx::PointF(100, 100) + delta1); EXPECT_FALSE(curve.IsFinished()); } TEST(SnapFlingCurveTest, AdvanceFullyThrough) { - SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500), + SnapFlingCurve curve(gfx::PointF(100, 100), gfx::PointF(500, 500), base::TimeTicks()); gfx::Vector2dF delta = curve.GetScrollDelta(base::TimeTicks() + curve.duration()); @@ -50,9 +50,9 @@ TEST(SnapFlingCurveTest, AdvanceFullyThrough) { } TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) { - SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500), + SnapFlingCurve curve(gfx::PointF(100, 100), gfx::PointF(500, 500), base::TimeTicks()); - curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500)); + curve.UpdateCurrentOffset(gfx::PointF(500, 500)); gfx::Vector2dF delta = curve.GetScrollDelta(base::TimeTicks()); EXPECT_EQ(gfx::Vector2dF(), delta); EXPECT_TRUE(curve.IsFinished()); @@ -63,16 +63,16 @@ TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) { } TEST(SnapFlingCurveTest, FlingFinishesWithinOnePixel) { - SnapFlingCurve curve(gfx::Vector2dF(0, 0), gfx::Vector2dF(100.5, 99.5), + SnapFlingCurve curve(gfx::PointF(0, 0), gfx::PointF(100.5, 99.5), base::TimeTicks()); EXPECT_FALSE(curve.IsFinished()); - curve.UpdateCurrentOffset(gfx::Vector2dF(99, 101)); + curve.UpdateCurrentOffset(gfx::PointF(99, 101)); // IsFinished() is updated in GetScrollDelta(). curve.GetScrollDelta(base::TimeTicks()); EXPECT_FALSE(curve.IsFinished()); - curve.UpdateCurrentOffset(gfx::Vector2dF(100, 100)); + curve.UpdateCurrentOffset(gfx::PointF(100, 100)); curve.GetScrollDelta(base::TimeTicks()); EXPECT_TRUE(curve.IsFinished()); } diff --git a/chromium/cc/input/snap_selection_strategy.cc b/chromium/cc/input/snap_selection_strategy.cc index c2b5a0187fc..3f1d659434d 100644 --- a/chromium/cc/input/snap_selection_strategy.cc +++ b/chromium/cc/input/snap_selection_strategy.cc @@ -10,7 +10,7 @@ namespace cc { std::unique_ptr<SnapSelectionStrategy> SnapSelectionStrategy::CreateForEndPosition( - const gfx::Vector2dF& current_position, + const gfx::PointF& current_position, bool scrolled_x, bool scrolled_y, SnapTargetsPrioritization prioritization) { @@ -19,7 +19,7 @@ SnapSelectionStrategy::CreateForEndPosition( } std::unique_ptr<SnapSelectionStrategy> -SnapSelectionStrategy::CreateForDirection(gfx::Vector2dF current_position, +SnapSelectionStrategy::CreateForDirection(gfx::PointF current_position, gfx::Vector2dF step, bool use_fractional_offsets, SnapStopAlwaysFilter filter) { @@ -28,7 +28,7 @@ SnapSelectionStrategy::CreateForDirection(gfx::Vector2dF current_position, } std::unique_ptr<SnapSelectionStrategy> -SnapSelectionStrategy::CreateForEndAndDirection(gfx::Vector2dF current_position, +SnapSelectionStrategy::CreateForEndAndDirection(gfx::PointF current_position, gfx::Vector2dF displacement, bool use_fractional_offsets) { return std::make_unique<EndAndDirectionStrategy>( @@ -36,7 +36,7 @@ SnapSelectionStrategy::CreateForEndAndDirection(gfx::Vector2dF current_position, } std::unique_ptr<SnapSelectionStrategy> -SnapSelectionStrategy::CreateForTargetElement(gfx::Vector2dF current_position) { +SnapSelectionStrategy::CreateForTargetElement(gfx::PointF current_position) { return std::make_unique<EndPositionStrategy>( current_position, true /* scrolled_x */, true /* scrolled_y */, SnapTargetsPrioritization::kRequire); @@ -73,11 +73,11 @@ bool EndPositionStrategy::ShouldSnapOnY() const { return scrolled_y_; } -gfx::Vector2dF EndPositionStrategy::intended_position() const { +gfx::PointF EndPositionStrategy::intended_position() const { return current_position_; } -gfx::Vector2dF EndPositionStrategy::base_position() const { +gfx::PointF EndPositionStrategy::base_position() const { return current_position_; } @@ -110,11 +110,11 @@ bool DirectionStrategy::ShouldSnapOnY() const { return step_.y() != 0; } -gfx::Vector2dF DirectionStrategy::intended_position() const { +gfx::PointF DirectionStrategy::intended_position() const { return current_position_ + step_; } -gfx::Vector2dF DirectionStrategy::base_position() const { +gfx::PointF DirectionStrategy::base_position() const { return current_position_; } @@ -184,11 +184,11 @@ bool EndAndDirectionStrategy::ShouldSnapOnY() const { return displacement_.y() != 0; } -gfx::Vector2dF EndAndDirectionStrategy::intended_position() const { +gfx::PointF EndAndDirectionStrategy::intended_position() const { return current_position_ + displacement_; } -gfx::Vector2dF EndAndDirectionStrategy::base_position() const { +gfx::PointF EndAndDirectionStrategy::base_position() const { return current_position_ + displacement_; } diff --git a/chromium/cc/input/snap_selection_strategy.h b/chromium/cc/input/snap_selection_strategy.h index 0814767f929..d2a173692b2 100644 --- a/chromium/cc/input/snap_selection_strategy.h +++ b/chromium/cc/input/snap_selection_strategy.h @@ -23,7 +23,7 @@ class CC_EXPORT SnapSelectionStrategy { SnapSelectionStrategy() = default; virtual ~SnapSelectionStrategy() = default; static std::unique_ptr<SnapSelectionStrategy> CreateForEndPosition( - const gfx::Vector2dF& current_position, + const gfx::PointF& current_position, bool scrolled_x, bool scrolled_y, SnapTargetsPrioritization prioritization = @@ -32,12 +32,12 @@ class CC_EXPORT SnapSelectionStrategy { // |use_fractional_offsets| should be true when the current position is // provided in fractional pixels. static std::unique_ptr<SnapSelectionStrategy> CreateForDirection( - gfx::Vector2dF current_position, + gfx::PointF current_position, gfx::Vector2dF step, bool use_fractional_offsets, SnapStopAlwaysFilter filter = SnapStopAlwaysFilter::kIgnore); static std::unique_ptr<SnapSelectionStrategy> CreateForEndAndDirection( - gfx::Vector2dF current_position, + gfx::PointF current_position, gfx::Vector2dF displacement, bool use_fractional_offsets); @@ -45,7 +45,7 @@ class CC_EXPORT SnapSelectionStrategy { // targets if possible, but defaults to finding the closest snap point if // the target no longer exists. static std::unique_ptr<SnapSelectionStrategy> CreateForTargetElement( - gfx::Vector2dF current_position); + gfx::PointF current_position); // Returns whether it's snappable on x or y depending on the scroll performed. virtual bool ShouldSnapOnX() const = 0; @@ -56,12 +56,12 @@ class CC_EXPORT SnapSelectionStrategy { virtual bool ShouldPrioritizeSnapTargets() const; // Returns the end position of the scroll if no snap interferes. - virtual gfx::Vector2dF intended_position() const = 0; + virtual gfx::PointF intended_position() const = 0; // Returns the scroll position from which the snap position should minimize // its distance. - virtual gfx::Vector2dF base_position() const = 0; + virtual gfx::PointF base_position() const = 0; // Returns the current scroll position of the snap container. - const gfx::Vector2dF& current_position() const { return current_position_; } + const gfx::PointF& current_position() const { return current_position_; } // Returns true if the selection strategy considers the given snap offset // valid for the current axis. @@ -89,9 +89,9 @@ class CC_EXPORT SnapSelectionStrategy { virtual bool UsingFractionalOffsets() const; protected: - explicit SnapSelectionStrategy(const gfx::Vector2dF& current_position) + explicit SnapSelectionStrategy(const gfx::PointF& current_position) : current_position_(current_position) {} - const gfx::Vector2dF current_position_; + const gfx::PointF current_position_; }; // Examples for intended end position scrolls include @@ -106,7 +106,7 @@ class CC_EXPORT SnapSelectionStrategy { // * Return the end position if that makes a snap area covers the snapport. class EndPositionStrategy : public SnapSelectionStrategy { public: - EndPositionStrategy(const gfx::Vector2dF& current_position, + EndPositionStrategy(const gfx::PointF& current_position, bool scrolled_x, bool scrolled_y, SnapTargetsPrioritization snap_targets_prioritization) @@ -119,8 +119,8 @@ class EndPositionStrategy : public SnapSelectionStrategy { bool ShouldSnapOnX() const override; bool ShouldSnapOnY() const override; - gfx::Vector2dF intended_position() const override; - gfx::Vector2dF base_position() const override; + gfx::PointF intended_position() const override; + gfx::PointF base_position() const override; bool IsValidSnapPosition(SearchAxis axis, float position) const override; bool HasIntendedDirection() const override; @@ -149,7 +149,7 @@ class DirectionStrategy : public SnapSelectionStrategy { public: // |use_fractional_offsets| should be true when the current position is // provided in fractional pixels. - DirectionStrategy(const gfx::Vector2dF& current_position, + DirectionStrategy(const gfx::PointF& current_position, const gfx::Vector2dF& step, SnapStopAlwaysFilter filter, bool use_fractional_offsets) @@ -162,8 +162,8 @@ class DirectionStrategy : public SnapSelectionStrategy { bool ShouldSnapOnX() const override; bool ShouldSnapOnY() const override; - gfx::Vector2dF intended_position() const override; - gfx::Vector2dF base_position() const override; + gfx::PointF intended_position() const override; + gfx::PointF base_position() const override; bool IsValidSnapPosition(SearchAxis axis, float position) const override; bool IsValidSnapArea(SearchAxis axis, @@ -194,7 +194,7 @@ class EndAndDirectionStrategy : public SnapSelectionStrategy { public: // |use_fractional_offsets| should be true when the current position is // provided in fractional pixels. - EndAndDirectionStrategy(const gfx::Vector2dF& current_position, + EndAndDirectionStrategy(const gfx::PointF& current_position, const gfx::Vector2dF& displacement, bool use_fractional_offsets) : SnapSelectionStrategy(current_position), @@ -205,8 +205,8 @@ class EndAndDirectionStrategy : public SnapSelectionStrategy { bool ShouldSnapOnX() const override; bool ShouldSnapOnY() const override; - gfx::Vector2dF intended_position() const override; - gfx::Vector2dF base_position() const override; + gfx::PointF intended_position() const override; + gfx::PointF base_position() const override; bool IsValidSnapPosition(SearchAxis axis, float position) const override; diff --git a/chromium/cc/input/threaded_input_handler.cc b/chromium/cc/input/threaded_input_handler.cc index 26877aa22eb..9cf134a8304 100644 --- a/chromium/cc/input/threaded_input_handler.cc +++ b/chromium/cc/input/threaded_input_handler.cc @@ -14,12 +14,12 @@ #include "cc/input/snap_selection_strategy.h" #include "cc/layers/viewport.h" #include "cc/trees/compositor_commit_data.h" +#include "cc/trees/latency_info_swap_promise_monitor.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/layer_tree_settings.h" #include "cc/trees/property_tree.h" #include "cc/trees/scroll_node.h" - #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/point_f.h" @@ -124,20 +124,23 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( ClearCurrentlyScrollingNode(); ElementId target_element_id = scroll_state->target_element_id(); + ScrollTree& scroll_tree = GetScrollTree(); + bool unification_enabled = + base::FeatureList::IsEnabled(features::kScrollUnification); if (target_element_id && !scroll_state->is_main_thread_hit_tested()) { TRACE_EVENT_INSTANT0("cc", "Latched scroll node provided", TRACE_EVENT_SCOPE_THREAD); // If the caller passed in an element_id we can skip all the hit-testing // bits and provide a node straight-away. - scrolling_node = GetScrollTree().FindNodeFromElementId(target_element_id); + scrolling_node = scroll_tree.FindNodeFromElementId(target_element_id); // In unified scrolling, if we found a node we get to scroll it. - if (!base::FeatureList::IsEnabled(features::kScrollUnification)) { + if (!unification_enabled) { // We still need to confirm the targeted node exists and can scroll on // the compositor. if (scrolling_node) { - scroll_status = TryScroll(GetScrollTree(), scrolling_node); + scroll_status = TryScroll(scroll_tree, scrolling_node); if (IsMainThreadScrolling(scroll_status, scrolling_node)) scroll_on_main_thread = true; } @@ -153,8 +156,8 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( // unification is enabled and the targeted scroller comes back from a // main thread hit test. DCHECK(scroll_state->data()->is_main_thread_hit_tested); - DCHECK(base::FeatureList::IsEnabled(features::kScrollUnification)); - starting_node = GetScrollTree().FindNodeFromElementId(target_element_id); + DCHECK(unification_enabled); + starting_node = scroll_tree.FindNodeFromElementId(target_element_id); if (!starting_node) { // The main thread sent us an element_id that the compositor doesn't @@ -167,7 +170,7 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; return scroll_status; } - } else { + } else { // !target_element_id TRACE_EVENT_INSTANT0("cc", "Hit Testing for ScrollNode", TRACE_EVENT_SCOPE_THREAD); gfx::Point viewport_point(scroll_state->position_x(), @@ -176,7 +179,7 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( gfx::ScalePoint(gfx::PointF(viewport_point), compositor_delegate_.DeviceScaleFactor()); - if (base::FeatureList::IsEnabled(features::kScrollUnification)) { + if (unification_enabled) { if (scroll_state->data()->is_main_thread_hit_tested) { // The client should have discarded the scroll when the hit test came // back with an invalid element id. If we somehow get here, we should @@ -226,7 +229,7 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( } starting_node = scroll_hit_test.scroll_node; - } else { + } else { // !unification_enabled LayerImpl* layer_impl = ActiveTree().FindLayerThatIsHitByPoint(device_viewport_point); @@ -273,7 +276,7 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( if (scroll_on_main_thread) { // Under scroll unification we can request a main thread hit test, but we // should never send scrolls to the main thread. - DCHECK(!base::FeatureList::IsEnabled(features::kScrollUnification)); + DCHECK(!unification_enabled); RecordCompositorSlowScrollMetric(type, MAIN_THREAD); scroll_status.thread = InputHandler::ScrollThread::SCROLL_ON_MAIN_THREAD; @@ -308,8 +311,13 @@ InputHandler::ScrollStatus ThreadedInputHandler::ScrollBegin( MainThreadScrollingReason::kNotScrollingOnMain); DCHECK_EQ(scroll_status.thread, InputHandler::ScrollThread::SCROLL_ON_IMPL_THREAD); + DCHECK(scrolling_node); ActiveTree().SetCurrentlyScrollingNode(scrolling_node); + if (unification_enabled && + !scroll_tree.CanRealizeScrollsOnCompositor(*scrolling_node)) { + scroll_status.needs_main_thread_repaint = true; + } DidLatchToScroller(*scroll_state, type); @@ -489,7 +497,7 @@ void ThreadedInputHandler::AdjustScrollDeltaForScrollbarSnap( // properly set. Currently, track and arrow scrolls both use a direction // strategy; however, the track should be using an "end and direction" // strategy. - gfx::Vector2dF current_position = GetVisualScrollOffset(*scroll_node); + gfx::PointF current_position = GetVisualScrollOffset(*scroll_node); const SnapContainerData& data = scroll_node->snap_container_data.value(); std::unique_ptr<SnapSelectionStrategy> strategy = SnapSelectionStrategy::CreateForDirection( @@ -497,7 +505,7 @@ void ThreadedInputHandler::AdjustScrollDeltaForScrollbarSnap( gfx::Vector2dF(scroll_state->delta_x(), scroll_state->delta_y()), true); - gfx::Vector2dF snap_position; + gfx::PointF snap_position; TargetSnapAreaElementIds snap_target_ids; if (!data.FindSnapPosition(*strategy, &snap_position, &snap_target_ids)) return; @@ -551,14 +559,14 @@ void ThreadedInputHandler::RecordScrollBegin( // Otherwise, the compositor-thread is the 'scrolling thread'. // TODO(crbug.com/1060712): We should also count 'main thread' as the // 'scrolling thread' if the layer being scrolled has scroll-event handlers. - FrameSequenceMetrics::ThreadType scrolling_thread; + FrameInfo::SmoothEffectDrivingThread scrolling_thread; switch (scroll_start_state) { case ScrollBeginThreadState::kScrollingOnCompositor: - scrolling_thread = FrameSequenceMetrics::ThreadType::kCompositor; + scrolling_thread = FrameInfo::SmoothEffectDrivingThread::kCompositor; break; case ScrollBeginThreadState::kScrollingOnMain: case ScrollBeginThreadState::kScrollingOnCompositorBlockedOnMain: - scrolling_thread = FrameSequenceMetrics::ThreadType::kMain; + scrolling_thread = FrameInfo::SmoothEffectDrivingThread::kMain; break; } compositor_delegate_.GetImplDeprecated().frame_trackers().StartScrollSequence( @@ -693,7 +701,7 @@ void ThreadedInputHandler::RequestUpdateForSynchronousInputHandler() { } void ThreadedInputHandler::SetSynchronousInputHandlerRootScrollOffset( - const gfx::Vector2dF& root_content_offset) { + const gfx::PointF& root_content_offset) { TRACE_EVENT2( "cc", "ThreadedInputHandler::SetSynchronousInputHandlerRootScrollOffset", "offset_x", root_content_offset.x(), "offset_y", root_content_offset.y()); @@ -848,7 +856,7 @@ ThreadedInputHandler::EventListenerTypeForTouchStartOrMoveAt( : InputHandler::TouchStartOrMoveEventListenerType::HANDLER; } -std::unique_ptr<SwapPromiseMonitor> +std::unique_ptr<LatencyInfoSwapPromiseMonitor> ThreadedInputHandler::CreateLatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency) { return compositor_delegate_.GetImplDeprecated() @@ -879,7 +887,7 @@ void ThreadedInputHandler::DestroyScrollElasticityHelper() { } bool ThreadedInputHandler::GetScrollOffsetForLayer(ElementId element_id, - gfx::Vector2dF* offset) { + gfx::PointF* offset) { ScrollTree& scroll_tree = GetScrollTree(); ScrollNode* scroll_node = scroll_tree.FindNodeFromElementId(element_id); if (!scroll_node) @@ -889,7 +897,7 @@ bool ThreadedInputHandler::GetScrollOffsetForLayer(ElementId element_id, } bool ThreadedInputHandler::ScrollLayerTo(ElementId element_id, - const gfx::Vector2dF& offset) { + const gfx::PointF& offset) { ScrollTree& scroll_tree = GetScrollTree(); ScrollNode* scroll_node = scroll_tree.FindNodeFromElementId(element_id); if (!scroll_node) @@ -920,8 +928,8 @@ bool ThreadedInputHandler::ScrollingShouldSwitchtoMainThread() { bool ThreadedInputHandler::GetSnapFlingInfoAndSetAnimatingSnapTarget( const gfx::Vector2dF& natural_displacement_in_viewport, - gfx::Vector2dF* out_initial_position, - gfx::Vector2dF* out_target_position) { + gfx::PointF* out_initial_position, + gfx::PointF* out_target_position) { ScrollNode* scroll_node = CurrentlyScrollingNode(); if (!scroll_node || !scroll_node->snap_container_data.has_value()) return false; @@ -931,7 +939,7 @@ bool ThreadedInputHandler::GetSnapFlingInfoAndSetAnimatingSnapTarget( gfx::Vector2dF natural_displacement_in_content = gfx::ScaleVector2d(natural_displacement_in_viewport, 1.f / scale_factor); - gfx::Vector2dF current_offset = GetVisualScrollOffset(*scroll_node); + gfx::PointF current_offset = GetVisualScrollOffset(*scroll_node); *out_initial_position = current_offset; // CC side always uses fractional scroll deltas. @@ -1316,8 +1324,7 @@ InputHandler::ScrollStatus ThreadedInputHandler::TryScroll( // The a viewport node should be scrolled even if it has no scroll extent // since it'll scroll using the Viewport class which will generate browser // controls movement and overscroll delta. - gfx::Vector2dF max_scroll_offset = - scroll_tree.MaxScrollOffset(scroll_node->id); + gfx::PointF max_scroll_offset = scroll_tree.MaxScrollOffset(scroll_node->id); if (max_scroll_offset.x() <= 0 && max_scroll_offset.y() <= 0 && !GetViewport().ShouldScroll(*scroll_node)) { TRACE_EVENT0("cc", @@ -1593,9 +1600,9 @@ gfx::Vector2dF ThreadedInputHandler::ComputeScrollDelta( adjusted_scroll.Scale(1.f / scale_factor); adjusted_scroll = UserScrollableDelta(scroll_node, adjusted_scroll); - gfx::Vector2dF old_offset = + gfx::PointF old_offset = scroll_tree.current_scroll_offset(scroll_node.element_id); - gfx::Vector2dF new_offset = scroll_tree.ClampScrollOffsetToLimits( + gfx::PointF new_offset = scroll_tree.ClampScrollOffsetToLimits( old_offset + adjusted_scroll, scroll_node); return new_offset - old_offset; @@ -1666,7 +1673,7 @@ gfx::Vector2dF ThreadedInputHandler::ScrollNodeWithViewportSpaceDelta( local_scroll_delta.y(), "is_outer", scrolls_outer_viewport); // Apply the scroll delta. - gfx::Vector2dF previous_offset = + gfx::PointF previous_offset = scroll_tree.current_scroll_offset(scroll_node.element_id); scroll_tree.ScrollBy(scroll_node, local_scroll_delta, &ActiveTree()); gfx::Vector2dF scrolled = @@ -1706,7 +1713,7 @@ gfx::Vector2dF ThreadedInputHandler::ScrollNodeWithLocalDelta( float page_scale_factor = compositor_delegate_.PageScaleFactor(); ScrollTree& scroll_tree = GetScrollTree(); - gfx::Vector2dF previous_offset = + gfx::PointF previous_offset = scroll_tree.current_scroll_offset(scroll_node.element_id); gfx::Vector2dF delta = local_delta; delta.Scale(1.f / page_scale_factor); @@ -1791,12 +1798,12 @@ void ThreadedInputHandler::ScrollLatchedScroller(ScrollState* scroll_state, if (animation_updated) { // Because we updated the animation target, consume delta so we notify - // the SwapPromiseMonitor to tell it that something happened that will - // cause a swap in the future. This will happen within the scope of - // the dispatch of a gesture scroll update input event. If we don't - // notify during the handling of the input event, the LatencyInfo - // associated with the input event will not be added as a swap promise - // and we won't get any swap results. + // the `LatencyInfoSwapPromiseMonitor` to tell it that something + // happened that will cause a swap in the future. This will happen + // within the scope of the dispatch of a gesture scroll update input + // event. If we don't notify during the handling of the input event, the + // `LatencyInfo` associated with the input event will not be added as a + // swap promise and we won't get any swap results. applied_delta = delta; } else { TRACE_EVENT_INSTANT0("cc", "Didn't Update Animation", @@ -2024,7 +2031,7 @@ bool ThreadedInputHandler::SnapAtScrollEnd(SnapReason reason) { return false; SnapContainerData& data = scroll_node->snap_container_data.value(); - gfx::Vector2dF current_position = GetVisualScrollOffset(*scroll_node); + gfx::PointF current_position = GetVisualScrollOffset(*scroll_node); // You might think that if a scroll never received a scroll update we could // just drop the snap. However, if the GSB+GSE arrived while we were mid-snap @@ -2058,7 +2065,7 @@ bool ThreadedInputHandler::SnapAtScrollEnd(SnapReason reason) { did_scroll_y_for_scroll_gesture_); } - gfx::Vector2dF snap_position; + gfx::PointF snap_position; TargetSnapAreaElementIds snap_target_ids; if (!data.FindSnapPosition(*strategy, &snap_position, &snap_target_ids)) return false; @@ -2096,7 +2103,7 @@ bool ThreadedInputHandler::IsAnimatingForSnap() const { return scroll_animating_snap_target_ids_ != TargetSnapAreaElementIds(); } -gfx::Vector2dF ThreadedInputHandler::GetVisualScrollOffset( +gfx::PointF ThreadedInputHandler::GetVisualScrollOffset( const ScrollNode& scroll_node) const { if (scroll_node.scrolls_outer_viewport) return GetViewport().TotalScrollOffset(); diff --git a/chromium/cc/input/threaded_input_handler.h b/chromium/cc/input/threaded_input_handler.h index 65a908f8491..e8c9d8573e8 100644 --- a/chromium/cc/input/threaded_input_handler.h +++ b/chromium/cc/input/threaded_input_handler.h @@ -9,6 +9,7 @@ #include "base/containers/flat_set.h" #include "base/gtest_prod_util.h" +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/input/compositor_input_interfaces.h" #include "cc/input/event_listener_properties.h" @@ -31,12 +32,12 @@ class Vector2dF; namespace cc { +class LatencyInfoSwapPromiseMonitor; class LayerImpl; class ScrollbarController; class ScrollElasticityHelper; struct ScrollNode; class ScrollTree; -class SwapPromiseMonitor; class Viewport; class CC_EXPORT ThreadedInputHandler : public InputHandler, @@ -71,7 +72,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler, const gfx::PointF& viewport_point) override; void RequestUpdateForSynchronousInputHandler() override; void SetSynchronousInputHandlerRootScrollOffset( - const gfx::Vector2dF& root_content_offset) override; + const gfx::PointF& root_content_offset) override; void PinchGestureBegin() override; void PinchGestureUpdate(float magnify_delta, const gfx::Point& anchor) override; @@ -86,22 +87,21 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler, EventListenerTypeForTouchStartOrMoveAt( const gfx::Point& viewport_port, TouchAction* out_touch_action) override; - std::unique_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( - ui::LatencyInfo* latency) override; + std::unique_ptr<LatencyInfoSwapPromiseMonitor> + CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) override; std::unique_ptr<EventsMetricsManager::ScopedMonitor> GetScopedEventMetricsMonitor( EventsMetricsManager::ScopedMonitor::DoneCallback done_callback) override; ScrollElasticityHelper* CreateScrollElasticityHelper() override; void DestroyScrollElasticityHelper() override; bool GetScrollOffsetForLayer(ElementId element_id, - gfx::Vector2dF* offset) override; - bool ScrollLayerTo(ElementId element_id, - const gfx::Vector2dF& offset) override; + gfx::PointF* offset) override; + bool ScrollLayerTo(ElementId element_id, const gfx::PointF& offset) override; bool ScrollingShouldSwitchtoMainThread() override; bool GetSnapFlingInfoAndSetAnimatingSnapTarget( const gfx::Vector2dF& natural_displacement_in_viewport, - gfx::Vector2dF* out_initial_position, - gfx::Vector2dF* out_target_position) override; + gfx::PointF* out_initial_position, + gfx::PointF* out_target_position) override; void ScrollEndForSnapFling(bool did_finish) override; void NotifyInputEvent() override; bool ScrollbarScrollIsActive() override; @@ -184,7 +184,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler, // This method gets the scroll offset for a regular scroller, or the combined // visual and layout offsets of the viewport. - gfx::Vector2dF GetVisualScrollOffset(const ScrollNode& scroll_node) const; + gfx::PointF GetVisualScrollOffset(const ScrollNode& scroll_node) const; bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor); bool IsAnimatingForSnap() const; @@ -359,7 +359,7 @@ class CC_EXPORT ThreadedInputHandler : public InputHandler, // together. CompositorDelegateForInput& compositor_delegate_; - InputHandlerClient* input_handler_client_ = nullptr; + raw_ptr<InputHandlerClient> input_handler_client_ = nullptr; // An object to implement the ScrollElasticityHelper interface and // hold all state related to elasticity. May be nullptr if never requested. diff --git a/chromium/cc/layers/append_quads_data.h b/chromium/cc/layers/append_quads_data.h index 7370a25cd1d..03b6ef705ec 100644 --- a/chromium/cc/layers/append_quads_data.h +++ b/chromium/cc/layers/append_quads_data.h @@ -44,6 +44,10 @@ class CC_EXPORT AppendQuadsData { // active CompositorFrames so that this CompositorFrame can // activate. std::vector<viz::SurfaceId> activation_dependencies; + + // Indicates if any layer has SharedElementResourceIds which need to be + // swapped with actual viz::ResourceIds in the Viz process. + bool has_shared_element_resources = false; }; } // namespace cc diff --git a/chromium/cc/layers/effect_tree_layer_list_iterator.h b/chromium/cc/layers/effect_tree_layer_list_iterator.h index 577e14b5f96..1943f933ed3 100644 --- a/chromium/cc/layers/effect_tree_layer_list_iterator.h +++ b/chromium/cc/layers/effect_tree_layer_list_iterator.h @@ -5,6 +5,7 @@ #ifndef CC_LAYERS_EFFECT_TREE_LAYER_LIST_ITERATOR_H_ #define CC_LAYERS_EFFECT_TREE_LAYER_LIST_ITERATOR_H_ +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_impl.h" @@ -115,8 +116,8 @@ class CC_EXPORT EffectTreeLayerListIterator { // render surface. int lowest_common_effect_tree_ancestor_index_; - LayerTreeImpl* layer_tree_impl_; - EffectTree* effect_tree_; + raw_ptr<LayerTreeImpl> layer_tree_impl_; + raw_ptr<EffectTree> effect_tree_; }; } // namespace cc diff --git a/chromium/cc/layers/heads_up_display_layer.cc b/chromium/cc/layers/heads_up_display_layer.cc index ec59418faea..9af25650012 100644 --- a/chromium/cc/layers/heads_up_display_layer.cc +++ b/chromium/cc/layers/heads_up_display_layer.cc @@ -34,30 +34,36 @@ void HeadsUpDisplayLayer::UpdateLocationAndSize( const gfx::Size& device_viewport, float device_scale_factor) { DCHECK(IsMutationAllowed()); - gfx::Size device_viewport_in_layout_pixels = - gfx::Size(device_viewport.width() / device_scale_factor, - device_viewport.height() / device_scale_factor); + float multiplier = 1.f / (device_scale_factor * + layer_tree_host()->painted_device_scale_factor()); + gfx::Size device_viewport_in_dips = + gfx::ScaleToFlooredSize(device_viewport, multiplier); - gfx::Size bounds; + gfx::Size bounds_in_dips; // If the HUD is not displaying full-viewport rects (e.g., it is showing the // Frame Rendering Stats), use a fixed size. constexpr int kDefaultHUDSize = 256; - bounds.SetSize(kDefaultHUDSize, kDefaultHUDSize); + bounds_in_dips.SetSize(kDefaultHUDSize, kDefaultHUDSize); if (layer_tree_host()->GetDebugState().ShowDebugRects()) { - bounds = device_viewport_in_layout_pixels; + bounds_in_dips = device_viewport_in_dips; } else if (layer_tree_host()->GetDebugState().show_web_vital_metrics || layer_tree_host()->GetDebugState().show_smoothness_metrics) { // If the HUD is used to display performance metrics (which is on the right // hand side_, make sure the bounds has the correct width, with a fixed // height. - bounds.set_width(device_viewport_in_layout_pixels.width()); + bounds_in_dips.set_width(device_viewport_in_dips.width()); // Increase HUD layer height to make sure all the metrics are showing. - bounds.set_height(kDefaultHUDSize * 2); + bounds_in_dips.set_height(kDefaultHUDSize * 2); } - SetBounds(bounds); + // DIPs are layout coordinates if painted dsf is 1. If it's not 1, then layout + // coordinates are DIPs * painted dsf. + auto bounds_in_layout_space = gfx::ScaleToCeiledSize( + bounds_in_dips, layer_tree_host()->painted_device_scale_factor()); + + SetBounds(bounds_in_layout_space); } bool HeadsUpDisplayLayer::HasDrawableContent() const { @@ -85,8 +91,11 @@ void HeadsUpDisplayLayer::UpdateWebVitalMetrics( web_vital_metrics_ = std::move(web_vital_metrics); } -void HeadsUpDisplayLayer::PushPropertiesTo(LayerImpl* layer) { - Layer::PushPropertiesTo(layer); +void HeadsUpDisplayLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + Layer::PushPropertiesTo(layer, commit_state, unsafe_state); TRACE_EVENT0("cc", "HeadsUpDisplayLayer::PushPropertiesTo"); HeadsUpDisplayLayerImpl* layer_impl = static_cast<HeadsUpDisplayLayerImpl*>(layer); diff --git a/chromium/cc/layers/heads_up_display_layer.h b/chromium/cc/layers/heads_up_display_layer.h index 9d497439259..ff42893afa0 100644 --- a/chromium/cc/layers/heads_up_display_layer.h +++ b/chromium/cc/layers/heads_up_display_layer.h @@ -36,7 +36,9 @@ class CC_EXPORT HeadsUpDisplayLayer : public Layer { std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; // Layer overrides. - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; protected: HeadsUpDisplayLayer(); diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc index 0c9fbd22e2b..d90e33e2075 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl.cc @@ -13,10 +13,11 @@ #include <vector> #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "base/memory/shared_memory_mapping.h" #include "base/numerics/safe_conversions.h" -#include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" +#include "base/task/single_thread_task_runner.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" @@ -24,8 +25,10 @@ #include "cc/debug/debug_colors.h" #include "cc/metrics/dropped_frame_counter.h" #include "cc/paint/display_item_list.h" +#include "cc/paint/image_provider.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" +#include "cc/paint/paint_image_builder.h" #include "cc/paint/paint_shader.h" #include "cc/paint/record_paint_canvas.h" #include "cc/paint/skia_paint_canvas.h" @@ -163,7 +166,7 @@ class HudGpuBacking : public ResourcePool::GpuBacking { pmd->AddOwnershipEdge(buffer_dump_guid, tracing_guid, importance); } - gpu::SharedImageInterface* shared_image_interface = nullptr; + raw_ptr<gpu::SharedImageInterface> shared_image_interface = nullptr; }; class HudSoftwareBacking : public ResourcePool::SoftwareBacking { @@ -181,7 +184,7 @@ class HudSoftwareBacking : public ResourcePool::SoftwareBacking { shared_mapping.guid(), importance); } - LayerTreeFrameSink* layer_tree_frame_sink; + raw_ptr<LayerTreeFrameSink> layer_tree_frame_sink; base::WritableSharedMemoryMapping shared_mapping; }; @@ -630,7 +633,7 @@ void HeadsUpDisplayLayerImpl::DrawHudContents(PaintCanvas* canvas) { TRACE_EVENT0("cc", "DrawHudContents"); canvas->clear(SkColorSetARGB(0, 0, 0, 0)); canvas->save(); - canvas->scale(internal_contents_scale_, internal_contents_scale_); + canvas->scale(internal_contents_scale_); if (debug_state.ShowDebugRects()) { DrawDebugRects(canvas, layer_tree_impl()->debug_rect_history()); @@ -644,6 +647,11 @@ void HeadsUpDisplayLayerImpl::DrawHudContents(PaintCanvas* canvas) { return; } + // Our output should be in layout space, but all of the draw commands for the + // HUD overlays here are in dips. Scale the canvas to account for this + // difference. + canvas->scale(layer_tree_impl()->painted_device_scale_factor()); + SkRect area = SkRect::MakeXYWH(0, 0, 0, 0); if (debug_state.show_fps_counter) { @@ -660,13 +668,13 @@ void HeadsUpDisplayLayerImpl::DrawHudContents(PaintCanvas* canvas) { // For the web vital and smoothness HUD on the top right corner, if the width // of the screen is smaller than the default width of the HUD, scale it down. - if (bounds().width() < metrics_sizes.kWidth) { - double scale_to_bounds = static_cast<double>(bounds().width()) / + if (bounds_width_in_dips() < metrics_sizes.kWidth) { + double scale_to_bounds = static_cast<double>(bounds_width_in_dips()) / static_cast<double>(metrics_sizes.kWidth); canvas->scale(scale_to_bounds, scale_to_bounds); } SkRect metrics_area = SkRect::MakeXYWH( - std::max<SkScalar>(0, bounds().width() - metrics_sizes.kWidth), 0, + std::max<SkScalar>(0, bounds_width_in_dips() - metrics_sizes.kWidth), 0, metrics_sizes.kWidth, 0); if (debug_state.show_web_vital_metrics) { metrics_area = DrawWebVitalMetrics( diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h index 211915e8330..1616ef0bf2f 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.h +++ b/chromium/cc/layers/heads_up_display_layer_impl.h @@ -10,6 +10,7 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" @@ -17,6 +18,7 @@ #include "cc/resources/memory_history.h" #include "cc/resources/resource_pool.h" #include "cc/trees/debug_rect_history.h" +#include "cc/trees/layer_tree_impl.h" #include "third_party/skia/include/core/SkRefCnt.h" class SkTypeface; @@ -163,9 +165,15 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl { int top, int width) const; + int bounds_width_in_dips() const { + // bounds() is specified in layout coordinates, which is painted dsf away + // from DIPs. + return bounds().width() / layer_tree_impl()->painted_device_scale_factor(); + } + ResourcePool::InUsePoolResource in_flight_resource_; std::unique_ptr<ResourcePool> pool_; - viz::DrawQuad* current_quad_ = nullptr; + raw_ptr<viz::DrawQuad> current_quad_ = nullptr; // Used for software raster when it will be uploaded to a texture. sk_sp<SkSurface> staging_surface_; diff --git a/chromium/cc/layers/heads_up_display_unittest.cc b/chromium/cc/layers/heads_up_display_unittest.cc index 20b6f21c510..3eed236b9a0 100644 --- a/chromium/cc/layers/heads_up_display_unittest.cc +++ b/chromium/cc/layers/heads_up_display_unittest.cc @@ -97,6 +97,29 @@ class HeadsUpDisplaySizeWithFPS : public LayerTreeTest { SINGLE_AND_MULTI_THREAD_TEST_F(HeadsUpDisplaySizeWithFPS); +class HeadsUpDisplaySizeWithFPSAndZoomForDSF : public LayerTreeTest { + public: + void InitializeSettings(LayerTreeSettings* settings) override { + settings->use_painted_device_scale_factor = true; + settings->initial_debug_state.show_fps_counter = true; + } + + void SetupTree() override { + SetInitialDeviceScaleFactor(3.f); + LayerTreeTest::SetupTree(); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DidCommit() override { + ASSERT_TRUE(layer_tree_host()->hud_layer()); + EXPECT_EQ(gfx::Size(768, 768), layer_tree_host()->hud_layer()->bounds()); + EndTest(); + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(HeadsUpDisplaySizeWithFPSAndZoomForDSF); + class HeadsUpDisplaySizeWithMetrics : public LayerTreeTest { public: void InitializeSettings(LayerTreeSettings* settings) override { diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc index 609aa503bf0..b2147aff5ef 100644 --- a/chromium/cc/layers/layer.cc +++ b/chromium/cc/layers/layer.cc @@ -13,9 +13,10 @@ #include "base/atomic_sequence_num.h" #include "base/location.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram.h" -#include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" +#include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "cc/base/features.h" @@ -53,14 +54,15 @@ struct SameSizeAsLayer : public base::RefCounted<SameSizeAsLayer> { SkColor background_color; Region non_fast_scrollable_region; TouchActionRegion touch_action_region; + void* capture_bounds; Region wheel_event_region; ElementId element_id; } inputs; - void* layer_tree_inputs; + raw_ptr<void> layer_tree_inputs; int int_fields[6]; gfx::Vector2dF offset; unsigned bitfields; - void* debug_info; + raw_ptr<void> debug_info; }; static_assert(sizeof(Layer) == sizeof(SameSizeAsLayer), @@ -235,13 +237,14 @@ bool Layer::IsMutationAllowed() const { } void Layer::CaptureContent(const gfx::Rect& rect, - std::vector<NodeInfo>* content) {} + std::vector<NodeInfo>* content) const {} -sk_sp<SkPicture> Layer::GetPicture() const { +sk_sp<const SkPicture> Layer::GetPicture() const { return nullptr; } void Layer::SetParent(Layer* layer) { + DCHECK(IsMutationAllowed()); DCHECK(!layer || !layer->HasAncestor(this)); parent_ = layer; @@ -396,6 +399,7 @@ void Layer::RemoveAllChildren() { void Layer::SetChildLayerList(LayerList new_children) { DCHECK(layer_tree_host_->IsUsingLayerLists()); + DCHECK(IsMutationAllowed()); // Early out without calling |LayerTreeHost::SetNeedsFullTreeSync| if no // layer has changed. @@ -506,7 +510,7 @@ void Layer::SetSafeOpaqueBackgroundColor(SkColor background_color) { SetNeedsPushProperties(); } -SkColor Layer::SafeOpaqueBackgroundColor() const { +SkColor Layer::SafeOpaqueBackgroundColor(SkColor host_background_color) const { if (contents_opaque()) { if (!layer_tree_host_ || !layer_tree_host_->IsUsingLayerLists()) { // In layer tree mode, PropertyTreeBuilder should have calculated the safe @@ -521,7 +525,7 @@ SkColor Layer::SafeOpaqueBackgroundColor() const { // background_color() if it's not transparent, or layer_tree_host_'s // background_color(), with the alpha channel forced to be opaque. SkColor color = background_color() == SK_ColorTRANSPARENT - ? layer_tree_host_->background_color() + ? host_background_color : background_color(); return SkColorSetA(color, SK_AlphaOPAQUE); } @@ -535,6 +539,13 @@ SkColor Layer::SafeOpaqueBackgroundColor() const { return background_color(); } +SkColor Layer::SafeOpaqueBackgroundColor() const { + SkColor host_background_color = + layer_tree_host_ ? layer_tree_host_->background_color() + : layer_tree_inputs()->safe_opaque_background_color; + return SafeOpaqueBackgroundColor(host_background_color); +} + void Layer::SetMasksToBounds(bool masks_to_bounds) { DCHECK(IsPropertyChangeAllowed()); auto& inputs = EnsureLayerTreeInputs(); @@ -602,7 +613,7 @@ gfx::RectF Layer::EffectiveClipRect() { void Layer::SetMaskLayer(scoped_refptr<PictureLayer> mask_layer) { DCHECK(IsPropertyChangeAllowed()); auto& inputs = EnsureLayerTreeInputs(); - if (inputs.mask_layer == mask_layer) + if (inputs.mask_layer.get() == mask_layer) return; if (inputs.mask_layer) { DCHECK_EQ(this, inputs.mask_layer->parent()); @@ -946,7 +957,7 @@ void Layer::SetTransformOrigin(const gfx::Point3F& transform_origin) { SetNeedsCommit(); } -void Layer::SetScrollOffset(const gfx::Vector2dF& scroll_offset) { +void Layer::SetScrollOffset(const gfx::PointF& scroll_offset) { DCHECK(IsPropertyChangeAllowed()); auto& inputs = EnsureLayerTreeInputs(); @@ -962,7 +973,7 @@ void Layer::SetScrollOffset(const gfx::Vector2dF& scroll_offset) { SetNeedsCommit(); } -void Layer::SetScrollOffsetFromImplSide(const gfx::Vector2dF& scroll_offset) { +void Layer::SetScrollOffsetFromImplSide(const gfx::PointF& scroll_offset) { DCHECK(IsPropertyChangeAllowed()); // This function only gets called during a BeginMainFrame, so there // is no need to call SetNeedsUpdate here. @@ -1007,7 +1018,7 @@ void Layer::UpdatePropertyTreeScrollOffset() { } void Layer::SetDidScrollCallback( - base::RepeatingCallback<void(const gfx::Vector2dF&, const ElementId&)> + base::RepeatingCallback<void(const gfx::PointF&, const ElementId&)> callback) { EnsureLayerTreeInputs().did_scroll_callback = std::move(callback); } @@ -1108,6 +1119,19 @@ void Layer::SetTouchActionRegion(TouchActionRegion touch_action_region) { SetNeedsCommit(); } +void Layer::SetCaptureBounds(std::unique_ptr<viz::RegionCaptureBounds> bounds) { + DCHECK(IsPropertyChangeAllowed()); + if (!inputs_.capture_bounds && !bounds) + return; + + if (inputs_.capture_bounds && bounds && *inputs_.capture_bounds == *bounds) + return; + + inputs_.capture_bounds = std::move(bounds); + SetPropertyTreesNeedRebuild(); + SetNeedsCommit(); +} + void Layer::SetWheelEventRegion(Region wheel_event_region) { DCHECK(IsPropertyChangeAllowed()); if (inputs_.wheel_event_region == wheel_event_region) @@ -1162,15 +1186,25 @@ void Layer::SetTransformTreeIndex(int index) { SetNeedsPushProperties(); } -int Layer::transform_tree_index() const { - if (!layer_tree_host_ || - layer_tree_host_->property_trees()->sequence_number != - property_tree_sequence_number_) { +int Layer::transform_tree_index(const PropertyTrees& property_trees) const { + if (property_trees.sequence_number != property_tree_sequence_number_) { return TransformTree::kInvalidNodeId; } return transform_tree_index_; } +bool Layer::transform_tree_index_is_valid( + const PropertyTrees& property_trees) const { + return transform_tree_index_ != TransformTree::kInvalidNodeId && + property_trees.sequence_number == property_tree_sequence_number_; +} + +int Layer::transform_tree_index() const { + if (!IsAttached()) + return TransformTree::kInvalidNodeId; + return transform_tree_index(*layer_tree_host()->property_trees()); +} + void Layer::SetClipTreeIndex(int index) { DCHECK(IsPropertyChangeAllowed()); if (clip_tree_index_ == index) @@ -1179,15 +1213,25 @@ void Layer::SetClipTreeIndex(int index) { SetNeedsPushProperties(); } -int Layer::clip_tree_index() const { - if (!layer_tree_host_ || - layer_tree_host_->property_trees()->sequence_number != - property_tree_sequence_number_) { +int Layer::clip_tree_index(const PropertyTrees& property_trees) const { + if (property_trees.sequence_number != property_tree_sequence_number_) { return ClipTree::kInvalidNodeId; } return clip_tree_index_; } +bool Layer::clip_tree_index_is_valid( + const PropertyTrees& property_trees) const { + return clip_tree_index_ != ClipTree::kInvalidNodeId && + property_trees.sequence_number == property_tree_sequence_number_; +} + +int Layer::clip_tree_index() const { + if (!IsAttached()) + return ClipTree::kInvalidNodeId; + return clip_tree_index(*layer_tree_host()->property_trees()); +} + void Layer::SetEffectTreeIndex(int index) { DCHECK(IsPropertyChangeAllowed()); if (effect_tree_index_ == index) @@ -1196,15 +1240,25 @@ void Layer::SetEffectTreeIndex(int index) { SetNeedsPushProperties(); } -int Layer::effect_tree_index() const { - if (!layer_tree_host_ || - layer_tree_host_->property_trees()->sequence_number != - property_tree_sequence_number_) { +int Layer::effect_tree_index(const PropertyTrees& property_trees) const { + if (property_trees.sequence_number != property_tree_sequence_number_) { return EffectTree::kInvalidNodeId; } return effect_tree_index_; } +bool Layer::effect_tree_index_is_valid( + const PropertyTrees& property_trees) const { + return effect_tree_index_ != EffectTree::kInvalidNodeId && + property_trees.sequence_number == property_tree_sequence_number_; +} + +int Layer::effect_tree_index() const { + if (!IsAttached()) + return EffectTree::kInvalidNodeId; + return effect_tree_index(*layer_tree_host()->property_trees()); +} + void Layer::SetScrollTreeIndex(int index) { DCHECK(IsPropertyChangeAllowed()); if (scroll_tree_index_ == index) @@ -1213,15 +1267,25 @@ void Layer::SetScrollTreeIndex(int index) { SetNeedsPushProperties(); } -int Layer::scroll_tree_index() const { - if (!layer_tree_host_ || - layer_tree_host_->property_trees()->sequence_number != - property_tree_sequence_number_) { +int Layer::scroll_tree_index(const PropertyTrees& property_trees) const { + if (property_trees.sequence_number != property_tree_sequence_number_) { return ScrollTree::kInvalidNodeId; } return scroll_tree_index_; } +bool Layer::scroll_tree_index_is_valid( + const PropertyTrees& property_trees) const { + return scroll_tree_index_ != ScrollTree::kInvalidNodeId && + property_trees.sequence_number == property_tree_sequence_number_; +} + +int Layer::scroll_tree_index() const { + if (!IsAttached()) + return ScrollTree::kInvalidNodeId; + return scroll_tree_index(*layer_tree_host()->property_trees()); +} + void Layer::SetOffsetToTransformParent(gfx::Vector2dF offset) { if (offset_to_transform_parent_ == offset) return; @@ -1327,23 +1391,28 @@ bool Layer::IsSnappedToPixelGridInTarget() { return false; } -void Layer::PushPropertiesTo(LayerImpl* layer) { +void Layer::PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "Layer::PushPropertiesTo"); DCHECK(layer_tree_host_); + const PropertyTrees& property_trees = unsafe_state.property_trees; + // The element id should be set first because other setters may // depend on it. Referencing element id on a layer is // deprecated. http://crbug.com/709137 layer->SetElementId(inputs_.element_id); layer->SetHasTransformNode(has_transform_node_); layer->SetBackgroundColor(inputs_.background_color); - layer->SetSafeOpaqueBackgroundColor(SafeOpaqueBackgroundColor()); + layer->SetSafeOpaqueBackgroundColor( + SafeOpaqueBackgroundColor(commit_state.background_color)); layer->SetBounds(inputs_.bounds); - layer->SetTransformTreeIndex(transform_tree_index()); - layer->SetEffectTreeIndex(effect_tree_index()); - layer->SetClipTreeIndex(clip_tree_index()); - layer->SetScrollTreeIndex(scroll_tree_index()); + layer->SetTransformTreeIndex(transform_tree_index(property_trees)); + layer->SetEffectTreeIndex(effect_tree_index(property_trees)); + layer->SetClipTreeIndex(clip_tree_index(property_trees)); + layer->SetScrollTreeIndex(scroll_tree_index(property_trees)); layer->SetOffsetToTransformParent(offset_to_transform_parent_); layer->SetDrawsContent(DrawsContent()); layer->SetHitTestable(HitTestable()); @@ -1354,20 +1423,11 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->set_may_contain_video(may_contain_video_); layer->SetNonFastScrollableRegion(inputs_.non_fast_scrollable_region); layer->SetTouchActionRegion(inputs_.touch_action_region); - - // TODO(https://crbug.com/841364): This block is optimized to avoid checks - // for kWheelEventRegions. It will be simplified once kWheelEventRegions - // feature flag is removed. - EventListenerProperties mouse_wheel_props = - layer_tree_host()->event_listener_properties( - EventListenerClass::kMouseWheel); - if ((mouse_wheel_props == EventListenerProperties::kBlocking || - mouse_wheel_props == EventListenerProperties::kBlockingAndPassive) && - !base::FeatureList::IsEnabled(::features::kWheelEventRegions)) - layer->SetWheelEventHandlerRegion(Region(gfx::Rect(bounds()))); - else - layer->SetWheelEventHandlerRegion(inputs_.wheel_event_region); - + layer->SetCaptureBounds( + inputs_.capture_bounds + ? std::make_unique<viz::RegionCaptureBounds>(*inputs_.capture_bounds) + : nullptr); + layer->SetWheelEventHandlerRegion(inputs_.wheel_event_region); layer->SetContentsOpaque(inputs_.contents_opaque); layer->SetContentsOpaqueForText(inputs_.contents_opaque_for_text); layer->SetShouldCheckBackfaceVisibility(should_check_backface_visibility_); @@ -1382,7 +1442,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { // the pending tree will clobber any impl-side scrolling occuring on the // active tree. To do so, avoid scrolling the pending tree along with it // instead of trying to undo that scrolling later. - if (layer_tree_host_->mutator_host()->ScrollOffsetAnimationWasInterrupted( + if (unsafe_state.mutator_host->ScrollOffsetAnimationWasInterrupted( element_id())) { PropertyTrees* trees = layer->layer_tree_impl()->property_trees(); trees->scroll_tree.SetScrollOffsetClobberActiveValue(layer->element_id()); diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h index 516f845eb23..c6ff3c6dad5 100644 --- a/chromium/cc/layers/layer.h +++ b/chromium/cc/layers/layer.h @@ -15,6 +15,7 @@ #include "base/auto_reset.h" #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/base/region.h" #include "cc/benchmarks/micro_benchmark.h" @@ -29,9 +30,11 @@ #include "cc/trees/effect_node.h" #include "cc/trees/property_tree.h" #include "cc/trees/target_property.h" +#include "components/viz/common/surfaces/region_capture_bounds.h" #include "components/viz/common/surfaces/subtree_capture_id.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/point3_f.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rounded_corners_f.h" #include "ui/gfx/geometry/rrect_f.h" @@ -50,6 +53,9 @@ class LayerTreeHostCommon; class LayerTreeImpl; class PictureLayer; +struct CommitState; +struct ThreadUnsafeCommitState; + // For tracing and debugging. The info will be attached to this layer's tracing // output. struct CC_EXPORT LayerDebugInfo { @@ -127,11 +133,14 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // The list of children of this layer. const LayerList& children() const { return inputs_.children; } + bool IsAttached() const { return layer_tree_host_; } + // Gets the LayerTreeHost that this layer is attached to, or null if not. // A layer is attached to a LayerTreeHost if it or an ancestor layer is set as // the root layer of a LayerTreeHost (while noting only a layer without a // parent may be set as the root layer). - LayerTreeHost* layer_tree_host() const { return layer_tree_host_; } + LayerTreeHost* layer_tree_host() { return layer_tree_host_; } + const LayerTreeHost* layer_tree_host() const { return layer_tree_host_; } // This requests the layer and its subtree be rendered and given to the // callback. If the copy is unable to be produced (the layer is destroyed @@ -140,7 +149,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // same source will be aborted. void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request); // True if a copy request has been inserted on this layer and a commit has not - // occured yet. + // occurred yet. bool HasCopyRequest() const { return layer_tree_inputs() && !layer_tree_inputs()->copy_requests.empty(); } @@ -160,11 +169,15 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // If the layer says contents_opaque() is true, in layer tree mode, this // returns the value set by SetSafeOpaqueBackgroundColor() which should be an // opaque color, and in layer list mode, returns an opaque color calculated - // from background_color() and layer_tree_host()->background_clor(). + // from background_color() and the argument host_background_color. // Otherwise, it returns something non-opaque. It prefers to return the // background_color(), but if the background_color() is opaque (and this layer // claims to not be), then SK_ColorTRANSPARENT is returned to avoid intrusive // checkerboard where the layer is not covered by the background_color(). + SkColor SafeOpaqueBackgroundColor(SkColor host_background_color) const; + + // Same as the one-argument version, except that host_background_color is + // layer_tree_host()->pending_commit_state()->background_color. SkColor SafeOpaqueBackgroundColor() const; // For layer tree mode only. @@ -220,10 +233,12 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // for each matching pixel. void SetMaskLayer(scoped_refptr<PictureLayer> mask_layer); const PictureLayer* mask_layer() const { - return layer_tree_inputs() ? layer_tree_inputs()->mask_layer : nullptr; + return layer_tree_inputs() ? layer_tree_inputs()->mask_layer.get() + : nullptr; } PictureLayer* mask_layer() { - return layer_tree_inputs() ? layer_tree_inputs()->mask_layer : nullptr; + return layer_tree_inputs() ? layer_tree_inputs()->mask_layer.get() + : nullptr; } // Marks the |dirty_rect| as being changed, which will cause a commit and @@ -387,16 +402,16 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // position of its subtree, as well as other layers for which this layer is // their scroll parent, and their subtrees) is moved up by the amount of // offset specified here. - void SetScrollOffset(const gfx::Vector2dF& scroll_offset); - gfx::Vector2dF scroll_offset() const { + void SetScrollOffset(const gfx::PointF& scroll_offset); + gfx::PointF scroll_offset() const { return layer_tree_inputs() ? layer_tree_inputs()->scroll_offset - : gfx::Vector2dF(); + : gfx::PointF(); } // For layer tree mode only. // Called internally during commit to update the layer with state from the // compositor thread. Not to be called externally by users of this class. - void SetScrollOffsetFromImplSide(const gfx::Vector2dF& scroll_offset); + void SetScrollOffsetFromImplSide(const gfx::PointF& scroll_offset); // For layer tree mode only. // Marks this layer as being scrollable and needing an associated scroll node, @@ -447,6 +462,12 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { return inputs_.touch_action_region; } + // Set or get the region that should be used for capture. + void SetCaptureBounds(std::unique_ptr<viz::RegionCaptureBounds> bounds); + const viz::RegionCaptureBounds* capture_bounds() const { + return inputs_.capture_bounds.get(); + } + // Set or get the set of blocking wheel rects of this layer. The // |wheel_event_region| is the set of rects for which there is a non-passive // wheel event listener that paints into this layer. Mouse wheel messages @@ -466,7 +487,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // which case nothing is called. This is for layer tree mode only. Should use // ScrollTree::SetScrollCallbacks() in layer list mode. void SetDidScrollCallback( - base::RepeatingCallback<void(const gfx::Vector2dF&, const ElementId&)>); + base::RepeatingCallback<void(const gfx::PointF&, const ElementId&)>); // For layer tree mode only. // Sets the given |subtree_id| on this layer, so that the layer subtree rooted @@ -554,6 +575,11 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { int effect_tree_index() const; int scroll_tree_index() const; + bool transform_tree_index_is_valid(const PropertyTrees&) const; + bool clip_tree_index_is_valid(const PropertyTrees&) const; + bool effect_tree_index_is_valid(const PropertyTrees&) const; + bool scroll_tree_index_is_valid(const PropertyTrees&) const; + // While all layers have an index into the transform tree, this value // indicates whether the transform tree node was created for this layer. void SetHasTransformNode(bool val) { has_transform_node_ = val; } @@ -596,13 +622,13 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // Captures text content within the given |rect| and returns the associated // NodeInfo in |content|. virtual void CaptureContent(const gfx::Rect& rect, - std::vector<NodeInfo>* content); + std::vector<NodeInfo>* content) const; // For tracing. Gets a recorded rasterization of this layer's contents that // can be displayed inside representations of this layer. May return null, in // which case the layer won't be shown with any content in the tracing // display. - virtual sk_sp<SkPicture> GetPicture() const; + virtual sk_sp<const SkPicture> GetPicture() const; const LayerDebugInfo* debug_info() const { return debug_info_.get(); } LayerDebugInfo& EnsureDebugInfo(); @@ -625,7 +651,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // that state as well. The |layer| passed in will be of the type created by // CreateLayerImpl(), so can be safely down-casted if the subclass uses a // different type for the compositor thread. - virtual void PushPropertiesTo(LayerImpl* layer); + virtual void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state); // Internal method to be overridden by Layer subclasses that need to do work // during a main frame. The method should compute any state that will need to @@ -836,6 +864,11 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void SetMirrorCount(int mirror_count); + int transform_tree_index(const PropertyTrees&) const; + int clip_tree_index(const PropertyTrees&) const; + int effect_tree_index(const PropertyTrees&) const; + int scroll_tree_index(const PropertyTrees&) const; + // Encapsulates all data, callbacks or interfaces received from the embedder. struct Inputs { explicit Inputs(int layer_id); @@ -853,17 +886,17 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // Hit testing depends on this bit. bool hit_testable : 1; - bool contents_opaque : 1; bool contents_opaque_for_text : 1; bool is_drawable : 1; - bool double_sided : 1; + // TODO(crbug.com/1264177): properties that are rarely set should be + // moved to a separate sub-struct. SkColor background_color; - Region non_fast_scrollable_region; TouchActionRegion touch_action_region; + std::unique_ptr<viz::RegionCaptureBounds> capture_bounds; Region wheel_event_region; ElementId element_id; @@ -882,7 +915,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // If not null, points to one of child layers which is set as mask layer // by SetMaskLayer(). - PictureLayer* mask_layer = nullptr; + raw_ptr<PictureLayer> mask_layer = nullptr; float opacity = 1.0f; SkBlendMode blend_mode = SkBlendMode::kSrcOver; @@ -924,7 +957,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { int mirror_count = 0; - gfx::Vector2dF scroll_offset; + gfx::PointF scroll_offset; // Size of the scroll container that this layer scrolls in. gfx::Size scroll_container_bounds; @@ -932,17 +965,17 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // top left, top right, bottom right, bottom left gfx::RoundedCornersF corner_radii; - base::RepeatingCallback<void(const gfx::Vector2dF&, const ElementId&)> + base::RepeatingCallback<void(const gfx::PointF&, const ElementId&)> did_scroll_callback; std::vector<std::unique_ptr<viz::CopyOutputRequest>> copy_requests; }; - Layer* parent_; + raw_ptr<Layer> parent_; // Layer instances have a weak pointer to their LayerTreeHost. // This pointer value is nil when a Layer is not in a tree and is // updated via SetLayerTreeHost() if a layer moves between trees. - LayerTreeHost* layer_tree_host_; + raw_ptr<LayerTreeHost> layer_tree_host_; Inputs inputs_; std::unique_ptr<LayerTreeInputs> layer_tree_inputs_; diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc index 17970a62818..2de573e17be 100644 --- a/chromium/cc/layers/layer_impl.cc +++ b/chromium/cc/layers/layer_impl.cc @@ -43,6 +43,15 @@ #include "ui/gfx/geometry/transform_util.h" #include "ui/gfx/geometry/vector2d_conversions.h" +namespace { + +template <typename T> +std::unique_ptr<T> ClonePtr(const std::unique_ptr<T>& value) { + return value ? std::make_unique<T>(*value) : nullptr; +} + +} // namespace + namespace cc { LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id, @@ -352,6 +361,11 @@ const Region& LayerImpl::GetAllTouchActionRegions() const { return *all_touch_action_regions_; } +void LayerImpl::SetCaptureBounds( + std::unique_ptr<viz::RegionCaptureBounds> bounds) { + capture_bounds_ = std::move(bounds); +} + std::unique_ptr<LayerImpl> LayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { return LayerImpl::Create(tree_impl, layer_id_); @@ -379,10 +393,8 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->hit_testable_ = hit_testable_; layer->non_fast_scrollable_region_ = non_fast_scrollable_region_; layer->touch_action_region_ = touch_action_region_; - layer->all_touch_action_regions_ = - all_touch_action_regions_ - ? std::make_unique<Region>(*all_touch_action_regions_) - : nullptr; + layer->all_touch_action_regions_ = ClonePtr(all_touch_action_regions_); + layer->capture_bounds_ = ClonePtr(capture_bounds_); layer->wheel_event_handler_region_ = wheel_event_handler_region_; layer->background_color_ = background_color_; layer->safe_opaque_background_color_ = safe_opaque_background_color_; @@ -603,7 +615,7 @@ gfx::Rect LayerImpl::GetDamageRect() const { return gfx::Rect(); } -void LayerImpl::SetCurrentScrollOffset(const gfx::Vector2dF& scroll_offset) { +void LayerImpl::SetCurrentScrollOffset(const gfx::PointF& scroll_offset) { DCHECK(IsActive()); if (GetScrollTree().SetScrollOffset(element_id(), scroll_offset)) layer_tree_impl()->DidUpdateScrollOffset(element_id()); @@ -814,6 +826,19 @@ const RenderSurfaceImpl* LayerImpl::render_target() const { } gfx::Vector2dF LayerImpl::GetIdealContentsScale() const { + const auto& transform = ScreenSpaceTransform(); + absl::optional<gfx::Vector2dF> transform_scales = + gfx::TryComputeTransform2dScaleComponents(transform); + if (transform_scales) { + // TODO(crbug.com/1196414): Remove this scale cap. + float scale_cap = GetPreferredRasterScale(*transform_scales); + transform_scales->SetToMin(gfx::Vector2dF(scale_cap, scale_cap)); + return *transform_scales; + } + + // TryComputeTransform2dScaleComponents couldn't compute a scale because of + // perspective components in the transform. + float page_scale = IsAffectedByPageScale() ? layer_tree_impl()->current_page_scale_factor() : 1.f; @@ -821,46 +846,34 @@ gfx::Vector2dF LayerImpl::GetIdealContentsScale() const { float default_scale = page_scale * device_scale; - const auto& transform = ScreenSpaceTransform(); - if (transform.HasPerspective()) { - // TODO(crbug.com/1196414): This function should return a 2D scale. - float scale = gfx::ComputeApproximateMaxScale(transform); - - const int kMaxTilesToCoverLayerDimension = 5; - // Cap the scale in a way that it should be covered by at most - // |kMaxTilesToCoverLayerDimension|^2 default tile sizes. If this is left - // uncapped, then we can fairly easily use too much memory (or too many - // tiles). See crbug.com/752382 for an example of such a page. Note that - // because this is an approximation anyway, it's fine to use a smaller scale - // that desired. On top of this, the layer has a perspective transform so - // technically it could all be within the viewport, so it's important for us - // to have a reasonable scale here. The scale we use would also be at least - // |default_scale|, as checked below. - float scale_cap = std::min( - (layer_tree_impl()->settings().default_tile_size.width() - 2) * - kMaxTilesToCoverLayerDimension / - static_cast<float>(bounds().width()), - (layer_tree_impl()->settings().default_tile_size.height() - 2) * - kMaxTilesToCoverLayerDimension / - static_cast<float>(bounds().height())); - scale = std::min(scale, scale_cap); - - // Since we're approximating the scale anyway, round it to the nearest - // integer to prevent jitter when animating the transform. - scale = std::round(scale); - - // Don't let the scale fall below the default scale. - scale = std::max(scale, default_scale); - return gfx::Vector2dF(scale, scale); - } - - gfx::Vector2dF transform_scales = - gfx::ComputeTransform2dScaleComponents(transform, default_scale); - - // TODO(crbug.com/1196414): Remove this scale cap. - float scale_cap = GetPreferredRasterScale(transform_scales); - transform_scales.SetToMin(gfx::Vector2dF(scale_cap, scale_cap)); - return transform_scales; + // TODO(crbug.com/1196414): This function should return a 2D scale. + float scale = gfx::ComputeApproximateMaxScale(transform); + + const int kMaxTilesToCoverLayerDimension = 5; + // Cap the scale in a way that it should be covered by at most + // |kMaxTilesToCoverLayerDimension|^2 default tile sizes. If this is left + // uncapped, then we can fairly easily use too much memory (or too many + // tiles). See crbug.com/752382 for an example of such a page. Note that + // because this is an approximation anyway, it's fine to use a smaller scale + // that desired. On top of this, the layer has a perspective transform so + // technically it could all be within the viewport, so it's important for us + // to have a reasonable scale here. The scale we use would also be at least + // |default_scale|, as checked below. + float scale_cap = std::min( + (layer_tree_impl()->settings().default_tile_size.width() - 2) * + kMaxTilesToCoverLayerDimension / static_cast<float>(bounds().width()), + (layer_tree_impl()->settings().default_tile_size.height() - 2) * + kMaxTilesToCoverLayerDimension / + static_cast<float>(bounds().height())); + scale = std::min(scale, scale_cap); + + // Since we're approximating the scale anyway, round it to the nearest + // integer to prevent jitter when animating the transform. + scale = std::round(scale); + + // Don't let the scale fall below the default scale. + scale = std::max(scale, default_scale); + return gfx::Vector2dF(scale, scale); } float LayerImpl::GetIdealContentsScaleKey() const { diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h index ce9ead1b922..3a0ea24f953 100644 --- a/chromium/cc/layers/layer_impl.h +++ b/chromium/cc/layers/layer_impl.h @@ -16,6 +16,7 @@ #include "base/check.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "cc/base/region.h" #include "cc/base/synced_property.h" #include "cc/cc_export.h" @@ -31,9 +32,11 @@ #include "cc/tiles/tile_priority.h" #include "cc/trees/target_property.h" #include "components/viz/common/quads/shared_quad_state.h" +#include "components/viz/common/surfaces/region_capture_bounds.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/display_color_spaces.h" #include "ui/gfx/geometry/point3_f.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/transform.h" @@ -243,7 +246,7 @@ class CC_EXPORT LayerImpl { is_inner_viewport_scroll_layer_ = true; } - void SetCurrentScrollOffset(const gfx::Vector2dF& scroll_offset); + void SetCurrentScrollOffset(const gfx::PointF& scroll_offset); // Returns the delta of the scroll that was outside of the bounds of the // initial scroll @@ -270,6 +273,11 @@ class CC_EXPORT LayerImpl { return !touch_action_region_.IsEmpty(); } + void SetCaptureBounds(std::unique_ptr<viz::RegionCaptureBounds> bounds); + const viz::RegionCaptureBounds* capture_bounds() const { + return capture_bounds_.get(); + } + // Set or get the region that contains wheel event handler. // The |wheel_event_handler_region| specify the area where wheel event handler // could block impl scrolling. @@ -456,7 +464,7 @@ class CC_EXPORT LayerImpl { virtual const char* LayerTypeAsString() const; const int layer_id_; - LayerTreeImpl* const layer_tree_impl_; + const raw_ptr<LayerTreeImpl> layer_tree_impl_; const bool will_always_push_properties_ : 1; // Properties synchronized from the associated Layer. @@ -500,6 +508,10 @@ class CC_EXPORT LayerImpl { Region non_fast_scrollable_region_; TouchActionRegion touch_action_region_; + + // The bounds of elements marked for potential region capture, stored in + // the coordinate space of this layer. + std::unique_ptr<viz::RegionCaptureBounds> capture_bounds_; Region wheel_event_handler_region_; SkColor background_color_; SkColor safe_opaque_background_color_; diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc index dd454f2c23e..93ad1328f19 100644 --- a/chromium/cc/layers/layer_impl_unittest.cc +++ b/chromium/cc/layers/layer_impl_unittest.cc @@ -6,18 +6,19 @@ #include <algorithm> +#include "base/memory/raw_ptr.h" #include "cc/layers/painted_scrollbar_layer_impl.h" #include "cc/layers/solid_color_scrollbar_layer_impl.h" #include "cc/paint/filter_operation.h" #include "cc/paint/filter_operations.h" #include "cc/test/animation_test_common.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" #include "cc/trees/tree_synchronizer.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/test/geometry_util.h" namespace cc { namespace { @@ -162,6 +163,8 @@ TEST_F(LayerImplTest, VerifyNeedsUpdateDrawProperties) { float arbitrary_number = 0.352f; gfx::Size arbitrary_size = gfx::Size(111, 222); gfx::Vector2d arbitrary_vector2d = gfx::Vector2d(111, 222); + gfx::PointF arbitrary_scroll_offset( + gfx::PointAtOffsetFromOrigin(arbitrary_vector2d)); gfx::Size large_size = gfx::Size(1000, 1000); SkColor arbitrary_color = SkColorSetRGB(10, 20, 30); gfx::Transform arbitrary_transform; @@ -208,9 +211,9 @@ TEST_F(LayerImplTest, VerifyNeedsUpdateDrawProperties) { ->scroll_tree.SetScrollOffsetDeltaForTesting(layer->element_id(), gfx::Vector2dF()); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - layer->SetCurrentScrollOffset(arbitrary_vector2d)); + layer->SetCurrentScrollOffset(arbitrary_scroll_offset)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( - layer->SetCurrentScrollOffset(arbitrary_vector2d)); + layer->SetCurrentScrollOffset(arbitrary_scroll_offset)); // Unrelated functions, always set to new values, always set needs update. host_impl()->active_tree()->set_needs_update_draw_properties(); @@ -253,6 +256,7 @@ TEST_F(LayerImplTest, PerspectiveTransformHasReasonableScale) { gfx::Transform transform; transform.Scale(10.2f, 15.1f); transform.ApplyPerspectiveDepth(10); + transform.RotateAboutXAxis(15.0f); layer->draw_properties().screen_space_transform = transform; ASSERT_TRUE(layer->ScreenSpaceTransform().HasPerspective()); @@ -263,6 +267,7 @@ TEST_F(LayerImplTest, PerspectiveTransformHasReasonableScale) { gfx::Transform transform; transform.Scale(0.1f, 0.2f); transform.ApplyPerspectiveDepth(10); + transform.RotateAboutXAxis(15.0f); layer->draw_properties().screen_space_transform = transform; ASSERT_TRUE(layer->ScreenSpaceTransform().HasPerspective()); @@ -273,6 +278,7 @@ TEST_F(LayerImplTest, PerspectiveTransformHasReasonableScale) { gfx::Transform transform; transform.Scale(10000.1f, 10000.2f); transform.ApplyPerspectiveDepth(10); + transform.RotateAboutXAxis(15.0f); layer->draw_properties().screen_space_transform = transform; ASSERT_TRUE(layer->ScreenSpaceTransform().HasPerspective()); @@ -319,7 +325,7 @@ class LayerImplScrollTest : public LayerImplTest { } private: - LayerImpl* layer_; + raw_ptr<LayerImpl> layer_; }; class CommitToPendingTreeLayerImplScrollTest : public LayerImplScrollTest { @@ -337,61 +343,63 @@ TEST_F(LayerImplScrollTest, ScrollByWithZeroOffset) { // Test that LayerImpl::ScrollBy only affects ScrollDelta and total scroll // offset is bounded by the range [0, max scroll offset]. - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(), CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(), scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), ScrollDelta(layer())); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(layer())); layer()->ScrollBy(gfx::Vector2dF(-100, 100)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 80), CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(0, 80), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(ScrollDelta(layer()), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointAtOffsetFromOrigin(ScrollDelta(layer())), + CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(), scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); layer()->ScrollBy(gfx::Vector2dF(100, -100)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(50, 0), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(ScrollDelta(layer()), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointAtOffsetFromOrigin(ScrollDelta(layer())), + CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(), scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); } TEST_F(LayerImplScrollTest, ScrollByWithNonZeroOffset) { - gfx::Vector2dF scroll_offset(10, 5); + gfx::PointF scroll_offset(10, 5); scroll_tree(layer())->UpdateScrollOffsetBaseForTesting(layer()->element_id(), scroll_offset); - EXPECT_VECTOR_EQ(scroll_offset, CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_offset, + EXPECT_POINTF_EQ(scroll_offset, CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(scroll_offset, scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), ScrollDelta(layer())); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(layer())); layer()->ScrollBy(gfx::Vector2dF(-100, 100)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 80), CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(0, 80), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_offset + ScrollDelta(layer()), + EXPECT_POINTF_EQ(scroll_offset + ScrollDelta(layer()), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_offset, + EXPECT_POINTF_EQ(scroll_offset, scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); layer()->ScrollBy(gfx::Vector2dF(100, -100)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(gfx::PointF(50, 0), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_offset + ScrollDelta(layer()), + EXPECT_POINTF_EQ(scroll_offset + ScrollDelta(layer()), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_offset, + EXPECT_POINTF_EQ(scroll_offset, scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); } TEST_F(LayerImplScrollTest, ApplySentScrollsNoListener) { - gfx::Vector2dF scroll_offset(10, 5); + gfx::PointF scroll_offset(10, 5); gfx::Vector2dF scroll_delta(20.5f, 8.5f); gfx::Vector2d sent_scroll_delta(12, -3); @@ -401,23 +409,23 @@ TEST_F(LayerImplScrollTest, ApplySentScrollsNoListener) { scroll_tree(layer())->CollectScrollDeltasForTesting(); layer()->SetCurrentScrollOffset(scroll_offset + scroll_delta); - EXPECT_VECTOR_EQ(scroll_offset + scroll_delta, CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_delta, ScrollDelta(layer())); - EXPECT_VECTOR_EQ(scroll_offset, + EXPECT_POINTF_EQ(scroll_offset + scroll_delta, CurrentScrollOffset(layer())); + EXPECT_VECTOR2DF_EQ(scroll_delta, ScrollDelta(layer())); + EXPECT_POINTF_EQ(scroll_offset, scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); scroll_tree(layer())->ApplySentScrollDeltasFromAbortedCommit(); - EXPECT_VECTOR_EQ(scroll_offset + scroll_delta, CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(scroll_delta - sent_scroll_delta, ScrollDelta(layer())); - EXPECT_VECTOR_EQ(scroll_offset + sent_scroll_delta, + EXPECT_POINTF_EQ(scroll_offset + scroll_delta, CurrentScrollOffset(layer())); + EXPECT_VECTOR2DF_EQ(scroll_delta - sent_scroll_delta, ScrollDelta(layer())); + EXPECT_POINTF_EQ(scroll_offset + sent_scroll_delta, scroll_tree(layer())->GetScrollOffsetBaseForTesting( layer()->element_id())); } TEST_F(LayerImplScrollTest, ScrollUserUnscrollableLayer) { - gfx::Vector2dF scroll_offset(10, 5); + gfx::PointF scroll_offset(10, 5); gfx::Vector2dF scroll_delta(20.5f, 8.5f); GetScrollNode(layer())->user_scrollable_vertical = false; @@ -426,8 +434,8 @@ TEST_F(LayerImplScrollTest, ScrollUserUnscrollableLayer) { scroll_offset); gfx::Vector2dF unscrolled = layer()->ScrollBy(scroll_delta); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 8.5f), unscrolled); - EXPECT_VECTOR_EQ(gfx::Vector2dF(30.5f, 5), CurrentScrollOffset(layer())); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 8.5f), unscrolled); + EXPECT_POINTF_EQ(gfx::PointF(30.5f, 5), CurrentScrollOffset(layer())); } // |LayerImpl::all_touch_action_regions_| is a cache of all regions on @@ -457,7 +465,7 @@ TEST_F(LayerImplScrollTest, TouchActionRegionCacheInvalidation) { TEST_F(CommitToPendingTreeLayerImplScrollTest, PushPropertiesToMirrorsCurrentScrollOffset) { - gfx::Vector2dF scroll_offset(10, 5); + gfx::PointF scroll_offset(10, 5); gfx::Vector2dF scroll_delta(12, 18); host_impl()->CreatePendingTree(); @@ -466,8 +474,8 @@ TEST_F(CommitToPendingTreeLayerImplScrollTest, scroll_offset); gfx::Vector2dF unscrolled = layer()->ScrollBy(scroll_delta); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), unscrolled); - EXPECT_VECTOR_EQ(gfx::Vector2dF(22, 23), CurrentScrollOffset(layer())); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 0), unscrolled); + EXPECT_POINTF_EQ(gfx::PointF(22, 23), CurrentScrollOffset(layer())); scroll_tree(layer())->CollectScrollDeltasForTesting(); @@ -481,8 +489,8 @@ TEST_F(CommitToPendingTreeLayerImplScrollTest, pending_layer->PushPropertiesTo(layer()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(22, 23), CurrentScrollOffset(layer())); - EXPECT_VECTOR_EQ(CurrentScrollOffset(layer()), + EXPECT_POINTF_EQ(gfx::PointF(22, 23), CurrentScrollOffset(layer())); + EXPECT_POINTF_EQ(CurrentScrollOffset(layer()), CurrentScrollOffset(pending_layer.get())); } @@ -509,7 +517,7 @@ TEST_F(LayerImplTest, JitterTest) { accumulated_scroll += scroll; SetScrollOffset( host_impl()->active_tree()->InnerViewportScrollLayerForTesting(), - gfx::Vector2dF(0, accumulated_scroll)); + gfx::PointF(0, accumulated_scroll)); UpdateActiveTreeDrawProperties(); host_impl()->CreatePendingTree(); @@ -517,7 +525,7 @@ TEST_F(LayerImplTest, JitterTest) { pending_tree->set_source_frame_number(i + 1); pending_tree->PushPageScaleFromMainThread(1.f, 1.f, 1.f); // Simulate scroll offset pushed from the main thread. - SetScrollOffset(scroll_layer, gfx::Vector2dF(0, accumulated_scroll)); + SetScrollOffset(scroll_layer, gfx::PointF(0, accumulated_scroll)); // The scroll done on the active tree is undone on the pending tree. content_layer->SetOffsetToTransformParent( gfx::Vector2dF(0, accumulated_scroll)); diff --git a/chromium/cc/layers/layer_list_iterator.cc b/chromium/cc/layers/layer_list_iterator.cc index 7e2066b089a..b30467b52b8 100644 --- a/chromium/cc/layers/layer_list_iterator.cc +++ b/chromium/cc/layers/layer_list_iterator.cc @@ -16,8 +16,6 @@ LayerListIterator::LayerListIterator(Layer* root_layer) LayerListIterator::LayerListIterator(const LayerListIterator& other) = default; -LayerListIterator::~LayerListIterator() = default; - LayerListIterator& LayerListIterator::operator++() { // case 0: done if (!current_layer_) @@ -48,15 +46,30 @@ LayerListIterator& LayerListIterator::operator++() { return *this; } +LayerListIterator::~LayerListIterator() = default; + +LayerListConstIterator::LayerListConstIterator(const Layer* root_layer) + : iterator_(const_cast<Layer*>(root_layer)) {} + +LayerListConstIterator& LayerListConstIterator::operator++() { + ++iterator_; + return *this; +} + +LayerListConstIterator::~LayerListConstIterator() = default; + LayerListReverseIterator::LayerListReverseIterator(Layer* root_layer) - : LayerListIterator(root_layer) { + : current_layer_(root_layer) { + DCHECK(!root_layer || !root_layer->parent()); + list_indices_.push_back(0); DescendToRightmostInSubtree(); } -LayerListReverseIterator::~LayerListReverseIterator() = default; +LayerListReverseIterator::LayerListReverseIterator( + const LayerListReverseIterator& other) = default; // We will only support prefix increment. -LayerListIterator& LayerListReverseIterator::operator++() { +LayerListReverseIterator& LayerListReverseIterator::operator++() { // case 0: done if (!current_layer_) return *this; @@ -91,4 +104,17 @@ void LayerListReverseIterator::DescendToRightmostInSubtree() { DescendToRightmostInSubtree(); } +LayerListReverseIterator::~LayerListReverseIterator() = default; + +LayerListReverseConstIterator::LayerListReverseConstIterator( + const Layer* root_layer) + : iterator_(const_cast<Layer*>(root_layer)) {} + +LayerListReverseConstIterator& LayerListReverseConstIterator::operator++() { + ++iterator_; + return *this; +} + +LayerListReverseConstIterator::~LayerListReverseConstIterator() = default; + } // namespace cc diff --git a/chromium/cc/layers/layer_list_iterator.h b/chromium/cc/layers/layer_list_iterator.h index e06686fae5a..6d82c12727c 100644 --- a/chromium/cc/layers/layer_list_iterator.h +++ b/chromium/cc/layers/layer_list_iterator.h @@ -8,6 +8,7 @@ #include <stdlib.h> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" namespace cc { @@ -19,7 +20,7 @@ class CC_EXPORT LayerListIterator { public: explicit LayerListIterator(Layer* root_layer); LayerListIterator(const LayerListIterator& other); - virtual ~LayerListIterator(); + ~LayerListIterator(); bool operator==(const LayerListIterator& other) const { return current_layer_ == other.current_layer_; @@ -30,30 +31,94 @@ class CC_EXPORT LayerListIterator { } // We will only support prefix increment. - virtual LayerListIterator& operator++(); + LayerListIterator& operator++(); Layer* operator->() const { return current_layer_; } Layer* operator*() const { return current_layer_; } - protected: + private: // The implementation of this iterator is currently tied tightly to the layer // tree, but it should be straightforward to reimplement in terms of a list // when it's ready. + + // `current_layer` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). Layer* current_layer_; + std::vector<size_t> list_indices_; }; -class CC_EXPORT LayerListReverseIterator : public LayerListIterator { +class CC_EXPORT LayerListConstIterator { + public: + explicit LayerListConstIterator(const Layer* root_layer); + LayerListConstIterator(const LayerListConstIterator& other) = default; + ~LayerListConstIterator(); + + bool operator==(const LayerListConstIterator& other) const { + return iterator_ == other.iterator_; + } + + bool operator!=(const LayerListConstIterator& other) const { + return !(*this == other); + } + + // We will only support prefix increment. + LayerListConstIterator& operator++(); + const Layer* operator->() const { return *iterator_; } + const Layer* operator*() const { return *iterator_; } + + private: + LayerListIterator iterator_; +}; + +class CC_EXPORT LayerListReverseIterator { public: explicit LayerListReverseIterator(Layer* root_layer); - ~LayerListReverseIterator() override; + LayerListReverseIterator(const LayerListReverseIterator& other); + ~LayerListReverseIterator(); + + bool operator==(const LayerListReverseIterator& other) const { + return current_layer_ == other.current_layer_; + } + + bool operator!=(const LayerListReverseIterator& other) const { + return !(*this == other); + } // We will only support prefix increment. - LayerListIterator& operator++() override; + LayerListReverseIterator& operator++(); + Layer* operator->() const { return current_layer_; } + Layer* operator*() const { return current_layer_; } private: void DescendToRightmostInSubtree(); + + raw_ptr<Layer> current_layer_; + std::vector<size_t> list_indices_; }; +class CC_EXPORT LayerListReverseConstIterator { + public: + explicit LayerListReverseConstIterator(const Layer* root_layer); + LayerListReverseConstIterator(const LayerListReverseConstIterator& other) = + default; + ~LayerListReverseConstIterator(); + + bool operator==(const LayerListReverseConstIterator& other) const { + return iterator_ == other.iterator_; + } + + bool operator!=(const LayerListReverseConstIterator& other) const { + return !(*this == other); + } + + // We will only support prefix increment. + LayerListReverseConstIterator& operator++(); + const Layer* operator->() const { return *iterator_; } + const Layer* operator*() const { return *iterator_; } + + private: + LayerListReverseIterator iterator_; +}; } // namespace cc #endif // CC_LAYERS_LAYER_LIST_ITERATOR_H_ diff --git a/chromium/cc/layers/layer_perftest.cc b/chromium/cc/layers/layer_perftest.cc index 52c71953cd6..4c419ecb509 100644 --- a/chromium/cc/layers/layer_perftest.cc +++ b/chromium/cc/layers/layer_perftest.cc @@ -85,7 +85,13 @@ TEST_F(LayerPerfTest, PushPropertiesTo) { test_layer->SetContentsOpaque(contents_opaque); test_layer->SetHideLayerAndSubtree(hide_layer_and_subtree); test_layer->SetMasksToBounds(masks_to_bounds); - test_layer->PushPropertiesTo(impl_layer.get()); + // Here and elsewhere: when doing a full commit, we would call + // layer_tree_host_->ActivateCommitState() and the second argument would + // come from layer_tree_host_->active_commit_state(); we use + // pending_commit_state() just to keep the test code simple. + test_layer->PushPropertiesTo( + impl_layer.get(), *layer_tree_host_->GetPendingCommitState(), + layer_tree_host_->GetThreadUnsafeCommitState()); transform_origin_z += 0.01f; scrollable = !scrollable; @@ -103,7 +109,9 @@ TEST_F(LayerPerfTest, PushPropertiesTo) { // Properties didn't change. timer_.Reset(); do { - test_layer->PushPropertiesTo(impl_layer.get()); + test_layer->PushPropertiesTo( + impl_layer.get(), *layer_tree_host_->GetPendingCommitState(), + layer_tree_host_->GetThreadUnsafeCommitState()); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc index d0791855665..5ae5958151b 100644 --- a/chromium/cc/layers/layer_unittest.cc +++ b/chromium/cc/layers/layer_unittest.cc @@ -25,7 +25,6 @@ #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_layer_tree_host_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" #include "cc/test/stub_layer_tree_host_single_thread_client.h" #include "cc/test/test_task_graph_runner.h" @@ -58,36 +57,27 @@ using ::testing::_; Mock::VerifyAndClearExpectations(layer_tree_host_.get()); \ } while (false) -#define EXECUTE_AND_VERIFY_SUBTREE_CHANGED(code_to_test) \ - code_to_test; \ - root->layer_tree_host()->BuildPropertyTreesForTesting(); \ - EXPECT_FALSE(root->subtree_property_changed()); \ - EXPECT_TRUE(top->subtree_property_changed()); \ - EXPECT_TRUE(base::Contains( \ - top->layer_tree_host()->LayersThatShouldPushProperties(), top.get())); \ - EXPECT_TRUE(child->subtree_property_changed()); \ - EXPECT_TRUE(base::Contains( \ - child->layer_tree_host()->LayersThatShouldPushProperties(), \ - child.get())); \ - EXPECT_TRUE(grand_child->subtree_property_changed()); \ - EXPECT_TRUE(base::Contains( \ - grand_child->layer_tree_host()->LayersThatShouldPushProperties(), \ - grand_child.get())); - -#define EXECUTE_AND_VERIFY_SUBTREE_NOT_CHANGED(code_to_test) \ - code_to_test; \ - root->layer_tree_host()->BuildPropertyTreesForTesting(); \ - EXPECT_FALSE(root->subtree_property_changed()); \ - EXPECT_FALSE(top->subtree_property_changed()); \ - EXPECT_FALSE(base::Contains( \ - top->layer_tree_host()->LayersThatShouldPushProperties(), top.get())); \ - EXPECT_FALSE(child->subtree_property_changed()); \ - EXPECT_FALSE(base::Contains( \ - child->layer_tree_host()->LayersThatShouldPushProperties(), \ - child.get())); \ - EXPECT_FALSE(grand_child->subtree_property_changed()); \ - EXPECT_FALSE(base::Contains( \ - grand_child->layer_tree_host()->LayersThatShouldPushProperties(), \ +#define EXECUTE_AND_VERIFY_SUBTREE_CHANGED(code_to_test) \ + code_to_test; \ + root->layer_tree_host()->BuildPropertyTreesForTesting(); \ + EXPECT_FALSE(root->subtree_property_changed()); \ + EXPECT_TRUE(top->subtree_property_changed()); \ + EXPECT_TRUE( \ + base::Contains(const_cast<const LayerTreeHost*>(top->layer_tree_host()) \ + ->thread_unsafe_commit_state() \ + .layers_that_should_push_properties, \ + top.get())); \ + EXPECT_TRUE(child->subtree_property_changed()); \ + EXPECT_TRUE(base::Contains( \ + const_cast<const LayerTreeHost*>(child->layer_tree_host()) \ + ->thread_unsafe_commit_state() \ + .layers_that_should_push_properties, \ + child.get())); \ + EXPECT_TRUE(grand_child->subtree_property_changed()); \ + EXPECT_TRUE(base::Contains( \ + const_cast<const LayerTreeHost*>(grand_child->layer_tree_host()) \ + ->thread_unsafe_commit_state() \ + .layers_that_should_push_properties, \ grand_child.get())); #define EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(code_to_test) \ @@ -115,6 +105,11 @@ class MockLayerTreeHost : public LayerTreeHost { base::ThreadTaskRunnerHandle::Get()); } + CommitState* GetPendingCommitState() { return pending_commit_state(); } + ThreadUnsafeCommitState& GetThreadUnsafeCommitState() { + return thread_unsafe_commit_state(); + } + MOCK_METHOD0(SetNeedsCommit, void()); MOCK_METHOD0(SetNeedsUpdateLayers, void()); MOCK_METHOD0(SetNeedsFullTreeSync, void()); @@ -172,7 +167,18 @@ class LayerTest : public testing::Test { void SimulateCommitForLayer(Layer* layer) { layer->PushPropertiesTo( - layer->CreateLayerImpl(host_impl_.active_tree()).get()); + layer->CreateLayerImpl(host_impl_.active_tree()).get(), + *layer_tree_host_->GetPendingCommitState(), + layer_tree_host_->GetThreadUnsafeCommitState()); + } + + void CommitAndPushProperties(Layer* layer, LayerImpl* layer_impl) { + auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); + std::unique_ptr<CommitState> commit_state = layer_tree_host_->WillCommit( + /*completion=*/nullptr, /*has_updates=*/true); + layer->PushPropertiesTo(layer_impl, *commit_state, unsafe_state); + layer_tree_host_->CommitComplete( + {base::TimeTicks(), base::TimeTicks::Now()}); } void VerifyTestTreeInitialState() const { @@ -292,7 +298,10 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { EXPECT_SET_NEEDS_COMMIT(0, mask_layer1->SetBounds(arbitrary_size)); EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(1); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); + layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetMaskLayer(mask_layer1)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); // Set up the impl layers after the full tree is constructed, including the // mask layer. @@ -311,12 +320,18 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { host_impl_.active_tree()->set_source_frame_number( host_impl_.active_tree()->source_frame_number() + 1); + auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); + std::unique_ptr<CommitState> commit_state = layer_tree_host_->WillCommit( + /*completion=*/nullptr, /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get()); - mask_layer1->PushPropertiesTo(mask_layer1_impl.get());); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state); + mask_layer1->PushPropertiesTo(mask_layer1_impl.get(), *commit_state, + unsafe_state);); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); // Once there is a mask layer, resizes require subtree properties to update. arbitrary_size = gfx::Size(11, 22); @@ -326,60 +341,95 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetMasksToBounds(true)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetContentsOpaque(true)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetTrilinearFiltering(true)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetTrilinearFiltering(false)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2); top->SetRoundedCorner({1, 2, 3, 4}); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetIsFastRoundedCorner(true)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetHideLayerAndSubtree(true)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetBlendMode(arbitrary_blend_mode)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); // Should be a different size than previous call, to ensure it marks tree // changed. @@ -387,30 +437,45 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetBounds(arbitrary_size)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(mask_layer1->SetBounds(arbitrary_size)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); FilterOperations arbitrary_filters; arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetFilters(arbitrary_filters)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2); EXECUTE_AND_VERIFY_SUBTREE_CHANGED( top->SetBackdropFilters(arbitrary_filters)); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get())); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state)); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); gfx::PointF arbitrary_point_f = gfx::PointF(0.125f, 0.25f); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); @@ -418,12 +483,17 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { TransformNode* node = layer_tree_host_->property_trees()->transform_tree.Node( top->transform_tree_index()); EXPECT_TRUE(node->transform_changed); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get()); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state); layer_tree_host_->property_trees()->ResetAllChangeTracking()); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_FALSE(node->transform_changed); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); @@ -431,10 +501,15 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { node = layer_tree_host_->property_trees()->transform_tree.Node( child->transform_tree_index()); EXPECT_TRUE(node->transform_changed); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - child->PushPropertiesTo(child_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get()); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state); layer_tree_host_->property_trees()->ResetAllChangeTracking()); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); node = layer_tree_host_->property_trees()->transform_tree.Node( child->transform_tree_index()); EXPECT_FALSE(node->transform_changed); @@ -445,12 +520,17 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { node = layer_tree_host_->property_trees()->transform_tree.Node( top->transform_tree_index()); EXPECT_TRUE(node->transform_changed); + + commit_state = layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( - top->PushPropertiesTo(top_impl.get()); - child->PushPropertiesTo(child_impl.get()); - child2->PushPropertiesTo(child2_impl.get()); - grand_child->PushPropertiesTo(grand_child_impl.get()); + top->PushPropertiesTo(top_impl.get(), *commit_state, unsafe_state); + child->PushPropertiesTo(child_impl.get(), *commit_state, unsafe_state); + child2->PushPropertiesTo(child2_impl.get(), *commit_state, unsafe_state); + grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state, + unsafe_state); layer_tree_host_->property_trees()->ResetAllChangeTracking()); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); gfx::Transform arbitrary_transform; arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f); @@ -585,7 +665,9 @@ TEST_F(LayerTest, ReorderChildren) { EXPECT_EQ(child2, parent->children()[1]); EXPECT_EQ(child3, parent->children()[2]); - layer_tree_host_->ClearLayersThatShouldPushProperties(); + // This is normally done by TreeSynchronizer::PushLayerProperties(). + auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); + unsafe_state.layers_that_should_push_properties.clear(); LayerList new_children_order; new_children_order.emplace_back(child3); @@ -597,8 +679,9 @@ TEST_F(LayerTest, ReorderChildren) { EXPECT_EQ(child2, parent->children()[2]); for (const auto& child : parent->children()) { - EXPECT_FALSE(base::Contains( - layer_tree_host_->LayersThatShouldPushProperties(), child.get())); + EXPECT_FALSE(base::Contains(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties, + child.get())); EXPECT_TRUE(child->subtree_property_changed()); } } @@ -929,8 +1012,7 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { // We can use any layer pointer here since we aren't syncing for real. EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetScrollable(gfx::Size(1, 1))); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUserScrollable(true, false)); - EXPECT_SET_NEEDS_COMMIT(1, - test_layer->SetScrollOffset(gfx::Vector2dF(10, 10))); + EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetScrollOffset(gfx::PointF(10, 10))); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNonFastScrollableRegion( Region(gfx::Rect(1, 1, 2, 2)))); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTransform( @@ -964,24 +1046,21 @@ TEST_F(LayerTest, PushPropertiesAccumulatesUpdateRect) { host_impl_.active_tree()->SetRootLayerForTesting(std::move(impl_layer)); LayerImpl* impl_layer_ptr = host_impl_.active_tree()->LayerById(1); test_layer->SetNeedsDisplayRect(gfx::Rect(5, 5)); - test_layer->PushPropertiesTo(impl_layer_ptr); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(0.f, 0.f, 5.f, 5.f), - impl_layer_ptr->update_rect()); + CommitAndPushProperties(test_layer.get(), impl_layer_ptr); + EXPECT_EQ(gfx::Rect(0, 0, 5, 5), impl_layer_ptr->update_rect()); // The LayerImpl's update_rect() should be accumulated here, since we did not // do anything to clear it. test_layer->SetNeedsDisplayRect(gfx::Rect(10, 10, 5, 5)); - test_layer->PushPropertiesTo(impl_layer_ptr); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(0.f, 0.f, 15.f, 15.f), - impl_layer_ptr->update_rect()); + CommitAndPushProperties(test_layer.get(), impl_layer_ptr); + EXPECT_EQ(gfx::Rect(0, 0, 15, 15), impl_layer_ptr->update_rect()); // If we do clear the LayerImpl side, then the next update_rect() should be // fresh without accumulation. host_impl_.active_tree()->ResetAllChangeTracking(); test_layer->SetNeedsDisplayRect(gfx::Rect(10, 10, 5, 5)); - test_layer->PushPropertiesTo(impl_layer_ptr); - EXPECT_FLOAT_RECT_EQ(gfx::RectF(10.f, 10.f, 5.f, 5.f), - impl_layer_ptr->update_rect()); + CommitAndPushProperties(test_layer.get(), impl_layer_ptr); + EXPECT_EQ(gfx::Rect(10, 10, 5, 5), impl_layer_ptr->update_rect()); } TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForTransform) { @@ -998,7 +1077,7 @@ TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForTransform) { EXPECT_FALSE(impl_layer->LayerPropertyChanged()); - test_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(test_layer.get(), impl_layer.get()); EXPECT_TRUE(impl_layer->LayerPropertyChanged()); EXPECT_FALSE(impl_layer->LayerPropertyChangedFromPropertyTrees()); @@ -1018,7 +1097,7 @@ TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForRoundCorner) { EXPECT_FALSE(impl_layer->LayerPropertyChanged()); - test_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(test_layer.get(), impl_layer.get()); EXPECT_TRUE(impl_layer->LayerPropertyChanged()); EXPECT_FALSE(impl_layer->LayerPropertyChangedFromPropertyTrees()); @@ -1037,7 +1116,7 @@ TEST_F(LayerTest, PushPropertiesCausesLayerPropertyChangedForOpacity) { EXPECT_FALSE(impl_layer->LayerPropertyChanged()); - test_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(test_layer.get(), impl_layer.get()); EXPECT_TRUE(impl_layer->LayerPropertyChanged()); EXPECT_FALSE(impl_layer->LayerPropertyChangedFromPropertyTrees()); @@ -1358,7 +1437,7 @@ TEST_F(LayerTest, PushUpdatesShouldHitTest) { // A layer that draws content should be hit testable. root_layer->SetIsDrawable(true); root_layer->SetHitTestable(true); - root_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(root_layer.get(), impl_layer.get()); EXPECT_TRUE(impl_layer->DrawsContent()); EXPECT_TRUE(impl_layer->HitTestable()); @@ -1366,14 +1445,14 @@ TEST_F(LayerTest, PushUpdatesShouldHitTest) { // content should not be hit testable. root_layer->SetIsDrawable(false); root_layer->SetHitTestable(false); - root_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(root_layer.get(), impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); EXPECT_FALSE(impl_layer->HitTestable()); // |SetHitTestableWithoutDrawsContent| should cause a layer to become hit // testable even though it does not draw content. root_layer->SetHitTestable(true); - root_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(root_layer.get(), impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); EXPECT_TRUE(impl_layer->HitTestable()); } @@ -1517,7 +1596,7 @@ TEST_F(LayerTest, AnimationSchedulesLayerUpdate) { // handled similarly to normal compositor scroll updates. EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(0); layer_tree_host_->SetElementScrollOffsetMutated( - element_id, ElementListType::ACTIVE, gfx::Vector2dF(10, 10)); + element_id, ElementListType::ACTIVE, gfx::PointF(10, 10)); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); } @@ -1535,7 +1614,7 @@ TEST_F(LayerTest, ElementIdIsPushed) { EXPECT_FALSE(impl_layer->element_id()); - test_layer->PushPropertiesTo(impl_layer.get()); + CommitAndPushProperties(test_layer.get(), impl_layer.get()); EXPECT_EQ(ElementId(2), impl_layer->element_id()); } @@ -1578,7 +1657,8 @@ TEST_F(LayerTest, PushAnimationCountsLazily) { EXPECT_FALSE(host_impl_.animation_host()->CurrentFrameHadRAF()); EXPECT_FALSE(host_impl_.animation_host()->HasSmilAnimation()); EXPECT_FALSE(animation_host_->needs_push_properties()); - animation_host_->PushPropertiesTo(host_impl_.animation_host()); + animation_host_->PushPropertiesTo(host_impl_.animation_host(), + *layer_tree_host_->property_trees()); EXPECT_TRUE(host_impl_.animation_host()->CurrentFrameHadRAF()); EXPECT_TRUE(host_impl_.animation_host()->HasSmilAnimation()); } @@ -1611,47 +1691,54 @@ TEST_F(LayerTest, SetElementIdNotUsingLayerLists) { TEST_F(LayerTest, UpdateMirrorCount) { scoped_refptr<Layer> test_layer = Layer::Create(); test_layer->SetLayerTreeHost(layer_tree_host_.get()); + auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); + + // This is normally done by TreeSynchronizer::PushLayerProperties(). + unsafe_state.layers_that_should_push_properties.clear(); + layer_tree_host_->property_trees()->needs_rebuild = false; - layer_tree_host_->ClearLayersThatShouldPushProperties(); EXPECT_EQ(0, test_layer->mirror_count()); EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_EQ(0u, layer_tree_host_->LayersThatShouldPushProperties().size()); + EXPECT_EQ(0u, layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties.size()); // Incrementing mirror count from zero should trigger property trees rebuild. test_layer->IncrementMirrorCount(); EXPECT_EQ(1, test_layer->mirror_count()); EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), + EXPECT_TRUE(base::Contains(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties, test_layer.get())); + unsafe_state.layers_that_should_push_properties.clear(); layer_tree_host_->property_trees()->needs_rebuild = false; - layer_tree_host_->ClearLayersThatShouldPushProperties(); // Incrementing mirror count from non-zero should not trigger property trees // rebuild. test_layer->IncrementMirrorCount(); EXPECT_EQ(2, test_layer->mirror_count()); EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), + EXPECT_TRUE(base::Contains(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties, test_layer.get())); - layer_tree_host_->ClearLayersThatShouldPushProperties(); + unsafe_state.layers_that_should_push_properties.clear(); // Decrementing mirror count to non-zero should not trigger property trees // rebuild. test_layer->DecrementMirrorCount(); EXPECT_EQ(1, test_layer->mirror_count()); EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), + EXPECT_TRUE(base::Contains(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties, test_layer.get())); - layer_tree_host_->ClearLayersThatShouldPushProperties(); - // Decrementing mirror count to zero should trigger property trees rebuild. test_layer->DecrementMirrorCount(); EXPECT_EQ(0, test_layer->mirror_count()); EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), + EXPECT_TRUE(base::Contains(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties, test_layer.get())); test_layer->SetLayerTreeHost(nullptr); diff --git a/chromium/cc/layers/mirror_layer.cc b/chromium/cc/layers/mirror_layer.cc index b89e300d2d6..82e421f7f91 100644 --- a/chromium/cc/layers/mirror_layer.cc +++ b/chromium/cc/layers/mirror_layer.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "cc/layers/mirror_layer.h" #include "cc/layers/mirror_layer_impl.h" @@ -13,8 +15,11 @@ std::unique_ptr<LayerImpl> MirrorLayer::CreateLayerImpl( return MirrorLayerImpl::Create(tree_impl, id()); } -void MirrorLayer::PushPropertiesTo(LayerImpl* layer) { - Layer::PushPropertiesTo(layer); +void MirrorLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + Layer::PushPropertiesTo(layer, commit_state, unsafe_state); auto* mirror_layer = static_cast<MirrorLayerImpl*>(layer); mirror_layer->SetMirroredLayerId(mirrored_layer_->id()); diff --git a/chromium/cc/layers/mirror_layer.h b/chromium/cc/layers/mirror_layer.h index 9915dcf525d..6a875a94995 100644 --- a/chromium/cc/layers/mirror_layer.h +++ b/chromium/cc/layers/mirror_layer.h @@ -5,6 +5,8 @@ #ifndef CC_LAYERS_MIRROR_LAYER_H_ #define CC_LAYERS_MIRROR_LAYER_H_ +#include <memory> + #include "base/memory/scoped_refptr.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" @@ -23,7 +25,9 @@ class CC_EXPORT MirrorLayer : public Layer { // Layer overrides. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; void SetLayerTreeHost(LayerTreeHost* host) override; protected: diff --git a/chromium/cc/layers/mirror_layer_unittest.cc b/chromium/cc/layers/mirror_layer_unittest.cc index deaa92c1940..5d488e93f4c 100644 --- a/chromium/cc/layers/mirror_layer_unittest.cc +++ b/chromium/cc/layers/mirror_layer_unittest.cc @@ -4,7 +4,6 @@ #include <memory> -#include "base/containers/contains.h" #include "cc/animation/animation_host.h" #include "cc/layers/mirror_layer.h" #include "cc/layers/mirror_layer_impl.h" @@ -25,8 +24,10 @@ class MirrorLayerTest : public testing::Test { // Synchronizes |layer_tree_host_| and |host_impl_| and pushes surface ids. void SynchronizeTrees() { - TreeSynchronizer::PushLayerProperties(layer_tree_host_.get(), - host_impl_.pending_tree()); + TreeSynchronizer::PushLayerProperties( + *layer_tree_host_->GetPendingCommitState(), + layer_tree_host_->GetThreadUnsafeCommitState(), + host_impl_.pending_tree()); } protected: @@ -87,8 +88,10 @@ TEST_F(MirrorLayerTest, MirrorCount) { auto mirrored = Layer::Create(); mirrored->SetLayerTreeHost(layer_tree_host_.get()); + layer_tree_host_->WillCommit(/*completion_event=*/nullptr, + /*has_updates=*/true); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); layer_tree_host_->property_trees()->needs_rebuild = false; - layer_tree_host_->ClearLayersThatShouldPushProperties(); EXPECT_EQ(0, mirrored->mirror_count()); // Creating the first mirror layer should trigger property trees rebuild. @@ -96,22 +99,18 @@ TEST_F(MirrorLayerTest, MirrorCount) { EXPECT_EQ(1, mirrored->mirror_count()); EXPECT_EQ(mirrored.get(), mirror1->mirrored_layer()); EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), - mirrored.get())); - + EXPECT_TRUE(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties.contains(mirrored.get())); layer_tree_host_->property_trees()->needs_rebuild = false; - layer_tree_host_->ClearLayersThatShouldPushProperties(); // Creating a second mirror layer should not trigger property trees rebuild. auto mirror2 = MirrorLayer::Create(mirrored); EXPECT_EQ(2, mirrored->mirror_count()); EXPECT_EQ(mirrored.get(), mirror2->mirrored_layer()); EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), - mirrored.get())); - + EXPECT_TRUE(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties.contains(mirrored.get())); layer_tree_host_->property_trees()->needs_rebuild = false; - layer_tree_host_->ClearLayersThatShouldPushProperties(); // Destroying one of the mirror layers should not trigger property trees // rebuild. @@ -119,10 +118,9 @@ TEST_F(MirrorLayerTest, MirrorCount) { mirror1 = nullptr; EXPECT_EQ(1, mirrored->mirror_count()); EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_EQ(1u, layer_tree_host_->LayersThatShouldPushProperties().size()); - + EXPECT_EQ(1u, layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties.size()); layer_tree_host_->property_trees()->needs_rebuild = false; - layer_tree_host_->ClearLayersThatShouldPushProperties(); // Destroying the only remaining mirror layer should trigger property trees // rebuild. @@ -130,8 +128,9 @@ TEST_F(MirrorLayerTest, MirrorCount) { mirror2 = nullptr; EXPECT_EQ(0, mirrored->mirror_count()); EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild); - EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(), - mirrored.get())); + EXPECT_TRUE(layer_tree_host_->GetThreadUnsafeCommitState() + .layers_that_should_push_properties.contains(mirrored.get())); + layer_tree_host_->property_trees()->needs_rebuild = false; mirrored->SetLayerTreeHost(nullptr); } diff --git a/chromium/cc/layers/nine_patch_layer.cc b/chromium/cc/layers/nine_patch_layer.cc index d17ad28f049..57cad735ab0 100644 --- a/chromium/cc/layers/nine_patch_layer.cc +++ b/chromium/cc/layers/nine_patch_layer.cc @@ -65,8 +65,11 @@ void NinePatchLayer::SetLayerOcclusion(const gfx::Rect& occlusion) { SetNeedsCommit(); } -void NinePatchLayer::PushPropertiesTo(LayerImpl* layer) { - UIResourceLayer::PushPropertiesTo(layer); +void NinePatchLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + UIResourceLayer::PushPropertiesTo(layer, commit_state, unsafe_state); TRACE_EVENT0("cc", "NinePatchLayer::PushPropertiesTo"); NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); diff --git a/chromium/cc/layers/nine_patch_layer.h b/chromium/cc/layers/nine_patch_layer.h index f492e6e4c49..95ebaf10803 100644 --- a/chromium/cc/layers/nine_patch_layer.h +++ b/chromium/cc/layers/nine_patch_layer.h @@ -22,7 +22,9 @@ class CC_EXPORT NinePatchLayer : public UIResourceLayer { NinePatchLayer(const NinePatchLayer&) = delete; NinePatchLayer& operator=(const NinePatchLayer&) = delete; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; // |border| is the space around the center rectangular region in layer space // (known as aperture in image space). |border.x()| and |border.y()| are the diff --git a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc index 66649978044..52aaa8090d1 100644 --- a/chromium/cc/layers/nine_patch_layer_impl_unittest.cc +++ b/chromium/cc/layers/nine_patch_layer_impl_unittest.cc @@ -16,7 +16,6 @@ #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_ui_resource_layer_tree_host_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/trees/single_thread_proxy.h" #include "components/viz/common/quads/texture_draw_quad.h" diff --git a/chromium/cc/layers/nine_patch_layer_unittest.cc b/chromium/cc/layers/nine_patch_layer_unittest.cc index 6ec1d95ac1d..8707c981db8 100644 --- a/chromium/cc/layers/nine_patch_layer_unittest.cc +++ b/chromium/cc/layers/nine_patch_layer_unittest.cc @@ -9,7 +9,6 @@ #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface_client.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/single_thread_proxy.h" diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.cc b/chromium/cc/layers/painted_overlay_scrollbar_layer.cc index 2aef7086dd0..c28b1152882 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.cc @@ -62,8 +62,11 @@ bool PaintedOverlayScrollbarLayer::OpacityCanAnimateOnImplThread() const { return true; } -void PaintedOverlayScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { - ScrollbarLayerBase::PushPropertiesTo(layer); +void PaintedOverlayScrollbarLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + ScrollbarLayerBase::PushPropertiesTo(layer, commit_state, unsafe_state); PaintedOverlayScrollbarLayerImpl* scrollbar_layer = static_cast<PaintedOverlayScrollbarLayerImpl*>(layer); @@ -81,9 +84,11 @@ void PaintedOverlayScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { } if (thumb_resource_.get()) { - scrollbar_layer->SetImageBounds( - layer_tree_host()->GetUIResourceManager()->GetUIResourceSize( - thumb_resource_->id())); + auto iter = commit_state.ui_resource_sizes.find(thumb_resource_->id()); + gfx::Size image_bounds = (iter == commit_state.ui_resource_sizes.end()) + ? gfx::Size() + : iter->second; + scrollbar_layer->SetImageBounds(image_bounds); scrollbar_layer->SetAperture(aperture_); scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id()); } else { diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.h b/chromium/cc/layers/painted_overlay_scrollbar_layer.h index 8651c6f4144..0178d52cadc 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer.h +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.h @@ -5,6 +5,8 @@ #ifndef CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_ #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_ +#include <memory> + #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" @@ -34,7 +36,9 @@ class CC_EXPORT PaintedOverlayScrollbarLayer : public ScrollbarLayerBase { bool OpacityCanAnimateOnImplThread() const override; bool Update() override; void SetLayerTreeHost(LayerTreeHost* host) override; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; ScrollbarLayerType GetScrollbarLayerType() const override; diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc index 76480c8306c..ba4a40a8da4 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_scrollbar_layer.cc @@ -55,8 +55,11 @@ bool PaintedScrollbarLayer::OpacityCanAnimateOnImplThread() const { return is_overlay_; } -void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { - ScrollbarLayerBase::PushPropertiesTo(layer); +void PaintedScrollbarLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + ScrollbarLayerBase::PushPropertiesTo(layer, commit_state, unsafe_state); PaintedScrollbarLayerImpl* scrollbar_layer = static_cast<PaintedScrollbarLayerImpl*>(layer); diff --git a/chromium/cc/layers/painted_scrollbar_layer.h b/chromium/cc/layers/painted_scrollbar_layer.h index a449ffc64e7..1b3f0f38667 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.h +++ b/chromium/cc/layers/painted_scrollbar_layer.h @@ -5,6 +5,8 @@ #ifndef CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_ #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_ +#include <memory> + #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" @@ -33,7 +35,9 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerBase { bool OpacityCanAnimateOnImplThread() const override; bool Update() override; void SetLayerTreeHost(LayerTreeHost* host) override; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; const gfx::Size& internal_content_bounds() const { return internal_content_bounds_; diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc index 290cf5ec6f1..455d8a71ac9 100644 --- a/chromium/cc/layers/picture_layer.cc +++ b/chromium/cc/layers/picture_layer.cc @@ -51,13 +51,16 @@ std::unique_ptr<LayerImpl> PictureLayer::CreateLayerImpl( return PictureLayerImpl::Create(tree_impl, id()); } -void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { +void PictureLayer::PushPropertiesTo( + LayerImpl* base_layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { // TODO(enne): http://crbug.com/918126 debugging CHECK(this); PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); - Layer::PushPropertiesTo(base_layer); + Layer::PushPropertiesTo(base_layer, commit_state, unsafe_state); TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "PictureLayer::PushPropertiesTo"); DropRecordingSourceContentIfInvalid( @@ -65,7 +68,7 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { layer_impl->SetNearestNeighbor(picture_layer_inputs_.nearest_neighbor); layer_impl->set_gpu_raster_max_texture_size( - layer_tree_host()->device_viewport_rect().size()); + commit_state.device_viewport_rect.size()); layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask()); layer_impl->SetDirectlyCompositedImageSize( picture_layer_inputs_.directly_composited_image_size); @@ -184,7 +187,7 @@ bool PictureLayer::Update() { return updated; } -sk_sp<SkPicture> PictureLayer::GetPicture() const { +sk_sp<const SkPicture> PictureLayer::GetPicture() const { if (!DrawsContent() || bounds().IsEmpty()) return nullptr; @@ -231,7 +234,7 @@ void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) { } void PictureLayer::CaptureContent(const gfx::Rect& rect, - std::vector<NodeInfo>* content) { + std::vector<NodeInfo>* content) const { if (!DrawsContent()) return; @@ -295,7 +298,7 @@ void PictureLayer::DropRecordingSourceContentIfInvalid( } } -const DisplayItemList* PictureLayer::GetDisplayItemList() { +const DisplayItemList* PictureLayer::GetDisplayItemList() const { return picture_layer_inputs_.display_list.get(); } diff --git a/chromium/cc/layers/picture_layer.h b/chromium/cc/layers/picture_layer.h index e99202e4e3a..05bfc3cf9e5 100644 --- a/chromium/cc/layers/picture_layer.h +++ b/chromium/cc/layers/picture_layer.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/base/devtools_instrumentation.h" #include "cc/base/invalidation_region.h" #include "cc/benchmarks/micro_benchmark_controller.h" @@ -41,13 +42,15 @@ class CC_EXPORT PictureLayer : public Layer { // Layer interface. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetLayerTreeHost(LayerTreeHost* host) override; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; void SetNeedsDisplayRect(const gfx::Rect& layer_rect) override; - sk_sp<SkPicture> GetPicture() const override; + sk_sp<const SkPicture> GetPicture() const override; bool Update() override; void RunMicroBenchmark(MicroBenchmark* benchmark) override; void CaptureContent(const gfx::Rect& rect, - std::vector<NodeInfo>* content) override; + std::vector<NodeInfo>* content) const override; ContentLayerClient* client() { return picture_layer_inputs_.client; } @@ -55,7 +58,7 @@ class CC_EXPORT PictureLayer : public Layer { return recording_source_.get(); } - const DisplayItemList* GetDisplayItemList(); + const DisplayItemList* GetDisplayItemList() const; protected: // Encapsulates all data, callbacks or interfaces received from the embedder. @@ -63,7 +66,7 @@ class CC_EXPORT PictureLayer : public Layer { PictureLayerInputs(); ~PictureLayerInputs(); - ContentLayerClient* client = nullptr; + raw_ptr<ContentLayerClient> client = nullptr; bool nearest_neighbor = false; bool is_backdrop_filter_mask = false; scoped_refptr<DisplayItemList> display_list; diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h index 92889279833..8003550dbd9 100644 --- a/chromium/cc/layers/picture_layer_impl.h +++ b/chromium/cc/layers/picture_layer_impl.h @@ -14,6 +14,7 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" @@ -176,6 +177,8 @@ class CC_EXPORT PictureLayerImpl } protected: + friend class RasterizeAndRecordBenchmarkImpl; + PictureLayerImpl(LayerTreeImpl* tree_impl, int id); PictureLayerTiling* AddTiling(const gfx::AxisTransform2d& contents_transform); void RemoveAllTilings(); @@ -240,7 +243,7 @@ class CC_EXPORT PictureLayerImpl // will change transform. bool HasWillChangeTransformHint() const; - PictureLayerImpl* twin_layer_ = nullptr; + raw_ptr<PictureLayerImpl> twin_layer_ = nullptr; std::unique_ptr<PictureLayerTilingSet> tilings_ = CreatePictureLayerTilingSet(); diff --git a/chromium/cc/layers/picture_layer_impl_perftest.cc b/chromium/cc/layers/picture_layer_impl_perftest.cc index d4567bcefad..4bb3d8146d7 100644 --- a/chromium/cc/layers/picture_layer_impl_perftest.cc +++ b/chromium/cc/layers/picture_layer_impl_perftest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/raw_ptr.h" #include "cc/layers/picture_layer_impl.h" #include "base/threading/thread_task_runner_handle.h" @@ -97,8 +98,7 @@ class PictureLayerImplPerfTest : public LayerTreeImplTestBase, ->pending_tree() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - pending_layer_->element_id(), - gfx::Vector2dF(viewport.x(), viewport.y())); + pending_layer_->element_id(), gfx::PointF(viewport.origin())); host_impl()->pending_tree()->UpdateDrawProperties(); timer_.Reset(); @@ -145,8 +145,7 @@ class PictureLayerImplPerfTest : public LayerTreeImplTestBase, ->pending_tree() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - pending_layer_->element_id(), - gfx::Vector2dF(viewport.x(), viewport.y())); + pending_layer_->element_id(), gfx::PointF(viewport.origin())); host_impl()->pending_tree()->UpdateDrawProperties(); timer_.Reset(); @@ -172,7 +171,7 @@ class PictureLayerImplPerfTest : public LayerTreeImplTestBase, return reporter; } - FakePictureLayerImpl* pending_layer_; + raw_ptr<FakePictureLayerImpl> pending_layer_; base::LapTimer timer_; }; diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc index 2bd4a017bbc..1187a517f67 100644 --- a/chromium/cc/layers/picture_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_layer_impl_unittest.cc @@ -14,6 +14,7 @@ #include "base/cxx17_backports.h" #include "base/location.h" +#include "base/memory/raw_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" #include "cc/base/math_util.h" @@ -28,7 +29,6 @@ #include "cc/test/fake_picture_layer_impl.h" #include "cc/test/fake_raster_source.h" #include "cc/test/fake_recording_source.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/test/skia_common.h" #include "cc/test/test_layer_tree_host_base.h" @@ -43,7 +43,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/test/gfx_util.h" +#include "ui/gfx/geometry/test/geometry_util.h" namespace cc { namespace { @@ -5226,7 +5226,7 @@ TEST_F(LegacySWPictureLayerImplTest, ScrollPropagatesToPending) { SetupDefaultTrees(layer_bounds); - active_layer()->SetCurrentScrollOffset(gfx::Vector2dF(0.0, 50.0)); + active_layer()->SetCurrentScrollOffset(gfx::PointF(0.0, 50.0)); UpdateDrawProperties(host_impl()->active_tree()); EXPECT_EQ("0,50 100x100", active_layer() ->HighResTiling() @@ -6153,7 +6153,7 @@ TEST_F(LegacySWPictureLayerImplTest, NoTilingsUsesScaleOne) { auto* shared_quad_state = render_pass->quad_list.begin()->shared_quad_state; // We should use scale 1 here, so the layer rect should be full layer bounds // and the transform should be identity. - EXPECT_RECT_EQ(gfx::Rect(1000, 10000), shared_quad_state->quad_layer_rect); + EXPECT_EQ(gfx::Rect(1000, 10000), shared_quad_state->quad_layer_rect); EXPECT_TRUE(shared_quad_state->quad_to_target_transform.IsIdentity()); } @@ -6302,9 +6302,9 @@ class LCDTextTest : public PictureLayerImplTest, } } - LayerTreeImpl* tree_ = nullptr; - PictureLayerImpl* layer_ = nullptr; - PictureLayerImpl* descendant_ = nullptr; + raw_ptr<LayerTreeImpl> tree_ = nullptr; + raw_ptr<PictureLayerImpl> layer_ = nullptr; + raw_ptr<PictureLayerImpl> descendant_ = nullptr; }; INSTANTIATE_TEST_SUITE_P(All, @@ -6322,7 +6322,7 @@ TEST_P(LCDTextTest, IdentityTransform) { TEST_P(LCDTextTest, IntegralTransform) { gfx::Transform integral_translation; integral_translation.Translate(1.0, 2.0); - SetTransform(layer_, integral_translation); + SetTransform(layer_.get(), integral_translation); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "integral transform"); } @@ -6331,13 +6331,13 @@ TEST_P(LCDTextTest, NonIntegralTranslation) { // Non-integral translation. gfx::Transform non_integral_translation; non_integral_translation.Translate(1.5, 2.5); - SetTransform(layer_, non_integral_translation); + SetTransform(layer_.get(), non_integral_translation); // We can use LCD-text as raster translation can align the text to physical // pixels for fragtional transform in the render target. CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "non-integeral translation"); - SetTransform(layer_, gfx::Transform()); + SetTransform(layer_.get(), gfx::Transform()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "identity transform"); } @@ -6345,13 +6345,13 @@ TEST_P(LCDTextTest, NonIntegralTranslationAboveRenderTarget) { // Non-integral translation above render target. gfx::Transform non_integral_translation; non_integral_translation.Translate(1.5, 2.5); - SetTransform(layer_, non_integral_translation); - SetRenderSurfaceReason(layer_, RenderSurfaceReason::kTest); + SetTransform(layer_.get(), non_integral_translation); + SetRenderSurfaceReason(layer_.get(), RenderSurfaceReason::kTest); // Raster translation can't handle fractional transform above the render // target, so LCD text is not allowed. CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation, "non-integeral translation above render target"); - SetTransform(layer_, gfx::Transform()); + SetTransform(layer_.get(), gfx::Transform()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "identity transform"); } @@ -6359,63 +6359,64 @@ TEST_P(LCDTextTest, NonTranslation) { // Rotation. gfx::Transform rotation; rotation.Rotate(10.0); - SetTransform(layer_, rotation); + SetTransform(layer_.get(), rotation); CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation, "Rotation transform"); // Scale. LCD text is allowed. gfx::Transform scale; scale.Scale(2.0, 2.0); - SetTransform(layer_, scale); + SetTransform(layer_.get(), scale); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "Scale transform"); // Skew. gfx::Transform skew; skew.Skew(10.0, 0.0); - SetTransform(layer_, skew); + SetTransform(layer_.get(), skew); CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation, "Skew transform"); - SetTransform(layer_, gfx::Transform()); + SetTransform(layer_.get(), gfx::Transform()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "identity transform"); } TEST_P(LCDTextTest, NonTranslationAboveRenderTarget) { - SetRenderSurfaceReason(layer_, RenderSurfaceReason::kTest); + SetRenderSurfaceReason(layer_.get(), RenderSurfaceReason::kTest); // Rotation. gfx::Transform rotation; rotation.Rotate(10.0); - SetTransform(layer_, rotation); + SetTransform(layer_.get(), rotation); CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation, "rotation transform above render target"); // Scale. LCD-text is allowed. gfx::Transform scale; scale.Scale(2.0, 2.0); - // Apply perspective to prevent the scale from applying to the layers below - // the render target. + // Apply perspective and rotation to prevent the scale from applying + // to the layers below the render target. scale.ApplyPerspectiveDepth(10); - SetTransform(layer_, scale); + scale.RotateAboutXAxis(15.0); + SetTransform(layer_.get(), scale); CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation, "scale transform above render target"); // Skew. gfx::Transform skew; skew.Skew(10.0, 0.0); - SetTransform(layer_, skew); + SetTransform(layer_.get(), skew); CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation, "skew transform above render target"); - SetTransform(layer_, gfx::Transform()); + SetTransform(layer_.get(), gfx::Transform()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "identity transform"); } TEST_P(LCDTextTest, Opacity) { // LCD-text is allowed with opacity paint property. - SetOpacity(layer_, 0.5f); + SetOpacity(layer_.get(), 0.5f); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "opacity: 0.5"); - SetOpacity(layer_, 1.f); + SetOpacity(layer_.get(), 1.f); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "opacity: 1.0"); } @@ -6440,11 +6441,11 @@ TEST_P(LCDTextTest, ContentsNotOpaque) { } TEST_P(LCDTextTest, WillChangeTransform) { - SetWillChangeTransform(layer_, true); + SetWillChangeTransform(layer_.get(), true); CheckCanUseLCDText(LCDTextDisallowedReason::kWillChangeTransform, "will-change:transform"); - SetWillChangeTransform(layer_, false); + SetWillChangeTransform(layer_.get(), false); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "no will-change: transform"); } @@ -6452,40 +6453,40 @@ TEST_P(LCDTextTest, WillChangeTransform) { TEST_P(LCDTextTest, Filter) { FilterOperations blur_filter; blur_filter.Append(FilterOperation::CreateBlurFilter(4.0f)); - SetFilter(layer_, blur_filter); + SetFilter(layer_.get(), blur_filter); CheckCanUseLCDText(LCDTextDisallowedReason::kPixelOrColorEffect, "filter"); - SetFilter(layer_, FilterOperations()); + SetFilter(layer_.get(), FilterOperations()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "no filter"); } TEST_P(LCDTextTest, FilterAnimation) { FilterOperations blur_filter; blur_filter.Append(FilterOperation::CreateBlurFilter(4.0f)); - SetFilter(layer_, blur_filter); + SetFilter(layer_.get(), blur_filter); CheckCanUseLCDText(LCDTextDisallowedReason::kPixelOrColorEffect, "filter"); - GetEffectNode(layer_)->has_potential_filter_animation = true; - SetFilter(layer_, FilterOperations()); + GetEffectNode(layer_.get())->has_potential_filter_animation = true; + SetFilter(layer_.get(), FilterOperations()); CheckCanUseLCDText(LCDTextDisallowedReason::kPixelOrColorEffect, "filter animation"); - GetEffectNode(layer_)->has_potential_filter_animation = false; - SetFilter(layer_, FilterOperations()); + GetEffectNode(layer_.get())->has_potential_filter_animation = false; + SetFilter(layer_.get(), FilterOperations()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "no filter"); } TEST_P(LCDTextTest, BackdropFilter) { FilterOperations backdrop_filter; backdrop_filter.Append(FilterOperation::CreateBlurFilter(4.0f)); - SetBackdropFilter(descendant_, backdrop_filter); + SetBackdropFilter(descendant_.get(), backdrop_filter); UpdateDrawProperties(host_impl()->active_tree()); CheckCanUseLCDText(LCDTextDisallowedReason::kPixelOrColorEffect, "backdrop-filter", layer_); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "backdrop-filter", descendant_); - SetBackdropFilter(descendant_, FilterOperations()); + SetBackdropFilter(descendant_.get(), FilterOperations()); UpdateDrawProperties(host_impl()->active_tree()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "no backdrop-filter", layer_); @@ -6494,20 +6495,22 @@ TEST_P(LCDTextTest, BackdropFilter) { TEST_P(LCDTextTest, BackdropFilterAnimation) { FilterOperations backdrop_filter; backdrop_filter.Append(FilterOperation::CreateBlurFilter(4.0f)); - SetBackdropFilter(descendant_, backdrop_filter); + SetBackdropFilter(descendant_.get(), backdrop_filter); UpdateDrawProperties(host_impl()->active_tree()); CheckCanUseLCDText(LCDTextDisallowedReason::kPixelOrColorEffect, "backdrop-filter", layer_); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "backdrop-filter", descendant_); - GetEffectNode(descendant_)->has_potential_backdrop_filter_animation = true; - SetBackdropFilter(descendant_, FilterOperations()); + GetEffectNode(descendant_.get())->has_potential_backdrop_filter_animation = + true; + SetBackdropFilter(descendant_.get(), FilterOperations()); UpdateDrawProperties(host_impl()->active_tree()); CheckCanUseLCDText(LCDTextDisallowedReason::kPixelOrColorEffect, "backdrop-filter animation", layer_); - GetEffectNode(descendant_)->has_potential_backdrop_filter_animation = false; + GetEffectNode(descendant_.get())->has_potential_backdrop_filter_animation = + false; UpdateDrawProperties(host_impl()->active_tree()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "no backdrop-filter", layer_); @@ -6526,13 +6529,13 @@ TEST_P(LCDTextTest, ContentsOpaqueForText) { } TEST_P(LCDTextTest, TransformAnimation) { - GetTransformNode(layer_)->has_potential_animation = true; - SetLocalTransformChanged(layer_); + GetTransformNode(layer_.get())->has_potential_animation = true; + SetLocalTransformChanged(layer_.get()); CheckCanUseLCDText(LCDTextDisallowedReason::kTransformAnimation, "transform animation"); - GetTransformNode(layer_)->has_potential_animation = false; - SetLocalTransformChanged(layer_); + GetTransformNode(layer_.get())->has_potential_animation = false; + SetLocalTransformChanged(layer_.get()); CheckCanUseLCDText(LCDTextDisallowedReason::kNone, "no transform animation"); } diff --git a/chromium/cc/layers/picture_layer_unittest.cc b/chromium/cc/layers/picture_layer_unittest.cc index d1f8dcacc03..986784742ad 100644 --- a/chromium/cc/layers/picture_layer_unittest.cc +++ b/chromium/cc/layers/picture_layer_unittest.cc @@ -52,8 +52,9 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) { layer->Update(); EXPECT_EQ(0, host->SourceFrameNumber()); - host->WillCommit(nullptr); - host->CommitComplete(); + host->WillCommit(/*completion=*/nullptr, /*has_updates=*/false); + EXPECT_EQ(1, host->SourceFrameNumber()); + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_EQ(1, host->SourceFrameNumber()); layer->SetBounds(gfx::Size(0, 0)); @@ -67,12 +68,16 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) { FakeLayerTreeHostImpl host_impl( LayerTreeSettings(), &impl_task_runner_provider, &task_graph_runner); host_impl.InitializeFrameSink(layer_tree_frame_sink.get()); - host->WillCommit(nullptr); host_impl.CreatePendingTree(); std::unique_ptr<FakePictureLayerImpl> layer_impl = FakePictureLayerImpl::Create(host_impl.pending_tree(), 1); - layer->PushPropertiesTo(layer_impl.get()); + // Here and elsewhere: when doing a full commit, we would call + // layer_tree_host_->ActivateCommitState() and the second argument would come + // from layer_tree_host_->active_commit_state(); we use pending_commit_state() + // just to keep the test code simple. + layer->PushPropertiesTo(layer_impl.get(), *host->GetPendingCommitState(), + host->GetThreadUnsafeCommitState()); EXPECT_FALSE(layer_impl->CanHaveTilings()); EXPECT_TRUE(layer_impl->bounds() == gfx::Size(0, 0)); EXPECT_EQ(gfx::Size(), layer_impl->raster_source()->GetSize()); @@ -100,8 +105,6 @@ TEST(PictureLayerTest, InvalidateRasterAfterUpdate) { layer->SetNeedsDisplayRect(invalidation_bounds); layer->Update(); - host->WillCommit(nullptr); - host->CommitComplete(); FakeImplTaskRunnerProvider impl_task_runner_provider; std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink( FakeLayerTreeFrameSink::Create3d()); @@ -115,7 +118,8 @@ TEST(PictureLayerTest, InvalidateRasterAfterUpdate) { FakePictureLayerImpl::Create(host_impl.pending_tree(), 1)); FakePictureLayerImpl* layer_impl = static_cast<FakePictureLayerImpl*>( host_impl.pending_tree()->root_layer()); - layer->PushPropertiesTo(layer_impl); + layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), + host->GetThreadUnsafeCommitState()); EXPECT_EQ(invalidation_bounds, layer_impl->GetPendingInvalidation()->bounds()); @@ -141,8 +145,6 @@ TEST(PictureLayerTest, InvalidateRasterWithoutUpdate) { // The important line is the following (note that we do not call Update): layer->SetNeedsDisplayRect(invalidation_bounds); - host->WillCommit(nullptr); - host->CommitComplete(); FakeImplTaskRunnerProvider impl_task_runner_provider; std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink( FakeLayerTreeFrameSink::Create3d()); @@ -157,7 +159,8 @@ TEST(PictureLayerTest, InvalidateRasterWithoutUpdate) { FakePictureLayerImpl::Create(host_impl.pending_tree(), 1)); FakePictureLayerImpl* layer_impl = static_cast<FakePictureLayerImpl*>( host_impl.pending_tree()->root_layer()); - layer->PushPropertiesTo(layer_impl); + layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), + host->GetThreadUnsafeCommitState()); EXPECT_EQ(gfx::Rect(), layer_impl->GetPendingInvalidation()->bounds()); } @@ -180,8 +183,8 @@ TEST(PictureLayerTest, ClearVisibleRectWhenNoTiling) { layer->Update(); EXPECT_EQ(0, host->SourceFrameNumber()); - host->WillCommit(nullptr); - host->CommitComplete(); + host->WillCommit(/*completion=*/nullptr, /*has_updates=*/false); + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_EQ(1, host->SourceFrameNumber()); layer->Update(); @@ -203,11 +206,13 @@ TEST(PictureLayerTest, ClearVisibleRectWhenNoTiling) { host_impl.pending_tree()->root_layer()); SetupRootProperties(layer_impl); UpdateDrawProperties(host_impl.pending_tree()); - host->WillCommit(nullptr); - layer->PushPropertiesTo(layer_impl); + const auto& unsafe_state = host->GetThreadUnsafeCommitState(); + std::unique_ptr<CommitState> commit_state = + host->WillCommit(/*completion=*/nullptr, /*has_updates=*/true); + layer->PushPropertiesTo(layer_impl, *commit_state, unsafe_state); + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); - host->CommitComplete(); EXPECT_EQ(2, host->SourceFrameNumber()); host_impl.ActivateSyncTree(); @@ -218,14 +223,14 @@ TEST(PictureLayerTest, ClearVisibleRectWhenNoTiling) { layer->SetBounds(gfx::Size(11, 11)); - host->WillCommit(nullptr); host_impl.CreatePendingTree(); layer_impl = static_cast<FakePictureLayerImpl*>( host_impl.pending_tree()->root_layer()); // We should now have invalid contents and should therefore clear the // recording source. - layer->PushPropertiesTo(layer_impl); + layer->PushPropertiesTo(layer_impl, *host->GetPendingCommitState(), + host->GetThreadUnsafeCommitState()); UpdateDrawProperties(host_impl.pending_tree()); host_impl.ActivateSyncTree(); diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc index 319bc82dfc5..4a99f99bdf5 100644 --- a/chromium/cc/layers/render_surface_impl.cc +++ b/chromium/cc/layers/render_surface_impl.cc @@ -402,6 +402,8 @@ RenderSurfaceImpl::CreateRenderPass() { pass->cache_render_pass = ShouldCacheRenderSurface(); pass->has_damage_from_contributing_content = HasDamageFromeContributingContent(); + pass->shared_element_resource_id = + OwningEffectNode()->shared_element_resource_id; return pass; } @@ -413,6 +415,12 @@ void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, if (unoccluded_content_rect.IsEmpty()) return; + // If this render surface has a valid |shared_element_resource_id| then its + // being used to produce live content. Its content will be drawn to its + // actual position in the Viz process. + if (OwningEffectNode()->shared_element_resource_id.IsValid()) + return; + const PropertyTrees* property_trees = layer_tree_impl_->property_trees(); int sorting_context_id = property_trees->transform_tree.Node(TransformTreeIndex()) diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h index bde641b5f7e..b6bf8fb52b5 100644 --- a/chromium/cc/layers/render_surface_impl.h +++ b/chromium/cc/layers/render_surface_impl.h @@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/document_transition/document_transition_shared_element_id.h" #include "cc/layers/draw_mode.h" @@ -232,7 +233,7 @@ class CC_EXPORT RenderSurfaceImpl { viz::SharedQuadState* shared_quad_state, const gfx::Rect& unoccluded_content_rect); - LayerTreeImpl* layer_tree_impl_; + raw_ptr<LayerTreeImpl> layer_tree_impl_; uint64_t stable_id_; int effect_tree_index_; @@ -283,7 +284,7 @@ class CC_EXPORT RenderSurfaceImpl { // The nearest ancestor target surface that will contain the contents of this // surface, and that ignores outside occlusion. This can point to itself. - const RenderSurfaceImpl* nearest_occlusion_immune_ancestor_; + raw_ptr<const RenderSurfaceImpl> nearest_occlusion_immune_ancestor_; std::unique_ptr<DamageTracker> damage_tracker_; }; diff --git a/chromium/cc/layers/render_surface_unittest.cc b/chromium/cc/layers/render_surface_unittest.cc index 472b5dea104..ae931c85b84 100644 --- a/chromium/cc/layers/render_surface_unittest.cc +++ b/chromium/cc/layers/render_surface_unittest.cc @@ -9,7 +9,6 @@ #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_picture_layer_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/test/mock_occlusion_tracker.h" #include "cc/test/test_task_graph_runner.h" diff --git a/chromium/cc/layers/scrollbar_layer_base.cc b/chromium/cc/layers/scrollbar_layer_base.cc index 993fd4adfe4..148ce6015f5 100644 --- a/chromium/cc/layers/scrollbar_layer_base.cc +++ b/chromium/cc/layers/scrollbar_layer_base.cc @@ -70,8 +70,11 @@ void ScrollbarLayerBase::SetScrollElementId(ElementId element_id) { SetNeedsCommit(); } -void ScrollbarLayerBase::PushPropertiesTo(LayerImpl* layer) { - Layer::PushPropertiesTo(layer); +void ScrollbarLayerBase::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + Layer::PushPropertiesTo(layer, commit_state, unsafe_state); auto* scrollbar_layer_impl = static_cast<ScrollbarLayerImplBase*>(layer); DCHECK_EQ(scrollbar_layer_impl->orientation(), orientation_); diff --git a/chromium/cc/layers/scrollbar_layer_base.h b/chromium/cc/layers/scrollbar_layer_base.h index 394e5087acb..eb5cd0b9956 100644 --- a/chromium/cc/layers/scrollbar_layer_base.h +++ b/chromium/cc/layers/scrollbar_layer_base.h @@ -24,7 +24,9 @@ class CC_EXPORT ScrollbarLayerBase : public Layer { return is_left_side_vertical_scrollbar_; } - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; enum ScrollbarLayerType { kSolidColor, diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc index e9c2590b952..c50bd285d1f 100644 --- a/chromium/cc/layers/scrollbar_layer_unittest.cc +++ b/chromium/cc/layers/scrollbar_layer_unittest.cc @@ -7,6 +7,7 @@ #include <memory> #include <unordered_map> +#include "base/memory/raw_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" #include "cc/input/scrollbar_animation_controller.h" @@ -24,7 +25,6 @@ #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_painted_scrollbar_layer.h" #include "cc/test/fake_scrollbar.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/test/layer_tree_test.h" #include "cc/test/mock_occlusion_tracker.h" @@ -133,7 +133,7 @@ class BaseScrollbarLayerTest : public testing::Test { } protected: - FakeResourceTrackingUIResourceManager* fake_ui_resource_manager_; + raw_ptr<FakeResourceTrackingUIResourceManager> fake_ui_resource_manager_; FakeLayerTreeHostClient fake_client_; StubLayerTreeHostSingleThreadClient single_thread_client_; TestTaskGraphRunner task_graph_runner_; @@ -248,7 +248,9 @@ TEST_F(ScrollbarLayerTest, SetNeedsDisplayDoesNotRequireUpdate) { // Simulate commit to compositor thread. scrollbar_layer->PushPropertiesTo( - scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get()); + scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get(), + *layer_tree_host_->GetPendingCommitState(), + layer_tree_host_->GetThreadUnsafeCommitState()); scrollbar_layer->fake_scrollbar()->set_needs_repaint_thumb(false); scrollbar_layer->fake_scrollbar()->set_needs_repaint_track(false); @@ -355,13 +357,19 @@ TEST_F(ScrollbarLayerTest, ScrollElementIdPushedAcrossCommit) { ASSERT_TRUE(layer_tree_host_->needs_commit()); + // WillCommit(_, true) here will ensure that + // layer_tree_host_->active_commit_state() is populated, which is required + // during FinishCommitOnImplThread(). + auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); + std::unique_ptr<CommitState> commit_state = + layer_tree_host_->WillCommit(/*completion=*/nullptr, + /*has_updates=*/true); { DebugScopedSetImplThread scoped_impl_thread( layer_tree_host_->GetTaskRunnerProvider()); - layer_tree_host_->FinishCommitOnImplThread( - layer_tree_host_->host_impl(), - layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises()); + layer_tree_host_->host_impl()->FinishCommit(*commit_state, unsafe_state); } + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_EQ(painted_scrollbar_layer_impl->scroll_element_id_, layer_b->element_id()); @@ -382,7 +390,7 @@ TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { // Choose bounds to give max_scroll_offset = (30, 50). layer_tree_root->SetBounds(gfx::Size(70, 150)); - scroll_layer->SetScrollOffset(gfx::Vector2dF(10, 20)); + scroll_layer->SetScrollOffset(gfx::PointF(10, 20)); scroll_layer->SetBounds(gfx::Size(100, 200)); scroll_layer->SetScrollable(gfx::Size(70, 150)); content_layer->SetBounds(gfx::Size(100, 200)); @@ -409,7 +417,7 @@ TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) { layer_tree_root->SetBounds(gfx::Size(700, 1500)); scroll_layer->SetScrollable(gfx::Size(700, 1500)); scroll_layer->SetBounds(gfx::Size(1000, 2000)); - scroll_layer->SetScrollOffset(gfx::Vector2dF(100, 200)); + scroll_layer->SetScrollOffset(gfx::PointF(100, 200)); content_layer->SetBounds(gfx::Size(1000, 2000)); layer_tree_host_->UpdateLayers(); @@ -455,7 +463,7 @@ TEST_F(ScrollbarLayerTest, UpdatePropertiesOfScrollBarWhenThumbRemoved) { root_layer->AddChild(content_layer); root_layer->AddChild(scrollbar_layer); - root_layer->SetScrollOffset(gfx::Vector2dF(0, 0)); + root_layer->SetScrollOffset(gfx::PointF(0, 0)); scrollbar_layer->SetBounds(gfx::Size(70, 10)); // The track_rect should be relative to the scrollbar's origin. @@ -493,7 +501,7 @@ TEST_F(ScrollbarLayerTest, ThumbRect) { root_layer->AddChild(content_layer); root_layer->AddChild(scrollbar_layer); - root_layer->SetScrollOffset(gfx::Vector2dF(0, 0)); + root_layer->SetScrollOffset(gfx::PointF(0, 0)); scrollbar_layer->SetBounds(gfx::Size(70, 10)); // The track_rect should be relative to the scrollbar's origin. @@ -512,14 +520,14 @@ TEST_F(ScrollbarLayerTest, ThumbRect) { scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); // Under-scroll (thumb position should clamp and be unchanged). - root_layer->SetScrollOffset(gfx::Vector2dF(-5, 0)); + root_layer->SetScrollOffset(gfx::PointF(-5, 0)); UPDATE_AND_EXTRACT_LAYER_POINTERS(); EXPECT_EQ(gfx::Rect(10, 0, 4, 10).ToString(), scrollbar_layer_impl->ComputeThumbQuadRect().ToString()); // Over-scroll (thumb position should clamp on the far side). - root_layer->SetScrollOffset(gfx::Vector2dF(85, 0)); + root_layer->SetScrollOffset(gfx::PointF(85, 0)); layer_tree_host_->UpdateLayers(); UPDATE_AND_EXTRACT_LAYER_POINTERS(); @@ -564,7 +572,7 @@ TEST_F(ScrollbarLayerTest, ThumbRectForOverlayLeftSideVerticalScrollbar) { layer_tree_host_->SetRootLayer(root_layer); root_layer->AddChild(scrollbar_layer); - root_layer->SetScrollOffset(gfx::Vector2dF(0, 0)); + root_layer->SetScrollOffset(gfx::PointF(0, 0)); scrollbar_layer->SetBounds(gfx::Size(10, 20)); scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(0, 0, 10, 20)); scrollbar_layer->fake_scrollbar()->set_thumb_size(gfx::Size(10, 4)); @@ -1140,7 +1148,7 @@ class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest { scrollbar_layer->SetIsDrawable(true); scrollbar_layer->SetBounds(gfx::Size(100, 100)); layer_tree_root->SetScrollable(gfx::Size(100, 200)); - layer_tree_root->SetScrollOffset(gfx::Vector2dF(10, 20)); + layer_tree_root->SetScrollOffset(gfx::PointF(10, 20)); layer_tree_root->SetBounds(gfx::Size(100, 200)); content_layer->SetBounds(gfx::Size(100, 200)); @@ -1328,7 +1336,9 @@ TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) { // Simulate commit to compositor thread. scrollbar_layer->PushPropertiesTo( - scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get()); + scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get(), + *layer_tree_host_->GetPendingCommitState(), + layer_tree_host_->GetThreadUnsafeCommitState()); scrollbar_layer->fake_scrollbar()->set_needs_repaint_thumb(false); scrollbar_layer->fake_scrollbar()->set_needs_repaint_track(false); diff --git a/chromium/cc/layers/shared_element_layer.cc b/chromium/cc/layers/shared_element_layer.cc new file mode 100644 index 00000000000..2a4cc024700 --- /dev/null +++ b/chromium/cc/layers/shared_element_layer.cc @@ -0,0 +1,30 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layers/shared_element_layer.h" + +#include "cc/layers/shared_element_layer_impl.h" +#include "cc/trees/layer_tree_host.h" + +#include "base/logging.h" + +namespace cc { + +scoped_refptr<SharedElementLayer> SharedElementLayer::Create( + const viz::SharedElementResourceId& resource_id) { + return base::WrapRefCounted(new SharedElementLayer(resource_id)); +} + +SharedElementLayer::SharedElementLayer( + const viz::SharedElementResourceId& resource_id) + : resource_id_(resource_id) {} + +SharedElementLayer::~SharedElementLayer() = default; + +std::unique_ptr<LayerImpl> SharedElementLayer::CreateLayerImpl( + LayerTreeImpl* tree_impl) { + return SharedElementLayerImpl::Create(tree_impl, id(), resource_id_); +} + +} // namespace cc diff --git a/chromium/cc/layers/shared_element_layer.h b/chromium/cc/layers/shared_element_layer.h new file mode 100644 index 00000000000..e11546b7779 --- /dev/null +++ b/chromium/cc/layers/shared_element_layer.h @@ -0,0 +1,43 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_LAYERS_SHARED_ELEMENT_LAYER_H_ +#define CC_LAYERS_SHARED_ELEMENT_LAYER_H_ + +#include "base/logging.h" + +#include "cc/cc_export.h" +#include "cc/layers/layer.h" +#include "components/viz/common/shared_element_resource_id.h" + +namespace cc { + +// A layer that renders a texture cached in the Viz process. +class CC_EXPORT SharedElementLayer : public Layer { + public: + static scoped_refptr<SharedElementLayer> Create( + const viz::SharedElementResourceId& resource_id); + + SharedElementLayer(const SharedElementLayer&) = delete; + SharedElementLayer& operator=(const SharedElementLayer&) = delete; + + const viz::SharedElementResourceId& resource_id() const { + return resource_id_; + } + + // Layer overrides. + std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; + + protected: + explicit SharedElementLayer(const viz::SharedElementResourceId& resource_id); + + private: + ~SharedElementLayer() override; + + const viz::SharedElementResourceId resource_id_; +}; + +} // namespace cc + +#endif // CC_LAYERS_SHARED_ELEMENT_LAYER_H_ diff --git a/chromium/cc/layers/shared_element_layer_impl.cc b/chromium/cc/layers/shared_element_layer_impl.cc new file mode 100644 index 00000000000..006e2d9b3c8 --- /dev/null +++ b/chromium/cc/layers/shared_element_layer_impl.cc @@ -0,0 +1,69 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layers/shared_element_layer_impl.h" + +#include "cc/layers/append_quads_data.h" +#include "cc/layers/layer_impl.h" +#include "cc/trees/layer_tree_impl.h" +#include "components/viz/common/quads/shared_element_draw_quad.h" +#include "components/viz/common/shared_element_resource_id.h" + +namespace cc { + +// static +std::unique_ptr<SharedElementLayerImpl> SharedElementLayerImpl::Create( + LayerTreeImpl* tree_impl, + int id, + const viz::SharedElementResourceId& resource_id) { + return base::WrapUnique( + new SharedElementLayerImpl(tree_impl, id, resource_id)); +} + +SharedElementLayerImpl::SharedElementLayerImpl( + LayerTreeImpl* tree_impl, + int id, + const viz::SharedElementResourceId& resource_id) + : LayerImpl(tree_impl, id), resource_id_(resource_id) {} + +SharedElementLayerImpl::~SharedElementLayerImpl() = default; + +std::unique_ptr<LayerImpl> SharedElementLayerImpl::CreateLayerImpl( + LayerTreeImpl* tree_impl) { + return SharedElementLayerImpl::Create(tree_impl, id(), resource_id_); +} + +void SharedElementLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass, + AppendQuadsData* append_quads_data) { + float device_scale_factor = layer_tree_impl()->device_scale_factor(); + + gfx::Rect quad_rect( + gfx::ScaleToEnclosingRect(gfx::Rect(bounds()), device_scale_factor)); + gfx::Rect visible_quad_rect = + draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( + gfx::Rect(bounds())); + + visible_quad_rect = + gfx::ScaleToEnclosingRect(visible_quad_rect, device_scale_factor); + visible_quad_rect = gfx::IntersectRects(quad_rect, visible_quad_rect); + + if (visible_quad_rect.IsEmpty()) + return; + + viz::SharedQuadState* shared_quad_state = + render_pass->CreateAndAppendSharedQuadState(); + PopulateScaledSharedQuadState(shared_quad_state, device_scale_factor, + contents_opaque()); + + auto* quad = + render_pass->CreateAndAppendDrawQuad<viz::SharedElementDrawQuad>(); + quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, resource_id_); + append_quads_data->has_shared_element_resources = true; +} + +const char* SharedElementLayerImpl::LayerTypeAsString() const { + return "cc::SharedElementLayerImpl"; +} + +} // namespace cc diff --git a/chromium/cc/layers/shared_element_layer_impl.h b/chromium/cc/layers/shared_element_layer_impl.h new file mode 100644 index 00000000000..92359beac4f --- /dev/null +++ b/chromium/cc/layers/shared_element_layer_impl.h @@ -0,0 +1,46 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_LAYERS_SHARED_ELEMENT_LAYER_IMPL_H_ +#define CC_LAYERS_SHARED_ELEMENT_LAYER_IMPL_H_ + +#include <memory> + +#include "cc/cc_export.h" +#include "cc/layers/layer_impl.h" +#include "components/viz/common/shared_element_resource_id.h" + +namespace cc { + +class CC_EXPORT SharedElementLayerImpl : public LayerImpl { + public: + static std::unique_ptr<SharedElementLayerImpl> Create( + LayerTreeImpl* tree_impl, + int id, + const viz::SharedElementResourceId& resource_id); + + SharedElementLayerImpl(const SharedElementLayerImpl&) = delete; + ~SharedElementLayerImpl() override; + + SharedElementLayerImpl& operator=(const SharedElementLayerImpl&) = delete; + + // LayerImpl overrides. + std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; + void AppendQuads(viz::CompositorRenderPass* render_pass, + AppendQuadsData* append_quads_data) override; + + protected: + SharedElementLayerImpl(LayerTreeImpl* tree_impl, + int id, + const viz::SharedElementResourceId& resource_id); + + private: + const char* LayerTypeAsString() const override; + + const viz::SharedElementResourceId resource_id_; +}; + +} // namespace cc + +#endif // CC_LAYERS_SHARED_ELEMENT_LAYER_IMPL_H_ diff --git a/chromium/cc/layers/solid_color_layer_impl_unittest.cc b/chromium/cc/layers/solid_color_layer_impl_unittest.cc index e2066774ea2..6c80c52dc8d 100644 --- a/chromium/cc/layers/solid_color_layer_impl_unittest.cc +++ b/chromium/cc/layers/solid_color_layer_impl_unittest.cc @@ -185,10 +185,13 @@ TEST_F(SolidColorLayerImplTest, VerifyNeedsBlending) { EXPECT_FALSE(layer->contents_opaque()); layer->SetBackgroundColor(SkColorSetARGB(255, 10, 20, 30)); EXPECT_TRUE(layer->contents_opaque()); + + auto& unsafe_state = host->GetUnsafeStateForCommit(); + std::unique_ptr<CommitState> commit_state = + host->WillCommit(/*completion=*/nullptr, /*has_updates=*/true); { DebugScopedSetImplThread scoped_impl_thread(host->GetTaskRunnerProvider()); - host->FinishCommitOnImplThread( - host->host_impl(), host->GetSwapPromiseManager()->TakeSwapPromises()); + host->host_impl()->FinishCommit(*commit_state, unsafe_state); LayerImpl* layer_impl = host->host_impl()->active_tree()->LayerById(layer->id()); @@ -209,14 +212,16 @@ TEST_F(SolidColorLayerImplTest, VerifyNeedsBlending) { EXPECT_TRUE( render_pass->quad_list.front()->shared_quad_state->are_contents_opaque); } + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); EXPECT_TRUE(layer->contents_opaque()); layer->SetBackgroundColor(SkColorSetARGB(254, 10, 20, 30)); EXPECT_FALSE(layer->contents_opaque()); + + commit_state = host->WillCommit(/*completion=*/nullptr, /*has_updates=*/true); { DebugScopedSetImplThread scoped_impl_thread(host->GetTaskRunnerProvider()); - host->FinishCommitOnImplThread( - host->host_impl(), host->GetSwapPromiseManager()->TakeSwapPromises()); + host->host_impl()->FinishCommit(*commit_state, unsafe_state); LayerImpl* layer_impl = host->host_impl()->active_tree()->LayerById(layer->id()); @@ -237,6 +242,7 @@ TEST_F(SolidColorLayerImplTest, VerifyNeedsBlending) { EXPECT_FALSE( render_pass->quad_list.front()->shared_quad_state->are_contents_opaque); } + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); } TEST_F(SolidColorLayerImplTest, Occlusion) { diff --git a/chromium/cc/layers/surface_layer.cc b/chromium/cc/layers/surface_layer.cc index cbfb533d36a..e49a864d661 100644 --- a/chromium/cc/layers/surface_layer.cc +++ b/chromium/cc/layers/surface_layer.cc @@ -155,8 +155,11 @@ void SurfaceLayer::SetLayerTreeHost(LayerTreeHost* host) { layer_tree_host()->AddSurfaceRange(surface_range_); } -void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) { - Layer::PushPropertiesTo(layer); +void SurfaceLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + Layer::PushPropertiesTo(layer, commit_state, unsafe_state); TRACE_EVENT0("cc", "SurfaceLayer::PushPropertiesTo"); SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer); layer_impl->SetRange(surface_range_, std::move(deadline_in_frames_)); diff --git a/chromium/cc/layers/surface_layer.h b/chromium/cc/layers/surface_layer.h index 6182a1a398b..7f8599ba285 100644 --- a/chromium/cc/layers/surface_layer.h +++ b/chromium/cc/layers/surface_layer.h @@ -64,7 +64,9 @@ class CC_EXPORT SurfaceLayer : public Layer { // Layer overrides. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetLayerTreeHost(LayerTreeHost* host) override; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; const viz::SurfaceId& surface_id() const { return surface_range_.end(); } diff --git a/chromium/cc/layers/surface_layer_unittest.cc b/chromium/cc/layers/surface_layer_unittest.cc index 9a2d6d65366..2ba3751761c 100644 --- a/chromium/cc/layers/surface_layer_unittest.cc +++ b/chromium/cc/layers/surface_layer_unittest.cc @@ -5,12 +5,13 @@ #include <stdint.h> #include <iostream> +#include <limits> #include <set> #include <vector> #include "base/location.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "cc/animation/animation_host.h" @@ -46,9 +47,16 @@ class SurfaceLayerTest : public testing::Test { // Synchronizes |layer_tree_host_| and |host_impl_| and pushes surface ids. void SynchronizeTrees() { - TreeSynchronizer::PushLayerProperties(layer_tree_host_.get(), + auto& unsafe_state = layer_tree_host_->GetThreadUnsafeCommitState(); + std::unique_ptr<CommitState> commit_state = + layer_tree_host_->ActivateCommitState(); + TreeSynchronizer::PushLayerProperties(*commit_state, unsafe_state, host_impl_.pending_tree()); - layer_tree_host_->PushSurfaceRangesTo(host_impl_.pending_tree()); + if (commit_state->needs_surface_ranges_sync) { + host_impl_.pending_tree()->ClearSurfaceRanges(); + host_impl_.pending_tree()->SetSurfaceRanges( + commit_state->SurfaceRanges()); + } } protected: @@ -133,8 +141,10 @@ TEST_F(SurfaceLayerTest, PushProperties) { layer->SetBackgroundColor(SK_ColorBLUE); layer->SetStretchContentToFillBounds(true); - EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); - EXPECT_EQ(layer_tree_host_->SurfaceRanges().size(), 1u); + EXPECT_TRUE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); + EXPECT_EQ(layer_tree_host_->GetPendingCommitState()->SurfaceRanges().size(), + 1u); // Verify that pending tree has no surface ids already. EXPECT_FALSE(host_impl_.pending_tree()->needs_surface_ranges_sync()); @@ -150,7 +160,8 @@ TEST_F(SurfaceLayerTest, PushProperties) { EXPECT_EQ(host_impl_.pending_tree()->SurfaceRanges().size(), 1u); // Verify we have reset the state on layer tree host. - EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); + EXPECT_FALSE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); // Verify that the primary and fallback SurfaceIds are pushed through. EXPECT_EQ(primary_id, layer_impl->range().end()); @@ -169,8 +180,10 @@ TEST_F(SurfaceLayerTest, PushProperties) { // Verify that fallback surface id is not recorded on the layer tree host as // surface synchronization is not enabled. - EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); - EXPECT_EQ(layer_tree_host_->SurfaceRanges().size(), 1u); + EXPECT_TRUE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); + EXPECT_EQ(layer_tree_host_->GetPendingCommitState()->SurfaceRanges().size(), + 1u); SynchronizeTrees(); @@ -216,7 +229,7 @@ TEST_F(SurfaceLayerTest, CheckSurfaceReferencesForClonedLayer) { SynchronizeTrees(); // Verify that only |old_surface_id| is going to be referenced. - EXPECT_THAT(layer_tree_host_->SurfaceRanges(), + EXPECT_THAT(layer_tree_host_->GetPendingCommitState()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id))); EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id))); @@ -232,7 +245,7 @@ TEST_F(SurfaceLayerTest, CheckSurfaceReferencesForClonedLayer) { SynchronizeTrees(); // Verify that both surface ids are going to be referenced. - EXPECT_THAT(layer_tree_host_->SurfaceRanges(), + EXPECT_THAT(layer_tree_host_->GetPendingCommitState()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(old_surface_id), viz::SurfaceRange(new_surface_id))); EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(), @@ -245,7 +258,7 @@ TEST_F(SurfaceLayerTest, CheckSurfaceReferencesForClonedLayer) { SynchronizeTrees(); // Verify that only |new_surface_id| is going to be referenced. - EXPECT_THAT(layer_tree_host_->SurfaceRanges(), + EXPECT_THAT(layer_tree_host_->GetPendingCommitState()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(new_surface_id))); EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(), ElementsAre(viz::SurfaceRange(new_surface_id))); @@ -268,15 +281,18 @@ TEST_F(SurfaceLayerTest, CheckNeedsSurfaceIdsSyncForClonedLayers) { // Verify the surface id is in SurfaceLayerIds() and // needs_surface_ranges_sync() is true. - EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); - EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(1)); + EXPECT_TRUE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); + EXPECT_THAT(layer_tree_host_->GetPendingCommitState()->SurfaceRanges(), + SizeIs(1)); std::unique_ptr<SurfaceLayerImpl> layer_impl1 = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer1->id()); SynchronizeTrees(); // After syncchronizing trees verify needs_surface_ranges_sync() is false. - EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); + EXPECT_FALSE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); // Create the second layer that is a clone of the first. scoped_refptr<SurfaceLayer> layer2 = SurfaceLayer::Create(); @@ -285,30 +301,36 @@ TEST_F(SurfaceLayerTest, CheckNeedsSurfaceIdsSyncForClonedLayers) { layer2->SetOldestAcceptableFallback(surface_id); // Verify that after creating the second layer with the same surface id that - // needs_surface_ranges_sync() is still false. - EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); - EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(1)); + // needs_surface_ranges_sync is still false. + EXPECT_TRUE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); + EXPECT_THAT(layer_tree_host_->GetPendingCommitState()->SurfaceRanges(), + SizeIs(1)); std::unique_ptr<SurfaceLayerImpl> layer_impl2 = SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer2->id()); SynchronizeTrees(); - // Verify needs_surface_ranges_sync() is still false after synchronizing + // Verify needs_surface_ranges_sync is still false after synchronizing // trees. - EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); + EXPECT_FALSE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); // Destroy one of the layers, leaving one layer with the surface id. layer1->SetLayerTreeHost(nullptr); - // Verify needs_surface_ranges_sync() is still false. - EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync()); + // Verify needs_surface_ranges_sync is still false. + EXPECT_FALSE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); // Destroy the last layer, this should change the set of layer surface ids. layer2->SetLayerTreeHost(nullptr); - // Verify SurfaceLayerIds() is empty and needs_surface_ranges_sync() is true. - EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync()); - EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(0)); + // Verify SurfaceLayerIds() is empty and needs_surface_ranges_sync is true. + EXPECT_TRUE( + layer_tree_host_->GetPendingCommitState()->needs_surface_ranges_sync); + EXPECT_THAT(layer_tree_host_->GetPendingCommitState()->SurfaceRanges(), + SizeIs(0)); } } // namespace diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc index 3cd7a40d81e..b1ab993d619 100644 --- a/chromium/cc/layers/texture_layer.cc +++ b/chromium/cc/layers/texture_layer.cc @@ -11,8 +11,8 @@ #include "base/callback_helpers.h" #include "base/containers/cxx20_erase.h" #include "base/location.h" -#include "base/sequenced_task_runner.h" #include "base/synchronization/lock.h" +#include "base/task/sequenced_task_runner.h" #include "base/trace_event/trace_event.h" #include "cc/base/features.h" #include "cc/base/simple_enclosed_region.h" @@ -191,8 +191,11 @@ bool TextureLayer::IsSnappedToPixelGridInTarget() { return true; } -void TextureLayer::PushPropertiesTo(LayerImpl* layer) { - Layer::PushPropertiesTo(layer); +void TextureLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + Layer::PushPropertiesTo(layer, commit_state, unsafe_state); TRACE_EVENT0("cc", "TextureLayer::PushPropertiesTo"); TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer); diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h index 6a08a98e6d3..3501e7645cb 100644 --- a/chromium/cc/layers/texture_layer.h +++ b/chromium/cc/layers/texture_layer.h @@ -10,6 +10,7 @@ #include <vector> #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -154,7 +155,9 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { void SetLayerTreeHost(LayerTreeHost* layer_tree_host) override; bool Update() override; bool IsSnappedToPixelGridInTarget() override; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; // Request a mapping from SharedBitmapId to SharedMemory be registered via the // LayerTreeFrameSink with the display compositor. Once this mapping is @@ -189,7 +192,7 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { // compositor. void UnregisterSharedBitmapId(viz::SharedBitmapId id); - TextureLayerClient* client_; + raw_ptr<TextureLayerClient> client_; bool flipped_ = true; bool nearest_neighbor_ = false; diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc index 94d4e308fad..195a22afc5e 100644 --- a/chromium/cc/layers/texture_layer_unittest.cc +++ b/chromium/cc/layers/texture_layer_unittest.cc @@ -16,11 +16,12 @@ #include "base/callback.h" #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/run_loop.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -1068,7 +1069,10 @@ class TextureLayerChangeInvisibleMailboxTest break; case 4: // Layer should have been updated. - EXPECT_EQ(2, prepare_called_); + // It's not sufficient to check if |prepare_called_| is 2. It's possible + // for BeginMainFrame and hence PrepareTransferableResource to run twice + // before DidReceiveCompositorFrameAck due to pipelining. + EXPECT_GE(prepare_called_, 2); // So the old resource should have been returned already. EXPECT_EQ(1, resource_returned_); texture_layer_->ClearClient(); @@ -1354,8 +1358,8 @@ class SoftwareLayerTreeHostClient : public StubLayerTreeHostClient { FakeLayerTreeFrameSink* frame_sink() const { return frame_sink_; } private: - FakeLayerTreeFrameSink* frame_sink_ = nullptr; - LayerTreeHost* host_ = nullptr; + raw_ptr<FakeLayerTreeFrameSink> frame_sink_ = nullptr; + raw_ptr<LayerTreeHost> host_ = nullptr; }; class SoftwareTextureLayerTest : public LayerTreeTest { @@ -1408,7 +1412,7 @@ class SoftwareTextureLayerTest : public LayerTreeTest { scoped_refptr<Layer> root_; scoped_refptr<SolidColorLayer> solid_color_layer_; scoped_refptr<TextureLayer> texture_layer_; - TestLayerTreeFrameSink* frame_sink_ = nullptr; + raw_ptr<TestLayerTreeFrameSink> frame_sink_ = nullptr; int num_frame_sinks_created_ = 0; }; @@ -1884,7 +1888,7 @@ class SoftwareTextureLayerLoseFrameSinkTest : public SoftwareTextureLayerTest { scoped_refptr<CrossThreadSharedBitmap> bitmap_; // Keeps a pointer value of the first frame sink, which will be removed // from the host and destroyed. - void* first_frame_sink_; + raw_ptr<void> first_frame_sink_; }; SINGLE_AND_MULTI_THREAD_TEST_F(SoftwareTextureLayerLoseFrameSinkTest); diff --git a/chromium/cc/layers/tile_size_calculator.h b/chromium/cc/layers/tile_size_calculator.h index ab00258e193..0cafa6998f9 100644 --- a/chromium/cc/layers/tile_size_calculator.h +++ b/chromium/cc/layers/tile_size_calculator.h @@ -5,6 +5,7 @@ #ifndef CC_LAYERS_TILE_SIZE_CALCULATOR_H_ #define CC_LAYERS_TILE_SIZE_CALCULATOR_H_ +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "ui/gfx/geometry/size.h" @@ -39,7 +40,7 @@ class CC_EXPORT TileSizeCalculator { AffectingParams GetAffectingParams(); bool IsAffectingParamsChanged(); - PictureLayerImpl* layer_impl_; + raw_ptr<PictureLayerImpl> layer_impl_; AffectingParams affecting_params_; diff --git a/chromium/cc/layers/ui_resource_layer.cc b/chromium/cc/layers/ui_resource_layer.cc index 0776817a082..7fda0055413 100644 --- a/chromium/cc/layers/ui_resource_layer.cc +++ b/chromium/cc/layers/ui_resource_layer.cc @@ -99,19 +99,21 @@ bool UIResourceLayer::HasDrawableContent() const { return resource_id_ && Layer::HasDrawableContent(); } -void UIResourceLayer::PushPropertiesTo(LayerImpl* layer) { - Layer::PushPropertiesTo(layer); +void UIResourceLayer::PushPropertiesTo( + LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) { + Layer::PushPropertiesTo(layer, commit_state, unsafe_state); TRACE_EVENT0("cc", "UIResourceLayer::PushPropertiesTo"); UIResourceLayerImpl* layer_impl = static_cast<UIResourceLayerImpl*>(layer); layer_impl->SetUIResourceId(resource_id_); if (resource_id_) { - DCHECK(layer_tree_host()); - - gfx::Size image_size = - layer_tree_host()->GetUIResourceManager()->GetUIResourceSize( - resource_id_); - layer_impl->SetImageBounds(image_size); + auto iter = commit_state.ui_resource_sizes.find(resource_id_); + gfx::Size image_bounds = (iter == commit_state.ui_resource_sizes.end()) + ? gfx::Size() + : iter->second; + layer_impl->SetImageBounds(image_bounds); layer_impl->SetUV(uv_top_left_, uv_bottom_right_); layer_impl->SetVertexOpacity(vertex_opacity_); } diff --git a/chromium/cc/layers/ui_resource_layer.h b/chromium/cc/layers/ui_resource_layer.h index 529ef85c69b..101a76f995f 100644 --- a/chromium/cc/layers/ui_resource_layer.h +++ b/chromium/cc/layers/ui_resource_layer.h @@ -23,7 +23,9 @@ class CC_EXPORT UIResourceLayer : public Layer { UIResourceLayer(const UIResourceLayer&) = delete; UIResourceLayer& operator=(const UIResourceLayer&) = delete; - void PushPropertiesTo(LayerImpl* layer) override; + void PushPropertiesTo(LayerImpl* layer, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override; void SetLayerTreeHost(LayerTreeHost* host) override; diff --git a/chromium/cc/layers/ui_resource_layer_unittest.cc b/chromium/cc/layers/ui_resource_layer_unittest.cc index 2b627f59cde..8345c6f3b10 100644 --- a/chromium/cc/layers/ui_resource_layer_unittest.cc +++ b/chromium/cc/layers/ui_resource_layer_unittest.cc @@ -8,7 +8,6 @@ #include "cc/animation/animation_host.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/test/fake_layer_tree_host.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/test/stub_layer_tree_host_single_thread_client.h" #include "cc/trees/single_thread_proxy.h" diff --git a/chromium/cc/layers/video_frame_provider_client_impl.h b/chromium/cc/layers/video_frame_provider_client_impl.h index bd34b6cc9c0..f736ce3cc60 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl.h +++ b/chromium/cc/layers/video_frame_provider_client_impl.h @@ -5,6 +5,7 @@ #ifndef CC_LAYERS_VIDEO_FRAME_PROVIDER_CLIENT_IMPL_H_ #define CC_LAYERS_VIDEO_FRAME_PROVIDER_CLIENT_IMPL_H_ +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -76,9 +77,9 @@ class CC_EXPORT VideoFrameProviderClientImpl VideoFrameControllerClient* client); ~VideoFrameProviderClientImpl() override; - VideoFrameProvider* provider_; - VideoFrameControllerClient* client_; - VideoLayerImpl* active_video_layer_; + raw_ptr<VideoFrameProvider> provider_; + raw_ptr<VideoFrameControllerClient> client_; + raw_ptr<VideoLayerImpl> active_video_layer_; bool stopped_; bool rendering_; bool needs_put_current_frame_; diff --git a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc index fa4c2e9209e..b23f387b0ad 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc +++ b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/layers/video_frame_provider_client_impl.h" +#include "base/memory/raw_ptr.h" #include "cc/layers/video_layer_impl.h" #include "cc/test/fake_video_frame_provider.h" #include "cc/test/layer_tree_impl_test_base.h" @@ -94,7 +95,7 @@ class VideoFrameProviderClientImplTest : public testing::Test, FakeVideoFrameProvider provider_; LayerTreeImplTestBase impl_; scoped_refptr<VideoFrameProviderClientImpl> client_impl_; - VideoLayerImpl* video_layer_impl_; + raw_ptr<VideoLayerImpl> video_layer_impl_; scoped_refptr<media::VideoFrame> test_frame_; }; diff --git a/chromium/cc/layers/video_layer.h b/chromium/cc/layers/video_layer.h index 142bf20ac9f..26fd4cff647 100644 --- a/chromium/cc/layers/video_layer.h +++ b/chromium/cc/layers/video_layer.h @@ -8,6 +8,7 @@ #include <memory> #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "media/base/video_transformation.h" @@ -42,7 +43,7 @@ class CC_EXPORT VideoLayer : public Layer { // This pointer is only for passing to VideoLayerImpl's constructor. It should // never be dereferenced by this class. - VideoFrameProvider* provider_; + raw_ptr<VideoFrameProvider> provider_; media::VideoTransformation transform_; }; diff --git a/chromium/cc/layers/viewport.cc b/chromium/cc/layers/viewport.cc index f34476dfaaf..b211a038e3c 100644 --- a/chromium/cc/layers/viewport.cc +++ b/chromium/cc/layers/viewport.cc @@ -12,7 +12,7 @@ #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/scroll_node.h" -#include "ui/gfx/geometry/vector2d_conversions.h" +#include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -267,10 +267,10 @@ void Viewport::PinchEnd(const gfx::Point& anchor, bool snap_to_min) { gfx::PointF(anchor + pinch_anchor_adjustment_); adjusted_anchor = gfx::ScalePoint(adjusted_anchor, min_scale / page_scale); - adjusted_anchor += TotalScrollOffset(); - host_impl_->StartPageScaleAnimation( - ToRoundedVector2d(adjusted_anchor.OffsetFromOrigin()), true, - min_scale, kSnapToMinZoomAnimationDuration); + adjusted_anchor += TotalScrollOffset().OffsetFromOrigin(); + host_impl_->StartPageScaleAnimation(gfx::ToRoundedPoint(adjusted_anchor), + true, min_scale, + kSnapToMinZoomAnimationDuration); } } @@ -325,29 +325,32 @@ gfx::Vector2dF Viewport::AdjustOverscroll(const gfx::Vector2dF& delta) const { return adjusted; } -gfx::Vector2dF Viewport::MaxTotalScrollOffset() const { - gfx::Vector2dF offset; - - offset += scroll_tree().MaxScrollOffset(InnerScrollNode()->id); +gfx::PointF Viewport::MaxTotalScrollOffset() const { + gfx::Vector2dF offset = + scroll_tree().MaxScrollOffset(InnerScrollNode()->id).OffsetFromOrigin(); if (auto* outer_node = OuterScrollNode()) - offset += scroll_tree().MaxScrollOffset(outer_node->id); + offset += scroll_tree().MaxScrollOffset(outer_node->id).OffsetFromOrigin(); - return offset; + return gfx::PointAtOffsetFromOrigin(offset); } -gfx::Vector2dF Viewport::TotalScrollOffset() const { - gfx::Vector2dF offset; - +gfx::PointF Viewport::TotalScrollOffset() const { if (!InnerScrollNode()) - return offset; + return gfx::PointF(); - offset += scroll_tree().current_scroll_offset(InnerScrollNode()->element_id); + gfx::Vector2dF offset = + scroll_tree() + .current_scroll_offset(InnerScrollNode()->element_id) + .OffsetFromOrigin(); - if (auto* outer_node = OuterScrollNode()) - offset += scroll_tree().current_scroll_offset(outer_node->element_id); + if (auto* outer_node = OuterScrollNode()) { + offset += scroll_tree() + .current_scroll_offset(outer_node->element_id) + .OffsetFromOrigin(); + } - return offset; + return gfx::PointAtOffsetFromOrigin(offset); } ScrollNode* Viewport::InnerScrollNode() const { diff --git a/chromium/cc/layers/viewport.h b/chromium/cc/layers/viewport.h index 3f885c92dc2..38c2583420f 100644 --- a/chromium/cc/layers/viewport.h +++ b/chromium/cc/layers/viewport.h @@ -8,6 +8,7 @@ #include <memory> #include "base/gtest_prod_util.h" +#include "base/memory/raw_ptr.h" #include "cc/layers/layer_impl.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -73,7 +74,7 @@ class CC_EXPORT Viewport { gfx::Vector2dF ScrollAnimated(const gfx::Vector2dF& delta, base::TimeDelta delayed_by); - gfx::Vector2dF TotalScrollOffset() const; + gfx::PointF TotalScrollOffset() const; void PinchUpdate(float magnify_delta, const gfx::Point& anchor); void PinchEnd(const gfx::Point& anchor, bool snap_to_min); @@ -117,7 +118,7 @@ class CC_EXPORT Viewport { // Sends the delta to the browser controls, returns the amount applied. gfx::Vector2dF ScrollBrowserControls(const gfx::Vector2dF& delta); - gfx::Vector2dF MaxTotalScrollOffset() const; + gfx::PointF MaxTotalScrollOffset() const; ScrollNode* InnerScrollNode() const; ScrollNode* OuterScrollNode() const; @@ -125,7 +126,7 @@ class CC_EXPORT Viewport { void SnapPinchAnchorIfWithinMargin(const gfx::Point& anchor); - LayerTreeHostImpl* host_impl_; + raw_ptr<LayerTreeHostImpl> host_impl_; bool pinch_zoom_active_; diff --git a/chromium/cc/metrics/average_lag_tracker.cc b/chromium/cc/metrics/average_lag_tracker.cc index 7f836c22703..7a33c68d0db 100644 --- a/chromium/cc/metrics/average_lag_tracker.cc +++ b/chromium/cc/metrics/average_lag_tracker.cc @@ -196,7 +196,7 @@ void AverageLagTracker::CalculateAndReportAverageLagUma(bool send_anyway) { base::UmaHistogramCounts1000( base::JoinString({GetAverageLagMetricName(event_type), "NoPrediction"}, "."), - scaled_lag_with_prediction); + scaled_lag_no_prediction); const float lag_improvement = scaled_lag_no_prediction - scaled_lag_with_prediction; diff --git a/chromium/cc/metrics/average_lag_tracker.h b/chromium/cc/metrics/average_lag_tracker.h index 2b8bf3c1d87..6ac409c9c49 100644 --- a/chromium/cc/metrics/average_lag_tracker.h +++ b/chromium/cc/metrics/average_lag_tracker.h @@ -8,7 +8,6 @@ #include <deque> #include <string> -#include "base/macros.h" #include "base/time/time.h" #include "cc/cc_export.h" diff --git a/chromium/cc/metrics/average_lag_tracker_unittest.cc b/chromium/cc/metrics/average_lag_tracker_unittest.cc index 9889ba185f1..e4540a582aa 100644 --- a/chromium/cc/metrics/average_lag_tracker_unittest.cc +++ b/chromium/cc/metrics/average_lag_tracker_unittest.cc @@ -63,11 +63,13 @@ class AverageLagTrackerTest : public testing::Test { ElementsAre(Bucket(bucket_value, count))); } - void CheckScrollUpdateHistograms(int bucket_value, int count) { + void CheckScrollUpdateWithPredictionHistograms(int bucket_value, int count) { EXPECT_THAT(histogram_tester().GetAllSamples( "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation"), ElementsAre(Bucket(bucket_value, count))); + } + void CheckScrollUpdateNoPredictionHistograms(int bucket_value, int count) { EXPECT_THAT( histogram_tester().GetAllSamples("Event.Latency.ScrollUpdate.Touch." "AverageLagPresentation.NoPrediction"), @@ -168,7 +170,8 @@ TEST_F(AverageLagTrackerTest, OneSecondInterval) { // is 5px, and Lag at this frame swap is 15px. For the one changing direction, // the Lag is from 5 to 10 and down to 5 again. So total LagArea is 99 * 100, // plus 75. the AverageLag in 1 second is 9.975px. - CheckScrollUpdateHistograms(9, 1); + CheckScrollUpdateWithPredictionHistograms(9, 1); + CheckScrollUpdateNoPredictionHistograms(9, 1); CheckPredictionPositiveHistograms(0, 1); CheckPredictionNegativeHistogramsTotalCount(0); CheckRemainingLagPercentageHistograms(100 - 0, 1); @@ -181,7 +184,8 @@ TEST_F(AverageLagTrackerTest, OneSecondInterval) { SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta); // The last ScrollUpdate's lag is 8.75px and truncated to 8. - CheckScrollUpdateHistograms(8, 1); + CheckScrollUpdateWithPredictionHistograms(8, 1); + CheckScrollUpdateNoPredictionHistograms(8, 1); CheckPredictionPositiveHistograms(0, 1); CheckPredictionNegativeHistogramsTotalCount(0); CheckRemainingLagPercentageHistograms(100 - 0, 1); @@ -218,7 +222,8 @@ TEST_F(AverageLagTrackerTest, LargerLatency) { SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta); // The to unfinished frames' lag are (finger_positon-rendered_position)*time, // AverageLag is ((30px-10px)*10ms+(30px-20px)*10ms)/20ms = 15px. - CheckScrollUpdateHistograms(14, 1); + CheckScrollUpdateWithPredictionHistograms(14, 1); + CheckScrollUpdateNoPredictionHistograms(14, 1); } // Test that multiple latency being flush in the same frame swap. @@ -251,7 +256,8 @@ TEST_F(AverageLagTrackerTest, TwoLatencyInfoInSameFrame) { // at t=25ms, finger_pos=-15px, rendered_pos=-10px; // To t=30ms both events get flush. // AverageLag is (0.5*(10px+5px)*5ms + 5px*5ms)/10ms = 6.25px - CheckScrollUpdateHistograms(6, 1); + CheckScrollUpdateWithPredictionHistograms(6, 1); + CheckScrollUpdateNoPredictionHistograms(6, 1); } // Test the case that switching direction causes lag at current frame @@ -280,7 +286,8 @@ TEST_F(AverageLagTrackerTest, ChangeDirectionInFrame) { // From t=20 to t=30, lag_area=2*(0.5*10px*5ms)=50px*ms. // From t=30 to t=40, lag_area=20px*10ms=200px*ms // AverageLag = (50+200)/20 = 12.5px. - CheckScrollUpdateHistograms(12, 1); + CheckScrollUpdateWithPredictionHistograms(12, 1); + CheckScrollUpdateNoPredictionHistograms(12, 1); } // A simple case without scroll prediction to compare with the two with @@ -313,7 +320,8 @@ TEST_F(AverageLagTrackerTest, NoScrollPrediction) { // At t=30, finger_pos = 25px, rendered_pos = 25px. // AverageLag = ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms // = 9.375 - CheckScrollUpdateHistograms(9, 1); + CheckScrollUpdateWithPredictionHistograms(9, 1); + CheckScrollUpdateNoPredictionHistograms(9, 1); } // Test AverageLag with perfect scroll prediction. @@ -351,11 +359,12 @@ TEST_F(AverageLagTrackerTest, ScrollPrediction) { // At t=30, finger_pos = 25px, rendered_pos = 30px. // AverageLag = ((0px+10px)*10ms/2 + (0px+5px)*10ms/2 + 5px*5ms)/20ms // = 4.375px + CheckScrollUpdateWithPredictionHistograms(4, 1); // AverageLag (w/o prediction) // ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms // = 9.375px + CheckScrollUpdateNoPredictionHistograms(9, 1); // Positive effect of prediction = 5px - CheckScrollUpdateHistograms(4, 1); CheckPredictionPositiveHistograms(5, 1); CheckPredictionNegativeHistogramsTotalCount(0); CheckRemainingLagPercentageHistograms(100 * 4.375 / 9.375, 1); @@ -392,10 +401,11 @@ TEST_F(AverageLagTrackerTest, ImperfectScrollPrediction) { CheckScrollBeginHistograms(7, 1); // AverageLag = ((2px*2ms/2+8px*8ms/2)+ ((3px+8px)*5ms/2+8px*5ms))/20ms // = 5.075px - CheckScrollUpdateHistograms(5, 1); + CheckScrollUpdateWithPredictionHistograms(5, 1); // AverageLag (w/o prediction = // ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms // = 9.375px + CheckScrollUpdateNoPredictionHistograms(9, 1); // Positive effect of prediction = 4.3px CheckPredictionPositiveHistograms(4, 1); CheckPredictionNegativeHistogramsTotalCount(0); @@ -432,10 +442,11 @@ TEST_F(AverageLagTrackerTest, NegativePredictionEffect) { CheckScrollBeginHistograms(7, 1); // AverageLag = ((10px+0px)*10ms/2)+ ((40px+35px)*5ms/2+35px*5ms))/20ms // = 20.625px - CheckScrollUpdateHistograms(20, 1); + CheckScrollUpdateWithPredictionHistograms(20, 1); // AverageLag (w/o prediction = // ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms // = 9.375px + CheckScrollUpdateNoPredictionHistograms(9, 1); // Negative effect of prediction = 11.25 CheckPredictionPositiveHistogramsTotalCount(0); CheckPredictionNegativeHistograms(11, 1); @@ -474,10 +485,11 @@ TEST_F(AverageLagTrackerTest, NoPredictionEffect) { CheckScrollBeginHistograms(7, 1); // AverageLag = ((15px+5px)*10ms/2 + (12px+7px)*5ms/2 + 7px*5ms)/20ms // = 9.125px - CheckScrollUpdateHistograms(9, 1); + CheckScrollUpdateWithPredictionHistograms(9, 1); // AverageLag (w/o prediction) = // ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms // = 9.375px + CheckScrollUpdateNoPredictionHistograms(9, 1); // Prediction slightly positive, we should see a 0 bucket in // PredictionPositive UMA CheckPredictionPositiveHistograms(0, 1); diff --git a/chromium/cc/metrics/compositor_frame_reporter.cc b/chromium/cc/metrics/compositor_frame_reporter.cc index 3da1a170dd7..b6ea0646d5e 100644 --- a/chromium/cc/metrics/compositor_frame_reporter.cc +++ b/chromium/cc/metrics/compositor_frame_reporter.cc @@ -32,6 +32,7 @@ using StageType = CompositorFrameReporter::StageType; using FrameReportType = CompositorFrameReporter::FrameReportType; using BlinkBreakdown = CompositorFrameReporter::BlinkBreakdown; using VizBreakdown = CompositorFrameReporter::VizBreakdown; +using FrameFinalState = FrameInfo::FrameFinalState; constexpr int kFrameReportTypeCount = static_cast<int>(FrameReportType::kMaxValue) + 1; @@ -341,6 +342,10 @@ std::string GetEventLatencyHistogramBaseName( : is_pinch ? event_metrics.GetPinchTypeName() : ""}); } +constexpr char kTraceCategory[] = + "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"); +constexpr char kTraceEventCategory[] = "cc,benchmark,input"; + base::TimeTicks ComputeSafeDeadlineForFrame(const viz::BeginFrameArgs& args) { return args.frame_time + (args.interval * 1.5); } @@ -539,7 +544,7 @@ CompositorFrameReporter::CompositorFrameReporter( const viz::BeginFrameArgs& args, bool should_report_metrics, SmoothThread smooth_thread, - FrameSequenceMetrics::ThreadType scrolling_thread, + FrameInfo::SmoothEffectDrivingThread scrolling_thread, int layer_tree_host_id, const GlobalMetricsTrackers& trackers) : should_report_metrics_(should_report_metrics), @@ -552,7 +557,14 @@ CompositorFrameReporter::CompositorFrameReporter( global_trackers_.dropped_frame_counter->OnBeginFrame( args, IsScrollActive(active_trackers_)); DCHECK(IsScrollActive(active_trackers_) || - scrolling_thread_ == FrameSequenceMetrics::ThreadType::kUnknown); + scrolling_thread_ == FrameInfo::SmoothEffectDrivingThread::kUnknown); + if (scrolling_thread_ == FrameInfo::SmoothEffectDrivingThread::kCompositor) { + DCHECK(smooth_thread_ == SmoothThread::kSmoothCompositor || + smooth_thread_ == SmoothThread::kSmoothBoth); + } else if (scrolling_thread_ == FrameInfo::SmoothEffectDrivingThread::kMain) { + DCHECK(smooth_thread_ == SmoothThread::kSmoothMain || + smooth_thread_ == SmoothThread::kSmoothBoth); + } } std::unique_ptr<CompositorFrameReporter> @@ -699,56 +711,36 @@ void CompositorFrameReporter::TerminateReporter() { std::make_unique<ProcessedVizBreakdown>(viz_start_time_, viz_breakdown_); DCHECK_EQ(current_stage_.start_time, base::TimeTicks()); - switch (frame_termination_status_) { - case FrameTerminationStatus::kPresentedFrame: - EnableReportType(FrameReportType::kNonDroppedFrame); - if (ComputeSafeDeadlineForFrame(args_) < frame_termination_time_) - EnableReportType(FrameReportType::kMissedDeadlineFrame); - break; - case FrameTerminationStatus::kDidNotPresentFrame: + const FrameInfo frame_info = GenerateFrameInfo(); + switch (frame_info.final_state) { + case FrameFinalState::kDropped: EnableReportType(FrameReportType::kDroppedFrame); break; - case FrameTerminationStatus::kReplacedByNewReporter: - EnableReportType(FrameReportType::kDroppedFrame); - break; - case FrameTerminationStatus::kDidNotProduceFrame: { - const bool no_update_from_main = - frame_skip_reason_.has_value() && - frame_skip_reason() == FrameSkippedReason::kNoDamage; - const bool no_update_from_compositor = - !has_partial_update_ && frame_skip_reason_.has_value() && - frame_skip_reason() == FrameSkippedReason::kWaitingOnMain; - const bool draw_is_throttled = - frame_skip_reason_.has_value() && - frame_skip_reason() == FrameSkippedReason::kDrawThrottled; - if (no_update_from_main) { - // If this reporter was cloned, and the cloned reporter was marked as - // containing 'partial update' (i.e. missing desired updates from the - // main-thread), but this reporter terminated with 'no damage', then - // reset the 'partial update' flag from the cloned reporter (as well as - // other depending reporters). - while (!partial_update_dependents_.empty()) { - auto dependent = partial_update_dependents_.front(); - if (dependent) - dependent->set_has_partial_update(false); - partial_update_dependents_.pop(); - } - } else if (!no_update_from_compositor) { - // If rather main thread has damage or compositor thread has partial - // damage, then it's a dropped frame. - EnableReportType(FrameReportType::kDroppedFrame); - } else if (draw_is_throttled) { - EnableReportType(FrameReportType::kDroppedFrame); + case FrameFinalState::kNoUpdateDesired: + // If this reporter was cloned, and the cloned reporter was marked as + // containing 'partial update' (i.e. missing desired updates from the + // main-thread), but this reporter terminated with 'no damage', then reset + // the 'partial update' flag from the cloned reporter (as well as other + // depending reporters). + while (!partial_update_dependents_.empty()) { + auto dependent = partial_update_dependents_.front(); + if (dependent) + dependent->set_has_partial_update(false); + partial_update_dependents_.pop(); } - break; - } - case FrameTerminationStatus::kUnknown: + + case FrameFinalState::kPresentedAll: + case FrameFinalState::kPresentedPartialNewMain: + case FrameFinalState::kPresentedPartialOldMain: + EnableReportType(FrameReportType::kNonDroppedFrame); + if (ComputeSafeDeadlineForFrame(args_) < frame_termination_time_) + EnableReportType(FrameReportType::kMissedDeadlineFrame); break; } - ReportCompositorLatencyTraceEvents(); + ReportCompositorLatencyTraceEvents(frame_info); if (TestReportType(FrameReportType::kNonDroppedFrame)) ReportEventLatencyTraceEvents(); @@ -778,8 +770,7 @@ void CompositorFrameReporter::TerminateReporter() { dropped_frame_counter->AddGoodFrame(); } - dropped_frame_counter->OnEndFrame(args_, - IsDroppedFrameAffectingSmoothness()); + dropped_frame_counter->OnEndFrame(args_, frame_info); } if (discarded_partial_update_dependents_count_ > 0) @@ -807,16 +798,18 @@ void CompositorFrameReporter::ReportCompositorLatencyHistograms() const { } } } + + if (global_trackers_.latency_ukm_reporter) { + global_trackers_.latency_ukm_reporter->ReportCompositorLatencyUkm( + report_types_, stage_history_, active_trackers_, + *processed_blink_breakdown_, *processed_viz_breakdown_); + } + for (size_t type = 0; type < report_types_.size(); ++type) { if (!report_types_.test(type)) continue; FrameReportType report_type = static_cast<FrameReportType>(type); UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type", report_type); - if (global_trackers_.latency_ukm_reporter) { - global_trackers_.latency_ukm_reporter->ReportCompositorLatencyUkm( - report_type, stage_history_, active_trackers_, - *processed_blink_breakdown_, *processed_viz_breakdown_); - } bool any_active_interaction = false; for (size_t fst_type = 0; fst_type < active_trackers_.size(); ++fst_type) { const auto tracker_type = static_cast<FrameSequenceTrackerType>(fst_type); @@ -1048,54 +1041,60 @@ void CompositorFrameReporter::ReportEventLatencyHistograms() const { } } -void CompositorFrameReporter::ReportCompositorLatencyTraceEvents() const { +void CompositorFrameReporter::ReportCompositorLatencyTraceEvents( + const FrameInfo& info) const { if (stage_history_.empty()) return; - if (IsDroppedFrameAffectingSmoothness()) { + if (info.IsDroppedAffectingSmoothness()) { devtools_instrumentation::DidDropSmoothnessFrame( - layer_tree_host_id_, args_.frame_time, args_.frame_id.sequence_number); + layer_tree_host_id_, args_.frame_time, args_.frame_id.sequence_number, + has_partial_update_); } const auto trace_track = perfetto::Track(base::trace_event::GetNextGlobalTraceId()); TRACE_EVENT_BEGIN( - "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"), - "PipelineReporter", trace_track, args_.frame_time, + kTraceCategory, "PipelineReporter", trace_track, args_.frame_time, [&](perfetto::EventContext context) { using perfetto::protos::pbzero::ChromeFrameReporter; - bool frame_dropped = TestReportType(FrameReportType::kDroppedFrame); ChromeFrameReporter::State state; - if (frame_dropped) { - state = ChromeFrameReporter::STATE_DROPPED; - } else if (frame_termination_status_ == - FrameTerminationStatus::kDidNotProduceFrame) { - state = ChromeFrameReporter::STATE_NO_UPDATE_DESIRED; - } else { - state = has_partial_update_ - ? ChromeFrameReporter::STATE_PRESENTED_PARTIAL - : ChromeFrameReporter::STATE_PRESENTED_ALL; + switch (info.final_state) { + case FrameInfo::FrameFinalState::kPresentedAll: + state = ChromeFrameReporter::STATE_PRESENTED_ALL; + break; + case FrameInfo::FrameFinalState::kPresentedPartialNewMain: + case FrameInfo::FrameFinalState::kPresentedPartialOldMain: + state = ChromeFrameReporter::STATE_PRESENTED_PARTIAL; + break; + case FrameInfo::FrameFinalState::kNoUpdateDesired: + state = ChromeFrameReporter::STATE_NO_UPDATE_DESIRED; + break; + case FrameInfo::FrameFinalState::kDropped: + state = ChromeFrameReporter::STATE_DROPPED; + break; } + auto* reporter = context.event()->set_chrome_frame_reporter(); reporter->set_state(state); reporter->set_frame_source(args_.frame_id.source_id); reporter->set_frame_sequence(args_.frame_id.sequence_number); reporter->set_layer_tree_host_id(layer_tree_host_id_); - reporter->set_has_missing_content(has_missing_content_); - if (IsDroppedFrameAffectingSmoothness()) { + reporter->set_has_missing_content(info.has_missing_content); + if (info.IsDroppedAffectingSmoothness()) { DCHECK(state == ChromeFrameReporter::STATE_DROPPED || state == ChromeFrameReporter::STATE_PRESENTED_PARTIAL); - reporter->set_affects_smoothness(true); } + reporter->set_affects_smoothness(info.IsDroppedAffectingSmoothness()); ChromeFrameReporter::ScrollState scroll_state; - switch (scrolling_thread_) { - case FrameSequenceMetrics::ThreadType::kMain: + switch (info.scroll_thread) { + case FrameInfo::SmoothEffectDrivingThread::kMain: scroll_state = ChromeFrameReporter::SCROLL_MAIN_THREAD; break; - case FrameSequenceMetrics::ThreadType::kCompositor: + case FrameInfo::SmoothEffectDrivingThread::kCompositor: scroll_state = ChromeFrameReporter::SCROLL_COMPOSITOR_THREAD; break; - case FrameSequenceMetrics::ThreadType::kUnknown: + case FrameInfo::SmoothEffectDrivingThread::kUnknown: scroll_state = ChromeFrameReporter::SCROLL_NONE; break; } @@ -1128,9 +1127,8 @@ void CompositorFrameReporter::ReportCompositorLatencyTraceEvents() const { if (stage.stage_type == StageType::kSendBeginMainFrameToCommit) { TRACE_EVENT_BEGIN( - "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"), - perfetto::StaticString{stage_name}, trace_track, stage.start_time, - [&](perfetto::EventContext context) { + kTraceCategory, perfetto::StaticString{stage_name}, trace_track, + stage.start_time, [&](perfetto::EventContext context) { DCHECK(processed_blink_breakdown_); auto* reporter = context.event<perfetto::protos::pbzero::ChromeTrackEvent>() @@ -1179,9 +1177,8 @@ void CompositorFrameReporter::ReportCompositorLatencyTraceEvents() const { } }); } else { - TRACE_EVENT_BEGIN( - "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"), - perfetto::StaticString{stage_name}, trace_track, stage.start_time); + TRACE_EVENT_BEGIN(kTraceCategory, perfetto::StaticString{stage_name}, + trace_track, stage.start_time); } if (stage.stage_type == @@ -1194,20 +1191,16 @@ void CompositorFrameReporter::ReportCompositorLatencyTraceEvents() const { if (start_time >= end_time) continue; const char* breakdown_name = GetVizBreakdownName(it.GetBreakdown()); - TRACE_EVENT_BEGIN("cc,benchmark", + TRACE_EVENT_BEGIN(kTraceCategory, perfetto::StaticString{breakdown_name}, trace_track, start_time); - TRACE_EVENT_END("cc,benchmark", trace_track, end_time); + TRACE_EVENT_END(kTraceCategory, trace_track, end_time); } } - TRACE_EVENT_END( - "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"), - trace_track, stage.end_time); + TRACE_EVENT_END(kTraceCategory, trace_track, stage.end_time); } - TRACE_EVENT_END( - "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"), - trace_track, frame_termination_time_); + TRACE_EVENT_END(kTraceCategory, trace_track, frame_termination_time_); } void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { @@ -1223,8 +1216,8 @@ void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { const auto trace_id = TRACE_ID_LOCAL(event_metrics.get()); TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1( - "cc,input", "EventLatency", trace_id, generated_timestamp, "event", - event_metrics->GetTypeName()); + kTraceEventCategory, "EventLatency", trace_id, generated_timestamp, + "event", event_metrics->GetTypeName()); // Event dispatch stages. EventMetrics::DispatchStage dispatch_stage = @@ -1251,9 +1244,9 @@ void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { const char* breakdown_name = GetEventLatencyDispatchBreakdownName(dispatch_stage, end_stage); TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - "cc,input", breakdown_name, trace_id, dispatch_timestamp); - TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0("cc,input", breakdown_name, - trace_id, end_timestamp); + kTraceEventCategory, breakdown_name, trace_id, dispatch_timestamp); + TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( + kTraceEventCategory, breakdown_name, trace_id, end_timestamp); dispatch_stage = end_stage; dispatch_timestamp = end_timestamp; @@ -1283,9 +1276,10 @@ void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { GetEventLatencyDispatchToCompositorBreakdownName(dispatch_stage, stage_it->stage_type); TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - "cc,input", d2c_breakdown_name, trace_id, dispatch_timestamp); - TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "cc,input", d2c_breakdown_name, trace_id, stage_it->start_time); + kTraceEventCategory, d2c_breakdown_name, trace_id, dispatch_timestamp); + TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(kTraceEventCategory, + d2c_breakdown_name, trace_id, + stage_it->start_time); // Compositor stages. for (; stage_it != stage_history_.end(); ++stage_it) { @@ -1300,7 +1294,7 @@ void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { const char* stage_name = GetStageName(stage_type_index); TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - "cc,input", stage_name, trace_id, stage_it->start_time); + kTraceEventCategory, stage_name, trace_id, stage_it->start_time); if (stage_it->stage_type == StageType::kSubmitCompositorFrameToPresentationCompositorFrame) { @@ -1313,17 +1307,17 @@ void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { continue; const char* breakdown_name = GetVizBreakdownName(it.GetBreakdown()); TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - "cc,input", breakdown_name, trace_id, start_time); + kTraceEventCategory, breakdown_name, trace_id, start_time); TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "cc,input", breakdown_name, trace_id, end_time); + kTraceEventCategory, breakdown_name, trace_id, end_time); } } TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "cc,input", stage_name, trace_id, stage_it->end_time); + kTraceEventCategory, stage_name, trace_id, stage_it->end_time); } TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "cc,input", "EventLatency", trace_id, frame_termination_time_); + kTraceEventCategory, "EventLatency", trace_id, frame_termination_time_); } } @@ -1338,33 +1332,6 @@ base::TimeTicks CompositorFrameReporter::Now() const { return tick_clock_->NowTicks(); } -bool CompositorFrameReporter::IsDroppedFrameAffectingSmoothness() const { - // If the frame was not shown, then it hurt smoothness only if either of the - // threads is affecting smoothness (e.g. running an animation, scroll, pinch, - // etc.). - if (TestReportType(FrameReportType::kDroppedFrame)) { - return smooth_thread_ != SmoothThread::kSmoothNone; - } - - // If the frame includes new main-thread update, even if it's for an earlier - // begin-frame, then do not count it as a dropped frame affecting smoothness. - if (is_accompanied_by_main_thread_update_) { - return false; - } - - // If the frame was shown, but included only partial updates, then it hurt - // smoothness only if the main-thread is affecting smoothness (e.g. running an - // animation, or scroll etc.). - if (has_partial_update_) { - return smooth_thread_ == SmoothThread::kSmoothMain || - smooth_thread_ == SmoothThread::kSmoothBoth; - } - - // If the frame was shown, and did not include partial updates, then this - // frame did not hurt smoothness. - return false; -} - void CompositorFrameReporter::AdoptReporter( std::unique_ptr<CompositorFrameReporter> reporter) { // If |this| reporter is dependent on another reporter to decide about partial @@ -1408,4 +1375,87 @@ base::WeakPtr<CompositorFrameReporter> CompositorFrameReporter::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } +FrameInfo CompositorFrameReporter::GenerateFrameInfo() const { + FrameFinalState final_state = FrameFinalState::kNoUpdateDesired; + switch (frame_termination_status_) { + case FrameTerminationStatus::kPresentedFrame: + if (has_partial_update_) { + final_state = is_accompanied_by_main_thread_update_ + ? FrameFinalState::kPresentedPartialNewMain + : FrameFinalState::kPresentedPartialOldMain; + } else { + final_state = FrameFinalState::kPresentedAll; + } + break; + + case FrameTerminationStatus::kDidNotPresentFrame: + case FrameTerminationStatus::kReplacedByNewReporter: + final_state = FrameFinalState::kDropped; + break; + + case FrameTerminationStatus::kDidNotProduceFrame: { + const bool no_update_expected_from_main = + frame_skip_reason_.has_value() && + frame_skip_reason() == FrameSkippedReason::kNoDamage; + const bool no_update_expected_from_compositor = + !has_partial_update_ && frame_skip_reason_.has_value() && + frame_skip_reason() == FrameSkippedReason::kWaitingOnMain; + const bool draw_is_throttled = + frame_skip_reason_.has_value() && + frame_skip_reason() == FrameSkippedReason::kDrawThrottled; + + if (!no_update_expected_from_main && + !no_update_expected_from_compositor) { + final_state = FrameFinalState::kDropped; + } else if (draw_is_throttled) { + final_state = FrameFinalState::kDropped; + } else { + final_state = FrameFinalState::kNoUpdateDesired; + } + break; + } + + case FrameTerminationStatus::kUnknown: + break; + } + + FrameInfo info; + info.final_state = final_state; + info.smooth_thread = smooth_thread_; + info.scroll_thread = scrolling_thread_; + info.has_missing_content = has_missing_content_; + + if (frame_skip_reason_.has_value() && + frame_skip_reason() == FrameSkippedReason::kNoDamage) { + // If the frame was explicitly skipped because of 'no damage', then that + // means this frame contains the response ('no damage') from the + // main-thread. + info.main_thread_response = FrameInfo::MainThreadResponse::kIncluded; + } else if (partial_update_dependents_.size() > 0) { + // Only a frame containing a response from the main-thread can have + // dependent reporters. + info.main_thread_response = FrameInfo::MainThreadResponse::kIncluded; + } else if (begin_main_frame_start_.is_null() || + (frame_skip_reason_.has_value() && + frame_skip_reason() == FrameSkippedReason::kWaitingOnMain)) { + // If 'begin main frame' never started, or if it started, but it + // had to be skipped because it was waiting on the main-thread, + // then the main-thread update is missing from this reporter. + info.main_thread_response = FrameInfo::MainThreadResponse::kMissing; + } else { + info.main_thread_response = FrameInfo::MainThreadResponse::kIncluded; + } + + if (!stage_history_.empty()) { + const auto& stage = stage_history_.back(); + if (stage.stage_type == StageType::kTotalLatency) { + DCHECK_EQ(frame_termination_time_ - args_.frame_time, + stage.end_time - stage.start_time); + info.total_latency = frame_termination_time_ - args_.frame_time; + } + } + + return info; +} + } // namespace cc diff --git a/chromium/cc/metrics/compositor_frame_reporter.h b/chromium/cc/metrics/compositor_frame_reporter.h index c2b62e51d38..2bcdf928834 100644 --- a/chromium/cc/metrics/compositor_frame_reporter.h +++ b/chromium/cc/metrics/compositor_frame_reporter.h @@ -12,12 +12,14 @@ #include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "cc/base/devtools_instrumentation.h" #include "cc/cc_export.h" #include "cc/metrics/begin_main_frame_metrics.h" #include "cc/metrics/event_metrics.h" +#include "cc/metrics/frame_info.h" #include "cc/metrics/frame_sequence_metrics.h" #include "cc/scheduler/scheduler.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" @@ -29,12 +31,14 @@ struct FrameTimingDetails; } namespace cc { +class FrameSequenceTrackerCollection; class DroppedFrameCounter; class LatencyUkmReporter; struct GlobalMetricsTrackers { DroppedFrameCounter* dropped_frame_counter = nullptr; LatencyUkmReporter* latency_ukm_reporter = nullptr; + FrameSequenceTrackerCollection* frame_sequence_trackers = nullptr; }; // This is used for tracing and reporting the duration of pipeline stages within @@ -139,12 +143,7 @@ class CC_EXPORT CompositorFrameReporter { ~StageData(); }; - enum SmoothThread { - kSmoothNone, - kSmoothCompositor, - kSmoothMain, - kSmoothBoth - }; + using SmoothThread = FrameInfo::SmoothThread; // Holds a processed list of Blink breakdowns with an `Iterator` class to // easily iterator over them. @@ -232,7 +231,7 @@ class CC_EXPORT CompositorFrameReporter { const viz::BeginFrameArgs& args, bool should_report_metrics, SmoothThread smooth_thread, - FrameSequenceMetrics::ThreadType scrolling_thread, + FrameInfo::SmoothEffectDrivingThread scrolling_thread, int layer_tree_host_id, const GlobalMetricsTrackers& trackers); ~CompositorFrameReporter(); @@ -327,6 +326,8 @@ class CC_EXPORT CompositorFrameReporter { CompositorFrameReporter* partial_update_decider() const { return partial_update_decider_.get(); } + using FrameReportTypes = + std::bitset<static_cast<size_t>(FrameReportType::kMaxValue) + 1>; protected: void set_has_partial_update(bool has_partial_update) { @@ -352,7 +353,7 @@ class CC_EXPORT CompositorFrameReporter { base::TimeDelta time_delta) const; void ReportEventLatencyHistograms() const; - void ReportCompositorLatencyTraceEvents() const; + void ReportCompositorLatencyTraceEvents(const FrameInfo& info) const; void ReportEventLatencyTraceEvents() const; void EnableReportType(FrameReportType report_type) { @@ -370,7 +371,7 @@ class CC_EXPORT CompositorFrameReporter { base::TimeTicks Now() const; - bool IsDroppedFrameAffectingSmoothness() const; + FrameInfo GenerateFrameInfo() const; base::WeakPtr<CompositorFrameReporter> GetWeakPtr(); @@ -395,8 +396,7 @@ class CC_EXPORT CompositorFrameReporter { // List of metrics for events affecting this frame. EventMetrics::List events_metrics_; - std::bitset<static_cast<size_t>(FrameReportType::kMaxValue) + 1> - report_types_; + FrameReportTypes report_types_; base::TimeTicks frame_termination_time_; base::TimeTicks begin_main_frame_start_; @@ -404,7 +404,7 @@ class CC_EXPORT CompositorFrameReporter { FrameTerminationStatus::kUnknown; const ActiveTrackers active_trackers_; - const FrameSequenceMetrics::ThreadType scrolling_thread_; + const FrameInfo::SmoothEffectDrivingThread scrolling_thread_; // Indicates if work on Impl frame is finished. bool did_finish_impl_frame_ = false; @@ -418,7 +418,8 @@ class CC_EXPORT CompositorFrameReporter { absl::optional<FrameSkippedReason> frame_skip_reason_; absl::optional<base::TimeTicks> main_frame_abort_time_; - const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance(); + raw_ptr<const base::TickClock> tick_clock_ = + base::DefaultTickClock::GetInstance(); bool has_partial_update_ = false; diff --git a/chromium/cc/metrics/compositor_frame_reporter_unittest.cc b/chromium/cc/metrics/compositor_frame_reporter_unittest.cc index c3e61ca1497..de005ae8148 100644 --- a/chromium/cc/metrics/compositor_frame_reporter_unittest.cc +++ b/chromium/cc/metrics/compositor_frame_reporter_unittest.cc @@ -111,7 +111,7 @@ class CompositorFrameReporterTest : public testing::Test { ActiveTrackers(), viz::BeginFrameArgs(), /*should_report_metrics=*/true, CompositorFrameReporter::SmoothThread::kSmoothBoth, - FrameSequenceMetrics::ThreadType::kUnknown, + FrameInfo::SmoothEffectDrivingThread::kUnknown, /*layer_tree_host_id=*/1, trackers); reporter->set_tick_clock(&test_tick_clock_); return reporter; diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller.cc b/chromium/cc/metrics/compositor_frame_reporting_controller.cc index 1a163b81978..9285b678b1e 100644 --- a/chromium/cc/metrics/compositor_frame_reporting_controller.cc +++ b/chromium/cc/metrics/compositor_frame_reporting_controller.cc @@ -7,17 +7,22 @@ #include <utility> #include "base/trace_event/trace_event.h" +#include "base/trace_event/trace_id_helper.h" #include "cc/metrics/compositor_frame_reporter.h" #include "cc/metrics/dropped_frame_counter.h" +#include "cc/metrics/frame_sequence_tracker_collection.h" #include "cc/metrics/latency_ukm_reporter.h" #include "components/viz/common/frame_timing_details.h" #include "components/viz/common/quads/compositor_frame_metadata.h" +#include "services/tracing/public/cpp/perfetto/macros.h" namespace cc { namespace { using SmoothThread = CompositorFrameReporter::SmoothThread; using StageType = CompositorFrameReporter::StageType; using FrameTerminationStatus = CompositorFrameReporter::FrameTerminationStatus; + +constexpr char kTraceCategory[] = "cc,benchmark"; } // namespace CompositorFrameReportingController::CompositorFrameReportingController( @@ -66,16 +71,23 @@ bool CompositorFrameReportingController::HasReporterAt( void CompositorFrameReportingController::ProcessSkippedFramesIfNecessary( const viz::BeginFrameArgs& args) { - if (previous_frame_.IsValid() && - previous_frame_.frame_id.source_id == args.frame_id.source_id) { - CreateReportersForDroppedFrames(previous_frame_, args); + const auto& previous_frame = last_started_compositor_frame_.args; + if (previous_frame.IsValid() && + previous_frame.frame_id.source_id == args.frame_id.source_id) { + CreateReportersForDroppedFrames(previous_frame, args); } - previous_frame_ = args; + + last_started_compositor_frame_.args = args; + last_started_compositor_frame_.scrolling_thread = scrolling_thread_; + last_started_compositor_frame_.active_trackers = active_trackers_; + last_started_compositor_frame_.smooth_thread = GetSmoothThread(); } void CompositorFrameReportingController::WillBeginImplFrame( const viz::BeginFrameArgs& args) { ProcessSkippedFramesIfNecessary(args); + ReportMultipleSwaps(args.frame_time, last_interval_); + last_interval_ = args.interval; base::TimeTicks begin_time = Now(); if (reporters_[PipelineStage::kBeginImplFrame]) { @@ -119,10 +131,22 @@ void CompositorFrameReportingController::WillBeginMainFrame( } else { // In this case we have already submitted the ImplFrame, but we received // beginMain frame before next BeginImplFrame (Not reached the ImplFrame - // deadline yet). So will start a new reporter at BeginMainFrame. + // deadline yet). So will start a new reporter at BeginMainFrame, and use + // the state(s) from the ImplFrame where necessary. + auto scrolling_thread = scrolling_thread_; + auto active_trackers = active_trackers_; + auto smooth_thread = GetSmoothThread(); + if (args.frame_id == last_started_compositor_frame_.args.frame_id) { + // TODO(1277547): Instead of replacing all current information with the + // older information from when the impl-frame started, merge the two sets + // of information that makes sense. + scrolling_thread = last_started_compositor_frame_.scrolling_thread; + active_trackers = last_started_compositor_frame_.active_trackers; + smooth_thread = last_started_compositor_frame_.smooth_thread; + } auto reporter = std::make_unique<CompositorFrameReporter>( - active_trackers_, args, should_report_metrics_, GetSmoothThread(), - scrolling_thread_, layer_tree_host_id_, global_trackers_); + active_trackers, args, should_report_metrics_, smooth_thread, + scrolling_thread, layer_tree_host_id_, global_trackers_); reporter->set_tick_clock(tick_clock_); reporter->StartStage(StageType::kSendBeginMainFrameToCommit, Now()); reporters_[PipelineStage::kBeginMainFrame] = std::move(reporter); @@ -354,6 +378,46 @@ void CompositorFrameReportingController:: } } +void CompositorFrameReportingController::TrackSwapTiming( + const viz::FrameTimingDetails& details) { + if (details.swap_timings.swap_start != base::TimeTicks()) { + if (latest_swap_times_.empty() || + latest_swap_times_.back() < details.swap_timings.swap_start) + latest_swap_times_.push(details.swap_timings.swap_start); + } + + // Making sure the queue would not keep growing in size. + DCHECK_LE(latest_swap_times_.size(), 10u); +} + +void CompositorFrameReportingController::ReportMultipleSwaps( + base::TimeTicks begin_frame_time, + base::TimeDelta interval) { + while (!latest_swap_times_.empty() && + latest_swap_times_.front() <= begin_frame_time - interval) { + latest_swap_times_.pop(); + } + + if (latest_swap_times_.empty()) + return; + + if (latest_swap_times_.size() > 1) { + base::TimeDelta swap_delta = + latest_swap_times_.back() - latest_swap_times_.front(); + + if (swap_delta < interval) { + UMA_HISTOGRAM_PERCENTAGE("GPU.MultipleSwapsDelta", + swap_delta * 100.0 / interval); + + const auto trace_track = + perfetto::Track(base::trace_event::GetNextGlobalTraceId()); + TRACE_EVENT_BEGIN(kTraceCategory, "MultipleSwaps", trace_track, + latest_swap_times_.front()); + TRACE_EVENT_END(kTraceCategory, trace_track, latest_swap_times_.back()); + } + } +} + void CompositorFrameReportingController::OnFinishImplFrame( const viz::BeginFrameId& id) { for (auto& reporter : reporters_) { @@ -368,6 +432,10 @@ void CompositorFrameReportingController::DidPresentCompositorFrame( uint32_t frame_token, const viz::FrameTimingDetails& details) { bool feedback_failed = details.presentation_feedback.failed(); + + if (!feedback_failed) + TrackSwapTiming(details); + for (auto submitted_frame = submitted_compositor_frames_.begin(); submitted_frame != submitted_compositor_frames_.end() && !viz::FrameTokenGT(submitted_frame->frame_token, frame_token);) { @@ -472,7 +540,7 @@ void CompositorFrameReportingController::OnStoppedRequestingBeginFrames() { now); } } - previous_frame_ = {}; + last_started_compositor_frame_ = {}; } void CompositorFrameReportingController::NotifyReadyToCommit( @@ -495,19 +563,19 @@ void CompositorFrameReportingController::RemoveActiveTracker( } void CompositorFrameReportingController::SetScrollingThread( - FrameSequenceMetrics::ThreadType thread) { + FrameInfo::SmoothEffectDrivingThread thread) { scrolling_thread_ = thread; } void CompositorFrameReportingController::SetThreadAffectsSmoothness( - FrameSequenceMetrics::ThreadType thread_type, + FrameInfo::SmoothEffectDrivingThread thread_type, bool affects_smoothness) { auto current_smooth_thread = GetSmoothThread(); - if (thread_type == FrameSequenceMetrics::ThreadType::kCompositor) { + if (thread_type == FrameInfo::SmoothEffectDrivingThread::kCompositor) { is_compositor_thread_driving_smoothness_ = affects_smoothness; } else { - DCHECK_EQ(thread_type, FrameSequenceMetrics::ThreadType::kMain); + DCHECK_EQ(thread_type, FrameInfo::SmoothEffectDrivingThread::kMain); is_main_thread_driving_smoothness_ = affects_smoothness; } @@ -651,6 +719,8 @@ void CompositorFrameReportingController::CreateReportersForDroppedFrames( old_args.frame_id.sequence_number + i, timestamp, timestamp + old_args.interval, old_args.interval, viz::BeginFrameArgs::NORMAL); + devtools_instrumentation::DidBeginFrame( + layer_tree_host_id_, args.frame_time, args.frame_id.sequence_number); // ThreadType::kUnknown is used here for scrolling thread, because the // frames reported here could have a scroll interaction active at their // start time, but they were skipped and history of scrolling thread might @@ -658,7 +728,7 @@ void CompositorFrameReportingController::CreateReportersForDroppedFrames( auto reporter = std::make_unique<CompositorFrameReporter>( active_trackers_, args, should_report_metrics_, GetSmoothThreadAtTime(timestamp), - FrameSequenceMetrics::ThreadType::kUnknown, layer_tree_host_id_, + FrameInfo::SmoothEffectDrivingThread::kUnknown, layer_tree_host_id_, global_trackers_); reporter->set_tick_clock(tick_clock_); reporter->StartStage(StageType::kBeginImplFrameToSendBeginMainFrame, @@ -668,4 +738,22 @@ void CompositorFrameReportingController::CreateReportersForDroppedFrames( } } +void CompositorFrameReportingController::AddSortedFrame( + const viz::BeginFrameArgs& args, + const FrameInfo& frame_info) { + if (global_trackers_.frame_sequence_trackers) { + global_trackers_.frame_sequence_trackers->AddSortedFrame(args, frame_info); + } +} + +void CompositorFrameReportingController::SetDroppedFrameCounter( + DroppedFrameCounter* counter) { + global_trackers_.dropped_frame_counter = counter; + if (counter) { + counter->SetSortedFrameCallback( + base::BindRepeating(&CompositorFrameReportingController::AddSortedFrame, + base::Unretained(this))); + } +} + } // namespace cc diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller.h b/chromium/cc/metrics/compositor_frame_reporting_controller.h index 18115a7f64c..b3dc01c56e3 100644 --- a/chromium/cc/metrics/compositor_frame_reporting_controller.h +++ b/chromium/cc/metrics/compositor_frame_reporting_controller.h @@ -7,8 +7,10 @@ #include <map> #include <memory> +#include <queue> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -24,6 +26,7 @@ namespace cc { class DroppedFrameCounter; class UkmManager; struct BeginMainFrameMetrics; +struct FrameInfo; // This is used for managing simultaneous CompositorFrameReporter instances // in the case that the compositor has high latency. Calling one of the @@ -81,10 +84,11 @@ class CC_EXPORT CompositorFrameReportingController { void AddActiveTracker(FrameSequenceTrackerType type); void RemoveActiveTracker(FrameSequenceTrackerType type); - void SetScrollingThread(FrameSequenceMetrics::ThreadType thread); + void SetScrollingThread(FrameInfo::SmoothEffectDrivingThread thread); - void SetThreadAffectsSmoothness(FrameSequenceMetrics::ThreadType thread_type, - bool affects_smoothness); + void SetThreadAffectsSmoothness( + FrameInfo::SmoothEffectDrivingThread thread_type, + bool affects_smoothness); bool is_main_thread_driving_smoothness() const { return is_main_thread_driving_smoothness_; } @@ -96,8 +100,11 @@ class CC_EXPORT CompositorFrameReportingController { std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; } - void SetDroppedFrameCounter(DroppedFrameCounter* counter) { - global_trackers_.dropped_frame_counter = counter; + void SetDroppedFrameCounter(DroppedFrameCounter* counter); + + void SetFrameSequenceTrackerCollection( + FrameSequenceTrackerCollection* frame_sequence_trackers) { + global_trackers_.frame_sequence_trackers = frame_sequence_trackers; } void BeginMainFrameStarted(base::TimeTicks begin_main_frame_start_time) { @@ -151,6 +158,12 @@ class CC_EXPORT CompositorFrameReportingController { // that reporter is in, its ownership might be pass or not. void SetPartialUpdateDeciderWhenWaitingOnMain( std::unique_ptr<CompositorFrameReporter>& reporter); + void TrackSwapTiming(const viz::FrameTimingDetails& details); + void ReportMultipleSwaps(base::TimeTicks begin_frame_time, + base::TimeDelta interval); + + void AddSortedFrame(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info); const bool should_report_metrics_; const int layer_tree_host_id_; @@ -159,8 +172,8 @@ class CC_EXPORT CompositorFrameReportingController { bool next_activate_has_invalidation_ = false; ActiveTrackers active_trackers_; - FrameSequenceMetrics::ThreadType scrolling_thread_ = - FrameSequenceMetrics::ThreadType::kUnknown; + FrameInfo::SmoothEffectDrivingThread scrolling_thread_ = + FrameInfo::SmoothEffectDrivingThread::kUnknown; bool is_compositor_thread_driving_smoothness_ = false; bool is_main_thread_driving_smoothness_ = false; @@ -184,12 +197,23 @@ class CC_EXPORT CompositorFrameReportingController { // must outlive the objects in |submitted_compositor_frames_|. base::circular_deque<SubmittedCompositorFrame> submitted_compositor_frames_; - // The latest frame that was started. - viz::BeginFrameArgs previous_frame_; + // Contains information about the latest frame that was started, and the state + // during that frame. This is used to process skipped frames, as well as + // making sure a CompositorFrameReporter object for a delayed main-frame is + // created with the correct state. + struct { + viz::BeginFrameArgs args; + FrameInfo::SmoothEffectDrivingThread scrolling_thread = + FrameInfo::SmoothEffectDrivingThread::kUnknown; + ActiveTrackers active_trackers; + CompositorFrameReporter::SmoothThread smooth_thread = + CompositorFrameReporter::SmoothThread::kSmoothNone; + } last_started_compositor_frame_; base::TimeTicks begin_main_frame_start_time_; - const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance(); + raw_ptr<const base::TickClock> tick_clock_ = + base::DefaultTickClock::GetInstance(); GlobalMetricsTrackers global_trackers_; @@ -198,7 +222,15 @@ class CC_EXPORT CompositorFrameReportingController { // these metrics and report them. std::map<viz::BeginFrameId, EventMetrics::List> events_metrics_from_dropped_frames_; + + // Tracking the swap times in a queue to measure delta of multiple swaps in + // each vsync. + std::queue<base::TimeTicks> latest_swap_times_; + + // interval of last begin frame args. + base::TimeDelta last_interval_; }; + } // namespace cc #endif // CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_ diff --git a/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc index 3757740d547..01d9953177a 100644 --- a/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc +++ b/chromium/cc/metrics/compositor_frame_reporting_controller_unittest.cc @@ -8,7 +8,6 @@ #include <utility> #include <vector> -#include "base/macros.h" #include "base/strings/strcat.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_tick_clock.h" @@ -1693,7 +1692,8 @@ TEST_F(CompositorFrameReportingControllerTest, TEST_F(CompositorFrameReportingControllerTest, SkippedFramesFromDisplayCompositorHaveSmoothThread) { - auto thread_type_compositor = FrameSequenceMetrics::ThreadType::kCompositor; + auto thread_type_compositor = + FrameInfo::SmoothEffectDrivingThread::kCompositor; reporting_controller_.SetThreadAffectsSmoothness(thread_type_compositor, true); dropped_counter_.OnFcpReceived(); @@ -1833,7 +1833,7 @@ TEST_F(CompositorFrameReportingControllerTest, TEST_F(CompositorFrameReportingControllerTest, NewMainThreadUpdateNotReportedAsDropped) { - auto thread_type_main = FrameSequenceMetrics::ThreadType::kMain; + auto thread_type_main = FrameInfo::SmoothEffectDrivingThread::kMain; reporting_controller_.SetThreadAffectsSmoothness(thread_type_main, /*affects_smoothness=*/true); dropped_counter_.OnFcpReceived(); @@ -1848,12 +1848,12 @@ TEST_F(CompositorFrameReportingControllerTest, reporting_controller_.DidPresentCompositorFrame(1u, details); // Starts a new frame and submit it prior to commit - reporting_controller_.WillCommit(); - reporting_controller_.DidCommit(); + SimulateCommit(nullptr); const auto previous_id = current_id_; SimulateBeginMainFrame(); + DCHECK_NE(previous_id, current_id_); reporting_controller_.OnFinishImplFrame(current_id_); // Starts a new frame and submit it prior to its commit, but the older frame @@ -1862,13 +1862,11 @@ TEST_F(CompositorFrameReportingControllerTest, reporting_controller_.DidActivate(); reporting_controller_.DidSubmitCompositorFrame( - 1u, current_id_, previous_id, {}, /*has_missing_content=*/false); + 2u, current_id_, previous_id, {}, /*has_missing_content=*/false); details.presentation_feedback.timestamp = AdvanceNowByMs(10); - reporting_controller_.DidPresentCompositorFrame(1u, details); - - reporting_controller_.WillCommit(); - reporting_controller_.DidCommit(); + reporting_controller_.DidPresentCompositorFrame(2u, details); + SimulateCommit(nullptr); SimulatePresentCompositorFrame(); // There are two frames with partial updates diff --git a/chromium/cc/metrics/compositor_timing_history.cc b/chromium/cc/metrics/compositor_timing_history.cc index 6a2ca30bd72..ba2ea3195c5 100644 --- a/chromium/cc/metrics/compositor_timing_history.cc +++ b/chromium/cc/metrics/compositor_timing_history.cc @@ -14,6 +14,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" +#include "cc/base/features.h" #include "cc/debug/rendering_stats_instrumentation.h" namespace cc { @@ -70,6 +71,42 @@ const double kPrepareTilesEstimationPercentile = 90.0; const double kActivateEstimationPercentile = 90.0; const double kDrawEstimationPercentile = 90.0; +double BeginMainFrameStartToReadyToCommitCriticalPercentile() { + if (base::FeatureList::IsEnabled( + features::kDurationEstimatesInCompositorTimingHistory)) { + double result = base::GetFieldTrialParamByFeatureAsDouble( + features::kDurationEstimatesInCompositorTimingHistory, + "BMFStartCritialPercentile", -1.0); + if (result > 0) + return result; + } + return 90.0; +} + +double BeginMainFrameStartToReadyToCommitNonCriticalPercentile() { + if (base::FeatureList::IsEnabled( + features::kDurationEstimatesInCompositorTimingHistory)) { + double result = base::GetFieldTrialParamByFeatureAsDouble( + features::kDurationEstimatesInCompositorTimingHistory, + "BMFStartNonCritialPercentile", -1.0); + if (result > 0) + return result; + } + return 90.0; +} + +double BeginMainFrameQueueToActivateCriticalPercentile() { + if (base::FeatureList::IsEnabled( + features::kDurationEstimatesInCompositorTimingHistory)) { + double result = base::GetFieldTrialParamByFeatureAsDouble( + features::kDurationEstimatesInCompositorTimingHistory, + "BMFQueueCritialPercentile", -1.0); + if (result > 0) + return result; + } + return 90.0; +} + // This macro is deprecated since its bucket count uses too much bandwidth. // It also has sub-optimal range and bucket distribution. // TODO(brianderson): Delete this macro and associated UMAs once there is @@ -416,6 +453,17 @@ CompositorTimingHistory::CompositorTimingHistory( prepare_tiles_duration_history_(kDurationHistorySize), activate_duration_history_(kDurationHistorySize), draw_duration_history_(kDurationHistorySize), + duration_estimates_enabled_(base::FeatureList::IsEnabled( + features::kDurationEstimatesInCompositorTimingHistory)), + bmf_start_to_ready_to_commit_critical_history_(kDurationHistorySize), + bmf_start_to_ready_to_commit_critical_percentile_( + BeginMainFrameStartToReadyToCommitCriticalPercentile()), + bmf_start_to_ready_to_commit_not_critical_history_(kDurationHistorySize), + bmf_start_to_ready_to_commit_not_critical_percentile_( + BeginMainFrameStartToReadyToCommitNonCriticalPercentile()), + bmf_queue_to_activate_critical_history_(kDurationHistorySize), + bmf_queue_to_activate_critical_percentile_( + BeginMainFrameQueueToActivateCriticalPercentile()), begin_main_frame_on_critical_path_(false), uma_reporter_(CreateUMAReporter(uma_category)), rendering_stats_instrumentation_(rendering_stats_instrumentation) {} @@ -509,6 +557,10 @@ base::TimeDelta CompositorTimingHistory::DrawDurationEstimate() const { base::TimeDelta CompositorTimingHistory::BeginMainFrameStartToReadyToCommitCriticalEstimate() const { + if (duration_estimates_enabled_) { + return bmf_start_to_ready_to_commit_critical_history_.Percentile( + bmf_start_to_ready_to_commit_critical_percentile_); + } return BeginMainFrameStartToReadyToCommitDurationEstimate() + BeginMainFrameQueueDurationCriticalEstimate(); } @@ -516,12 +568,20 @@ CompositorTimingHistory::BeginMainFrameStartToReadyToCommitCriticalEstimate() base::TimeDelta CompositorTimingHistory::BeginMainFrameStartToReadyToCommitNotCriticalEstimate() const { + if (duration_estimates_enabled_) { + return bmf_start_to_ready_to_commit_not_critical_history_.Percentile( + bmf_start_to_ready_to_commit_not_critical_percentile_); + } return BeginMainFrameStartToReadyToCommitDurationEstimate() + BeginMainFrameQueueDurationNotCriticalEstimate(); } base::TimeDelta CompositorTimingHistory::BeginMainFrameQueueToActivateCriticalEstimate() const { + if (duration_estimates_enabled_) { + return bmf_queue_to_activate_critical_history_.Percentile( + bmf_queue_to_activate_critical_percentile_); + } return BeginMainFrameStartToReadyToCommitDurationEstimate() + CommitDurationEstimate() + CommitToReadyToActivateDurationEstimate() + ActivateDurationEstimate() + @@ -575,6 +635,18 @@ void CompositorTimingHistory::NotifyReadyToCommit() { DCHECK_NE(begin_main_frame_start_time_, base::TimeTicks()); begin_main_frame_start_to_ready_to_commit_duration_history_.InsertSample( Now() - begin_main_frame_start_time_); + if (duration_estimates_enabled_) { + bmf_start_to_activate_duration_ = Now() - begin_main_frame_start_time_; + if (begin_main_frame_on_critical_path_) { + bmf_start_to_ready_to_commit_critical_history_.InsertSample( + (Now() - begin_main_frame_start_time_) + + begin_main_frame_queue_duration_); + } else { + bmf_start_to_ready_to_commit_not_critical_history_.InsertSample( + (Now() - begin_main_frame_start_time_) + + begin_main_frame_queue_duration_); + } + } } void CompositorTimingHistory::WillCommit() { @@ -591,6 +663,10 @@ void CompositorTimingHistory::DidCommit() { commit_duration_history_.InsertSample(begin_main_frame_end_time - commit_start_time_); + if (enabled_ && duration_estimates_enabled_) { + bmf_start_to_activate_duration_ += + begin_main_frame_end_time - commit_start_time_; + } pending_tree_is_impl_side_ = false; pending_tree_creation_time_ = begin_main_frame_end_time; } @@ -625,6 +701,10 @@ void CompositorTimingHistory::DidBeginMainFrame( begin_main_frame_queue_duration_not_critical_history_.InsertSample( begin_main_frame_queue_duration); } + + if (duration_estimates_enabled_) { + begin_main_frame_queue_duration_ = begin_main_frame_queue_duration; + } } begin_main_frame_sent_time_ = base::TimeTicks(); @@ -682,6 +762,8 @@ void CompositorTimingHistory::ReadyToActivate() { if (enabled_) { commit_to_ready_to_activate_duration_history_.InsertSample( time_since_commit); + if (duration_estimates_enabled_) + bmf_start_to_activate_duration_ += time_since_commit; } } } @@ -700,9 +782,18 @@ void CompositorTimingHistory::DidActivate() { DCHECK_NE(base::TimeTicks(), activate_start_time_); base::TimeDelta activate_duration = Now() - activate_start_time_; - if (enabled_) + if (enabled_) { activate_duration_history_.InsertSample(activate_duration); + if (duration_estimates_enabled_) { + if (begin_main_frame_on_critical_path_) { + bmf_queue_to_activate_critical_history_.InsertSample( + bmf_start_to_activate_duration_ + activate_duration + + begin_main_frame_queue_duration_); + } + } + } + activate_start_time_ = base::TimeTicks(); } @@ -781,5 +872,12 @@ void CompositorTimingHistory::ClearHistory() { prepare_tiles_duration_history_.Clear(); activate_duration_history_.Clear(); draw_duration_history_.Clear(); + bmf_start_to_ready_to_commit_critical_history_.Clear(); + bmf_start_to_ready_to_commit_not_critical_history_.Clear(); + bmf_queue_to_activate_critical_history_.Clear(); +} + +size_t CompositorTimingHistory::CommitDurationSampleCountForTesting() const { + return commit_duration_history_.sample_count(); } } // namespace cc diff --git a/chromium/cc/metrics/compositor_timing_history.h b/chromium/cc/metrics/compositor_timing_history.h index 8d01636964d..3b130bd5f10 100644 --- a/chromium/cc/metrics/compositor_timing_history.h +++ b/chromium/cc/metrics/compositor_timing_history.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/base/rolling_time_delta_history.h" #include "cc/cc_export.h" #include "cc/metrics/event_metrics.h" @@ -96,6 +97,8 @@ class CC_EXPORT CompositorTimingHistory { void ClearHistory(); + size_t CommitDurationSampleCountForTesting() const; + protected: void DidBeginMainFrame(base::TimeTicks begin_main_frame_end_time); @@ -126,6 +129,21 @@ class CC_EXPORT CompositorTimingHistory { RollingTimeDeltaHistory activate_duration_history_; RollingTimeDeltaHistory draw_duration_history_; + // Used for duration estimates when enabled. Without this feature, compositor + // timing history collects timing history of each stage and use sum of + // percentile for duration estimates. With this feature, we use percentile of + // sum instead. + bool duration_estimates_enabled_; + RollingTimeDeltaHistory bmf_start_to_ready_to_commit_critical_history_; + double bmf_start_to_ready_to_commit_critical_percentile_; + RollingTimeDeltaHistory bmf_start_to_ready_to_commit_not_critical_history_; + double bmf_start_to_ready_to_commit_not_critical_percentile_; + RollingTimeDeltaHistory bmf_queue_to_activate_critical_history_; + double bmf_queue_to_activate_critical_percentile_; + + base::TimeDelta begin_main_frame_queue_duration_; + base::TimeDelta bmf_start_to_activate_duration_; + bool begin_main_frame_on_critical_path_; base::TimeTicks begin_main_frame_sent_time_; base::TimeTicks begin_main_frame_start_time_; @@ -141,7 +159,7 @@ class CC_EXPORT CompositorTimingHistory { std::unique_ptr<UMAReporter> uma_reporter_; // Owned by LayerTreeHost and is destroyed when LayerTreeHost is destroyed. - RenderingStatsInstrumentation* rendering_stats_instrumentation_; + raw_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_; // Used only for reporting animation targeted UMA. bool previous_frame_had_custom_property_animations_ = false; diff --git a/chromium/cc/metrics/compositor_timing_history_unittest.cc b/chromium/cc/metrics/compositor_timing_history_unittest.cc index 97a27478e9a..c077c871612 100644 --- a/chromium/cc/metrics/compositor_timing_history_unittest.cc +++ b/chromium/cc/metrics/compositor_timing_history_unittest.cc @@ -5,6 +5,7 @@ #include "cc/metrics/compositor_timing_history.h" #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/metrics/dropped_frame_counter.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,7 +29,7 @@ class TestCompositorTimingHistory : public CompositorTimingHistory { protected: base::TimeTicks Now() const override; - CompositorTimingHistoryTest* test_; + raw_ptr<CompositorTimingHistoryTest> test_; }; class CompositorTimingHistoryTest : public testing::Test { diff --git a/chromium/cc/metrics/dropped_frame_counter.cc b/chromium/cc/metrics/dropped_frame_counter.cc index cdf900958fc..db8d087d3cd 100644 --- a/chromium/cc/metrics/dropped_frame_counter.cc +++ b/chromium/cc/metrics/dropped_frame_counter.cc @@ -6,12 +6,15 @@ #include <algorithm> #include <cmath> +#include <iterator> #include "base/bind.h" -#include "base/logging.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" +#include "build/chromeos_buildflags.h" +#include "cc/base/features.h" #include "cc/metrics/frame_sorter.h" #include "cc/metrics/total_frame_counter.h" #include "cc/metrics/ukm_smoothness_data.h" @@ -19,6 +22,9 @@ namespace cc { namespace { +const char kSlidingWindowForDroppedFrameCounterSeconds[] = "seconds"; +const base::TimeDelta kDefaultSlidingWindowInterval = base::Seconds(1); + // The start ranges of each bucket, up to but not including the start of the // next bucket. The last bucket contains the remaining values. constexpr double kBucketBounds[7] = {0, 3, 6, 12, 25, 50, 75}; @@ -63,6 +69,27 @@ uint32_t SlidingWindowHistogram::GetPercentDroppedFramePercentile( return current_index; } +double SlidingWindowHistogram::GetPercentDroppedFrameVariance() const { + double sum = 0; + size_t bin_count = sizeof(histogram_bins_) / sizeof(uint32_t); + for (size_t i = 0; i < bin_count; ++i) { + sum += histogram_bins_[i] * i; + } + double average = sum / total_count_; + sum = 0; // Sum is reset to be used for variance calculation + + for (size_t i = 0; i < bin_count; ++i) { + sum += histogram_bins_[i] * (i - average) * (i - average); + // histogram_bins_[i] is the number of PDFs which were in the range of + // [i,i+1) so i is used as the actual value which is repeated for + // histogram_bins_[i] times. + } + + if (total_count_ <= 1) + return 0; + return sum / (total_count_ - 1); +} + std::vector<double> SlidingWindowHistogram::GetPercentDroppedFrameBuckets() const { if (total_count_ == 0) @@ -96,13 +123,23 @@ std::ostream& operator<<( DroppedFrameCounter::DroppedFrameCounter() : frame_sorter_(base::BindRepeating(&DroppedFrameCounter::NotifyFrameResult, - base::Unretained(this))) {} + base::Unretained(this))) { + sliding_window_interval_ = kDefaultSlidingWindowInterval; + if (base::FeatureList::IsEnabled( + features::kSlidingWindowForDroppedFrameCounter)) { + int sliding_window_seconds = base::GetFieldTrialParamByFeatureAsInt( + features::kSlidingWindowForDroppedFrameCounter, + kSlidingWindowForDroppedFrameCounterSeconds, 0); + if (sliding_window_seconds) + sliding_window_interval_ = base::Seconds(sliding_window_seconds); + } +} DroppedFrameCounter::~DroppedFrameCounter() = default; uint32_t DroppedFrameCounter::GetAverageThroughput() const { size_t good_frames = 0; for (auto it = --end(); it; --it) { - if (**it == kFrameStateComplete) + if (**it == kFrameStateComplete || **it == kFrameStatePartial) ++good_frames; } double throughput = 100. * good_frames / ring_buffer_.BufferSize(); @@ -135,38 +172,28 @@ void DroppedFrameCounter::ResetPendingFrames(base::TimeTicks timestamp) { // Before resetting the pending frames, update the measurements for the // sliding windows. if (!latest_sliding_window_start_.is_null()) { - const auto report_until = timestamp - kSlidingWindowInterval; + const auto report_until = timestamp - sliding_window_interval_; // Report the sliding window metrics for frames that have already been // completed (and some of which may have been dropped). while (!sliding_window_.empty()) { const auto& args = sliding_window_.front().first; - latest_sliding_window_start_ = args.frame_time; - latest_sliding_window_interval_ = args.interval; - bool was_dropped = sliding_window_.front().second; - if (was_dropped) { - DCHECK_GT(dropped_frame_count_in_window_, 0u); - --dropped_frame_count_in_window_; - } - sliding_window_.pop(); - if (latest_sliding_window_start_ > report_until) + if (args.frame_time > report_until) break; - double percent_dropped_frame = std::min( - (dropped_frame_count_in_window_ * 100.0) / total_frames_in_window_, - 100.0); - // TODO(jonross): we have divergent calculations for the sliding window - // between here and NotifyFrameResult. We should merge them to avoid - // inconsistencies in calculations. (https://crbug.com/1225307) - if (percent_dropped_frame > sliding_window_max_percent_dropped_) { - time_max_delta_ = args.frame_time - time_fcp_received_; - sliding_window_max_percent_dropped_ = percent_dropped_frame; - } - UpdateMaxPercentDroppedFrame(percent_dropped_frame); - - sliding_window_histogram_.AddPercentDroppedFrame(percent_dropped_frame, - /*count=*/1); + PopSlidingWindow(); } if (sliding_window_.empty()) { - DCHECK_EQ(dropped_frame_count_in_window_, 0u); + DCHECK_EQ( + dropped_frame_count_in_window_[SmoothnessStrategy::kDefaultStrategy], + 0u); + DCHECK_EQ(dropped_frame_count_in_window_ + [SmoothnessStrategy::kCompositorFocusedStrategy], + 0u); + DCHECK_EQ(dropped_frame_count_in_window_ + [SmoothnessStrategy::kMainFocusedStrategy], + 0u); + DCHECK_EQ(dropped_frame_count_in_window_ + [SmoothnessStrategy::kScrollFocusedStrategy], + 0u); } // Report no dropped frames for the sliding windows spanning the rest of the @@ -175,17 +202,33 @@ void DroppedFrameCounter::ResetPendingFrames(base::TimeTicks timestamp) { const auto difference = report_until - latest_sliding_window_start_; const size_t count = std::ceil(difference / latest_sliding_window_interval_); - if (count > 0) - sliding_window_histogram_.AddPercentDroppedFrame(0., count); + if (count > 0) { + sliding_window_histogram_[SmoothnessStrategy::kDefaultStrategy] + .AddPercentDroppedFrame(0., count); + sliding_window_histogram_[SmoothnessStrategy::kMainFocusedStrategy] + .AddPercentDroppedFrame(0., count); + sliding_window_histogram_ + [SmoothnessStrategy::kCompositorFocusedStrategy] + .AddPercentDroppedFrame(0., count); + sliding_window_histogram_[SmoothnessStrategy::kScrollFocusedStrategy] + .AddPercentDroppedFrame(0., count); + } } } - dropped_frame_count_in_window_ = 0; + std::fill_n(dropped_frame_count_in_window_, + SmoothnessStrategy::kStrategyCount, 0); sliding_window_ = {}; latest_sliding_window_start_ = {}; latest_sliding_window_interval_ = {}; } +void DroppedFrameCounter::EnableReporForUI() { + report_for_ui_ = true; + // We do not allow parameterized sliding windows for UI reports. + sliding_window_interval_ = base::Seconds(1); +} + void DroppedFrameCounter::OnBeginFrame(const viz::BeginFrameArgs& args, bool is_scroll_active) { // Remember when scrolling starts/ends. Do this even if fcp has not happened @@ -207,39 +250,48 @@ void DroppedFrameCounter::OnBeginFrame(const viz::BeginFrameArgs& args, } void DroppedFrameCounter::OnEndFrame(const viz::BeginFrameArgs& args, - bool is_dropped) { + const FrameInfo& frame_info) { + const bool is_dropped = frame_info.IsDroppedAffectingSmoothness(); if (!args.interval.is_zero()) - total_frames_in_window_ = kSlidingWindowInterval / args.interval; + total_frames_in_window_ = sliding_window_interval_ / args.interval; // Don't measure smoothness for frames that start before FCP is received, or // that have already been reported as dropped. if (is_dropped && fcp_received_ && args.frame_time >= time_fcp_received_ && - !frame_sorter_.IsFrameDropped(args.frame_id)) { + !frame_sorter_.IsAlreadyReportedDropped(args.frame_id)) { ++total_smoothness_dropped_; - ReportFrames(); - } - auto iter = scroll_start_per_frame_.find(args.frame_id); - if (iter != scroll_start_per_frame_.end()) { - ScrollStartInfo& scroll_start = iter->second; - if (args.frame_id.source_id == scroll_start.frame_id.source_id) { - UMA_HISTOGRAM_CUSTOM_TIMES( - "Graphics.Smoothness.Diagnostic.DroppedFrameAfterScrollStart.Time", - (args.frame_time - scroll_start.timestamp), base::Milliseconds(1), - base::Seconds(4), 50); - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Graphics.Smoothness.Diagnostic.DroppedFrameAfterScrollStart.Frames", - (args.frame_id.sequence_number - - scroll_start.frame_id.sequence_number), - 1, 250, 50); + + if (report_for_ui_) + ReportFramesForUI(); + else + ReportFrames(); + + auto iter = scroll_start_per_frame_.find(args.frame_id); + if (iter != scroll_start_per_frame_.end()) { + ScrollStartInfo& scroll_start = iter->second; + if (args.frame_id.source_id == scroll_start.frame_id.source_id) { + UMA_HISTOGRAM_CUSTOM_TIMES( + "Graphics.Smoothness.Diagnostic.DroppedFrameAfterScrollStart2.Time", + (args.frame_time - scroll_start.timestamp), base::Milliseconds(1), + base::Seconds(4), 50); + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Graphics.Smoothness.Diagnostic.DroppedFrameAfterScrollStart2." + "Frames", + (args.frame_id.sequence_number - + scroll_start.frame_id.sequence_number), + 1, 250, 50); + } + scroll_start_per_frame_.erase(iter); } - scroll_start_per_frame_.erase(iter); } if (fcp_received_) - frame_sorter_.AddFrameResult(args, is_dropped); + frame_sorter_.AddFrameResult(args, frame_info); } void DroppedFrameCounter::ReportFrames() { + DCHECK(!report_for_ui_); + const auto total_frames = total_counter_->ComputeTotalVisibleFrames(base::TimeTicks::Now()); TRACE_EVENT2("cc,benchmark", "SmoothnessDroppedFrame", "total", total_frames, @@ -253,7 +305,8 @@ void DroppedFrameCounter::ReportFrames() { } uint32_t sliding_window_95pct_percent_dropped = - SlidingWindow95PercentilePercentDropped(); + SlidingWindow95PercentilePercentDropped( + SmoothnessStrategy::kDefaultStrategy); if (sliding_window_95pct_percent_dropped != last_reported_metrics_.p95_window) { UMA_HISTOGRAM_PERCENTAGE( @@ -279,14 +332,52 @@ void DroppedFrameCounter::ReportFrames() { static_cast<double>(total_smoothness_dropped_) * 100 / total_frames; smoothness_data.worst_smoothness = sliding_window_max_percent_dropped_; smoothness_data.percentile_95 = sliding_window_95pct_percent_dropped; + smoothness_data.median_smoothness = + SlidingWindowMedianPercentDropped(SmoothnessStrategy::kDefaultStrategy); + + uint32_t default_variance = + static_cast<uint32_t>(SlidingWindowPercentDroppedVariance( + SmoothnessStrategy::kDefaultStrategy)); + DCHECK_LE(default_variance, 5000u); + DCHECK_LE(0u, default_variance); + smoothness_data.variance = default_variance; std::vector<double> sliding_window_buckets = - sliding_window_histogram_.GetPercentDroppedFrameBuckets(); + sliding_window_histogram_[SmoothnessStrategy::kDefaultStrategy] + .GetPercentDroppedFrameBuckets(); DCHECK_EQ(sliding_window_buckets.size(), base::size(smoothness_data.buckets)); std::copy(sliding_window_buckets.begin(), sliding_window_buckets.end(), smoothness_data.buckets); + smoothness_data.main_focused_median = SlidingWindowMedianPercentDropped( + SmoothnessStrategy::kMainFocusedStrategy); + smoothness_data.main_focused_percentile_95 = + SlidingWindow95PercentilePercentDropped( + SmoothnessStrategy::kMainFocusedStrategy); + smoothness_data.main_focused_variance = + static_cast<uint32_t>(SlidingWindowPercentDroppedVariance( + SmoothnessStrategy::kMainFocusedStrategy)); + + smoothness_data.compositor_focused_median = + SlidingWindowMedianPercentDropped( + SmoothnessStrategy::kCompositorFocusedStrategy); + smoothness_data.compositor_focused_percentile_95 = + SlidingWindow95PercentilePercentDropped( + SmoothnessStrategy::kCompositorFocusedStrategy); + smoothness_data.compositor_focused_variance = + static_cast<uint32_t>(SlidingWindowPercentDroppedVariance( + SmoothnessStrategy::kCompositorFocusedStrategy)); + + smoothness_data.scroll_focused_median = SlidingWindowMedianPercentDropped( + SmoothnessStrategy::kScrollFocusedStrategy); + smoothness_data.scroll_focused_percentile_95 = + SlidingWindow95PercentilePercentDropped( + SmoothnessStrategy::kScrollFocusedStrategy); + smoothness_data.scroll_focused_variance = + static_cast<uint32_t>(SlidingWindowPercentDroppedVariance( + SmoothnessStrategy::kScrollFocusedStrategy)); + if (sliding_window_max_percent_dropped_After_1_sec_.has_value()) smoothness_data.worst_smoothness_after1sec = sliding_window_max_percent_dropped_After_1_sec_.value(); @@ -301,6 +392,22 @@ void DroppedFrameCounter::ReportFrames() { } } +void DroppedFrameCounter::ReportFramesForUI() { + DCHECK(report_for_ui_); +#if BUILDFLAG(IS_CHROMEOS_ASH) + UMA_HISTOGRAM_PERCENTAGE( + "Ash.Smoothness.MaxPercentDroppedFrames_1sWindow.Uniform", + sliding_window_max_percent_dropped_); + + if (sliding_window_max_percent_dropped_ != + last_reported_metrics_.max_window) { + UMA_HISTOGRAM_PERCENTAGE("Ash.Smoothness.MaxPercentDroppedFrames_1sWindow", + sliding_window_max_percent_dropped_); + last_reported_metrics_.max_window = sliding_window_max_percent_dropped_; + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) +} + double DroppedFrameCounter::GetMostRecentAverageSmoothness() const { if (ukm_smoothness_data_) return ukm_smoothness_data_->data.avg_smoothness; @@ -330,11 +437,16 @@ void DroppedFrameCounter::Reset() { sliding_window_max_percent_dropped_After_1_sec_.reset(); sliding_window_max_percent_dropped_After_2_sec_.reset(); sliding_window_max_percent_dropped_After_5_sec_.reset(); - dropped_frame_count_in_window_ = 0; + std::fill_n(dropped_frame_count_in_window_, + SmoothnessStrategy::kStrategyCount, 0); fcp_received_ = false; sliding_window_ = {}; latest_sliding_window_start_ = {}; - sliding_window_histogram_.Clear(); + sliding_window_histogram_[SmoothnessStrategy::kDefaultStrategy].Clear(); + sliding_window_histogram_[SmoothnessStrategy::kScrollFocusedStrategy].Clear(); + sliding_window_histogram_[SmoothnessStrategy::kMainFocusedStrategy].Clear(); + sliding_window_histogram_[SmoothnessStrategy::kCompositorFocusedStrategy] + .Clear(); ring_buffer_.Clear(); time_max_delta_ = {}; last_reported_metrics_ = {}; @@ -349,69 +461,148 @@ base::TimeDelta DroppedFrameCounter::ComputeCurrentWindowSize() const { } void DroppedFrameCounter::NotifyFrameResult(const viz::BeginFrameArgs& args, - bool is_dropped) { + const FrameInfo& frame_info) { // Entirely disregard the frames with interval larger than the window -- // these are violating the assumptions in the below code and should // only occur with external frame control, where dropped frame stats // are not relevant. - if (args.interval >= kSlidingWindowInterval) + if (args.interval >= sliding_window_interval_) return; - sliding_window_.push({args, is_dropped}); + if (sorted_frame_callback_) + sorted_frame_callback_->Run(args, frame_info); - if (ComputeCurrentWindowSize() < kSlidingWindowInterval) { - if (is_dropped) - ++dropped_frame_count_in_window_; + sliding_window_.push({args, frame_info}); + UpdateDroppedFrameCountInWindow(frame_info, 1); + + if (ComputeCurrentWindowSize() < sliding_window_interval_) return; + + DCHECK_GE( + dropped_frame_count_in_window_[SmoothnessStrategy::kDefaultStrategy], 0u); + DCHECK_GE( + sliding_window_.size(), + dropped_frame_count_in_window_[SmoothnessStrategy::kDefaultStrategy]); + + while (ComputeCurrentWindowSize() > sliding_window_interval_) { + PopSlidingWindow(); } + DCHECK(!sliding_window_.empty()); +} - DCHECK_GE(dropped_frame_count_in_window_, 0u); - DCHECK_GE(sliding_window_.size(), dropped_frame_count_in_window_); +void DroppedFrameCounter::PopSlidingWindow() { + const auto removed_args = sliding_window_.front().first; + const auto removed_frame_info = sliding_window_.front().second; + UpdateDroppedFrameCountInWindow(removed_frame_info, -1); + sliding_window_.pop(); + if (sliding_window_.empty()) + return; - const auto max_sliding_window_start = - args.frame_time - kSlidingWindowInterval; - const auto max_difference = args.interval * 1.5; - while (ComputeCurrentWindowSize() > kSlidingWindowInterval) { - const auto removed_args = sliding_window_.front().first; - const auto removed_was_dropped = sliding_window_.front().second; - if (removed_was_dropped) { - DCHECK_GT(dropped_frame_count_in_window_, 0u); - --dropped_frame_count_in_window_; - } - sliding_window_.pop(); - DCHECK(!sliding_window_.empty()); - - auto dropped = dropped_frame_count_in_window_; - if (ComputeCurrentWindowSize() <= kSlidingWindowInterval && is_dropped) - ++dropped; - - // If two consecutive 'completed' frames are far apart from each other (in - // time), then report the 'dropped frame count' for the sliding window(s) in - // between. Note that the window-size still needs to be at least - // kSlidingWindowInterval. - const auto& remaining_oldest_args = sliding_window_.front().first; - const auto last_timestamp = - std::min(remaining_oldest_args.frame_time, max_sliding_window_start); - const auto difference = last_timestamp - removed_args.frame_time; - const size_t count = - difference > max_difference ? std::ceil(difference / args.interval) : 1; - double percent_dropped_frame = - std::min((dropped * 100.0) / total_frames_in_window_, 100.0); - sliding_window_histogram_.AddPercentDroppedFrame(percent_dropped_frame, - count); - - if (percent_dropped_frame > sliding_window_max_percent_dropped_) { - time_max_delta_ = args.frame_time - time_fcp_received_; - sliding_window_max_percent_dropped_ = percent_dropped_frame; - } - UpdateMaxPercentDroppedFrame(percent_dropped_frame); + // Don't count the newest element if it is outside the current window. + const auto& newest_args = sliding_window_.back().first; + const auto newest_was_dropped = + sliding_window_.back().second.IsDroppedAffectingSmoothness(); - latest_sliding_window_start_ = last_timestamp; - latest_sliding_window_interval_ = remaining_oldest_args.interval; + uint32_t invalidated_frames = 0; + if (ComputeCurrentWindowSize() > sliding_window_interval_ && + newest_was_dropped) { + invalidated_frames++; } - if (is_dropped) - ++dropped_frame_count_in_window_; + // If two consecutive 'completed' frames are far apart from each other (in + // time), then report the 'dropped frame count' for the sliding window(s) in + // between. Note that the window-size still needs to be at least + // sliding_window_interval_. + const auto max_sliding_window_start = + newest_args.frame_time - sliding_window_interval_; + const auto max_difference = newest_args.interval * 1.5; + const auto& remaining_oldest_args = sliding_window_.front().first; + const auto last_timestamp = + std::min(remaining_oldest_args.frame_time, max_sliding_window_start); + const auto difference = last_timestamp - removed_args.frame_time; + const size_t count = difference > max_difference + ? std::ceil(difference / newest_args.interval) + : 1; + + uint32_t dropped = + dropped_frame_count_in_window_[SmoothnessStrategy::kDefaultStrategy] - + invalidated_frames; + double percent_dropped_frame = + std::min((dropped * 100.0) / total_frames_in_window_, 100.0); + sliding_window_histogram_[SmoothnessStrategy::kDefaultStrategy] + .AddPercentDroppedFrame(percent_dropped_frame, count); + + uint32_t dropped_compositor = + dropped_frame_count_in_window_ + [SmoothnessStrategy::kCompositorFocusedStrategy] - + invalidated_frames; + double percent_dropped_frame_compositor = + std::min((dropped_compositor * 100.0) / total_frames_in_window_, 100.0); + sliding_window_histogram_[SmoothnessStrategy::kCompositorFocusedStrategy] + .AddPercentDroppedFrame(percent_dropped_frame_compositor, count); + + uint32_t dropped_main = + dropped_frame_count_in_window_[SmoothnessStrategy::kMainFocusedStrategy] - + invalidated_frames; + double percent_dropped_frame_main = + std::min((dropped_main * 100.0) / total_frames_in_window_, 100.0); + sliding_window_histogram_[SmoothnessStrategy::kMainFocusedStrategy] + .AddPercentDroppedFrame(percent_dropped_frame_main, count); + + uint32_t dropped_scroll = dropped_frame_count_in_window_ + [SmoothnessStrategy::kScrollFocusedStrategy] - + invalidated_frames; + double percent_dropped_frame_scroll = + std::min((dropped_scroll * 100.0) / total_frames_in_window_, 100.0); + sliding_window_histogram_[SmoothnessStrategy::kScrollFocusedStrategy] + .AddPercentDroppedFrame(percent_dropped_frame_scroll, count); + + if (percent_dropped_frame > sliding_window_max_percent_dropped_) { + time_max_delta_ = newest_args.frame_time - time_fcp_received_; + sliding_window_max_percent_dropped_ = percent_dropped_frame; + } + + latest_sliding_window_start_ = last_timestamp; + latest_sliding_window_interval_ = remaining_oldest_args.interval; + + UpdateMaxPercentDroppedFrame(percent_dropped_frame); +} + +void DroppedFrameCounter::UpdateDroppedFrameCountInWindow( + const FrameInfo& frame_info, + int count) { + if (frame_info.IsDroppedAffectingSmoothness()) { + DCHECK_GE( + dropped_frame_count_in_window_[SmoothnessStrategy::kDefaultStrategy] + + count, + 0u); + dropped_frame_count_in_window_[SmoothnessStrategy::kDefaultStrategy] += + count; + } + if (frame_info.WasCompositorUpdateDropped()) { + DCHECK_GE(dropped_frame_count_in_window_ + [SmoothnessStrategy::kCompositorFocusedStrategy] + + count, + 0u); + dropped_frame_count_in_window_ + [SmoothnessStrategy::kCompositorFocusedStrategy] += count; + } + if (frame_info.WasMainUpdateDropped()) { + DCHECK_GE(dropped_frame_count_in_window_ + [SmoothnessStrategy::kMainFocusedStrategy] + + count, + 0u); + dropped_frame_count_in_window_[SmoothnessStrategy::kMainFocusedStrategy] += + count; + } + if (frame_info.IsScrollPrioritizeFrameDropped()) { + DCHECK_GE(dropped_frame_count_in_window_ + [SmoothnessStrategy::kScrollFocusedStrategy] + + count, + 0u); + dropped_frame_count_in_window_ + [SmoothnessStrategy::kScrollFocusedStrategy] += count; + } } void DroppedFrameCounter::UpdateMaxPercentDroppedFrame( @@ -419,7 +610,7 @@ void DroppedFrameCounter::UpdateMaxPercentDroppedFrame( if (!fcp_received_) return; - const auto fcp_time_delta = base::TimeTicks::Now() - time_fcp_received_; + const auto fcp_time_delta = latest_sliding_window_start_ - time_fcp_received_; if (fcp_time_delta > base::Seconds(1)) sliding_window_max_percent_dropped_After_1_sec_ = @@ -441,4 +632,8 @@ void DroppedFrameCounter::OnFcpReceived() { time_fcp_received_ = base::TimeTicks::Now(); } +void DroppedFrameCounter::SetSortedFrameCallback(SortedFrameCallback callback) { + sorted_frame_callback_ = callback; +} + } // namespace cc diff --git a/chromium/cc/metrics/dropped_frame_counter.h b/chromium/cc/metrics/dropped_frame_counter.h index 87f4daf9fb8..38248dcfb2a 100644 --- a/chromium/cc/metrics/dropped_frame_counter.h +++ b/chromium/cc/metrics/dropped_frame_counter.h @@ -11,8 +11,11 @@ #include <utility> #include <vector> +#include "base/callback_forward.h" #include "base/containers/ring_buffer.h" +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" +#include "cc/metrics/frame_info.h" #include "cc/metrics/frame_sorter.h" #include "cc/metrics/ukm_smoothness_data.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -30,10 +33,20 @@ class CC_EXPORT DroppedFrameCounter { kFrameStateComplete }; + enum SmoothnessStrategy { + kDefaultStrategy, // All threads and interactions are considered equal. + kScrollFocusedStrategy, // Scroll interactions has the highest priority. + kMainFocusedStrategy, // Reports dropped frames with main thread updates. + kCompositorFocusedStrategy, // Reports dropped frames with compositor + // thread updates. + kStrategyCount + }; + class CC_EXPORT SlidingWindowHistogram { public: void AddPercentDroppedFrame(double percent_dropped_frame, size_t count = 1); uint32_t GetPercentDroppedFramePercentile(double percentile) const; + double GetPercentDroppedFrameVariance() const; std::vector<double> GetPercentDroppedFrameBuckets() const; void Clear(); std::ostream& Dump(std::ostream& stream) const; @@ -63,6 +76,11 @@ class CC_EXPORT DroppedFrameCounter { double GetMostRecentAverageSmoothness() const; double GetMostRecent95PercentileSmoothness() const; + using SortedFrameCallback = + base::RepeatingCallback<void(const viz::BeginFrameArgs& args, + const FrameInfo&)>; + void SetSortedFrameCallback(SortedFrameCallback callback); + typedef base::RingBuffer<FrameState, 180> RingBufferType; RingBufferType::Iterator begin() const { return ring_buffer_.Begin(); } RingBufferType::Iterator end() const { return ring_buffer_.End(); } @@ -71,9 +89,10 @@ class CC_EXPORT DroppedFrameCounter { void AddPartialFrame(); void AddDroppedFrame(); void ReportFrames(); + void ReportFramesForUI(); void OnBeginFrame(const viz::BeginFrameArgs& args, bool is_scroll_active); - void OnEndFrame(const viz::BeginFrameArgs& args, bool is_dropped); + void OnEndFrame(const viz::BeginFrameArgs& args, const FrameInfo& frame_info); void SetUkmSmoothnessDestination(UkmSmoothnessDataShared* smoothness_data); void OnFcpReceived(); @@ -87,6 +106,9 @@ class CC_EXPORT DroppedFrameCounter { // frames are not considered to be dropped. void ResetPendingFrames(base::TimeTicks timestamp); + // Enable dropped frame report for ui::Compositor.. + void EnableReporForUI(); + void set_total_counter(TotalFrameCounter* total_counter) { total_counter_ = total_counter; } @@ -100,25 +122,62 @@ class CC_EXPORT DroppedFrameCounter { return sliding_window_max_percent_dropped_; } - uint32_t SlidingWindow95PercentilePercentDropped() const { - return sliding_window_histogram_.GetPercentDroppedFramePercentile(0.95); + absl::optional<double> max_percent_dropped_After_1_sec() const { + return sliding_window_max_percent_dropped_After_1_sec_; } - const SlidingWindowHistogram* GetSlidingWindowHistogram() const { - return &sliding_window_histogram_; + absl::optional<double> max_percent_dropped_After_2_sec() const { + return sliding_window_max_percent_dropped_After_2_sec_; + } + + absl::optional<double> max_percent_dropped_After_5_sec() const { + return sliding_window_max_percent_dropped_After_5_sec_; + } + + uint32_t SlidingWindow95PercentilePercentDropped( + SmoothnessStrategy strategy) const { + DCHECK_GT(SmoothnessStrategy::kStrategyCount, strategy); + return sliding_window_histogram_[strategy].GetPercentDroppedFramePercentile( + 0.95); + } + + uint32_t SlidingWindowMedianPercentDropped( + SmoothnessStrategy strategy) const { + DCHECK_GT(SmoothnessStrategy::kStrategyCount, strategy); + return sliding_window_histogram_[strategy].GetPercentDroppedFramePercentile( + 0.5); + } + + double SlidingWindowPercentDroppedVariance( + SmoothnessStrategy strategy) const { + DCHECK_GT(SmoothnessStrategy::kStrategyCount, strategy); + return sliding_window_histogram_[strategy].GetPercentDroppedFrameVariance(); + } + + const SlidingWindowHistogram* GetSlidingWindowHistogram( + SmoothnessStrategy strategy) const { + DCHECK_GT(SmoothnessStrategy::kStrategyCount, strategy); + return &sliding_window_histogram_[strategy]; } private: - void NotifyFrameResult(const viz::BeginFrameArgs& args, bool is_dropped); + void NotifyFrameResult(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info); base::TimeDelta ComputeCurrentWindowSize() const; + void PopSlidingWindow(); void UpdateMaxPercentDroppedFrame(double percent_dropped_frame); - const base::TimeDelta kSlidingWindowInterval = base::Seconds(1); - std::queue<std::pair<const viz::BeginFrameArgs, bool>> sliding_window_; - uint32_t dropped_frame_count_in_window_ = 0; + // Adds count to dropped_frame_count_in_window_ of each strategy. + void UpdateDroppedFrameCountInWindow(const FrameInfo& frame_info, int count); + + base::TimeDelta sliding_window_interval_; + std::queue<std::pair<const viz::BeginFrameArgs, FrameInfo>> sliding_window_; + uint32_t dropped_frame_count_in_window_[SmoothnessStrategy::kStrategyCount] = + {0}; double total_frames_in_window_ = 60.0; - SlidingWindowHistogram sliding_window_histogram_; + SlidingWindowHistogram + sliding_window_histogram_[SmoothnessStrategy::kStrategyCount]; base::TimeTicks latest_sliding_window_start_; base::TimeDelta latest_sliding_window_interval_; @@ -135,9 +194,9 @@ class CC_EXPORT DroppedFrameCounter { absl::optional<double> sliding_window_max_percent_dropped_After_5_sec_; base::TimeTicks time_fcp_received_; base::TimeDelta time_max_delta_; - UkmSmoothnessDataShared* ukm_smoothness_data_ = nullptr; + raw_ptr<UkmSmoothnessDataShared> ukm_smoothness_data_ = nullptr; FrameSorter frame_sorter_; - TotalFrameCounter* total_counter_ = nullptr; + raw_ptr<TotalFrameCounter> total_counter_ = nullptr; struct { double max_window = 0; @@ -153,6 +212,10 @@ class CC_EXPORT DroppedFrameCounter { }; absl::optional<ScrollStartInfo> scroll_start_; std::map<viz::BeginFrameId, ScrollStartInfo> scroll_start_per_frame_; + + absl::optional<SortedFrameCallback> sorted_frame_callback_; + + bool report_for_ui_ = false; }; CC_EXPORT std::ostream& operator<<( diff --git a/chromium/cc/metrics/dropped_frame_counter_unittest.cc b/chromium/cc/metrics/dropped_frame_counter_unittest.cc index 0ac7053f0ef..abff7346657 100644 --- a/chromium/cc/metrics/dropped_frame_counter_unittest.cc +++ b/chromium/cc/metrics/dropped_frame_counter_unittest.cc @@ -6,17 +6,29 @@ #include <vector> +#include "base/memory/raw_ptr.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" +#include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" +#include "build/chromeos_buildflags.h" #include "cc/animation/animation_host.h" #include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_frame_info.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" namespace cc { namespace { +using SmoothnessStrategy = DroppedFrameCounter::SmoothnessStrategy; + +FrameInfo CreateStubFrameInfo(bool is_dropped) { + return CreateFakeFrameInfo(is_dropped + ? FrameInfo::FrameFinalState::kDropped + : FrameInfo::FrameFinalState::kPresentedAll); +} + class DroppedFrameCounterTestBase : public LayerTreeTest { public: DroppedFrameCounterTestBase() = default; @@ -188,7 +200,7 @@ class DroppedFrameCounterTestBase : public LayerTreeTest { // The |wait_| event is used when the test wants to deliberately force the // main-thread to block while processing begin-main-frames. base::Lock wait_lock_; - base::WaitableEvent* wait_ = nullptr; + raw_ptr<base::WaitableEvent> wait_ = nullptr; // These fields are populated in the compositor thread when the desired number // of frames have been processed. These fields are subsequently compared @@ -255,7 +267,9 @@ class DroppedFrameCounterMainDropsSmoothnessTest class DroppedFrameCounterTest : public testing::Test { public: - DroppedFrameCounterTest() { + explicit DroppedFrameCounterTest(SmoothnessStrategy smoothness_strategy = + SmoothnessStrategy::kDefaultStrategy) + : smoothness_strategy_(smoothness_strategy) { dropped_frame_counter_.set_total_counter(&total_frame_counter_); dropped_frame_counter_.OnFcpReceived(); } @@ -267,7 +281,8 @@ class DroppedFrameCounterTest : public testing::Test { for (auto is_dropped : frame_states) { viz::BeginFrameArgs args_ = SimulateBeginFrameArgs(); dropped_frame_counter_.OnBeginFrame(args_, /*is_scroll_active=*/false); - dropped_frame_counter_.OnEndFrame(args_, is_dropped); + dropped_frame_counter_.OnEndFrame(args_, + CreateStubFrameInfo(is_dropped)); sequence_number_++; frame_time_ += interval_; } @@ -300,8 +315,17 @@ class DroppedFrameCounterTest : public testing::Test { viz::BeginFrameArgs args_ = SimulateBeginFrameArgs(); dropped_frame_counter_.OnBeginFrame(args_, /*is_scroll_active=*/false); dropped_frame_counter_.OnBeginFrame(args_, /*is_scroll_active=*/false); - dropped_frame_counter_.OnEndFrame(args_, main_dropped); - dropped_frame_counter_.OnEndFrame(args_, impl_dropped); + + // End the 'main thread' arm of the fork. + auto main_info = CreateStubFrameInfo(main_dropped); + main_info.main_thread_response = FrameInfo::MainThreadResponse::kIncluded; + dropped_frame_counter_.OnEndFrame(args_, main_info); + + // End the 'compositor thread' arm of the fork. + auto impl_info = CreateStubFrameInfo(impl_dropped); + impl_info.main_thread_response = FrameInfo::MainThreadResponse::kMissing; + dropped_frame_counter_.OnEndFrame(args_, impl_info); + sequence_number_++; frame_time_ += interval_; } @@ -314,8 +338,46 @@ class DroppedFrameCounterTest : public testing::Test { return dropped_frame_counter_.sliding_window_max_percent_dropped(); } + double MaxPercentDroppedFrameAfter1Sec() { + auto percent_dropped = + dropped_frame_counter_.max_percent_dropped_After_1_sec(); + EXPECT_TRUE(percent_dropped.has_value()); + return percent_dropped.value(); + } + + double MaxPercentDroppedFrameAfter2Sec() { + auto percent_dropped = + dropped_frame_counter_.max_percent_dropped_After_2_sec(); + EXPECT_TRUE(percent_dropped.has_value()); + return percent_dropped.value(); + } + + double MaxPercentDroppedFrameAfter5Sec() { + auto percent_dropped = + dropped_frame_counter_.max_percent_dropped_After_5_sec(); + EXPECT_TRUE(percent_dropped.has_value()); + return percent_dropped.value(); + } + double PercentDroppedFrame95Percentile() { - return dropped_frame_counter_.SlidingWindow95PercentilePercentDropped(); + return dropped_frame_counter_.SlidingWindow95PercentilePercentDropped( + smoothness_strategy_); + } + + double PercentDroppedFrameMedian() { + return dropped_frame_counter_.SlidingWindowMedianPercentDropped( + smoothness_strategy_); + } + + double PercentDroppedFrameVariance() { + return dropped_frame_counter_.SlidingWindowPercentDroppedVariance( + smoothness_strategy_); + } + + const DroppedFrameCounter::SlidingWindowHistogram* + GetSlidingWindowHistogram() { + return dropped_frame_counter_.GetSlidingWindowHistogram( + smoothness_strategy_); } double GetTotalFramesInWindow() { return base::Seconds(1) / interval_; } @@ -330,8 +392,7 @@ class DroppedFrameCounterTest : public testing::Test { constexpr double epsilon = 0.001; bool buckets_match = true; std::vector<double> buckets = - dropped_frame_counter_.GetSlidingWindowHistogram() - ->GetPercentDroppedFrameBuckets(); + GetSlidingWindowHistogram()->GetPercentDroppedFrameBuckets(); if (buckets.size() != expected_buckets.size()) { buckets_match = false; } else { @@ -357,10 +418,13 @@ class DroppedFrameCounterTest : public testing::Test { TotalFrameCounter total_frame_counter_; uint64_t sequence_number_ = 1; uint64_t source_id_ = 1; - const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance(); + raw_ptr<const base::TickClock> tick_clock_ = + base::DefaultTickClock::GetInstance(); base::TimeTicks frame_time_ = tick_clock_->NowTicks(); base::TimeDelta interval_ = base::Microseconds(16667); // 16.667 ms + SmoothnessStrategy smoothness_strategy_; + viz::BeginFrameArgs SimulateBeginFrameArgs() { viz::BeginFrameId current_id_(source_id_, sequence_number_); viz::BeginFrameArgs args = viz::BeginFrameArgs(); @@ -371,7 +435,30 @@ class DroppedFrameCounterTest : public testing::Test { } }; -TEST_F(DroppedFrameCounterTest, SimplePattern1) { +// Test class that supports parameterized tests for each of the different +// SmoothnessStrategy. +// +// TODO(jonross): when we build the other strategies parameterize the +// expectations. +class SmoothnessStrategyDroppedFrameCounterTest + : public DroppedFrameCounterTest, + public testing::WithParamInterface<SmoothnessStrategy> { + public: + SmoothnessStrategyDroppedFrameCounterTest() + : DroppedFrameCounterTest(GetParam()) {} + ~SmoothnessStrategyDroppedFrameCounterTest() override = default; + SmoothnessStrategyDroppedFrameCounterTest( + const SmoothnessStrategyDroppedFrameCounterTest&) = delete; + SmoothnessStrategyDroppedFrameCounterTest& operator=( + const SmoothnessStrategyDroppedFrameCounterTest&) = delete; +}; + +INSTANTIATE_TEST_SUITE_P( + DefaultStrategy, + SmoothnessStrategyDroppedFrameCounterTest, + ::testing::Values(SmoothnessStrategy::kDefaultStrategy)); + +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, SimplePattern1) { // 2 out of every 3 frames are dropped (In total 80 frames out of 120). SimulateFrameSequence({true, true, true, false, true, false}, 20); @@ -380,36 +467,46 @@ TEST_F(DroppedFrameCounterTest, SimplePattern1) { // Which means a max of 67 dropped frames. EXPECT_EQ(std::round(MaxPercentDroppedFrame()), 67); EXPECT_EQ(PercentDroppedFrame95Percentile(), 67); // all values are in the - // 67th bucket, and as a result 95th percentile is also 67. + // 65th-67th bucket, and as a result 95th percentile is also 67. + EXPECT_EQ(PercentDroppedFrameMedian(), 65); + EXPECT_LE(PercentDroppedFrameVariance(), 1); } -TEST_F(DroppedFrameCounterTest, SimplePattern2) { +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, SimplePattern2) { // 1 out of every 5 frames are dropped (In total 24 frames out of 120). SimulateFrameSequence({false, false, false, false, true}, 24); double expected_percent_dropped_frame = (12 / GetTotalFramesInWindow()) * 100; EXPECT_FLOAT_EQ(MaxPercentDroppedFrame(), expected_percent_dropped_frame); - EXPECT_EQ(PercentDroppedFrame95Percentile(), 20); // all values are in the + EXPECT_EQ(PercentDroppedFrame95Percentile(), + 20); // all values are in the // 20th bucket, and as a result 95th percentile is also 20. + EXPECT_EQ(PercentDroppedFrameMedian(), 20); + EXPECT_LE(PercentDroppedFrameVariance(), 1); } -TEST_F(DroppedFrameCounterTest, IncompleteWindow) { - // There are only 5 frames submitted and both Max and 95pct should report - // zero. +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, IncompleteWindow) { + // There are only 5 frames submitted, so Max, 95pct, median and variance + // should report zero. SimulateFrameSequence({false, false, false, false, true}, 1); EXPECT_EQ(MaxPercentDroppedFrame(), 0.0); EXPECT_EQ(PercentDroppedFrame95Percentile(), 0); + EXPECT_EQ(PercentDroppedFrameMedian(), 0); + EXPECT_LE(PercentDroppedFrameVariance(), 1); } -TEST_F(DroppedFrameCounterTest, MaxPercentDroppedChanges) { +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, MaxPercentDroppedChanges) { // First 60 frames have 20% dropped. SimulateFrameSequence({false, false, false, false, true}, 12); double expected_percent_dropped_frame1 = (12 / GetTotalFramesInWindow()) * 100; EXPECT_EQ(MaxPercentDroppedFrame(), expected_percent_dropped_frame1); - EXPECT_FLOAT_EQ(PercentDroppedFrame95Percentile(), 20); // There is only one + EXPECT_FLOAT_EQ(PercentDroppedFrame95Percentile(), + 20); // There is only one // element in the histogram and that is 20. + EXPECT_EQ(PercentDroppedFrameMedian(), 20); + EXPECT_LE(PercentDroppedFrameVariance(), 1); // 30 new frames are added that have 18 dropped frames. // and the 30 frame before that had 6 dropped frames. @@ -455,7 +552,7 @@ TEST_F(DroppedFrameCounterTest, NoCrashForIntervalLargerThanWindow) { SimulateFrameSequence({false, false}, 1); } -TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFrames) { +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, Percentile95WithIdleFrames) { // Test scenario: // . 4s of 20% dropped frames. // . 96s of idle time. @@ -469,7 +566,7 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFrames) { "kFps must be a multiple of 5 because this test depends on it."); SetInterval(kInterval); - const auto* histogram = dropped_frame_counter_.GetSlidingWindowHistogram(); + const auto* histogram = GetSlidingWindowHistogram(); // First 4 seconds with 20% dropped frames. SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 4); @@ -487,7 +584,8 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFrames) { EXPECT_GT(histogram->GetPercentDroppedFramePercentile(0.97), 0u); } -TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesWhileHidden) { +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, + Percentile95WithIdleFramesWhileHidden) { // The test scenario is the same as |Percentile95WithIdleFrames| test: // . 4s of 20% dropped frames. // . 96s of idle time. @@ -503,7 +601,7 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesWhileHidden) { "kFps must be a multiple of 5 because this test depends on it."); SetInterval(kInterval); - const auto* histogram = dropped_frame_counter_.GetSlidingWindowHistogram(); + const auto* histogram = GetSlidingWindowHistogram(); // First 4 seconds with 20% dropped frames. SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 4); @@ -520,7 +618,8 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesWhileHidden) { EXPECT_EQ(histogram->GetPercentDroppedFramePercentile(0.95), 20u); } -TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesThenHide) { +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, + Percentile95WithIdleFramesThenHide) { // The test scenario is the same as |Percentile95WithIdleFramesWhileHidden|: // . 4s of 20% dropped frames. // . 96s of idle time. @@ -536,7 +635,7 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesThenHide) { "kFps must be a multiple of 5 because this test depends on it."); SetInterval(kInterval); - const auto* histogram = dropped_frame_counter_.GetSlidingWindowHistogram(); + const auto* histogram = GetSlidingWindowHistogram(); // First 4 seconds with 20% dropped frames. SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 4); @@ -556,7 +655,7 @@ TEST_F(DroppedFrameCounterTest, Percentile95WithIdleFramesThenHide) { // Tests that when ResetPendingFrames updates the sliding window, that the max // PercentDroppedFrames is also updated accordingly. (https://crbug.com/1225307) -TEST_F(DroppedFrameCounterTest, +TEST_P(SmoothnessStrategyDroppedFrameCounterTest, ResetPendingFramesUpdatesMaxPercentDroppedFrames) { // This tests a scenario where gaps in frame production lead to having // leftover frames in the sliding window for calculations of @@ -589,13 +688,14 @@ TEST_F(DroppedFrameCounterTest, // Advance 1s so that we will attempt to update the window when resetting the // pending frames. The pending dropped frame above should be calculated here, - // and both the max and 95th percentile should be updated. + // and the max percentile should be updated. AdvancetimeByIntervals(kFps); dropped_frame_counter_.ResetPendingFrames(GetNextFrameTime()); - - EXPECT_EQ(dropped_frame_counter_.sliding_window_max_percent_dropped(), - dropped_frame_counter_.SlidingWindow95PercentilePercentDropped()); EXPECT_GT(dropped_frame_counter_.sliding_window_max_percent_dropped(), 0u); + + // There should be enough sliding windows reported with 0 dropped frames that + // the 95th percentile stays at 0. + EXPECT_EQ(PercentDroppedFrame95Percentile(), 0u); } TEST_F(DroppedFrameCounterTest, ResetPendingFramesAccountingForPendingFrames) { @@ -747,7 +847,7 @@ TEST_F(DroppedFrameCounterTest, FramesInFlightWhenFcpReceived) { // End each of the frames as dropped. The first three should not count for // smoothness, only the last two. for (const auto& frame : pending_frames) { - dropped_frame_counter_.OnEndFrame(frame, true); + dropped_frame_counter_.OnEndFrame(frame, CreateStubFrameInfo(true)); } EXPECT_EQ(dropped_frame_counter_.total_smoothness_dropped(), 2u); } @@ -768,5 +868,79 @@ TEST_F(DroppedFrameCounterTest, ForkedCompositorFrameReporter) { EXPECT_EQ(dropped_frame_counter_.total_smoothness_dropped(), 3u); } +TEST_F(DroppedFrameCounterTest, WorstSmoothnessTiming) { + // Set an interval that rounds up nicely with 1 second. + constexpr auto kInterval = base::Milliseconds(10); + constexpr size_t kFps = base::Seconds(1) / kInterval; + static_assert( + kFps % 5 == 0, + "kFps must be a multiple of 5 because this test depends on it."); + SetInterval(kInterval); + + // Prepare a second of pending frames, and send FCP after the last of these + // frames. + dropped_frame_counter_.Reset(); + std::vector<viz::BeginFrameArgs> pending_frames = SimulatePendingFrame(kFps); + const auto& last_frame = pending_frames.back(); + base::TimeTicks time_fcp_sent = + last_frame.frame_time + last_frame.interval / 2; + dropped_frame_counter_.OnFcpReceived(); + dropped_frame_counter_.SetTimeFcpReceivedForTesting(time_fcp_sent); + + // End each of the pending frames as dropped. These shouldn't affect any of + // the metrics. + for (const auto& frame : pending_frames) { + dropped_frame_counter_.OnEndFrame(frame, CreateStubFrameInfo(true)); + } + + // After FCP time, add a second each of 80% and 60%, and three seconds of 40% + // dropped frames. This should be five seconds total. + SimulateFrameSequence({false, true, true, true, true}, kFps / 5); + SimulateFrameSequence({false, false, true, true, true}, kFps / 5); + SimulateFrameSequence({false, false, false, true, true}, (kFps / 5) * 3); + + // Next two seconds are 20% dropped frames. + SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 2); + + // The first 1, 2, and 5 seconds shouldn't be recorded in the corresponding + // max dropped after N seconds metrics. + EXPECT_FLOAT_EQ(MaxPercentDroppedFrame(), 80); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrameAfter1Sec(), 60); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrameAfter2Sec(), 40); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrameAfter5Sec(), 20); + + // Next second is 100% dropped frames, all metrics should include this. + SimulateFrameSequence({true}, kFps); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrame(), 100); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrameAfter1Sec(), 100); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrameAfter2Sec(), 100); + EXPECT_FLOAT_EQ(MaxPercentDroppedFrameAfter5Sec(), 100); +} + +#if BUILDFLAG(IS_CHROMEOS_ASH) +TEST_F(DroppedFrameCounterTest, ReportForUI) { + constexpr auto kInterval = base::Milliseconds(10); + constexpr size_t kFps = base::Seconds(1) / kInterval; + static_assert( + kFps % 5 == 0, + "kFps must be a multiple of 5 because this test depends on it."); + SetInterval(kInterval); + + dropped_frame_counter_.EnableReporForUI(); + base::HistogramTester histogram_tester; + + // 4 seconds with 20% dropped frames. + SimulateFrameSequence({false, false, false, false, true}, (kFps / 5) * 4); + + // Exact 1 sample of changing to 20% dropped frame percentage. + histogram_tester.ExpectUniqueSample( + "Ash.Smoothness.MaxPercentDroppedFrames_1sWindow", 20, 1); + // More than 1 samples of 20% dropped frame percentage. + EXPECT_GE(histogram_tester.GetBucketCount( + "Ash.Smoothness.MaxPercentDroppedFrames_1sWindow.Uniform", 20), + 1); +} +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + } // namespace } // namespace cc diff --git a/chromium/cc/metrics/event_metrics.cc b/chromium/cc/metrics/event_metrics.cc index 983e9de69d8..8391d3bc4ac 100644 --- a/chromium/cc/metrics/event_metrics.cc +++ b/chromium/cc/metrics/event_metrics.cc @@ -5,6 +5,7 @@ #include "cc/metrics/event_metrics.h" #include <algorithm> +#include <ostream> #include <utility> #include "base/check.h" @@ -251,9 +252,10 @@ std::unique_ptr<EventMetrics> EventMetrics::CreateFromExisting( absl::optional<GestureParams> gesture_params, DispatchStage last_dispatch_stage, const EventMetrics* existing) { - std::unique_ptr<EventMetrics> metrics = CreateInternal( - type, gesture_params, base::TimeTicks(), - existing ? existing->tick_clock_ : base::DefaultTickClock::GetInstance()); + std::unique_ptr<EventMetrics> metrics = + CreateInternal(type, gesture_params, base::TimeTicks(), + existing ? existing->tick_clock_.get() + : base::DefaultTickClock::GetInstance()); if (!metrics) return nullptr; diff --git a/chromium/cc/metrics/event_metrics.h b/chromium/cc/metrics/event_metrics.h index 3c6f3b32d56..14d318b7c26 100644 --- a/chromium/cc/metrics/event_metrics.h +++ b/chromium/cc/metrics/event_metrics.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -224,7 +225,7 @@ class CC_EXPORT EventMetrics { // the event. absl::optional<PinchType> pinch_type_; - const base::TickClock* const tick_clock_; + const raw_ptr<const base::TickClock> tick_clock_; // Timestamps of different stages of event dispatch. Timestamps are set as the // event moves forward in the pipeline. In the end, some stages might not have diff --git a/chromium/cc/metrics/events_metrics_manager.cc b/chromium/cc/metrics/events_metrics_manager.cc index 72993dae887..581a6c9ffec 100644 --- a/chromium/cc/metrics/events_metrics_manager.cc +++ b/chromium/cc/metrics/events_metrics_manager.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" +#include "base/memory/raw_ptr.h" namespace cc { @@ -35,7 +36,7 @@ class EventsMetricsManager::ScopedMonitorImpl void set_save_metrics() { save_metrics_ = true; } private: - EventsMetricsManager* const manager_; + const raw_ptr<EventsMetricsManager> manager_; DoneCallback done_callback_; bool save_metrics_ = false; }; diff --git a/chromium/cc/metrics/frame_info.cc b/chromium/cc/metrics/frame_info.cc new file mode 100644 index 00000000000..6d03d2fefd7 --- /dev/null +++ b/chromium/cc/metrics/frame_info.cc @@ -0,0 +1,189 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/metrics/frame_info.h" + +#include <algorithm> + +#include "build/build_config.h" + +namespace cc { + +namespace { + +bool IsCompositorSmooth(FrameInfo::SmoothThread thread) { + return thread == FrameInfo::SmoothThread::kSmoothCompositor || + thread == FrameInfo::SmoothThread::kSmoothBoth; +} + +bool IsMainSmooth(FrameInfo::SmoothThread thread) { + return thread == FrameInfo::SmoothThread::kSmoothMain || + thread == FrameInfo::SmoothThread::kSmoothBoth; +} + +bool ValidateFinalStateIsForMainThread(FrameInfo::FrameFinalState state) { + switch (state) { + case FrameInfo::FrameFinalState::kPresentedPartialOldMain: + case FrameInfo::FrameFinalState::kPresentedPartialNewMain: + // Frames that contain main-thread update cannot have a 'partial update' + // state. + return false; + + case FrameInfo::FrameFinalState::kPresentedAll: + case FrameInfo::FrameFinalState::kNoUpdateDesired: + case FrameInfo::FrameFinalState::kDropped: + return true; + } +} + +} // namespace + +bool FrameInfo::IsDroppedAffectingSmoothness() const { + // If neither of the threads are expected to be smooth, then this frame cannot + // affect smoothness. + if (smooth_thread == SmoothThread::kSmoothNone) + return false; + + if (IsMainSmooth(smooth_thread) && WasMainUpdateDropped()) { + return true; + } + + if (IsCompositorSmooth(smooth_thread) && WasCompositorUpdateDropped()) { + return true; + } + + return false; +} + +void FrameInfo::MergeWith(const FrameInfo& other) { +#if defined(OS_ANDROID) + // TODO(1278168): on android-webview, multiple frames can be submitted against + // the same BeginFrameArgs. This can trip the DCHECK()s in this function. + if (was_merged) + return; +#endif + DCHECK(!was_merged); + DCHECK(!other.was_merged); + DCHECK(Validate()); + DCHECK(other.Validate()); + + if (main_thread_response == MainThreadResponse::kIncluded) { + // |this| includes the main-thread updates. Therefore: + // - |other| must not also include main-thread updates. + // - |this| must have a valid final-state. + DCHECK_EQ(MainThreadResponse::kMissing, other.main_thread_response); + DCHECK(ValidateFinalStateIsForMainThread(final_state)); + + // If the compositor-only update did not include any changes from the + // main-thread, then it did drop the main-thread update. Therefore, overall + // the main-thread update was dropped, even if the 'main thread update' is + // presented in a subsequent frame. + bool compositor_only_change_included_new_main = + other.final_state == FrameFinalState::kPresentedAll || + other.final_state == FrameFinalState::kPresentedPartialNewMain; + main_update_was_dropped = final_state == FrameFinalState::kDropped || + !compositor_only_change_included_new_main; + + compositor_update_was_dropped = + other.final_state == FrameFinalState::kDropped; + } else { + // |this| does not include main-thread updates. Therefore: + // - |other| must include main-thread updates. + // - |other| must have a valid final-state. + DCHECK_EQ(MainThreadResponse::kIncluded, other.main_thread_response); + DCHECK(ValidateFinalStateIsForMainThread(other.final_state)); + + main_update_was_dropped = other.final_state == FrameFinalState::kDropped; + compositor_update_was_dropped = final_state == FrameFinalState::kDropped; + } + + was_merged = true; + main_thread_response = MainThreadResponse::kIncluded; + + // The |scroll_thread| information cannot change once the frame starts. So + // it should not need to be updated during merge. + DCHECK_EQ(scroll_thread, other.scroll_thread); + + if (other.has_missing_content) + has_missing_content = true; + + if (other.final_state == FrameFinalState::kDropped) + final_state = FrameFinalState::kDropped; + + const bool is_compositor_smooth = IsCompositorSmooth(smooth_thread) || + IsCompositorSmooth(other.smooth_thread); + const bool is_main_smooth = + IsMainSmooth(smooth_thread) || IsMainSmooth(other.smooth_thread); + if (is_compositor_smooth && is_main_smooth) { + smooth_thread = SmoothThread::kSmoothBoth; + } else if (is_compositor_smooth) { + smooth_thread = SmoothThread::kSmoothCompositor; + } else if (is_main_smooth) { + smooth_thread = SmoothThread::kSmoothMain; + } else { + smooth_thread = SmoothThread::kSmoothNone; + } + + total_latency = std::max(total_latency, other.total_latency); + + // Validate the state after the merge. + DCHECK(Validate()); +} + +bool FrameInfo::Validate() const { + // If |scroll_thread| is set, then the |smooth_thread| must include that + // thread. + if (scroll_thread == SmoothEffectDrivingThread::kCompositor) { + DCHECK(IsCompositorSmooth(smooth_thread)); + } else if (scroll_thread == SmoothEffectDrivingThread::kMain) { + DCHECK(IsMainSmooth(smooth_thread)); + } + + return true; +} + +bool FrameInfo::WasCompositorUpdateDropped() const { + if (was_merged) + return compositor_update_was_dropped; + return final_state == FrameFinalState::kDropped; +} + +bool FrameInfo::WasMainUpdateDropped() const { + if (was_merged) + return main_update_was_dropped; + + switch (final_state) { + case FrameFinalState::kDropped: + case FrameFinalState::kPresentedPartialOldMain: + return true; + + case FrameFinalState::kPresentedPartialNewMain: + // Although this frame dropped the main-thread updates for this particular + // frame, it did include new main-thread update. So do not treat this as a + // dropped frame. + return false; + + case FrameFinalState::kNoUpdateDesired: + case FrameFinalState::kPresentedAll: + return false; + } + + return false; +} + +bool FrameInfo::IsScrollPrioritizeFrameDropped() const { + // If any scroll is active the dropped frame for only the scrolling thread is + // reported. If no scroll is active then reports if dropped frames is + // affecting smoothness. + switch (scroll_thread) { + case SmoothEffectDrivingThread::kCompositor: + return WasCompositorUpdateDropped(); + case SmoothEffectDrivingThread::kMain: + return WasMainUpdateDropped(); + case SmoothEffectDrivingThread::kUnknown: + return IsDroppedAffectingSmoothness(); + } +} + +} // namespace cc diff --git a/chromium/cc/metrics/frame_info.h b/chromium/cc/metrics/frame_info.h new file mode 100644 index 00000000000..aa3a3a23ce7 --- /dev/null +++ b/chromium/cc/metrics/frame_info.h @@ -0,0 +1,81 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_METRICS_FRAME_INFO_H_ +#define CC_METRICS_FRAME_INFO_H_ + +#include "base/time/time.h" +#include "cc/cc_export.h" + +namespace cc { + +struct CC_EXPORT FrameInfo { + enum class FrameFinalState { + kNoUpdateDesired, + kDropped, + + // A `presented all` frame contains all the desired update for this vsync. + // Note that this doesn't necessarily mean the frame included updates from + // both the main and the compositor thread. For example, if there's only a + // main-thread animation running, and the animation update was included in + // the frame produced, then it's `presented all`, although the compositor + // thread did not have any updates for this frame. + kPresentedAll, + + // A `partial update` frame contains updates from a compositor frame, but + // misses the update from the main-thread for the same vsync. However, it is + // still possible for such a `partial update` frame to contain new update + // from an earlier main-thread. + // + // `kPresentedPartialOldMain` represents a partial update frame without any + // new update from the main-thread. + // `kPresentedPartialNewMain` represents a partial update frame with some + // new update from the main-thread. + kPresentedPartialOldMain, + kPresentedPartialNewMain, + }; + FrameFinalState final_state = FrameFinalState::kNoUpdateDesired; + + enum class SmoothThread { + kSmoothNone, + kSmoothCompositor, + kSmoothMain, + kSmoothBoth + }; + SmoothThread smooth_thread = SmoothThread::kSmoothNone; + + enum class MainThreadResponse { + kIncluded, + kMissing, + }; + MainThreadResponse main_thread_response = MainThreadResponse::kIncluded; + + enum class SmoothEffectDrivingThread { kMain, kCompositor, kUnknown }; + SmoothEffectDrivingThread scroll_thread = SmoothEffectDrivingThread::kUnknown; + + bool has_missing_content = false; + + // The total latency for the frame. If the frame had to be 'split' (i.e. + // compositor-thread update and main-thread updates were presented in separate + // frames), then this contains the maximum latency of the two updates. + base::TimeDelta total_latency; + + bool IsDroppedAffectingSmoothness() const; + void MergeWith(const FrameInfo& info); + + bool Validate() const; + + bool WasCompositorUpdateDropped() const; + bool WasMainUpdateDropped() const; + bool IsScrollPrioritizeFrameDropped() const; + + private: + bool was_merged = false; + bool compositor_update_was_dropped = false; + bool main_update_was_dropped = false; +}; + +} // namespace cc + +#endif // CC_METRICS_FRAME_INFO_H_ diff --git a/chromium/cc/metrics/frame_info_unittest.cc b/chromium/cc/metrics/frame_info_unittest.cc new file mode 100644 index 00000000000..2ac2cb24f92 --- /dev/null +++ b/chromium/cc/metrics/frame_info_unittest.cc @@ -0,0 +1,53 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/metrics/frame_info.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +using MainThreadResponse = FrameInfo::MainThreadResponse; +using FrameFinalState = FrameInfo::FrameFinalState; + +TEST(FrameInfoTest, WasMainUpdateDroppedForkedReporters) { + FrameInfo main, compositor; + + main.main_thread_response = MainThreadResponse::kIncluded; + compositor.main_thread_response = MainThreadResponse::kMissing; + + // For a 'forked' frame: the compositor-update is dropped, and the main-thread + // update was presented. For this frame, both the compositor-thread and the + // main-thread update are considered dropped (because the compositor-thread + // did not update any new main-thread). + main.final_state = FrameFinalState::kPresentedAll; + compositor.final_state = FrameFinalState::kDropped; + + auto test = main; + test.MergeWith(compositor); + EXPECT_TRUE(test.WasMainUpdateDropped()); + EXPECT_TRUE(test.WasCompositorUpdateDropped()); + + // Even if the compositor-thread update is presented, the overall main-thread + // update is dropped if the compositor-update is not accompanied by new + // main-thread update (from earlier frames). + compositor.final_state = FrameFinalState::kPresentedPartialOldMain; + test = main; + test.MergeWith(compositor); + EXPECT_TRUE(test.WasMainUpdateDropped()); + EXPECT_FALSE(test.WasCompositorUpdateDropped()); + + // If the compositor-thread is accompanied by new main-thread update (even if + // from earlier frames), then the main-thread is update is considered not + // dropped. + compositor.final_state = FrameFinalState::kPresentedPartialNewMain; + test = main; + test.MergeWith(compositor); + EXPECT_FALSE(test.WasMainUpdateDropped()); + EXPECT_FALSE(test.WasCompositorUpdateDropped()); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/metrics/frame_sequence_metrics.cc b/chromium/cc/metrics/frame_sequence_metrics.cc index b5a1767bb1a..e4b9c405a0e 100644 --- a/chromium/cc/metrics/frame_sequence_metrics.cc +++ b/chromium/cc/metrics/frame_sequence_metrics.cc @@ -16,25 +16,28 @@ #include "cc/metrics/frame_sequence_tracker.h" #include "cc/metrics/jank_metrics.h" #include "cc/metrics/throughput_ukm_reporter.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" namespace cc { +using SmoothEffectDrivingThread = FrameInfo::SmoothEffectDrivingThread; + bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type, - FrameSequenceMetrics::ThreadType thread_type) { + SmoothEffectDrivingThread thread_type) { if (sequence_type == FrameSequenceTrackerType::kCompositorAnimation) - return thread_type == FrameSequenceMetrics::ThreadType::kCompositor; + return thread_type == SmoothEffectDrivingThread::kCompositor; if (sequence_type == FrameSequenceTrackerType::kMainThreadAnimation || sequence_type == FrameSequenceTrackerType::kJSAnimation) - return thread_type == FrameSequenceMetrics::ThreadType::kMain; + return thread_type == SmoothEffectDrivingThread::kMain; return false; } bool ShouldReportForInteraction( FrameSequenceTrackerType sequence_type, - FrameSequenceMetrics::ThreadType reporting_thread_type, - FrameSequenceMetrics::ThreadType metrics_effective_thread_type) { + SmoothEffectDrivingThread reporting_thread_type, + SmoothEffectDrivingThread metrics_effective_thread_type) { // For scrollbar/touch/wheel scroll, the slower thread is the one we want to // report. For pinch-zoom, it's the compositor-thread. if (sequence_type == FrameSequenceTrackerType::kScrollbarScroll || @@ -43,8 +46,7 @@ bool ShouldReportForInteraction( return reporting_thread_type == metrics_effective_thread_type; if (sequence_type == FrameSequenceTrackerType::kPinchZoom) - return reporting_thread_type == - FrameSequenceMetrics::ThreadType::kCompositor; + return reporting_thread_type == SmoothEffectDrivingThread::kCompositor; return false; } @@ -59,11 +61,11 @@ constexpr int kBuiltinSequenceNum = static_cast<int>(FrameSequenceTrackerType::kMaxType) + 1; constexpr int kMaximumHistogramIndex = 3 * kBuiltinSequenceNum; -int GetIndexForMetric(FrameSequenceMetrics::ThreadType thread_type, +int GetIndexForMetric(SmoothEffectDrivingThread thread_type, FrameSequenceTrackerType type) { - if (thread_type == FrameSequenceMetrics::ThreadType::kMain) + if (thread_type == SmoothEffectDrivingThread::kMain) return static_cast<int>(type); - if (thread_type == FrameSequenceMetrics::ThreadType::kCompositor) + if (thread_type == SmoothEffectDrivingThread::kCompositor) return static_cast<int>(type) + kBuiltinSequenceNum; return static_cast<int>(type) + 2 * kBuiltinSequenceNum; } @@ -100,13 +102,13 @@ bool IsInteractionType(FrameSequenceTrackerType sequence_type) { FrameSequenceMetrics::FrameSequenceMetrics(FrameSequenceTrackerType type, ThroughputUkmReporter* ukm_reporter) : type_(type), throughput_ukm_reporter_(ukm_reporter) { - ThreadType thread_type = GetEffectiveThread(); + SmoothEffectDrivingThread thread_type = GetEffectiveThread(); // Only construct |jank_reporter_| if it has a valid tracker and thread type. // For scrolling tracker types, |jank_reporter_| may be constructed later in // SetScrollingThread(). - if (thread_type == ThreadType::kCompositor || - thread_type == ThreadType::kMain) { + if (thread_type == SmoothEffectDrivingThread::kCompositor || + thread_type == SmoothEffectDrivingThread::kMain) { jank_reporter_ = std::make_unique<JankMetrics>(type, thread_type); } } @@ -118,15 +120,16 @@ void FrameSequenceMetrics::ReportLeftoverData() { ReportMetrics(); } -void FrameSequenceMetrics::SetScrollingThread(ThreadType scrolling_thread) { +void FrameSequenceMetrics::SetScrollingThread( + SmoothEffectDrivingThread scrolling_thread) { DCHECK(type_ == FrameSequenceTrackerType::kTouchScroll || type_ == FrameSequenceTrackerType::kWheelScroll || type_ == FrameSequenceTrackerType::kScrollbarScroll); - DCHECK_EQ(scrolling_thread_, ThreadType::kUnknown); + DCHECK_EQ(scrolling_thread_, SmoothEffectDrivingThread::kUnknown); scrolling_thread_ = scrolling_thread; DCHECK(!jank_reporter_); - DCHECK_NE(scrolling_thread, ThreadType::kUnknown); + DCHECK_NE(scrolling_thread, SmoothEffectDrivingThread::kUnknown); jank_reporter_ = std::make_unique<JankMetrics>(type_, scrolling_thread); } @@ -135,19 +138,18 @@ void FrameSequenceMetrics::SetCustomReporter(CustomReporter custom_reporter) { custom_reporter_ = std::move(custom_reporter); } -FrameSequenceMetrics::ThreadType FrameSequenceMetrics::GetEffectiveThread() - const { +SmoothEffectDrivingThread FrameSequenceMetrics::GetEffectiveThread() const { switch (type_) { case FrameSequenceTrackerType::kCompositorAnimation: case FrameSequenceTrackerType::kPinchZoom: case FrameSequenceTrackerType::kVideo: - return ThreadType::kCompositor; + return SmoothEffectDrivingThread::kCompositor; case FrameSequenceTrackerType::kMainThreadAnimation: case FrameSequenceTrackerType::kRAF: case FrameSequenceTrackerType::kCanvasAnimation: case FrameSequenceTrackerType::kJSAnimation: - return ThreadType::kMain; + return SmoothEffectDrivingThread::kMain; case FrameSequenceTrackerType::kTouchScroll: case FrameSequenceTrackerType::kScrollbarScroll: @@ -155,12 +157,12 @@ FrameSequenceMetrics::ThreadType FrameSequenceMetrics::GetEffectiveThread() return scrolling_thread_; case FrameSequenceTrackerType::kCustom: - return ThreadType::kMain; + return SmoothEffectDrivingThread::kMain; case FrameSequenceTrackerType::kMaxType: NOTREACHED(); } - return ThreadType::kUnknown; + return SmoothEffectDrivingThread::kUnknown; } void FrameSequenceMetrics::Merge( @@ -173,6 +175,9 @@ void FrameSequenceMetrics::Merge( main_throughput_.Merge(metrics->main_throughput_); frames_checkerboarded_ += metrics->frames_checkerboarded_; + v2_.frames_expected += metrics->v2_.frames_expected; + v2_.frames_dropped += metrics->v2_.frames_dropped; + if (jank_reporter_) jank_reporter_->Merge(std::move(metrics->jank_reporter_)); @@ -229,9 +234,34 @@ void FrameSequenceMetrics::ReportMetrics() { } const bool main_report = ThroughputData::CanReportHistogram( - this, ThreadType::kMain, main_throughput_); + this, SmoothEffectDrivingThread::kMain, main_throughput_); const bool compositor_report = ThroughputData::CanReportHistogram( - this, ThreadType::kCompositor, impl_throughput_); + this, SmoothEffectDrivingThread::kCompositor, impl_throughput_); + + if (v2_.frames_expected >= kMinFramesForThroughputMetric) { + const auto thread_type = GetEffectiveThread(); + const bool is_animation = ShouldReportForAnimation(type(), thread_type); + const bool is_interaction = + ShouldReportForInteraction(type(), thread_type, thread_type); + int percent = v2_.frames_expected == 0 + ? 0 + : std::ceil(100. * v2_.frames_dropped / + static_cast<double>(v2_.frames_expected)); + + if (is_animation) { + UMA_HISTOGRAM_PERCENTAGE( + "Graphics.Smoothness.PercentDroppedFrames2.AllAnimations", percent); + } + if (is_interaction) { + UMA_HISTOGRAM_PERCENTAGE( + "Graphics.Smoothness.PercentDroppedFrames2.AllInteractions", percent); + } + if (is_animation || is_interaction) { + UMA_HISTOGRAM_PERCENTAGE( + "Graphics.Smoothness.PercentDroppedFrames2.AllSequences", percent); + } + v2_ = {}; + } absl::optional<int> impl_throughput_percent_dropped; absl::optional<int> impl_throughput_percent_missed; @@ -242,44 +272,42 @@ void FrameSequenceMetrics::ReportMetrics() { if (compositor_report) { impl_throughput_percent_dropped = ThroughputData::ReportDroppedFramePercentHistogram( - this, ThreadType::kCompositor, - GetIndexForMetric(FrameSequenceMetrics::ThreadType::kCompositor, - type_), + this, SmoothEffectDrivingThread::kCompositor, + GetIndexForMetric(SmoothEffectDrivingThread::kCompositor, type_), impl_throughput_); impl_throughput_percent_missed = ThroughputData::ReportMissedDeadlineFramePercentHistogram( - this, ThreadType::kCompositor, - GetIndexForMetric(FrameSequenceMetrics::ThreadType::kCompositor, - type_), + this, SmoothEffectDrivingThread::kCompositor, + GetIndexForMetric(SmoothEffectDrivingThread::kCompositor, type_), impl_throughput_); } if (main_report) { main_throughput_percent_dropped = ThroughputData::ReportDroppedFramePercentHistogram( - this, ThreadType::kMain, - GetIndexForMetric(FrameSequenceMetrics::ThreadType::kMain, type_), + this, SmoothEffectDrivingThread::kMain, + GetIndexForMetric(SmoothEffectDrivingThread::kMain, type_), main_throughput_); main_throughput_percent_missed = ThroughputData::ReportMissedDeadlineFramePercentHistogram( - this, ThreadType::kMain, - GetIndexForMetric(FrameSequenceMetrics::ThreadType::kMain, type_), + this, SmoothEffectDrivingThread::kMain, + GetIndexForMetric(SmoothEffectDrivingThread::kMain, type_), main_throughput_); } // Report for the 'scrolling thread' for the scrolling interactions. - if (scrolling_thread_ != ThreadType::kUnknown) { + if (scrolling_thread_ != SmoothEffectDrivingThread::kUnknown) { absl::optional<int> scrolling_thread_throughput_dropped; absl::optional<int> scrolling_thread_throughput_missed; switch (scrolling_thread_) { - case ThreadType::kCompositor: + case SmoothEffectDrivingThread::kCompositor: scrolling_thread_throughput_dropped = impl_throughput_percent_dropped; scrolling_thread_throughput_missed = impl_throughput_percent_missed; break; - case ThreadType::kMain: + case SmoothEffectDrivingThread::kMain: scrolling_thread_throughput_dropped = main_throughput_percent_dropped; scrolling_thread_throughput_missed = main_throughput_percent_missed; break; - case ThreadType::kUnknown: + case SmoothEffectDrivingThread::kUnknown: NOTREACHED(); break; } @@ -337,12 +365,12 @@ void FrameSequenceMetrics::ReportMetrics() { // Report the jank metrics if (jank_reporter_) { if (jank_reporter_->thread_type() == - FrameSequenceMetrics::ThreadType::kCompositor && + SmoothEffectDrivingThread::kCompositor && impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) { DCHECK_EQ(jank_reporter_->thread_type(), this->GetEffectiveThread()); jank_reporter_->ReportJankMetrics(impl_throughput_.frames_expected); } else if (jank_reporter_->thread_type() == - FrameSequenceMetrics::ThreadType::kMain && + SmoothEffectDrivingThread::kMain && main_throughput_.frames_expected >= kMinFramesForThroughputMetric) { DCHECK_EQ(jank_reporter_->thread_type(), this->GetEffectiveThread()); @@ -357,11 +385,10 @@ void FrameSequenceMetrics::ReportMetrics() { main_throughput_ = {}; } -void FrameSequenceMetrics::ComputeJank( - FrameSequenceMetrics::ThreadType thread_type, - uint32_t frame_token, - base::TimeTicks presentation_time, - base::TimeDelta frame_interval) { +void FrameSequenceMetrics::ComputeJank(SmoothEffectDrivingThread thread_type, + uint32_t frame_token, + base::TimeTicks presentation_time, + base::TimeDelta frame_interval) { if (!jank_reporter_) return; @@ -371,7 +398,7 @@ void FrameSequenceMetrics::ComputeJank( } void FrameSequenceMetrics::NotifySubmitForJankReporter( - FrameSequenceMetrics::ThreadType thread_type, + SmoothEffectDrivingThread thread_type, uint32_t frame_token, uint32_t sequence_number) { if (!jank_reporter_) @@ -382,7 +409,7 @@ void FrameSequenceMetrics::NotifySubmitForJankReporter( } void FrameSequenceMetrics::NotifyNoUpdateForJankReporter( - FrameSequenceMetrics::ThreadType thread_type, + SmoothEffectDrivingThread thread_type, uint32_t sequence_number, base::TimeDelta frame_interval) { if (!jank_reporter_) @@ -394,20 +421,20 @@ void FrameSequenceMetrics::NotifyNoUpdateForJankReporter( bool FrameSequenceMetrics::ThroughputData::CanReportHistogram( FrameSequenceMetrics* metrics, - ThreadType thread_type, + SmoothEffectDrivingThread thread_type, const ThroughputData& data) { const auto sequence_type = metrics->type(); DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType); // All video frames are compositor thread only. if (sequence_type == FrameSequenceTrackerType::kVideo && - thread_type == ThreadType::kMain) + thread_type == SmoothEffectDrivingThread::kMain) return false; // RAF and CanvasAnimation are main thread only. if ((sequence_type == FrameSequenceTrackerType::kRAF || sequence_type == FrameSequenceTrackerType::kCanvasAnimation) && - thread_type == ThreadType::kCompositor) + thread_type == SmoothEffectDrivingThread::kCompositor) return false; if (data.frames_expected < kMinFramesForThroughputMetric) @@ -424,7 +451,7 @@ bool FrameSequenceMetrics::ThroughputData::CanReportHistogram( int FrameSequenceMetrics::ThroughputData::ReportDroppedFramePercentHistogram( FrameSequenceMetrics* metrics, - ThreadType thread_type, + SmoothEffectDrivingThread thread_type, int metric_index, const ThroughputData& data) { const auto sequence_type = metrics->type(); @@ -483,9 +510,9 @@ int FrameSequenceMetrics::ThroughputData::ReportDroppedFramePercentHistogram( } } - const char* thread_name = thread_type == ThreadType::kCompositor - ? "CompositorThread" - : "MainThread"; + const char* thread_name = + thread_type == SmoothEffectDrivingThread::kCompositor ? "CompositorThread" + : "MainThread"; STATIC_HISTOGRAM_POINTER_GROUP( GetThroughputHistogramName(sequence_type, thread_name), metric_index, kMaximumHistogramIndex, Add(percent), @@ -496,10 +523,11 @@ int FrameSequenceMetrics::ThroughputData::ReportDroppedFramePercentHistogram( } int FrameSequenceMetrics::ThroughputData:: - ReportMissedDeadlineFramePercentHistogram(FrameSequenceMetrics* metrics, - ThreadType thread_type, - int metric_index, - const ThroughputData& data) { + ReportMissedDeadlineFramePercentHistogram( + FrameSequenceMetrics* metrics, + SmoothEffectDrivingThread thread_type, + int metric_index, + const ThroughputData& data) { const auto sequence_type = metrics->type(); DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType); @@ -544,9 +572,9 @@ int FrameSequenceMetrics::ThroughputData:: percent); } - const char* thread_name = thread_type == ThreadType::kCompositor - ? "CompositorThread" - : "MainThread"; + const char* thread_name = + thread_type == SmoothEffectDrivingThread::kCompositor ? "CompositorThread" + : "MainThread"; STATIC_HISTOGRAM_POINTER_GROUP( GetMissedDeadlineHistogramName(sequence_type, thread_name), metric_index, kMaximumHistogramIndex, Add(percent), @@ -560,9 +588,9 @@ std::unique_ptr<base::trace_event::TracedValue> FrameSequenceMetrics::ThroughputData::ToTracedValue( const ThroughputData& impl, const ThroughputData& main, - ThreadType effective_thread) { + SmoothEffectDrivingThread effective_thread) { auto dict = std::make_unique<base::trace_event::TracedValue>(); - if (effective_thread == ThreadType::kMain) { + if (effective_thread == SmoothEffectDrivingThread::kMain) { dict->SetInteger("main-frames-produced", main.frames_produced); dict->SetInteger("main-frames-expected", main.frames_expected); dict->SetInteger("main-frames-ontime", main.frames_ontime); @@ -616,4 +644,25 @@ void FrameSequenceMetrics::TraceData::Advance(base::TimeTicks new_timestamp) { this->last_timestamp = new_timestamp; } +void FrameSequenceMetrics::AddSortedFrame(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info) { + switch (GetEffectiveThread()) { + case SmoothEffectDrivingThread::kCompositor: + if (frame_info.WasCompositorUpdateDropped()) { + ++v2_.frames_dropped; + } + ++v2_.frames_expected; + break; + case SmoothEffectDrivingThread::kMain: + if (frame_info.WasMainUpdateDropped()) { + ++v2_.frames_dropped; + } + ++v2_.frames_expected; + break; + case SmoothEffectDrivingThread::kUnknown: + NOTREACHED(); + break; + } +} + } // namespace cc diff --git a/chromium/cc/metrics/frame_sequence_metrics.h b/chromium/cc/metrics/frame_sequence_metrics.h index c051a27f5f8..0b979d52dc8 100644 --- a/chromium/cc/metrics/frame_sequence_metrics.h +++ b/chromium/cc/metrics/frame_sequence_metrics.h @@ -9,12 +9,19 @@ #include <memory> #include "base/callback.h" +#include "base/memory/raw_ptr.h" #include "base/trace_event/traced_value.h" #include "cc/cc_export.h" +#include "cc/metrics/frame_info.h" + +namespace viz { +struct BeginFrameArgs; +} // namespace viz namespace cc { class ThroughputUkmReporter; class JankMetrics; +struct FrameInfo; enum class FrameSequenceTrackerType { // Used as an enum for metrics. DO NOT reorder or delete values. Rather, @@ -70,28 +77,28 @@ class CC_EXPORT FrameSequenceMetrics { FrameSequenceMetrics(const FrameSequenceMetrics&) = delete; FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete; - enum class ThreadType { kMain, kCompositor, kUnknown }; - struct ThroughputData { static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue( const ThroughputData& impl, const ThroughputData& main, - ThreadType effective_thred); + FrameInfo::SmoothEffectDrivingThread effective_thred); - static bool CanReportHistogram(FrameSequenceMetrics* metrics, - ThreadType thread_type, - const ThroughputData& data); + static bool CanReportHistogram( + FrameSequenceMetrics* metrics, + FrameInfo::SmoothEffectDrivingThread thread_type, + const ThroughputData& data); // Returns the dropped throughput in percent - static int ReportDroppedFramePercentHistogram(FrameSequenceMetrics* metrics, - ThreadType thread_type, - int metric_index, - const ThroughputData& data); + static int ReportDroppedFramePercentHistogram( + FrameSequenceMetrics* metrics, + FrameInfo::SmoothEffectDrivingThread thread_type, + int metric_index, + const ThroughputData& data); // Returns the missed deadline throughput in percent static int ReportMissedDeadlineFramePercentHistogram( FrameSequenceMetrics* metrics, - ThreadType thread_type, + FrameInfo::SmoothEffectDrivingThread thread_type, int metric_index, const ThroughputData& data); @@ -141,7 +148,7 @@ class CC_EXPORT FrameSequenceMetrics { #endif }; - void SetScrollingThread(ThreadType thread); + void SetScrollingThread(FrameInfo::SmoothEffectDrivingThread thread); struct CustomReportData { uint32_t frames_expected = 0; @@ -154,7 +161,7 @@ class CC_EXPORT FrameSequenceMetrics { // Returns the 'effective thread' for the metrics (i.e. the thread most // relevant for this metric). - ThreadType GetEffectiveThread() const; + FrameInfo::SmoothEffectDrivingThread GetEffectiveThread() const; void Merge(std::unique_ptr<FrameSequenceMetrics> metrics); bool HasEnoughDataForReporting() const; @@ -162,6 +169,9 @@ class CC_EXPORT FrameSequenceMetrics { // Report related metrics: throughput, checkboarding... void ReportMetrics(); + void AddSortedFrame(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info); + ThroughputData& impl_throughput() { return impl_throughput_; } ThroughputData& main_throughput() { return main_throughput_; } void add_checkerboarded_frames(int64_t frames) { @@ -180,17 +190,18 @@ class CC_EXPORT FrameSequenceMetrics { void AdoptTrace(FrameSequenceMetrics* adopt_from); void AdvanceTrace(base::TimeTicks timestamp); - void ComputeJank(FrameSequenceMetrics::ThreadType thread_type, + void ComputeJank(FrameInfo::SmoothEffectDrivingThread thread_type, uint32_t frame_token, base::TimeTicks presentation_time, base::TimeDelta frame_interval); - void NotifySubmitForJankReporter(FrameSequenceMetrics::ThreadType thread_type, - uint32_t frame_token, - uint32_t sequence_number); + void NotifySubmitForJankReporter( + FrameInfo::SmoothEffectDrivingThread thread_type, + uint32_t frame_token, + uint32_t sequence_number); void NotifyNoUpdateForJankReporter( - FrameSequenceMetrics::ThreadType thread_type, + FrameInfo::SmoothEffectDrivingThread thread_type, uint32_t sequence_number, base::TimeDelta frame_interval); @@ -201,23 +212,30 @@ class CC_EXPORT FrameSequenceMetrics { struct TraceData { explicit TraceData(FrameSequenceMetrics* metrics); ~TraceData(); - FrameSequenceMetrics* metrics; + raw_ptr<FrameSequenceMetrics> metrics; base::TimeTicks last_timestamp = base::TimeTicks::Now(); int frame_count = 0; bool enabled = false; - void* trace_id = nullptr; + raw_ptr<void> trace_id = nullptr; void Advance(base::TimeTicks new_timestamp); void Terminate(); } trace_data_{this}; // Pointer to the reporter owned by the FrameSequenceTrackerCollection. - ThroughputUkmReporter* const throughput_ukm_reporter_; + const raw_ptr<ThroughputUkmReporter> throughput_ukm_reporter_; + + // Track state for measuring the PercentDroppedFrames v2 metrics. + struct { + uint32_t frames_expected = 0; + uint32_t frames_dropped = 0; + } v2_; ThroughputData impl_throughput_; ThroughputData main_throughput_; - ThreadType scrolling_thread_ = ThreadType::kUnknown; + FrameInfo::SmoothEffectDrivingThread scrolling_thread_ = + FrameInfo::SmoothEffectDrivingThread::kUnknown; // Tracks the number of produced frames that had some amount of // checkerboarding, and how many frames showed such checkerboarded frames. @@ -230,12 +248,12 @@ class CC_EXPORT FrameSequenceMetrics { }; bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type, - FrameSequenceMetrics::ThreadType thread_type); + FrameInfo::SmoothEffectDrivingThread thread_type); bool ShouldReportForInteraction( FrameSequenceTrackerType sequence_type, - FrameSequenceMetrics::ThreadType reporting_thread_type, - FrameSequenceMetrics::ThreadType metrics_effective_thread_type); + FrameInfo::SmoothEffectDrivingThread reporting_thread_type, + FrameInfo::SmoothEffectDrivingThread metrics_effective_thread_type); } // namespace cc diff --git a/chromium/cc/metrics/frame_sequence_metrics_unittest.cc b/chromium/cc/metrics/frame_sequence_metrics_unittest.cc index f2bf7ee43ad..cbef003b39b 100644 --- a/chromium/cc/metrics/frame_sequence_metrics_unittest.cc +++ b/chromium/cc/metrics/frame_sequence_metrics_unittest.cc @@ -4,7 +4,6 @@ #include "cc/metrics/frame_sequence_tracker.h" -#include "base/macros.h" #include "base/test/metrics/histogram_tester.h" #include "cc/metrics/throughput_ukm_reporter.h" #include "cc/trees/ukm_manager.h" @@ -40,14 +39,14 @@ TEST(FrameSequenceMetricsTest, MergeMetrics) { #if DCHECK_IS_ON() TEST(FrameSequenceMetricsTest, ScrollingThreadMergeMetrics) { FrameSequenceMetrics first(FrameSequenceTrackerType::kTouchScroll, nullptr); - first.SetScrollingThread(FrameSequenceMetrics::ThreadType::kCompositor); + first.SetScrollingThread(FrameInfo::SmoothEffectDrivingThread::kCompositor); first.impl_throughput().frames_expected = 20; first.impl_throughput().frames_produced = 10; first.impl_throughput().frames_ontime = 10; auto second = std::make_unique<FrameSequenceMetrics>( FrameSequenceTrackerType::kTouchScroll, nullptr); - second->SetScrollingThread(FrameSequenceMetrics::ThreadType::kMain); + second->SetScrollingThread(FrameInfo::SmoothEffectDrivingThread::kMain); second->main_throughput().frames_expected = 50; second->main_throughput().frames_produced = 10; second->main_throughput().frames_ontime = 10; @@ -213,7 +212,7 @@ TEST(FrameSequenceMetricsTest, ScrollingThreadMetricsReportedForInteractions) { base::HistogramTester histograms; auto metrics = setup(); EXPECT_TRUE(metrics->HasEnoughDataForReporting()); - metrics->SetScrollingThread(FrameSequenceMetrics::ThreadType::kMain); + metrics->SetScrollingThread(FrameInfo::SmoothEffectDrivingThread::kMain); metrics->ReportMetrics(); histograms.ExpectTotalCount(metric, 1u); EXPECT_THAT(histograms.GetAllSamples(metric), @@ -225,7 +224,8 @@ TEST(FrameSequenceMetricsTest, ScrollingThreadMetricsReportedForInteractions) { base::HistogramTester histograms; auto metrics = setup(); EXPECT_TRUE(metrics->HasEnoughDataForReporting()); - metrics->SetScrollingThread(FrameSequenceMetrics::ThreadType::kCompositor); + metrics->SetScrollingThread( + FrameInfo::SmoothEffectDrivingThread::kCompositor); metrics->ReportMetrics(); histograms.ExpectTotalCount(metric, 1u); EXPECT_THAT(histograms.GetAllSamples(metric), diff --git a/chromium/cc/metrics/frame_sequence_tracker.cc b/chromium/cc/metrics/frame_sequence_tracker.cc index 65f52e8aae3..ca00bb02e07 100644 --- a/chromium/cc/metrics/frame_sequence_tracker.cc +++ b/chromium/cc/metrics/frame_sequence_tracker.cc @@ -35,7 +35,14 @@ namespace cc { -using ThreadType = FrameSequenceMetrics::ThreadType; +namespace { + +constexpr char kTraceCategory[] = + "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"); + +} // namespace + +using ThreadType = FrameInfo::SmoothEffectDrivingThread; // In the |TRACKER_TRACE_STREAM|, we mod the numbers such as frame sequence // number, or frame token, such that the debug string is not too long. @@ -83,7 +90,7 @@ FrameSequenceTracker::FrameSequenceTracker( // TODO(crbug.com/1158439): remove the trace event once the validation is // completed. TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1( - "cc,benchmark", "TrackerValidation", TRACE_ID_LOCAL(this), + kTraceCategory, "TrackerValidation", TRACE_ID_LOCAL(this), base::TimeTicks::Now(), "name", GetFrameSequenceTrackerTypeName(type)); } @@ -99,9 +106,10 @@ FrameSequenceTracker::FrameSequenceTracker( } FrameSequenceTracker::~FrameSequenceTracker() { - TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "cc,benchmark", "TrackerValidation", TRACE_ID_LOCAL(this), - base::TimeTicks::Now()); + TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP2( + kTraceCategory, "TrackerValidation", TRACE_ID_LOCAL(this), + base::TimeTicks::Now(), "aborted_main", aborted_main_frame_, + "no_damage_main", no_damage_draw_main_frames_); CleanUp(); } @@ -186,9 +194,8 @@ void FrameSequenceTracker::ReportBeginMainFrame( } #endif - DCHECK_EQ(awaiting_main_response_sequence_, 0u) << TRACKER_DCHECK_MSG; last_processed_main_sequence_latency_ = 0; - awaiting_main_response_sequence_ = args.frame_id.sequence_number; + pending_main_sequences_.push_back(args.frame_id.sequence_number); UpdateTrackedFrameData(&begin_main_frame_data_, args.frame_id.source_id, args.frame_id.sequence_number, @@ -232,16 +239,11 @@ void FrameSequenceTracker::ReportMainFrameProcessed( if (first_received_main_sequence_ && args.frame_id.sequence_number >= first_received_main_sequence_) { - if (awaiting_main_response_sequence_) { - DCHECK_EQ(awaiting_main_response_sequence_, args.frame_id.sequence_number) - << TRACKER_DCHECK_MSG; - } DCHECK_EQ(last_processed_main_sequence_latency_, 0u) << TRACKER_DCHECK_MSG; last_processed_main_sequence_ = args.frame_id.sequence_number; last_processed_main_sequence_latency_ = std::max(last_started_impl_sequence_, last_processed_impl_sequence_) - args.frame_id.sequence_number; - awaiting_main_response_sequence_ = 0; } } @@ -289,7 +291,7 @@ void FrameSequenceTracker::ReportSubmitFrame( TRACKER_TRACE_STREAM << "s(" << frame_token % kDebugStrMod << ")"; had_impl_frame_submitted_between_commits_ = true; metrics()->NotifySubmitForJankReporter( - FrameSequenceMetrics::ThreadType::kCompositor, frame_token, + FrameInfo::SmoothEffectDrivingThread::kCompositor, frame_token, ack.frame_id.sequence_number); const bool main_changes_after_sequence_started = @@ -314,7 +316,7 @@ void FrameSequenceTracker::ReportSubmitFrame( kDebugStrMod << ")"; metrics()->NotifySubmitForJankReporter( - FrameSequenceMetrics::ThreadType::kMain, frame_token, + FrameInfo::SmoothEffectDrivingThread::kMain, frame_token, origin_args.frame_id.sequence_number); last_submitted_main_sequence_ = origin_args.frame_id.sequence_number; @@ -337,6 +339,16 @@ void FrameSequenceTracker::ReportFrameEnd( if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id)) return; + // We only update the `pending_main_sequences` when the frame has successfully + // submitted, or when we determine that it has no damage. See + // ReportMainFrameCausedNoDamage. We do not do this in + // NotifyMainFrameProcessed, as that can occur during Commit, and we may yet + // determine at Draw that there was no damage. + while (!pending_main_sequences_.empty() && + pending_main_sequences_.front() <= + main_args.frame_id.sequence_number) { + pending_main_sequences_.pop_front(); + } TRACKER_TRACE_STREAM << "e(" << args.frame_id.sequence_number % kDebugStrMod << "," << main_args.frame_id.sequence_number % kDebugStrMod @@ -377,7 +389,7 @@ void FrameSequenceTracker::ReportFrameEnd( << TRACKER_DCHECK_MSG; --impl_throughput().frames_expected; metrics()->NotifyNoUpdateForJankReporter( - FrameSequenceMetrics::ThreadType::kCompositor, + FrameInfo::SmoothEffectDrivingThread::kCompositor, args.frame_id.sequence_number, args.interval); #if DCHECK_IS_ON() ++impl_throughput().frames_processed; @@ -473,7 +485,7 @@ void FrameSequenceTracker::ReportFramePresented( metrics()->AdvanceTrace(feedback.timestamp); } - metrics()->ComputeJank(FrameSequenceMetrics::ThreadType::kCompositor, + metrics()->ComputeJank(FrameInfo::SmoothEffectDrivingThread::kCompositor, frame_token, feedback.timestamp, vsync_interval); } @@ -494,7 +506,7 @@ void FrameSequenceTracker::ReportFramePresented( metrics()->AdvanceTrace(feedback.timestamp); } - metrics()->ComputeJank(FrameSequenceMetrics::ThreadType::kMain, + metrics()->ComputeJank(FrameInfo::SmoothEffectDrivingThread::kMain, frame_token, feedback.timestamp, vsync_interval); } if (main_frames_.size() < size_before_erase) { @@ -568,7 +580,8 @@ void FrameSequenceTracker::ReportImplFrameCausedNoDamage( } void FrameSequenceTracker::ReportMainFrameCausedNoDamage( - const viz::BeginFrameArgs& args) { + const viz::BeginFrameArgs& args, + bool aborted) { if (termination_status_ != TerminationStatus::kActive) return; @@ -589,17 +602,28 @@ void FrameSequenceTracker::ReportMainFrameCausedNoDamage( if (last_no_main_damage_sequence_ == args.frame_id.sequence_number) return; - // It is possible for |awaiting_main_response_sequence_| to be zero here if a - // commit had already happened before (e.g. B(x)E(x)N(x)). So check that case - // here. - if (awaiting_main_response_sequence_) { - DCHECK_EQ(awaiting_main_response_sequence_, args.frame_id.sequence_number) - << TRACKER_DCHECK_MSG; - } else { - DCHECK_EQ(last_processed_main_sequence_, args.frame_id.sequence_number) - << TRACKER_DCHECK_MSG; + auto initial_pending_size = pending_main_sequences_.size(); + while (!pending_main_sequences_.empty() && + pending_main_sequences_.front() <= args.frame_id.sequence_number) { + pending_main_sequences_.pop_front(); } - awaiting_main_response_sequence_ = 0; + // If we didn't remove any `pending_main_sequences`, then we have previously + // submitted a CompositorFrame with damage for `args.frame_id.sequence_number` + // and the sequence is being re-used on a subsequent Impl frame. Which just + // happens to have no damage. + // + // This can occur when there is a Compositor Animation that is offscreen, and + // when we are awaiting the next BeginMainFrame to be Committed and Activated. + // + // We do not change the `main_throughput` expectations when the sequence is + // re-used. + if (pending_main_sequences_.size() == initial_pending_size) + return; + + if (aborted) + ++aborted_main_frame_; + else + ++no_damage_draw_main_frames_; DCHECK_GT(main_throughput().frames_expected, 0u) << TRACKER_DCHECK_MSG; DCHECK_GT(main_throughput().frames_expected, @@ -610,15 +634,15 @@ void FrameSequenceTracker::ReportMainFrameCausedNoDamage( last_no_main_damage_sequence_ = args.frame_id.sequence_number; --main_throughput().frames_expected; metrics()->NotifyNoUpdateForJankReporter( - FrameSequenceMetrics::ThreadType::kMain, args.frame_id.sequence_number, - args.interval); + FrameInfo::SmoothEffectDrivingThread::kMain, + args.frame_id.sequence_number, args.interval); DCHECK_GE(main_throughput().frames_expected, main_frames_.size()) << TRACKER_DCHECK_MSG; // Could be 0 if there were a pause frame production. if (begin_main_frame_data_.previous_sequence != 0) { - DCHECK_EQ(begin_main_frame_data_.previous_sequence, + DCHECK_GE(begin_main_frame_data_.previous_sequence, args.frame_id.sequence_number) << TRACKER_DCHECK_MSG; } @@ -694,6 +718,12 @@ void FrameSequenceTracker::CleanUp() { metrics_->ReportLeftoverData(); } +void FrameSequenceTracker::AddSortedFrame(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info) { + if (metrics_) + metrics_->AddSortedFrame(args, frame_info); +} + FrameSequenceTracker::CheckerboardingData::CheckerboardingData() = default; FrameSequenceTracker::CheckerboardingData::~CheckerboardingData() = default; diff --git a/chromium/cc/metrics/frame_sequence_tracker.h b/chromium/cc/metrics/frame_sequence_tracker.h index fd6201207c1..e395c1788bc 100644 --- a/chromium/cc/metrics/frame_sequence_tracker.h +++ b/chromium/cc/metrics/frame_sequence_tracker.h @@ -5,6 +5,7 @@ #ifndef CC_METRICS_FRAME_SEQUENCE_TRACKER_H_ #define CC_METRICS_FRAME_SEQUENCE_TRACKER_H_ +#include <deque> #include <memory> #include <sstream> @@ -85,7 +86,8 @@ class CC_EXPORT FrameSequenceTracker { // Notifies the tracker that a |BeginFrameArgs| either was not dispatched to // the main-thread (because it did not ask for it), or that a |BeginFrameArgs| // that was dispatched to the main-thread did not cause any updates/damage. - void ReportMainFrameCausedNoDamage(const viz::BeginFrameArgs& args); + void ReportMainFrameCausedNoDamage(const viz::BeginFrameArgs& args, + bool aborted); // Notifies that frame production has currently paused. This is typically used // for interactive frame-sequences, e.g. during touch-scroll. @@ -106,6 +108,9 @@ class CC_EXPORT FrameSequenceTracker { // |metrics_| to report. void CleanUp(); + void AddSortedFrame(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info); + private: friend class FrameSequenceTrackerCollection; friend class FrameSequenceTrackerTest; @@ -193,8 +198,14 @@ class CC_EXPORT FrameSequenceTracker { // This is used to decide when to terminate this FrameSequenceTracker object. uint32_t last_submitted_frame_ = 0; - // Keeps track of the begin-main-frame that needs to be processed next. - uint64_t awaiting_main_response_sequence_ = 0; + // Keeps track of the begin-main-frames that need to be processed. There can + // be multiple in-flight, as BeginMainFrame to ReadyToCommit can be longer + // than one `viz::BeginFrameArgs.interval`. When this occurs the Compositor + // can send the `n+1` sequence_number, only for the Commit for `n` to arrive + // and lead to frame production. + std::deque<uint64_t> pending_main_sequences_; + uint64_t aborted_main_frame_ = 0; + uint64_t no_damage_draw_main_frames_ = 0; // Keeps track of the last sequence-number that produced a frame from the // main-thread. diff --git a/chromium/cc/metrics/frame_sequence_tracker_collection.cc b/chromium/cc/metrics/frame_sequence_tracker_collection.cc index b6394a6360d..b675de14e4f 100644 --- a/chromium/cc/metrics/frame_sequence_tracker_collection.cc +++ b/chromium/cc/metrics/frame_sequence_tracker_collection.cc @@ -18,7 +18,7 @@ namespace cc { namespace { -using ThreadType = FrameSequenceMetrics::ThreadType; +using ThreadType = FrameInfo::SmoothEffectDrivingThread; bool IsScrollType(FrameSequenceTrackerType type) { return type == FrameSequenceTrackerType::kTouchScroll || @@ -45,7 +45,7 @@ FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() { FrameSequenceTracker* FrameSequenceTrackerCollection::StartSequenceInternal( FrameSequenceTrackerType type, - FrameSequenceMetrics::ThreadType scrolling_thread) { + FrameInfo::SmoothEffectDrivingThread scrolling_thread) { DCHECK_NE(FrameSequenceTrackerType::kCustom, type); if (is_single_threaded_) return nullptr; @@ -98,7 +98,7 @@ FrameSequenceTracker* FrameSequenceTrackerCollection::StartSequence( FrameSequenceTracker* FrameSequenceTrackerCollection::StartScrollSequence( FrameSequenceTrackerType type, - FrameSequenceMetrics::ThreadType scrolling_thread) { + FrameInfo::SmoothEffectDrivingThread scrolling_thread) { DCHECK(IsScrollType(type)); return StartSequenceInternal(type, scrolling_thread); } @@ -232,11 +232,12 @@ void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage( } void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage( - const viz::BeginFrameArgs& args) { + const viz::BeginFrameArgs& args, + bool aborted) { for (auto& tracker : frame_trackers_) - tracker.second->ReportMainFrameCausedNoDamage(args); + tracker.second->ReportMainFrameCausedNoDamage(args, aborted); for (auto& tracker : custom_frame_trackers_) - tracker.second->ReportMainFrameCausedNoDamage(args); + tracker.second->ReportMainFrameCausedNoDamage(args, aborted); } void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() { @@ -359,7 +360,7 @@ void FrameSequenceTrackerCollection::RecreateTrackers( // The frame sequence is still active, so create a new tracker to keep // tracking this sequence. - if (thread_type != FrameSequenceMetrics::ThreadType::kUnknown) { + if (thread_type != FrameInfo::SmoothEffectDrivingThread::kUnknown) { DCHECK(IsScrollType(tracker_type)); StartScrollSequence(tracker_type, thread_type); } else { @@ -406,4 +407,13 @@ void FrameSequenceTrackerCollection::AddCustomTrackerResult( custom_tracker_results_added_callback_.Run(results); } +void FrameSequenceTrackerCollection::AddSortedFrame( + const viz::BeginFrameArgs& args, + const FrameInfo& frame_info) { + for (auto& tracker : frame_trackers_) + tracker.second->AddSortedFrame(args, frame_info); + for (auto& tracker : custom_frame_trackers_) + tracker.second->AddSortedFrame(args, frame_info); +} + } // namespace cc diff --git a/chromium/cc/metrics/frame_sequence_tracker_collection.h b/chromium/cc/metrics/frame_sequence_tracker_collection.h index e3dc01d9af8..f8b023efd3b 100644 --- a/chromium/cc/metrics/frame_sequence_tracker_collection.h +++ b/chromium/cc/metrics/frame_sequence_tracker_collection.h @@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/metrics/frame_sequence_metrics.h" @@ -54,7 +55,7 @@ class CC_EXPORT FrameSequenceTrackerCollection { FrameSequenceTracker* StartSequence(FrameSequenceTrackerType type); FrameSequenceTracker* StartScrollSequence( FrameSequenceTrackerType type, - FrameSequenceMetrics::ThreadType scrolling_thread); + FrameInfo::SmoothEffectDrivingThread scrolling_thread); // Schedules |tracker| for destruction. This is preferred instead of outright // desrtruction of the tracker, since this ensures that the actual tracker @@ -84,7 +85,8 @@ class CC_EXPORT FrameSequenceTrackerCollection { void NotifyBeginMainFrame(const viz::BeginFrameArgs& args); void NotifyMainFrameProcessed(const viz::BeginFrameArgs& args); void NotifyImplFrameCausedNoDamage(const viz::BeginFrameAck& ack); - void NotifyMainFrameCausedNoDamage(const viz::BeginFrameArgs& args); + void NotifyMainFrameCausedNoDamage(const viz::BeginFrameArgs& args, + bool aborted); void NotifyPauseFrameProduction(); void NotifySubmitFrame(uint32_t frame_token, bool has_missing_content, @@ -118,12 +120,15 @@ class CC_EXPORT FrameSequenceTrackerCollection { custom_tracker_results_added_callback_ = std::move(callback); } + void AddSortedFrame(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info); + private: friend class FrameSequenceTrackerTest; FrameSequenceTracker* StartSequenceInternal( FrameSequenceTrackerType type, - FrameSequenceMetrics::ThreadType scrolling_thread); + FrameInfo::SmoothEffectDrivingThread scrolling_thread); void RecreateTrackers(const viz::BeginFrameArgs& args); // Destroy the trackers that are ready to be terminated. @@ -151,7 +156,7 @@ class CC_EXPORT FrameSequenceTrackerCollection { // The callsite can use the type to manipulate the tracker. base::flat_map< - std::pair<FrameSequenceTrackerType, FrameSequenceMetrics::ThreadType>, + std::pair<FrameSequenceTrackerType, FrameInfo::SmoothEffectDrivingThread>, std::unique_ptr<FrameSequenceTracker>> frame_trackers_; @@ -164,11 +169,11 @@ class CC_EXPORT FrameSequenceTrackerCollection { NotifyCustomerTrackerResutlsCallback custom_tracker_results_added_callback_; std::vector<std::unique_ptr<FrameSequenceTracker>> removal_trackers_; - CompositorFrameReportingController* const + const raw_ptr<CompositorFrameReportingController> compositor_frame_reporting_controller_; base::flat_map< - std::pair<FrameSequenceTrackerType, FrameSequenceMetrics::ThreadType>, + std::pair<FrameSequenceTrackerType, FrameInfo::SmoothEffectDrivingThread>, std::unique_ptr<FrameSequenceMetrics>> accumulated_metrics_; diff --git a/chromium/cc/metrics/frame_sequence_tracker_unittest.cc b/chromium/cc/metrics/frame_sequence_tracker_unittest.cc index 4def808398d..cb3c6d72cfd 100644 --- a/chromium/cc/metrics/frame_sequence_tracker_unittest.cc +++ b/chromium/cc/metrics/frame_sequence_tracker_unittest.cc @@ -8,7 +8,7 @@ #include <utility> #include <vector> -#include "base/macros.h" +#include "base/memory/raw_ptr.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "cc/metrics/compositor_frame_reporting_controller.h" @@ -51,12 +51,12 @@ class FrameSequenceTrackerTest : public testing::Test { compositor_frame_reporting_controller_.get()) { tracker_ = collection_.StartScrollSequence( FrameSequenceTrackerType::kTouchScroll, - FrameSequenceMetrics::ThreadType::kCompositor); + FrameInfo::SmoothEffectDrivingThread::kCompositor); } ~FrameSequenceTrackerTest() override = default; - void CreateNewTracker(FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor) { + void CreateNewTracker(FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor) { tracker_ = collection_.StartScrollSequence( FrameSequenceTrackerType::kTouchScroll, thread_type); } @@ -84,7 +84,7 @@ class FrameSequenceTrackerTest : public testing::Test { if (damage_type & kImplDamage) { if (!(damage_type & kMainDamage)) { - collection_.NotifyMainFrameCausedNoDamage(args); + collection_.NotifyMainFrameCausedNoDamage(args, false); } else { collection_.NotifyMainFrameProcessed(args); } @@ -96,7 +96,7 @@ class FrameSequenceTrackerTest : public testing::Test { } else { collection_.NotifyImplFrameCausedNoDamage( viz::BeginFrameAck(args, false)); - collection_.NotifyMainFrameCausedNoDamage(args); + collection_.NotifyMainFrameCausedNoDamage(args, true); collection_.NotifyFrameEnd(args, args); } return 0; @@ -109,13 +109,15 @@ class FrameSequenceTrackerTest : public testing::Test { // Check whether a type of tracker exists in |frame_trackers_| or not. bool TrackerExists(FrameSequenceTrackerType type) const { - auto key = std::make_pair(type, FrameSequenceMetrics::ThreadType::kUnknown); + auto key = + std::make_pair(type, FrameInfo::SmoothEffectDrivingThread::kUnknown); if (type == FrameSequenceTrackerType::kTouchScroll || type == FrameSequenceTrackerType::kWheelScroll || type == FrameSequenceTrackerType::kScrollbarScroll) { - key = std::make_pair(type, FrameSequenceMetrics::ThreadType::kCompositor); + key = std::make_pair(type, + FrameInfo::SmoothEffectDrivingThread::kCompositor); if (!collection_.frame_trackers_.contains(key)) - key = std::make_pair(type, FrameSequenceMetrics::ThreadType::kMain); + key = std::make_pair(type, FrameInfo::SmoothEffectDrivingThread::kMain); } return collection_.frame_trackers_.contains(key); } @@ -234,7 +236,7 @@ class FrameSequenceTrackerTest : public testing::Test { case 'N': collection_.NotifyMainFrameCausedNoDamage( - CreateBeginFrameArgs(source_id, sequence)); + CreateBeginFrameArgs(source_id, sequence), true); break; default: @@ -305,7 +307,7 @@ class FrameSequenceTrackerTest : public testing::Test { std::unique_ptr<CompositorFrameReportingController> compositor_frame_reporting_controller_; FrameSequenceTrackerCollection collection_; - FrameSequenceTracker* tracker_; + raw_ptr<FrameSequenceTracker> tracker_; }; // Tests that the tracker works correctly when the source-id for the @@ -331,7 +333,7 @@ TEST_F(FrameSequenceTrackerTest, SourceIdChangeDuringSequence) { auto args_2 = CreateBeginFrameArgs(source_2, ++sequence_2); collection_.NotifyBeginImplFrame(args_2); collection_.NotifyBeginMainFrame(args_2); - collection_.NotifyMainFrameCausedNoDamage(args_2); + collection_.NotifyMainFrameCausedNoDamage(args_2, true); // Since the main-frame did not have any new damage from the latest // BeginFrameArgs, the submit-frame will carry the previous BeginFrameArgs // (from source_1); @@ -725,7 +727,7 @@ TEST_F(FrameSequenceTrackerTest, ScrollingThreadMetricCompositorThread) { } TEST_F(FrameSequenceTrackerTest, ScrollingThreadMetricMainThread) { - CreateNewTracker(FrameSequenceMetrics::ThreadType::kMain); + CreateNewTracker(FrameInfo::SmoothEffectDrivingThread::kMain); // Start with a bunch of frames so that the metric does get reported at the // end of the test. @@ -807,6 +809,18 @@ TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamageFromOlderFrame) { EXPECT_EQ(MainThroughput().frames_produced, 0u); } +// This tests when a BeginMainFrame leads to No Damage, after the next Main +// Frame has started. This should not crash. +TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamageAfterNextMainFrame) { + const char sequence[] = + "b(1)B(0,1)n(1)e(1,0)E(1)b(2)B(0,2)N(0,1)n(2)N(0,2)e(2,0)"; + GenerateSequence(sequence); + EXPECT_EQ(ImplThroughput().frames_expected, 0u); + EXPECT_EQ(MainThroughput().frames_expected, 0u); + EXPECT_EQ(ImplThroughput().frames_produced, 0u); + EXPECT_EQ(MainThroughput().frames_produced, 0u); +} + TEST_F(FrameSequenceTrackerTest, StateResetDuringSequence) { const char sequence[] = "b(1)B(0,1)n(1)N(1,1)Re(1,0)b(2)n(2)e(2,0)"; GenerateSequence(sequence); @@ -1717,7 +1731,7 @@ TEST_F(FrameSequenceTrackerTest, MergeTrackersScrollOnSameThread) { GenerateSequence(first_sequence); collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll); - CreateNewTracker(FrameSequenceMetrics::ThreadType::kCompositor); + CreateNewTracker(FrameInfo::SmoothEffectDrivingThread::kCompositor); const char second_sequence[] = "b(81)s(3)e(81,0)P(3)b(101)s(4)e(101,0)P(4)"; GenerateSequence(second_sequence); collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll); @@ -1738,7 +1752,7 @@ TEST_F(FrameSequenceTrackerTest, MergeTrackersScrollOnDifferentThreads) { GenerateSequence(compscroll_sequence); collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll); - CreateNewTracker(FrameSequenceMetrics::ThreadType::kMain); + CreateNewTracker(FrameInfo::SmoothEffectDrivingThread::kMain); const char mainscroll_sequence[] = "b(81)s(3)e(81,0)P(3)b(101)s(4)e(101,0)P(4)"; GenerateSequence(mainscroll_sequence); diff --git a/chromium/cc/metrics/frame_sorter.cc b/chromium/cc/metrics/frame_sorter.cc index 91c98d1ea31..a74d723d918 100644 --- a/chromium/cc/metrics/frame_sorter.cc +++ b/chromium/cc/metrics/frame_sorter.cc @@ -6,6 +6,8 @@ #include <utility> +#include "cc/metrics/frame_info.h" + namespace cc { using FrameState = FrameSorter::FrameState; @@ -62,12 +64,13 @@ void FrameSorter::AddNewFrame(const viz::BeginFrameArgs& args) { while (pending_frames_.size() > kPendingFramesMaxSize) { const auto& first = pending_frames_.front(); frame_states_.erase(first.frame_id); + frame_infos_.erase(first.frame_id); pending_frames_.pop_front(); } } void FrameSorter::AddFrameResult(const viz::BeginFrameArgs& args, - bool is_dropped) { + const FrameInfo& frame_info) { if (pending_frames_.empty() || current_source_id_ > args.frame_id.source_id) { // The change in source_id can be as a result of crash on gpu process, // and as a result the corresponding frame to result does not exist. @@ -79,6 +82,15 @@ void FrameSorter::AddFrameResult(const viz::BeginFrameArgs& args, // - When the frame was in pending_frames_ and was removed because of reset. if (!frame_states_.count(args.frame_id)) return; + + const auto f = frame_infos_.find(args.frame_id); + if (f != frame_infos_.end()) { + f->second.MergeWith(frame_info); + } else { + frame_infos_[args.frame_id] = frame_info; + } + + const bool is_dropped = frame_info.IsDroppedAffectingSmoothness(); auto& frame_state = frame_states_[args.frame_id]; frame_state.OnAck(is_dropped); if (!frame_state.IsComplete()) { @@ -87,6 +99,7 @@ void FrameSorter::AddFrameResult(const viz::BeginFrameArgs& args, if (frame_state.should_ignore()) { // The associated frame in pending_frames_ was already removed in Reset(). frame_states_.erase(args.frame_id); + frame_infos_.erase(args.frame_id); return; } @@ -107,7 +120,7 @@ void FrameSorter::AddFrameResult(const viz::BeginFrameArgs& args, } } -bool FrameSorter::IsFrameDropped(const viz::BeginFrameId& id) const { +bool FrameSorter::IsAlreadyReportedDropped(const viz::BeginFrameId& id) const { auto it = frame_states_.find(id); if (it == frame_states_.end()) return false; @@ -116,10 +129,12 @@ bool FrameSorter::IsFrameDropped(const viz::BeginFrameId& id) const { void FrameSorter::Reset() { for (auto pending_frame : pending_frames_) { - auto& frame_state = frame_states_[pending_frame.frame_id]; + const auto& frame_id = pending_frame.frame_id; + auto& frame_state = frame_states_[frame_id]; if (frame_state.IsComplete() && !frame_state.should_ignore()) { - flush_callback_.Run(pending_frame, frame_state.is_dropped()); - frame_states_.erase(pending_frame.frame_id); + flush_callback_.Run(pending_frame, frame_infos_[frame_id]); + frame_states_.erase(frame_id); + frame_infos_.erase(frame_id); continue; } frame_state.OnReset(); @@ -132,12 +147,14 @@ void FrameSorter::FlushFrames() { size_t flushed_count = 0; while (!pending_frames_.empty()) { const auto& first = pending_frames_.front(); - auto& frame_state = frame_states_[first.frame_id]; + const auto& frame_id = first.frame_id; + auto& frame_state = frame_states_[frame_id]; if (!frame_state.IsComplete()) break; ++flushed_count; - flush_callback_.Run(first, frame_state.is_dropped()); - frame_states_.erase(first.frame_id); + flush_callback_.Run(first, frame_infos_[frame_id]); + frame_states_.erase(frame_id); + frame_infos_.erase(frame_id); pending_frames_.pop_front(); } DCHECK_GT(flushed_count, 0u); diff --git a/chromium/cc/metrics/frame_sorter.h b/chromium/cc/metrics/frame_sorter.h index 9e612765777..f06221fc126 100644 --- a/chromium/cc/metrics/frame_sorter.h +++ b/chromium/cc/metrics/frame_sorter.h @@ -17,6 +17,8 @@ namespace cc { +struct FrameInfo; + // This class is used to process the frames in order of initiation. // So regardless of which order frames are terminated, the callback function // will frames sorter will br called on the frames in the order of initiation @@ -41,7 +43,7 @@ class CC_EXPORT FrameSorter { using InOrderBeginFramesCallback = base::RepeatingCallback<void(const viz::BeginFrameArgs&, - bool /*is_dropped*/)>; + const FrameInfo&)>; explicit FrameSorter(InOrderBeginFramesCallback callback); ~FrameSorter(); @@ -53,10 +55,11 @@ class CC_EXPORT FrameSorter { // The results can be added in any order. However, the frame must have been // added by an earlier call to |AddNewFrame()|. - void AddFrameResult(const viz::BeginFrameArgs& args, bool is_dropped); + void AddFrameResult(const viz::BeginFrameArgs& args, + const FrameInfo& frame_info); // Check if a frame has been previously reported as dropped. - bool IsFrameDropped(const viz::BeginFrameId& id) const; + bool IsAlreadyReportedDropped(const viz::BeginFrameId& id) const; void Reset(); @@ -73,6 +76,7 @@ class CC_EXPORT FrameSorter { // State of each frame in terms of ack expectation. std::map<viz::BeginFrameId, FrameState> frame_states_; + std::map<viz::BeginFrameId, FrameInfo> frame_infos_; absl::optional<uint64_t> current_source_id_; }; diff --git a/chromium/cc/metrics/frame_sorter_unittest.cc b/chromium/cc/metrics/frame_sorter_unittest.cc index e8f58f43dc0..0672e6f9843 100644 --- a/chromium/cc/metrics/frame_sorter_unittest.cc +++ b/chromium/cc/metrics/frame_sorter_unittest.cc @@ -6,9 +6,12 @@ #include <string> #include <utility> +#include <vector> #include "base/bind.h" #include "base/strings/string_number_conversions.h" +#include "cc/metrics/frame_info.h" +#include "cc/test/fake_frame_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -49,6 +52,9 @@ class FrameSorterTest : public testing::Test { // "R": Reset the frame sorter. // Method expects the start of frames to be in order starting with 1. void SimulateQueries(std::vector<std::string> queries) { + // Keeps track of how many times a frame is terminated. + std::map<int, int> end_counters; + for (auto& query : queries) { int id; base::StringToInt(query.substr(1), &id); @@ -60,12 +66,38 @@ class FrameSorterTest : public testing::Test { case 'S': frame_sorter_.AddNewFrame(args_[id]); break; - case 'D': - frame_sorter_.AddFrameResult(args_[id], true); + case 'D': { + ++end_counters[id]; + FrameInfo info = + CreateFakeFrameInfo(FrameInfo::FrameFinalState::kDropped); + if (end_counters[id] == 1) { + // For the first response to the frame, mark it as not including + // update from the main-thread. + info.main_thread_response = FrameInfo::MainThreadResponse::kMissing; + } else { + DCHECK_EQ(2, end_counters[id]); + info.main_thread_response = + FrameInfo::MainThreadResponse::kIncluded; + } + frame_sorter_.AddFrameResult(args_[id], info); break; - case 'P': - frame_sorter_.AddFrameResult(args_[id], false); + } + case 'P': { + ++end_counters[id]; + FrameInfo info = + CreateFakeFrameInfo(FrameInfo::FrameFinalState::kPresentedAll); + if (end_counters[id] == 1) { + // For the first response to the frame, mark it as not including + // update from the main-thread. + info.main_thread_response = FrameInfo::MainThreadResponse::kMissing; + } else { + DCHECK_EQ(2, end_counters[id]); + info.main_thread_response = + FrameInfo::MainThreadResponse::kIncluded; + } + frame_sorter_.AddFrameResult(args_[id], info); break; + } case 'I': IncreaseSourceId(); break; @@ -89,8 +121,8 @@ class FrameSorterTest : public testing::Test { } private: - void FlushFrame(const viz::BeginFrameArgs& args, bool is_dropped) { - sorted_frames_.emplace_back(args, is_dropped); + void FlushFrame(const viz::BeginFrameArgs& args, const FrameInfo& frame) { + sorted_frames_.emplace_back(args, frame.IsDroppedAffectingSmoothness()); } FrameSorter frame_sorter_; diff --git a/chromium/cc/metrics/jank_injector.cc b/chromium/cc/metrics/jank_injector.cc index 01bf704bbcf..da18a0ce561 100644 --- a/chromium/cc/metrics/jank_injector.cc +++ b/chromium/cc/metrics/jank_injector.cc @@ -23,6 +23,9 @@ namespace cc { namespace { +constexpr char kTraceCategory[] = + "cc,benchmark," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame"); + const char kJankInjectionAllowedURLs[] = "allowed_urls"; const char kJankInjectionClusterSize[] = "cluster"; const char kJankInjectionTargetPercent[] = "percent"; @@ -88,7 +91,7 @@ bool IsJankInjectionEnabledForURL(const GURL& url) { } void RunJank(JankInjectionParams params) { - TRACE_EVENT0("cc,benchmark", "Injected Jank"); + TRACE_EVENT0(kTraceCategory, "Injected Jank"); if (params.busy_loop) { // Do some useless work, and prevent any weird compiler optimization from // doing anything here. diff --git a/chromium/cc/metrics/jank_injector.h b/chromium/cc/metrics/jank_injector.h index b6f22d554a0..9c2d693b363 100644 --- a/chromium/cc/metrics/jank_injector.h +++ b/chromium/cc/metrics/jank_injector.h @@ -5,7 +5,7 @@ #ifndef CC_METRICS_JANK_INJECTOR_H_ #define CC_METRICS_JANK_INJECTOR_H_ -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "cc/cc_export.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" diff --git a/chromium/cc/metrics/jank_metrics.cc b/chromium/cc/metrics/jank_metrics.cc index 2ae7f7c90ca..499f2d66881 100644 --- a/chromium/cc/metrics/jank_metrics.cc +++ b/chromium/cc/metrics/jank_metrics.cc @@ -29,18 +29,19 @@ constexpr base::TimeDelta kStaleHistogramMin = base::Microseconds(1); constexpr base::TimeDelta kStaleHistogramMax = base::Milliseconds(1000); constexpr int kStaleHistogramBucketCount = 200; -constexpr bool IsValidJankThreadType(FrameSequenceMetrics::ThreadType type) { - return type == FrameSequenceMetrics::ThreadType::kCompositor || - type == FrameSequenceMetrics::ThreadType::kMain; +constexpr bool IsValidJankThreadType( + FrameInfo::SmoothEffectDrivingThread type) { + return type == FrameInfo::SmoothEffectDrivingThread::kCompositor || + type == FrameInfo::SmoothEffectDrivingThread::kMain; } -const char* GetJankThreadTypeName(FrameSequenceMetrics::ThreadType type) { +const char* GetJankThreadTypeName(FrameInfo::SmoothEffectDrivingThread type) { DCHECK(IsValidJankThreadType(type)); switch (type) { - case FrameSequenceMetrics::ThreadType::kCompositor: + case FrameInfo::SmoothEffectDrivingThread::kCompositor: return "Compositor"; - case FrameSequenceMetrics::ThreadType::kMain: + case FrameInfo::SmoothEffectDrivingThread::kMain: return "Main"; default: NOTREACHED(); @@ -48,13 +49,13 @@ const char* GetJankThreadTypeName(FrameSequenceMetrics::ThreadType type) { } } -int GetIndexForJankMetric(FrameSequenceMetrics::ThreadType thread_type, +int GetIndexForJankMetric(FrameInfo::SmoothEffectDrivingThread thread_type, FrameSequenceTrackerType type) { DCHECK(IsValidJankThreadType(thread_type)); - if (thread_type == FrameSequenceMetrics::ThreadType::kMain) + if (thread_type == FrameInfo::SmoothEffectDrivingThread::kMain) return static_cast<int>(type); - DCHECK_EQ(thread_type, FrameSequenceMetrics::ThreadType::kCompositor); + DCHECK_EQ(thread_type, FrameInfo::SmoothEffectDrivingThread::kCompositor); return static_cast<int>(type) + kBuiltinSequenceNum; } @@ -84,7 +85,7 @@ std::string GetMaxStaleHistogramName(FrameSequenceTrackerType type) { } // namespace JankMetrics::JankMetrics(FrameSequenceTrackerType tracker_type, - FrameSequenceMetrics::ThreadType effective_thread) + FrameInfo::SmoothEffectDrivingThread effective_thread) : tracker_type_(tracker_type), effective_thread_(effective_thread) { DCHECK(IsValidJankThreadType(effective_thread)); } diff --git a/chromium/cc/metrics/jank_metrics.h b/chromium/cc/metrics/jank_metrics.h index 91ca7fa3d5c..7f8c9d4559a 100644 --- a/chromium/cc/metrics/jank_metrics.h +++ b/chromium/cc/metrics/jank_metrics.h @@ -25,7 +25,7 @@ namespace cc { class CC_EXPORT JankMetrics { public: JankMetrics(FrameSequenceTrackerType tracker_type, - FrameSequenceMetrics::ThreadType effective_thread); + FrameInfo::SmoothEffectDrivingThread effective_thread); ~JankMetrics(); JankMetrics(const JankMetrics&) = delete; @@ -55,7 +55,7 @@ class CC_EXPORT JankMetrics { int jank_count() const { return jank_count_; } base::TimeDelta max_staleness() const { return max_staleness_; } - FrameSequenceMetrics::ThreadType thread_type() const { + FrameInfo::SmoothEffectDrivingThread thread_type() const { return effective_thread_; } @@ -65,7 +65,7 @@ class CC_EXPORT JankMetrics { // The thread that contributes to the janks detected by the current // JankMetrics object. - const FrameSequenceMetrics::ThreadType effective_thread_; + const FrameInfo::SmoothEffectDrivingThread effective_thread_; // Number of janks detected. int jank_count_ = 0; diff --git a/chromium/cc/metrics/jank_metrics_unittest.cc b/chromium/cc/metrics/jank_metrics_unittest.cc index 0e9cf3bb3af..7f524364d7b 100644 --- a/chromium/cc/metrics/jank_metrics_unittest.cc +++ b/chromium/cc/metrics/jank_metrics_unittest.cc @@ -10,7 +10,6 @@ #include <utility> #include <vector> -#include "base/macros.h" #include "base/strings/strcat.h" #include "base/test/metrics/histogram_tester.h" #include "cc/metrics/frame_sequence_tracker.h" @@ -138,8 +137,8 @@ TEST_F(JankMetricsTest, CompositorAnimationOneJankWithMildFluctuation) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kCompositorAnimation; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor; JankMetrics jank_reporter{tracker_type, thread_type}; // One Jank; there are no no-update frames. The fluctuation in presentation of @@ -197,8 +196,8 @@ TEST_F(JankMetricsTest, MainThreadAnimationOneJankWithNoUpdate) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kMainThreadAnimation; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kMain; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kMain; JankMetrics jank_reporter{tracker_type, thread_type}; // There are only 1 jank because of a no-update frame. @@ -250,8 +249,8 @@ TEST_F(JankMetricsTest, MainThreadAnimationOneJankWithNoUpdate) { TEST_F(JankMetricsTest, VideoManyJanksOver300ExpectedFrames) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kVideo; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor; JankMetrics jank_reporter{tracker_type, thread_type}; // 7 janks. @@ -298,8 +297,8 @@ TEST_F(JankMetricsTest, WheelScrollMainThreadNoJanksWithNoUpdates) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kWheelScroll; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kMain; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kMain; JankMetrics jank_reporter{tracker_type, thread_type}; SimulateFrameSequence(&jank_reporter, @@ -349,8 +348,8 @@ TEST_F(JankMetricsTest, WheelScrollCompositorTwoJanksWithLargeFluctuation) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kWheelScroll; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor; JankMetrics jank_reporter{tracker_type, thread_type}; // Two janks; there are no no-update frames. The fluctuations in presentation @@ -405,8 +404,8 @@ TEST_F(JankMetricsTest, TouchScrollCompositorThreadManyJanksLongLatency) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kTouchScroll; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor; JankMetrics jank_reporter{tracker_type, thread_type}; @@ -464,8 +463,8 @@ TEST_F(JankMetricsTest, TouchScrollCompositorThreadManyJanksLongLatency) { TEST_F(JankMetricsTest, RAFMergeJanks) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kRAF; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kMain; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kMain; JankMetrics jank_reporter{tracker_type, thread_type}; std::unique_ptr<JankMetrics> other_reporter = @@ -523,8 +522,8 @@ TEST_F(JankMetricsTest, RAFMergeJanks) { TEST_F(JankMetricsTest, CustomNotReported) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kCustom; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kMain; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kMain; JankMetrics jank_reporter{tracker_type, thread_type}; // There should be 4 janks, but the jank reporter does not track or report @@ -559,8 +558,8 @@ TEST_F(JankMetricsTest, CompositorAnimationOneJankWithLongIdlePeriod) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kCompositorAnimation; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor; JankMetrics jank_reporter{tracker_type, thread_type}; // One jank at E. The long delay of 100 frames between b and c is considered @@ -625,8 +624,8 @@ TEST_F(JankMetricsTest, CompositorAnimationTwoJanksWithModerateIdlePeriod) { base::HistogramTester histogram_tester; FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kCompositorAnimation; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; + FrameInfo::SmoothEffectDrivingThread thread_type = + FrameInfo::SmoothEffectDrivingThread::kCompositor; JankMetrics jank_reporter{tracker_type, thread_type}; // Two janks at D and E. The long delay of 99 no-update frames does not diff --git a/chromium/cc/metrics/latency_ukm_reporter.cc b/chromium/cc/metrics/latency_ukm_reporter.cc index 996d2462fc6..70201ef5957 100644 --- a/chromium/cc/metrics/latency_ukm_reporter.cc +++ b/chromium/cc/metrics/latency_ukm_reporter.cc @@ -86,7 +86,7 @@ LatencyUkmReporter::LatencyUkmReporter() LatencyUkmReporter::~LatencyUkmReporter() = default; void LatencyUkmReporter::ReportCompositorLatencyUkm( - CompositorFrameReporter::FrameReportType report_type, + const CompositorFrameReporter::FrameReportTypes& report_types, const std::vector<CompositorFrameReporter::StageData>& stage_history, const ActiveTrackers& active_trackers, const CompositorFrameReporter::ProcessedBlinkBreakdown& @@ -96,7 +96,7 @@ void LatencyUkmReporter::ReportCompositorLatencyUkm( if (ukm_manager_ && compositor_latency_sampling_controller_->ShouldRecordNextEvent()) { ukm_manager_->RecordCompositorLatencyUKM( - report_type, stage_history, active_trackers, processed_blink_breakdown, + report_types, stage_history, active_trackers, processed_blink_breakdown, processed_viz_breakdown); } } diff --git a/chromium/cc/metrics/latency_ukm_reporter.h b/chromium/cc/metrics/latency_ukm_reporter.h index 0e289fddad8..0c26f560afc 100644 --- a/chromium/cc/metrics/latency_ukm_reporter.h +++ b/chromium/cc/metrics/latency_ukm_reporter.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/metrics/compositor_frame_reporter.h" #include "cc/metrics/event_metrics.h" @@ -26,7 +27,7 @@ class CC_EXPORT LatencyUkmReporter { LatencyUkmReporter& operator=(const LatencyUkmReporter&) = delete; void ReportCompositorLatencyUkm( - CompositorFrameReporter::FrameReportType report_type, + const CompositorFrameReporter::FrameReportTypes& report_types, const std::vector<CompositorFrameReporter::StageData>& stage_history, const ActiveTrackers& active_trackers, const CompositorFrameReporter::ProcessedBlinkBreakdown& @@ -52,7 +53,7 @@ class CC_EXPORT LatencyUkmReporter { // pointer is initialized, there should be no trackers yet. Moreover, the // LayerTreeHostImpl::ukm_manager_ lives as long as the LayerTreeHostImpl, so // this pointer should never be null as long as LayerTreeHostImpl is alive. - UkmManager* ukm_manager_ = nullptr; + raw_ptr<UkmManager> ukm_manager_ = nullptr; std::unique_ptr<SamplingController> compositor_latency_sampling_controller_; std::unique_ptr<SamplingController> event_latency_sampling_controller_; diff --git a/chromium/cc/metrics/lcd_text_metrics_reporter.h b/chromium/cc/metrics/lcd_text_metrics_reporter.h index b2aede915a5..ea93de770ec 100644 --- a/chromium/cc/metrics/lcd_text_metrics_reporter.h +++ b/chromium/cc/metrics/lcd_text_metrics_reporter.h @@ -8,6 +8,7 @@ #include <cstdint> #include <memory> +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -36,7 +37,7 @@ class CC_EXPORT LCDTextMetricsReporter { private: explicit LCDTextMetricsReporter(const LayerTreeHostImpl*); - const LayerTreeHostImpl* layer_tree_host_impl_; + raw_ptr<const LayerTreeHostImpl> layer_tree_host_impl_; base::TimeTicks last_report_frame_time_; base::TimeTicks current_frame_time_; uint64_t frame_count_since_last_report_ = 0; diff --git a/chromium/cc/metrics/throughput_ukm_reporter.cc b/chromium/cc/metrics/throughput_ukm_reporter.cc index b11ef1f4e22..077e9592442 100644 --- a/chromium/cc/metrics/throughput_ukm_reporter.cc +++ b/chromium/cc/metrics/throughput_ukm_reporter.cc @@ -37,13 +37,13 @@ void ThroughputUkmReporter::ReportThroughputUkm( samples_to_next_event_[static_cast<int>(type)] = kNumberOfSamplesToReport; if (impl_throughput_percent) { ukm_manager_->RecordThroughputUKM( - type, FrameSequenceMetrics::ThreadType::kCompositor, + type, FrameInfo::SmoothEffectDrivingThread::kCompositor, impl_throughput_percent.value()); } if (main_throughput_percent) { - ukm_manager_->RecordThroughputUKM(type, - FrameSequenceMetrics::ThreadType::kMain, - main_throughput_percent.value()); + ukm_manager_->RecordThroughputUKM( + type, FrameInfo::SmoothEffectDrivingThread::kMain, + main_throughput_percent.value()); } } DCHECK_GT(samples_to_next_event_[static_cast<int>(type)], 0u); diff --git a/chromium/cc/metrics/throughput_ukm_reporter.h b/chromium/cc/metrics/throughput_ukm_reporter.h index 7309f837aa4..f2dae411c5b 100644 --- a/chromium/cc/metrics/throughput_ukm_reporter.h +++ b/chromium/cc/metrics/throughput_ukm_reporter.h @@ -5,6 +5,7 @@ #ifndef CC_METRICS_THROUGHPUT_UKM_REPORTER_H_ #define CC_METRICS_THROUGHPUT_UKM_REPORTER_H_ +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/metrics/frame_sequence_metrics.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -49,7 +50,7 @@ class CC_EXPORT ThroughputUkmReporter { // This is pointing to the LayerTreeHostImpl::ukm_manager_, which is // initialized right after the LayerTreeHostImpl is created. So when this // pointer is initialized, there should be no trackers yet. - UkmManager* const ukm_manager_; + const raw_ptr<UkmManager> ukm_manager_; }; } // namespace cc diff --git a/chromium/cc/metrics/ukm_smoothness_data.cc b/chromium/cc/metrics/ukm_smoothness_data.cc new file mode 100644 index 00000000000..0daa46a4fba --- /dev/null +++ b/chromium/cc/metrics/ukm_smoothness_data.cc @@ -0,0 +1,11 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/metrics/ukm_smoothness_data.h" + +namespace cc { + +UkmSmoothnessData::UkmSmoothnessData() = default; + +} // namespace cc diff --git a/chromium/cc/metrics/ukm_smoothness_data.h b/chromium/cc/metrics/ukm_smoothness_data.h index 592f792352e..8aaedcb22b1 100644 --- a/chromium/cc/metrics/ukm_smoothness_data.h +++ b/chromium/cc/metrics/ukm_smoothness_data.h @@ -5,6 +5,8 @@ #ifndef CC_METRICS_UKM_SMOOTHNESS_DATA_H_ #define CC_METRICS_UKM_SMOOTHNESS_DATA_H_ +#include "base/time/time.h" +#include "cc/cc_export.h" #include "cc/metrics/shared_metrics_buffer.h" namespace cc { @@ -12,9 +14,12 @@ namespace cc { // The smoothness metrics, containing the score measured using various // normalization strategies. The normalization strategies are detailed in // https://docs.google.com/document/d/1ENJXn2bPqvxycnVS9X35qDu1642DQyz42upj5ETOhSs/preview -struct UkmSmoothnessData { +struct CC_EXPORT UkmSmoothnessData { + UkmSmoothnessData(); + double avg_smoothness = 0.0; double worst_smoothness = 0.0; + double median_smoothness = 0.0; // Values are set to -1 to help with recognizing when these metrics are not // calculated. @@ -24,8 +29,21 @@ struct UkmSmoothnessData { double above_threshold = 0.0; double percentile_95 = 0.0; + double variance = 0.0; double buckets[7] = {0}; base::TimeDelta time_max_delta = base::Milliseconds(1); + + double scroll_focused_median = 0.0; + double scroll_focused_percentile_95 = 0.0; + double scroll_focused_variance = 0.0; + + double main_focused_median = 0.0; + double main_focused_percentile_95 = 0.0; + double main_focused_variance = 0.0; + + double compositor_focused_median = 0.0; + double compositor_focused_percentile_95 = 0.0; + double compositor_focused_variance = 0.0; }; using UkmSmoothnessDataShared = SharedMetricsBuffer<UkmSmoothnessData>; diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc index f3f2fc5e416..a7f0a88a5fd 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc @@ -10,7 +10,9 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/threading/platform_thread.h" #include "base/trace_event/trace_event.h" +#include "build/build_config.h" #include "cc/base/histograms.h" #include "cc/trees/layer_tree_frame_sink_client.h" #include "components/power_scheduler/power_mode.h" @@ -49,6 +51,9 @@ AsyncLayerTreeFrameSink::AsyncLayerTreeFrameSink( params->gpu_memory_buffer_manager), synthetic_begin_frame_source_( std::move(params->synthetic_begin_frame_source)), +#if defined(OS_ANDROID) + io_thread_id_(params->io_thread_id), +#endif pipes_(std::move(params->pipes)), wants_animate_only_begin_frames_(params->wants_animate_only_begin_frames), power_mode_voter_("PowerModeVoter.Animation") { @@ -95,6 +100,14 @@ bool AsyncLayerTreeFrameSink::BindToClient(LayerTreeFrameSinkClient* client) { compositor_frame_sink_ptr_->InitializeCompositorFrameSinkType( viz::mojom::CompositorFrameSinkType::kLayerTree); +#if defined(OS_ANDROID) + std::vector<int32_t> thread_ids; + thread_ids.push_back(base::PlatformThread::CurrentId()); + if (io_thread_id_ != base::kInvalidThreadId) + thread_ids.push_back(io_thread_id_); + compositor_frame_sink_ptr_->SetThreadIds(thread_ids); +#endif + return true; } diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h index bc258e3d193..b10b55d020f 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h @@ -9,9 +9,12 @@ #include <string> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" +#include "base/threading/platform_thread.h" +#include "build/build_config.h" #include "cc/mojo_embedder/mojo_embedder_export.h" #include "cc/trees/layer_tree_frame_sink.h" #include "components/power_scheduler/power_mode_voter.h" @@ -61,12 +64,13 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink ~InitParams(); scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner; - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager = nullptr; + raw_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager = nullptr; std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source; UnboundMessagePipes pipes; bool wants_animate_only_begin_frames = false; const char* client_name = nullptr; + base::PlatformThreadId io_thread_id = base::kInvalidThreadId; }; AsyncLayerTreeFrameSink( @@ -121,6 +125,9 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink viz::LocalSurfaceId local_surface_id_; std::unique_ptr<viz::ExternalBeginFrameSource> begin_frame_source_; std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_begin_frame_source_; +#if defined(OS_ANDROID) + base::PlatformThreadId io_thread_id_; +#endif // Message pipes that will be bound when BindToClient() is called. UnboundMessagePipes pipes_; @@ -128,7 +135,7 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink // One of |compositor_frame_sink_| or |compositor_frame_sink_associated_| will // be bound after calling BindToClient(). |compositor_frame_sink_ptr_| will // point to message pipe we want to use. - viz::mojom::CompositorFrameSink* compositor_frame_sink_ptr_ = nullptr; + raw_ptr<viz::mojom::CompositorFrameSink> compositor_frame_sink_ptr_ = nullptr; mojo::Remote<viz::mojom::CompositorFrameSink> compositor_frame_sink_; mojo::AssociatedRemote<viz::mojom::CompositorFrameSink> compositor_frame_sink_associated_; diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc index 3629e396af2..ca9a80df59d 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc @@ -8,9 +8,10 @@ #include <utility> #include "base/bind.h" +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" @@ -55,8 +56,8 @@ class ThreadTrackingLayerTreeFrameSinkClient } private: - base::PlatformThreadId* called_thread_id_; - base::RunLoop* run_loop_; + raw_ptr<base::PlatformThreadId> called_thread_id_; + raw_ptr<base::RunLoop> run_loop_; }; TEST(AsyncLayerTreeFrameSinkTest, diff --git a/chromium/cc/mojom/render_frame_metadata.mojom b/chromium/cc/mojom/render_frame_metadata.mojom index eaee8d7fe15..cbb8a037ba1 100644 --- a/chromium/cc/mojom/render_frame_metadata.mojom +++ b/chromium/cc/mojom/render_frame_metadata.mojom @@ -31,7 +31,7 @@ struct RenderFrameMetadata { // Scroll offset of the root layer. This optional parameter is only sent // during tests. - gfx.mojom.Vector2dF? root_scroll_offset; + gfx.mojom.PointF? root_scroll_offset; // Indicates whether the scroll offset of the root layer is at top, i.e., // whether scroll_offset.y() == 0. @@ -153,5 +153,5 @@ interface RenderFrameMetadataObserverClient { // Only called if ReportAllRootScrolls(true) has been called. See // ReportAllRootScrolls() for details. [EnableIf=is_android] - OnRootScrollOffsetChanged(gfx.mojom.Vector2dF root_scroll_offset); + OnRootScrollOffsetChanged(gfx.mojom.PointF root_scroll_offset); }; diff --git a/chromium/cc/mojom/render_frame_metadata_mojom_traits.h b/chromium/cc/mojom/render_frame_metadata_mojom_traits.h index 717a9bb3555..ffacfc94477 100644 --- a/chromium/cc/mojom/render_frame_metadata_mojom_traits.h +++ b/chromium/cc/mojom/render_frame_metadata_mojom_traits.h @@ -36,7 +36,7 @@ struct COMPONENT_EXPORT(CC_SHARED_MOJOM_TRAITS) return metadata.root_background_color; } - static absl::optional<gfx::Vector2dF> root_scroll_offset( + static absl::optional<gfx::PointF> root_scroll_offset( const cc::RenderFrameMetadata& metadata) { return metadata.root_scroll_offset; } diff --git a/chromium/cc/paint/BUILD.gn b/chromium/cc/paint/BUILD.gn index 98b86f97527..19a0a6330ff 100644 --- a/chromium/cc/paint/BUILD.gn +++ b/chromium/cc/paint/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//cc/cc.gni") +import("//skia/features.gni") import("//testing/libfuzzer/fuzzer_test.gni") cc_component("paint") { @@ -81,6 +82,13 @@ cc_component("paint") { "skia_paint_canvas.h", "skia_paint_image_generator.cc", "skia_paint_image_generator.h", + "skottie_frame_data.cc", + "skottie_frame_data.h", + "skottie_frame_data_provider.h", + "skottie_resource_metadata.cc", + "skottie_resource_metadata.h", + "skottie_transfer_cache_entry.cc", + "skottie_transfer_cache_entry.h", "skottie_wrapper.cc", "skottie_wrapper.h", "solid_color_analyzer.cc", @@ -103,6 +111,7 @@ cc_component("paint") { "//cc/debug", "//skia", "//skia:skcms", + "//third_party/abseil-cpp:absl", "//ui/gfx:color_space", "//ui/gfx/geometry", "//ui/gfx/geometry:geometry_skia", @@ -116,11 +125,20 @@ cc_component("paint") { "//ui/gfx/ipc/color", ] - if (!is_android) { + if (skia_support_skottie) { + # All source files that depend on the actual Skottie module within Skia + # should go here. If a source file is Skottie-related but depends only on + # Chromium and/or "common" Skia dependencies, it is fine to include that + # in the main "sources" list. Note that ultimately, all dependencies on + # the Skottie library should be contained in some way/shape/form within + # skottie_wrapper_impl.cc sources += [ - "skottie_transfer_cache_entry.cc", - "skottie_transfer_cache_entry.h", + "skottie_mru_resource_provider.cc", + "skottie_mru_resource_provider.h", + "skottie_wrapper_impl.cc", ] + } else { + sources += [ "skottie_wrapper_stub.cc" ] } } diff --git a/chromium/cc/paint/DEPS b/chromium/cc/paint/DEPS index 2dffad4d1db..873400ee890 100644 --- a/chromium/cc/paint/DEPS +++ b/chromium/cc/paint/DEPS @@ -5,6 +5,7 @@ include_rules = [ "+cc/base", "+cc/debug", "+cc/paint", + "+skia/buildflags.h", ] specific_include_rules = { @@ -24,7 +25,4 @@ specific_include_rules = { "oop_pixeltest.cc": [ "+gpu/command_buffer", ], - "skottie_wrapper.h": [ - "+third_party/skia", - ], } diff --git a/chromium/cc/paint/decoded_draw_image.cc b/chromium/cc/paint/decoded_draw_image.cc index d03a42b2779..f582a4bcefd 100644 --- a/chromium/cc/paint/decoded_draw_image.cc +++ b/chromium/cc/paint/decoded_draw_image.cc @@ -8,7 +8,7 @@ namespace cc { -DecodedDrawImage::DecodedDrawImage(sk_sp<const SkImage> image, +DecodedDrawImage::DecodedDrawImage(sk_sp<SkImage> image, sk_sp<SkColorFilter> dark_mode_color_filter, const SkSize& src_rect_offset, const SkSize& scale_adjustment, diff --git a/chromium/cc/paint/decoded_draw_image.h b/chromium/cc/paint/decoded_draw_image.h index 8b52faeecd0..bde75665398 100644 --- a/chromium/cc/paint/decoded_draw_image.h +++ b/chromium/cc/paint/decoded_draw_image.h @@ -26,7 +26,7 @@ namespace cc { // to be rastered directly, it uses the SkImage constructor. class CC_PAINT_EXPORT DecodedDrawImage { public: - DecodedDrawImage(sk_sp<const SkImage> image, + DecodedDrawImage(sk_sp<SkImage> image, sk_sp<SkColorFilter> dark_mode_color_filter, const SkSize& src_rect_offset, const SkSize& scale_adjustment, @@ -49,7 +49,7 @@ class CC_PAINT_EXPORT DecodedDrawImage { DecodedDrawImage(); ~DecodedDrawImage(); - const sk_sp<const SkImage>& image() const { return image_; } + const sk_sp<SkImage>& image() const { return image_; } const sk_sp<SkColorFilter>& dark_mode_color_filter() const { return dark_mode_color_filter_; } @@ -73,7 +73,7 @@ class CC_PAINT_EXPORT DecodedDrawImage { } private: - sk_sp<const SkImage> image_; + sk_sp<SkImage> image_; gpu::Mailbox mailbox_; absl::optional<uint32_t> transfer_cache_entry_id_; sk_sp<SkColorFilter> dark_mode_color_filter_; diff --git a/chromium/cc/paint/discardable_image_map.cc b/chromium/cc/paint/discardable_image_map.cc index 0e94618e7b8..d4cf1dbc10b 100644 --- a/chromium/cc/paint/discardable_image_map.cc +++ b/chromium/cc/paint/discardable_image_map.cc @@ -11,11 +11,14 @@ #include "base/auto_reset.h" #include "base/containers/adapters.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/trace_event/trace_event.h" +#include "cc/paint/image_provider.h" #include "cc/paint/paint_filter.h" #include "cc/paint/paint_op_buffer.h" +#include "cc/paint/skottie_wrapper.h" #include "third_party/skia/include/utils/SkNoDrawCanvas.h" #include "ui/gfx/display_color_spaces.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -76,7 +79,7 @@ class DiscardableImageGenerator { } private: - DiscardableImageGenerator* generator_; + raw_ptr<DiscardableImageGenerator> generator_; gfx::Rect op_rect_; }; @@ -146,6 +149,42 @@ class DiscardableImageGenerator { AddImage(image_rect_op->image, image_rect_op->flags.useDarkModeForImage(), image_rect_op->src, op_rect, matrix, image_rect_op->flags.getFilterQuality()); + } else if (op_type == PaintOpType::DrawSkottie) { + auto* skottie_op = static_cast<DrawSkottieOp*>(op); + for (const auto& image_pair : skottie_op->images) { + const SkottieFrameData& frame_data = image_pair.second; + // Add the whole image (no cropping). + SkRect image_src_rect = SkRect::MakeIWH(frame_data.image.width(), + frame_data.image.height()); + // It is too difficult to tell which specific portion of the animation + // frame this image will ultimately occupy. So just assume it occupies + // the whole animation frame for the purposes of finding which images + // overlap with a given rectangle on the screen. + gfx::Rect dst_rect = op_rect; + // Skottie ultimately takes care of scaling and positioning the image + // internally within the animation frame. However, the image that gets + // cached in the ImageDecodeCache should have dimensions that at least + // roughly reflect the ultimate output both for cache space + // consumption reasons and to make Skottie's scaling job easier + // (performance). For this reason, the DrawImage submitted to the + // cache is scaled by the same amount that the entire animation frame + // itself is scaled. This should get the image dimensions in the right + // ballpark in the event that the animation's native size and the + // destination's size differ drastically. + // + // Do not allow stretching the image in 1 dimension when scaling. This + // matches Skottie's scaling behavior. + static constexpr SkMatrix::ScaleToFit kScalingMode = + SkMatrix::kCenter_ScaleToFit; + SkRect skottie_frame_native_size = + SkRect::MakeSize(skottie_op->skottie->size()); + SkM44 matrix = ctm * SkM44(SkMatrix::RectToRect( + skottie_frame_native_size, + gfx::RectToSkRect(dst_rect), kScalingMode)); + AddImage(frame_data.image, /*use_dark_mode=*/false, + std::move(image_src_rect), std::move(dst_rect), matrix, + frame_data.quality); + } } else if (op_type == PaintOpType::DrawRecord) { GatherDiscardableImages( static_cast<const DrawRecordOp*>(op)->record.get(), diff --git a/chromium/cc/paint/discardable_image_map_unittest.cc b/chromium/cc/paint/discardable_image_map_unittest.cc index f119ceb5d71..b3a5b016ef8 100644 --- a/chromium/cc/paint/discardable_image_map_unittest.cc +++ b/chromium/cc/paint/discardable_image_map_unittest.cc @@ -17,10 +17,15 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_op_buffer.h" #include "cc/paint/paint_recorder.h" +#include "cc/paint/skottie_frame_data.h" +#include "cc/paint/skottie_resource_metadata.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_recording_source.h" +#include "cc/test/lottie_test_data.h" #include "cc/test/skia_common.h" #include "cc/test/test_paint_worklet_input.h" +#include "skia/buildflags.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkGraphics.h" @@ -32,6 +37,12 @@ namespace cc { namespace { +using ::testing::Contains; +using ::testing::Eq; +using ::testing::Field; +using ::testing::FloatNear; +using ::testing::IsEmpty; +using ::testing::SizeIs; using Rects = base::StackVector<gfx::Rect, 1>; struct PositionScaleDrawImage { @@ -1166,6 +1177,104 @@ TEST_F(DiscardableImageMapTest, ContentColorUsage) { gfx::ContentColorUsage::kHDR); } +#if BUILDFLAG(SKIA_SUPPORT_SKOTTIE) +TEST_F(DiscardableImageMapTest, + GetDiscardableImagesInRectSkottieWithoutImages) { + gfx::Rect visible_rect(2048, 2048); + FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); + content_layer_client.add_draw_skottie(FakeContentLayerClient::SkottieData( + CreateSkottie(gfx::Size(2048, 2048), /*duration_secs=*/1.f), + /*dst=*/gfx::Rect(2048, 2048), /*t=*/0.1f, SkottieFrameDataMap())); + + scoped_refptr<DisplayItemList> display_list = + content_layer_client.PaintContentsToDisplayList(); + display_list->GenerateDiscardableImagesMetadata(); + const DiscardableImageMap& image_map = display_list->discardable_image_map(); + EXPECT_THAT(GetDiscardableImagesInRect(image_map, gfx::Rect(2048, 2048)), + IsEmpty()); +} + +TEST_F(DiscardableImageMapTest, GetDiscardableImagesInRectSkottieWithImages) { + gfx::Rect visible_rect(2048, 2048); + FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); + // Skottie animation only is rendered in the right half of the screen. + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + + SkottieFrameDataMap images_in; + PaintImage image_0 = CreateDiscardablePaintImage( + gfx::Size(kLottieDataWith2AssetsWidth, kLottieDataWith2AssetsHeight)); + PaintImage image_1 = CreateDiscardablePaintImage( + gfx::Size(kLottieDataWith2AssetsWidth, kLottieDataWith2AssetsHeight)); + images_in[HashSkottieResourceId("image_0")] = { + .image = image_0, .quality = PaintFlags::FilterQuality::kHigh}; + images_in[HashSkottieResourceId("image_1")] = { + .image = image_1, .quality = PaintFlags::FilterQuality::kHigh}; + content_layer_client.add_draw_skottie(FakeContentLayerClient::SkottieData( + CreateSkottieFromString(kLottieDataWith2Assets), + /*dst=*/gfx::Rect(1024, 0, 1024, 2048), + /*t=*/0.1f, images_in)); + + scoped_refptr<DisplayItemList> display_list = + content_layer_client.PaintContentsToDisplayList(); + display_list->GenerateDiscardableImagesMetadata(); + const DiscardableImageMap& image_map = display_list->discardable_image_map(); + // Left Half of screen should return no images. + EXPECT_THAT(GetDiscardableImagesInRect(image_map, gfx::Rect(1023, 2048)), + IsEmpty()); + // Right Half of screen should return 2 images. + std::vector<PositionScaleDrawImage> images_out = + GetDiscardableImagesInRect(image_map, gfx::Rect(1024, 0, 1024, 2048)); + ASSERT_THAT(images_out, SizeIs(2)); + EXPECT_THAT(images_out, + Contains(Field(&PositionScaleDrawImage::image, Eq(image_0)))); + EXPECT_THAT(images_out, + Contains(Field(&PositionScaleDrawImage::image, Eq(image_1)))); +} + +TEST_F(DiscardableImageMapTest, + GetDiscardableImagesInRectSkottieWithImagesScalesProperly) { + gfx::Rect visible_rect(kLottieDataWith2AssetsWidth * 2, + kLottieDataWith2AssetsHeight * 3); + FakeContentLayerClient content_layer_client; + content_layer_client.set_bounds(visible_rect.size()); + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + + SkottieFrameDataMap images_in; + PaintImage image_0 = CreateDiscardablePaintImage( + gfx::Size(kLottieDataWith2AssetsWidth, kLottieDataWith2AssetsHeight)); + PaintImage image_1 = CreateDiscardablePaintImage( + gfx::Size(kLottieDataWith2AssetsWidth, kLottieDataWith2AssetsHeight)); + images_in[HashSkottieResourceId("image_0")] = { + .image = image_0, .quality = PaintFlags::FilterQuality::kHigh}; + images_in[HashSkottieResourceId("image_1")] = { + .image = image_1, .quality = PaintFlags::FilterQuality::kHigh}; + content_layer_client.add_draw_skottie(FakeContentLayerClient::SkottieData( + CreateSkottieFromString(kLottieDataWith2Assets), + /*dst=*/visible_rect, + /*t=*/0.1f, images_in)); + + scoped_refptr<DisplayItemList> display_list = + content_layer_client.PaintContentsToDisplayList(); + display_list->GenerateDiscardableImagesMetadata(); + const DiscardableImageMap& image_map = display_list->discardable_image_map(); + std::vector<PositionScaleDrawImage> images_out = + GetDiscardableImagesInRect(image_map, visible_rect); + ASSERT_THAT(images_out, SizeIs(2)); + for (const PositionScaleDrawImage& image_out : images_out) { + static constexpr float kScaleTolerance = .01f; + EXPECT_THAT(image_out.scale.width(), FloatNear(2.f, kScaleTolerance)); + // Even though the destination rect's height is 3x the animation frame's + // height, the image should not get stretched. + EXPECT_THAT(image_out.scale.height(), FloatNear(2.f, kScaleTolerance)); + } +} + +#endif // BUILDFLAG(SKIA_SUPPORT_SKOTTIE) + class DiscardableImageMapColorSpaceTest : public DiscardableImageMapTest, public testing::WithParamInterface<gfx::ColorSpace> {}; diff --git a/chromium/cc/paint/display_item_list_unittest.cc b/chromium/cc/paint/display_item_list_unittest.cc index 04036dce3f6..7cd50e328bc 100644 --- a/chromium/cc/paint/display_item_list_unittest.cc +++ b/chromium/cc/paint/display_item_list_unittest.cc @@ -19,7 +19,6 @@ #include "cc/paint/paint_record.h" #include "cc/paint/render_surface_filters.h" #include "cc/paint/skia_paint_canvas.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/pixel_test_utils.h" #include "cc/test/skia_common.h" #include "cc/test/test_skcanvas.h" @@ -114,17 +113,22 @@ TEST_F(DisplayItemListTest, TraceEmptyVisualRect) { ASSERT_TRUE(params_dict->GetList("items", &items)); ASSERT_EQ(2u, items->GetList().size()); + const base::Value* item_value; const base::DictionaryValue* item_dict; const base::ListValue* visual_rect; std::string name; - ASSERT_TRUE(items->GetDictionary(0, &item_dict)); + item_value = &items->GetList()[0]; + ASSERT_TRUE(item_value->is_dict()); + item_dict = &base::Value::AsDictionaryValue(*item_value); ASSERT_TRUE(item_dict->GetList("visual_rect", &visual_rect)); EXPECT_TRACED_RECT(0, 0, 0, 0, visual_rect); EXPECT_TRUE(item_dict->GetString("name", &name)); EXPECT_EQ("DrawRect", name); - ASSERT_TRUE(items->GetDictionary(1, &item_dict)); + item_value = &items->GetList()[1]; + ASSERT_TRUE(item_value->is_dict()); + item_dict = &base::Value::AsDictionaryValue(*item_value); ASSERT_TRUE(item_dict->GetList("visual_rect", &visual_rect)); EXPECT_TRACED_RECT(8, 9, 10, 10, visual_rect); EXPECT_TRUE(item_dict->GetString("name", &name)); @@ -562,20 +566,22 @@ TEST_F(DisplayItemListTest, AsValueWithOps) { bool expected_has_skp[] = {false, true, true, true, true, false, false}; for (int i = 0; i < 7; ++i) { - const base::DictionaryValue* item_dict; - ASSERT_TRUE(items->GetDictionary(i, &item_dict)); + const base::Value& item_value = items->GetList()[i]; + ASSERT_TRUE(item_value.is_dict()); + const base::DictionaryValue& item_dict = + base::Value::AsDictionaryValue(item_value); const base::ListValue* visual_rect; - ASSERT_TRUE(item_dict->GetList("visual_rect", &visual_rect)); + ASSERT_TRUE(item_dict.GetList("visual_rect", &visual_rect)); EXPECT_TRACED_RECT(2, 3, 8, 9, visual_rect); std::string name; - EXPECT_TRUE(item_dict->GetString("name", &name)); + EXPECT_TRUE(item_dict.GetString("name", &name)); EXPECT_EQ(expected_names[i], name); EXPECT_EQ( expected_has_skp[i], - item_dict->GetString("skp64", static_cast<std::string*>(nullptr))); + item_dict.GetString("skp64", static_cast<std::string*>(nullptr))); } } } @@ -648,7 +654,7 @@ TEST_F(DisplayItemListTest, AppendVisualRectSimple) { } EXPECT_EQ(1u, list->TotalOpCount()); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(0)); } TEST_F(DisplayItemListTest, AppendVisualRectEmptyBlock) { @@ -671,9 +677,9 @@ TEST_F(DisplayItemListTest, AppendVisualRectEmptyBlock) { } EXPECT_EQ(3u, list->TotalOpCount()); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(2)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(0)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(1)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(2)); } TEST_F(DisplayItemListTest, AppendVisualRectEmptyBlockContainingEmptyBlock) { @@ -708,11 +714,11 @@ TEST_F(DisplayItemListTest, AppendVisualRectEmptyBlockContainingEmptyBlock) { } EXPECT_EQ(5u, list->TotalOpCount()); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(3)); - EXPECT_RECT_EQ(gfx::Rect(), list->VisualRectForTesting(4)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(0)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(1)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(2)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(3)); + EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(4)); } TEST_F(DisplayItemListTest, AppendVisualRectBlockContainingDrawing) { @@ -743,10 +749,10 @@ TEST_F(DisplayItemListTest, AppendVisualRectBlockContainingDrawing) { } EXPECT_EQ(4u, list->TotalOpCount()); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(3)); } TEST_F(DisplayItemListTest, AppendVisualRectBlockContainingEscapedDrawing) { @@ -777,10 +783,10 @@ TEST_F(DisplayItemListTest, AppendVisualRectBlockContainingEscapedDrawing) { } EXPECT_EQ(4u, list->TotalOpCount()); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(3)); } TEST_F(DisplayItemListTest, @@ -820,11 +826,11 @@ TEST_F(DisplayItemListTest, } EXPECT_EQ(5u, list->TotalOpCount()); - EXPECT_RECT_EQ(drawing_a_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); + EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); } TEST_F(DisplayItemListTest, AppendVisualRectTwoBlocksTwoDrawings) { @@ -878,14 +884,14 @@ TEST_F(DisplayItemListTest, AppendVisualRectTwoBlocksTwoDrawings) { EXPECT_EQ(8u, list->TotalOpCount()); gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds); merged_drawing_bounds.Union(drawing_b_bounds); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); } TEST_F(DisplayItemListTest, @@ -941,14 +947,14 @@ TEST_F(DisplayItemListTest, EXPECT_EQ(8u, list->TotalOpCount()); gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds); merged_drawing_bounds.Union(drawing_b_bounds); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); } TEST_F(DisplayItemListTest, @@ -1004,14 +1010,14 @@ TEST_F(DisplayItemListTest, EXPECT_EQ(8u, list->TotalOpCount()); gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds); merged_drawing_bounds.Union(drawing_b_bounds); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); } TEST_F(DisplayItemListTest, @@ -1067,14 +1073,14 @@ TEST_F(DisplayItemListTest, EXPECT_EQ(8u, list->TotalOpCount()); gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds); merged_drawing_bounds.Union(drawing_b_bounds); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); - EXPECT_RECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); - EXPECT_RECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1)); + EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5)); + EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6)); + EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7)); } TEST_F(DisplayItemListTest, VisualRectForPairsEnclosingEmptyPainting) { @@ -1103,9 +1109,9 @@ TEST_F(DisplayItemListTest, VisualRectForPairsEnclosingEmptyPainting) { } EXPECT_EQ(3u, list->TotalOpCount()); - EXPECT_RECT_EQ(visual_rect, list->VisualRectForTesting(0)); - EXPECT_RECT_EQ(visual_rect, list->VisualRectForTesting(1)); - EXPECT_RECT_EQ(visual_rect, list->VisualRectForTesting(2)); + EXPECT_EQ(visual_rect, list->VisualRectForTesting(0)); + EXPECT_EQ(visual_rect, list->VisualRectForTesting(1)); + EXPECT_EQ(visual_rect, list->VisualRectForTesting(2)); } TEST_F(DisplayItemListTest, TotalOpCount) { diff --git a/chromium/cc/paint/image_transfer_cache_entry.h b/chromium/cc/paint/image_transfer_cache_entry.h index 65b3644fa11..4a54a41d3a9 100644 --- a/chromium/cc/paint/image_transfer_cache_entry.h +++ b/chromium/cc/paint/image_transfer_cache_entry.h @@ -12,6 +12,7 @@ #include "base/atomic_sequence_num.h" #include "base/containers/span.h" +#include "base/memory/raw_ptr.h" #include "cc/paint/transfer_cache_entry.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkImageInfo.h" @@ -75,15 +76,15 @@ class CC_PAINT_EXPORT ClientImageTransferCacheEntry final static base::AtomicSequenceNumber s_next_id_; // RGBX-only members. - const SkPixmap* const pixmap_; - const SkColorSpace* const + const raw_ptr<const SkPixmap> pixmap_; + const raw_ptr<const SkColorSpace> target_color_space_; // Unused for YUV because Skia handles colorspaces // at raster. // YUVA-only members. absl::optional<std::array<const SkPixmap*, SkYUVAInfo::kMaxPlanes>> yuv_pixmaps_; - const SkColorSpace* const decoded_color_space_; + const raw_ptr<const SkColorSpace> decoded_color_space_; SkYUVAInfo::Subsampling subsampling_ = SkYUVAInfo::Subsampling::kUnknown; SkYUVColorSpace yuv_color_space_; @@ -154,7 +155,7 @@ class CC_PAINT_EXPORT ServiceImageTransferCacheEntry final uint32_t height, sk_sp<SkColorSpace> target_color_space); - GrDirectContext* context_ = nullptr; + raw_ptr<GrDirectContext> context_ = nullptr; std::vector<sk_sp<SkImage>> plane_images_; SkYUVAInfo::PlaneConfig plane_config_ = SkYUVAInfo::PlaneConfig::kUnknown; std::vector<size_t> plane_sizes_; diff --git a/chromium/cc/paint/oop_pixeltest.cc b/chromium/cc/paint/oop_pixeltest.cc index 174f41378b1..08df0a23b25 100644 --- a/chromium/cc/paint/oop_pixeltest.cc +++ b/chromium/cc/paint/oop_pixeltest.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/memory/raw_ptr.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -141,9 +142,9 @@ class OopPixelTest : public testing::Test, bool requires_clear = false; bool preclear = false; SkColor preclear_color; - ImageDecodeCache* image_cache = nullptr; + raw_ptr<ImageDecodeCache> image_cache = nullptr; std::vector<scoped_refptr<DisplayItemList>> additional_lists; - PaintShader* shader_with_animated_images = nullptr; + raw_ptr<PaintShader> shader_with_animated_images = nullptr; }; SkBitmap Raster(scoped_refptr<DisplayItemList> display_item_list, diff --git a/chromium/cc/paint/paint_cache.h b/chromium/cc/paint/paint_cache.h index 1d53dace843..e0cd5384ebf 100644 --- a/chromium/cc/paint/paint_cache.h +++ b/chromium/cc/paint/paint_cache.h @@ -10,7 +10,7 @@ #include <utility> #include <vector> -#include "base/containers/mru_cache.h" +#include "base/containers/lru_cache.h" #include "base/containers/stack_container.h" #include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkPath.h" @@ -87,7 +87,7 @@ class CC_PAINT_EXPORT ClientPaintCache { private: using CacheKey = std::pair<PaintCacheDataType, PaintCacheId>; - using CacheMap = base::MRUCache<CacheKey, size_t>; + using CacheMap = base::LRUCache<CacheKey, size_t>; template <typename Iterator> void EraseFromMap(Iterator it); diff --git a/chromium/cc/paint/paint_canvas.h b/chromium/cc/paint/paint_canvas.h index ec980047a91..0ae9e7776f9 100644 --- a/chromium/cc/paint/paint_canvas.h +++ b/chromium/cc/paint/paint_canvas.h @@ -6,11 +6,13 @@ #define CC_PAINT_PAINT_CANVAS_H_ #include "base/compiler_specific.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "cc/paint/node_id.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_image.h" +#include "cc/paint/skottie_frame_data.h" #include "third_party/skia/include/core/SkCanvas.h" class SkTextBlob; @@ -78,6 +80,7 @@ class CC_PAINT_EXPORT PaintCanvas { virtual void restoreToCount(int save_count) = 0; virtual void translate(SkScalar dx, SkScalar dy) = 0; virtual void scale(SkScalar sx, SkScalar sy) = 0; + void scale(SkScalar s) { scale(s, s); } virtual void rotate(SkScalar degrees) = 0; // TODO(aaronhk): crbug.com/1153330 deprecate these in favor of the SkM44 // versions. @@ -181,10 +184,13 @@ class CC_PAINT_EXPORT PaintCanvas { // Draws the frame of the |skottie| animation specified by the normalized time // t [0->first frame..1->last frame] at the destination bounds given by |dst| - // onto the canvas. + // onto the canvas. |images| is a map from asset id to the corresponding image + // to use when rendering this frame; it may be empty if this animation frame + // does not contain any images in it. virtual void drawSkottie(scoped_refptr<SkottieWrapper> skottie, const SkRect& dst, - float t) = 0; + float t, + SkottieFrameDataMap images) = 0; virtual void drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar x, @@ -205,6 +211,8 @@ class CC_PAINT_EXPORT PaintCanvas { virtual SkMatrix getTotalMatrix() const = 0; virtual SkM44 getLocalToDevice() const = 0; + virtual bool NeedsFlush() const = 0; + // Used for printing enum class AnnotationType { URL, @@ -261,7 +269,7 @@ class CC_PAINT_EXPORT PaintCanvasAutoRestore { } private: - PaintCanvas* canvas_ = nullptr; + raw_ptr<PaintCanvas> canvas_ = nullptr; int save_count_ = 0; }; diff --git a/chromium/cc/paint/paint_filter.cc b/chromium/cc/paint/paint_filter.cc index 2dd7b517537..5ebd057f16a 100644 --- a/chromium/cc/paint/paint_filter.cc +++ b/chromium/cc/paint/paint_filter.cc @@ -9,11 +9,15 @@ #include <vector> #include "base/no_destructor.h" +#include "base/stl_util.h" #include "build/build_config.h" +#include "cc/paint/draw_image.h" #include "cc/paint/filter_operations.h" +#include "cc/paint/image_provider.h" #include "cc/paint/paint_image_builder.h" #include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" +#include "cc/paint/scoped_raster_flags.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkMath.h" #include "third_party/skia/include/core/SkString.h" @@ -341,6 +345,10 @@ std::string PaintFilter::TypeToString(Type type) { return "Unknown"; } +const PaintFilter::CropRect* PaintFilter::GetCropRect() const { + return base::OptionalOrNullptr(crop_rect_); +} + size_t PaintFilter::GetFilterSize(const PaintFilter* filter) { // A null type is used to indicate no filter. if (!filter) @@ -481,7 +489,7 @@ size_t ColorFilterPaintFilter::SerializedSize() const { sk_sp<PaintFilter> ColorFilterPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<ColorFilterPaintFilter>( - color_filter_, Snapshot(input_, image_provider), crop_rect()); + color_filter_, Snapshot(input_, image_provider), GetCropRect()); } bool ColorFilterPaintFilter::operator==( @@ -519,7 +527,7 @@ sk_sp<PaintFilter> BlurPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<BlurPaintFilter>(sigma_x_, sigma_y_, tile_mode_, Snapshot(input_, image_provider), - crop_rect()); + GetCropRect()); } bool BlurPaintFilter::operator==(const BlurPaintFilter& other) const { @@ -570,7 +578,7 @@ sk_sp<PaintFilter> DropShadowPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<DropShadowPaintFilter>( dx_, dy_, sigma_x_, sigma_y_, color_, shadow_mode_, - Snapshot(input_, image_provider), crop_rect()); + Snapshot(input_, image_provider), GetCropRect()); } bool DropShadowPaintFilter::operator==( @@ -607,7 +615,7 @@ size_t MagnifierPaintFilter::SerializedSize() const { sk_sp<PaintFilter> MagnifierPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<MagnifierPaintFilter>( - src_rect_, inset_, Snapshot(input_, image_provider), crop_rect()); + src_rect_, inset_, Snapshot(input_, image_provider), GetCropRect()); } bool MagnifierPaintFilter::operator==(const MagnifierPaintFilter& other) const { @@ -676,7 +684,7 @@ sk_sp<PaintFilter> AlphaThresholdPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<AlphaThresholdPaintFilter>(region_, inner_min_, outer_max_, Snapshot(input_, image_provider), - crop_rect()); + GetCropRect()); } bool AlphaThresholdPaintFilter::operator==( @@ -717,7 +725,7 @@ sk_sp<PaintFilter> XfermodePaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<XfermodePaintFilter>( blend_mode_, Snapshot(background_, image_provider), - Snapshot(foreground_, image_provider), crop_rect()); + Snapshot(foreground_, image_provider), GetCropRect()); } bool XfermodePaintFilter::operator==(const XfermodePaintFilter& other) const { @@ -766,7 +774,7 @@ sk_sp<PaintFilter> ArithmeticPaintFilter::SnapshotWithImagesInternal( return sk_make_sp<ArithmeticPaintFilter>( k1_, k2_, k3_, k4_, enforce_pm_color_, Snapshot(background_, image_provider), - Snapshot(foreground_, image_provider), crop_rect()); + Snapshot(foreground_, image_provider), GetCropRect()); } bool ArithmeticPaintFilter::operator==( @@ -824,7 +832,7 @@ sk_sp<PaintFilter> MatrixConvolutionPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<MatrixConvolutionPaintFilter>( kernel_size_, &kernel_[0], gain_, bias_, kernel_offset_, tile_mode_, - convolve_alpha_, Snapshot(input_, image_provider), crop_rect()); + convolve_alpha_, Snapshot(input_, image_provider), GetCropRect()); } bool MatrixConvolutionPaintFilter::operator==( @@ -876,7 +884,7 @@ sk_sp<PaintFilter> DisplacementMapEffectPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<DisplacementMapEffectPaintFilter>( channel_x_, channel_y_, scale_, Snapshot(displacement_, image_provider), - Snapshot(color_, image_provider), crop_rect()); + Snapshot(color_, image_provider), GetCropRect()); } bool DisplacementMapEffectPaintFilter::operator==( @@ -1087,7 +1095,7 @@ size_t MergePaintFilter::SerializedSize() const { sk_sp<PaintFilter> MergePaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_sp<MergePaintFilter>(new MergePaintFilter( - &inputs_[0], inputs_->size(), crop_rect(), image_provider)); + &inputs_[0], inputs_->size(), GetCropRect(), image_provider)); } bool MergePaintFilter::operator==(const MergePaintFilter& other) const { @@ -1136,7 +1144,7 @@ sk_sp<PaintFilter> MorphologyPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<MorphologyPaintFilter>(morph_type_, radius_x_, radius_y_, Snapshot(input_, image_provider), - crop_rect()); + GetCropRect()); } bool MorphologyPaintFilter::operator==( @@ -1170,7 +1178,7 @@ size_t OffsetPaintFilter::SerializedSize() const { sk_sp<PaintFilter> OffsetPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<OffsetPaintFilter>( - dx_, dy_, Snapshot(input_, image_provider), crop_rect()); + dx_, dy_, Snapshot(input_, image_provider), GetCropRect()); } bool OffsetPaintFilter::operator==(const OffsetPaintFilter& other) const { @@ -1254,7 +1262,7 @@ sk_sp<PaintFilter> TurbulencePaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<TurbulencePaintFilter>(turbulence_type_, base_frequency_x_, base_frequency_y_, num_octaves_, - seed_, &tile_size_, crop_rect()); + seed_, &tile_size_, GetCropRect()); } bool TurbulencePaintFilter::operator==( @@ -1320,11 +1328,11 @@ sk_sp<PaintFilter> ShaderPaintFilter::SnapshotWithImagesInternal( return sk_make_sp<ShaderPaintFilter>( sk_ref_sp(snapshot->getShader()), snapshot->getAlpha(), snapshot->getFilterQuality(), - snapshot->isDither() ? Dither::kYes : Dither::kNo, crop_rect()); + snapshot->isDither() ? Dither::kYes : Dither::kNo, GetCropRect()); } else { // If decode failed, then just fallback to the solid color return sk_make_sp<ShaderPaintFilter>(nullptr, alpha_, filter_quality_, - dither_, crop_rect()); + dither_, GetCropRect()); } } @@ -1413,7 +1421,7 @@ sk_sp<PaintFilter> LightingDistantPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<LightingDistantPaintFilter>( lighting_type_, direction_, light_color_, surface_scale_, kconstant_, - shininess_, Snapshot(input_, image_provider), crop_rect()); + shininess_, Snapshot(input_, image_provider), GetCropRect()); } bool LightingDistantPaintFilter::operator==( @@ -1472,7 +1480,7 @@ sk_sp<PaintFilter> LightingPointPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<LightingPointPaintFilter>( lighting_type_, location_, light_color_, surface_scale_, kconstant_, - shininess_, Snapshot(input_, image_provider), crop_rect()); + shininess_, Snapshot(input_, image_provider), GetCropRect()); } bool LightingPointPaintFilter::operator==( @@ -1540,7 +1548,7 @@ sk_sp<PaintFilter> LightingSpotPaintFilter::SnapshotWithImagesInternal( return sk_make_sp<LightingSpotPaintFilter>( lighting_type_, location_, target_, specular_exponent_, cutoff_angle_, light_color_, surface_scale_, kconstant_, shininess_, - Snapshot(input_, image_provider), crop_rect()); + Snapshot(input_, image_provider), GetCropRect()); } bool LightingSpotPaintFilter::operator==( @@ -1621,7 +1629,7 @@ sk_sp<PaintFilter> StretchPaintFilter::SnapshotWithImagesInternal( ImageProvider* image_provider) const { return sk_make_sp<StretchPaintFilter>(stretch_x_, stretch_y_, width_, height_, Snapshot(input_, image_provider), - crop_rect()); + GetCropRect()); } bool StretchPaintFilter::operator==(const StretchPaintFilter& other) const { diff --git a/chromium/cc/paint/paint_filter.h b/chromium/cc/paint/paint_filter.h index 3f11012035e..93a456dff66 100644 --- a/chromium/cc/paint/paint_filter.h +++ b/chromium/cc/paint/paint_filter.h @@ -9,11 +9,9 @@ #include "base/check_op.h" #include "base/containers/stack_container.h" -#include "base/stl_util.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_image.h" #include "cc/paint/paint_shader.h" -#include "cc/paint/scoped_raster_flags.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "third_party/skia/include/core/SkImageFilter.h" @@ -96,9 +94,7 @@ class CC_PAINT_EXPORT PaintFilter : public SkRefCnt { return 0; return cached_sk_filter_->countInputs(); } - const CropRect* crop_rect() const { - return base::OptionalOrNullptr(crop_rect_); - } + const CropRect* GetCropRect() const; bool has_discardable_images() const { return has_discardable_images_; } ImageAnalysisState image_analysis_state() const { diff --git a/chromium/cc/paint/paint_filter_unittest.cc b/chromium/cc/paint/paint_filter_unittest.cc index ddb8ac02a52..a25d3fd9ba5 100644 --- a/chromium/cc/paint/paint_filter_unittest.cc +++ b/chromium/cc/paint/paint_filter_unittest.cc @@ -4,6 +4,7 @@ #include "cc/paint/paint_filter.h" +#include "cc/paint/image_provider.h" #include "cc/paint/paint_op_buffer.h" #include "cc/test/skia_common.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/cc/paint/paint_image.cc b/chromium/cc/paint/paint_image.cc index f9626c0063f..7a3b09d6968 100644 --- a/chromium/cc/paint/paint_image.cc +++ b/chromium/cc/paint/paint_image.cc @@ -316,7 +316,10 @@ int PaintImage::height() const { : GetSkImageInfo().height(); } -gfx::ContentColorUsage PaintImage::GetContentColorUsage() const { +gfx::ContentColorUsage PaintImage::GetContentColorUsage(bool* is_hlg) const { + if (is_hlg) + *is_hlg = false; + // Right now, JS paint worklets can only be in sRGB if (paint_worklet_input_) return gfx::ContentColorUsage::kSRGB; @@ -328,10 +331,15 @@ gfx::ContentColorUsage PaintImage::GetContentColorUsage() const { return gfx::ContentColorUsage::kSRGB; skcms_TransferFunction fn; - if (!color_space->isNumericalTransferFn(&fn) && - (skcms_TransferFunction_isPQish(&fn) || - skcms_TransferFunction_isHLGish(&fn))) { - return gfx::ContentColorUsage::kHDR; + if (!color_space->isNumericalTransferFn(&fn)) { + if (skcms_TransferFunction_isPQish(&fn)) + return gfx::ContentColorUsage::kHDR; + + if (skcms_TransferFunction_isHLGish(&fn)) { + if (is_hlg) + *is_hlg = true; + return gfx::ContentColorUsage::kHDR; + } } // If it's not HDR and not SRGB, report it as WCG. diff --git a/chromium/cc/paint/paint_image.h b/chromium/cc/paint/paint_image.h index 5b92f1d8ad1..d8973314810 100644 --- a/chromium/cc/paint/paint_image.h +++ b/chromium/cc/paint/paint_image.h @@ -282,7 +282,7 @@ class CC_PAINT_EXPORT PaintImage { return paint_worklet_input_ ? nullptr : GetSkImageInfo().colorSpace(); } - gfx::ContentColorUsage GetContentColorUsage() const; + gfx::ContentColorUsage GetContentColorUsage(bool* is_hlg = nullptr) const; // Returns whether this image will be decoded and rendered from YUV data // and fills out |info|. |supported_data_types| indicates the bit depths and @@ -336,6 +336,7 @@ class CC_PAINT_EXPORT PaintImage { friend class PlaybackImageProvider; friend class DrawImageRectOp; friend class DrawImageOp; + friend class DrawSkottieOp; // TODO(crbug.com/1031051): Remove these once GetSkImage() // is fully removed. diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc index 257f290a70c..e8c9303555a 100644 --- a/chromium/cc/paint/paint_op_buffer.cc +++ b/chromium/cc/paint/paint_op_buffer.cc @@ -9,8 +9,9 @@ #include <utility> #include <vector> +#include "base/bind.h" +#include "base/memory/raw_ptr.h" #include "base/stl_util.h" -#include "build/build_config.h" #include "cc/paint/decoded_draw_image.h" #include "cc/paint/display_item_list.h" #include "cc/paint/image_provider.h" @@ -20,14 +21,15 @@ #include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" #include "cc/paint/scoped_raster_flags.h" -#include "cc/paint/skottie_wrapper.h" #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRegion.h" #include "third_party/skia/include/core/SkSerialProcs.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/docs/SkPDFDocument.h" #include "third_party/skia/include/gpu/GrRecordingContext.h" +#include "third_party/skia/include/private/chromium/GrSlug.h" #include "ui/gfx/geometry/skia_conversions.h" namespace cc { @@ -361,7 +363,8 @@ PaintOp::SerializeOptions::SerializeOptions( sk_sp<SkColorSpace> color_space, bool can_use_lcd_text, bool context_supports_distance_field_text, - int max_texture_size) + int max_texture_size, + bool raw_draw) : image_provider(image_provider), transfer_cache(transfer_cache), paint_cache(paint_cache), @@ -370,7 +373,8 @@ PaintOp::SerializeOptions::SerializeOptions( can_use_lcd_text(can_use_lcd_text), context_supports_distance_field_text( context_supports_distance_field_text), - max_texture_size(max_texture_size) {} + max_texture_size(max_texture_size), + raw_draw(raw_draw) {} PaintOp::SerializeOptions::SerializeOptions() = default; PaintOp::SerializeOptions::SerializeOptions(const SerializeOptions&) = default; @@ -691,19 +695,29 @@ size_t DrawSkottieOp::Serialize(const PaintOp* base_op, const PaintFlags* flags_to_serialize, const SkM44& current_ctm, const SkM44& original_ctm) { -#if defined(OS_ANDROID) - // Skottie is not used in android, so to keep apk size small it is excluded - // from the build. - NOTREACHED(); - return 0u; -#else auto* op = static_cast<const DrawSkottieOp*>(base_op); PaintOpWriter helper(memory, size, options); helper.Write(op->dst); helper.Write(SkFloatToScalar(op->t)); helper.Write(op->skottie); + // Write number of images in the map first so that we know how many images to + // read from the buffer during deserialization. + helper.WriteSize(op->images.size()); + for (const auto& image_asset_pair : op->images) { + const SkottieResourceIdHash& asset_id_hash = image_asset_pair.first; + const SkottieFrameData& frame_data = image_asset_pair.second; + helper.WriteSize(asset_id_hash.GetUnsafeValue()); + // |scale_adjustment| is not ultimately used; Skottie handles image scale + // adjustment internally when rastering. + SkSize scale_adjustment = SkSize::MakeEmpty(); + helper.Write(DrawImage(frame_data.image, /*use_dark_mode=*/false, + SkIRect::MakeWH(frame_data.image.width(), + frame_data.image.height()), + frame_data.quality, current_ctm), + &scale_adjustment); + helper.Write(frame_data.quality); + } return helper.size(); -#endif // OS_ANDROID } size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, @@ -722,6 +736,9 @@ size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, helper.Write(op->x); helper.Write(op->y); helper.Write(op->blob); + helper.Write(options.raw_draw); + if (options.raw_draw) + helper.Write(current_ctm.asM33()); return helper.size(); } @@ -862,25 +879,76 @@ void UpdateTypeAndSkip(T* op) { op->skip = PaintOpBuffer::ComputeOpSkip(sizeof(T)); } +template <typename T> +class PaintOpDeserializer { + public: + static_assert(std::is_convertible<T, PaintOp>::value, "T not a PaintOp."); + + explicit PaintOpDeserializer(const volatile void* input, + size_t input_size, + const PaintOp::DeserializeOptions& options, + T* op) + : reader_(input, input_size, options), op_(op) { + DCHECK(op_); + } + PaintOpDeserializer(const PaintOpDeserializer&) = delete; + PaintOpDeserializer& operator=(const PaintOpDeserializer&) = delete; + + ~PaintOpDeserializer() { + DCHECK(!op_) + << "FinalizeOp must be called before PaintOpDeserializer is destroyed. " + "type=" + << T::kType; + } + + PaintOp* FinalizeOp(bool force_invalid = false) { + DCHECK(op_) << "PaintOp has already been finalized. type=" << T::kType; + + if (force_invalid || !reader_.valid() || !op_->IsValid()) { + op_->~T(); + op_ = nullptr; + return nullptr; + } + + UpdateTypeAndSkip(op_.get()); + T* op_snapshot = op_; + op_ = nullptr; + return op_snapshot; + } + + PaintOp* InvalidateAndFinalizeOp() { + return FinalizeOp(/*force_invalid=*/true); + } + + T* operator->() { return op_; } + + template <typename... Args> + void Read(Args&&... args) { + reader_.Read(std::forward<Args>(args)...); + } + + void ReadSize(size_t* size) { reader_.ReadSize(size); } + + void AlignMemory(size_t alignment) { reader_.AlignMemory(alignment); } + + private: + PaintOpReader reader_; + raw_ptr<T> op_; +}; + PaintOp* AnnotateOp::Deserialize(const volatile void* input, size_t input_size, void* output, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(AnnotateOp)); - AnnotateOp* op = new (output) AnnotateOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->annotation_type); - helper.Read(&op->rect); - helper.Read(&op->data); - if (!helper.valid() || !op->IsValid()) { - op->~AnnotateOp(); - return nullptr; - } + PaintOpDeserializer<AnnotateOp> deserializer(input, input_size, options, + new (output) AnnotateOp); - UpdateTypeAndSkip(op); - return op; + deserializer.Read(&deserializer->annotation_type); + deserializer.Read(&deserializer->rect); + deserializer.Read(&deserializer->data); + return deserializer.FinalizeOp(); } PaintOp* ClipPathOp::Deserialize(const volatile void* input, @@ -889,19 +957,13 @@ PaintOp* ClipPathOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipPathOp)); - ClipPathOp* op = new (output) ClipPathOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->path); - helper.Read(&op->op); - helper.Read(&op->antialias); - if (!helper.valid() || !op->IsValid()) { - op->~ClipPathOp(); - return nullptr; - } + PaintOpDeserializer<ClipPathOp> deserializer(input, input_size, options, + new (output) ClipPathOp); - UpdateTypeAndSkip(op); - return op; + deserializer.Read(&deserializer->path); + deserializer.Read(&deserializer->op); + deserializer.Read(&deserializer->antialias); + return deserializer.FinalizeOp(); } PaintOp* ClipRectOp::Deserialize(const volatile void* input, @@ -910,19 +972,12 @@ PaintOp* ClipRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipRectOp)); - ClipRectOp* op = new (output) ClipRectOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->rect); - helper.Read(&op->op); - helper.Read(&op->antialias); - if (!helper.valid() || !op->IsValid()) { - op->~ClipRectOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<ClipRectOp> deserializer(input, input_size, options, + new (output) ClipRectOp); + deserializer.Read(&deserializer->rect); + deserializer.Read(&deserializer->op); + deserializer.Read(&deserializer->antialias); + return deserializer.FinalizeOp(); } PaintOp* ClipRRectOp::Deserialize(const volatile void* input, @@ -931,19 +986,12 @@ PaintOp* ClipRRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipRRectOp)); - ClipRRectOp* op = new (output) ClipRRectOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->rrect); - helper.Read(&op->op); - helper.Read(&op->antialias); - if (!helper.valid() || !op->IsValid()) { - op->~ClipRRectOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<ClipRRectOp> deserializer(input, input_size, options, + new (output) ClipRRectOp); + deserializer.Read(&deserializer->rrect); + deserializer.Read(&deserializer->op); + deserializer.Read(&deserializer->antialias); + return deserializer.FinalizeOp(); } PaintOp* ConcatOp::Deserialize(const volatile void* input, @@ -952,17 +1000,10 @@ PaintOp* ConcatOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ConcatOp)); - ConcatOp* op = new (output) ConcatOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->matrix); - if (!helper.valid() || !op->IsValid()) { - op->~ConcatOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<ConcatOp> deserializer(input, input_size, options, + new (output) ConcatOp); + deserializer.Read(&deserializer->matrix); + return deserializer.FinalizeOp(); } PaintOp* CustomDataOp::Deserialize(const volatile void* input, @@ -971,17 +1012,10 @@ PaintOp* CustomDataOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(CustomDataOp)); - CustomDataOp* op = new (output) CustomDataOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->id); - if (!helper.valid() || !op->IsValid()) { - op->~CustomDataOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<CustomDataOp> deserializer(input, input_size, options, + new (output) CustomDataOp); + deserializer.Read(&deserializer->id); + return deserializer.FinalizeOp(); } PaintOp* DrawColorOp::Deserialize(const volatile void* input, @@ -990,18 +1024,11 @@ PaintOp* DrawColorOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawColorOp)); - DrawColorOp* op = new (output) DrawColorOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->color); - helper.Read(&op->mode); - if (!helper.valid() || !op->IsValid()) { - op->~DrawColorOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawColorOp> deserializer(input, input_size, options, + new (output) DrawColorOp); + deserializer.Read(&deserializer->color); + deserializer.Read(&deserializer->mode); + return deserializer.FinalizeOp(); } PaintOp* DrawDRRectOp::Deserialize(const volatile void* input, @@ -1010,18 +1037,12 @@ PaintOp* DrawDRRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawDRRectOp)); - DrawDRRectOp* op = new (output) DrawDRRectOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->outer); - helper.Read(&op->inner); - if (!helper.valid() || !op->IsValid()) { - op->~DrawDRRectOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawDRRectOp> deserializer(input, input_size, options, + new (output) DrawDRRectOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->outer); + deserializer.Read(&deserializer->inner); + return deserializer.FinalizeOp(); } PaintOp* DrawImageOp::Deserialize(const volatile void* input, @@ -1030,25 +1051,19 @@ PaintOp* DrawImageOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawImageOp)); - DrawImageOp* op = new (output) DrawImageOp; + PaintOpDeserializer<DrawImageOp> deserializer(input, input_size, options, + new (output) DrawImageOp); + deserializer.Read(&deserializer->flags); - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); + deserializer.Read(&deserializer->image); + deserializer.AlignMemory(alignof(SkScalar)); + deserializer.Read(&deserializer->scale_adjustment.fWidth); + deserializer.Read(&deserializer->scale_adjustment.fHeight); - helper.Read(&op->image); - helper.AlignMemory(alignof(SkScalar)); - helper.Read(&op->scale_adjustment.fWidth); - helper.Read(&op->scale_adjustment.fHeight); - - helper.Read(&op->left); - helper.Read(&op->top); - helper.Read(&op->sampling); - if (!helper.valid() || !op->IsValid()) { - op->~DrawImageOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + deserializer.Read(&deserializer->left); + deserializer.Read(&deserializer->top); + deserializer.Read(&deserializer->sampling); + return deserializer.FinalizeOp(); } PaintOp* DrawImageRectOp::Deserialize(const volatile void* input, @@ -1057,26 +1072,20 @@ PaintOp* DrawImageRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawImageRectOp)); - DrawImageRectOp* op = new (output) DrawImageRectOp; + PaintOpDeserializer<DrawImageRectOp> deserializer( + input, input_size, options, new (output) DrawImageRectOp); + deserializer.Read(&deserializer->flags); - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); + deserializer.Read(&deserializer->image); + deserializer.AlignMemory(alignof(SkScalar)); + deserializer.Read(&deserializer->scale_adjustment.fWidth); + deserializer.Read(&deserializer->scale_adjustment.fHeight); - helper.Read(&op->image); - helper.AlignMemory(alignof(SkScalar)); - helper.Read(&op->scale_adjustment.fWidth); - helper.Read(&op->scale_adjustment.fHeight); - - helper.Read(&op->src); - helper.Read(&op->dst); - helper.Read(&op->sampling); - helper.Read(&op->constraint); - if (!helper.valid() || !op->IsValid()) { - op->~DrawImageRectOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + deserializer.Read(&deserializer->src); + deserializer.Read(&deserializer->dst); + deserializer.Read(&deserializer->sampling); + deserializer.Read(&deserializer->constraint); + return deserializer.FinalizeOp(); } PaintOp* DrawIRectOp::Deserialize(const volatile void* input, @@ -1085,17 +1094,11 @@ PaintOp* DrawIRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawIRectOp)); - DrawIRectOp* op = new (output) DrawIRectOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->rect); - if (!helper.valid() || !op->IsValid()) { - op->~DrawIRectOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawIRectOp> deserializer(input, input_size, options, + new (output) DrawIRectOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->rect); + return deserializer.FinalizeOp(); } PaintOp* DrawLineOp::Deserialize(const volatile void* input, @@ -1104,21 +1107,15 @@ PaintOp* DrawLineOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawLineOp)); - DrawLineOp* op = new (output) DrawLineOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.AlignMemory(alignof(SkScalar)); - helper.Read(&op->x0); - helper.Read(&op->y0); - helper.Read(&op->x1); - helper.Read(&op->y1); - if (!helper.valid() || !op->IsValid()) { - op->~DrawLineOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawLineOp> deserializer(input, input_size, options, + new (output) DrawLineOp); + deserializer.Read(&deserializer->flags); + deserializer.AlignMemory(alignof(SkScalar)); + deserializer.Read(&deserializer->x0); + deserializer.Read(&deserializer->y0); + deserializer.Read(&deserializer->x1); + deserializer.Read(&deserializer->y1); + return deserializer.FinalizeOp(); } PaintOp* DrawOvalOp::Deserialize(const volatile void* input, @@ -1127,17 +1124,11 @@ PaintOp* DrawOvalOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawOvalOp)); - DrawOvalOp* op = new (output) DrawOvalOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->oval); - if (!helper.valid() || !op->IsValid()) { - op->~DrawOvalOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawOvalOp> deserializer(input, input_size, options, + new (output) DrawOvalOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->oval); + return deserializer.FinalizeOp(); } PaintOp* DrawPathOp::Deserialize(const volatile void* input, @@ -1146,19 +1137,14 @@ PaintOp* DrawPathOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawPathOp)); - DrawPathOp* op = new (output) DrawPathOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->path); - helper.Read(&op->sk_path_fill_type); - op->path.setFillType(static_cast<SkPathFillType>(op->sk_path_fill_type)); - if (!helper.valid() || !op->IsValid()) { - op->~DrawPathOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawPathOp> deserializer(input, input_size, options, + new (output) DrawPathOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->path); + deserializer.Read(&deserializer->sk_path_fill_type); + deserializer->path.setFillType( + static_cast<SkPathFillType>(deserializer->sk_path_fill_type)); + return deserializer.FinalizeOp(); } PaintOp* DrawRecordOp::Deserialize(const volatile void* input, @@ -1177,17 +1163,11 @@ PaintOp* DrawRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawRectOp)); - DrawRectOp* op = new (output) DrawRectOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->rect); - if (!helper.valid() || !op->IsValid()) { - op->~DrawRectOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawRectOp> deserializer(input, input_size, options, + new (output) DrawRectOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->rect); + return deserializer.FinalizeOp(); } PaintOp* DrawRRectOp::Deserialize(const volatile void* input, @@ -1196,17 +1176,11 @@ PaintOp* DrawRRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawRRectOp)); - DrawRRectOp* op = new (output) DrawRRectOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->rrect); - if (!helper.valid() || !op->IsValid()) { - op->~DrawRRectOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<DrawRRectOp> deserializer(input, input_size, options, + new (output) DrawRRectOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->rrect); + return deserializer.FinalizeOp(); } PaintOp* DrawSkottieOp::Deserialize(const volatile void* input, @@ -1214,30 +1188,55 @@ PaintOp* DrawSkottieOp::Deserialize(const volatile void* input, void* output, size_t output_size, const DeserializeOptions& options) { -#if defined(OS_ANDROID) - // Skottie is not used on Android. To keep apk size small the skottie library - // is excluded from the binary. - return nullptr; -#else DCHECK_GE(output_size, sizeof(DrawSkottieOp)); - DrawSkottieOp* op = new (output) DrawSkottieOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->dst); + PaintOpDeserializer<DrawSkottieOp> deserializer(input, input_size, options, + new (output) DrawSkottieOp); + deserializer.Read(&deserializer->dst); SkScalar t; - helper.Read(&t); - op->t = SkScalarToFloat(t); - - helper.Read(&op->skottie); - - if (!helper.valid() || !op->IsValid()) { - op->~DrawSkottieOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; -#endif // OS_ANDROID + deserializer.Read(&t); + deserializer->t = SkScalarToFloat(t); + + deserializer.Read(&deserializer->skottie); + // The |skottie| object gets used below, so no point in continuing if it's + // invalid. That can lead to crashing or unexpected behavior. + if (!deserializer->skottie || !deserializer->skottie->is_valid()) + return deserializer.InvalidateAndFinalizeOp(); + + size_t num_images = 0; + deserializer.ReadSize(&num_images); + // In the off chance that there's a bug or corruption in the underlying + // buffer, |num_images| may be some invalid enormous value. Sanity check it + // with the animation to prevent looping below for long periods of time if an + // unexpected error happens. + size_t num_assets_in_animation = + deserializer->skottie->GetImageAssetMetadata().asset_storage().size(); + if (num_images > num_assets_in_animation) + return deserializer.InvalidateAndFinalizeOp(); + + for (size_t i = 0; i < num_images; ++i) { + size_t asset_id_hash_raw = 0; + deserializer.ReadSize(&asset_id_hash_raw); + SkottieResourceIdHash asset_id_hash = + SkottieResourceIdHash::FromUnsafeValue(asset_id_hash_raw); + + SkottieFrameData frame_data; + deserializer.Read(&frame_data.image); + deserializer.Read(&frame_data.quality); + if (!asset_id_hash || !frame_data.image) + return deserializer.InvalidateAndFinalizeOp(); + + // If we've inserted a duplicate, that means the buffer specifies 2 + // different images for the same asset in this frame. This should not happen + // by design since |images| is a map with the asset id as the key. But + // defend against it gracefully in case the underlying buffer is corrupted. + bool new_entry = + deserializer->images.emplace(asset_id_hash, std::move(frame_data)) + .second; + if (!new_entry) + return deserializer.InvalidateAndFinalizeOp(); + } + return deserializer.FinalizeOp(); } PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input, @@ -1245,21 +1244,22 @@ PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input, void* output, size_t output_size, const DeserializeOptions& options) { - DCHECK_GE(output_size, sizeof(DrawTextBlobOp) - sizeof(NodeId)); - DrawTextBlobOp* op = new (output) DrawTextBlobOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.AlignMemory(alignof(SkScalar)); - helper.Read(&op->x); - helper.Read(&op->y); - helper.Read(&op->blob); - if (!helper.valid() || !op->IsValid()) { - op->~DrawTextBlobOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + DCHECK_GE(output_size, sizeof(DrawTextBlobOp)); + PaintOpDeserializer<DrawTextBlobOp> deserializer(input, input_size, options, + new (output) DrawTextBlobOp); + deserializer.Read(&deserializer->flags); + deserializer.AlignMemory(alignof(SkScalar)); + deserializer.Read(&deserializer->x); + deserializer.Read(&deserializer->y); + deserializer.Read(&deserializer->blob); + bool raw_draw = false; + deserializer.Read(&raw_draw); + if (raw_draw) { + SkMatrix hint; + deserializer.Read(&hint); + deserializer->hint = hint; + } + return deserializer.FinalizeOp(); } PaintOp* NoopOp::Deserialize(const volatile void* input, @@ -1268,16 +1268,9 @@ PaintOp* NoopOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(NoopOp)); - NoopOp* op = new (output) NoopOp; - - PaintOpReader helper(input, input_size, options); - if (!helper.valid() || !op->IsValid()) { - op->~NoopOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<NoopOp> deserializer(input, input_size, options, + new (output) NoopOp); + return deserializer.FinalizeOp(); } PaintOp* RestoreOp::Deserialize(const volatile void* input, @@ -1286,16 +1279,9 @@ PaintOp* RestoreOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(RestoreOp)); - RestoreOp* op = new (output) RestoreOp; - - PaintOpReader helper(input, input_size, options); - if (!helper.valid() || !op->IsValid()) { - op->~RestoreOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<RestoreOp> deserializer(input, input_size, options, + new (output) RestoreOp); + return deserializer.FinalizeOp(); } PaintOp* RotateOp::Deserialize(const volatile void* input, @@ -1304,17 +1290,10 @@ PaintOp* RotateOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(RotateOp)); - RotateOp* op = new (output) RotateOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->degrees); - if (!helper.valid() || !op->IsValid()) { - op->~RotateOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<RotateOp> deserializer(input, input_size, options, + new (output) RotateOp); + deserializer.Read(&deserializer->degrees); + return deserializer.FinalizeOp(); } PaintOp* SaveOp::Deserialize(const volatile void* input, @@ -1323,16 +1302,9 @@ PaintOp* SaveOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveOp)); - SaveOp* op = new (output) SaveOp; - - PaintOpReader helper(input, input_size, options); - if (!helper.valid() || !op->IsValid()) { - op->~SaveOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<SaveOp> deserializer(input, input_size, options, + new (output) SaveOp); + return deserializer.FinalizeOp(); } PaintOp* SaveLayerOp::Deserialize(const volatile void* input, @@ -1341,17 +1313,11 @@ PaintOp* SaveLayerOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveLayerOp)); - SaveLayerOp* op = new (output) SaveLayerOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->flags); - helper.Read(&op->bounds); - if (!helper.valid() || !op->IsValid()) { - op->~SaveLayerOp(); - return nullptr; - } - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<SaveLayerOp> deserializer(input, input_size, options, + new (output) SaveLayerOp); + deserializer.Read(&deserializer->flags); + deserializer.Read(&deserializer->bounds); + return deserializer.FinalizeOp(); } PaintOp* SaveLayerAlphaOp::Deserialize(const volatile void* input, @@ -1360,18 +1326,11 @@ PaintOp* SaveLayerAlphaOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveLayerAlphaOp)); - SaveLayerAlphaOp* op = new (output) SaveLayerAlphaOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->bounds); - helper.Read(&op->alpha); - if (!helper.valid() || !op->IsValid()) { - op->~SaveLayerAlphaOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<SaveLayerAlphaOp> deserializer( + input, input_size, options, new (output) SaveLayerAlphaOp); + deserializer.Read(&deserializer->bounds); + deserializer.Read(&deserializer->alpha); + return deserializer.FinalizeOp(); } PaintOp* ScaleOp::Deserialize(const volatile void* input, @@ -1380,18 +1339,11 @@ PaintOp* ScaleOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ScaleOp)); - ScaleOp* op = new (output) ScaleOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->sx); - helper.Read(&op->sy); - if (!helper.valid() || !op->IsValid()) { - op->~ScaleOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<ScaleOp> deserializer(input, input_size, options, + new (output) ScaleOp); + deserializer.Read(&deserializer->sx); + deserializer.Read(&deserializer->sy); + return deserializer.FinalizeOp(); } PaintOp* SetMatrixOp::Deserialize(const volatile void* input, @@ -1400,17 +1352,10 @@ PaintOp* SetMatrixOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SetMatrixOp)); - SetMatrixOp* op = new (output) SetMatrixOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->matrix); - if (!helper.valid() || !op->IsValid()) { - op->~SetMatrixOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<SetMatrixOp> deserializer(input, input_size, options, + new (output) SetMatrixOp); + deserializer.Read(&deserializer->matrix); + return deserializer.FinalizeOp(); } PaintOp* SetNodeIdOp::Deserialize(const volatile void* input, @@ -1419,17 +1364,10 @@ PaintOp* SetNodeIdOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SetNodeIdOp)); - SetNodeIdOp* op = new (output) SetNodeIdOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->node_id); - if (!helper.valid() || !op->IsValid()) { - op->~SetNodeIdOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<SetNodeIdOp> deserializer(input, input_size, options, + new (output) SetNodeIdOp); + deserializer.Read(&deserializer->node_id); + return deserializer.FinalizeOp(); } PaintOp* TranslateOp::Deserialize(const volatile void* input, @@ -1438,18 +1376,11 @@ PaintOp* TranslateOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(TranslateOp)); - TranslateOp* op = new (output) TranslateOp; - - PaintOpReader helper(input, input_size, options); - helper.Read(&op->dx); - helper.Read(&op->dy); - if (!helper.valid() || !op->IsValid()) { - op->~TranslateOp(); - return nullptr; - } - - UpdateTypeAndSkip(op); - return op; + PaintOpDeserializer<TranslateOp> deserializer(input, input_size, options, + new (output) TranslateOp); + deserializer.Read(&deserializer->dx); + deserializer.Read(&deserializer->dy); + return deserializer.FinalizeOp(); } void AnnotateOp::Raster(const AnnotateOp* op, @@ -1722,7 +1653,51 @@ void DrawRRectOp::RasterWithFlags(const DrawRRectOp* op, void DrawSkottieOp::Raster(const DrawSkottieOp* op, SkCanvas* canvas, const PlaybackParams& params) { - op->skottie->Draw(canvas, op->t, op->dst); + // Binding unretained references in the callback is safe because Draw()'s API + // guarantees that the callback is invoked synchronously. + op->skottie->Draw( + canvas, op->t, op->dst, + base::BindRepeating(&DrawSkottieOp::GetImageAssetForRaster, + base::Unretained(op), canvas, std::cref(params))); +} + +SkottieWrapper::FrameDataFetchResult DrawSkottieOp::GetImageAssetForRaster( + SkCanvas* canvas, + const PlaybackParams& params, + SkottieResourceIdHash asset_id, + float t_frame, + sk_sp<SkImage>& sk_image, + SkSamplingOptions& sampling_out) const { + auto images_iter = images.find(asset_id); + if (images_iter == images.end()) + return SkottieWrapper::FrameDataFetchResult::NO_UPDATE; + + const SkottieFrameData& frame_data = images_iter->second; + if (params.image_provider) { + // There is no use case for applying dark mode filters to skottie images + // currently. + DrawImage draw_image( + frame_data.image, /*use_dark_mode=*/false, + SkIRect::MakeWH(frame_data.image.width(), frame_data.image.height()), + frame_data.quality, canvas->getLocalToDevice()); + auto scoped_result = params.image_provider->GetRasterContent(draw_image); + if (scoped_result) { + sk_image = scoped_result.decoded_image().image(); + DCHECK(sk_image); + } + } else { + if (frame_data.image.IsTextureBacked()) { + sk_image = frame_data.image.GetAcceleratedSkImage(); + DCHECK(sk_image || !canvas->recordingContext()); + } + if (!sk_image) + sk_image = frame_data.image.GetSwSkImage(); + } + DCHECK(sk_image) << "Failed to fetch SkImage for Skottie image asset " + << asset_id; + sampling_out = + PaintFlags::FilterQualityToSkSamplingOptions(frame_data.quality); + return SkottieWrapper::FrameDataFetchResult::NEW_DATA_AVAILABLE; } void DrawTextBlobOp::RasterWithFlags(const DrawTextBlobOp* op, @@ -1732,7 +1707,18 @@ void DrawTextBlobOp::RasterWithFlags(const DrawTextBlobOp* op, if (op->node_id) SkPDF::SetNodeId(canvas, op->node_id); flags->DrawToSk(canvas, [op](SkCanvas* c, const SkPaint& p) { - c->drawTextBlob(op->blob.get(), op->x, op->y, p); + if (op->hint) { + sk_sp<GrSlug> slug; + { + SkAutoCanvasRestore auto_save(c, true); + c->setMatrix(*op->hint); + slug = GrSlug::ConvertBlob(c, *op->blob, {op->x, op->y}, p); + } + if (slug) + slug->draw(c); + } else { + c->drawTextBlob(op->blob.get(), op->x, op->y, p); + } }); if (op->node_id) SkPDF::SetNodeId(canvas, 0); @@ -2149,6 +2135,24 @@ bool DrawSkottieOp::AreEqual(const PaintOp* base_left, return false; if (!AreSkRectsEqual(left->dst, right->dst)) return false; + if (left->images.size() != right->images.size()) + return false; + + auto left_iter = left->images.begin(); + auto right_iter = right->images.begin(); + for (; left_iter != left->images.end(); ++left_iter, ++right_iter) { + if (left_iter->first != right_iter->first || + // PaintImage's comparison operator compares the underlying SkImage's + // pointer address. This does not necessarily hold in cases where the + // image's content may be the same, but it got realloacted to a + // different spot somewhere in memory via the transfer cache. The next + // best thing is to just compare the dimensions of the PaintImage. + left_iter->second.image.width() != right_iter->second.image.width() || + left_iter->second.image.height() != right_iter->second.image.height() || + left_iter->second.quality != right_iter->second.quality) { + return false; + } + } return true; } @@ -2513,6 +2517,9 @@ bool PaintOp::OpHasDiscardableImages(const PaintOp* op) { } else if (op->GetType() == PaintOpType::DrawRecord && static_cast<const DrawRecordOp*>(op)->HasDiscardableImages()) { return true; + } else if (op->GetType() == PaintOpType::DrawSkottie && + static_cast<const DrawSkottieOp*>(op)->HasDiscardableImages()) { + return true; } return false; @@ -2678,13 +2685,22 @@ size_t DrawRecordOp::AdditionalOpCount() const { DrawSkottieOp::DrawSkottieOp(scoped_refptr<SkottieWrapper> skottie, SkRect dst, - float t) - : PaintOp(kType), skottie(std::move(skottie)), dst(dst), t(t) {} + float t, + SkottieFrameDataMap images) + : PaintOp(kType), + skottie(std::move(skottie)), + dst(dst), + t(t), + images(std::move(images)) {} DrawSkottieOp::DrawSkottieOp() : PaintOp(kType) {} DrawSkottieOp::~DrawSkottieOp() = default; +bool DrawSkottieOp::HasDiscardableImages() const { + return !images.empty(); +} + bool DrawRecordOp::HasDiscardableImages() const { return record->HasDiscardableImages(); } diff --git a/chromium/cc/paint/paint_op_buffer.h b/chromium/cc/paint/paint_op_buffer.h index 43450190698..b375ad49ac1 100644 --- a/chromium/cc/paint/paint_op_buffer.h +++ b/chromium/cc/paint/paint_op_buffer.h @@ -16,9 +16,11 @@ #include "base/callback.h" #include "base/check_op.h" +#include "base/containers/flat_map.h" #include "base/containers/stack_container.h" #include "base/debug/alias.h" #include "base/memory/aligned_memory.h" +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/notreached.h" #include "cc/base/math_util.h" @@ -26,14 +28,19 @@ #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_flags.h" +#include "cc/paint/skottie_frame_data.h" +#include "cc/paint/skottie_resource_metadata.h" +#include "cc/paint/skottie_wrapper.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkScalar.h" #include "ui/gfx/geometry/rect.h" class SkColorSpace; +class SkImage; class SkStrikeClient; class SkStrikeServer; class SkTextBlob; @@ -44,7 +51,6 @@ namespace cc { class ClientPaintCache; class ImageProvider; class ServicePaintCache; -class SkottieWrapper; class TransferCacheDeserializeHelper; class TransferCacheSerializeHelper; @@ -134,7 +140,10 @@ struct CC_PAINT_EXPORT PlaybackParams { PlaybackParams(const PlaybackParams& other); PlaybackParams& operator=(const PlaybackParams& other); + // `image_provider` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). ImageProvider* image_provider; + SkM44 original_ctm; CustomDataRasterCallback custom_callback; DidDrawOpCallback did_draw_op_callback; @@ -170,20 +179,22 @@ class CC_PAINT_EXPORT PaintOp { sk_sp<SkColorSpace> color_space, bool can_use_lcd_text, bool context_supports_distance_field_text, - int max_texture_size); + int max_texture_size, + bool raw_draw = false); SerializeOptions(const SerializeOptions&); SerializeOptions& operator=(const SerializeOptions&); ~SerializeOptions(); // Required. - ImageProvider* image_provider = nullptr; - TransferCacheSerializeHelper* transfer_cache = nullptr; - ClientPaintCache* paint_cache = nullptr; - SkStrikeServer* strike_server = nullptr; + raw_ptr<ImageProvider> image_provider = nullptr; + raw_ptr<TransferCacheSerializeHelper> transfer_cache = nullptr; + raw_ptr<ClientPaintCache> paint_cache = nullptr; + raw_ptr<SkStrikeServer> strike_server = nullptr; sk_sp<SkColorSpace> color_space = nullptr; bool can_use_lcd_text = false; bool context_supports_distance_field_text = true; int max_texture_size = 0; + bool raw_draw = false; // TODO(crbug.com/1096123): Cleanup after study completion. // @@ -797,7 +808,10 @@ class CC_PAINT_EXPORT DrawSkottieOp final : public PaintOp { public: static constexpr PaintOpType kType = PaintOpType::DrawSkottie; static constexpr bool kIsDrawOp = true; - DrawSkottieOp(scoped_refptr<SkottieWrapper> skottie, SkRect dst, float t); + DrawSkottieOp(scoped_refptr<SkottieWrapper> skottie, + SkRect dst, + float t, + SkottieFrameDataMap images); ~DrawSkottieOp(); static void Raster(const DrawSkottieOp* op, SkCanvas* canvas, @@ -806,16 +820,33 @@ class CC_PAINT_EXPORT DrawSkottieOp final : public PaintOp { return !!skottie && !dst.isEmpty() && t >= 0 && t <= 1.f; } static bool AreEqual(const PaintOp* left, const PaintOp* right); + bool HasDiscardableImages() const; HAS_SERIALIZATION_FUNCTIONS(); scoped_refptr<SkottieWrapper> skottie; SkRect dst; float t; + // Image to use for each asset in this frame of the animation. If an asset is + // missing, the most recently used image for that asset (from a previous + // DrawSkottieOp) gets reused when rendering this frame. Given that image + // assets generally do not change from frame to frame in most animations, that + // means in practice, this map is often empty. + SkottieFrameDataMap images; private: + SkottieWrapper::FrameDataFetchResult GetImageAssetForRaster( + SkCanvas* canvas, + const PlaybackParams& params, + SkottieResourceIdHash asset_id, + float t_frame, + sk_sp<SkImage>& image_out, + SkSamplingOptions& sampling_out) const; + DrawSkottieOp(); }; +// TODO(penghuang): Replace DrawTextBlobOp with DrawSlugOp, when GrSlug can be +// serialized. class CC_PAINT_EXPORT DrawTextBlobOp final : public PaintOpWithFlags { public: static constexpr PaintOpType kType = PaintOpType::DrawTextBlob; @@ -844,6 +875,7 @@ class CC_PAINT_EXPORT DrawTextBlobOp final : public PaintOpWithFlags { SkScalar y; // This field isn't serialized. NodeId node_id = kInvalidNodeId; + absl::optional<SkMatrix> hint; private: DrawTextBlobOp(); @@ -1223,8 +1255,11 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { DCHECK(!buffer->are_ops_destroyed()); } + // `buffer_` and `ptr_` are not a raw_ptr<...> for performance reasons + // (based on analysis of sampling profiler data and tab_search:top100:2020). const PaintOpBuffer* buffer_ = nullptr; char* ptr_ = nullptr; + size_t op_offset_ = 0; }; @@ -1288,9 +1323,13 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { DCHECK(!buffer->are_ops_destroyed()); } + // `buffer_`, `ptr_`, and `offsets_` are not a raw_ptr<...> for performance + // reasons (based on analysis of sampling profiler data and + // tab_search:top100:2020). const PaintOpBuffer* buffer_ = nullptr; char* ptr_ = nullptr; const std::vector<size_t>* offsets_; + size_t op_offset_ = 0; size_t offsets_index_ = 0; }; @@ -1363,7 +1402,11 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { // FIFO queue of paint ops that have been peeked at. base::StackVector<const PaintOp*, 3> stack_; DrawColorOp folded_draw_color_; + + // `current_op_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). const PaintOp* current_op_ = nullptr; + uint8_t current_alpha_ = 255; }; diff --git a/chromium/cc/paint/paint_op_buffer_serializer.h b/chromium/cc/paint/paint_op_buffer_serializer.h index 34863f62471..2684208c6aa 100644 --- a/chromium/cc/paint/paint_op_buffer_serializer.h +++ b/chromium/cc/paint/paint_op_buffer_serializer.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/paint/paint_op_buffer.h" #include "third_party/skia/src/core/SkRemoteGlyphCache.h" @@ -136,7 +137,7 @@ class CC_PAINT_EXPORT SimpleBufferSerializer : public PaintOpBufferSerializer { const SkM44& current_ctm, const SkM44& original_ctm); - void* memory_; + raw_ptr<void> memory_; const size_t total_; size_t written_ = 0u; }; diff --git a/chromium/cc/paint/paint_op_buffer_unittest.cc b/chromium/cc/paint/paint_op_buffer_unittest.cc index 476dfcfda6d..2bae382d497 100644 --- a/chromium/cc/paint/paint_op_buffer_unittest.cc +++ b/chromium/cc/paint/paint_op_buffer_unittest.cc @@ -8,9 +8,10 @@ #include "base/bind.h" #include "base/cxx17_backports.h" +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/strings/stringprintf.h" -#include "build/build_config.h" +#include "base/test/bind.h" #include "cc/paint/decoded_draw_image.h" #include "cc/paint/display_item_list.h" #include "cc/paint/image_provider.h" @@ -21,25 +22,32 @@ #include "cc/paint/paint_op_reader.h" #include "cc/paint/paint_op_writer.h" #include "cc/paint/shader_transfer_cache_entry.h" +#include "cc/paint/skottie_resource_metadata.h" #include "cc/paint/skottie_wrapper.h" #include "cc/paint/transfer_cache_entry.h" -#include "cc/test/geometry_test_utils.h" +#include "cc/test/lottie_test_data.h" #include "cc/test/paint_op_helper.h" #include "cc/test/skia_common.h" #include "cc/test/test_options_provider.h" #include "cc/test/test_paint_worklet_input.h" #include "cc/test/test_skcanvas.h" #include "cc/test/transfer_cache_test_helper.h" +#include "skia/buildflags.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "third_party/skia/src/core/SkRemoteGlyphCache.h" +#include "ui/gfx/geometry/test/geometry_util.h" using testing::_; -using testing::Property; +using testing::AtLeast; +using testing::Contains; +using testing::Key; using testing::Mock; +using testing::NiceMock; +using testing::NotNull; namespace cc { namespace { @@ -48,40 +56,6 @@ namespace { // unit test suite as generally deserialized ops are smaller. static constexpr size_t kBufferBytesPerOp = 1000 + sizeof(LargestPaintOp); -#if !defined(OS_ANDROID) -// A skottie animation with solid green color for the first 2.5 seconds and then -// a solid blue color for the next 2.5 seconds. -constexpr char kSkottieData[] = - "{" - " \"v\" : \"4.12.0\"," - " \"fr\": 30," - " \"w\" : 400," - " \"h\" : 200," - " \"ip\": 0," - " \"op\": 150," - " \"assets\": []," - - " \"layers\": [" - " {" - " \"ty\": 1," - " \"sw\": 400," - " \"sh\": 200," - " \"sc\": \"#00ff00\"," - " \"ip\": 0," - " \"op\": 75" - " }," - " {" - " \"ty\": 1," - " \"sw\": 400," - " \"sh\": 200," - " \"sc\": \"#0000ff\"," - " \"ip\": 76," - " \"op\": 150" - " }" - " ]" - "}"; -#endif // !defined(OS_ANDROID) - template <typename T> void ValidateOps(PaintOpBuffer* buffer) { // Make sure all test data is valid before serializing it. @@ -1258,15 +1232,24 @@ std::vector<PaintImage> test_images = { CreateDiscardablePaintImage(gfx::Size(50, 50)), }; +#if BUILDFLAG(SKIA_SUPPORT_SKOTTIE) +bool kIsSkottieSupported = true; + std::vector<scoped_refptr<SkottieWrapper>> test_skotties = { CreateSkottie(gfx::Size(10, 20), 4), CreateSkottie(gfx::Size(100, 40), 5), - CreateSkottie(gfx::Size(80, 70), 6)}; - -std::vector<float> test_skottie_floats = {0, 0.1f, 1.f}; - -std::vector<SkRect> test_skottie_rects = {SkRect::MakeXYWH(10, 20, 30, 40), - SkRect::MakeXYWH(0, 5, 10, 20), - SkRect::MakeXYWH(6, 0, 3, 50)}; + CreateSkottie(gfx::Size(80, 70), 6), + CreateSkottieFromString(kLottieDataWith2Assets)}; +std::vector<float> test_skottie_floats = {0, 0.1f, 1.f, 0.2f}; +std::vector<SkRect> test_skottie_rects = { + SkRect::MakeXYWH(10, 20, 30, 40), SkRect::MakeXYWH(0, 5, 10, 20), + SkRect::MakeXYWH(6, 0, 3, 50), SkRect::MakeXYWH(10, 10, 100, 100)}; +#else +bool kIsSkottieSupported = false; + +std::vector<scoped_refptr<SkottieWrapper>> test_skotties; +std::vector<float> test_skottie_floats; +std::vector<SkRect> test_skottie_rects; +#endif // Writes as many ops in |buffer| as can fit in |output_size| to |output|. // Records the numbers of bytes written for each op. @@ -1290,7 +1273,7 @@ class SimpleSerializer { if (!bytes_written) return; - PaintOp* written = reinterpret_cast<PaintOp*>(current_); + PaintOp* written = reinterpret_cast<PaintOp*>(current_.get()); EXPECT_EQ(op->GetType(), written->GetType()); EXPECT_EQ(bytes_written, written->skip); @@ -1311,7 +1294,7 @@ class SimpleSerializer { TestOptionsProvider* options_provider() { return &options_provider_; } private: - char* current_ = nullptr; + raw_ptr<char> current_ = nullptr; size_t output_size_ = 0u; size_t remaining_ = 0u; std::vector<size_t> bytes_written_; @@ -1397,14 +1380,14 @@ class DeserializerIterator { &last_bytes_read_, options_); } - const void* input_ = nullptr; + raw_ptr<const void> input_ = nullptr; const char* current_ = nullptr; size_t input_size_ = 0u; size_t remaining_ = 0u; size_t last_bytes_read_ = 0u; PaintOp::DeserializeOptions options_; std::unique_ptr<char, base::AlignedFreeDeleter> data_; - PaintOp* deserialized_op_ = nullptr; + raw_ptr<PaintOp> deserialized_op_ = nullptr; }; void PushAnnotateOps(PaintOpBuffer* buffer) { @@ -1556,11 +1539,33 @@ void PushDrawRRectOps(PaintOpBuffer* buffer) { ValidateOps<DrawRRectOp>(buffer); } +SkottieFrameDataMap GetTestImagesForSkottie(SkottieWrapper& skottie, + const SkRect& skottie_rect, + PaintFlags::FilterQuality quality, + float t) { + SkottieFrameDataMap images; + skottie.Seek( + t, + base::BindLambdaForTesting([&](SkottieResourceIdHash asset_id, + float t_frame, sk_sp<SkImage>& image_out, + SkSamplingOptions& sampling_out) { + SkottieFrameData frame_data; + frame_data.image = CreateBitmapImage( + gfx::Size(skottie_rect.width() / 2, skottie_rect.height() / 2)); + frame_data.quality = quality; + images[asset_id] = std::move(frame_data); + return SkottieWrapper::FrameDataFetchResult::NO_UPDATE; + })); + return images; +} + void PushDrawSkottieOps(PaintOpBuffer* buffer) { size_t len = std::min(test_skotties.size(), test_flags.size()); for (size_t i = 0; i < len; i++) { - buffer->push<DrawSkottieOp>(test_skotties[i], test_skottie_rects[i], - test_skottie_floats[i]); + buffer->push<DrawSkottieOp>( + test_skotties[i], test_skottie_rects[i], test_skottie_floats[i], + GetTestImagesForSkottie(*test_skotties[i], test_skottie_rects[i], + PaintFlags::FilterQuality::kHigh, /*t=*/0)); } ValidateOps<DrawSkottieOp>(buffer); } @@ -1759,8 +1764,7 @@ class PaintOpSerializationTest : public ::testing::TestWithParam<uint8_t> { PushDrawRRectOps(&buffer_); break; case PaintOpType::DrawSkottie: - // Not supported - // TODO(malaykeshav): Add test when Drawable supports serialization. + PushDrawSkottieOps(&buffer_); break; case PaintOpType::DrawTextBlob: PushDrawTextBlobOps(&buffer_); @@ -1807,11 +1811,10 @@ class PaintOpSerializationTest : public ::testing::TestWithParam<uint8_t> { } bool IsTypeSupported() { - // DrawRecordOps and DrawSkottieOps must be flattened and are not currently - // serialized. All other types must push non-zero amounts of ops in - // PushTestOps. + // DrawRecordOps must be flattened and are not currently serialized. All + // other types must push non-zero amounts of ops in PushTestOps. return GetParamType() != PaintOpType::DrawRecord && - GetParamType() != PaintOpType::DrawSkottie; + (GetParamType() != PaintOpType::DrawSkottie || kIsSkottieSupported); } protected: @@ -2190,8 +2193,8 @@ TEST(PaintOpSerializationTest, Preamble) { ASSERT_EQ(op->GetType(), PaintOpType::ClipRect) << PaintOpTypeToString(op->GetType()); const auto* clip_op = static_cast<const ClipRectOp*>(op); - EXPECT_FLOAT_RECT_EQ(gfx::SkRectToRectF(clip_op->rect), - preamble.playback_rect); + EXPECT_RECTF_EQ(gfx::SkRectToRectF(clip_op->rect), + gfx::RectF(preamble.playback_rect)); continue; } @@ -2799,19 +2802,6 @@ TEST(PaintOpBufferTest, BoundingRect_DrawDRRectOp) { } } -TEST(PaintOpBufferTest, BoundingRect_DrawSkottieOp) { - PaintOpBuffer buffer; - PushDrawSkottieOps(&buffer); - - SkRect rect; - for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) { - auto* op = static_cast<DrawSkottieOp*>(base_op); - - ASSERT_TRUE(PaintOp::GetBounds(op, &rect)); - EXPECT_EQ(rect, op->dst.makeSorted()); - } -} - TEST(PaintOpBufferTest, BoundingRect_DrawTextBlobOp) { PaintOpBuffer buffer; PushDrawTextBlobOps(&buffer); @@ -2839,6 +2829,7 @@ class MockImageProvider : public ImageProvider { ImageProvider::ScopedResult GetRasterContent( const DrawImage& draw_image) override { + decoded_images_.push_back(draw_image); if (draw_image.paint_image().IsPaintWorklet()) return ScopedResult(record_); @@ -2856,6 +2847,10 @@ class MockImageProvider : public ImageProvider { void SetRecord(sk_sp<PaintRecord> record) { record_ = std::move(record); } + const std::vector<DrawImage>& decoded_images() const { + return decoded_images_; + } + private: std::vector<SkSize> src_rect_offset_; std::vector<SkSize> scale_; @@ -2863,6 +2858,7 @@ class MockImageProvider : public ImageProvider { size_t index_ = 0; bool fail_all_decodes_ = false; sk_sp<PaintRecord> record_; + std::vector<DrawImage> decoded_images_; }; TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { @@ -2917,6 +2913,10 @@ MATCHER(NonLazyImage, "") { return !arg->isLazyGenerated(); } +MATCHER_P(MatchesPaintImage, paint_image, "") { + return arg.paint_image() == paint_image; +} + MATCHER_P2(MatchesRect, rect, scale, "") { EXPECT_EQ(arg.x(), rect.x() * scale.width()); EXPECT_EQ(arg.y(), rect.y() * scale.height()); @@ -3448,78 +3448,43 @@ TEST(PaintOpBufferTest, PaintRecordShaderSerialization) { auto* op = *it; ASSERT_TRUE(op->GetType() == PaintOpType::DrawRect); auto* rect_op = static_cast<DrawRectOp*>(op); - EXPECT_FLOAT_RECT_EQ(rect_op->rect, SkRect::MakeXYWH(1, 2, 3, 4)); + EXPECT_SKRECT_EQ(rect_op->rect, SkRect::MakeXYWH(1, 2, 3, 4)); EXPECT_TRUE(rect_op->flags == flags); EXPECT_TRUE(*rect_op->flags.getShader() == *flags.getShader()); } -#if !defined(OS_ANDROID) -TEST(PaintOpBufferTest, DrawSkottieOpSerialization) { - std::unique_ptr<char, base::AlignedFreeDeleter> memory( - static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, - PaintOpBuffer::PaintOpAlign))); - std::vector<uint8_t> data(std::strlen(kSkottieData)); - data.assign(reinterpret_cast<const uint8_t*>(kSkottieData), - reinterpret_cast<const uint8_t*>(kSkottieData) + - std::strlen(kSkottieData)); - - scoped_refptr<SkottieWrapper> skottie = - SkottieWrapper::CreateSerializable(std::move(data)); - - ASSERT_TRUE(skottie->is_valid()); - const SkRect input_rect = SkRect::MakeIWH(400, 300); - const float input_t = 0.4f; - +#if BUILDFLAG(SKIA_SUPPORT_SKOTTIE) +TEST(PaintOpBufferTest, BoundingRect_DrawSkottieOp) { PaintOpBuffer buffer; - buffer.push<DrawSkottieOp>(skottie, input_rect, input_t); - - // Serialize - TestOptionsProvider options_provider; - SimpleBufferSerializer serializer(memory.get(), - PaintOpBuffer::kInitialBufferSize, - options_provider.serialize_options()); - serializer.Serialize(&buffer); - ASSERT_TRUE(serializer.valid()); - ASSERT_GT(serializer.written(), 0u); + PushDrawSkottieOps(&buffer); - // De-Serialize - auto deserialized_buffer = - PaintOpBuffer::MakeFromMemory(memory.get(), serializer.written(), - options_provider.deserialize_options()); - ASSERT_TRUE(deserialized_buffer); - PaintOpBuffer::Iterator it(deserialized_buffer.get()); - ASSERT_TRUE(it); - auto* op = *it; - ASSERT_TRUE(op->GetType() == PaintOpType::DrawSkottie); - auto* skottie_op = static_cast<DrawSkottieOp*>(op); - EXPECT_FLOAT_RECT_EQ(skottie_op->dst, input_rect); - EXPECT_FLOAT_EQ(skottie_op->t, input_t); - EXPECT_EQ(skottie_op->skottie->id(), skottie->id()); - EXPECT_TRUE(skottie_op->skottie->is_valid()); + SkRect rect; + for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) { + auto* op = static_cast<DrawSkottieOp*>(base_op); - // Check that an entry in transfer cache is present for the skottie data. - EXPECT_TRUE(options_provider.transfer_cache_helper()->GetEntryInternal( - TransferCacheEntryType::kSkottie, skottie->id())); + ASSERT_TRUE(PaintOp::GetBounds(op, &rect)); + EXPECT_EQ(rect, op->dst.makeSorted()); + } } -TEST(PaintOpBufferTest, DrawSkottieOpSerializationFailure) { +// Skottie-specific deserialization failure case. +TEST(PaintOpBufferTest, + DrawSkottieOpSerializationFailureFromUnPrivilegedProcess) { std::unique_ptr<char, base::AlignedFreeDeleter> memory( static_cast<char*>(base::AlignedAlloc(PaintOpBuffer::kInitialBufferSize, PaintOpBuffer::PaintOpAlign))); - std::vector<uint8_t> data(std::strlen(kSkottieData)); - data.assign(reinterpret_cast<const uint8_t*>(kSkottieData), - reinterpret_cast<const uint8_t*>(kSkottieData) + - std::strlen(kSkottieData)); - scoped_refptr<SkottieWrapper> skottie = - SkottieWrapper::CreateSerializable(std::move(data)); + CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/1); ASSERT_TRUE(skottie->is_valid()); const SkRect input_rect = SkRect::MakeIWH(400, 300); const float input_t = 0.4f; PaintOpBuffer buffer; - buffer.push<DrawSkottieOp>(skottie, input_rect, input_t); + buffer.push<DrawSkottieOp>( + skottie, input_rect, input_t, + GetTestImagesForSkottie(*skottie, input_rect, + PaintFlags::FilterQuality::kHigh, input_t)); // Serialize TestOptionsProvider options_provider; @@ -3540,7 +3505,121 @@ TEST(PaintOpBufferTest, DrawSkottieOpSerializationFailure) { memory.get(), serializer.written(), d_options); ASSERT_FALSE(deserialized_buffer); } -#endif // !defined(OS_ANDROID + +TEST(PaintOpBufferTest, DrawSkottieOpRasterWithoutImageAssets) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/5); + SkRect skottie_rect = SkRect::MakeWH(100, 100); + DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.1, + /*images=*/SkottieFrameDataMap()); + PlaybackParams playback_params(/*image_provider=*/nullptr); + { + NiceMock<MockCanvas> canvas; + EXPECT_CALL(canvas, onDrawImage2(_, _, _, _, _)).Times(0); + DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params); + } +} + +TEST(PaintOpBufferTest, DrawSkottieOpRasterWithoutImageProvider) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + SkRect skottie_rect = SkRect::MakeWH(100, 100); + SkottieFrameDataMap images_in = GetTestImagesForSkottie( + *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.1f); + ASSERT_FALSE(images_in.empty()); + DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.1, images_in); + PlaybackParams playback_params(/*image_provider=*/nullptr); + { + NiceMock<MockCanvas> canvas; + // Do not over-assert. Ultimately it is up to Skottie's implementation how + // many "draw image" calls are made, and what the arguments are. But it's + // fair to say that it has to make at least one "draw image" call for a + // frame in the animation that renders one of the assets. + EXPECT_CALL(canvas, onDrawImage2(NotNull(), _, _, _, _)).Times(AtLeast(1)); + DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params); + } +} + +TEST(PaintOpBufferTest, DrawSkottieOpRasterWithImageProvider) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + SkRect skottie_rect = SkRect::MakeWH(100, 100); + std::vector<SkSize> src_rect_offset = {SkSize::Make(2.0f, 2.0f), + SkSize::Make(3.0f, 3.0f)}; + std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f), + SkSize::Make(0.3f, 0.3f)}; + std::vector<PaintFlags::FilterQuality> quality = { + PaintFlags::FilterQuality::kHigh, PaintFlags::FilterQuality::kMedium}; + + MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality); + PlaybackParams playback_params(&image_provider); + ASSERT_TRUE(image_provider.decoded_images().empty()); + { + SkottieFrameDataMap images_in = GetTestImagesForSkottie( + *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.25f); + ASSERT_THAT(images_in, Contains(Key(HashSkottieResourceId("image_0")))); + DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.25, images_in); + NiceMock<MockCanvas> canvas; + EXPECT_CALL(canvas, onDrawImage2(NotNull(), _, _, _, _)).Times(AtLeast(1)); + DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params); + ASSERT_EQ(image_provider.decoded_images().size(), 1u); + EXPECT_THAT(image_provider.decoded_images(), + Contains(MatchesPaintImage( + images_in.at(HashSkottieResourceId("image_0")).image))); + } + { + SkottieFrameDataMap images_in = GetTestImagesForSkottie( + *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.75f); + ASSERT_THAT(images_in, Contains(Key(HashSkottieResourceId("image_1")))); + DrawSkottieOp skottie_op(skottie, skottie_rect, /*t=*/0.75, images_in); + NiceMock<MockCanvas> canvas; + EXPECT_CALL(canvas, onDrawImage2(NotNull(), _, _, _, _)).Times(AtLeast(1)); + DrawSkottieOp::Raster(&skottie_op, &canvas, playback_params); + ASSERT_EQ(image_provider.decoded_images().size(), 2u); + EXPECT_THAT(image_provider.decoded_images(), + Contains(MatchesPaintImage( + images_in.at(HashSkottieResourceId("image_1")).image))); + } +} + +TEST(PaintOpBufferTest, DiscardableImagesTrackingSkottieOpNoImages) { + PaintOpBuffer buffer; + buffer.push<DrawSkottieOp>( + CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/1), + /*dst=*/SkRect::MakeWH(100, 100), /*t=*/0.1f, SkottieFrameDataMap()); + EXPECT_FALSE(buffer.HasDiscardableImages()); +} + +TEST(PaintOpBufferTest, DiscardableImagesTrackingSkottieOpWithImages) { + PaintOpBuffer buffer; + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + SkRect skottie_rect = SkRect::MakeWH(100, 100); + SkottieFrameDataMap images_in = GetTestImagesForSkottie( + *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.1f); + ASSERT_FALSE(images_in.empty()); + buffer.push<DrawSkottieOp>(skottie, skottie_rect, /*t=*/0.1f, images_in); + EXPECT_TRUE(buffer.HasDiscardableImages()); +} + +TEST(PaintOpBufferTest, OpHasDiscardableImagesSkottieOpNoImages) { + DrawSkottieOp op(CreateSkottie(gfx::Size(100, 100), /*duration_secs=*/1), + /*dst=*/SkRect::MakeWH(100, 100), /*t=*/0.1f, + SkottieFrameDataMap()); + EXPECT_FALSE(PaintOp::OpHasDiscardableImages(&op)); +} + +TEST(PaintOpBufferTest, OpHasDiscardableImagesSkottieOpWithImages) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + SkRect skottie_rect = SkRect::MakeWH(100, 100); + SkottieFrameDataMap images_in = GetTestImagesForSkottie( + *skottie, skottie_rect, PaintFlags::FilterQuality::kHigh, /*t=*/0.1f); + ASSERT_FALSE(images_in.empty()); + DrawSkottieOp op(skottie, skottie_rect, /*t=*/0.1f, images_in); + EXPECT_TRUE(PaintOp::OpHasDiscardableImages(&op)); +} +#endif // BUILDFLAG(SKIA_SUPPORT_SKOTTIE) TEST(PaintOpBufferTest, CustomData) { // Basic tests: size, move, comparison. diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc index 63afe24cde7..d71230cfc47 100644 --- a/chromium/cc/paint/paint_op_reader.cc +++ b/chromium/cc/paint/paint_op_reader.cc @@ -14,6 +14,7 @@ #include "base/bits.h" #include "base/compiler_specific.h" #include "base/debug/dump_without_crashing.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/rand_util.h" #include "base/stl_util.h" @@ -25,6 +26,8 @@ #include "cc/paint/paint_op_buffer.h" #include "cc/paint/paint_shader.h" #include "cc/paint/shader_transfer_cache_entry.h" +#include "cc/paint/skottie_transfer_cache_entry.h" +#include "cc/paint/skottie_wrapper.h" #include "cc/paint/transfer_cache_deserialize_helper.h" #include "components/crash/core/common/crash_key.h" #include "third_party/skia/include/core/SkPath.h" @@ -33,11 +36,6 @@ #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/src/core/SkRemoteGlyphCache.h" -#if !defined(OS_ANDROID) -#include "cc/paint/skottie_transfer_cache_entry.h" -#include "cc/paint/skottie_wrapper.h" -#endif - namespace cc { namespace { @@ -54,7 +52,7 @@ bool IsValidPaintShaderScalingBehavior(PaintShader::ScalingBehavior behavior) { struct TypefaceCtx { explicit TypefaceCtx(SkStrikeClient* client) : client(client) {} bool invalid_typeface = false; - SkStrikeClient* client = nullptr; + raw_ptr<SkStrikeClient> client = nullptr; }; sk_sp<SkTypeface> DeserializeTypeface(const void* data, @@ -728,9 +726,6 @@ void PaintOpReader::Read(gpu::Mailbox* mailbox) { ReadData(sizeof(gpu::Mailbox::Name), (*mailbox).name); } -// Android does not use skottie. Remove below section to keep binary size to a -// minimum. -#if !defined(OS_ANDROID) void PaintOpReader::Read(scoped_refptr<SkottieWrapper>* skottie) { if (!options_.is_privileged) { valid_ = false; @@ -761,7 +756,6 @@ void PaintOpReader::Read(scoped_refptr<SkottieWrapper>* skottie) { memory_ += bytes_to_skip; remaining_bytes_ -= bytes_to_skip; } -#endif // !defined(OS_ANDROID) void PaintOpReader::AlignMemory(size_t alignment) { size_t padding = base::bits::AlignUp(memory_, alignment) - memory_; @@ -1164,6 +1158,14 @@ void PaintOpReader::ReadRecordPaintFilter( return; } + // RecordPaintFilter also requires kRasterAtScale to have {1.f, 1.f} as the + // raster_scale, since that is intended for kFixedScale + if (scaling_behavior == PaintShader::ScalingBehavior::kRasterAtScale && + (raster_scale.width() != 1.f || raster_scale.height() != 1.f)) { + SetInvalid(DeserializationError::kInvalidRasterScale); + return; + } + Read(&record); if (!valid_) return; diff --git a/chromium/cc/paint/paint_op_reader.h b/chromium/cc/paint/paint_op_reader.h index 1782eae6069..201cdfde5ee 100644 --- a/chromium/cc/paint/paint_op_reader.h +++ b/chromium/cc/paint/paint_op_reader.h @@ -6,7 +6,6 @@ #define CC_PAINT_PAINT_OP_READER_H_ #include "base/memory/scoped_refptr.h" -#include "build/build_config.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_filter.h" #include "cc/paint/paint_op_writer.h" @@ -79,9 +78,7 @@ class CC_PAINT_EXPORT PaintOpReader { void Read(SkYUVAInfo::Subsampling* subsampling); void Read(gpu::Mailbox* mailbox); -#if !defined(OS_ANDROID) void Read(scoped_refptr<SkottieWrapper>* skottie); -#endif void Read(SkClipOp* op) { ReadEnum<SkClipOp, SkClipOp::kMax_EnumValue>(op); } void Read(PaintCanvas::AnnotationType* type) { diff --git a/chromium/cc/paint/paint_op_writer.cc b/chromium/cc/paint/paint_op_writer.cc index 1f1182ff9b7..b4f5a03ef80 100644 --- a/chromium/cc/paint/paint_op_writer.cc +++ b/chromium/cc/paint/paint_op_writer.cc @@ -14,6 +14,8 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_op_buffer_serializer.h" #include "cc/paint/paint_shader.h" +#include "cc/paint/skottie_transfer_cache_entry.h" +#include "cc/paint/skottie_wrapper.h" #include "cc/paint/transfer_cache_serialize_helper.h" #include "gpu/command_buffer/common/mailbox.h" #include "third_party/skia/include/core/SkSerialProcs.h" @@ -22,11 +24,6 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/skia_conversions.h" -#if !defined(OS_ANDROID) -#include "cc/paint/skottie_transfer_cache_entry.h" -#include "cc/paint/skottie_wrapper.h" -#endif - namespace cc { namespace { constexpr size_t kSkiaAlignment = 4u; @@ -108,7 +105,7 @@ void PaintOpWriter::WriteSimple(const T& val) { if (!valid_) return; - reinterpret_cast<T*>(memory_)[0] = val; + reinterpret_cast<T*>(memory_.get())[0] = val; memory_ += size; remaining_bytes_ -= size; @@ -136,7 +133,7 @@ void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) { uint64_t* PaintOpWriter::WriteSize(size_t size) { AlignMemory(8); - uint64_t* memory = reinterpret_cast<uint64_t*>(memory_); + uint64_t* memory = reinterpret_cast<uint64_t*>(memory_.get()); WriteSimple<uint64_t>(size); return memory; } @@ -282,9 +279,6 @@ void PaintOpWriter::Write(const DrawImage& draw_image, WriteImage(decoded_draw_image); } -// Android does not use skottie. Remove below section to keep binary size to a -// minimum. -#if !defined(OS_ANDROID) void PaintOpWriter::Write(scoped_refptr<SkottieWrapper> skottie) { uint32_t id = skottie->id(); Write(id); @@ -309,7 +303,6 @@ void PaintOpWriter::Write(scoped_refptr<SkottieWrapper> skottie) { memory_ += bytes_written; remaining_bytes_ -= bytes_written; } -#endif // !defined(OS_ANDROID) void PaintOpWriter::WriteImage(const DecodedDrawImage& decoded_draw_image) { if (!decoded_draw_image.mailbox().IsZero()) { @@ -588,7 +581,7 @@ void PaintOpWriter::AlignMemory(size_t alignment) { DCHECK_GT(alignment, 0u); DCHECK_EQ(alignment & (alignment - 1), 0u); - uintptr_t memory = reinterpret_cast<uintptr_t>(memory_); + uintptr_t memory = reinterpret_cast<uintptr_t>(memory_.get()); // The following is equivalent to: // padding = (alignment - memory % alignment) % alignment; // because alignment is a power of two. This doesn't use modulo operator @@ -608,7 +601,7 @@ void PaintOpWriter::Write(const PaintFilter* filter, const SkM44& current_ctm) { return; } WriteEnum(filter->type()); - auto* crop_rect = filter->crop_rect(); + auto* crop_rect = filter->GetCropRect(); WriteSimple(static_cast<uint32_t>(!!crop_rect)); if (crop_rect) { WriteSimple(*crop_rect); diff --git a/chromium/cc/paint/paint_op_writer.h b/chromium/cc/paint/paint_op_writer.h index 2e6fc5bfdd1..520eaca8900 100644 --- a/chromium/cc/paint/paint_op_writer.h +++ b/chromium/cc/paint/paint_op_writer.h @@ -5,7 +5,7 @@ #ifndef CC_PAINT_PAINT_OP_WRITER_H_ #define CC_PAINT_PAINT_OP_WRITER_H_ -#include "build/build_config.h" +#include "base/memory/raw_ptr.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_filter.h" @@ -23,6 +23,7 @@ struct Mailbox; namespace cc { +class DecodedDrawImage; class DrawImage; class PaintShader; @@ -119,10 +120,8 @@ class CC_PAINT_EXPORT PaintOpWriter { // image. void Write(const DrawImage& draw_image, SkSize* scale_adjustment); -#if !defined(OS_ANDROID) // Serializes the given |skottie| vector graphic. void Write(scoped_refptr<SkottieWrapper> skottie); -#endif private: template <typename T> @@ -182,7 +181,7 @@ class CC_PAINT_EXPORT PaintOpWriter { bool* paint_image_needs_mips, gpu::Mailbox* mailbox_out); - char* memory_ = nullptr; + raw_ptr<char> memory_ = nullptr; size_t size_ = 0u; size_t remaining_bytes_ = 0u; const PaintOp::SerializeOptions& options_; diff --git a/chromium/cc/paint/paint_shader.cc b/chromium/cc/paint/paint_shader.cc index a0002f9fde1..87ba9d4115f 100644 --- a/chromium/cc/paint/paint_shader.cc +++ b/chromium/cc/paint/paint_shader.cc @@ -8,6 +8,7 @@ #include "base/atomic_sequence_num.h" #include "base/stl_util.h" +#include "cc/paint/image_provider.h" #include "cc/paint/paint_image_builder.h" #include "cc/paint/paint_op_writer.h" #include "cc/paint/paint_record.h" diff --git a/chromium/cc/paint/paint_shader.h b/chromium/cc/paint/paint_shader.h index 84092d34860..80519ed3e89 100644 --- a/chromium/cc/paint/paint_shader.h +++ b/chromium/cc/paint/paint_shader.h @@ -9,7 +9,6 @@ #include <vector> #include "base/gtest_prod_util.h" -#include "base/stl_util.h" #include "cc/paint/image_analysis_state.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_flags.h" @@ -146,9 +145,6 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { return image_; } - const gfx::SizeF* tile_scale() const { - return base::OptionalOrNullptr(tile_scale_); - } const sk_sp<PaintRecord>& paint_record() const { return record_; } bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const { return GetClampedRasterizationTileRect(ctm, /*max_texture_size=*/0, diff --git a/chromium/cc/paint/record_paint_canvas.cc b/chromium/cc/paint/record_paint_canvas.cc index 8349dd9e4a3..a22017105a9 100644 --- a/chromium/cc/paint/record_paint_canvas.cc +++ b/chromium/cc/paint/record_paint_canvas.cc @@ -10,6 +10,7 @@ #include "cc/paint/paint_image_builder.h" #include "cc/paint/paint_record.h" #include "cc/paint/paint_recorder.h" +#include "cc/paint/skottie_frame_data.h" #include "cc/paint/skottie_wrapper.h" #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkTextBlob.h" @@ -29,6 +30,19 @@ SkImageInfo RecordPaintCanvas::imageInfo() const { return GetCanvas()->imageInfo(); } +template <typename T, typename... Args> +size_t RecordPaintCanvas::push(Args&&... args) { +#if DCHECK_IS_ON() + // The following check fails if client code does not check and handle + // NeedsFlush() before issuing draw calls. + // Note: restore ops are tolerated when flushes are requested since they are + // often necessary in order to bring the canvas to a flushable state + DCHECK(disable_flush_check_scope_ || !needs_flush_ || + (std::is_same<T, RestoreOp>::value)); +#endif + return list_->push<T>(std::forward<Args>(args)...); +} + void* RecordPaintCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { @@ -37,11 +51,22 @@ void* RecordPaintCanvas::accessTopLayerPixels(SkImageInfo* info, } void RecordPaintCanvas::flush() { - // This is a noop when recording. + // RecordPaintCanvas is unable to flush its own recording into the graphics + // pipeline. So instead we make note of the flush request so that it can be + // handled by code that owns the recording. + // + // Note: The value of needs_flush_ never gets reset. That is because + // flushing a recording implies closing this RecordPaintCanvas and starting a + // new one. + needs_flush_ = true; +} + +bool RecordPaintCanvas::NeedsFlush() const { + return needs_flush_; } int RecordPaintCanvas::save() { - list_->push<SaveOp>(); + push<SaveOp>(); return GetCanvas()->save(); } @@ -58,21 +83,21 @@ int RecordPaintCanvas::saveLayer(const SkRect* bounds, // TODO(enne): it appears that image filters affect matrices and color // matrices affect transparent flags on SkCanvas layers, but it's not clear // whether those are actually needed and we could just skip ToSkPaint here. - list_->push<SaveLayerOp>(bounds, flags); + push<SaveLayerOp>(bounds, flags); SkPaint paint = flags->ToSkPaint(); return GetCanvas()->saveLayer(bounds, &paint); } - list_->push<SaveLayerOp>(bounds, flags); + push<SaveLayerOp>(bounds, flags); return GetCanvas()->saveLayer(bounds, nullptr); } int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) { - list_->push<SaveLayerAlphaOp>(bounds, alpha); + push<SaveLayerAlphaOp>(bounds, alpha); return GetCanvas()->saveLayerAlpha(bounds, alpha); } void RecordPaintCanvas::restore() { - list_->push<RestoreOp>(); + push<RestoreOp>(); GetCanvas()->restore(); } @@ -94,46 +119,46 @@ void RecordPaintCanvas::restoreToCount(int save_count) { } void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) { - list_->push<TranslateOp>(dx, dy); + push<TranslateOp>(dx, dy); GetCanvas()->translate(dx, dy); } void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) { - list_->push<ScaleOp>(sx, sy); + push<ScaleOp>(sx, sy); GetCanvas()->scale(sx, sy); } void RecordPaintCanvas::rotate(SkScalar degrees) { - list_->push<RotateOp>(degrees); + push<RotateOp>(degrees); GetCanvas()->rotate(degrees); } void RecordPaintCanvas::concat(const SkMatrix& matrix) { SkM44 m = SkM44(matrix); - list_->push<ConcatOp>(m); + push<ConcatOp>(m); GetCanvas()->concat(m); } void RecordPaintCanvas::concat(const SkM44& matrix) { - list_->push<ConcatOp>(matrix); + push<ConcatOp>(matrix); GetCanvas()->concat(matrix); } void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) { SkM44 m = SkM44(matrix); - list_->push<SetMatrixOp>(m); + push<SetMatrixOp>(m); GetCanvas()->setMatrix(m); } void RecordPaintCanvas::setMatrix(const SkM44& matrix) { - list_->push<SetMatrixOp>(matrix); + push<SetMatrixOp>(matrix); GetCanvas()->setMatrix(matrix); } void RecordPaintCanvas::clipRect(const SkRect& rect, SkClipOp op, bool antialias) { - list_->push<ClipRectOp>(rect, op, antialias); + push<ClipRectOp>(rect, op, antialias); GetCanvas()->clipRect(rect, op, antialias); } @@ -145,7 +170,7 @@ void RecordPaintCanvas::clipRRect(const SkRRect& rrect, clipRect(rrect.getBounds(), op, antialias); return; } - list_->push<ClipRRectOp>(rrect, op, antialias); + push<ClipRRectOp>(rrect, op, antialias); GetCanvas()->clipRRect(rrect, op, antialias); } @@ -174,7 +199,7 @@ void RecordPaintCanvas::clipPath(const SkPath& path, } } - list_->push<ClipPathOp>(path, op, antialias, use_paint_cache); + push<ClipPathOp>(path, op, antialias, use_paint_cache); GetCanvas()->clipPath(path, op, antialias); return; } @@ -200,11 +225,11 @@ bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const { } void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) { - list_->push<DrawColorOp>(color, mode); + push<DrawColorOp>(color, mode); } void RecordPaintCanvas::clear(SkColor color) { - list_->push<DrawColorOp>(color, SkBlendMode::kSrc); + push<DrawColorOp>(color, SkBlendMode::kSrc); } void RecordPaintCanvas::drawLine(SkScalar x0, @@ -212,25 +237,25 @@ void RecordPaintCanvas::drawLine(SkScalar x0, SkScalar x1, SkScalar y1, const PaintFlags& flags) { - list_->push<DrawLineOp>(x0, y0, x1, y1, flags); + push<DrawLineOp>(x0, y0, x1, y1, flags); } void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { - list_->push<DrawRectOp>(rect, flags); + push<DrawRectOp>(rect, flags); } void RecordPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { - list_->push<DrawIRectOp>(rect, flags); + push<DrawIRectOp>(rect, flags); } void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { - list_->push<DrawOvalOp>(oval, flags); + push<DrawOvalOp>(oval, flags); } void RecordPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) { - list_->push<DrawRRectOp>(rrect, flags); + push<DrawRRectOp>(rrect, flags); } void RecordPaintCanvas::drawDRRect(const SkRRect& outer, @@ -242,7 +267,7 @@ void RecordPaintCanvas::drawDRRect(const SkRRect& outer, drawRRect(outer, flags); return; } - list_->push<DrawDRRectOp>(outer, inner, flags); + push<DrawDRRectOp>(outer, inner, flags); } void RecordPaintCanvas::drawRoundRect(const SkRect& rect, @@ -262,7 +287,7 @@ void RecordPaintCanvas::drawRoundRect(const SkRect& rect, void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags, UsePaintCache use_paint_cache) { - list_->push<DrawPathOp>(path, flags, use_paint_cache); + push<DrawPathOp>(path, flags, use_paint_cache); } void RecordPaintCanvas::drawImage(const PaintImage& image, @@ -271,7 +296,7 @@ void RecordPaintCanvas::drawImage(const PaintImage& image, const SkSamplingOptions& sampling, const PaintFlags* flags) { DCHECK(!image.IsPaintWorklet()); - list_->push<DrawImageOp>(image, left, top, sampling, flags); + push<DrawImageOp>(image, left, top, sampling, flags); } void RecordPaintCanvas::drawImageRect(const PaintImage& image, @@ -280,20 +305,21 @@ void RecordPaintCanvas::drawImageRect(const PaintImage& image, const SkSamplingOptions& sampling, const PaintFlags* flags, SkCanvas::SrcRectConstraint constraint) { - list_->push<DrawImageRectOp>(image, src, dst, sampling, flags, constraint); + push<DrawImageRectOp>(image, src, dst, sampling, flags, constraint); } void RecordPaintCanvas::drawSkottie(scoped_refptr<SkottieWrapper> skottie, const SkRect& dst, - float t) { - list_->push<DrawSkottieOp>(std::move(skottie), dst, t); + float t, + SkottieFrameDataMap images) { + push<DrawSkottieOp>(std::move(skottie), dst, t, std::move(images)); } void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, const PaintFlags& flags) { - list_->push<DrawTextBlobOp>(std::move(blob), x, y, flags); + push<DrawTextBlobOp>(std::move(blob), x, y, flags); } void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, @@ -301,12 +327,12 @@ void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar y, NodeId node_id, const PaintFlags& flags) { - list_->push<DrawTextBlobOp>(std::move(blob), x, y, node_id, flags); + push<DrawTextBlobOp>(std::move(blob), x, y, node_id, flags); } void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) { // TODO(enne): If this is small, maybe flatten it? - list_->push<DrawRecordOp>(record); + push<DrawRecordOp>(record); } bool RecordPaintCanvas::isClipEmpty() const { @@ -325,15 +351,15 @@ SkM44 RecordPaintCanvas::getLocalToDevice() const { void RecordPaintCanvas::Annotate(AnnotationType type, const SkRect& rect, sk_sp<SkData> data) { - list_->push<AnnotateOp>(type, rect, data); + push<AnnotateOp>(type, rect, data); } void RecordPaintCanvas::recordCustomData(uint32_t id) { - list_->push<CustomDataOp>(id); + push<CustomDataOp>(id); } void RecordPaintCanvas::setNodeId(int node_id) { - list_->push<SetNodeIdOp>(node_id); + push<SetNodeIdOp>(node_id); } const SkNoDrawCanvas* RecordPaintCanvas::GetCanvas() const { diff --git a/chromium/cc/paint/record_paint_canvas.h b/chromium/cc/paint/record_paint_canvas.h index c0aa89129fb..65fbc092d38 100644 --- a/chromium/cc/paint/record_paint_canvas.h +++ b/chromium/cc/paint/record_paint_canvas.h @@ -6,6 +6,7 @@ #define CC_PAINT_RECORD_PAINT_CANVAS_H_ #include "base/compiler_specific.h" +#include "base/memory/raw_ptr.h" #include "build/build_config.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_flags.h" @@ -96,7 +97,8 @@ class CC_PAINT_EXPORT RecordPaintCanvas : public PaintCanvas { SkCanvas::SrcRectConstraint constraint) override; void drawSkottie(scoped_refptr<SkottieWrapper> skottie, const SkRect& dst, - float t) override; + float t, + SkottieFrameDataMap images) override; void drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, @@ -119,6 +121,8 @@ class CC_PAINT_EXPORT RecordPaintCanvas : public PaintCanvas { void recordCustomData(uint32_t id) override; void setNodeId(int) override; + bool NeedsFlush() const override; + // Don't shadow non-virtual helper functions. using PaintCanvas::clipRect; using PaintCanvas::clipRRect; @@ -127,7 +131,46 @@ class CC_PAINT_EXPORT RecordPaintCanvas : public PaintCanvas { using PaintCanvas::drawImage; using PaintCanvas::drawPicture; +#if DCHECK_IS_ON() + void EnterDisableFlushCheckScope() { ++disable_flush_check_scope_; } + void LeaveDisableFlushCheckScope() { DCHECK(disable_flush_check_scope_--); } + bool IsInDisableFlushCheckScope() { return disable_flush_check_scope_; } +#endif + + class DisableFlushCheckScope { + // Create an object of this type to temporarily allow draw commands to be + // recorded while the recording is marked as needing to be flushed. This is + // meant to be used to allow client code to issue the commands necessary to + // reach a state where the recording can be safely flushed before beginning + // to enforce a check that forbids recording additional draw commands after + // a flush was requested. + public: + explicit DisableFlushCheckScope(RecordPaintCanvas* canvas) { +#if DCHECK_IS_ON() + // We require that NeedsFlush be false upon entering a top-level scope + // to prevent consecutive scopes from evading evading flush checks + // indefinitely. + DCHECK(!canvas->NeedsFlush() || canvas->IsInDisableFlushCheckScope()); + canvas->EnterDisableFlushCheckScope(); + canvas_ = canvas; +#endif + } + ~DisableFlushCheckScope() { +#if DCHECK_IS_ON() + canvas_->LeaveDisableFlushCheckScope(); +#endif + } + + private: +#if DCHECK_IS_ON() + raw_ptr<RecordPaintCanvas> canvas_; +#endif + }; + private: + template <typename T, typename... Args> + size_t push(Args&&... args); + const SkNoDrawCanvas* GetCanvas() const; SkNoDrawCanvas* GetCanvas(); @@ -145,6 +188,10 @@ class CC_PAINT_EXPORT RecordPaintCanvas : public PaintCanvas { // lazy initialize the canvas can still be const. mutable absl::optional<SkNoDrawCanvas> canvas_; SkRect recording_bounds_; + bool needs_flush_ = false; +#if DCHECK_IS_ON() + unsigned disable_flush_check_scope_ = 0; +#endif }; } // namespace cc diff --git a/chromium/cc/paint/render_surface_filters.cc b/chromium/cc/paint/render_surface_filters.cc index 8f2606725bd..fde3c82a8a1 100644 --- a/chromium/cc/paint/render_surface_filters.cc +++ b/chromium/cc/paint/render_surface_filters.cc @@ -263,7 +263,7 @@ sk_sp<PaintFilter> RenderSurfaceFilters::BuildImageFilter( sk_sp<SkColorFilter> cf; bool has_input = false; if (op.image_filter()->type() == PaintFilter::Type::kColorFilter && - !op.image_filter()->crop_rect()) { + !op.image_filter()->GetCropRect()) { auto* color_paint_filter = static_cast<ColorFilterPaintFilter*>(op.image_filter().get()); cf = color_paint_filter->color_filter(); diff --git a/chromium/cc/paint/skia_paint_canvas.cc b/chromium/cc/paint/skia_paint_canvas.cc index 34e9cf4f0f5..b00ceacd635 100644 --- a/chromium/cc/paint/skia_paint_canvas.cc +++ b/chromium/cc/paint/skia_paint_canvas.cc @@ -5,6 +5,7 @@ #include "cc/paint/skia_paint_canvas.h" #include "base/bind.h" +#include "base/notreached.h" #include "base/trace_event/trace_event.h" #include "cc/paint/display_item_list.h" #include "cc/paint/paint_recorder.h" @@ -14,6 +15,7 @@ #include "third_party/skia/include/core/SkAnnotation.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/docs/SkPDFDocument.h" +#include "third_party/skia/include/gpu/GrRecordingContext.h" namespace cc { SkiaPaintCanvas::ContextFlushes::ContextFlushes() @@ -56,6 +58,12 @@ void SkiaPaintCanvas::flush() { canvas_->flush(); } +bool SkiaPaintCanvas::NeedsFlush() const { + // Since flush() is always capable of flushing immediately with + // SkiaPaintCanvas, there is never any need for deferred flushing. + return false; +} + int SkiaPaintCanvas::save() { return canvas_->save(); } @@ -161,7 +169,7 @@ void SkiaPaintCanvas::drawLine(SkScalar x0, SkScalar y1, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -175,7 +183,7 @@ void SkiaPaintCanvas::drawLine(SkScalar x0, void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -187,7 +195,7 @@ void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -199,7 +207,7 @@ void SkiaPaintCanvas::drawIRect(const SkIRect& rect, const PaintFlags& flags) { void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -211,7 +219,7 @@ void SkiaPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) { void SkiaPaintCanvas::drawRRect(const SkRRect& rrect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -225,7 +233,7 @@ void SkiaPaintCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -241,7 +249,7 @@ void SkiaPaintCanvas::drawRoundRect(const SkRect& rect, SkScalar ry, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -256,7 +264,7 @@ void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags, UsePaintCache) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -275,7 +283,7 @@ void SkiaPaintCanvas::drawImage(const PaintImage& image, absl::optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - max_texture_size(), 255u); + GetMaxTextureSize(), 255u); if (!scoped_flags->flags()) return; } @@ -296,7 +304,7 @@ void SkiaPaintCanvas::drawImageRect(const PaintImage& image, absl::optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - max_texture_size(), 255u); + GetMaxTextureSize(), 255u); if (!scoped_flags->flags()) return; } @@ -312,7 +320,16 @@ void SkiaPaintCanvas::drawImageRect(const PaintImage& image, void SkiaPaintCanvas::drawSkottie(scoped_refptr<SkottieWrapper> skottie, const SkRect& dst, - float t) { + float t, + SkottieFrameDataMap images) { + if (!images.empty()) { + // This is not implemented solely because there's no use case yet. To + // implement, we could retrieve the underlying SkImage from each + // PaintImage in |images| here and call SkottieWrapper::SetImageForAsset(). + NOTIMPLEMENTED() + << "Rendering skottie frames with image assets directly to a " + "SkiaPaintCanvas is currently not supported."; + } skottie->Draw(canvas_, t, dst); } @@ -321,7 +338,7 @@ void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar y, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), max_texture_size(), + canvas_->getTotalMatrix(), GetMaxTextureSize(), 255u); if (!raster_flags.flags()) return; @@ -407,4 +424,9 @@ void SkiaPaintCanvas::FlushAfterDrawIfNeeded() { } } +int SkiaPaintCanvas::GetMaxTextureSize() const { + auto* context = canvas_->recordingContext(); + return context ? context->maxTextureSize() : 0; +} + } // namespace cc diff --git a/chromium/cc/paint/skia_paint_canvas.h b/chromium/cc/paint/skia_paint_canvas.h index d83020ced20..e9b0f704144 100644 --- a/chromium/cc/paint/skia_paint_canvas.h +++ b/chromium/cc/paint/skia_paint_canvas.h @@ -13,7 +13,6 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_record.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/gpu/GrRecordingContext.h" namespace cc { class ImageProvider; @@ -120,7 +119,8 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { SkCanvas::SrcRectConstraint constraint) override; void drawSkottie(scoped_refptr<SkottieWrapper> skottie, const SkRect& dst, - float t) override; + float t, + SkottieFrameDataMap images) override; void drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar x, SkScalar y, @@ -137,6 +137,8 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { SkMatrix getTotalMatrix() const override; SkM44 getLocalToDevice() const override; + bool NeedsFlush() const override; + void Annotate(AnnotationType type, const SkRect& rect, sk_sp<SkData> data) override; @@ -160,10 +162,7 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { private: void FlushAfterDrawIfNeeded(); - int max_texture_size() const { - auto* context = canvas_->recordingContext(); - return context ? context->maxTextureSize() : 0; - } + int GetMaxTextureSize() const; SkCanvas* canvas_; SkBitmap bitmap_; diff --git a/chromium/cc/paint/skottie_frame_data.cc b/chromium/cc/paint/skottie_frame_data.cc new file mode 100644 index 00000000000..45e2e2fca01 --- /dev/null +++ b/chromium/cc/paint/skottie_frame_data.cc @@ -0,0 +1,14 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_frame_data.h" + +namespace cc { + +bool operator==(const SkottieFrameData& frame_l, + const SkottieFrameData& frame_r) { + return frame_l.image == frame_r.image && frame_l.quality == frame_r.quality; +} + +} // namespace cc diff --git a/chromium/cc/paint/skottie_frame_data.h b/chromium/cc/paint/skottie_frame_data.h new file mode 100644 index 00000000000..c76115f0f3a --- /dev/null +++ b/chromium/cc/paint/skottie_frame_data.h @@ -0,0 +1,43 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_SKOTTIE_FRAME_DATA_H_ +#define CC_PAINT_SKOTTIE_FRAME_DATA_H_ + +#include "base/containers/flat_map.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/paint_flags.h" +#include "cc/paint/paint_image.h" +#include "cc/paint/skottie_resource_metadata.h" + +namespace cc { + +// The equivalent of skresources::ImageAsset::FrameData, except expressed in +// terms of Chromium Compositor constructs rather than Skia constructs. +// Represents the image to use for an asset in one frame of a Skottie animation. +// +// There's currently no use case for |skresources::ImageAsset::FrameData.matrix| +// so it is omitted for now. +struct CC_PAINT_EXPORT SkottieFrameData { + // PaintImage is preferable at the compositor layer instead of a "raw" + // SkImage. It not only is more well supported for circulating through the + // compositor/graphics pipeline, but also gives the client the most + // versatility for how the image is "backed" (ex: a PaintImageGenerator or + // PaintRecord can be used). + PaintImage image; + // Chromium version of SkSamplingOptions. Controls resampling quality if the + // image needs to be resized when rendering. + PaintFlags::FilterQuality quality; +}; + +CC_PAINT_EXPORT bool operator==(const SkottieFrameData& frame_l, + const SkottieFrameData& frame_r); + +// Map from asset id to the image to use for that asset. +using SkottieFrameDataMap = + base::flat_map<SkottieResourceIdHash, SkottieFrameData>; + +} // namespace cc + +#endif // CC_PAINT_SKOTTIE_FRAME_DATA_H_ diff --git a/chromium/cc/paint/skottie_frame_data_provider.h b/chromium/cc/paint/skottie_frame_data_provider.h new file mode 100644 index 00000000000..28542f74a61 --- /dev/null +++ b/chromium/cc/paint/skottie_frame_data_provider.h @@ -0,0 +1,70 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_SKOTTIE_FRAME_DATA_PROVIDER_H_ +#define CC_PAINT_SKOTTIE_FRAME_DATA_PROVIDER_H_ + +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/strings/string_piece.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/skottie_frame_data.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace cc { + +// A Chromium-specific version of the skresources::ResourceProvider API, which +// allows the code driving the animation to specify which image should be used +// for each asset in each frame of the animation. Callers rendering Skottie +// animations that may have images embedded in them must implement this API. In +// the most basic case where an image asset does not change throughout the +// course of the animation, the same image can be provided for every frame. But +// more complex logic such as providing a different image at the start of each +// animation cycle can be implemented if desired. +// +// Implementations are not required to be thread-safe (the provider and its +// ImageAssets shall always be invoked from the same sequence). +class CC_PAINT_EXPORT SkottieFrameDataProvider { + public: + class CC_PAINT_EXPORT ImageAsset + : public base::RefCountedThreadSafe<ImageAsset> { + public: + // Returns the image to use for an asset in a frame of a skottie animation. + // If absl::nullopt is returned, the most recently provided image for this + // asset is reused when the frame is rendered. Thus, the ImageAsset may + // return "null" if: a) The most recent image intentionally should be + // reused or b) The provider knows that this particular asset does not + // appear at the specified timestamp of the animation. + // + // |t|: See skresources::ImageAsset::getFrame(). Same semantics. Specifies + // the frame of interest in the animation that's about to be rendered. + // |scale_factor|: See |image_scale| in gfx::Canvas. Can be used to generate + // a PaintImage from a gfx::ImageSkia instance. + virtual absl::optional<SkottieFrameData> GetFrameData( + float t, + float scale_factor) = 0; + + protected: + virtual ~ImageAsset() = default; + + private: + friend class base::RefCountedThreadSafe<ImageAsset>; + }; + + virtual ~SkottieFrameDataProvider() = default; + + // Loads the image asset in the animation with the given |resource_id|, as it + // appears in the lottie json file. The ImageAsset instance that's returned + // for the given |resource_id| gets re-used for the lifetime of the animation; + // LoadImageAsset() is not called multiple times for the same |resource_id|. + // The returned value must never be null. + virtual scoped_refptr<ImageAsset> LoadImageAsset( + base::StringPiece resource_id, + const base::FilePath& resource_path) = 0; +}; + +} // namespace cc + +#endif // CC_PAINT_SKOTTIE_FRAME_DATA_PROVIDER_H_ diff --git a/chromium/cc/paint/skottie_mru_resource_provider.cc b/chromium/cc/paint/skottie_mru_resource_provider.cc new file mode 100644 index 00000000000..8a522d2dcb7 --- /dev/null +++ b/chromium/cc/paint/skottie_mru_resource_provider.cc @@ -0,0 +1,77 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_mru_resource_provider.h" + +#include <utility> + +#include "base/check.h" +#include "base/logging.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkRefCnt.h" + +namespace cc { +namespace { + +class ImageAssetImpl : public skresources::ImageAsset { + public: + using FrameData = skresources::ImageAsset::FrameData; + using FrameDataCallback = SkottieWrapper::FrameDataCallback; + + ImageAssetImpl(SkottieResourceIdHash asset_id, + FrameDataCallback frame_data_cb) + : asset_id_(asset_id), frame_data_cb_(std::move(frame_data_cb)) { + DCHECK(frame_data_cb_); + } + + bool isMultiFrame() override { return true; } + + FrameData getFrameData(float t) override { + FrameData new_frame_data; + SkottieWrapper::FrameDataFetchResult result = frame_data_cb_.Run( + asset_id_, t, new_frame_data.image, new_frame_data.sampling); + switch (result) { + case SkottieWrapper::FrameDataFetchResult::NEW_DATA_AVAILABLE: + current_frame_data_ = std::move(new_frame_data); + break; + case SkottieWrapper::FrameDataFetchResult::NO_UPDATE: + break; + } + return current_frame_data_; + } + + private: + const SkottieResourceIdHash asset_id_; + const FrameDataCallback frame_data_cb_; + FrameData current_frame_data_; +}; + +} // namespace + +SkottieMRUResourceProvider::SkottieMRUResourceProvider( + FrameDataCallback frame_data_cb) + : frame_data_cb_(std::move(frame_data_cb)) {} + +SkottieMRUResourceProvider::~SkottieMRUResourceProvider() = default; + +const SkottieResourceMetadataMap& +SkottieMRUResourceProvider::GetImageAssetMetadata() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return image_asset_metadata_; +} + +sk_sp<skresources::ImageAsset> SkottieMRUResourceProvider::loadImageAsset( + const char resource_path[], + const char resource_name[], + const char resource_id[]) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!image_asset_metadata_.RegisterAsset(resource_path, resource_name, + resource_id)) { + return nullptr; + } + return sk_make_sp<ImageAssetImpl>(HashSkottieResourceId(resource_id), + frame_data_cb_); +} + +} // namespace cc diff --git a/chromium/cc/paint/skottie_mru_resource_provider.h b/chromium/cc/paint/skottie_mru_resource_provider.h new file mode 100644 index 00000000000..3140d2748f9 --- /dev/null +++ b/chromium/cc/paint/skottie_mru_resource_provider.h @@ -0,0 +1,56 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_SKOTTIE_MRU_RESOURCE_PROVIDER_H_ +#define CC_PAINT_SKOTTIE_MRU_RESOURCE_PROVIDER_H_ + +#include "base/sequence_checker.h" +#include "cc/paint/paint_export.h" +#include "cc/paint/skottie_resource_metadata.h" +#include "cc/paint/skottie_wrapper.h" +#include "third_party/skia/modules/skresources/include/SkResources.h" + +namespace cc { + +// Provides Skottie the most recent SkImage that was returned by a +// SkottieWrapper::FrameDataCallback for each ImageAsset. Note this is a +// "multi-frame" ResourceProvider, so the caller is capable of supporting +// animations where the image assets do/don't change between frames. +// +// Not thread-safe. All public methods must be called from the sequence that +// SkottieMRUResourceProvider is constructed on. +class CC_PAINT_EXPORT SkottieMRUResourceProvider + : public skresources::ResourceProvider { + public: + using FrameDataCallback = SkottieWrapper::FrameDataCallback; + + explicit SkottieMRUResourceProvider(FrameDataCallback frame_data_cb); + SkottieMRUResourceProvider(const SkottieMRUResourceProvider&) = delete; + SkottieMRUResourceProvider& operator=(const SkottieMRUResourceProvider&) = + delete; + ~SkottieMRUResourceProvider() override; + + // Contains the metadata for all currently known ImageAssets in the animation. + const SkottieResourceMetadataMap& GetImageAssetMetadata() const; + + private: + // skresources::ResourceProvider implementation: + sk_sp<skresources::ImageAsset> loadImageAsset( + const char resource_path[], + const char resource_name[], + const char resource_id[]) const override; + + const SkottieWrapper::FrameDataCallback frame_data_cb_; + // SkResources.h declares loadImageAsset() as a "const" method. Although the + // method is logically const, these book-keeping members need to be updated in + // that method. Hence, they're marked "mutable". + mutable SkottieResourceMetadataMap image_asset_metadata_ + GUARDED_BY_CONTEXT(sequence_checker_); + + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace cc + +#endif // CC_PAINT_SKOTTIE_MRU_RESOURCE_PROVIDER_H_ diff --git a/chromium/cc/paint/skottie_mru_resource_provider_unittest.cc b/chromium/cc/paint/skottie_mru_resource_provider_unittest.cc new file mode 100644 index 00000000000..90ad41f6bfa --- /dev/null +++ b/chromium/cc/paint/skottie_mru_resource_provider_unittest.cc @@ -0,0 +1,135 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_mru_resource_provider.h" + +#include <utility> + +#include "base/bind.h" +#include "base/containers/flat_map.h" +#include "base/files/file_path.h" +#include "base/memory/raw_ptr.h" +#include "base/strings/string_piece.h" +#include "cc/paint/paint_image.h" +#include "cc/paint/skottie_resource_metadata.h" +#include "cc/test/skia_common.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkRefCnt.h" +#include "third_party/skia/modules/skresources/include/SkResources.h" +#include "ui/gfx/geometry/size.h" + +namespace cc { +namespace { + +using ::testing::Contains; +using ::testing::Eq; +using ::testing::Key; +using ::testing::Pair; +using ::testing::SizeIs; +using ::testing::UnorderedElementsAre; + +class FrameDataStub { + public: + using FrameData = skresources::ImageAsset::FrameData; + + void SetAssetFrameData(base::StringPiece asset_id, + FrameData current_frame_data) { + asset_to_frame_data_[HashSkottieResourceId(asset_id)] = + std::move(current_frame_data); + asset_to_result_[HashSkottieResourceId(asset_id)] = + SkottieWrapper::FrameDataFetchResult::NEW_DATA_AVAILABLE; + } + + void SetAssetResult(base::StringPiece asset_id, + SkottieWrapper::FrameDataFetchResult current_result) { + asset_to_result_[HashSkottieResourceId(asset_id)] = current_result; + } + + SkottieWrapper::FrameDataFetchResult GetFrameDataForAsset( + SkottieResourceIdHash asset_id, + float t, + sk_sp<SkImage>& image_out, + SkSamplingOptions& sampling_out) const { + if (asset_to_frame_data_.contains(asset_id)) { + image_out = asset_to_frame_data_.at(asset_id).image; + sampling_out = asset_to_frame_data_.at(asset_id).sampling; + } + return asset_to_result_.contains(asset_id) + ? asset_to_result_.at(asset_id) + : SkottieWrapper::FrameDataFetchResult::NO_UPDATE; + } + + private: + base::flat_map<SkottieResourceIdHash, FrameData> asset_to_frame_data_; + base::flat_map<SkottieResourceIdHash, SkottieWrapper::FrameDataFetchResult> + asset_to_result_; +}; + +class SkottieMRUResourceProviderTest : public ::testing::Test { + protected: + SkottieMRUResourceProviderTest() + : provider_(sk_make_sp<SkottieMRUResourceProvider>( + base::BindRepeating(&FrameDataStub::GetFrameDataForAsset, + base::Unretained(&frame_data_stub_)))), + provider_base_(provider_.get()) {} + + FrameDataStub frame_data_stub_; + const sk_sp<SkottieMRUResourceProvider> provider_; + const raw_ptr<skresources::ResourceProvider> provider_base_; +}; + +TEST_F(SkottieMRUResourceProviderTest, ProvidesMostRecentFrameDataForAsset) { + sk_sp<skresources::ImageAsset> asset = provider_base_->loadImageAsset( + "test-resource-path", "test-resource-name", "test-resource-id"); + PaintImage image_1 = CreateBitmapImage(gfx::Size(10, 10)); + frame_data_stub_.SetAssetFrameData("test-resource-id", + {.image = image_1.GetSwSkImage()}); + EXPECT_THAT(asset->getFrameData(/*t=*/0).image, Eq(image_1.GetSwSkImage())); + // The same image should be re-used for the next timestamp. + frame_data_stub_.SetAssetResult( + "test-resource-id", SkottieWrapper::FrameDataFetchResult::NO_UPDATE); + EXPECT_THAT(asset->getFrameData(/*t=*/0.1).image, Eq(image_1.GetSwSkImage())); + // Now the new image should be used. + PaintImage image_2 = CreateBitmapImage(gfx::Size(20, 20)); + frame_data_stub_.SetAssetFrameData("test-resource-id", + {.image = image_2.GetSwSkImage()}); + EXPECT_THAT(asset->getFrameData(/*t=*/0.2).image, Eq(image_2.GetSwSkImage())); +} + +TEST_F(SkottieMRUResourceProviderTest, ProvidesFrameDataForMultipleAssets) { + sk_sp<skresources::ImageAsset> asset_1 = provider_base_->loadImageAsset( + "test-resource-path", "test-resource-name", "test-resource-id-1"); + sk_sp<skresources::ImageAsset> asset_2 = provider_base_->loadImageAsset( + "test-resource-path", "test-resource-name", "test-resource-id-2"); + PaintImage image_1 = CreateBitmapImage(gfx::Size(10, 10)); + frame_data_stub_.SetAssetFrameData("test-resource-id-1", + {.image = image_1.GetSwSkImage()}); + PaintImage image_2 = CreateBitmapImage(gfx::Size(20, 20)); + frame_data_stub_.SetAssetFrameData("test-resource-id-2", + {.image = image_2.GetSwSkImage()}); + EXPECT_THAT(asset_1->getFrameData(/*t=*/0).image, Eq(image_1.GetSwSkImage())); + EXPECT_THAT(asset_2->getFrameData(/*t=*/0).image, Eq(image_2.GetSwSkImage())); +} + +TEST_F(SkottieMRUResourceProviderTest, ReturnsCorrectImageAssetMetadata) { + sk_sp<skresources::ImageAsset> asset_1 = provider_base_->loadImageAsset( + "test-resource-path-1", "test-resource-name-1", "test-resource-id-1"); + sk_sp<skresources::ImageAsset> asset_2 = provider_base_->loadImageAsset( + "test-resource-path-2", "test-resource-name-2", "test-resource-id-2"); + EXPECT_THAT( + provider_->GetImageAssetMetadata().asset_storage(), + UnorderedElementsAre( + Pair("test-resource-id-1", + base::FilePath(FILE_PATH_LITERAL( + "test-resource-path-1/test-resource-name-1")) + .NormalizePathSeparators()), + Pair("test-resource-id-2", + base::FilePath(FILE_PATH_LITERAL( + "test-resource-path-2/test-resource-name-2")) + .NormalizePathSeparators()))); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/paint/skottie_resource_metadata.cc b/chromium/cc/paint/skottie_resource_metadata.cc new file mode 100644 index 00000000000..39057813bfa --- /dev/null +++ b/chromium/cc/paint/skottie_resource_metadata.cc @@ -0,0 +1,58 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_resource_metadata.h" + +#include "base/check.h" +#include "base/hash/hash.h" +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" + +namespace cc { + +SkottieResourceMetadataMap::SkottieResourceMetadataMap() = default; + +SkottieResourceMetadataMap::SkottieResourceMetadataMap( + const SkottieResourceMetadataMap&) = default; + +SkottieResourceMetadataMap& SkottieResourceMetadataMap::operator=( + const SkottieResourceMetadataMap&) = default; + +SkottieResourceMetadataMap::~SkottieResourceMetadataMap() = default; + +bool SkottieResourceMetadataMap::RegisterAsset(base::StringPiece resource_path, + base::StringPiece resource_name, + base::StringPiece resource_id) { + if (resource_id.empty()) { + LOG(ERROR) << "Skottie animation has asset with empty resource_id"; + return false; + } + + base::FilePath resource_name_component = + base::FilePath::FromASCII(resource_name); + if (resource_name_component.IsAbsolute()) { + // If the path is absolute, base::FilePath::Append() will fail anyways, + // likely with a fatal error. + LOG(ERROR) << "Skottie animation specifies an absolute resource_name path: " + << resource_name << ". Must be relative."; + return false; + } + + bool inserted = asset_storage_ + .try_emplace(std::string(resource_id), + base::FilePath::FromASCII(resource_path) + .Append(resource_name_component)) + .second; + if (!inserted) { + LOG(ERROR) << "Skottie animation has assets with duplicate resource_id: " + << resource_id; + } + return inserted; +} + +SkottieResourceIdHash HashSkottieResourceId(base::StringPiece resource_id) { + return SkottieResourceIdHash::FromUnsafeValue(base::FastHash(resource_id)); +} + +} // namespace cc diff --git a/chromium/cc/paint/skottie_resource_metadata.h b/chromium/cc/paint/skottie_resource_metadata.h new file mode 100644 index 00000000000..67f7e22920d --- /dev/null +++ b/chromium/cc/paint/skottie_resource_metadata.h @@ -0,0 +1,55 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_SKOTTIE_RESOURCE_METADATA_H_ +#define CC_PAINT_SKOTTIE_RESOURCE_METADATA_H_ + +#include <string> + +#include "base/containers/flat_map.h" +#include "base/files/file_path.h" +#include "base/strings/string_piece.h" +#include "base/types/id_type.h" +#include "cc/paint/paint_export.h" + +namespace cc { + +// Each asset in a Skottie animation has a unique "resource_id" in string +// format. This is a map from resource_id to its corresponding location. +class CC_PAINT_EXPORT SkottieResourceMetadataMap { + public: + using Storage = base::flat_map<std::string /*resource_id*/, + base::FilePath /*resource_path*/>; + + SkottieResourceMetadataMap(); + SkottieResourceMetadataMap(const SkottieResourceMetadataMap&); + SkottieResourceMetadataMap& operator=(const SkottieResourceMetadataMap&); + ~SkottieResourceMetadataMap(); + + // Adds a new asset to the map. Returns true on success; false if an asset + // with the provided |resource_id| already exists or if the |resource_id| is + // invalid. + // + // The arguments used here deliberately reflect those in Skia's + // ResourceProvider::loadImageAsset(). + bool RegisterAsset(base::StringPiece resource_path, + base::StringPiece resource_name, + base::StringPiece resource_id); + + const Storage& asset_storage() const { return asset_storage_; } + + private: + Storage asset_storage_; +}; + +// For performance reasons, the resource_id can be hashed, and the caller can +// circulate the resulting integer throughout the system. +using SkottieResourceIdHash = + base::IdType<SkottieResourceMetadataMap, size_t, 0>; +SkottieResourceIdHash CC_PAINT_EXPORT +HashSkottieResourceId(base::StringPiece resource_id); + +} // namespace cc + +#endif // CC_PAINT_SKOTTIE_RESOURCE_METADATA_H_ diff --git a/chromium/cc/paint/skottie_resource_metadata_unittest.cc b/chromium/cc/paint/skottie_resource_metadata_unittest.cc new file mode 100644 index 00000000000..7c339cbf94d --- /dev/null +++ b/chromium/cc/paint/skottie_resource_metadata_unittest.cc @@ -0,0 +1,74 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_resource_metadata.h" + +#include "base/files/file_path.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +using ::testing::AllOf; +using ::testing::Eq; +using ::testing::Field; +using ::testing::Ne; +using ::testing::Pair; +using ::testing::UnorderedElementsAre; + +TEST(SkottieResourceMetadataTest, SkottieResourceMetadataMapRegistersAssets) { + SkottieResourceMetadataMap resource_map; + ASSERT_TRUE(resource_map.RegisterAsset( + "test-resource-path-1", "test-resource-name-1", "test-resource-id-1")); + ASSERT_TRUE(resource_map.RegisterAsset( + "test-resource-path-2", "test-resource-name-2", "test-resource-id-2")); + EXPECT_THAT( + resource_map.asset_storage(), + UnorderedElementsAre( + Pair("test-resource-id-1", + base::FilePath(FILE_PATH_LITERAL( + "test-resource-path-1/test-resource-name-1")) + .NormalizePathSeparators()), + Pair("test-resource-id-2", + base::FilePath(FILE_PATH_LITERAL( + "test-resource-path-2/test-resource-name-2")) + .NormalizePathSeparators()))); +} + +TEST(SkottieResourceMetadataTest, + SkottieResourceMetadataMapRejectsDuplicateAssets) { + SkottieResourceMetadataMap resource_map; + ASSERT_TRUE(resource_map.RegisterAsset( + "test-resource-path-1", "test-resource-name-1", "test-resource-id-1")); + EXPECT_FALSE(resource_map.RegisterAsset( + "test-resource-path-2", "test-resource-name-2", "test-resource-id-1")); +} + +TEST(SkottieResourceMetadataTest, + SkottieResourceMetadataMapRejectsEmptyAssets) { + SkottieResourceMetadataMap resource_map; + EXPECT_FALSE(resource_map.RegisterAsset( + "test-resource-path", "test-resource-name", /*resource_id=*/"")); +} + +TEST(SkottieResourceMetadataTest, + SkottieResourceMetadataMapRejectsAbsoluteResourceNames) { + SkottieResourceMetadataMap resource_map; + EXPECT_FALSE(resource_map.RegisterAsset( + "test-resource-path", "/absolute-resource-name", /*resource_id=*/"")); +} + +TEST(SkottieResourceMetadataTest, HashSkottieResourceIdReturnsMatchingHashes) { + EXPECT_THAT(HashSkottieResourceId("test-resource-id-1"), + Eq(HashSkottieResourceId("test-resource-id-1"))); +} + +TEST(SkottieResourceMetadataTest, HashSkottieResourceIdReturnsDifferentHashes) { + EXPECT_THAT(HashSkottieResourceId("test-resource-id-1"), + Ne(HashSkottieResourceId("test-resource-id-2"))); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/paint/skottie_transfer_cache_entry_unittest.cc b/chromium/cc/paint/skottie_transfer_cache_entry_unittest.cc index 812c697e66c..8ee012f4c06 100644 --- a/chromium/cc/paint/skottie_transfer_cache_entry_unittest.cc +++ b/chromium/cc/paint/skottie_transfer_cache_entry_unittest.cc @@ -3,54 +3,25 @@ // found in the LICENSE file. #include <memory> +#include <utility> +#include <vector> #include "base/containers/span.h" #include "base/memory/scoped_refptr.h" #include "cc/paint/skottie_transfer_cache_entry.h" #include "cc/paint/skottie_wrapper.h" +#include "cc/test/lottie_test_data.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkSize.h" namespace cc { -namespace { - -// A skottie animation with solid green color for the first 2.5 seconds and then -// a solid blue color for the next 2.5 seconds. -constexpr char kData[] = - "{" - " \"v\" : \"4.12.0\"," - " \"fr\": 30," - " \"w\" : 400," - " \"h\" : 200," - " \"ip\": 0," - " \"op\": 150," - " \"assets\": []," - - " \"layers\": [" - " {" - " \"ty\": 1," - " \"sw\": 400," - " \"sh\": 200," - " \"sc\": \"#00ff00\"," - " \"ip\": 0," - " \"op\": 75" - " }," - " {" - " \"ty\": 1," - " \"sw\": 400," - " \"sh\": 200," - " \"sc\": \"#0000ff\"," - " \"ip\": 76," - " \"op\": 150" - " }" - " ]" - "}"; - -} // namespace TEST(SkottieTransferCacheEntryTest, SerializationDeserialization) { - std::vector<uint8_t> a_data(std::strlen(kData)); - a_data.assign(reinterpret_cast<const uint8_t*>(kData), - reinterpret_cast<const uint8_t*>(kData) + std::strlen(kData)); + std::vector<uint8_t> a_data(kLottieDataWithoutAssets1.length()); + a_data.assign( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()), + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()) + + kLottieDataWithoutAssets1.length()); scoped_refptr<SkottieWrapper> skottie = SkottieWrapper::CreateSerializable(std::move(a_data)); diff --git a/chromium/cc/paint/skottie_wrapper.cc b/chromium/cc/paint/skottie_wrapper.cc index 6656ce5cfd0..1c12844e872 100644 --- a/chromium/cc/paint/skottie_wrapper.cc +++ b/chromium/cc/paint/skottie_wrapper.cc @@ -1,52 +1,17 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "cc/paint/skottie_wrapper.h" -#include <vector> - -#include "base/hash/hash.h" -#include "base/trace_event/trace_event.h" namespace cc { -// static -scoped_refptr<SkottieWrapper> SkottieWrapper::CreateSerializable( - std::vector<uint8_t> data) { - return base::WrapRefCounted<SkottieWrapper>( - new SkottieWrapper(std::move(data))); -} - -// static -scoped_refptr<SkottieWrapper> SkottieWrapper::CreateNonSerializable( - base::span<const uint8_t> data) { - return base::WrapRefCounted<SkottieWrapper>(new SkottieWrapper(data)); +void SkottieWrapper::Seek(float t) { + Seek(t, FrameDataCallback()); } -SkottieWrapper::SkottieWrapper(base::span<const uint8_t> data) - : animation_( - skottie::Animation::Make(reinterpret_cast<const char*>(data.data()), - data.size())), - id_(base::FastHash(data)) {} - -SkottieWrapper::SkottieWrapper(std::vector<uint8_t> data) - : animation_( - skottie::Animation::Make(reinterpret_cast<const char*>(data.data()), - data.size())), - raw_data_(std::move(data)), - id_(base::FastHash(raw_data_)) {} - -SkottieWrapper::~SkottieWrapper() = default; - void SkottieWrapper::Draw(SkCanvas* canvas, float t, const SkRect& rect) { - base::AutoLock lock(lock_); - animation_->seek(t); - animation_->render(canvas, &rect); -} - -base::span<const uint8_t> SkottieWrapper::raw_data() const { - DCHECK(raw_data_.size()); - return base::as_bytes(base::make_span(raw_data_.data(), raw_data_.size())); + Draw(canvas, t, rect, FrameDataCallback()); } } // namespace cc diff --git a/chromium/cc/paint/skottie_wrapper.h b/chromium/cc/paint/skottie_wrapper.h index abf92010e28..64edab1a199 100644 --- a/chromium/cc/paint/skottie_wrapper.h +++ b/chromium/cc/paint/skottie_wrapper.h @@ -5,23 +5,30 @@ #ifndef CC_PAINT_SKOTTIE_WRAPPER_H_ #define CC_PAINT_SKOTTIE_WRAPPER_H_ -#include <memory> #include <vector> +#include "base/callback.h" #include "base/containers/span.h" #include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" #include "cc/paint/paint_export.h" -#include "third_party/skia/modules/skottie/include/Skottie.h" +#include "cc/paint/skottie_resource_metadata.h" +#include "third_party/skia/include/core/SkRefCnt.h" +#include "third_party/skia/include/core/SkSamplingOptions.h" class SkCanvas; +class SkImage; struct SkRect; +struct SkSize; namespace cc { // A wrapper over Skia's Skottie object that can be shared by multiple // SkiaVectorAnimation objects. This class is thread safe when performing a draw // on an SkCanvas. +// +// The API intentionally does not have any dependencies on the Skottie public +// header files. This is to facilitate a "dummy" implementation for builds where +// the Skottie library should not be compiled/linked into the final binary. class CC_PAINT_EXPORT SkottieWrapper : public base::RefCountedThreadSafe<SkottieWrapper> { public: @@ -35,42 +42,73 @@ class CC_PAINT_EXPORT SkottieWrapper base::span<const uint8_t> data); SkottieWrapper(const SkottieWrapper&) = delete; - SkottieWrapper& operator=(const SkottieWrapper&) = delete; - // Returns true if the |animation_| object initialized is a valid skottie - // animation. - bool is_valid() const { return !!animation_; } + // Returns true if this object contains a valid skottie animation. + virtual bool is_valid() const = 0; + + // Returns the set of all image assets in the animation and their + // corresponding metadata. The returned map is effectively immutable; it + // does not change during SkottieWrapper's lifetime. + virtual const SkottieResourceMetadataMap& GetImageAssetMetadata() const = 0; + + // FrameDataCallback is implemented by the caller and invoked + // synchronously during calls to Seek() and Draw(). The callback is used by + // SkottieWrapper to fetch the corresponding image for each asset that is + // present in the frame with the desired timestamp. It is invoked once for + // each asset. A null callback may be passed to Seek() and Draw() if the + // animation is known to not have any image assets. + enum class FrameDataFetchResult { + // A new image is available for the given asset, and the callback's output + // parameters have been filled with the new frame data. + NEW_DATA_AVAILABLE, + // The callback's output parameters have not been filled and will be + // ignored by SkottieWrapper. In this case, SkottieWrapper will reuse the + // frame data that was most recently provided for the given asset (it caches + // this internally). If no frame data has ever been provided for this asset, + // a null image will be passed to Skottie's Animation during Seek(); this + // is acceptable if there's no rendering. + NO_UPDATE, + }; + // The callback's implementation must synchronously fill the output + // arguments. |asset_id| is guaranteed to be a valid asset that's present + // in GetImageAssetMetadata(). See skresources::ImageAsset::getFrame() for + // the semantics of |t|. + using FrameDataCallback = base::RepeatingCallback<FrameDataFetchResult( + SkottieResourceIdHash asset_id, + float t, + sk_sp<SkImage>& image_out, + SkSamplingOptions& sampling_out)>; + + // Seeks to the normalized time instant |t|, but does not render. This method + // is thread safe. + virtual void Seek(float t, FrameDataCallback frame_data_cb) = 0; + // Variant with null FrameDataCallback() if the animation does not have image + // assets. + void Seek(float t); // A thread safe call that will draw an image with bounds |rect| for the // frame at normalized time instant |t| onto the |canvas|. + virtual void Draw(SkCanvas* canvas, + float t, + const SkRect& rect, + FrameDataCallback frame_data_cb) = 0; + // Variant with null FrameDataCallback() if the animation does not have image + // assets. void Draw(SkCanvas* canvas, float t, const SkRect& rect); - float duration() const { return animation_->duration(); } - SkSize size() const { return animation_->size(); } + virtual float duration() const = 0; + virtual SkSize size() const = 0; + + virtual base::span<const uint8_t> raw_data() const = 0; + virtual uint32_t id() const = 0; - base::span<const uint8_t> raw_data() const; - uint32_t id() const { return id_; } + protected: + SkottieWrapper() = default; + virtual ~SkottieWrapper() = default; private: friend class base::RefCountedThreadSafe<SkottieWrapper>; - - explicit SkottieWrapper(base::span<const uint8_t> data); - explicit SkottieWrapper(std::vector<uint8_t> data); - - ~SkottieWrapper(); - - base::Lock lock_; - sk_sp<skottie::Animation> animation_; - - // The raw byte data is stored for serialization across OOP-R. This is only - // valid if serialization was enabled at construction. - const std::vector<uint8_t> raw_data_; - - // Unique id generated for a given animation. This will be unique per - // animation file. 2 animation objects from the same source file will have the - // same value. - const uint32_t id_; }; } // namespace cc diff --git a/chromium/cc/paint/skottie_wrapper_impl.cc b/chromium/cc/paint/skottie_wrapper_impl.cc new file mode 100644 index 00000000000..e401994e679 --- /dev/null +++ b/chromium/cc/paint/skottie_wrapper_impl.cc @@ -0,0 +1,167 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_wrapper.h" + +#include <functional> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/hash/hash.h" +#include "base/logging.h" +#include "base/synchronization/lock.h" +#include "base/thread_annotations.h" +#include "base/trace_event/trace_event.h" +#include "cc/paint/skottie_mru_resource_provider.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/modules/skottie/include/Skottie.h" +#include "third_party/skia/modules/skresources/include/SkResources.h" + +namespace cc { +namespace { + +// Directs logs from the skottie animation builder to //base/logging. Without +// this, errors/warnings from the animation builder get silently dropped. +class SkottieLogWriter : public skottie::Logger { + public: + void log(Level level, const char message[], const char* json) override { + static constexpr char kSkottieLogPrefix[] = "[Skottie] \""; + static constexpr char kSkottieLogSuffix[] = "\""; + switch (level) { + case Level::kWarning: + LOG(WARNING) << kSkottieLogPrefix << message << kSkottieLogSuffix; + break; + case Level::kError: + LOG(ERROR) << kSkottieLogPrefix << message << kSkottieLogSuffix; + break; + } + } +}; + +class SkottieWrapperImpl : public SkottieWrapper { + public: + SkottieWrapperImpl(base::span<const uint8_t> data, + std::vector<uint8_t> owned_data) + : SkottieWrapperImpl( + data, + owned_data, + // * Unretained is safe because SkottieMRUResourceProvider cannot + // outlive SkottieWrapperImpl. + // * Binding "this" in the constructor is safe because the frame + // data callback is only triggered during calls to + // |animation_->seek()|. + sk_make_sp<SkottieMRUResourceProvider>(base::BindRepeating( + &SkottieWrapperImpl::RunCurrentFrameDataCallback, + base::Unretained(this)))) {} + + SkottieWrapperImpl(const SkottieWrapperImpl&) = delete; + SkottieWrapperImpl& operator=(const SkottieWrapperImpl&) = delete; + + // SkottieWrapper implementation: + bool is_valid() const override { return !!animation_; } + + const SkottieResourceMetadataMap& GetImageAssetMetadata() const override { + return image_asset_metadata_; + } + + void Seek(float t, FrameDataCallback frame_data_cb) override + LOCKS_EXCLUDED(lock_) { + base::AutoLock lock(lock_); + // There's no need to reset |current_frame_data_cb_| to null when finished. + // The callback is guaranteed to only be invoked synchronously during calls + // to |animation_->seek/render()|, and not thereafter. + current_frame_data_cb_ = std::move(frame_data_cb); + animation_->seek(t); + } + + void Draw(SkCanvas* canvas, + float t, + const SkRect& rect, + FrameDataCallback frame_data_cb) override LOCKS_EXCLUDED(lock_) { + base::AutoLock lock(lock_); + current_frame_data_cb_ = std::move(frame_data_cb); + animation_->seek(t); + animation_->render(canvas, &rect); + } + + float duration() const override { return animation_->duration(); } + + SkSize size() const override { return animation_->size(); } + + base::span<const uint8_t> raw_data() const override { + DCHECK(raw_data_.size()); + return base::as_bytes(base::make_span(raw_data_.data(), raw_data_.size())); + } + + uint32_t id() const override { return id_; } + + private: + SkottieWrapperImpl( + base::span<const uint8_t> data, + std::vector<uint8_t> raw_data, + const sk_sp<SkottieMRUResourceProvider>& mru_resource_provider) + : animation_( + skottie::Animation::Builder() + .setLogger(sk_make_sp<SkottieLogWriter>()) + .setResourceProvider(skresources::CachingResourceProvider::Make( + mru_resource_provider)) + .make(reinterpret_cast<const char*>(data.data()), data.size())), + raw_data_(std::move(raw_data)), + id_(base::FastHash(data)), + // The underlying assumption here is that |skottie::Animation::Builder| + // loads image assets on initialization rather than doing so lazily at + // |render()| time. This is the case currently, and there will be unit + // test failures if this does not hold at some point in the future. + image_asset_metadata_(mru_resource_provider->GetImageAssetMetadata()) {} + + ~SkottieWrapperImpl() override = default; + + FrameDataFetchResult RunCurrentFrameDataCallback( + SkottieResourceIdHash asset_id_hash, + float t, + sk_sp<SkImage>& image_out, + SkSamplingOptions& sampling_out) EXCLUSIVE_LOCKS_REQUIRED(lock_) { + lock_.AssertAcquired(); + DCHECK(current_frame_data_cb_); + return current_frame_data_cb_.Run(asset_id_hash, t, image_out, + sampling_out); + } + + base::Lock lock_; + FrameDataCallback current_frame_data_cb_ GUARDED_BY(lock_); + sk_sp<skottie::Animation> animation_; + + // The raw byte data is stored for serialization across OOP-R. This is only + // valid if serialization was enabled at construction. + const std::vector<uint8_t> raw_data_; + + // Unique id generated for a given animation. This will be unique per + // animation file. 2 animation objects from the same source file will have the + // same value. + const uint32_t id_; + + const SkottieResourceMetadataMap image_asset_metadata_; +}; + +} // namespace + +// static +scoped_refptr<SkottieWrapper> SkottieWrapper::CreateSerializable( + std::vector<uint8_t> data) { + base::span<const uint8_t> data_span(data); + return base::WrapRefCounted( + new SkottieWrapperImpl(data_span, std::move(data))); +} + +// static +scoped_refptr<SkottieWrapper> SkottieWrapper::CreateNonSerializable( + base::span<const uint8_t> data) { + return base::WrapRefCounted( + new SkottieWrapperImpl(data, + /*owned_data=*/std::vector<uint8_t>())); +} + +} // namespace cc diff --git a/chromium/cc/paint/skottie_wrapper_stub.cc b/chromium/cc/paint/skottie_wrapper_stub.cc new file mode 100644 index 00000000000..b298d717c02 --- /dev/null +++ b/chromium/cc/paint/skottie_wrapper_stub.cc @@ -0,0 +1,29 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_wrapper.h" + +#include "base/check.h" + +namespace cc { + +// This stub source file is only built on platforms that don't support skottie. +// Skottie code paths should not be taken at all on these platforms, so +// a concrete SkottieWrapper implementation is not required. + +// static +scoped_refptr<SkottieWrapper> SkottieWrapper::CreateSerializable( + std::vector<uint8_t> data) { + CHECK(false) << "Skottie is not supported on this platform"; + return nullptr; +} + +// static +scoped_refptr<SkottieWrapper> SkottieWrapper::CreateNonSerializable( + base::span<const uint8_t> data) { + CHECK(false) << "Skottie is not supported on this platform"; + return nullptr; +} + +} // namespace cc diff --git a/chromium/cc/paint/skottie_wrapper_unittest.cc b/chromium/cc/paint/skottie_wrapper_unittest.cc new file mode 100644 index 00000000000..61f6a9820f2 --- /dev/null +++ b/chromium/cc/paint/skottie_wrapper_unittest.cc @@ -0,0 +1,173 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/paint/skottie_wrapper.h" + +#include <cstdint> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/containers/span.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_refptr.h" +#include "cc/paint/skottie_mru_resource_provider.h" +#include "cc/paint/skottie_resource_metadata.h" +#include "cc/test/lottie_test_data.h" +#include "cc/test/skia_common.h" +#include "cc/test/test_skcanvas.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace cc { +namespace { + +using ::testing::_; +using ::testing::Contains; +using ::testing::Eq; +using ::testing::IsEmpty; +using ::testing::Key; +using ::testing::Mock; +using ::testing::Ne; +using ::testing::NotNull; +using ::testing::Pair; +using ::testing::SizeIs; +using ::testing::UnorderedElementsAre; + +class MockFrameDataCallback { + public: + MOCK_METHOD(SkottieWrapper::FrameDataFetchResult, + OnAssetLoaded, + (SkottieResourceIdHash asset_id_hash, + float t, + sk_sp<SkImage>& image_out, + SkSamplingOptions& sampling_out)); + + SkottieWrapper::FrameDataCallback Get() { + return base::BindRepeating(&MockFrameDataCallback::OnAssetLoaded, + base::Unretained(this)); + } +}; + +TEST(SkottieWrapperTest, LoadsValidLottieFileNonSerializable) { + scoped_refptr<SkottieWrapper> skottie = + SkottieWrapper::CreateNonSerializable(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()), + kLottieDataWithoutAssets1.length())); + EXPECT_TRUE(skottie->is_valid()); +} + +TEST(SkottieWrapperTest, LoadsValidLottieFileSerializable) { + scoped_refptr<SkottieWrapper> skottie = + SkottieWrapper::CreateSerializable(std::vector<uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()), + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()) + + kLottieDataWithoutAssets1.length())); + EXPECT_TRUE(skottie->is_valid()); +} + +TEST(SkottieWrapperTest, DetectsInvalidLottieFile) { + static constexpr base::StringPiece kInvalidJson = "this is invalid json"; + scoped_refptr<SkottieWrapper> skottie = + SkottieWrapper::CreateNonSerializable(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(kInvalidJson.data()), + kInvalidJson.length())); + EXPECT_FALSE(skottie->is_valid()); +} + +TEST(SkottieWrapperTest, IdMatchesForSameLottieFile) { + scoped_refptr<SkottieWrapper> skottie_1 = + SkottieWrapper::CreateNonSerializable(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()), + kLottieDataWithoutAssets1.length())); + scoped_refptr<SkottieWrapper> skottie_2 = + SkottieWrapper::CreateSerializable(std::vector<uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()), + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()) + + kLottieDataWithoutAssets1.length())); + ASSERT_TRUE(skottie_1->is_valid()); + ASSERT_TRUE(skottie_2->is_valid()); + EXPECT_THAT(skottie_1->id(), Eq(skottie_2->id())); +} + +TEST(SkottieWrapperTest, IdDoesNotMatchForDifferentLottieFile) { + scoped_refptr<SkottieWrapper> skottie_1 = + SkottieWrapper::CreateNonSerializable(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets1.data()), + kLottieDataWithoutAssets1.length())); + scoped_refptr<SkottieWrapper> skottie_2 = + SkottieWrapper::CreateNonSerializable(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWithoutAssets2.data()), + kLottieDataWithoutAssets2.length())); + ASSERT_TRUE(skottie_1->is_valid()); + ASSERT_TRUE(skottie_2->is_valid()); + EXPECT_THAT(skottie_1->id(), Ne(skottie_2->id())); +} + +TEST(SkottieWrapperTest, LoadsImageAssetsMetadata) { + scoped_refptr<SkottieWrapper> skottie = + SkottieWrapper::CreateNonSerializable(base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(kLottieDataWith2Assets.data()), + kLottieDataWith2Assets.length())); + ASSERT_TRUE(skottie->is_valid()); + SkottieResourceMetadataMap metadata = skottie->GetImageAssetMetadata(); + EXPECT_THAT( + metadata.asset_storage(), + UnorderedElementsAre( + Pair("image_0", base::FilePath(FILE_PATH_LITERAL("images/img_0.jpg")) + .NormalizePathSeparators()), + Pair("image_1", base::FilePath(FILE_PATH_LITERAL("images/img_1.jpg")) + .NormalizePathSeparators()))); +} + +TEST(SkottieWrapperTest, LoadsCorrectAssetsForDraw) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + ASSERT_TRUE(skottie->is_valid()); + ::testing::NiceMock<MockCanvas> canvas; + MockFrameDataCallback mock_callback; + EXPECT_CALL(mock_callback, + OnAssetLoaded(HashSkottieResourceId("image_0"), _, _, _)); + skottie->Draw(&canvas, /*t=*/0.25, SkRect::MakeWH(500, 500), + mock_callback.Get()); + Mock::VerifyAndClearExpectations(&mock_callback); + + EXPECT_CALL(mock_callback, + OnAssetLoaded(HashSkottieResourceId("image_1"), _, _, _)); + skottie->Draw(&canvas, /*t=*/0.75, SkRect::MakeWH(500, 500), + mock_callback.Get()); + Mock::VerifyAndClearExpectations(&mock_callback); +} + +TEST(SkottieWrapperTest, AllowsNullFrameDataCallbackForDraw) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWithoutAssets1); + ASSERT_TRUE(skottie->is_valid()); + // Just verify that this call does not cause a CHECK failure. + ::testing::NiceMock<MockCanvas> canvas; + skottie->Draw(&canvas, /*t=*/0, SkRect::MakeWH(500, 500), + SkottieWrapper::FrameDataCallback()); +} + +TEST(SkottieWrapperTest, LoadsCorrectAssetsForSeek) { + scoped_refptr<SkottieWrapper> skottie = + CreateSkottieFromString(kLottieDataWith2Assets); + ASSERT_TRUE(skottie->is_valid()); + ::testing::NiceMock<MockCanvas> canvas; + MockFrameDataCallback mock_callback; + EXPECT_CALL(mock_callback, + OnAssetLoaded(HashSkottieResourceId("image_0"), _, _, _)); + skottie->Seek(/*t=*/0.25, mock_callback.Get()); + Mock::VerifyAndClearExpectations(&mock_callback); + + EXPECT_CALL(mock_callback, + OnAssetLoaded(HashSkottieResourceId("image_1"), _, _, _)); + skottie->Seek(/*t=*/0.75, mock_callback.Get()); + Mock::VerifyAndClearExpectations(&mock_callback); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/paint/transfer_cache_entry.cc b/chromium/cc/paint/transfer_cache_entry.cc index 5a6dda6942d..edd4e2b4597 100644 --- a/chromium/cc/paint/transfer_cache_entry.cc +++ b/chromium/cc/paint/transfer_cache_entry.cc @@ -7,14 +7,10 @@ #include <memory> #include "base/notreached.h" -#include "build/build_config.h" #include "cc/paint/image_transfer_cache_entry.h" #include "cc/paint/raw_memory_transfer_cache_entry.h" #include "cc/paint/shader_transfer_cache_entry.h" - -#if !defined(OS_ANDROID) #include "cc/paint/skottie_transfer_cache_entry.h" -#endif namespace cc { @@ -30,11 +26,7 @@ std::unique_ptr<ServiceTransferCacheEntry> ServiceTransferCacheEntry::Create( // CreateLocalEntry and is never serialized/deserialized. return nullptr; case TransferCacheEntryType::kSkottie: -#if !defined(OS_ANDROID) return std::make_unique<ServiceSkottieTransferCacheEntry>(); -#else - return nullptr; -#endif } return nullptr; diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.cc b/chromium/cc/raster/bitmap_raster_buffer_provider.cc index e49c0ca96fc..a404b098d21 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.cc +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.cc @@ -10,6 +10,7 @@ #include <algorithm> #include <utility> +#include "base/memory/raw_ptr.h" #include "base/memory/shared_memory_mapping.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" @@ -37,7 +38,7 @@ class BitmapSoftwareBacking : public ResourcePool::SoftwareBacking { importance); } - LayerTreeFrameSink* frame_sink; + raw_ptr<LayerTreeFrameSink> frame_sink; base::WritableSharedMemoryMapping mapping; }; @@ -85,6 +86,10 @@ class BitmapRasterBufferImpl : public RasterBuffer { private: const gfx::Size resource_size_; const gfx::ColorSpace color_space_; + + // `pixels_` is not a raw_ptr<...> for performance reasons: pointee is never + // protected by BackupRefPtr, because the pointer comes either from using + // `mmap`, MapViewOfFile or base::AllocPages directly. void* const pixels_; bool resource_has_previous_content_; }; diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.h b/chromium/cc/raster/bitmap_raster_buffer_provider.h index a2a14fc85f1..15e2fb04419 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.h +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.h @@ -10,6 +10,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/raster/raster_buffer_provider.h" namespace base { @@ -55,7 +56,7 @@ class CC_EXPORT BitmapRasterBufferProvider : public RasterBufferProvider { std::unique_ptr<base::trace_event::ConvertableToTraceFormat> StateAsValue() const; - LayerTreeFrameSink* const frame_sink_; + const raw_ptr<LayerTreeFrameSink> frame_sink_; }; } // namespace cc diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.cc b/chromium/cc/raster/gpu_raster_buffer_provider.cc index 5c0ad160c0e..d92fe141447 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.cc +++ b/chromium/cc/raster/gpu_raster_buffer_provider.cc @@ -12,6 +12,7 @@ #include <vector> #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/trace_event/process_memory_dump.h" @@ -34,11 +35,11 @@ #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/common/shared_image_trace_utils.h" #include "gpu/command_buffer/common/shared_image_usage.h" -#include "gpu/config/gpu_finch_features.h" #include "skia/ext/legacy_display_globals.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrDirectContext.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/axis_transform2d.h" #include "url/gurl.h" @@ -59,7 +60,8 @@ static void RasterizeSourceOOP( const gfx::Rect& playback_rect, const gfx::AxisTransform2d& transform, const RasterSource::PlaybackSettings& playback_settings, - viz::RasterContextProvider* context_provider) { + viz::RasterContextProvider* context_provider, + bool is_using_raw_draw) { gpu::raster::RasterInterface* ri = context_provider->RasterInterface(); bool mailbox_needs_clear = false; if (mailbox->IsZero()) { @@ -70,7 +72,7 @@ static void RasterizeSourceOOP( gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION; if (texture_is_overlay_candidate) { flags |= gpu::SHARED_IMAGE_USAGE_SCANOUT; - } else if (features::IsUsingRawDraw()) { + } else if (is_using_raw_draw) { flags |= gpu::SHARED_IMAGE_USAGE_RAW_DRAW; } *mailbox = sii->CreateSharedImage( @@ -87,10 +89,15 @@ static void RasterizeSourceOOP( ? gpu::raster::kMSAA : gpu::raster::kNoMSAA; - ri->BeginRasterCHROMIUM( - raster_source->background_color(), mailbox_needs_clear, - playback_settings.msaa_sample_count, msaa_mode, - playback_settings.use_lcd_text, color_space, mailbox->name); + // With Raw Draw, the framebuffer will be the rasterization target. It cannot + // support LCD text, so disable LCD text for Raw Draw backings. + // TODO(penghuang): remove it when GrSlug can be serialized. + bool is_raw_draw_backing = is_using_raw_draw && !texture_is_overlay_candidate; + bool use_lcd_text = playback_settings.use_lcd_text && !is_raw_draw_backing; + ri->BeginRasterCHROMIUM(raster_source->background_color(), + mailbox_needs_clear, + playback_settings.msaa_sample_count, msaa_mode, + use_lcd_text, color_space, mailbox->name); gfx::Vector2dF recording_to_raster_scale = transform.scale(); recording_to_raster_scale.Scale(1 / raster_source->recording_scale_factor()); gfx::Size content_size = raster_source->GetContentSize(transform.scale()); @@ -212,7 +219,7 @@ class GpuRasterBufferProvider::GpuRasterBacking } // The ContextProvider used to clean up the mailbox - viz::RasterContextProvider* worker_context_provider = nullptr; + raw_ptr<viz::RasterContextProvider> worker_context_provider = nullptr; }; GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl( @@ -309,7 +316,8 @@ GpuRasterBufferProvider::GpuRasterBufferProvider( enable_oop_rasterization_(enable_oop_rasterization), pending_raster_queries_(pending_raster_queries), random_generator_(static_cast<uint32_t>(base::RandUint64())), - bernoulli_distribution_(raster_metric_probability) { + bernoulli_distribution_(raster_metric_probability), + is_using_raw_draw_(features::IsUsingRawDraw()) { DCHECK(pending_raster_queries); DCHECK(compositor_context_provider); DCHECK(worker_context_provider); @@ -513,11 +521,12 @@ gpu::SyncToken GpuRasterBufferProvider::PlaybackOnWorkerThreadInternal( if (measure_raster_metric) timer.emplace(); if (enable_oop_rasterization_) { - RasterizeSourceOOP( - raster_source, resource_has_previous_content, mailbox, sync_token, - texture_target, texture_is_overlay_candidate, resource_size, - resource_format, color_space, raster_full_rect, playback_rect, - transform, playback_settings, worker_context_provider_); + RasterizeSourceOOP(raster_source, resource_has_previous_content, mailbox, + sync_token, texture_target, + texture_is_overlay_candidate, resource_size, + resource_format, color_space, raster_full_rect, + playback_rect, transform, playback_settings, + worker_context_provider_, is_using_raw_draw_); } else { RasterizeSource(raster_source, resource_has_previous_content, mailbox, sync_token, texture_target, texture_is_overlay_candidate, diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.h b/chromium/cc/raster/gpu_raster_buffer_provider.h index 2980c4c3b5c..a5e4459cfc6 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.h +++ b/chromium/cc/raster/gpu_raster_buffer_provider.h @@ -10,6 +10,7 @@ #include <random> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/raster_query_queue.h" @@ -116,8 +117,8 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { private: // These fields may only be used on the compositor thread. - GpuRasterBufferProvider* const client_; - GpuRasterBacking* backing_; + const raw_ptr<GpuRasterBufferProvider> client_; + raw_ptr<GpuRasterBacking> backing_; // These fields are for use on the worker thread. const gfx::Size resource_size_; @@ -159,18 +160,19 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { bool depends_on_at_raster_decodes, RasterQuery* query); - viz::ContextProvider* const compositor_context_provider_; - viz::RasterContextProvider* const worker_context_provider_; + const raw_ptr<viz::ContextProvider> compositor_context_provider_; + const raw_ptr<viz::RasterContextProvider> worker_context_provider_; const bool use_gpu_memory_buffer_resources_; const viz::ResourceFormat tile_format_; const gfx::Size max_tile_size_; const bool enable_oop_rasterization_; - RasterQueryQueue* const pending_raster_queries_; + const raw_ptr<RasterQueryQueue> pending_raster_queries_; // Accessed with the worker context lock acquired. std::mt19937 random_generator_; std::bernoulli_distribution bernoulli_distribution_; + const bool is_using_raw_draw_; }; } // namespace cc diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.cc b/chromium/cc/raster/one_copy_raster_buffer_provider.cc index 739ebd8d92d..dd23a107246 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.cc @@ -12,6 +12,7 @@ #include "base/debug/alias.h" #include "base/feature_list.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" @@ -80,7 +81,7 @@ class OneCopyRasterBufferProvider::OneCopyGpuBacking } // The ContextProvider used to clean up the mailbox - viz::RasterContextProvider* worker_context_provider = nullptr; + raw_ptr<viz::RasterContextProvider> worker_context_provider = nullptr; }; OneCopyRasterBufferProvider::RasterBufferImpl::RasterBufferImpl( diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.h b/chromium/cc/raster/one_copy_raster_buffer_provider.h index 9c38d691cfe..d4e3817a30d 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.h @@ -10,7 +10,8 @@ #include <memory> #include <vector> -#include "base/sequenced_task_runner.h" +#include "base/memory/raw_ptr.h" +#include "base/task/sequenced_task_runner.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/staging_buffer_pool.h" #include "components/viz/client/client_resource_provider.h" @@ -116,8 +117,8 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { private: // These fields may only be used on the compositor thread. - OneCopyRasterBufferProvider* const client_; - OneCopyGpuBacking* backing_; + const raw_ptr<OneCopyRasterBufferProvider> client_; + raw_ptr<OneCopyGpuBacking> backing_; // These fields are for use on the worker thread. const gfx::Size resource_size_; @@ -155,10 +156,10 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const gpu::SyncToken& sync_token, const gfx::ColorSpace& color_space); - viz::ContextProvider* const compositor_context_provider_; - viz::RasterContextProvider* const worker_context_provider_; - gpu::GpuMemoryBufferManager* const gpu_memory_buffer_manager_; - base::WaitableEvent* shutdown_event_ = nullptr; + const raw_ptr<viz::ContextProvider> compositor_context_provider_; + const raw_ptr<viz::RasterContextProvider> worker_context_provider_; + const raw_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_; + raw_ptr<base::WaitableEvent> shutdown_event_ = nullptr; const int max_bytes_per_copy_operation_; const bool use_partial_raster_; const bool use_gpu_memory_buffer_resources_; diff --git a/chromium/cc/raster/raster_buffer_provider_perftest.cc b/chromium/cc/raster/raster_buffer_provider_perftest.cc index 2db759a9334..e168d9adc07 100644 --- a/chromium/cc/raster/raster_buffer_provider_perftest.cc +++ b/chromium/cc/raster/raster_buffer_provider_perftest.cc @@ -5,6 +5,7 @@ #include <stddef.h> #include <stdint.h> +#include "base/memory/raw_ptr.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" #include "base/timer/lap_timer.h" @@ -239,7 +240,7 @@ class PerfRasterTaskImpl : public PerfTileTask { ~PerfRasterTaskImpl() override = default; private: - ResourcePool* const pool_; + const raw_ptr<ResourcePool> pool_; ResourcePool::InUsePoolResource resource_; std::unique_ptr<RasterBuffer> raster_buffer_; }; diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc index fcdf00e15a1..c8c922e32dc 100644 --- a/chromium/cc/raster/raster_buffer_provider_unittest.cc +++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc @@ -20,11 +20,12 @@ #include "base/cancelable_callback.h" #include "base/check.h" #include "base/location.h" +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_base.h" #include "base/notreached.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/test/metrics/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -113,7 +114,7 @@ class TestRasterTaskImpl : public TileTask { ~TestRasterTaskImpl() override = default; private: - TestRasterTaskCompletionHandler* completion_handler_; + raw_ptr<TestRasterTaskCompletionHandler> completion_handler_; unsigned id_; std::unique_ptr<RasterBuffer> raster_buffer_; scoped_refptr<RasterSource> raster_source_; @@ -147,7 +148,7 @@ class BlockingTestRasterTaskImpl : public TestRasterTaskImpl { ~BlockingTestRasterTaskImpl() override = default; private: - base::Lock* lock_; + raw_ptr<base::Lock> lock_; }; class RasterImplementationForOOPR diff --git a/chromium/cc/raster/raster_query_queue.h b/chromium/cc/raster/raster_query_queue.h index e81400a30e1..573d509e6c6 100644 --- a/chromium/cc/raster/raster_query_queue.h +++ b/chromium/cc/raster/raster_query_queue.h @@ -6,6 +6,7 @@ #define CC_RASTER_RASTER_QUERY_QUEUE_H_ #include "base/containers/circular_deque.h" +#include "base/memory/raw_ptr.h" #include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "base/time/time.h" @@ -54,7 +55,7 @@ class CC_EXPORT RasterQueryQueue { virtual bool CheckRasterFinishedQueries(); private: - viz::RasterContextProvider* const worker_context_provider_; + const raw_ptr<viz::RasterContextProvider> worker_context_provider_; const bool oop_rasterization_enabled_; // Note that this lock should never be acquired while holding the raster diff --git a/chromium/cc/raster/raster_source.h b/chromium/cc/raster/raster_source.h index ca2aa3c9294..f3411fe87d4 100644 --- a/chromium/cc/raster/raster_source.h +++ b/chromium/cc/raster/raster_source.h @@ -12,6 +12,7 @@ #include <vector> #include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/cc_export.h" #include "cc/debug/rendering_stats_instrumentation.h" @@ -51,7 +52,7 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // Specifies the sample count if MSAA is enabled for this tile. int msaa_sample_count = 0; - ImageProvider* image_provider = nullptr; + raw_ptr<ImageProvider> image_provider = nullptr; }; RasterSource(const RasterSource&) = delete; diff --git a/chromium/cc/raster/scoped_gpu_raster.h b/chromium/cc/raster/scoped_gpu_raster.h index e238605b1dc..8c8b93315d6 100644 --- a/chromium/cc/raster/scoped_gpu_raster.h +++ b/chromium/cc/raster/scoped_gpu_raster.h @@ -5,6 +5,7 @@ #ifndef CC_RASTER_SCOPED_GPU_RASTER_H_ #define CC_RASTER_SCOPED_GPU_RASTER_H_ +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" namespace viz { @@ -28,7 +29,7 @@ class CC_EXPORT ScopedGpuRaster { void BeginGpuRaster(); void EndGpuRaster(); - viz::ContextProvider* context_provider_; + raw_ptr<viz::ContextProvider> context_provider_; }; } // namespace cc diff --git a/chromium/cc/raster/single_thread_task_graph_runner.cc b/chromium/cc/raster/single_thread_task_graph_runner.cc index 0dab12cd4f2..f886c829fd7 100644 --- a/chromium/cc/raster/single_thread_task_graph_runner.cc +++ b/chromium/cc/raster/single_thread_task_graph_runner.cc @@ -158,7 +158,7 @@ bool SingleThreadTaskGraphRunner::RunTaskWithLockAcquired() { prioritized_task.task->RunOnWorkerThread(); } - auto* task_namespace = prioritized_task.task_namespace; + auto* task_namespace = prioritized_task.task_namespace.get(); work_queue_.CompleteTask(std::move(prioritized_task)); // If namespace has finished running all tasks, wake up origin thread. diff --git a/chromium/cc/raster/staging_buffer_pool.h b/chromium/cc/raster/staging_buffer_pool.h index 0dd19250349..a0785c40f33 100644 --- a/chromium/cc/raster/staging_buffer_pool.h +++ b/chromium/cc/raster/staging_buffer_pool.h @@ -12,9 +12,10 @@ #include "base/containers/circular_deque.h" #include "base/memory/memory_pressure_listener.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" #include "base/synchronization/lock.h" +#include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/trace_event.h" @@ -127,7 +128,7 @@ class CC_EXPORT StagingBufferPool final base::MemoryPressureListener::MemoryPressureLevel level); scoped_refptr<base::SequencedTaskRunner> task_runner_; - viz::RasterContextProvider* const worker_context_provider_; + const raw_ptr<viz::RasterContextProvider> worker_context_provider_; const bool use_partial_raster_; mutable base::Lock lock_; diff --git a/chromium/cc/raster/task_graph_work_queue.cc b/chromium/cc/raster/task_graph_work_queue.cc index 48575f7cdbe..1ca3c67c2a9 100644 --- a/chromium/cc/raster/task_graph_work_queue.cc +++ b/chromium/cc/raster/task_graph_work_queue.cc @@ -94,9 +94,15 @@ class DependentIterator { operator bool() const { return current_index_ < graph_->edges.size(); } private: + // `graph_` and `task_` are not a raw_ptr<...> for performance reasons (based + // on analysis of sampling profiler data and tab_search:top100:2020). TaskGraph* graph_; const Task* task_; + size_t current_index_; + + // `current_node_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). TaskGraph::Node* current_node_; }; diff --git a/chromium/cc/raster/task_graph_work_queue.h b/chromium/cc/raster/task_graph_work_queue.h index 3b739f7214d..5ad11b4fc45 100644 --- a/chromium/cc/raster/task_graph_work_queue.h +++ b/chromium/cc/raster/task_graph_work_queue.h @@ -11,6 +11,7 @@ #include <map> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/raster/task_graph_runner.h" @@ -43,7 +44,7 @@ class CC_EXPORT TaskGraphWorkQueue { PrioritizedTask& operator=(PrioritizedTask&& other) = default; scoped_refptr<Task> task; - TaskNamespace* task_namespace; + raw_ptr<TaskNamespace> task_namespace; uint16_t category; uint16_t priority; }; diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc index 2184021a872..112b23950fd 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc @@ -9,6 +9,7 @@ #include <algorithm> #include <utility> +#include "base/memory/raw_ptr.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" @@ -55,7 +56,7 @@ class ZeroCopyGpuBacking : public ResourcePool::GpuBacking { } // The SharedImageInterface used to clean up the shared image. - gpu::SharedImageInterface* shared_image_interface = nullptr; + raw_ptr<gpu::SharedImageInterface> shared_image_interface = nullptr; // The backing for zero-copy gpu resources. The |texture_id| is bound to // this. std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; @@ -154,11 +155,11 @@ class ZeroCopyRasterBufferImpl : public RasterBuffer { private: // This field may only be used on the compositor thread. - ZeroCopyGpuBacking* backing_; + raw_ptr<ZeroCopyGpuBacking> backing_; // These fields are for use on the worker thread. - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; - base::WaitableEvent* shutdown_event_; + raw_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_; + raw_ptr<base::WaitableEvent> shutdown_event_; gfx::Size resource_size_; viz::ResourceFormat resource_format_; gfx::ColorSpace resource_color_space_; diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.h b/chromium/cc/raster/zero_copy_raster_buffer_provider.h index 78d680f8fb5..ed26b34d6f4 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.h @@ -10,6 +10,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "cc/raster/raster_buffer_provider.h" @@ -63,9 +64,9 @@ class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { std::unique_ptr<base::trace_event::ConvertableToTraceFormat> StateAsValue() const; - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; - base::WaitableEvent* shutdown_event_ = nullptr; - viz::ContextProvider* compositor_context_provider_; + raw_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_; + raw_ptr<base::WaitableEvent> shutdown_event_ = nullptr; + raw_ptr<viz::ContextProvider> compositor_context_provider_; viz::ResourceFormat tile_format_; }; diff --git a/chromium/cc/resources/resource_pool.cc b/chromium/cc/resources/resource_pool.cc index 805bf859f23..7c02c09de8c 100644 --- a/chromium/cc/resources/resource_pool.cc +++ b/chromium/cc/resources/resource_pool.cc @@ -16,8 +16,8 @@ #include "base/atomic_sequence_num.h" #include "base/bind.h" #include "base/format_macros.h" -#include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_tick_clock.h" #include "base/trace_event/memory_dump_manager.h" diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h index 33246505665..88ffc7aee8e 100644 --- a/chromium/cc/resources/resource_pool.h +++ b/chromium/cc/resources/resource_pool.h @@ -16,6 +16,7 @@ #include "base/containers/circular_deque.h" #include "base/gtest_prod_util.h" #include "base/memory/memory_pressure_listener.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/tick_clock.h" #include "base/trace_event/memory_allocator_dump_guid.h" @@ -186,6 +187,9 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { void SetWasFreedByResourcePool() { resource_ = nullptr; } bool is_gpu_ = false; + + // `resource_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). PoolResource* resource_ = nullptr; }; @@ -389,8 +393,8 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { base::TimeTicks GetUsageTimeForLRUResource() const; void FlushEvictedResources(); - viz::ClientResourceProvider* const resource_provider_; - viz::ContextProvider* const context_provider_; + const raw_ptr<viz::ClientResourceProvider> resource_provider_; + const raw_ptr<viz::ContextProvider> context_provider_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const base::TimeDelta resource_expiration_delay_; const bool disallow_non_exact_reuse_ = false; @@ -416,7 +420,7 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { base::TimeTicks flush_evicted_resources_deadline_; - const base::TickClock* clock_; + raw_ptr<const base::TickClock> clock_; base::WeakPtrFactory<ResourcePool> weak_ptr_factory_{this}; }; diff --git a/chromium/cc/resources/resource_pool_unittest.cc b/chromium/cc/resources/resource_pool_unittest.cc index acbb20db33f..d4985b0d6a3 100644 --- a/chromium/cc/resources/resource_pool_unittest.cc +++ b/chromium/cc/resources/resource_pool_unittest.cc @@ -6,7 +6,8 @@ #include <stddef.h> -#include "base/single_thread_task_runner.h" +#include "base/memory/raw_ptr.h" +#include "base/task/single_thread_task_runner.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/viz/client/client_resource_provider.h" @@ -70,7 +71,7 @@ class ResourcePoolTest : public testing::Test { } viz::TestSharedBitmapManager shared_bitmap_manager_; - MockContextSupport* context_support_; + raw_ptr<MockContextSupport> context_support_; scoped_refptr<viz::TestContextProvider> context_provider_; std::unique_ptr<viz::ClientResourceProvider> resource_provider_; scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; diff --git a/chromium/cc/resources/scoped_ui_resource.h b/chromium/cc/resources/scoped_ui_resource.h index 3e6f4d3928a..9452291656a 100644 --- a/chromium/cc/resources/scoped_ui_resource.h +++ b/chromium/cc/resources/scoped_ui_resource.h @@ -5,6 +5,7 @@ #ifndef CC_RESOURCES_SCOPED_UI_RESOURCE_H_ #define CC_RESOURCES_SCOPED_UI_RESOURCE_H_ +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/cc_export.h" #include "cc/resources/ui_resource_bitmap.h" @@ -42,7 +43,7 @@ class CC_EXPORT ScopedUIResource : public UIResourceClient { const UIResourceBitmap& bitmap); UIResourceBitmap bitmap_; - UIResourceManager* ui_resource_manager_; + raw_ptr<UIResourceManager> ui_resource_manager_; UIResourceId id_; }; diff --git a/chromium/cc/resources/ui_resource_manager.cc b/chromium/cc/resources/ui_resource_manager.cc index aadb255862d..83cfdccbade 100644 --- a/chromium/cc/resources/ui_resource_manager.cc +++ b/chromium/cc/resources/ui_resource_manager.cc @@ -5,6 +5,7 @@ #include "cc/resources/ui_resource_manager.h" #include <algorithm> +#include <utility> #include "cc/resources/scoped_ui_resource.h" @@ -62,13 +63,12 @@ void UIResourceManager::RecreateUIResources() { } } -gfx::Size UIResourceManager::GetUIResourceSize(UIResourceId uid) const { - const auto iter = ui_resource_client_map_.find(uid); - if (iter == ui_resource_client_map_.end()) - return gfx::Size(); - - const UIResourceClientData& data = iter->second; - return data.size; +base::flat_map<UIResourceId, gfx::Size> UIResourceManager::GetUIResourceSizes() + const { + base::flat_map<UIResourceId, gfx::Size> result; + for (const auto pair : ui_resource_client_map_) + result.emplace(pair.first, pair.second.size); + return result; } std::vector<UIResourceRequest> UIResourceManager::TakeUIResourcesRequests() { diff --git a/chromium/cc/resources/ui_resource_manager.h b/chromium/cc/resources/ui_resource_manager.h index e3e51204656..cf18142a115 100644 --- a/chromium/cc/resources/ui_resource_manager.h +++ b/chromium/cc/resources/ui_resource_manager.h @@ -5,9 +5,11 @@ #ifndef CC_RESOURCES_UI_RESOURCE_MANAGER_H_ #define CC_RESOURCES_UI_RESOURCE_MANAGER_H_ +#include <memory> #include <unordered_map> #include <vector> +#include "base/containers/flat_map.h" #include "cc/cc_export.h" #include "cc/resources/ui_resource_request.h" @@ -33,7 +35,7 @@ class CC_EXPORT UIResourceManager { // Deletes a UI resource. May safely be called more than once. virtual void DeleteUIResource(UIResourceId id); - virtual gfx::Size GetUIResourceSize(UIResourceId id) const; + base::flat_map<UIResourceId, gfx::Size> GetUIResourceSizes() const; // Methods meant to be used only internally in cc ------------ diff --git a/chromium/cc/scheduler/begin_frame_tracker.cc b/chromium/cc/scheduler/begin_frame_tracker.cc index ccc5b97be75..747ca29d98a 100644 --- a/chromium/cc/scheduler/begin_frame_tracker.cc +++ b/chromium/cc/scheduler/begin_frame_tracker.cc @@ -20,8 +20,8 @@ void BeginFrameTracker::Start(const viz::BeginFrameArgs& new_args) { // Trace the frame time being passed between BeginFrameTrackers. TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", - TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, new_args.frame_time.since_origin().InMicroseconds(), + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "location", location_string_); // Trace this specific begin frame tracker Start/Finish times. diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc index 594c7ea2b8a..09f27ac9a81 100644 --- a/chromium/cc/scheduler/scheduler.cc +++ b/chromium/cc/scheduler/scheduler.cc @@ -13,7 +13,7 @@ #include "base/check_op.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "cc/base/devtools_instrumentation.h" @@ -39,8 +39,6 @@ Scheduler::Scheduler( int layer_tree_host_id, base::SingleThreadTaskRunner* task_runner, std::unique_ptr<CompositorTimingHistory> compositor_timing_history, - gfx::RenderingPipeline* main_thread_pipeline, - gfx::RenderingPipeline* compositor_thread_pipeline, CompositorFrameReportingController* compositor_frame_reporting_controller, power_scheduler::PowerModeArbiter* power_mode_arbiter) : settings_(settings), @@ -52,8 +50,6 @@ Scheduler::Scheduler( compositor_frame_reporting_controller), begin_impl_frame_tracker_(FROM_HERE), state_machine_(settings), - main_thread_pipeline_(main_thread_pipeline), - compositor_thread_pipeline_(compositor_thread_pipeline), power_mode_voter_( power_mode_arbiter->NewVoter("PowerModeVoter.MainThreadAnimation")) { TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue()); @@ -215,8 +211,6 @@ void Scheduler::NotifyReadyToCommit( } void Scheduler::DidCommit() { - if (main_thread_pipeline_) - main_thread_pipeline_->NotifyFrameFinished(); compositor_timing_history_->DidCommit(); compositor_frame_reporting_controller_->DidCommit(); } @@ -230,8 +224,6 @@ void Scheduler::BeginMainFrameAborted(CommitEarlyOutReason reason) { reason); state_machine_.BeginMainFrameAborted(reason); - if (main_thread_pipeline_) - main_thread_pipeline_->NotifyFrameFinished(); ProcessScheduledActions(); } @@ -325,8 +317,6 @@ void Scheduler::StartOrStopBeginFrames() { devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, false); client_->WillNotReceiveBeginFrame(); - main_thread_pipeline_active_.reset(); - compositor_thread_pipeline_active_.reset(); } } @@ -380,8 +370,7 @@ bool Scheduler::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) { // zero then let |client_| know about the new interval for animations. In // theory the interval should always be bigger than zero but the value is // provided by APIs outside our control. - if (args.interval != last_frame_interval_ && - args.interval > base::TimeDelta()) { + if (args.interval != last_frame_interval_ && args.interval.is_positive()) { last_frame_interval_ = args.interval; client_->FrameIntervalUpdated(last_frame_interval_); } @@ -399,8 +388,9 @@ bool Scheduler::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) { // Trace this begin frame time through the Chrome stack TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), - "viz::BeginFrameArgs", TRACE_EVENT_FLAG_FLOW_OUT, - args.frame_time.since_origin().InMicroseconds()); + "viz::BeginFrameArgs", + args.frame_time.since_origin().InMicroseconds(), + TRACE_EVENT_FLAG_FLOW_OUT); if (settings_.using_synchronous_renderer_compositor) { BeginImplFrameSynchronous(args); @@ -568,29 +558,6 @@ void Scheduler::BeginImplFrameWithDeadline(const viz::BeginFrameArgs& args) { state_machine_.set_should_defer_invalidation_for_fast_main_frame( main_thread_response_expected_before_deadline); - // A pipeline is activated if it's subscribed to BeginFrame callbacks. For the - // compositor this implies BeginImplFrames while for the main thread it would - // be BeginMainFrames. - // TODO(crbug.com/1157620) : For now this also includes cases where the - // rendering loop doesn't lead to any visual updates, for example a rAF - // callback updating content offscreen. These can be treated differently from - // a scheduling perspective (Idle vs Animating). - if (compositor_thread_pipeline_) { - if (!compositor_thread_pipeline_active_) - compositor_thread_pipeline_active_.emplace(compositor_thread_pipeline_); - compositor_thread_pipeline_->SetTargetDuration(adjusted_args.interval); - } - - if (main_thread_pipeline_) { - // TODO(crbug.com/1157620) : We need a heuristic to mark the main pipeline - // inactive if it stops subscribing to main frames. For instance after a - // composited animation is committed. - if (state_machine_.did_commit_during_frame() && - !main_thread_pipeline_active_) - main_thread_pipeline_active_.emplace(main_thread_pipeline_); - main_thread_pipeline_->SetTargetDuration(adjusted_args.interval); - } - BeginImplFrame(adjusted_args, now); } @@ -670,9 +637,6 @@ void Scheduler::FinishImplFrame() { if (begin_frame_source_) begin_frame_source_->DidFinishFrame(this); - - if (compositor_thread_pipeline_) - compositor_thread_pipeline_->NotifyFrameFinished(); } void Scheduler::SendDidNotProduceFrame(const viz::BeginFrameArgs& args, @@ -839,7 +803,7 @@ void Scheduler::DrawIfPossible() { DrawResult result = client_->ScheduledActionDrawIfPossible(); state_machine_.DidDraw(result); compositor_timing_history_->DidDraw(drawing_with_new_active_tree, - client_->HasCustomPropertyAnimations()); + client_->HasInvalidationAnimation()); } void Scheduler::DrawForced() { @@ -853,7 +817,7 @@ void Scheduler::DrawForced() { DrawResult result = client_->ScheduledActionDrawForced(); state_machine_.DidDraw(result); compositor_timing_history_->DidDraw(drawing_with_new_active_tree, - client_->HasCustomPropertyAnimations()); + client_->HasInvalidationAnimation()); } void Scheduler::SetDeferBeginMainFrame(bool defer_begin_main_frame) { @@ -1023,6 +987,11 @@ bool Scheduler::IsBeginMainFrameSent() const { SchedulerStateMachine::BeginMainFrameState::SENT; } +size_t Scheduler::CommitDurationSampleCountForTesting() const { + return compositor_timing_history_ + ->CommitDurationSampleCountForTesting(); // IN-TEST +} + viz::BeginFrameAck Scheduler::CurrentBeginFrameAckForActiveTree() const { return viz::BeginFrameAck(begin_main_frame_args_, true); } diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h index 2b46df206e5..7e2b30fae25 100644 --- a/chromium/cc/scheduler/scheduler.h +++ b/chromium/cc/scheduler/scheduler.h @@ -10,6 +10,7 @@ #include <vector> #include "base/cancelable_callback.h" +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/metrics/event_metrics.h" @@ -22,7 +23,6 @@ #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" -#include "ui/gfx/rendering_pipeline.h" namespace perfetto { namespace protos { @@ -88,7 +88,7 @@ class SchedulerClient { virtual void FrameIntervalUpdated(base::TimeDelta interval) = 0; // Functions used for reporting animation targeting UMA, crbug.com/758439. - virtual bool HasCustomPropertyAnimations() const = 0; + virtual bool HasInvalidationAnimation() const = 0; protected: virtual ~SchedulerClient() {} @@ -102,8 +102,6 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase { int layer_tree_host_id, base::SingleThreadTaskRunner* task_runner, std::unique_ptr<CompositorTimingHistory> compositor_timing_history, - gfx::RenderingPipeline* main_thread_pipeline, - gfx::RenderingPipeline* compositor_thread_pipeline, CompositorFrameReportingController* compositor_frame_reporting_controller, power_scheduler::PowerModeArbiter* power_mode_arbiter); Scheduler(const Scheduler&) = delete; @@ -273,16 +271,18 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase { bool IsBeginMainFrameSent() const; + size_t CommitDurationSampleCountForTesting() const; + protected: // Virtual for testing. virtual base::TimeTicks Now() const; const SchedulerSettings settings_; - SchedulerClient* const client_; + const raw_ptr<SchedulerClient> client_; const int layer_tree_host_id_; - base::SingleThreadTaskRunner* task_runner_; + raw_ptr<base::SingleThreadTaskRunner> task_runner_; - viz::BeginFrameSource* begin_frame_source_ = nullptr; + raw_ptr<viz::BeginFrameSource> begin_frame_source_ = nullptr; bool observing_begin_frame_source_ = false; bool skipped_last_frame_missed_exceeded_deadline_ = false; @@ -291,7 +291,8 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase { // Owned by LayerTreeHostImpl and is destroyed when LayerTreeHostImpl is // destroyed. - CompositorFrameReportingController* compositor_frame_reporting_controller_; + raw_ptr<CompositorFrameReportingController> + compositor_frame_reporting_controller_; // What the latest deadline was, and when it was scheduled. base::TimeTicks deadline_; @@ -342,14 +343,6 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase { // arrive so that |client_| can be informed about changes. base::TimeDelta last_frame_interval_; - gfx::RenderingPipeline* const main_thread_pipeline_; - absl::optional<gfx::RenderingPipeline::ScopedPipelineActive> - main_thread_pipeline_active_; - - gfx::RenderingPipeline* const compositor_thread_pipeline_; - absl::optional<gfx::RenderingPipeline::ScopedPipelineActive> - compositor_thread_pipeline_active_; - std::unique_ptr<power_scheduler::PowerModeVoter> power_mode_voter_; power_scheduler::PowerMode last_power_mode_vote_ = power_scheduler::PowerMode::kIdle; diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h index 70f8b8b2f1d..929d58550de 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.h +++ b/chromium/cc/scheduler/scheduler_state_machine.h @@ -349,7 +349,6 @@ class CC_EXPORT SchedulerStateMachine { bool should_defer_invalidation_for_fast_main_frame() const { return should_defer_invalidation_for_fast_main_frame_; } - bool did_commit_during_frame() const { return did_commit_during_frame_; } int aborted_begin_main_frame_count() const { return aborted_begin_main_frame_count_; diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc index 0ba69163277..a8f74d96bf8 100644 --- a/chromium/cc/scheduler/scheduler_unittest.cc +++ b/chromium/cc/scheduler/scheduler_unittest.cc @@ -15,6 +15,7 @@ #include "base/bind.h" #include "base/check_op.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/run_loop.h" @@ -273,7 +274,7 @@ class FakeSchedulerClient : public SchedulerClient, PushAction("RemoveObserver(this)"); } - bool HasCustomPropertyAnimations() const override { return false; } + bool HasInvalidationAnimation() const override { return false; } protected: bool InsideBeginImplFrameCallback(bool state) { @@ -294,7 +295,7 @@ class FakeSchedulerClient : public SchedulerClient, viz::BeginFrameAck last_begin_frame_ack_; base::TimeTicks posted_begin_impl_frame_deadline_; std::vector<const char*> actions_; - TestScheduler* scheduler_ = nullptr; + raw_ptr<TestScheduler> scheduler_ = nullptr; base::TimeDelta frame_interval_; absl::optional<FrameSkippedReason> last_frame_skipped_reason_; }; @@ -594,7 +595,7 @@ class SchedulerTest : public testing::Test { std::unique_ptr<FakeSchedulerClient> client_; PowerModeArbiter power_mode_arbiter_; std::unique_ptr<TestScheduler> scheduler_; - FakeCompositorTimingHistory* fake_compositor_timing_history_; + raw_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history_; DroppedFrameCounter dropped_counter; std::unique_ptr<CompositorFrameReportingController> reporting_controller; }; diff --git a/chromium/cc/tiles/checker_image_tracker.h b/chromium/cc/tiles/checker_image_tracker.h index 76cdea7cac6..5612e452413 100644 --- a/chromium/cc/tiles/checker_image_tracker.h +++ b/chromium/cc/tiles/checker_image_tracker.h @@ -8,6 +8,7 @@ #include <unordered_map> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/paint/image_id.h" #include "cc/tiles/image_controller.h" @@ -157,7 +158,7 @@ class CC_EXPORT CheckerImageTracker { ScopedDecodeHolder& operator=(const ScopedDecodeHolder&) = delete; private: - ImageController* controller_; + raw_ptr<ImageController> controller_; ImageController::ImageDecodeRequestId request_id_; }; @@ -172,8 +173,8 @@ class CC_EXPORT CheckerImageTracker { PaintImage::Id paint_image_id, DecodeState* decode_state); - ImageController* image_controller_; - CheckerImageTrackerClient* client_; + raw_ptr<ImageController> image_controller_; + raw_ptr<CheckerImageTrackerClient> client_; const bool enable_checker_imaging_; const size_t min_image_bytes_to_checker_; diff --git a/chromium/cc/tiles/decoded_image_tracker.h b/chromium/cc/tiles/decoded_image_tracker.h index c3bf49793bc..6a5a61efb02 100644 --- a/chromium/cc/tiles/decoded_image_tracker.h +++ b/chromium/cc/tiles/decoded_image_tracker.h @@ -9,6 +9,7 @@ #include <vector> #include "base/bind.h" +#include "base/memory/raw_ptr.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -66,7 +67,7 @@ class CC_EXPORT DecodedImageTracker { void OnTimeoutImages(); void EnqueueTimeout(); - ImageController* image_controller_; + raw_ptr<ImageController> image_controller_; // Helper class tracking a locked image decode. Automatically releases the // lock using the provided DecodedImageTracker* on destruction. @@ -82,7 +83,7 @@ class CC_EXPORT DecodedImageTracker { base::TimeTicks lock_time() const { return lock_time_; } private: - DecodedImageTracker* tracker_; + raw_ptr<DecodedImageTracker> tracker_; ImageController::ImageDecodeRequestId request_id_; base::TimeTicks lock_time_; }; @@ -91,7 +92,7 @@ class CC_EXPORT DecodedImageTracker { scoped_refptr<base::SequencedTaskRunner> task_runner_; // Defaults to base::TimeTicks::Now(), but overrideable for testing. - const base::TickClock* tick_clock_; + raw_ptr<const base::TickClock> tick_clock_; base::WeakPtrFactory<DecodedImageTracker> weak_ptr_factory_{this}; }; diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc index 412ae9fac50..ea39d8f9b02 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache.cc @@ -19,6 +19,7 @@ #include "base/hash/hash.h" #include "base/logging.h" #include "base/memory/discardable_memory_allocator.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_math.h" #include "base/strings/stringprintf.h" @@ -540,7 +541,7 @@ class GpuImageDecodeTaskImpl : public TileTask { ~GpuImageDecodeTaskImpl() override = default; private: - GpuImageDecodeCache* cache_; + raw_ptr<GpuImageDecodeCache> cache_; DrawImage image_; const ImageDecodeCache::TracingInfo tracing_info_; const GpuImageDecodeCache::DecodeTaskType task_type_; @@ -591,7 +592,7 @@ class ImageUploadTaskImpl : public TileTask { ~ImageUploadTaskImpl() override = default; private: - GpuImageDecodeCache* cache_; + raw_ptr<GpuImageDecodeCache> cache_; DrawImage image_; const ImageDecodeCache::TracingInfo tracing_info_; }; @@ -2934,14 +2935,28 @@ sk_sp<SkColorSpace> GpuImageDecodeCache::ColorSpaceForImageDecode( bool GpuImageDecodeCache::NeedsColorSpaceAdjustedForUpload( const DrawImage& image) const { - return image.sdr_white_level() != gfx::ColorSpace::kDefaultSDRWhiteLevel && - image.paint_image().GetContentColorUsage() == - gfx::ContentColorUsage::kHDR; + bool is_hlg = false; + if (image.paint_image().GetContentColorUsage(&is_hlg) != + gfx::ContentColorUsage::kHDR) { + return false; + } + + // Attempt basic "tonemapping" of HLG content when rendering to SDR. + if (is_hlg && !image.target_color_space().IsHDR()) + return true; + + return image.sdr_white_level() != gfx::ColorSpace::kDefaultSDRWhiteLevel; } sk_sp<SkColorSpace> GpuImageDecodeCache::ColorSpaceForImageUpload( const DrawImage& image) const { DCHECK(NeedsColorSpaceAdjustedForUpload(image)); + if (!image.target_color_space().IsHDR()) { + // HLG is designed such that treating it as 2.2 gamma content works well. + constexpr skcms_TransferFunction kGamma22 = {2.2, 1, 0, 0, 0, 0, 0}; + return SkColorSpace::MakeRGB(kGamma22, SkNamedGamut::kRec2020); + } + return gfx::ColorSpace(*image.paint_image().color_space()) .GetWithSDRWhiteLevel(image.sdr_white_level()) .ToSkColorSpace(); diff --git a/chromium/cc/tiles/gpu_image_decode_cache.h b/chromium/cc/tiles/gpu_image_decode_cache.h index edea739d938..e230c246b68 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.h +++ b/chromium/cc/tiles/gpu_image_decode_cache.h @@ -11,10 +11,11 @@ #include <utility> #include <vector> -#include "base/containers/mru_cache.h" +#include "base/containers/lru_cache.h" #include "base/logging.h" #include "base/memory/discardable_memory.h" #include "base/memory/memory_pressure_listener.h" +#include "base/memory/raw_ptr.h" #include "base/synchronization/lock.h" #include "base/trace_event/memory_dump_provider.h" #include "cc/cc_export.h" @@ -728,7 +729,7 @@ class CC_EXPORT GpuImageDecodeCache // |persistent_cache_| represents the long-lived cache, keeping a certain // budget of ImageDatas alive even when their ref count reaches zero. - using PersistentCache = base::HashingMRUCache<PaintImage::FrameKey, + using PersistentCache = base::HashingLRUCache<PaintImage::FrameKey, scoped_refptr<ImageData>, PaintImage::FrameKeyHash>; void AddToPersistentCache(const DrawImage& draw_image, @@ -741,7 +742,7 @@ class CC_EXPORT GpuImageDecodeCache const SkColorType color_type_; const bool use_transfer_cache_ = false; - viz::RasterContextProvider* context_; + raw_ptr<viz::RasterContextProvider> context_; int max_texture_size_ = 0; const PaintImage::GeneratorClientId generator_client_id_; bool allow_accelerated_jpeg_decodes_ = false; diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc index 80ed2b1fcdc..5f11e495501 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc @@ -13,6 +13,7 @@ #include <vector> #include "base/feature_list.h" +#include "base/memory/raw_ptr.h" #include "base/test/scoped_feature_list.h" #include "cc/base/switches.h" #include "cc/paint/draw_image.h" @@ -112,7 +113,7 @@ class FakeDiscardableManager { std::map<GLuint, int32_t> textures_; size_t live_textures_count_ = 0; size_t cached_textures_limit_ = std::numeric_limits<size_t>::max(); - viz::TestGLES2Interface* gl_ = nullptr; + raw_ptr<viz::TestGLES2Interface> gl_ = nullptr; }; class FakeGPUImageDecodeTestGLES2Interface : public viz::TestGLES2Interface, @@ -252,8 +253,8 @@ class FakeGPUImageDecodeTestGLES2Interface : public viz::TestGLES2Interface, private: const std::string extension_string_; - FakeDiscardableManager* discardable_manager_; - TransferCacheTestHelper* transfer_cache_helper_; + raw_ptr<FakeDiscardableManager> discardable_manager_; + raw_ptr<TransferCacheTestHelper> transfer_cache_helper_; bool advertise_accelerated_decoding_ = false; size_t mapped_entry_size_ = 0; std::unique_ptr<uint8_t[]> mapped_entry_; diff --git a/chromium/cc/tiles/image_controller.h b/chromium/cc/tiles/image_controller.h index 560226c00fd..20c4a0dc249 100644 --- a/chromium/cc/tiles/image_controller.h +++ b/chromium/cc/tiles/image_controller.h @@ -10,9 +10,10 @@ #include "base/callback.h" #include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" +#include "base/task/sequenced_task_runner.h" #include "base/threading/simple_thread.h" #include "cc/base/unique_notifier.h" #include "cc/cc_export.h" @@ -114,13 +115,13 @@ class CC_EXPORT ImageController { base::WeakPtr<ImageController> weak_ptr_; - ImageDecodeCache* cache_ = nullptr; + raw_ptr<ImageDecodeCache> cache_ = nullptr; std::vector<DrawImage> predecode_locked_images_; static ImageDecodeRequestId s_next_image_decode_queue_id_; base::flat_map<ImageDecodeRequestId, DrawImage> requested_locked_images_; - base::SequencedTaskRunner* origin_task_runner_ = nullptr; + raw_ptr<base::SequencedTaskRunner> origin_task_runner_ = nullptr; size_t image_cache_max_limit_bytes_ = 0u; // The variables defined below this lock (aside from weak_ptr_factory_) can diff --git a/chromium/cc/tiles/mipmap_util_unittest.cc b/chromium/cc/tiles/mipmap_util_unittest.cc index edbe87b5bed..2f473eb0809 100644 --- a/chromium/cc/tiles/mipmap_util_unittest.cc +++ b/chromium/cc/tiles/mipmap_util_unittest.cc @@ -4,8 +4,10 @@ #include "cc/tiles/mipmap_util.h" -#include "cc/test/geometry_test_utils.h" +#include <limits> + #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/test/geometry_util.h" namespace cc { namespace { @@ -18,12 +20,11 @@ TEST(MipMapUtilTest, Basic) { const SkSize expected_scale = SkSize::Make(0.25f, 0.25f); EXPECT_EQ(target_level, MipMapUtil::GetLevelForSize(src_size, target_size)); - EXPECT_FLOAT_SIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForLevel( - src_size, target_level)); - EXPECT_SIZE_EQ(target_size, - MipMapUtil::GetSizeForLevel(src_size, target_level)); - EXPECT_FLOAT_SIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForSize( - src_size, target_size)); + EXPECT_SKSIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForLevel( + src_size, target_level)); + EXPECT_EQ(target_size, MipMapUtil::GetSizeForLevel(src_size, target_level)); + EXPECT_SKSIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForSize( + src_size, target_size)); } // Ensures that a no-op scale works. @@ -34,12 +35,11 @@ TEST(MipMapUtilTest, NoScale) { const SkSize expected_scale = SkSize::Make(1, 1); EXPECT_EQ(target_level, MipMapUtil::GetLevelForSize(src_size, target_size)); - EXPECT_FLOAT_SIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForLevel( - src_size, target_level)); - EXPECT_SIZE_EQ(target_size, - MipMapUtil::GetSizeForLevel(src_size, target_level)); - EXPECT_FLOAT_SIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForSize( - src_size, target_size)); + EXPECT_SKSIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForLevel( + src_size, target_level)); + EXPECT_EQ(target_size, MipMapUtil::GetSizeForLevel(src_size, target_level)); + EXPECT_SKSIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForSize( + src_size, target_size)); } // Ensures that we return the base mip level if the caller requests an upscale. @@ -50,9 +50,9 @@ TEST(MipMapUtilTest, Upscale) { const int result_level = 0; EXPECT_EQ(result_level, MipMapUtil::GetLevelForSize(src_size, target_size)); - EXPECT_FLOAT_SIZE_EQ(result_size, MipMapUtil::GetScaleAdjustmentForSize( - src_size, target_size)); - EXPECT_SIZE_EQ(src_size, MipMapUtil::GetSizeForLevel(src_size, result_level)); + EXPECT_SKSIZE_EQ(result_size, MipMapUtil::GetScaleAdjustmentForSize( + src_size, target_size)); + EXPECT_EQ(src_size, MipMapUtil::GetSizeForLevel(src_size, result_level)); } // Ensures that the maximum mip level GetLevelForSize will ever return is 30. @@ -74,12 +74,11 @@ TEST(MipMapUtilTest, NonSquare) { static_cast<float>(target_size.width()) / src_size.width(), 1); EXPECT_EQ(target_level, MipMapUtil::GetLevelForSize(src_size, target_size)); - EXPECT_FLOAT_SIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForLevel( - src_size, target_level)); - EXPECT_SIZE_EQ(target_size, - MipMapUtil::GetSizeForLevel(src_size, target_level)); - EXPECT_FLOAT_SIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForSize( - src_size, target_size)); + EXPECT_SKSIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForLevel( + src_size, target_level)); + EXPECT_EQ(target_size, MipMapUtil::GetSizeForLevel(src_size, target_level)); + EXPECT_SKSIZE_EQ(expected_scale, MipMapUtil::GetScaleAdjustmentForSize( + src_size, target_size)); } // Ensures that we handle rounding images correctly. @@ -98,20 +97,19 @@ TEST(MipMapUtilTest, Rounding) { MipMapUtil::GetLevelForSize(src_size, target_size_larger)); EXPECT_EQ(target_level_smaller, MipMapUtil::GetLevelForSize(src_size, target_size_smaller)); - EXPECT_FLOAT_SIZE_EQ( + EXPECT_SKSIZE_EQ( expected_scale_larger, MipMapUtil::GetScaleAdjustmentForLevel(src_size, target_level_larger)); - EXPECT_FLOAT_SIZE_EQ( + EXPECT_SKSIZE_EQ( expected_scale_smaller, MipMapUtil::GetScaleAdjustmentForLevel(src_size, target_level_smaller)); - EXPECT_SIZE_EQ(src_size, - MipMapUtil::GetSizeForLevel(src_size, target_level_larger)); - EXPECT_SIZE_EQ(target_size_smaller, - MipMapUtil::GetSizeForLevel(src_size, target_level_smaller)); - EXPECT_FLOAT_SIZE_EQ( - expected_scale_larger, - MipMapUtil::GetScaleAdjustmentForSize(src_size, target_size_larger)); - EXPECT_FLOAT_SIZE_EQ( + EXPECT_EQ(src_size, + MipMapUtil::GetSizeForLevel(src_size, target_level_larger)); + EXPECT_EQ(target_size_smaller, + MipMapUtil::GetSizeForLevel(src_size, target_level_smaller)); + EXPECT_SKSIZE_EQ(expected_scale_larger, MipMapUtil::GetScaleAdjustmentForSize( + src_size, target_size_larger)); + EXPECT_SKSIZE_EQ( expected_scale_smaller, MipMapUtil::GetScaleAdjustmentForSize(src_size, target_size_smaller)); } diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc index 58f0f0cedca..8090d64a88e 100644 --- a/chromium/cc/tiles/picture_layer_tiling.cc +++ b/chromium/cc/tiles/picture_layer_tiling.cc @@ -509,7 +509,7 @@ PictureLayerTiling::CoverageIterator::operator++() { // unexpectedly. Unfortunately, there isn't much we can do at this point, so // we just do the correctness checks if both y and x offsets are // 'reasonable', meaning they are less than the specified value. - static constexpr int kReasonableOffsetForDcheck = 500'000'000; + static constexpr int kReasonableOffsetForDcheck = 100'000'000; if (!new_row && current_geometry_rect_.x() <= kReasonableOffsetForDcheck && current_geometry_rect_.y() <= kReasonableOffsetForDcheck) { DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x()); diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h index f22de238906..8d9a5e80e02 100644 --- a/chromium/cc/tiles/picture_layer_tiling.h +++ b/chromium/cc/tiles/picture_layer_tiling.h @@ -15,6 +15,7 @@ #include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/base/region.h" #include "cc/base/tiling_data.h" #include "cc/cc_export.h" @@ -266,12 +267,18 @@ class CC_EXPORT PictureLayerTiling { private: gfx::Rect ComputeGeometryRect() const; + // `tiling_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). const PictureLayerTiling* tiling_ = nullptr; + gfx::Size coverage_rect_max_bounds_; gfx::Rect coverage_rect_; gfx::AxisTransform2d coverage_to_content_; + // `current_tile_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). Tile* current_tile_ = nullptr; + gfx::Rect current_geometry_rect_; int tile_i_ = 0; int tile_j_ = 0; @@ -483,7 +490,7 @@ class CC_EXPORT PictureLayerTiling { // Given properties. const gfx::AxisTransform2d raster_transform_; - PictureLayerTilingClient* const client_; + const raw_ptr<PictureLayerTilingClient> client_; const WhichTree tree_; scoped_refptr<RasterSource> raster_source_; const float min_preraster_distance_; diff --git a/chromium/cc/tiles/picture_layer_tiling_set.h b/chromium/cc/tiles/picture_layer_tiling_set.h index d580aa38396..887d960879b 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set.h +++ b/chromium/cc/tiles/picture_layer_tiling_set.h @@ -12,6 +12,7 @@ #include <set> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/base/region.h" #include "cc/tiles/picture_layer_tiling.h" #include "ui/gfx/geometry/size.h" @@ -176,7 +177,7 @@ class CC_EXPORT PictureLayerTilingSet { private: size_t NextTiling() const; - const PictureLayerTilingSet* set_; + raw_ptr<const PictureLayerTilingSet> set_; float coverage_scale_; PictureLayerTiling::CoverageIterator tiling_iter_; size_t current_tiling_; @@ -210,7 +211,7 @@ class CC_EXPORT PictureLayerTilingSet { ~AutoClear() { *state_to_clear_ = StateSinceLastTilePriorityUpdate(); } private: - StateSinceLastTilePriorityUpdate* state_to_clear_; + raw_ptr<StateSinceLastTilePriorityUpdate> state_to_clear_; }; StateSinceLastTilePriorityUpdate() @@ -252,7 +253,7 @@ class CC_EXPORT PictureLayerTilingSet { const float skewport_target_time_in_seconds_; const int skewport_extrapolation_limit_in_screen_pixels_; WhichTree tree_; - PictureLayerTilingClient* client_; + raw_ptr<PictureLayerTilingClient> client_; const float max_preraster_distance_; // State saved for computing velocities based on finite differences. // .front() of the deque refers to the most recent FrameVisibleRect. diff --git a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc index 5313a1b9d66..01ff1e3170c 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_set_unittest.cc @@ -7,6 +7,7 @@ #include <map> #include <vector> +#include "build/build_config.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/fake_picture_layer_tiling_client.h" #include "cc/test/fake_raster_source.h" @@ -317,11 +318,23 @@ TEST_F(PictureLayerTilingSetTestWithResources, TwoTilings_Larger) { RunTest(2, 2.f, 8.f, 1.f, 2.f); } -TEST_F(PictureLayerTilingSetTestWithResources, ManyTilings_Equal) { +// Test is flaky: https://crbug.com/1056828. +#if defined(OS_LINUX) && defined(THREAD_SANITIZER) +#define MAYBE_ManyTilings_Equal DISABLED_ManyTilings_Equal +#else +#define MAYBE_ManyTilings_Equal ManyTilings_Equal +#endif +TEST_F(PictureLayerTilingSetTestWithResources, MAYBE_ManyTilings_Equal) { RunTest(10, 1.f, 1.f, 5.f, 5.f); } -TEST_F(PictureLayerTilingSetTestWithResources, ManyTilings_NotEqual) { +// Test is flaky: https://crbug.com/1056828. +#if defined(OS_LINUX) && defined(THREAD_SANITIZER) +#define MAYBE_ManyTilings_NotEqual DISABLED_ManyTilings_NotEqual +#else +#define MAYBE_ManyTilings_NotEqual ManyTilings_NotEqual +#endif +TEST_F(PictureLayerTilingSetTestWithResources, MAYBE_ManyTilings_NotEqual) { RunTest(10, 1.f, 1.f, 4.5f, 5.f); } diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc index 16333b02ae2..587db407bf4 100644 --- a/chromium/cc/tiles/software_image_decode_cache.cc +++ b/chromium/cc/tiles/software_image_decode_cache.cc @@ -13,7 +13,9 @@ #include "base/bind.h" #include "base/debug/stack_trace.h" #include "base/format_macros.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" +#include "base/numerics/ostream_operators.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" @@ -47,9 +49,10 @@ class AutoRemoveKeyFromTaskMap { ~AutoRemoveKeyFromTaskMap() { task_map_->erase(key_); } private: - std::unordered_map<SoftwareImageDecodeCache::CacheKey, - scoped_refptr<TileTask>, - SoftwareImageDecodeCache::CacheKeyHash>* task_map_; + raw_ptr<std::unordered_map<SoftwareImageDecodeCache::CacheKey, + scoped_refptr<TileTask>, + SoftwareImageDecodeCache::CacheKeyHash>> + task_map_; const SoftwareImageDecodeCache::CacheKey& key_; }; @@ -104,7 +107,7 @@ class SoftwareImageDecodeTaskImpl : public TileTask { ~SoftwareImageDecodeTaskImpl() override = default; private: - SoftwareImageDecodeCache* cache_; + raw_ptr<SoftwareImageDecodeCache> cache_; SoftwareImageDecodeCache::CacheKey image_key_; PaintImage paint_image_; SoftwareImageDecodeCache::DecodeTaskType task_type_; @@ -141,7 +144,7 @@ SoftwareImageDecodeCache::SoftwareImageDecodeCache( SkColorType color_type, size_t locked_memory_limit_bytes, PaintImage::GeneratorClientId generator_client_id) - : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), + : decoded_images_(ImageLRUCache::NO_AUTO_EVICT), locked_images_budget_(locked_memory_limit_bytes), color_type_(color_type), generator_client_id_(generator_client_id), diff --git a/chromium/cc/tiles/software_image_decode_cache.h b/chromium/cc/tiles/software_image_decode_cache.h index 8cf91a07936..e56288030a4 100644 --- a/chromium/cc/tiles/software_image_decode_cache.h +++ b/chromium/cc/tiles/software_image_decode_cache.h @@ -11,7 +11,7 @@ #include <unordered_map> #include <vector> -#include "base/containers/mru_cache.h" +#include "base/containers/lru_cache.h" #include "base/memory/ref_counted.h" #include "base/numerics/safe_math.h" #include "base/thread_annotations.h" @@ -96,8 +96,8 @@ class CC_EXPORT SoftwareImageDecodeCache base::CheckedNumeric<size_t> current_usage_bytes_; }; - using ImageMRUCache = base:: - HashingMRUCache<CacheKey, std::unique_ptr<CacheEntry>, CacheKeyHash>; + using ImageLRUCache = base:: + HashingLRUCache<CacheKey, std::unique_ptr<CacheEntry>, CacheKeyHash>; // Get the decoded draw image for the given key and paint_image. Note that // when used internally, we still require that DrawWithImageFinished() is @@ -140,7 +140,7 @@ class CC_EXPORT SoftwareImageDecodeCache base::Lock lock_; // Decoded images and ref counts (predecode path). - ImageMRUCache decoded_images_ GUARDED_BY(lock_); + ImageLRUCache decoded_images_ GUARDED_BY(lock_); // A map of PaintImage::FrameKey to the ImageKeys for cached decodes of this // PaintImage. diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h index b2e820f5c94..bf4d2d6eff6 100644 --- a/chromium/cc/tiles/tile.h +++ b/chromium/cc/tiles/tile.h @@ -12,6 +12,7 @@ #include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/paint/draw_image.h" #include "cc/raster/tile_task.h" @@ -143,8 +144,8 @@ class CC_EXPORT Tile { int source_frame_number, int flags); - TileManager* const tile_manager_; - const PictureLayerTiling* tiling_; + const raw_ptr<TileManager> tile_manager_; + raw_ptr<const PictureLayerTiling> tiling_; const gfx::Rect content_rect_; const gfx::Rect enclosing_layer_rect_; const gfx::AxisTransform2d raster_transform_; diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc index c10888335c2..f92aa115bd2 100644 --- a/chromium/cc/tiles/tile_manager.cc +++ b/chromium/cc/tiles/tile_manager.cc @@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/json/json_writer.h" #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram.h" #include "base/numerics/safe_conversions.h" #include "base/threading/thread_checker.h" @@ -159,7 +160,7 @@ class RasterTaskImpl : public TileTask { // The following members are needed for processing completion of this task on // origin thread. These are not thread-safe and should be accessed only in // origin thread. Ensure their access by checking CalledOnValidThread(). - TileManager* tile_manager_; + raw_ptr<TileManager> tile_manager_; Tile::Id tile_id_; ResourcePool::InUsePoolResource resource_; @@ -172,7 +173,7 @@ class RasterTaskImpl : public TileTask { TileResolution tile_resolution_; int layer_id_; uint64_t source_prepare_tiles_id_; - void* tile_tracing_id_; + raw_ptr<void> tile_tracing_id_; uint64_t new_content_id_; int source_frame_number_; std::unique_ptr<RasterBuffer> raster_buffer_; @@ -330,7 +331,7 @@ class TaskSetFinishedTaskImpl : public TileTask { } private: - base::SequencedTaskRunner* task_runner_; + raw_ptr<base::SequencedTaskRunner> task_runner_; const base::RepeatingClosure on_task_set_finished_callback_; }; @@ -363,8 +364,8 @@ class DidFinishRunningAllTilesTask : public TileTask { ~DidFinishRunningAllTilesTask() override = default; private: - base::SequencedTaskRunner* task_runner_; - RasterQueryQueue* pending_raster_queries_; + raw_ptr<base::SequencedTaskRunner> task_runner_; + raw_ptr<RasterQueryQueue> pending_raster_queries_; CompletionCb completion_cb_; }; diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h index f243af2984c..250d227ff74 100644 --- a/chromium/cc/tiles/tile_manager.h +++ b/chromium/cc/tiles/tile_manager.h @@ -15,8 +15,9 @@ #include <utility> #include <vector> -#include "base/sequenced_task_runner.h" +#include "base/memory/raw_ptr.h" #include "base/synchronization/waitable_event.h" +#include "base/task/sequenced_task_runner.h" #include "cc/base/unique_notifier.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/raster_query_queue.h" @@ -438,18 +439,18 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { void ScheduleCheckRasterFinishedQueries(); void CheckRasterFinishedQueries(); - TileManagerClient* client_; - base::SequencedTaskRunner* task_runner_; - ResourcePool* resource_pool_; + raw_ptr<TileManagerClient> client_; + raw_ptr<base::SequencedTaskRunner> task_runner_; + raw_ptr<ResourcePool> resource_pool_; std::unique_ptr<TileTaskManager> tile_task_manager_; - RasterBufferProvider* raster_buffer_provider_; + raw_ptr<RasterBufferProvider> raster_buffer_provider_; GlobalStateThatImpactsTilePriority global_state_; size_t scheduled_raster_task_limit_; const TileManagerSettings tile_manager_settings_; bool use_gpu_rasterization_; bool use_oop_rasterization_; - RasterQueryQueue* pending_raster_queries_ = nullptr; + raw_ptr<RasterQueryQueue> pending_raster_queries_ = nullptr; std::unordered_map<Tile::Id, Tile*> tiles_; diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc index c94adcdf0a1..703f2122581 100644 --- a/chromium/cc/tiles/tile_manager_unittest.cc +++ b/chromium/cc/tiles/tile_manager_unittest.cc @@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/containers/contains.h" +#include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -1624,7 +1625,7 @@ class TestSoftwareRasterBufferProvider : public FakeRasterBufferProviderImpl { private: gfx::Size size_; - void* pixels_; + raw_ptr<void> pixels_; }; }; diff --git a/chromium/cc/tiles/tile_task_manager.h b/chromium/cc/tiles/tile_task_manager.h index f77a4603b91..4e5cc789700 100644 --- a/chromium/cc/tiles/tile_task_manager.h +++ b/chromium/cc/tiles/tile_task_manager.h @@ -7,6 +7,7 @@ #include <stddef.h> +#include "base/memory/raw_ptr.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/task_graph_runner.h" #include "cc/raster/tile_task.h" @@ -52,7 +53,7 @@ class CC_EXPORT TileTaskManagerImpl : public TileTaskManager { protected: explicit TileTaskManagerImpl(TaskGraphRunner* task_graph_runner); - TaskGraphRunner* task_graph_runner_; + raw_ptr<TaskGraphRunner> task_graph_runner_; const NamespaceToken namespace_token_; }; diff --git a/chromium/cc/tiles/tiling_set_eviction_queue.h b/chromium/cc/tiles/tiling_set_eviction_queue.h index ebd01011c19..6b830f1a3c0 100644 --- a/chromium/cc/tiles/tiling_set_eviction_queue.h +++ b/chromium/cc/tiles/tiling_set_eviction_queue.h @@ -112,7 +112,11 @@ class CC_EXPORT TilingSetEvictionQueue { bool GetFirstTileAndCheckIfValid(TilingIteratorType* iterator); PrioritizedTile prioritized_tile_; + + // `tilings_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data and tab_search:top100:2020). std::vector<PictureLayerTiling*>* tilings_; + WhichTree tree_; PictureLayerTiling::PriorityRectType priority_rect_type_; size_t tiling_index_; diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.h b/chromium/cc/tiles/tiling_set_raster_queue_all.h index 07c98b5fc47..92fd6c679fd 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_all.h +++ b/chromium/cc/tiles/tiling_set_raster_queue_all.h @@ -62,8 +62,13 @@ class CC_EXPORT TilingSetRasterQueueAll { IsTileValidResult IsTileValid(const Tile* tile) const; PrioritizedTile current_tile_; + + // `tiling_` and `tiling_data_` are not a raw_ptr<...> for performance + // reasons (based on analysis of sampling profiler data and + // tab_search:top100:2020). PictureLayerTiling* tiling_; TilingData* tiling_data_; + PictureLayerTiling::PriorityRectType priority_rect_type_; gfx::Rect pending_visible_rect_; }; @@ -163,6 +168,9 @@ class CC_EXPORT TilingSetRasterQueueAll { void AdvancePhase(); + // `tiling_` and `tiling_data_` are not a raw_ptr<...> for performance + // reasons (based on analysis of sampling profiler data and + // tab_search:top100:2020). PictureLayerTiling* tiling_; TilingData* tiling_data_; @@ -186,6 +194,8 @@ class CC_EXPORT TilingSetRasterQueueAll { void MakeTilingIterator(IteratorType type, PictureLayerTiling* tiling); void AdvanceToNextStage(); + // `tiling_set_` is not a raw_ptr<...> for performance reasons (based on + // analysis of sampling profiler data). PictureLayerTilingSet* tiling_set_; struct IterationStage { diff --git a/chromium/cc/tiles/tiling_set_raster_queue_required.h b/chromium/cc/tiles/tiling_set_raster_queue_required.h index 3bc8a96037f..1a89cad01f7 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_required.h +++ b/chromium/cc/tiles/tiling_set_raster_queue_required.h @@ -42,6 +42,9 @@ class CC_EXPORT TilingSetRasterQueueRequired { TilingIterator& operator++(); private: + // `tiling_` and `tiling_data_` are not a raw_ptr<...> for performance + // reasons (based on analysis of sampling profiler data and + // tab_search:top100:2020). PictureLayerTiling* tiling_; TilingData* tiling_data_; diff --git a/chromium/cc/trees/commit_state.cc b/chromium/cc/trees/commit_state.cc new file mode 100644 index 00000000000..50f631479bc --- /dev/null +++ b/chromium/cc/trees/commit_state.cc @@ -0,0 +1,64 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/trees/commit_state.h" + +namespace cc { + +CommitState::CommitState() = default; +CommitState::~CommitState() = default; +CommitState::CommitState(const CommitState& prev) + : surface_ranges(prev.surface_ranges), + visual_properties_update_duration(prev.visual_properties_update_duration), + have_scroll_event_handlers(prev.have_scroll_event_handlers), + is_external_pinch_gesture_active(prev.is_external_pinch_gesture_active), + is_viewport_mobile_optimized(prev.is_viewport_mobile_optimized), + may_throttle_if_undrawn_frames(prev.may_throttle_if_undrawn_frames), + prefers_reduced_motion(prev.prefers_reduced_motion), + browser_controls_params(prev.browser_controls_params), + bottom_controls_shown_ratio(prev.bottom_controls_shown_ratio), + device_scale_factor(prev.device_scale_factor), + external_page_scale_factor(prev.external_page_scale_factor), + max_page_scale_factor(prev.max_page_scale_factor), + min_page_scale_factor(prev.min_page_scale_factor), + page_scale_factor(prev.page_scale_factor), + painted_device_scale_factor(prev.painted_device_scale_factor), + top_controls_shown_ratio(prev.top_controls_shown_ratio), + display_color_spaces(prev.display_color_spaces), + display_transform_hint(prev.display_transform_hint), + device_viewport_rect(prev.device_viewport_rect), + visual_device_viewport_size(prev.visual_device_viewport_size), + elastic_overscroll(prev.elastic_overscroll), + hud_layer_id(prev.hud_layer_id), + source_frame_number(prev.source_frame_number), + selection(prev.selection), + debug_state(prev.debug_state), + overscroll_behavior(prev.overscroll_behavior), + background_color(prev.background_color), + viewport_property_ids(prev.viewport_property_ids), + local_surface_id_from_parent(prev.local_surface_id_from_parent) { + memcpy(event_listener_properties, prev.event_listener_properties, + sizeof(event_listener_properties)); +} + +base::flat_set<viz::SurfaceRange> CommitState::SurfaceRanges() const { + base::flat_set<viz::SurfaceRange> ranges; + for (auto& map_entry : surface_ranges) + ranges.insert(map_entry.first); + return ranges; +} + +EventListenerProperties CommitState::GetEventListenerProperties( + EventListenerClass listener_class) const { + DCHECK(listener_class >= EventListenerClass::kPointerRawUpdate); + DCHECK(listener_class <= EventListenerClass::kTouchEndOrCancel); + return event_listener_properties[static_cast<size_t>(listener_class)]; +} + +ThreadUnsafeCommitState::ThreadUnsafeCommitState(MutatorHost* mh) + : mutator_host(mh) {} + +ThreadUnsafeCommitState::~ThreadUnsafeCommitState() = default; + +} // namespace cc diff --git a/chromium/cc/trees/commit_state.h b/chromium/cc/trees/commit_state.h new file mode 100644 index 00000000000..fbd458e9df6 --- /dev/null +++ b/chromium/cc/trees/commit_state.h @@ -0,0 +1,179 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_COMMIT_STATE_H_ +#define CC_TREES_COMMIT_STATE_H_ + +#include <memory> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "base/time/time.h" +#include "cc/benchmarks/micro_benchmark_impl.h" +#include "cc/cc_export.h" +#include "cc/debug/layer_tree_debug_state.h" +#include "cc/document_transition/document_transition_request.h" +#include "cc/input/event_listener_properties.h" +#include "cc/input/layer_selection_bound.h" +#include "cc/input/overscroll_behavior.h" +#include "cc/input/page_scale_animation.h" +#include "cc/layers/layer.h" +#include "cc/layers/layer_list_iterator.h" +#include "cc/metrics/begin_main_frame_metrics.h" +#include "cc/metrics/event_metrics.h" +#include "cc/paint/paint_image.h" +#include "cc/resources/ui_resource_request.h" +#include "cc/trees/browser_controls_params.h" +#include "cc/trees/presentation_time_callback_buffer.h" +#include "cc/trees/swap_promise.h" +#include "cc/trees/viewport_property_ids.h" +#include "components/viz/common/surfaces/local_surface_id.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/delegated_ink_metadata.h" +#include "ui/gfx/display_color_spaces.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/vector2d_f.h" +#include "ui/gfx/overlay_transform.h" + +namespace cc { + +// CommitState and ThreadUnsafeCommitState contain all of the information from +// LayerTreeHost that is needed to run compositor commit. CommitState is +// effectively POD; the compositor gets its own copy, which it may read or write +// without any concurrency issues. ThreadUnsafeCommitState is shared data that +// is *not* copied to the compositor. Main thread code must take care not to +// modify anything reachable from ThreadUnsafeCommitState while commit is +// running on the impl thread, typically by adding calls to +// LayerTreeHost::WaitForCommitCompletion() before attempting to mutate state. + +struct CC_EXPORT CommitState { + CommitState(); + // Note: the copy constructor only copies persistent fields + CommitState(const CommitState&); + CommitState& operator=(const CommitState&) = delete; + ~CommitState(); + + base::flat_set<viz::SurfaceRange> SurfaceRanges() const; + EventListenerProperties GetEventListenerProperties(EventListenerClass) const; + + // ------------------------------------------------------------------------- + // Persistent: these values persist on the LayerTreeHost between commits. + // When a new persistent field is added, it must also be added to the copy + // constructor. + + base::flat_map<viz::SurfaceRange, int> surface_ranges; + base::TimeDelta visual_properties_update_duration; + bool needs_gpu_rasterization_histogram = false; + bool have_scroll_event_handlers = false; + bool is_external_pinch_gesture_active = false; + // Set to true if viewport is mobile optimized by using meta tag + // <meta name="viewport" content="width=device-width"> + // or + // <meta name="viewport" content="initial-scale=1.0"> + bool is_viewport_mobile_optimized = false; + bool may_throttle_if_undrawn_frames = true; + bool prefers_reduced_motion = false; + BrowserControlsParams browser_controls_params; + EventListenerProperties + event_listener_properties[static_cast<size_t>(EventListenerClass::kLast) + + 1] = {EventListenerProperties::kNone}; + float bottom_controls_shown_ratio = 0.f; + float device_scale_factor = 1.f; + float external_page_scale_factor = 1.f; + float max_page_scale_factor = 1.f; + float min_page_scale_factor = 1.f; + float page_scale_factor = 1.f; + float painted_device_scale_factor = 1.f; + float top_controls_shown_ratio = 0.f; + gfx::DisplayColorSpaces display_color_spaces; + // Display transform hint to tag generated compositor frames. + gfx::OverlayTransform display_transform_hint = gfx::OVERLAY_TRANSFORM_NONE; + gfx::Rect device_viewport_rect; + gfx::Size visual_device_viewport_size; + gfx::Vector2dF elastic_overscroll; + int hud_layer_id = Layer::INVALID_ID; + int source_frame_number = 0; + LayerSelection selection; + LayerTreeDebugState debug_state; + OverscrollBehavior overscroll_behavior; + SkColor background_color = SK_ColorWHITE; + ViewportPropertyIds viewport_property_ids; + viz::LocalSurfaceId local_surface_id_from_parent; + + // ------------------------------------------------------------------------- + // Take/reset: these values are reset on the LayerTreeHost between commits. + + // The number of SurfaceLayers that have (fallback,primary) set to + // viz::SurfaceRange. + bool clear_caches_on_next_commit = false; + // Whether we have a pending request to force send RenderFrameMetadata with + // the next frame. + bool force_send_metadata_request = false; + bool commit_waits_for_activation = false; + bool needs_full_tree_sync = false; + bool needs_surface_ranges_sync = false; + bool new_local_surface_id_request = false; + bool next_commit_forces_recalculate_raster_scales = false; + bool next_commit_forces_redraw = false; + EventMetrics::List event_metrics; + // Latency information for work done in ProxyMain::BeginMainFrame. The + // unique_ptr is allocated in RequestMainFrameUpdate, and passed to Blink's + // LocalFrameView that fills in the fields. This object adds the timing for + // UpdateLayers. CC reads the data during commit, and clears the unique_ptr. + std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics; + // Metadata required for drawing a delegated ink trail onto the end of a + // stroke. std::unique_ptr was specifically chosen so that it would be + // cleared as it is forwarded along the pipeline to avoid old information + // incorrectly sticking around and potentially being reused. + std::unique_ptr<gfx::DelegatedInkMetadata> delegated_ink_metadata; + std::unique_ptr<PendingPageScaleAnimation> pending_page_scale_animation; + std::vector<std::pair<int, std::unique_ptr<PaintImage>>> queued_image_decodes; + // Presentation time callbacks requested for the next frame are initially + // added here. + std::vector<PresentationTimeCallbackBuffer::MainCallback> + pending_presentation_time_callbacks; + std::vector<std::unique_ptr<MicroBenchmarkImpl>> benchmarks; + // A list of document transitions that need to be transported from Blink to + // Viz, as a CompositorFrameTransitionDirective. + std::vector<std::unique_ptr<DocumentTransitionRequest>> + document_transition_requests; + std::vector<std::unique_ptr<SwapPromise>> swap_promises; + std::vector<UIResourceRequest> ui_resource_request_queue; + base::flat_map<UIResourceId, gfx::Size> ui_resource_sizes; +}; + +struct CC_EXPORT ThreadUnsafeCommitState { + explicit ThreadUnsafeCommitState(MutatorHost* mh); + ~ThreadUnsafeCommitState(); + + // TODO(szager/vmpstr): These methods are to support range-based 'for' loops, + // which is weird because ThreadUnsafeCommitState is not a collection or + // container. We should do something more sensible and less weird. + LayerListIterator begin() const { + return LayerListIterator(root_layer.get()); + } + LayerListIterator end() const { return LayerListIterator(nullptr); } + + // Set of layers that need to push properties. + base::flat_set<Layer*> layers_that_should_push_properties; + MutatorHost* mutator_host; + PropertyTrees property_trees; + scoped_refptr<Layer> root_layer; +}; + +struct CC_EXPORT CommitTimestamps { + // Time when the compositor first became aware that a commit was requested by + // the main thread. + base::TimeTicks start; + // Time when the compositor finished the commit. + base::TimeTicks finish; +}; + +} // namespace cc + +#endif // CC_TREES_COMMIT_STATE_H_ diff --git a/chromium/cc/trees/damage_tracker.h b/chromium/cc/trees/damage_tracker.h index 70a8356ce58..d4bb1fc802a 100644 --- a/chromium/cc/trees/damage_tracker.h +++ b/chromium/cc/trees/damage_tracker.h @@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/layers/layer_collections.h" #include "ui/gfx/geometry/rect.h" @@ -157,7 +158,7 @@ class CC_EXPORT DamageTracker { struct SurfaceWithRect { SurfaceWithRect(RenderSurfaceImpl* rs, const gfx::Rect& rect) : render_surface(rs), rect_in_target_space(rect) {} - RenderSurfaceImpl* render_surface; + raw_ptr<RenderSurfaceImpl> render_surface; const gfx::Rect rect_in_target_space; }; diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 48332d88b20..e3524c8214c 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -8,13 +8,13 @@ #include <limits> #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "cc/base/math_util.h" #include "cc/layers/layer_impl.h" #include "cc/paint/filter_operation.h" #include "cc/paint/filter_operations.h" #include "cc/test/fake_picture_layer_impl.h" #include "cc/test/fake_raster_source.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/test/property_tree_test_utils.h" #include "cc/trees/effect_node.h" @@ -301,12 +301,12 @@ class DamageTrackerTest : public LayerTreeImplTestBase, public testing::Test { std::vector<TestLayerImpl*> child_layers_; // Store result of CreateTestTreeWithTwoSurfaces(). - TestLayerImpl* child1_ = nullptr; - TestLayerImpl* child2_ = nullptr; - TestLayerImpl* grand_child1_ = nullptr; - TestLayerImpl* grand_child2_ = nullptr; - TestLayerImpl* grand_child3_ = nullptr; - TestLayerImpl* grand_child4_ = nullptr; + raw_ptr<TestLayerImpl> child1_ = nullptr; + raw_ptr<TestLayerImpl> child2_ = nullptr; + raw_ptr<TestLayerImpl> grand_child1_ = nullptr; + raw_ptr<TestLayerImpl> grand_child2_ = nullptr; + raw_ptr<TestLayerImpl> grand_child3_ = nullptr; + raw_ptr<TestLayerImpl> grand_child4_ = nullptr; }; TEST_F(DamageTrackerTest, SanityCheckTestTreeWithOneSurface) { @@ -563,7 +563,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPropertyChanges) { expected_rect.Union(gfx::Rect(200, 230, 30, 30)); EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid( &root_damage_rect)); - EXPECT_FLOAT_RECT_EQ(expected_rect, root_damage_rect); + EXPECT_EQ(expected_rect, root_damage_rect); EXPECT_TRUE(GetRenderSurface(root) ->damage_tracker() ->has_damage_from_contributing_content()); @@ -1334,7 +1334,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantSurface) { gfx::Rect root_damage_rect; ClearDamageForAllSurfaces(root); - SetPostTranslation(child1_, gfx::Vector2dF(105.f, 107.f)); + SetPostTranslation(child1_.get(), gfx::Vector2dF(105.f, 107.f)); child1_->NoteLayerPropertyChanged(); EmulateDrawingOneFrame(root); EXPECT_TRUE(GetRenderSurface(child1_)->damage_tracker()->GetDamageRectIfValid( @@ -1413,7 +1413,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) { // CASE 1: If a descendant surface disappears, its entire old area becomes // exposed. ClearDamageForAllSurfaces(root); - SetRenderSurfaceReason(child1_, RenderSurfaceReason::kNone); + SetRenderSurfaceReason(child1_.get(), RenderSurfaceReason::kNone); EmulateDrawingOneFrame(root); // Sanity check that there is only one surface now. @@ -1442,7 +1442,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingRenderSurfaces) { // Then change the tree so that the render surface is added back. ClearDamageForAllSurfaces(root); - SetRenderSurfaceReason(child1_, RenderSurfaceReason::kTest); + SetRenderSurfaceReason(child1_.get(), RenderSurfaceReason::kTest); EmulateDrawingOneFrame(root); @@ -1687,7 +1687,7 @@ TEST_F(DamageTrackerTest, VerifyDamageWithNoContributingLayers) { EmulateDrawingOneFrame(root); DCHECK_EQ(GetRenderSurface(empty_surface), empty_surface->render_target()); - RenderSurfaceImpl* target_surface = GetRenderSurface(empty_surface); + const RenderSurfaceImpl* target_surface = GetRenderSurface(empty_surface); gfx::Rect damage_rect; EXPECT_TRUE( target_surface->damage_tracker()->GetDamageRectIfValid(&damage_rect)); @@ -1956,7 +1956,7 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(5.f)); child1_->SetDrawsContent(true); - SetBackdropFilter(child1_, filters); + SetBackdropFilter(child1_.get(), filters); // Really far left. grand_child1_->SetOffsetToTransformParent(gfx::Vector2dF( @@ -2051,7 +2051,7 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { // Add a backdrop blur filter onto child1_ FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(2.f)); - SetBackdropFilter(child1_, filters); + SetBackdropFilter(child1_.get(), filters); child1_->NoteLayerPropertyChanged(); // intersects_damage_under_ is false by default. EXPECT_TRUE(GetRenderSurface(child1_)->intersects_damage_under()); @@ -2091,10 +2091,10 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { // backdrop-filtered result of the corresponding render surfaces. ClearDamageForAllSurfaces(root); // Remove the backdrop filter on child1_ - SetBackdropFilter(child1_, FilterOperations()); + SetBackdropFilter(child1_.get(), FilterOperations()); grand_child1_->NoteLayerPropertyChanged(); // Add a backdrop blur filtre to grand_child4_ - SetBackdropFilter(grand_child4_, filters); + SetBackdropFilter(grand_child4_.get(), filters); grand_child4_->NoteLayerPropertyChanged(); EmulateDrawingOneFrame(root); EXPECT_TRUE(GetRenderSurface(grand_child4_)->intersects_damage_under()); @@ -2201,7 +2201,7 @@ TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) { // surface with the backdrop filter invalidate cached backdrop-filtered // result. ClearDamageForAllSurfaces(root); - SetRenderSurfaceReason(grand_child3_, RenderSurfaceReason::kNone); + SetRenderSurfaceReason(grand_child3_.get(), RenderSurfaceReason::kNone); grand_child3_->SetDrawsContent(false); EmulateDrawingOneFrame(root); EXPECT_TRUE(GetRenderSurface(grand_child4_)->intersects_damage_under()); @@ -2337,7 +2337,7 @@ TEST_F(DamageTrackerTest, VerifyDamageExpansionWithBackdropBlurFilters) { // Setting the filter will damage the whole surface. ClearDamageForAllSurfaces(root); - SetBackdropFilter(child1_, filters); + SetBackdropFilter(child1_.get(), filters); child1_->NoteLayerPropertyChanged(); EmulateDrawingOneFrame(root); diff --git a/chromium/cc/trees/debug_rect_history.cc b/chromium/cc/trees/debug_rect_history.cc index 6d460fad605..107602b69a2 100644 --- a/chromium/cc/trees/debug_rect_history.cc +++ b/chromium/cc/trees/debug_rect_history.cc @@ -7,7 +7,6 @@ #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" @@ -71,6 +70,11 @@ void DebugRectHistory::SaveDebugRectsForCurrentFrame( } void DebugRectHistory::SaveLayoutShiftRects(HeadsUpDisplayLayerImpl* hud) { + // We store the layout shift rects on the hud layer. If we don't have the hud + // layer, then there is nothing to store. + if (!hud) + return; + for (gfx::Rect rect : hud->LayoutShiftRects()) { debug_rects_.push_back(DebugRect( LAYOUT_SHIFT_RECT_TYPE, @@ -166,35 +170,14 @@ void DebugRectHistory::SaveWheelEventHandlerRects(LayerTreeImpl* tree_impl) { // 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; + 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))); } - - // 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)))); } } diff --git a/chromium/cc/trees/debug_rect_history.h b/chromium/cc/trees/debug_rect_history.h index 0321cb73135..021f2af69b6 100644 --- a/chromium/cc/trees/debug_rect_history.h +++ b/chromium/cc/trees/debug_rect_history.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "cc/cc_export.h" #include "cc/input/touch_action.h" #include "cc/layers/layer_collections.h" #include "ui/gfx/geometry/rect.h" @@ -77,7 +78,7 @@ struct DebugRect { // This class maintains a history of rects of various types that can be used // for debugging purposes. The overhead of collecting rects is performed only if // the appropriate LayerTreeSettings are enabled. -class DebugRectHistory { +class CC_EXPORT DebugRectHistory { public: static std::unique_ptr<DebugRectHistory> Create(); diff --git a/chromium/cc/trees/draw_properties_unittest.cc b/chromium/cc/trees/draw_properties_unittest.cc index dfc6851cf1e..84983a541d4 100644 --- a/chromium/cc/trees/draw_properties_unittest.cc +++ b/chromium/cc/trees/draw_properties_unittest.cc @@ -12,6 +12,7 @@ #include "base/containers/contains.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "cc/animation/animation.h" #include "cc/animation/animation_host.h" #include "cc/animation/animation_id_provider.h" @@ -24,7 +25,6 @@ #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/fake_picture_layer_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/test/property_tree_test_utils.h" #include "cc/trees/clip_node.h" @@ -39,6 +39,7 @@ #include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform.h" #include "ui/gfx/geometry/transform_operations.h" #include "ui/gfx/geometry/transform_util.h" @@ -104,7 +105,8 @@ class DrawPropertiesTestBase : public LayerTreeImplTestBase { // TODO(https://crbug.com/939968) This call should be handled by // FakeLayerTreeHost instead of manually pushing the properties from the // layer tree host to the pending tree. - host()->PushLayerTreePropertiesTo(host_impl()->pending_tree()); + host_impl()->pending_tree()->PullLayerTreePropertiesFrom( + *host()->GetPendingCommitState()); UpdateDrawProperties(host_impl()->pending_tree()); } @@ -210,13 +212,10 @@ TEST_F(DrawPropertiesTest, TransformsForNoOpLayer) { UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), child->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - child->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - grand_child->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - grand_child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), child->DrawTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), grand_child->DrawTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), grand_child->ScreenSpaceTransform()); } TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { @@ -235,10 +234,10 @@ TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { // transform or the screenspace transform. layer->SetBounds(gfx::Size(10, 12)); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::DrawTransform(layer, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::ScreenSpaceTransform(layer, transform_tree)); @@ -247,10 +246,10 @@ TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { CreateTransformNode(layer).origin = gfx::Point3F(2.5f, 3.0f, 0.f); layer->SetBounds(gfx::Size(10, 12)); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::DrawTransform(layer, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::ScreenSpaceTransform(layer, transform_tree)); @@ -260,10 +259,10 @@ TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { position_transform.Translate(0.f, 1.2f); SetPostTranslation(layer, gfx::Vector2dF(0.f, 1.2f)); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( position_transform, draw_property_utils::DrawTransform(layer, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( position_transform, draw_property_utils::ScreenSpaceTransform(layer, transform_tree)); @@ -276,10 +275,9 @@ TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { SetTransformOrigin(layer, gfx::Point3F()); SetPostTranslation(layer, gfx::Vector2dF()); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( - layer_transform, - draw_property_utils::DrawTransform(layer, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(layer_transform, draw_property_utils::DrawTransform( + layer, transform_tree, effect_tree)); + EXPECT_TRANSFORM_EQ( layer_transform, draw_property_utils::ScreenSpaceTransform(layer, transform_tree)); @@ -290,10 +288,9 @@ TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { gfx::InvertAndCheck(translation_to_anchor); SetTransformOrigin(layer, gfx::Point3F(5.f, 0.f, 0.f)); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected_result, - draw_property_utils::DrawTransform(layer, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(expected_result, draw_property_utils::DrawTransform( + layer, transform_tree, effect_tree)); + EXPECT_TRANSFORM_EQ( expected_result, draw_property_utils::ScreenSpaceTransform(layer, transform_tree)); @@ -305,16 +302,15 @@ TEST_F(DrawPropertiesTest, TransformsForSingleLayer) { gfx::InvertAndCheck(translation_to_anchor); SetPostTranslation(layer, gfx::Vector2dF(0.f, 1.2f)); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected_result, - draw_property_utils::DrawTransform(layer, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(expected_result, draw_property_utils::DrawTransform( + layer, transform_tree, effect_tree)); + EXPECT_TRANSFORM_EQ( expected_result, draw_property_utils::ScreenSpaceTransform(layer, transform_tree)); } TEST_F(DrawPropertiesTest, TransformsAboutScrollOffset) { - const gfx::Vector2dF kScrollOffset(50, 100); + const gfx::PointF kScrollOffset(50, 100); const gfx::Vector2dF kScrollDelta(2.34f, 5.67f); const gfx::Vector2d kMaxScrollOffset(200, 200); const gfx::PointF kScrollLayerPosition(-kScrollOffset.x(), @@ -356,10 +352,8 @@ TEST_F(DrawPropertiesTest, TransformsAboutScrollOffset) { std::round(sub_layer_screen_position.y() * page_scale * kDeviceScale)); expected_transform.Scale(page_scale * kDeviceScale, page_scale * kDeviceScale); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - sublayer->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - sublayer->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, sublayer->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, sublayer->ScreenSpaceTransform()); gfx::Transform arbitrary_translate; const float kTranslateX = 10.6f; @@ -375,8 +369,7 @@ TEST_F(DrawPropertiesTest, TransformsAboutScrollOffset) { sub_layer_screen_position.y() * page_scale * kDeviceScale)); expected_transform.Scale(page_scale * kDeviceScale, page_scale * kDeviceScale); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - sublayer->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, sublayer->DrawTransform()); // Test that page scale is updated even when we don't rebuild property trees. page_scale = 1.888f; @@ -393,8 +386,7 @@ TEST_F(DrawPropertiesTest, TransformsAboutScrollOffset) { sub_layer_screen_position.y() * page_scale * kDeviceScale)); expected_transform.Scale(page_scale * kDeviceScale, page_scale * kDeviceScale); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - sublayer->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, sublayer->DrawTransform()); } TEST_F(DrawPropertiesTest, TransformsForSimpleHierarchy) { @@ -423,16 +415,16 @@ TEST_F(DrawPropertiesTest, TransformsForSimpleHierarchy) { UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::DrawTransform(child, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::ScreenSpaceTransform(child, transform_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), draw_property_utils::DrawTransform( - grand_child, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(gfx::Transform(), + draw_property_utils::DrawTransform( + grand_child, transform_tree, effect_tree)); + EXPECT_TRANSFORM_EQ( gfx::Transform(), draw_property_utils::ScreenSpaceTransform(grand_child, transform_tree)); @@ -441,16 +433,16 @@ TEST_F(DrawPropertiesTest, TransformsForSimpleHierarchy) { parent_position_transform.Translate(0.f, 1.2f); SetPostTranslation(parent, gfx::Vector2dF(0.f, 1.2f)); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( parent_position_transform, draw_property_utils::DrawTransform(child, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( parent_position_transform, draw_property_utils::ScreenSpaceTransform(child, transform_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( - parent_position_transform, draw_property_utils::DrawTransform( - grand_child, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(parent_position_transform, + draw_property_utils::DrawTransform( + grand_child, transform_tree, effect_tree)); + EXPECT_TRANSFORM_EQ( parent_position_transform, draw_property_utils::ScreenSpaceTransform(grand_child, transform_tree)); @@ -465,17 +457,16 @@ TEST_F(DrawPropertiesTest, TransformsForSimpleHierarchy) { SetTransform(parent, parent_layer_transform); SetPostTranslation(parent, gfx::Vector2dF()); UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( parent_composite_transform, draw_property_utils::DrawTransform(child, transform_tree, effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( parent_composite_transform, draw_property_utils::ScreenSpaceTransform(child, transform_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( - parent_composite_transform, - draw_property_utils::DrawTransform(grand_child, transform_tree, - effect_tree)); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(parent_composite_transform, + draw_property_utils::DrawTransform( + grand_child, transform_tree, effect_tree)); + EXPECT_TRANSFORM_EQ( parent_composite_transform, draw_property_utils::ScreenSpaceTransform(grand_child, transform_tree)); } @@ -525,22 +516,20 @@ TEST_F(DrawPropertiesTest, TransformsForSingleRenderSurface) { // The child layer's draw transform should refer to its new render surface. // The screen-space transform, however, should still refer to the root. - EXPECT_TRANSFORMATION_MATRIX_EQ(surface_sublayer_transform, - child->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(parent_composite_transform, - child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(surface_sublayer_transform, child->DrawTransform()); + EXPECT_TRANSFORM_EQ(parent_composite_transform, + child->ScreenSpaceTransform()); // Because the grand_child is the only drawable content, the child's render // surface will tighten its bounds to the grand_child. The scale at which the // surface's subtree is drawn must be removed from the composite transform. - EXPECT_TRANSFORMATION_MATRIX_EQ(surface_sublayer_composite_transform, - child->render_target()->draw_transform()); + EXPECT_TRANSFORM_EQ(surface_sublayer_composite_transform, + child->render_target()->draw_transform()); // The screen space is the same as the target since the child surface draws // into the root. - EXPECT_TRANSFORMATION_MATRIX_EQ( - surface_sublayer_composite_transform, - child->render_target()->screen_space_transform()); + EXPECT_TRANSFORM_EQ(surface_sublayer_composite_transform, + child->render_target()->screen_space_transform()); } TEST_F(DrawPropertiesTest, TransformsForRenderSurfaceHierarchy) { @@ -708,54 +697,46 @@ TEST_F(DrawPropertiesTest, TransformsForRenderSurfaceHierarchy) { // Verify layer draw transforms note that draw transforms are described with // respect to the nearest ancestor render surface but screen space transforms // are described with respect to the root. - EXPECT_TRANSFORMATION_MATRIX_EQ(A, parent->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A, child_of_root->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A, - grand_child_of_root->DrawTransform()); + EXPECT_TRANSFORM_EQ(A, parent->DrawTransform()); + EXPECT_TRANSFORM_EQ(A * A, child_of_root->DrawTransform()); + EXPECT_TRANSFORM_EQ(A * A * A, grand_child_of_root->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(SS1, render_surface1->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(SS1 * A, child_of_rs1->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(SS1 * A * A, - grand_child_of_rs1->DrawTransform()); + EXPECT_TRANSFORM_EQ(SS1, render_surface1->DrawTransform()); + EXPECT_TRANSFORM_EQ(SS1 * A, child_of_rs1->DrawTransform()); + EXPECT_TRANSFORM_EQ(SS1 * A * A, grand_child_of_rs1->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(SS2, render_surface2->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(SS2 * A, child_of_rs2->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(SS2 * A * A, - grand_child_of_rs2->DrawTransform()); + EXPECT_TRANSFORM_EQ(SS2, render_surface2->DrawTransform()); + EXPECT_TRANSFORM_EQ(SS2 * A, child_of_rs2->DrawTransform()); + EXPECT_TRANSFORM_EQ(SS2 * A * A, grand_child_of_rs2->DrawTransform()); // Verify layer screen-space transforms // - EXPECT_TRANSFORMATION_MATRIX_EQ(A, parent->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A, child_of_root->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A, - grand_child_of_root->ScreenSpaceTransform()); - - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A, - render_surface1->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A, - child_of_rs1->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A * A, - grand_child_of_rs1->ScreenSpaceTransform()); - - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A, - render_surface2->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A * A, - child_of_rs2->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * A * A * A * A, - grand_child_of_rs2->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A, parent->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A * A, child_of_root->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A * A * A, grand_child_of_root->ScreenSpaceTransform()); + + EXPECT_TRANSFORM_EQ(A * A, render_surface1->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A * A * A, child_of_rs1->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A * A * A * A, + grand_child_of_rs1->ScreenSpaceTransform()); + + EXPECT_TRANSFORM_EQ(A * A * A, render_surface2->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A * A * A * A, child_of_rs2->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(A * A * A * A * A, + grand_child_of_rs2->ScreenSpaceTransform()); // Verify render surface transforms. // // Draw transform of render surface 1 is described with respect to root. - EXPECT_TRANSFORMATION_MATRIX_EQ( - A * A * S1, GetRenderSurface(render_surface1)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(A * A * S1, + GetRenderSurface(render_surface1)->draw_transform()); + EXPECT_TRANSFORM_EQ( A * A * S1, GetRenderSurface(render_surface1)->screen_space_transform()); // Draw transform of render surface 2 is described with respect to render // surface 1. - EXPECT_TRANSFORMATION_MATRIX_EQ( - SS1 * A * S2, GetRenderSurface(render_surface2)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ(SS1 * A * S2, + GetRenderSurface(render_surface2)->draw_transform()); + EXPECT_TRANSFORM_EQ( A * A * A * S2, GetRenderSurface(render_surface2)->screen_space_transform()); @@ -846,11 +827,10 @@ TEST_F(DrawPropertiesTest, TransformsForDegenerateIntermediateLayer) { ASSERT_TRUE(GetRenderSurface(child)); // This is the real test, the rest are sanity checks. - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(child)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), child->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - grand_child->DrawTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(child)->draw_transform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), child->DrawTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), grand_child->DrawTransform()); } TEST_F(DrawPropertiesTest, RenderSurfaceWithSublayerScale) { @@ -908,13 +888,13 @@ TEST_F(DrawPropertiesTest, TransformAboveRootLayer) { { SetDeviceTransform(translate); UpdateActiveTreeDrawProperties(device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ( - translate, root->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ( - translate, child->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(root)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(translate, child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(translate, + root->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(translate, + child->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(root)->draw_transform()); + EXPECT_TRANSFORM_EQ(translate, child->ScreenSpaceTransform()); EXPECT_EQ(gfx::Rect(50, 50, 100, 100), child->clip_rect()); } @@ -923,13 +903,11 @@ TEST_F(DrawPropertiesTest, TransformAboveRootLayer) { { SetDeviceTransform(scale); UpdateActiveTreeDrawProperties(device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ( - scale, root->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ( - scale, child->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(root)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(scale, child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(scale, root->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(scale, child->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(root)->draw_transform()); + EXPECT_TRANSFORM_EQ(scale, child->ScreenSpaceTransform()); EXPECT_EQ(gfx::Rect(0, 0, 200, 200), child->clip_rect()); } @@ -938,13 +916,12 @@ TEST_F(DrawPropertiesTest, TransformAboveRootLayer) { { SetDeviceTransform(rotate); UpdateActiveTreeDrawProperties(device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ( - rotate, root->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ( - rotate, child->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(root)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(rotate, child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(rotate, root->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(rotate, + child->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(root)->draw_transform()); + EXPECT_TRANSFORM_EQ(rotate, child->ScreenSpaceTransform()); EXPECT_EQ(gfx::Rect(-4, 0, 104, 104), child->clip_rect()); } @@ -955,13 +932,13 @@ TEST_F(DrawPropertiesTest, TransformAboveRootLayer) { { SetDeviceTransform(composite); UpdateActiveTreeDrawProperties(device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ( - composite, root->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ( - composite, child->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(root)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(composite, child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(composite, + root->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(composite, + child->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(root)->draw_transform()); + EXPECT_TRANSFORM_EQ(composite, child->ScreenSpaceTransform()); EXPECT_EQ(gfx::Rect(89, 103, 208, 208), child->clip_rect()); } @@ -973,16 +950,13 @@ TEST_F(DrawPropertiesTest, TransformAboveRootLayer) { UpdateActiveTreeDrawProperties(device_scale_factor); gfx::Transform device_scaled_translate = translate; device_scaled_translate.Scale(device_scale_factor, device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ( - device_scaled_translate, - root->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ( - device_scaled_translate, - child->draw_properties().target_space_transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(root)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(device_scaled_translate, - child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(device_scaled_translate, + root->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(device_scaled_translate, + child->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(root)->draw_transform()); + EXPECT_TRANSFORM_EQ(device_scaled_translate, child->ScreenSpaceTransform()); EXPECT_EQ(gfx::Rect(50, 50, 150, 150), child->clip_rect()); } } @@ -2475,8 +2449,8 @@ TEST_F(DrawPropertiesTestWithLayerTree, OcclusionBySiblingOfTarget) { CommitAndActivate(); - EXPECT_TRANSFORMATION_MATRIX_EQ( - GetRenderSurfaceImpl(surface)->draw_transform(), translate); + EXPECT_TRANSFORM_EQ(GetRenderSurfaceImpl(surface)->draw_transform(), + translate); // surface_sibling draws into the root render surface and occludes // surface_child's contents. Occlusion actual_occlusion = @@ -3124,10 +3098,8 @@ TEST_F(DrawPropertiesScalingTest, LayerTransformsInHighDPI) { // Verify root transforms gfx::Transform expected_root_transform; expected_root_transform.Scale(device_scale_factor, device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_root_transform, - root->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_root_transform, - root->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_root_transform, root->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_root_transform, root->DrawTransform()); // Verify results of transformed root rects gfx::RectF root_bounds(gfx::SizeF(root->bounds())); @@ -3139,21 +3111,17 @@ TEST_F(DrawPropertiesScalingTest, LayerTransformsInHighDPI) { gfx::RectF expected_root_draw_rect(gfx::SizeF(root->bounds())); expected_root_draw_rect.Scale(device_scale_factor); - EXPECT_FLOAT_RECT_EQ(expected_root_draw_rect, root_draw_rect); - EXPECT_FLOAT_RECT_EQ(expected_root_draw_rect, root_screen_space_rect); + EXPECT_RECTF_EQ(expected_root_draw_rect, root_draw_rect); + EXPECT_RECTF_EQ(expected_root_draw_rect, root_screen_space_rect); // Verify child and child2 transforms. They should match. gfx::Transform expected_child_transform; expected_child_transform.Scale(device_scale_factor, device_scale_factor); expected_child_transform.Translate(child->offset_to_transform_parent()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child2->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, - child2->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_child_transform, child->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_child_transform, child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_child_transform, child2->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_child_transform, child2->ScreenSpaceTransform()); // Verify results of transformed child and child2 rects. They should // match. @@ -3173,16 +3141,17 @@ TEST_F(DrawPropertiesScalingTest, LayerTransformsInHighDPI) { gfx::PointAtOffsetFromOrigin(child->offset_to_transform_parent()), gfx::SizeF(child->bounds())); expected_child_draw_rect.Scale(device_scale_factor); - EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_draw_rect); - EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_screen_space_rect); - EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child2_draw_rect); - EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child2_screen_space_rect); + EXPECT_RECTF_EQ(expected_child_draw_rect, child_draw_rect); + EXPECT_RECTF_EQ(expected_child_draw_rect, child_screen_space_rect); + EXPECT_RECTF_EQ(expected_child_draw_rect, child2_draw_rect); + EXPECT_RECTF_EQ(expected_child_draw_rect, child2_screen_space_rect); } // Verify draw and screen space transforms of layers in a surface. TEST_F(DrawPropertiesScalingTest, SurfaceLayerTransformsInHighDPI) { gfx::Transform perspective_matrix; perspective_matrix.ApplyPerspectiveDepth(2.0); + perspective_matrix.RotateAboutYAxis(15.0); gfx::Vector2dF perspective_surface_offset(2.f, 2.f); gfx::Transform scale_small_matrix; @@ -3251,28 +3220,28 @@ TEST_F(DrawPropertiesScalingTest, SurfaceLayerTransformsInHighDPI) { gfx::Transform expected_parent_draw_transform; expected_parent_draw_transform.Scale(contents_scale_factor, contents_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_draw_transform, - parent->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_parent_draw_transform, parent->DrawTransform()); // The scale for the perspective surface is not known, so it is rendered 1:1 // with the screen, and then scaled during drawing. gfx::Transform expected_perspective_surface_draw_transform; + expected_perspective_surface_draw_transform.Scale(contents_scale_factor, + contents_scale_factor); expected_perspective_surface_draw_transform.Translate( - contents_scale_factor * perspective_surface_offset.x(), - contents_scale_factor * perspective_surface_offset.y()); + perspective_surface_offset); expected_perspective_surface_draw_transform.PreconcatTransform( perspective_matrix); expected_perspective_surface_draw_transform.PreconcatTransform( scale_small_matrix); + expected_perspective_surface_draw_transform.Scale( + 1.0f / contents_scale_factor, 1.0f / contents_scale_factor); gfx::Transform expected_perspective_surface_layer_draw_transform; expected_perspective_surface_layer_draw_transform.Scale( contents_scale_factor, contents_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected_perspective_surface_draw_transform, - GetRenderSurface(perspective_surface)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected_perspective_surface_layer_draw_transform, - perspective_surface->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_perspective_surface_draw_transform, + GetRenderSurface(perspective_surface)->draw_transform()); + EXPECT_TRANSFORM_EQ(expected_perspective_surface_layer_draw_transform, + perspective_surface->DrawTransform()); } TEST_F(DrawPropertiesScalingTest, SmallIdealScale) { @@ -3308,7 +3277,7 @@ TEST_F(DrawPropertiesScalingTest, SmallIdealScale) { CopyProperties(parent, child_scale); CreateTransformNode(child_scale).local = child_scale_matrix; - LayerTreeImpl::ViewportPropertyIds viewport_property_ids; + ViewportPropertyIds viewport_property_ids; viewport_property_ids.page_scale_transform = page_scale->transform_tree_index(); host_impl()->active_tree()->SetViewportPropertyIds(viewport_property_ids); @@ -3399,30 +3368,27 @@ TEST_F(DrawPropertiesTest, RenderSurfaceTransformsInHighDPI) { gfx::Transform expected_parent_transform; expected_parent_transform.Scale(device_scale_factor, device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_transform, - parent->ScreenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_parent_transform, - parent->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_parent_transform, + parent->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_parent_transform, parent->DrawTransform()); gfx::Transform expected_draw_transform; expected_draw_transform.Scale(device_scale_factor, device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_draw_transform, - child->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_draw_transform, child->DrawTransform()); gfx::Transform expected_screen_space_transform; expected_screen_space_transform.Scale(device_scale_factor, device_scale_factor); expected_screen_space_transform.Translate(child_offset); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_screen_space_transform, - child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_screen_space_transform, + child->ScreenSpaceTransform()); gfx::Transform expected_duplicate_child_draw_transform = child->DrawTransform(); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_duplicate_child_draw_transform, - duplicate_child_non_owner->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ( - child->ScreenSpaceTransform(), - duplicate_child_non_owner->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_duplicate_child_draw_transform, + duplicate_child_non_owner->DrawTransform()); + EXPECT_TRANSFORM_EQ(child->ScreenSpaceTransform(), + duplicate_child_non_owner->ScreenSpaceTransform()); EXPECT_EQ(child->visible_drawable_content_rect(), duplicate_child_non_owner->visible_drawable_content_rect()); EXPECT_EQ(child->bounds(), duplicate_child_non_owner->bounds()); @@ -3431,21 +3397,20 @@ TEST_F(DrawPropertiesTest, RenderSurfaceTransformsInHighDPI) { expected_render_surface_draw_transform.Translate( device_scale_factor * child_offset.x(), device_scale_factor * child_offset.y()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_render_surface_draw_transform, - GetRenderSurface(child)->draw_transform()); + EXPECT_TRANSFORM_EQ(expected_render_surface_draw_transform, + GetRenderSurface(child)->draw_transform()); gfx::Transform expected_surface_draw_transform; expected_surface_draw_transform.Translate(device_scale_factor * 2.f, device_scale_factor * 2.f); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform, - GetRenderSurface(child)->draw_transform()); + EXPECT_TRANSFORM_EQ(expected_surface_draw_transform, + GetRenderSurface(child)->draw_transform()); gfx::Transform expected_surface_screen_space_transform; expected_surface_screen_space_transform.Translate(device_scale_factor * 2.f, device_scale_factor * 2.f); - EXPECT_TRANSFORMATION_MATRIX_EQ( - expected_surface_screen_space_transform, - GetRenderSurface(child)->screen_space_transform()); + EXPECT_TRANSFORM_EQ(expected_surface_screen_space_transform, + GetRenderSurface(child)->screen_space_transform()); } TEST_F(DrawPropertiesTest, @@ -3469,12 +3434,12 @@ TEST_F(DrawPropertiesTest, // render surface (it needs one because of force_render_surface). EXPECT_EQ(2u, GetRenderSurfaceList().size()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(child)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - GetRenderSurface(child)->draw_transform()); - EXPECT_TRANSFORMATION_MATRIX_EQ( - gfx::Transform(), GetRenderSurface(child)->screen_space_transform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(child)->draw_transform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(child)->draw_transform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), + GetRenderSurface(child)->screen_space_transform()); } // Needs layer tree mode: mask layer. Not using impl-side PropertyTreeBuilder. @@ -4213,7 +4178,7 @@ TEST_F(DrawPropertiesTest, ClipParentScrolledInterveningLayer) { CopyProperties(render_surface2, clip_child); clip_child->SetClipTreeIndex(clip_parent->clip_tree_index()); - SetScrollOffset(intervening, gfx::Vector2dF(3, 3)); + SetScrollOffset(intervening, gfx::PointF(3, 3)); UpdateActiveTreeDrawProperties(); EXPECT_TRUE(GetRenderSurface(root)); @@ -4501,7 +4466,7 @@ TEST_F(DrawPropertiesTest, ScrollChildAndScrollParentDifferentTargets) { EXPECT_EQ(scroll_child->clip_rect(), gfx::Rect(15, 15, 75, 75)); gfx::Transform scale; scale.Scale(device_scale_factor, device_scale_factor); - EXPECT_TRANSFORMATION_MATRIX_EQ(scroll_child->DrawTransform(), scale); + EXPECT_TRANSFORM_EQ(scroll_child->DrawTransform(), scale); } TEST_F(DrawPropertiesTest, SingularTransformSubtreesDoNotDraw) { @@ -4579,7 +4544,7 @@ TEST_F(DrawPropertiesTest, ScrollSnapping) { SetScrollOffsetDelta(scroller, scroll_delta); UpdateActiveTreeDrawProperties(); - EXPECT_VECTOR_EQ( + EXPECT_VECTOR2DF_EQ( scroller->draw_properties().screen_space_transform.To2dTranslation(), container_offset - scroll_delta); } @@ -4591,7 +4556,7 @@ TEST_F(DrawPropertiesTest, ScrollSnapping) { UpdateActiveTreeDrawProperties(); gfx::Vector2dF rounded_scroll_delta(4.f, 8.f); - EXPECT_VECTOR_EQ( + EXPECT_VECTOR2DF_EQ( scroller->draw_properties().screen_space_transform.To2dTranslation(), container_offset - rounded_scroll_delta); } @@ -4703,8 +4668,8 @@ TEST_F(DrawPropertiesTest, ScrollSnappingWithScrollChild) { gfx::Transform expected_scroll_child_screen_space_transform; expected_scroll_child_screen_space_transform.Translate(-5.3f, -9.3f); expected_scroll_child_screen_space_transform.RotateAboutYAxis(30); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_scroll_child_screen_space_transform, - scroll_child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected_scroll_child_screen_space_transform, + scroll_child->ScreenSpaceTransform()); } class DrawPropertiesStickyPositionTest : public DrawPropertiesTest { @@ -4772,9 +4737,9 @@ class DrawPropertiesStickyPositionTest : public DrawPropertiesTest { scoped_refptr<Layer> container_; scoped_refptr<Layer> scroller_; scoped_refptr<Layer> sticky_pos_; - LayerImpl* root_impl_; - LayerImpl* scroller_impl_; - LayerImpl* sticky_pos_impl_; + raw_ptr<LayerImpl> root_impl_; + raw_ptr<LayerImpl> scroller_impl_; + raw_ptr<LayerImpl> sticky_pos_impl_; }; TEST_F(DrawPropertiesStickyPositionTest, StickyPositionTop) { @@ -5157,7 +5122,7 @@ TEST_F(DrawPropertiesStickyPositionTest, StickyPositionMainThreadUpdates) { sticky_pos_impl_->ScreenSpaceTransform().To2dTranslation()); // Now the main thread commits the new position of the sticky element. - SetScrollOffset(scroller_.get(), gfx::Vector2dF(15, 15)); + SetScrollOffset(scroller_.get(), gfx::PointF(15, 15)); // Shift the layer by -offset_for_position_sticky. SetPostTranslation(sticky_pos_.get(), gfx::PointF(10, 25) - gfx::PointF(0, 5)); @@ -5228,7 +5193,7 @@ TEST_F(DrawPropertiesStickyPositionTest, StickyPositionCompositedContainer) { sticky_pos_impl_->ScreenSpaceTransform().To2dTranslation()); // Now the main thread commits the new position of the sticky element. - SetScrollOffset(scroller_.get(), gfx::Vector2dF(0, 25)); + SetScrollOffset(scroller_.get(), gfx::PointF(0, 25)); // Shift the layer by -offset_for_position_sticky. SetPostTranslation(sticky_pos_.get(), gfx::PointF(0, 15) - gfx::PointF(0, 5) + @@ -6014,7 +5979,7 @@ TEST_F(DrawPropertiesTest, DrawPropertyScales) { CopyProperties(page_scale.get(), child2.get()); CreateTransformNode(child2.get()).local = scale_transform_child2; - LayerTreeHost::ViewportPropertyIds viewport_property_ids; + ViewportPropertyIds viewport_property_ids; viewport_property_ids.page_scale_transform = page_scale->transform_tree_index(); host()->RegisterViewportPropertyIds(viewport_property_ids); @@ -6401,7 +6366,7 @@ TEST_F(DrawPropertiesTest, UpdateScrollChildPosition) { UpdateActiveTreeDrawProperties(); EXPECT_EQ(gfx::Rect(25, 25), scroll_child->visible_layer_rect()); - SetScrollOffset(scroll_parent, gfx::Vector2dF(0.f, 10.f)); + SetScrollOffset(scroll_parent, gfx::PointF(0.f, 10.f)); UpdateActiveTreeDrawProperties(); EXPECT_EQ(gfx::Rect(0, 5, 25, 25), scroll_child->visible_layer_rect()); @@ -7165,8 +7130,7 @@ TEST_F(DrawPropertiesTest, LayerWithInputHandlerAndZeroOpacity) { CreateEffectNode(test_layer).opacity = 0.f; UpdateActiveTreeDrawProperties(); - EXPECT_TRANSFORMATION_MATRIX_EQ(translation, - test_layer->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(translation, test_layer->ScreenSpaceTransform()); } TEST_F(DrawPropertiesTest, ClipParentDrawsIntoScaledRootSurface) { @@ -7360,22 +7324,19 @@ TEST_F(DrawPropertiesTestWithLayerTree, MaskLayerDrawProperties) { EXPECT_FALSE(ImplOf(child)->contributes_to_drawn_render_surface()); EXPECT_FALSE(ImplOf(mask)->contributes_to_drawn_render_surface()); EXPECT_EQ(gfx::Rect(), ImplOf(mask)->visible_layer_rect()); - EXPECT_TRANSFORMATION_MATRIX_EQ(transform, - ImplOf(mask)->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(transform, ImplOf(mask)->ScreenSpaceTransform()); // Make the child's render surface have contributing content. child->SetOpacity(1.f); CommitAndActivate(); EXPECT_TRUE(ImplOf(mask)->contributes_to_drawn_render_surface()); EXPECT_EQ(gfx::Rect(30, 30), ImplOf(mask)->visible_layer_rect()); - EXPECT_TRANSFORMATION_MATRIX_EQ(transform, - ImplOf(mask)->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(transform, ImplOf(mask)->ScreenSpaceTransform()); transform.Translate(10, 10); child->SetTransform(transform); CommitAndActivate(); - EXPECT_TRANSFORMATION_MATRIX_EQ(transform, - ImplOf(mask)->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(transform, ImplOf(mask)->ScreenSpaceTransform()); EXPECT_EQ(gfx::Rect(20, 20), ImplOf(mask)->visible_layer_rect()); // For now SetIsDrawable of masked layer doesn't affect draw properties of @@ -7467,7 +7428,7 @@ TEST_F(DrawPropertiesTest, NoisyTransform) { expected.matrix().setDouble(0, 2, 6.12323e-17); expected.matrix().setDouble(2, 0, -1); expected.matrix().setDouble(2, 2, 6.12323e-17); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(expected, child->ScreenSpaceTransform()); } TEST_F(DrawPropertiesTest, LargeTransformTest) { diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index 752d7d20116..2b8ad609327 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -1192,10 +1192,12 @@ void UpdateElasticOverscroll( // On other platforms, we modify the translation offset to match the // overscroll amount. - if (overscroll_elasticity_transform_node->scroll_offset == elastic_overscroll) + gfx::PointF overscroll_offset = + gfx::PointAtOffsetFromOrigin(elastic_overscroll); + if (overscroll_elasticity_transform_node->scroll_offset == overscroll_offset) return; - overscroll_elasticity_transform_node->scroll_offset = elastic_overscroll; + overscroll_elasticity_transform_node->scroll_offset = overscroll_offset; overscroll_elasticity_transform_node->needs_local_transform_update = true; property_trees->transform_tree.set_needs_update(true); diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index 19b5bbfe2e3..1d530fe1515 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -9,6 +9,7 @@ #include "cc/document_transition/document_transition_shared_element_id.h" #include "cc/paint/element_id.h" #include "cc/paint/filter_operations.h" +#include "components/viz/common/shared_element_resource_id.h" #include "components/viz/common/surfaces/subtree_capture_id.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkBlendMode.h" @@ -168,6 +169,10 @@ struct CC_EXPORT EffectNode { // Represents a shared element id for the document transition API. DocumentTransitionSharedElementId document_transition_shared_element_id; + // Represents a resource id for a resource cached or generated in the Viz + // process. + viz::SharedElementResourceId shared_element_resource_id; + bool HasRenderSurface() const { return render_surface_reason != RenderSurfaceReason::kNone; } diff --git a/chromium/cc/trees/frame_rate_estimator.h b/chromium/cc/trees/frame_rate_estimator.h index 378a21784e6..750c42d800d 100644 --- a/chromium/cc/trees/frame_rate_estimator.h +++ b/chromium/cc/trees/frame_rate_estimator.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_FRAME_RATE_ESTIMATOR_H_ #define CC_TREES_FRAME_RATE_ESTIMATOR_H_ -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "cc/base/delayed_unique_notifier.h" #include "cc/cc_export.h" diff --git a/chromium/cc/trees/image_animation_controller.h b/chromium/cc/trees/image_animation_controller.h index 361f1fbc512..63cfcc8b983 100644 --- a/chromium/cc/trees/image_animation_controller.h +++ b/chromium/cc/trees/image_animation_controller.h @@ -11,6 +11,7 @@ #include "base/cancelable_callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -115,6 +116,7 @@ class CC_EXPORT ImageAnimationController { // Notifies the beginning of an impl frame with the given |args|. void WillBeginImplFrame(const viz::BeginFrameArgs& args); + bool did_navigate() const { return did_navigate_; } void set_did_navigate() { did_navigate_ = true; } const base::flat_set<AnimationDriver*>& GetDriversForTesting( @@ -278,8 +280,8 @@ class CC_EXPORT ImageAnimationController { void RequestBeginFrame(); void RequestInvalidation(); - base::SingleThreadTaskRunner* task_runner_; - Client* const client_; + raw_ptr<base::SingleThreadTaskRunner> task_runner_; + const raw_ptr<Client> client_; NowCallback now_callback_for_testing_; InvalidationState state_ = InvalidationState::kIdle; diff --git a/chromium/cc/trees/image_animation_controller_unittest.cc b/chromium/cc/trees/image_animation_controller_unittest.cc index c6863af7305..627880884fa 100644 --- a/chromium/cc/trees/image_animation_controller_unittest.cc +++ b/chromium/cc/trees/image_animation_controller_unittest.cc @@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/test/gtest_util.h" #include "base/threading/thread_task_runner_handle.h" @@ -67,7 +68,7 @@ class DelayTrackingTaskRunner : public base::SingleThreadTaskRunner { ~DelayTrackingTaskRunner() override = default; absl::optional<base::TimeDelta> last_delay_; - base::SingleThreadTaskRunner* task_runner_; + raw_ptr<base::SingleThreadTaskRunner> task_runner_; }; class ImageAnimationControllerTest : public testing::Test, diff --git a/chromium/cc/trees/latency_info_swap_promise.cc b/chromium/cc/trees/latency_info_swap_promise.cc index 183e912e3b1..a6110c4f873 100644 --- a/chromium/cc/trees/latency_info_swap_promise.cc +++ b/chromium/cc/trees/latency_info_swap_promise.cc @@ -34,7 +34,7 @@ SwapPromise::DidNotSwapAction LatencyInfoSwapPromise::DidNotSwap( return DidNotSwapAction::BREAK_PROMISE; } -int64_t LatencyInfoSwapPromise::TraceId() const { +int64_t LatencyInfoSwapPromise::GetTraceId() const { return latency_.trace_id(); } @@ -47,11 +47,11 @@ void LatencyInfoSwapPromise::OnCommit() { [this](perfetto::EventContext ctx) { ChromeLatencyInfo* latency_info = ctx.event()->set_chrome_latency_info(); - latency_info->set_trace_id(TraceId()); + latency_info->set_trace_id(GetTraceId()); latency_info->set_step( ChromeLatencyInfo::STEP_HANDLE_INPUT_EVENT_MAIN_COMMIT); tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT, - TraceId()); + GetTraceId()); }); } diff --git a/chromium/cc/trees/latency_info_swap_promise.h b/chromium/cc/trees/latency_info_swap_promise.h index 5891dfeceba..23e07e823dd 100644 --- a/chromium/cc/trees/latency_info_swap_promise.h +++ b/chromium/cc/trees/latency_info_swap_promise.h @@ -30,7 +30,7 @@ class CC_EXPORT LatencyInfoSwapPromise : public SwapPromise { DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override; void OnCommit() override; - int64_t TraceId() const override; + int64_t GetTraceId() const override; private: ui::LatencyInfo latency_; diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.cc b/chromium/cc/trees/latency_info_swap_promise_monitor.cc index 0cb8e0b2731..151c6f24c0a 100644 --- a/chromium/cc/trees/latency_info_swap_promise_monitor.cc +++ b/chromium/cc/trees/latency_info_swap_promise_monitor.cc @@ -8,7 +8,6 @@ #include <memory> #include <utility> -#include "base/threading/platform_thread.h" #include "cc/trees/latency_info_swap_promise.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" @@ -34,16 +33,33 @@ namespace cc { LatencyInfoSwapPromiseMonitor::LatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency, SwapPromiseManager* swap_promise_manager) - : SwapPromiseMonitor(swap_promise_manager), latency_(latency) {} + : latency_(latency), swap_promise_manager_(swap_promise_manager) { + DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); + DCHECK(swap_promise_manager); + swap_promise_manager_->InsertLatencyInfoSwapPromiseMonitor(this); +} LatencyInfoSwapPromiseMonitor::LatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency, LayerTreeHostImpl* host_impl) - : SwapPromiseMonitor(host_impl), latency_(latency) {} + : latency_(latency), host_impl_(host_impl) { + DCHECK_CALLED_ON_VALID_SEQUENCE(impl_sequence_checker_); + DCHECK(host_impl); + host_impl_->InsertLatencyInfoSwapPromiseMonitor(this); +} -LatencyInfoSwapPromiseMonitor::~LatencyInfoSwapPromiseMonitor() = default; +LatencyInfoSwapPromiseMonitor::~LatencyInfoSwapPromiseMonitor() { + if (swap_promise_manager_) { + DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); + swap_promise_manager_->RemoveLatencyInfoSwapPromiseMonitor(this); + } else if (host_impl_) { + DCHECK_CALLED_ON_VALID_SEQUENCE(impl_sequence_checker_); + host_impl_->RemoveLatencyInfoSwapPromiseMonitor(this); + } +} void LatencyInfoSwapPromiseMonitor::OnSetNeedsCommitOnMain() { + DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); if (AddRenderingScheduledComponent(latency_, true /* on_main */)) { std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(*latency_)); @@ -52,6 +68,7 @@ void LatencyInfoSwapPromiseMonitor::OnSetNeedsCommitOnMain() { } void LatencyInfoSwapPromiseMonitor::OnSetNeedsRedrawOnImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(impl_sequence_checker_); if (AddRenderingScheduledComponent(latency_, false /* on_main */)) { std::unique_ptr<SwapPromise> swap_promise( new LatencyInfoSwapPromise(*latency_)); diff --git a/chromium/cc/trees/latency_info_swap_promise_monitor.h b/chromium/cc/trees/latency_info_swap_promise_monitor.h index a9ffbf0c01c..aacde443a3a 100644 --- a/chromium/cc/trees/latency_info_swap_promise_monitor.h +++ b/chromium/cc/trees/latency_info_swap_promise_monitor.h @@ -5,31 +5,62 @@ #ifndef CC_TREES_LATENCY_INFO_SWAP_PROMISE_MONITOR_H_ #define CC_TREES_LATENCY_INFO_SWAP_PROMISE_MONITOR_H_ -#include "base/compiler_specific.h" -#include "cc/trees/swap_promise_monitor.h" +#include "base/memory/raw_ptr.h" +#include "base/sequence_checker.h" +#include "cc/cc_export.h" namespace ui { class LatencyInfo; -} // namespace ui +} namespace cc { -// A LatencyInfoSwapPromiseMonitor queues a LatencyInfoSwapPromise into -// LayerTreeHost or LayerTreeHostImpl if there is compositor state change -// while it is being mointored. -class CC_EXPORT LatencyInfoSwapPromiseMonitor : public SwapPromiseMonitor { +class LayerTreeHostImpl; +class SwapPromiseManager; + +// A `LatencyInfoSwapPromiseMonitor` is used to monitor compositor state change +// that should be associated with a `LatencyInfoSwapPromise`, e.g. +// `SetNeedsCommit()` is called on the main thread or `SetNeedsRedraw()` is +// called on the compositor thread. +// +// Creating a `LatencyInfoSwapPromiseMonitor` will insert it into a +// `SwapPromiseManager` or `LayerTreeHostImpl`, depending on the constructor +// used. +// +// Notification of compositor state change will be sent through +// `OnSetNeedsCommitOnMain()` or `OnSetNeedsRedrawOnImpl()`. Note that multiple +// notifications of the same type to the same monitor will only queue one +// `LatencyInfoSwapPromise`. +// +// When `LatencyInfoSwapPromiseMonitor` is destroyed, it will unregister itself +// from `SwapPromiseManager` or `LayerTreeHostImpl`. +class CC_EXPORT LatencyInfoSwapPromiseMonitor { public: + // Constructor for when the monitor lives on the main thread. LatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency, SwapPromiseManager* swap_promise_manager); + + // Constructor for when the monitor lives on the compositor thread. LatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency, LayerTreeHostImpl* host_impl); - ~LatencyInfoSwapPromiseMonitor() override; - void OnSetNeedsCommitOnMain() override; - void OnSetNeedsRedrawOnImpl() override; + LatencyInfoSwapPromiseMonitor(const LatencyInfoSwapPromiseMonitor&) = delete; + LatencyInfoSwapPromiseMonitor& operator=( + const LatencyInfoSwapPromiseMonitor&) = delete; + + virtual ~LatencyInfoSwapPromiseMonitor(); + + // Virtual so that tests can mock them. + virtual void OnSetNeedsCommitOnMain(); + virtual void OnSetNeedsRedrawOnImpl(); private: - ui::LatencyInfo* latency_; + const raw_ptr<ui::LatencyInfo> latency_; + const raw_ptr<SwapPromiseManager> swap_promise_manager_ = nullptr; + const raw_ptr<LayerTreeHostImpl> host_impl_ = nullptr; + + SEQUENCE_CHECKER(main_sequence_checker_); + SEQUENCE_CHECKER(impl_sequence_checker_); }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h index d83c534ab31..ba1286cb85d 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.h +++ b/chromium/cc/trees/layer_tree_frame_sink.h @@ -8,10 +8,11 @@ #include <deque> #include <memory> +#include "base/memory/raw_ptr.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "cc/cc_export.h" #include "cc/scheduler/scheduler.h" @@ -140,12 +141,12 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, // viz::ContextLostObserver: void OnContextLost() override; - LayerTreeFrameSinkClient* client_ = nullptr; + raw_ptr<LayerTreeFrameSinkClient> client_ = nullptr; scoped_refptr<viz::ContextProvider> context_provider_; scoped_refptr<viz::RasterContextProvider> worker_context_provider_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; + raw_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_; std::unique_ptr<ContextLostForwarder> worker_context_lost_forwarder_; diff --git a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc index 6efdbcb6a47..cce1ce8d505 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc @@ -5,7 +5,7 @@ #include "cc/trees/layer_tree_frame_sink.h" #include "base/memory/read_only_shared_memory_region.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/test/test_simple_task_runner.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" #include "components/viz/common/quads/compositor_frame.h" diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 94e21251dec..8a286f5ce38 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -24,9 +24,9 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_math.h" -#include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" @@ -50,6 +50,7 @@ #include "cc/resources/ui_resource_manager.h" #include "cc/tiles/raster_dark_mode_filter.h" #include "cc/trees/clip_node.h" +#include "cc/trees/commit_state.h" #include "cc/trees/compositor_commit_data.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/effect_node.h" @@ -142,38 +143,42 @@ LayerTreeHost::LayerTreeHost(InitParams params, CompositorMode mode) client_(params.client), scheduling_client_(params.scheduling_client), rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()), + pending_commit_state_(std::make_unique<CommitState>()), + thread_unsafe_commit_state_(params.mutator_host), settings_(*params.settings), - debug_state_(settings_.initial_debug_state), id_(s_layer_tree_host_sequence_number.GetNext() + 1), task_graph_runner_(params.task_graph_runner), - main_thread_pipeline_(params.main_thread_pipeline), - compositor_thread_pipeline_(params.compositor_thread_pipeline), - event_listener_properties_(), 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_); - mutator_host_->SetMutatorHostClient(this); + pending_commit_state_->needs_gpu_rasterization_histogram = + (mode == CompositorMode::THREADED); + pending_commit_state_->needs_full_tree_sync = true; + pending_commit_state_->debug_state = settings_.initial_debug_state; + + params.mutator_host->SetMutatorHostClient(this); rendering_stats_instrumentation_->set_record_rendering_stats( - debug_state_.RecordRenderingStats()); + pending_commit_state_->debug_state.RecordRenderingStats()); } bool LayerTreeHost::IsMobileOptimized() const { gfx::SizeF scrollable_viewport_size; - auto* inner_node = - property_trees()->scroll_tree.Node(viewport_property_ids_.inner_scroll); + auto* inner_node = property_trees()->scroll_tree.Node( + pending_commit_state()->viewport_property_ids.inner_scroll); if (!inner_node) scrollable_viewport_size = gfx::SizeF(); else scrollable_viewport_size = gfx::ScaleSize( gfx::SizeF(inner_node->container_bounds), - 1.0f / (external_page_scale_factor_ * page_scale_factor())); + 1.0f / (pending_commit_state()->external_page_scale_factor * + page_scale_factor())); gfx::SizeF scrollable_size; - auto* scroll_node = - property_trees()->scroll_tree.Node(viewport_property_ids_.outer_scroll); + auto* scroll_node = property_trees()->scroll_tree.Node( + pending_commit_state()->viewport_property_ids.outer_scroll); if (!scroll_node) { DCHECK(!inner_node); scrollable_size = gfx::SizeF(); @@ -186,7 +191,8 @@ bool LayerTreeHost::IsMobileOptimized() const { return util::IsMobileOptimized( min_page_scale_factor(), max_page_scale_factor(), page_scale_factor(), - scrollable_viewport_size, scrollable_size, is_viewport_mobile_optimized_); + scrollable_viewport_size, scrollable_size, + pending_commit_state()->is_viewport_mobile_optimized); } void LayerTreeHost::InitializeThreaded( @@ -239,18 +245,19 @@ LayerTreeHost::~LayerTreeHost() { // Track when we're inside a main frame to see if compositor is being // destroyed midway which causes a crash. crbug.com/895883 CHECK(!inside_main_frame_); + DCHECK(!in_commit()); TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost"); // Clear any references into the LayerTreeHost. - mutator_host_->SetMutatorHostClient(nullptr); + mutator_host()->SetMutatorHostClient(nullptr); - if (root_layer_) { - root_layer_->SetLayerTreeHost(nullptr); + if (root_layer()) { + root_layer()->SetLayerTreeHost(nullptr); // The root layer must be destroyed before the layer tree. We've made a // contract with our animation controllers that the animation_host will // outlive them, and we must make good. - root_layer_ = nullptr; + thread_unsafe_commit_state().root_layer = nullptr; } // Fail any pending image decodes. @@ -272,14 +279,14 @@ int LayerTreeHost::GetId() const { int LayerTreeHost::SourceFrameNumber() const { DCHECK(task_runner_provider_->IsMainThread()); - return source_frame_number_; + return pending_commit_state()->source_frame_number; } -UIResourceManager* LayerTreeHost::GetUIResourceManager() const { +UIResourceManager* LayerTreeHost::GetUIResourceManager() { return ui_resource_manager_.get(); } -TaskRunnerProvider* LayerTreeHost::GetTaskRunnerProvider() const { +TaskRunnerProvider* LayerTreeHost::GetTaskRunnerProvider() { return task_runner_provider_.get(); } @@ -332,150 +339,16 @@ void LayerTreeHost::BeginMainFrame(const viz::BeginFrameArgs& args) { } const LayerTreeDebugState& LayerTreeHost::GetDebugState() const { - return debug_state_; + return pending_commit_state()->debug_state; } -void LayerTreeHost::RequestMainFrameUpdate(bool report_cc_metrics) { +void LayerTreeHost::RequestMainFrameUpdate(bool report_metrics) { client_->UpdateLayerTreeHost(); - if (report_cc_metrics) - begin_main_frame_metrics_ = client_->GetBeginMainFrameMetrics(); + if (report_metrics) + pending_commit_state()->begin_main_frame_metrics = + client_->GetBeginMainFrameMetrics(); else - begin_main_frame_metrics_.reset(); -} - -// This function commits the LayerTreeHost to an impl tree. When modifying -// this function, keep in mind that the function *runs* on the impl thread! Any -// code that is logically a main thread operation, e.g. deletion of a Layer, -// should be delayed until the LayerTreeHost::CommitComplete, which will run -// after the commit, but on the main thread. -void LayerTreeHost::FinishCommitOnImplThread( - LayerTreeHostImpl* host_impl, - std::vector<std::unique_ptr<SwapPromise>> swap_promises) { - DCHECK(task_runner_provider_->IsImplThread()); - - TRACE_EVENT0("cc,benchmark", "LayerTreeHost::FinishCommitOnImplThread"); - - LayerTreeImpl* sync_tree = host_impl->sync_tree(); - sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync); - - if (next_commit_forces_redraw_) { - sync_tree->ForceRedrawNextActivation(); - next_commit_forces_redraw_ = false; - } - if (next_commit_forces_recalculate_raster_scales_) { - sync_tree->ForceRecalculateRasterScales(); - next_commit_forces_recalculate_raster_scales_ = false; - } - - if (!pending_presentation_time_callbacks_.empty()) { - sync_tree->AddPresentationCallbacks( - std::move(pending_presentation_time_callbacks_)); - pending_presentation_time_callbacks_.clear(); - } - - if (needs_full_tree_sync_) - TreeSynchronizer::SynchronizeTrees(root_layer(), sync_tree); - - if (clear_caches_on_next_commit_) { - clear_caches_on_next_commit_ = false; - proxy_->ClearHistory(); - host_impl->ClearCaches(); - } - - { - TRACE_EVENT0("cc", "LayerTreeHost::PushProperties"); - - PushPropertyTreesTo(sync_tree); - sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedPropertyTrees); - - PushSurfaceRangesTo(sync_tree); - TreeSynchronizer::PushLayerProperties(this, sync_tree); - sync_tree->lifecycle().AdvanceTo( - LayerTreeLifecycle::kSyncedLayerProperties); - - PushLayerTreePropertiesTo(sync_tree); - PushLayerTreeHostPropertiesTo(host_impl); - - sync_tree->PassSwapPromises(std::move(swap_promises)); - sync_tree->AppendEventsMetricsFromMainThread( - events_metrics_manager_.TakeSavedEventsMetrics()); - - sync_tree->set_ui_resource_request_queue( - ui_resource_manager_->TakeUIResourcesRequests()); - - // This must happen after synchronizing property trees and after pushing - // properties, which updates the clobber_active_value flag. - // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. - sync_tree->property_trees()->scroll_tree.PushScrollUpdatesFromMainThread( - property_trees(), sync_tree, settings_.commit_fractional_scroll_deltas); - - // This must happen after synchronizing property trees and after push - // properties, which updates property tree indices, but before animation - // host pushes properties as animation host push properties can change - // KeyframeModel::InEffect and we want the old InEffect value for updating - // property tree scrolling and animation. - // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. - sync_tree->UpdatePropertyTreeAnimationFromMainThread(); - - TRACE_EVENT0("cc", "LayerTreeHost::AnimationHost::PushProperties"); - DCHECK(host_impl->mutator_host()); - mutator_host_->PushPropertiesTo(host_impl->mutator_host()); - MoveChangeTrackingToLayers(sync_tree); - - // Updating elements affects whether animations are in effect based on their - // properties so run after pushing updated animation properties. - host_impl->UpdateElements(ElementListType::PENDING); - - sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kNotSyncing); - } - - // Transfer image decode requests to the impl thread. - for (auto& request : queued_image_decodes_) { - int next_id = s_image_decode_sequence_number.GetNext(); - pending_image_decodes_[next_id] = std::move(request.second); - host_impl->QueueImageDecode(next_id, std::move(request.first)); - } - queued_image_decodes_.clear(); - - micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); - property_trees_.ResetAllChangeTracking(); - - SetImplCommitFinishTime(base::TimeTicks::Now()); - - // Dump property trees and layers if run with: - // --vmodule=layer_tree_host=3 - if (VLOG_IS_ON(3)) { - const char* client_name = GetClientNameForMetrics(); - if (!client_name) - client_name = "<unknown client>"; - VLOG(3) << "After finishing (" << client_name - << ") commit on impl, the sync tree:" - << "\nproperty_trees:\n" - << sync_tree->property_trees()->ToString() << "\n" - << "cc::LayerImpls:\n" - << sync_tree->LayerListAsJson(); - } -} - -void LayerTreeHost::MoveChangeTrackingToLayers(LayerTreeImpl* tree_impl) { - // This is only true for single-thread compositing (i.e. not via Blink). - bool property_trees_changed_on_active_tree = - tree_impl->IsActiveTree() && tree_impl->property_trees()->changed; - - if (property_trees_changed_on_active_tree) { - // Property trees may store damage status. We preserve the sync tree damage - // status by pushing the damage status from sync tree property trees to main - // thread property trees or by moving it onto the layers. - if (root_layer_) { - if (property_trees_.sequence_number == - tree_impl->property_trees()->sequence_number) - tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_); - else - tree_impl->MoveChangeTrackingToLayers(); - } - } else { - tree_impl->MoveChangeTrackingToLayers(); - } + pending_commit_state()->begin_main_frame_metrics.reset(); } void LayerTreeHost::ImageDecodesFinished( @@ -489,31 +362,47 @@ void LayerTreeHost::ImageDecodesFinished( } } -void LayerTreeHost::PushPropertyTreesTo(LayerTreeImpl* tree_impl) { - bool property_trees_changed_on_active_tree = - tree_impl->IsActiveTree() && tree_impl->property_trees()->changed; - // Property trees may store damage status. We preserve the sync tree damage - // status by pushing the damage status from sync tree property trees to main - // thread property trees or by moving it onto the layers. - if (root_layer_ && property_trees_changed_on_active_tree) { - if (property_trees_.sequence_number == - tree_impl->property_trees()->sequence_number) - tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_); - else - tree_impl->MoveChangeTrackingToLayers(); - } - - tree_impl->SetPropertyTrees(&property_trees_); +void LayerTreeHost::SetNextCommitWaitsForActivation() { + DCHECK(task_runner_provider_->IsMainThread()); + pending_commit_state()->commit_waits_for_activation = true; } -void LayerTreeHost::WillCommit(std::unique_ptr<CompletionEvent> completion) { +std::unique_ptr<CommitState> LayerTreeHost::WillCommit( + std::unique_ptr<CompletionEvent> completion, + bool has_updates) { DCHECK(!commit_completion_event_); commit_completion_event_ = std::move(completion); + std::unique_ptr<CommitState> result; + if (has_updates) + result = ActivateCommitState(); swap_promise_manager_.WillCommit(); - client_->WillCommit(); + client_->WillCommit(has_updates ? *result : *pending_commit_state()); + pending_commit_state()->source_frame_number++; + return result; +} + +std::unique_ptr<CommitState> LayerTreeHost::ActivateCommitState() { + DCHECK(pending_commit_state()); + + // Pull state not stored directly on LayerTreeHost + pending_commit_state()->event_metrics = + events_metrics_manager_.TakeSavedEventsMetrics(); + pending_commit_state()->swap_promises = + GetSwapPromiseManager()->TakeSwapPromises(); + pending_commit_state()->ui_resource_request_queue = + ui_resource_manager_->TakeUIResourcesRequests(); + pending_commit_state()->ui_resource_sizes = + ui_resource_manager_->GetUIResourceSizes(); + pending_commit_state()->benchmarks = + micro_benchmark_controller_.CreateImplBenchmarks(); + + auto active_commit_state = std::move(pending_commit_state_); + pending_commit_state_ = std::make_unique<CommitState>(*active_commit_state); + return active_commit_state; } void LayerTreeHost::WaitForCommitCompletion() { + DCHECK(task_runner_provider_->IsMainThread()); if (commit_completion_event_) { commit_completion_event_->Wait(); commit_completion_event_ = nullptr; @@ -521,21 +410,20 @@ void LayerTreeHost::WaitForCommitCompletion() { } void LayerTreeHost::UpdateDeferMainFrameUpdateInternal() { - proxy_->SetDeferMainFrameUpdate(defer_main_frame_update_count_ > 0 || - !local_surface_id_from_parent_.is_valid()); + proxy_->SetDeferMainFrameUpdate( + defer_main_frame_update_count_ > 0 || + !pending_commit_state()->local_surface_id_from_parent.is_valid()); } bool LayerTreeHost::IsUsingLayerLists() const { return settings_.use_layer_lists; } -void LayerTreeHost::CommitComplete() { +void LayerTreeHost::CommitComplete(const CommitTimestamps& commit_timestamps) { // This DCHECK ensures that WaitForCommitCompletion() will not block. DCHECK(!in_commit()); WaitForCommitCompletion(); - source_frame_number_++; - client_->DidCommit(impl_commit_start_time_, impl_commit_finish_time_); - impl_commit_start_time_ = impl_commit_finish_time_ = base::TimeTicks(); + client_->DidCommit(commit_timestamps.start, commit_timestamps.finish); if (did_complete_scale_animation_) { client_->DidCompletePageScaleAnimation(); did_complete_scale_animation_ = false; @@ -595,29 +483,54 @@ void LayerTreeHost::DidFailToInitializeLayerTreeFrameSink() { std::unique_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl( LayerTreeHostImplClient* client) { + // This method is special: it should be the only LayerTreeHost method that + // runs on the impl thread. As such, it cannot use LayerTreeHost getter + // methods that enforce DCHECK(IsMainThread()). Because it only ever runs when + // the main thread is blocked, it's safe to access member variables directly. DCHECK(task_runner_provider_->IsImplThread()); - + DCHECK(task_runner_provider_->IsMainThreadBlocked()); + return CreateLayerTreeHostImplInternal( + client, thread_unsafe_commit_state_.mutator_host, settings_, + task_runner_provider_.get(), dark_mode_filter_, id_, task_graph_runner_, + image_worker_task_runner_, scheduling_client_, + rendering_stats_instrumentation_.get(), ukm_recorder_factory_, + compositor_delegate_weak_ptr_); +} + +std::unique_ptr<LayerTreeHostImpl> +LayerTreeHost::CreateLayerTreeHostImplInternal( + LayerTreeHostImplClient* client, + MutatorHost* mutator_host, + const LayerTreeSettings& settings, + TaskRunnerProvider* task_runner_provider, + raw_ptr<RasterDarkModeFilter>& dark_mode_filter, + int id, + raw_ptr<TaskGraphRunner>& task_graph_runner, + scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, + LayerTreeHostSchedulingClient* scheduling_client, + RenderingStatsInstrumentation* rendering_stats_instrumentation, + std::unique_ptr<UkmRecorderFactory>& ukm_recorder_factory, + base::WeakPtr<CompositorDelegateForInput>& compositor_delegate_weak_ptr) { std::unique_ptr<MutatorHost> mutator_host_impl = - mutator_host_->CreateImplInstance(); + mutator_host->CreateImplInstance(); - if (!settings_.scroll_animation_duration_for_testing.is_zero()) { - mutator_host_->SetScrollAnimationDurationForTesting( - settings_.scroll_animation_duration_for_testing); + if (!settings.scroll_animation_duration_for_testing.is_zero()) { + mutator_host->SetScrollAnimationDurationForTesting( // IN-TEST + settings.scroll_animation_duration_for_testing); } 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), 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(); + settings, client, task_runner_provider, rendering_stats_instrumentation, + task_graph_runner, 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(); + task_graph_runner = nullptr; + dark_mode_filter = nullptr; + compositor_delegate_weak_ptr = host_impl->AsWeakPtr(); return host_impl; } @@ -672,7 +585,7 @@ void LayerTreeHost::OnDeferCommitsChanged(bool defer_status, DISABLE_CFI_PERF void LayerTreeHost::SetNeedsAnimate() { proxy_->SetNeedsAnimate(); - swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit(); + swap_promise_manager_.NotifyLatencyInfoSwapPromiseMonitors(); events_metrics_manager_.SaveActiveEventMetrics(); } @@ -684,13 +597,13 @@ void LayerTreeHost::SetNeedsAnimateIfNotInsideMainFrame() { DISABLE_CFI_PERF void LayerTreeHost::SetNeedsUpdateLayers() { proxy_->SetNeedsUpdateLayers(); - swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit(); + swap_promise_manager_.NotifyLatencyInfoSwapPromiseMonitors(); events_metrics_manager_.SaveActiveEventMetrics(); } void LayerTreeHost::SetNeedsCommit() { proxy_->SetNeedsCommit(); - swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit(); + swap_promise_manager_.NotifyLatencyInfoSwapPromiseMonitors(); events_metrics_manager_.SaveActiveEventMetrics(); } @@ -699,12 +612,12 @@ void LayerTreeHost::SetTargetLocalSurfaceId( proxy_->SetTargetLocalSurfaceId(target_local_surface_id); } -bool LayerTreeHost::RequestedMainFramePendingForTesting() const { +bool LayerTreeHost::RequestedMainFramePending() const { return proxy_->RequestedAnimatePending(); } void LayerTreeHost::SetNeedsRecalculateRasterScales() { - next_commit_forces_recalculate_raster_scales_ = true; + pending_commit_state()->next_commit_forces_recalculate_raster_scales = true; proxy_->SetNeedsCommit(); } @@ -716,12 +629,8 @@ bool LayerTreeHost::CommitRequested() const { return proxy_->CommitRequested(); } -void LayerTreeHost::SetNextCommitWaitsForActivation() { - proxy_->SetNextCommitWaitsForActivation(); -} - void LayerTreeHost::SetNeedsCommitWithForcedRedraw() { - next_commit_forces_redraw_ = true; + pending_commit_state()->next_commit_forces_redraw = true; // This method is used by tests to ensure a commit before grabbing a screen // shot or processing input, so do not defer the commit. StopDeferringCommits(PaintHoldingCommitTrigger::kFeatureDisabled); @@ -729,13 +638,14 @@ void LayerTreeHost::SetNeedsCommitWithForcedRedraw() { } void LayerTreeHost::SetDebugState(const LayerTreeDebugState& new_debug_state) { - if (LayerTreeDebugState::Equal(debug_state_, new_debug_state)) + if (LayerTreeDebugState::Equal(pending_commit_state()->debug_state, + new_debug_state)) return; - debug_state_ = new_debug_state; + pending_commit_state()->debug_state = new_debug_state; rendering_stats_instrumentation_->set_record_rendering_stats( - debug_state_.RecordRenderingStats()); + pending_commit_state()->debug_state.RecordRenderingStats()); SetNeedsCommit(); } @@ -744,7 +654,8 @@ void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(float page_scale_delta) { DCHECK(CommitRequested()); if (page_scale_delta == 1.f) return; - float page_scale = page_scale_factor_ * page_scale_delta; + float page_scale = + pending_commit_state()->page_scale_factor * page_scale_delta; SetPageScaleFromImplSide(page_scale); } @@ -778,8 +689,8 @@ void LayerTreeHost::CompositeForTest(base::TimeTicks frame_begin_time, bool LayerTreeHost::UpdateLayers() { if (!root_layer()) { - property_trees_.clear(); - viewport_property_ids_ = ViewportPropertyIds(); + property_trees()->clear(); + pending_commit_state()->viewport_property_ids = ViewportPropertyIds(); return false; } @@ -792,8 +703,10 @@ bool LayerTreeHost::UpdateLayers() { micro_benchmark_controller_.DidUpdateLayers(); base::TimeDelta elapsed_delta = timer.Elapsed(); - if (begin_main_frame_metrics_) - begin_main_frame_metrics_->update_layers = elapsed_delta; + if (pending_commit_state()->begin_main_frame_metrics) { + pending_commit_state()->begin_main_frame_metrics->update_layers = + elapsed_delta; + } if (const char* client_name = GetClientNameForMetrics()) { auto elapsed = elapsed_delta.InMicroseconds(); @@ -818,32 +731,6 @@ void LayerTreeHost::DidCompletePageScaleAnimation() { did_complete_scale_animation_ = true; } -void LayerTreeHost::RecordGpuRasterizationHistogram( - const LayerTreeHostImpl* host_impl) { - // Gpu rasterization is only supported for Renderer compositors. - // Checking for IsSingleThreaded() to exclude Browser compositors. - if (gpu_rasterization_histogram_recorded_ || IsSingleThreaded()) - return; - - bool gpu_rasterization_enabled = false; - if (host_impl->layer_tree_frame_sink()) { - viz::ContextProvider* compositor_context_provider = - host_impl->layer_tree_frame_sink()->context_provider(); - if (compositor_context_provider) { - gpu_rasterization_enabled = - compositor_context_provider->ContextCapabilities().gpu_rasterization; - } - } - - // Record how widely gpu rasterization is enabled. - // This number takes device/gpu allowlist/denylist into account. - // Note that we do not consider the forced gpu rasterization mode, which is - // mostly used for debugging purposes. - UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationEnabled", - gpu_rasterization_enabled); - gpu_rasterization_histogram_recorded_ = true; -} - std::string LayerTreeHost::LayersAsString() const { std::string layers; for (const auto* layer : *this) @@ -851,14 +738,14 @@ std::string LayerTreeHost::LayersAsString() const { return layers; } -bool LayerTreeHost::CaptureContent(std::vector<NodeInfo>* content) { +bool LayerTreeHost::CaptureContent(std::vector<NodeInfo>* content) const { if (visual_device_viewport_intersection_rect_.IsEmpty()) return false; gfx::Rect rect = gfx::Rect(visual_device_viewport_intersection_rect_.width(), visual_device_viewport_intersection_rect_.height()); - for (auto* layer : *this) { + for (const auto* layer : *this) { // Normally, the node won't be drawn in multiple layers, even it is, such as // text strokes, the visual rect don't have too much different. layer->CaptureContent(rect, content); @@ -875,7 +762,14 @@ void LayerTreeHost::DidObserveFirstScrollDelay( void LayerTreeHost::AddDocumentTransitionRequest( std::unique_ptr<DocumentTransitionRequest> request) { - document_transition_requests_.push_back(std::move(request)); + // Store the commit callback on LayerTreeHost, so that we can invoke them + // when the request is finished. + DCHECK( + !base::Contains(document_transition_callbacks_, request->sequence_id())); + document_transition_callbacks_[request->sequence_id()] = + request->TakeFinishedCallback(); + pending_commit_state()->document_transition_requests.push_back( + std::move(request)); SetNeedsCommit(); } @@ -883,7 +777,7 @@ bool LayerTreeHost::DoUpdateLayers() { TRACE_EVENT1("cc,benchmark", "LayerTreeHost::DoUpdateLayers", "source_frame_number", SourceFrameNumber()); - UpdateHudLayer(debug_state_.ShouldCreateHudLayer()); + UpdateHudLayer(pending_commit_state()->debug_state.ShouldCreateHudLayer()); // In layer lists mode, the cc property trees are built directly and do not // need to be built here. @@ -893,21 +787,21 @@ bool LayerTreeHost::DoUpdateLayers() { TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "LayerTreeHost::UpdateLayers_BuiltPropertyTrees", TRACE_EVENT_SCOPE_THREAD, "property_trees", - property_trees_.AsTracedValue()); + property_trees()->AsTracedValue()); } else { TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "LayerTreeHost::UpdateLayers_ReceivedPropertyTrees", TRACE_EVENT_SCOPE_THREAD, "property_trees", - property_trees_.AsTracedValue()); + property_trees()->AsTracedValue()); // The HUD layer is managed outside the layer list sent to LayerTreeHost // and needs to have its property tree state set. - if (hud_layer_ && root_layer_.get()) { - hud_layer_->SetTransformTreeIndex(root_layer_->transform_tree_index()); - hud_layer_->SetEffectTreeIndex(root_layer_->effect_tree_index()); - hud_layer_->SetClipTreeIndex(root_layer_->clip_tree_index()); - hud_layer_->SetScrollTreeIndex(root_layer_->scroll_tree_index()); - hud_layer_->set_property_tree_sequence_number( - root_layer_->property_tree_sequence_number()); + if (hud_layer() && root_layer()) { + hud_layer()->SetTransformTreeIndex(root_layer()->transform_tree_index()); + hud_layer()->SetEffectTreeIndex(root_layer()->effect_tree_index()); + hud_layer()->SetClipTreeIndex(root_layer()->clip_tree_index()); + hud_layer()->SetScrollTreeIndex(root_layer()->scroll_tree_index()); + hud_layer()->set_property_tree_sequence_number( + root_layer()->property_tree_sequence_number()); } } @@ -918,16 +812,17 @@ bool LayerTreeHost::DoUpdateLayers() { // |PropertyTreeBuilder::BuildPropertyTrees| fails to create property tree // nodes. for (auto* layer : *this) { - DCHECK(property_trees_.effect_tree.Node(layer->effect_tree_index())); - DCHECK(property_trees_.transform_tree.Node(layer->transform_tree_index())); - DCHECK(property_trees_.clip_tree.Node(layer->clip_tree_index())); - DCHECK(property_trees_.scroll_tree.Node(layer->scroll_tree_index())); + DCHECK(property_trees()->effect_tree.Node(layer->effect_tree_index())); + DCHECK( + property_trees()->transform_tree.Node(layer->transform_tree_index())); + DCHECK(property_trees()->clip_tree.Node(layer->clip_tree_index())); + DCHECK(property_trees()->scroll_tree.Node(layer->scroll_tree_index())); } #else // This is a quick sanity check for readiness of paint properties. // TODO(crbug.com/913464): This is to help analysis of crashes of the bug. // Remove this CHECK when we close the bug. - CHECK(property_trees_.effect_tree.Node(root_layer_->effect_tree_index())); + CHECK(property_trees()->effect_tree.Node(root_layer()->effect_tree_index())); #endif draw_property_utils::UpdatePropertyTrees(this); @@ -976,14 +871,14 @@ void LayerTreeHost::ApplyViewportChanges( is_pinch_gesture_active_from_impl_ = commit_data.is_pinch_gesture_active; if (auto* inner_scroll = property_trees()->scroll_tree.Node( - viewport_property_ids_.inner_scroll)) { + pending_commit_state()->viewport_property_ids.inner_scroll)) { UpdateScrollOffsetFromImpl( inner_scroll->element_id, inner_viewport_scroll_delta, commit_data.inner_viewport_scroll.snap_target_element_ids); } ApplyPageScaleDeltaFromImplSide(commit_data.page_scale_delta); - SetElasticOverscrollFromImplSide(elastic_overscroll_ + + SetElasticOverscrollFromImplSide(pending_commit_state()->elastic_overscroll + commit_data.elastic_overscroll_delta); // TODO(ccameron): pass the elastic overscroll here so that input events // may be translated appropriately. @@ -1051,15 +946,15 @@ void LayerTreeHost::ApplyCompositorChanges(CompositorCommitData* commit_data) { "input,benchmark", "LatencyInfo.Flow", [&swap_promise](perfetto::EventContext ctx) { ChromeLatencyInfo* info = ctx.event()->set_chrome_latency_info(); - info->set_trace_id(swap_promise->TraceId()); + info->set_trace_id(swap_promise->GetTraceId()); info->set_step(ChromeLatencyInfo::STEP_MAIN_THREAD_SCROLL_UPDATE); tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT, - swap_promise->TraceId()); + swap_promise->GetTraceId()); }); swap_promise_manager_.QueueSwapPromise(std::move(swap_promise)); } - if (root_layer_) { + if (root_layer()) { auto& scroll_tree = property_trees()->scroll_tree; for (auto& scroll : commit_data->scrolls) { UpdateScrollOffsetFromImpl(scroll.element_id, scroll.scroll_delta, @@ -1082,7 +977,7 @@ void LayerTreeHost::ApplyCompositorChanges(CompositorCommitData* commit_data) { void LayerTreeHost::ApplyMutatorEvents(std::unique_ptr<MutatorEvents> events) { DCHECK(task_runner_provider_->IsMainThread()); if (!events->IsEmpty()) - mutator_host_->SetAnimationEvents(std::move(events)); + mutator_host()->SetAnimationEvents(std::move(events)); } void LayerTreeHost::RecordStartOfFrameMetrics() { @@ -1114,17 +1009,17 @@ void LayerTreeHost::UpdateBrowserControlsState(BrowserControlsState constraints, } void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) { - std::unique_ptr<MutatorEvents> events = mutator_host_->CreateEvents(); + std::unique_ptr<MutatorEvents> events = mutator_host()->CreateEvents(); - if (mutator_host_->TickAnimations(monotonic_time, - property_trees()->scroll_tree, true)) - mutator_host_->UpdateAnimationState(true, events.get()); + if (mutator_host()->TickAnimations(monotonic_time, + property_trees()->scroll_tree, true)) + mutator_host()->UpdateAnimationState(true, events.get()); if (!events->IsEmpty()) { // If not using layer lists, animation state changes will require // rebuilding property trees to track them. if (!IsUsingLayerLists()) - property_trees_.needs_rebuild = true; + property_trees()->needs_rebuild = true; // A commit is required to push animation changes to the compositor. SetNeedsCommit(); @@ -1179,7 +1074,8 @@ bool LayerTreeHost::IsThreaded() const { void LayerTreeHost::RequestPresentationTimeForNextFrame( PresentationTimeCallbackBuffer::MainCallback callback) { - pending_presentation_time_callbacks_.push_back(std::move(callback)); + pending_commit_state()->pending_presentation_time_callbacks.push_back( + std::move(callback)); } void LayerTreeHost::RequestScrollAnimationEndNotification( @@ -1191,24 +1087,28 @@ void LayerTreeHost::RequestScrollAnimationEndNotification( std::move(callback).Run(); } -void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { - if (root_layer_.get() == root_layer.get()) +void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> new_root_layer) { + if (root_layer() == new_root_layer.get()) return; - if (root_layer_.get()) - root_layer_->SetLayerTreeHost(nullptr); - root_layer_ = root_layer; - if (root_layer_.get()) { - DCHECK(!root_layer_->parent()); - root_layer_->SetLayerTreeHost(this); + if (root_layer()) { + WaitForCommitCompletion(); + root_layer()->SetLayerTreeHost(nullptr); + } + thread_unsafe_commit_state().root_layer = new_root_layer; + if (root_layer()) { + DCHECK(!root_layer()->parent()); + root_layer()->SetLayerTreeHost(this); } - if (hud_layer_.get()) - hud_layer_->RemoveFromParent(); + if (hud_layer()) { + WaitForCommitCompletion(); + hud_layer()->RemoveFromParent(); + } // Reset gpu rasterization tracking. // This flag is sticky until a new tree comes along. - gpu_rasterization_histogram_recorded_ = false; + pending_commit_state()->needs_gpu_rasterization_histogram = IsThreaded(); SetNeedsFullTreeSync(); } @@ -1216,76 +1116,52 @@ void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { void LayerTreeHost::RegisterViewportPropertyIds( const ViewportPropertyIds& ids) { DCHECK(IsUsingLayerLists()); - viewport_property_ids_ = ids; + pending_commit_state()->viewport_property_ids = ids; // Outer viewport properties exist only if inner viewport property exists. DCHECK(ids.inner_scroll != ScrollTree::kInvalidNodeId || (ids.outer_scroll == ScrollTree::kInvalidNodeId && ids.outer_clip == ClipTree::kInvalidNodeId)); } -Layer* LayerTreeHost::InnerViewportScrollLayerForTesting() const { - auto* scroll_node = - property_trees()->scroll_tree.Node(viewport_property_ids_.inner_scroll); +Layer* LayerTreeHost::InnerViewportScrollLayerForTesting() { + auto* scroll_node = property_trees()->scroll_tree.Node( + pending_commit_state()->viewport_property_ids.inner_scroll); return scroll_node ? LayerByElementId(scroll_node->element_id) : nullptr; } -Layer* LayerTreeHost::OuterViewportScrollLayerForTesting() const { +Layer* LayerTreeHost::OuterViewportScrollLayerForTesting() { return LayerByElementId(OuterViewportScrollElementId()); } ElementId LayerTreeHost::OuterViewportScrollElementId() const { - auto* scroll_node = - property_trees()->scroll_tree.Node(viewport_property_ids_.outer_scroll); + auto* scroll_node = property_trees()->scroll_tree.Node( + pending_commit_state()->viewport_property_ids.outer_scroll); return scroll_node ? scroll_node->element_id : ElementId(); } void LayerTreeHost::RegisterSelection(const LayerSelection& selection) { - if (selection_ == selection) + if (pending_commit_state()->selection == selection) return; - selection_ = selection; + pending_commit_state()->selection = selection; SetNeedsCommit(); } void LayerTreeHost::SetHaveScrollEventHandlers(bool have_event_handlers) { - if (have_scroll_event_handlers_ == have_event_handlers) + if (pending_commit_state()->have_scroll_event_handlers == have_event_handlers) return; - have_scroll_event_handlers_ = have_event_handlers; + pending_commit_state()->have_scroll_event_handlers = have_event_handlers; SetNeedsCommit(); } void LayerTreeHost::SetEventListenerProperties( EventListenerClass event_class, EventListenerProperties properties) { - const size_t index = static_cast<size_t>(event_class); - if (event_listener_properties_[index] == properties) + if (event_listener_properties(event_class) == properties) return; - - // If the mouse wheel event listener is blocking, then every layer in the - // layer tree sets a wheel event handler region to be its entire bounds, - // otherwise it sets it to empty. - // - // 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 && - !base::FeatureList::IsEnabled(::features::kWheelEventRegions)) { - bool new_property_is_blocking = - properties == EventListenerProperties::kBlocking || - properties == EventListenerProperties::kBlockingAndPassive; - EventListenerProperties old_properties = event_listener_properties_[index]; - bool old_property_is_blocking = - old_properties == EventListenerProperties::kBlocking || - old_properties == EventListenerProperties::kBlockingAndPassive; - - if (old_property_is_blocking != new_property_is_blocking) { - for (auto* layer : *this) - layer->SetNeedsPushProperties(); - } - } - - event_listener_properties_[index] = properties; + const size_t index = static_cast<size_t>(event_class); + pending_commit_state()->event_listener_properties[index] = properties; SetNeedsCommit(); } @@ -1294,7 +1170,7 @@ void LayerTreeHost::SetViewportRectAndScale( float device_scale_factor, const viz::LocalSurfaceId& local_surface_id_from_parent) { const viz::LocalSurfaceId previous_local_surface_id = - local_surface_id_from_parent_; + pending_commit_state()->local_surface_id_from_parent; SetLocalSurfaceIdFromParent(local_surface_id_from_parent); TRACE_EVENT_NESTABLE_ASYNC_END1("cc", "LayerTreeHostSize", @@ -1305,22 +1181,23 @@ void LayerTreeHost::SetViewportRectAndScale( local_surface_id_from_parent.ToString()); bool device_viewport_rect_changed = false; - if (device_viewport_rect_ != device_viewport_rect) { - device_viewport_rect_ = device_viewport_rect; + if (pending_commit_state()->device_viewport_rect != device_viewport_rect) { + pending_commit_state()->device_viewport_rect = device_viewport_rect; device_viewport_rect_changed = true; } bool painted_device_scale_factor_changed = false; bool device_scale_factor_changed = false; if (settings_.use_painted_device_scale_factor) { - DCHECK_EQ(device_scale_factor_, 1.f); - if (painted_device_scale_factor_ != device_scale_factor) { - painted_device_scale_factor_ = device_scale_factor; + DCHECK_EQ(pending_commit_state()->device_scale_factor, 1.f); + if (pending_commit_state()->painted_device_scale_factor != + device_scale_factor) { + pending_commit_state()->painted_device_scale_factor = device_scale_factor; painted_device_scale_factor_changed = true; } } else { - DCHECK_EQ(painted_device_scale_factor_, 1.f); - if (device_scale_factor_ != device_scale_factor) { - device_scale_factor_ = device_scale_factor; + DCHECK_EQ(pending_commit_state()->painted_device_scale_factor, 1.f); + if (pending_commit_state()->device_scale_factor != device_scale_factor) { + pending_commit_state()->device_scale_factor = device_scale_factor; device_scale_factor_changed = true; } } @@ -1349,46 +1226,48 @@ void LayerTreeHost::SetVisualDeviceViewportIntersectionRect( void LayerTreeHost::SetVisualDeviceViewportSize( const gfx::Size& visual_device_viewport_size) { - if (visual_device_viewport_size == visual_device_viewport_size_) + if (visual_device_viewport_size == + pending_commit_state()->visual_device_viewport_size) return; - visual_device_viewport_size_ = visual_device_viewport_size; + pending_commit_state()->visual_device_viewport_size = + visual_device_viewport_size; SetNeedsCommit(); } void LayerTreeHost::SetBrowserControlsParams( const BrowserControlsParams& params) { - if (browser_controls_params_ == params) + if (pending_commit_state()->browser_controls_params == params) return; - browser_controls_params_ = params; + pending_commit_state()->browser_controls_params = params; SetNeedsCommit(); } void LayerTreeHost::SetBrowserControlsShownRatio(float top_ratio, float bottom_ratio) { - if (top_controls_shown_ratio_ == top_ratio && - bottom_controls_shown_ratio_ == bottom_ratio) + if (pending_commit_state()->top_controls_shown_ratio == top_ratio && + pending_commit_state()->bottom_controls_shown_ratio == bottom_ratio) return; - top_controls_shown_ratio_ = top_ratio; - bottom_controls_shown_ratio_ = bottom_ratio; + pending_commit_state()->top_controls_shown_ratio = top_ratio; + pending_commit_state()->bottom_controls_shown_ratio = bottom_ratio; SetNeedsCommit(); } void LayerTreeHost::SetOverscrollBehavior(const OverscrollBehavior& behavior) { - if (overscroll_behavior_ == behavior) + if (pending_commit_state()->overscroll_behavior == behavior) return; - overscroll_behavior_ = behavior; + pending_commit_state()->overscroll_behavior = behavior; SetNeedsCommit(); } void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor) { - if (page_scale_factor_ == page_scale_factor && - min_page_scale_factor_ == min_page_scale_factor && - max_page_scale_factor_ == max_page_scale_factor) + if (pending_commit_state()->page_scale_factor == page_scale_factor && + pending_commit_state()->min_page_scale_factor == min_page_scale_factor && + pending_commit_state()->max_page_scale_factor == max_page_scale_factor) return; DCHECK_GE(page_scale_factor, min_page_scale_factor); DCHECK_LE(page_scale_factor, max_page_scale_factor); @@ -1396,29 +1275,31 @@ void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor, // TODO(wjmaclean): Remove this dcheck as a pre-condition to closing the bug. // https://crbug.com/845097 DCHECK(!settings_.is_layer_tree_for_subframe || - page_scale_factor == page_scale_factor_) - << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_ + page_scale_factor == pending_commit_state()->page_scale_factor) + << "Setting PSF in oopif subframe: old psf = " + << pending_commit_state()->page_scale_factor << ", new psf = " << page_scale_factor; - page_scale_factor_ = page_scale_factor; - min_page_scale_factor_ = min_page_scale_factor; - max_page_scale_factor_ = max_page_scale_factor; + pending_commit_state()->page_scale_factor = page_scale_factor; + pending_commit_state()->min_page_scale_factor = min_page_scale_factor; + pending_commit_state()->max_page_scale_factor = max_page_scale_factor; SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } -void LayerTreeHost::StartPageScaleAnimation(const gfx::Vector2d& target_offset, +void LayerTreeHost::StartPageScaleAnimation(const gfx::Point& target_offset, bool use_anchor, float scale, base::TimeDelta duration) { - pending_page_scale_animation_ = std::make_unique<PendingPageScaleAnimation>( - target_offset, use_anchor, scale, duration); + pending_commit_state()->pending_page_scale_animation = + std::make_unique<PendingPageScaleAnimation>(target_offset, use_anchor, + scale, duration); SetNeedsCommit(); } bool LayerTreeHost::HasPendingPageScaleAnimation() const { - return !!pending_page_scale_animation_.get(); + return !!pending_commit_state()->pending_page_scale_animation.get(); } void LayerTreeHost::SetRecordingScaleFactor(float recording_scale_factor) { @@ -1429,50 +1310,56 @@ void LayerTreeHost::SetRecordingScaleFactor(float recording_scale_factor) { void LayerTreeHost::SetDisplayColorSpaces( const gfx::DisplayColorSpaces& display_color_spaces) { - if (display_color_spaces_ == display_color_spaces) + if (pending_commit_state()->display_color_spaces == display_color_spaces) return; - display_color_spaces_ = display_color_spaces; + pending_commit_state()->display_color_spaces = display_color_spaces; for (auto* layer : *this) layer->SetNeedsDisplay(); } void LayerTreeHost::UpdateViewportIsMobileOptimized( bool is_viewport_mobile_optimized) { - if (is_viewport_mobile_optimized_ == is_viewport_mobile_optimized) + if (pending_commit_state()->is_viewport_mobile_optimized == + is_viewport_mobile_optimized) return; - is_viewport_mobile_optimized_ = is_viewport_mobile_optimized; + pending_commit_state()->is_viewport_mobile_optimized = + is_viewport_mobile_optimized; SetNeedsCommit(); } void LayerTreeHost::SetPrefersReducedMotion(bool prefers_reduced_motion) { - if (prefers_reduced_motion_ == prefers_reduced_motion) + if (pending_commit_state()->prefers_reduced_motion == prefers_reduced_motion) return; - prefers_reduced_motion_ = prefers_reduced_motion; + pending_commit_state()->prefers_reduced_motion = prefers_reduced_motion; SetNeedsCommit(); } void LayerTreeHost::SetMayThrottleIfUndrawnFrames( bool may_throttle_if_undrawn_frames) { - if (may_throttle_if_undrawn_frames_ == may_throttle_if_undrawn_frames) + if (pending_commit_state()->may_throttle_if_undrawn_frames == + may_throttle_if_undrawn_frames) return; - may_throttle_if_undrawn_frames_ = may_throttle_if_undrawn_frames; + pending_commit_state()->may_throttle_if_undrawn_frames = + may_throttle_if_undrawn_frames; SetNeedsCommit(); } bool LayerTreeHost::GetMayThrottleIfUndrawnFramesForTesting() const { - return may_throttle_if_undrawn_frames_; + return pending_commit_state()->may_throttle_if_undrawn_frames; } void LayerTreeHost::SetExternalPageScaleFactor( float page_scale_factor, bool is_external_pinch_gesture_active) { - if (external_page_scale_factor_ == page_scale_factor && - is_external_pinch_gesture_active_ == is_external_pinch_gesture_active) { + if (pending_commit_state()->external_page_scale_factor == page_scale_factor && + pending_commit_state()->is_external_pinch_gesture_active == + is_external_pinch_gesture_active) { return; } - external_page_scale_factor_ = page_scale_factor; - is_external_pinch_gesture_active_ = is_external_pinch_gesture_active; + pending_commit_state()->external_page_scale_factor = page_scale_factor; + pending_commit_state()->is_external_pinch_gesture_active = + is_external_pinch_gesture_active; SetNeedsCommit(); } @@ -1486,10 +1373,11 @@ void LayerTreeHost::SetLocalSurfaceIdFromParent( // // TODO(jonross): Untangle startup so that we don't have this invalid partial // state. (https://crbug.com/1185286) (https://crbug.com/419087) - if (local_surface_id_from_parent_ == local_surface_id_from_parent) + if (pending_commit_state()->local_surface_id_from_parent == + local_surface_id_from_parent) return; const viz::LocalSurfaceId current_local_surface_id_from_parent = - local_surface_id_from_parent_; + pending_commit_state()->local_surface_id_from_parent; // These traces are split into two due to the usage of TRACE_ID_GLOBAL for the // incoming flow (it comes from a different process), and TRACE_ID_LOCAL for @@ -1509,7 +1397,8 @@ void LayerTreeHost::SetLocalSurfaceIdFromParent( "local_surface_id", local_surface_id_from_parent.ToString()); // Always update the cached state of the viz::LocalSurfaceId to reflect the // latest value received from our parent. - local_surface_id_from_parent_ = local_surface_id_from_parent; + pending_commit_state()->local_surface_id_from_parent = + local_surface_id_from_parent; // If the parent sequence number has not advanced, then there is no need to // commit anything. This can occur when the child sequence number has @@ -1530,21 +1419,16 @@ void LayerTreeHost::SetLocalSurfaceIdFromParent( void LayerTreeHost::RequestNewLocalSurfaceId() { // We can still request a new viz::LocalSurfaceId but that request will be // deferred until we have a valid viz::LocalSurfaceId from the parent. - if (new_local_surface_id_request_) + if (pending_commit_state()->new_local_surface_id_request) return; - new_local_surface_id_request_ = true; + pending_commit_state()->new_local_surface_id_request = true; SetNeedsCommit(); } -bool LayerTreeHost::TakeNewLocalSurfaceIdRequest() { - bool new_local_surface_id_request = new_local_surface_id_request_; - new_local_surface_id_request_ = false; - return new_local_surface_id_request; -} - void LayerTreeHost::SetVisualPropertiesUpdateDuration( base::TimeDelta visual_properties_update_duration) { - visual_properties_update_duration_ = visual_properties_update_duration; + pending_commit_state()->visual_properties_update_duration = + visual_properties_update_duration; } void LayerTreeHost::RegisterLayer(Layer* layer) { @@ -1552,8 +1436,8 @@ void LayerTreeHost::RegisterLayer(Layer* layer) { DCHECK(!in_paint_layer_contents_); layer_id_map_[layer->id()] = layer; if (!IsUsingLayerLists() && layer->element_id()) { - mutator_host_->RegisterElementId(layer->element_id(), - ElementListType::ACTIVE); + mutator_host()->RegisterElementId(layer->element_id(), + ElementListType::ACTIVE); } } @@ -1561,14 +1445,14 @@ void LayerTreeHost::UnregisterLayer(Layer* layer) { DCHECK(LayerById(layer->id())); DCHECK(!in_paint_layer_contents_); if (!IsUsingLayerLists() && layer->element_id()) { - mutator_host_->UnregisterElementId(layer->element_id(), - ElementListType::ACTIVE); + mutator_host()->UnregisterElementId(layer->element_id(), + ElementListType::ACTIVE); } - layers_that_should_push_properties_.erase(layer); + thread_unsafe_commit_state().layers_that_should_push_properties.erase(layer); layer_id_map_.erase(layer->id()); } -Layer* LayerTreeHost::LayerById(int id) const { +Layer* LayerTreeHost::LayerById(int id) { auto iter = layer_id_map_.find(id); return iter != layer_id_map_.end() ? iter->second : nullptr; } @@ -1583,34 +1467,23 @@ bool LayerTreeHost::PaintContent(const LayerList& update_layer_list) { } void LayerTreeHost::AddSurfaceRange(const viz::SurfaceRange& surface_range) { - if (++surface_ranges_[surface_range] == 1) - needs_surface_ranges_sync_ = true; + if (++pending_commit_state()->surface_ranges[surface_range] == 1) + pending_commit_state()->needs_surface_ranges_sync = true; } void LayerTreeHost::RemoveSurfaceRange(const viz::SurfaceRange& surface_range) { - auto iter = surface_ranges_.find(surface_range); - if (iter == surface_ranges_.end()) + auto iter = pending_commit_state()->surface_ranges.find(surface_range); + if (iter == pending_commit_state()->surface_ranges.end()) return; if (--iter->second <= 0) { - surface_ranges_.erase(iter); - needs_surface_ranges_sync_ = true; + pending_commit_state()->surface_ranges.erase(iter); + pending_commit_state()->needs_surface_ranges_sync = true; } } -base::flat_set<viz::SurfaceRange> LayerTreeHost::SurfaceRanges() const { - base::flat_set<viz::SurfaceRange> ranges; - for (auto& map_entry : surface_ranges_) - ranges.insert(map_entry.first); - return ranges; -} - void LayerTreeHost::AddLayerShouldPushProperties(Layer* layer) { - layers_that_should_push_properties_.insert(layer); -} - -void LayerTreeHost::ClearLayersThatShouldPushProperties() { - layers_that_should_push_properties_.clear(); + thread_unsafe_commit_state().layers_that_should_push_properties.insert(layer); } void LayerTreeHost::SetPageScaleFromImplSide(float page_scale) { @@ -1619,28 +1492,32 @@ void LayerTreeHost::SetPageScaleFromImplSide(float page_scale) { // TODO(wjmaclean): Remove this check as a pre-condition to closing the bug. // https://crbug.com/845097 DCHECK(!settings_.is_layer_tree_for_subframe || - page_scale == page_scale_factor_) - << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_ + page_scale == pending_commit_state()->page_scale_factor) + << "Setting PSF in oopif subframe: old psf = " + << pending_commit_state()->page_scale_factor << ", new psf = " << page_scale; - page_scale_factor_ = page_scale; + pending_commit_state()->page_scale_factor = page_scale; SetPropertyTreesNeedRebuild(); } void LayerTreeHost::SetElasticOverscrollFromImplSide( gfx::Vector2dF elastic_overscroll) { DCHECK(CommitRequested()); - elastic_overscroll_ = elastic_overscroll; + pending_commit_state()->elastic_overscroll = elastic_overscroll; } void LayerTreeHost::UpdateHudLayer(bool show_hud_info) { if (show_hud_info) { - if (!hud_layer_.get()) + if (!hud_layer()) { hud_layer_ = HeadsUpDisplayLayer::Create(); - if (root_layer_.get() && !hud_layer_->parent()) - root_layer_->AddChild(hud_layer_); - hud_layer_->UpdateLocationAndSize(device_viewport_rect_.size(), - device_scale_factor_); - if (debug_state_.show_web_vital_metrics) { + pending_commit_state()->hud_layer_id = hud_layer()->id(); + } + if (root_layer() && !hud_layer()->parent()) + root_layer()->AddChild(hud_layer()); + hud_layer()->UpdateLocationAndSize( + pending_commit_state()->device_viewport_rect.size(), + pending_commit_state()->device_scale_factor); + if (pending_commit_state()->debug_state.show_web_vital_metrics) { // This WebVitalMetrics is filled by the main frame, which is equivalent // to WebPerf's numbers. The main frame's number doesn't include any // iframes. UMA/UKM records metrics for the entire page aggregating all @@ -1648,11 +1525,12 @@ void LayerTreeHost::UpdateHudLayer(bool show_hud_info) { // TODO(weiliangc): Get the page metrics for display. auto metrics = client_->GetWebVitalMetrics(); if (metrics && metrics->HasValue()) - hud_layer_->UpdateWebVitalMetrics(std::move(metrics)); + hud_layer()->UpdateWebVitalMetrics(std::move(metrics)); } - } else if (hud_layer_.get()) { - hud_layer_->RemoveFromParent(); + } else if (hud_layer()) { + hud_layer()->RemoveFromParent(); hud_layer_ = nullptr; + pending_commit_state()->hud_layer_id = Layer::INVALID_ID; } } @@ -1661,131 +1539,26 @@ bool LayerTreeHost::is_hud_layer(const Layer* layer) const { } void LayerTreeHost::SetNeedsFullTreeSync() { - needs_full_tree_sync_ = true; - property_trees_.needs_rebuild = true; + pending_commit_state()->needs_full_tree_sync = true; + property_trees()->needs_rebuild = true; SetNeedsCommit(); } -void LayerTreeHost::SetPropertyTreesNeedRebuild() { - property_trees_.needs_rebuild = true; - SetNeedsUpdateLayers(); -} - -void LayerTreeHost::PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl) { - tree_impl->set_needs_full_tree_sync(needs_full_tree_sync_); - needs_full_tree_sync_ = false; - - if (hud_layer_.get()) { - LayerImpl* hud_impl = tree_impl->LayerById(hud_layer_->id()); - tree_impl->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl)); - } else { - tree_impl->set_hud_layer(nullptr); - } - - tree_impl->set_background_color(background_color_); - tree_impl->set_have_scroll_event_handlers(have_scroll_event_handlers_); - tree_impl->set_event_listener_properties( - EventListenerClass::kTouchStartOrMove, - event_listener_properties(EventListenerClass::kTouchStartOrMove)); - tree_impl->set_event_listener_properties( - EventListenerClass::kMouseWheel, - event_listener_properties(EventListenerClass::kMouseWheel)); - tree_impl->set_event_listener_properties( - EventListenerClass::kTouchEndOrCancel, - event_listener_properties(EventListenerClass::kTouchEndOrCancel)); - - tree_impl->SetViewportPropertyIds(viewport_property_ids_); - - tree_impl->RegisterSelection(selection_); - - tree_impl->PushPageScaleFromMainThread( - page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_); - - tree_impl->SetBrowserControlsParams(browser_controls_params_); - tree_impl->set_overscroll_behavior(overscroll_behavior_); - tree_impl->PushBrowserControlsFromMainThread(top_controls_shown_ratio_, - bottom_controls_shown_ratio_); - tree_impl->elastic_overscroll()->PushMainToPending(elastic_overscroll_); - if (tree_impl->IsActiveTree()) - tree_impl->elastic_overscroll()->PushPendingToActive(); - - tree_impl->SetDisplayColorSpaces(display_color_spaces_); - tree_impl->SetExternalPageScaleFactor(external_page_scale_factor_); - - tree_impl->set_painted_device_scale_factor(painted_device_scale_factor_); - tree_impl->SetDeviceScaleFactor(device_scale_factor_); - tree_impl->SetDeviceViewportRect(device_viewport_rect_); - - if (TakeNewLocalSurfaceIdRequest()) - tree_impl->RequestNewLocalSurfaceId(); - - tree_impl->SetLocalSurfaceIdFromParent(local_surface_id_from_parent_); - tree_impl->SetVisualPropertiesUpdateDuration( - visual_properties_update_duration_); - - if (pending_page_scale_animation_) { - tree_impl->SetPendingPageScaleAnimation( - std::move(pending_page_scale_animation_)); - } - - if (TakeForceSendMetadataRequest()) - tree_impl->RequestForceSendMetadata(); - - tree_impl->set_has_ever_been_drawn(false); - - // TODO(ericrk): The viewport changes caused by |top_controls_shown_ratio_| - // changes should propagate back to the main tree. This does not currently - // happen, so we must force the impl tree to update its viewports if - // |top_controls_shown_ratio_| is greater than 0.0f and less than 1.0f - // (partially shown). crbug.com/875943 - if (top_controls_shown_ratio_ > 0.0f && top_controls_shown_ratio_ < 1.0f) { - tree_impl->UpdateViewportContainerSizes(); - } - - tree_impl->set_display_transform_hint(display_transform_hint_); - - if (delegated_ink_metadata_) - tree_impl->set_delegated_ink_metadata(std::move(delegated_ink_metadata_)); - - // Transfer page transition directives. - for (auto& request : document_transition_requests_) { - // Store the commit callback on LayerTreeHost, so that we can invoke them - // when the request is finished. - DCHECK(!base::Contains(document_transition_callbacks_, - request->sequence_id())); - document_transition_callbacks_[request->sequence_id()] = - request->TakeFinishedCallback(); - - tree_impl->AddDocumentTransitionRequest(std::move(request)); - } - document_transition_requests_.clear(); +void LayerTreeHost::ResetNeedsFullTreeSyncForTesting() { + pending_commit_state()->needs_full_tree_sync = false; } -void LayerTreeHost::PushSurfaceRangesTo(LayerTreeImpl* tree_impl) { - if (needs_surface_ranges_sync()) { - tree_impl->ClearSurfaceRanges(); - tree_impl->SetSurfaceRanges(SurfaceRanges()); - // Reset for next update - set_needs_surface_ranges_sync(false); - } +void LayerTreeHost::SetPropertyTreesNeedRebuild() { + property_trees()->needs_rebuild = true; + SetNeedsUpdateLayers(); } -void LayerTreeHost::PushLayerTreeHostPropertiesTo( - LayerTreeHostImpl* host_impl) { - // TODO(bokan): The |external_pinch_gesture_active| should not be going - // through the LayerTreeHost but directly from InputHandler to InputHandler. - host_impl->SetExternalPinchGestureActive(is_external_pinch_gesture_active_); - - RecordGpuRasterizationHistogram(host_impl); - - host_impl->SetDebugState(debug_state_); - host_impl->SetVisualDeviceViewportSize(visual_device_viewport_size_); - host_impl->set_viewport_mobile_optimized(is_viewport_mobile_optimized_); - host_impl->SetPrefersReducedMotion(prefers_reduced_motion_); - host_impl->SetMayThrottleIfUndrawnFrames(may_throttle_if_undrawn_frames_); +Layer* LayerTreeHost::LayerByElementId(ElementId element_id) { + auto iter = element_layers_map_.find(element_id); + return iter != element_layers_map_.end() ? iter->second : nullptr; } -Layer* LayerTreeHost::LayerByElementId(ElementId element_id) const { +const Layer* LayerTreeHost::LayerByElementId(ElementId element_id) const { auto iter = element_layers_map_.find(element_id); return iter != element_layers_map_.end() ? iter->second : nullptr; } @@ -1794,18 +1567,18 @@ void LayerTreeHost::RegisterElement(ElementId element_id, Layer* layer) { element_layers_map_[element_id] = layer; if (!IsUsingLayerLists()) - mutator_host_->RegisterElementId(element_id, ElementListType::ACTIVE); + mutator_host()->RegisterElementId(element_id, ElementListType::ACTIVE); } void LayerTreeHost::UnregisterElement(ElementId element_id) { if (!IsUsingLayerLists()) - mutator_host_->UnregisterElementId(element_id, ElementListType::ACTIVE); + mutator_host()->UnregisterElementId(element_id, ElementListType::ACTIVE); element_layers_map_.erase(element_id); } void LayerTreeHost::UpdateActiveElements() { DCHECK(IsUsingLayerLists()); - mutator_host_->UpdateRegisteredElementIds(ElementListType::ACTIVE); + mutator_host()->UpdateRegisteredElementIds(ElementListType::ACTIVE); } void LayerTreeHost::SetElementIdsForTesting() { @@ -1831,7 +1604,7 @@ void LayerTreeHost::SetMutatorsNeedCommit() { } void LayerTreeHost::SetMutatorsNeedRebuildPropertyTrees() { - property_trees_.needs_rebuild = true; + property_trees()->needs_rebuild = true; } void LayerTreeHost::SetElementFilterMutated(ElementId element_id, @@ -1840,7 +1613,7 @@ void LayerTreeHost::SetElementFilterMutated(ElementId element_id, if (IsUsingLayerLists()) { // In BlinkGenPropertyTrees/CompositeAfterPaint we always have property // tree nodes and can set the filter directly on the effect node. - property_trees_.effect_tree.OnFilterAnimated(element_id, filters); + property_trees()->effect_tree.OnFilterAnimated(element_id, filters); return; } @@ -1856,8 +1629,8 @@ void LayerTreeHost::SetElementBackdropFilterMutated( if (IsUsingLayerLists()) { // In BlinkGenPropertyTrees/CompositeAfterPaint we always have property // tree nodes and can set the backdrop_filter directly on the effect node. - property_trees_.effect_tree.OnBackdropFilterAnimated(element_id, - backdrop_filters); + property_trees()->effect_tree.OnBackdropFilterAnimated(element_id, + backdrop_filters); return; } @@ -1873,7 +1646,7 @@ void LayerTreeHost::SetElementOpacityMutated(ElementId element_id, DCHECK_LE(opacity, 1.f); if (IsUsingLayerLists()) { - property_trees_.effect_tree.OnOpacityAnimated(element_id, opacity); + property_trees()->effect_tree.OnOpacityAnimated(element_id, opacity); return; } @@ -1882,13 +1655,13 @@ void LayerTreeHost::SetElementOpacityMutated(ElementId element_id, layer->OnOpacityAnimated(opacity); if (EffectNode* node = - property_trees_.effect_tree.Node(layer->effect_tree_index())) { + property_trees()->effect_tree.Node(layer->effect_tree_index())) { DCHECK_EQ(layer->effect_tree_index(), node->id); if (node->opacity == opacity) return; node->opacity = opacity; - property_trees_.effect_tree.set_needs_update(true); + property_trees()->effect_tree.set_needs_update(true); } SetNeedsUpdateLayers(); @@ -1899,7 +1672,7 @@ void LayerTreeHost::SetElementTransformMutated( ElementListType list_type, const gfx::Transform& transform) { if (IsUsingLayerLists()) { - property_trees_.transform_tree.OnTransformAnimated(element_id, transform); + property_trees()->transform_tree.OnTransformAnimated(element_id, transform); return; } @@ -1909,14 +1682,14 @@ void LayerTreeHost::SetElementTransformMutated( if (layer->has_transform_node()) { TransformNode* node = - property_trees_.transform_tree.Node(layer->transform_tree_index()); + property_trees()->transform_tree.Node(layer->transform_tree_index()); if (node->local == transform) return; node->local = transform; node->needs_local_transform_update = true; node->has_potential_animation = true; - property_trees_.transform_tree.set_needs_update(true); + property_trees()->transform_tree.set_needs_update(true); } SetNeedsUpdateLayers(); @@ -1925,7 +1698,7 @@ void LayerTreeHost::SetElementTransformMutated( void LayerTreeHost::SetElementScrollOffsetMutated( ElementId element_id, ElementListType list_type, - const gfx::Vector2dF& scroll_offset) { + const gfx::PointF& scroll_offset) { // Do nothing. Scroll deltas will be sent from the compositor thread back // to the main thread in the same manner as during non-animated // compositor-driven scrolling. @@ -1948,37 +1721,51 @@ void LayerTreeHost::MaximumScaleChanged(ElementId element_id, property_trees()->MaximumAnimationScaleChanged(element_id, maximum_scale); } -gfx::Vector2dF LayerTreeHost::GetScrollOffsetForAnimation( - ElementId element_id) const { - return property_trees()->scroll_tree.current_scroll_offset(element_id); -} - void LayerTreeHost::QueueImageDecode(const PaintImage& image, base::OnceCallback<void(bool)> callback) { TRACE_EVENT0("cc", "LayerTreeHost::QueueImageDecode"); - queued_image_decodes_.emplace_back(image, std::move(callback)); + int next_id = s_image_decode_sequence_number.GetNext(); + pending_commit_state()->queued_image_decodes.emplace_back( + next_id, std::make_unique<PaintImage>(image)); + pending_image_decodes_.emplace(next_id, std::move(callback)); SetNeedsCommit(); } -LayerListIterator LayerTreeHost::begin() const { - return LayerListIterator(root_layer_.get()); +LayerListIterator LayerTreeHost::begin() { + return LayerListIterator(root_layer()); +} + +LayerListConstIterator LayerTreeHost::begin() const { + return LayerListConstIterator(root_layer()); } -LayerListIterator LayerTreeHost::end() const { +LayerListIterator LayerTreeHost::end() { return LayerListIterator(nullptr); } +LayerListConstIterator LayerTreeHost::end() const { + return LayerListConstIterator(nullptr); +} + LayerListReverseIterator LayerTreeHost::rbegin() { - return LayerListReverseIterator(root_layer_.get()); + return LayerListReverseIterator(root_layer()); +} + +LayerListReverseConstIterator LayerTreeHost::rbegin() const { + return LayerListReverseConstIterator(root_layer()); } LayerListReverseIterator LayerTreeHost::rend() { return LayerListReverseIterator(nullptr); } +LayerListReverseConstIterator LayerTreeHost::rend() const { + return LayerListReverseConstIterator(nullptr); +} + void LayerTreeHost::SetPropertyTreesForTesting( const PropertyTrees* property_trees) { - property_trees_ = *property_trees; + thread_unsafe_commit_state().property_trees = *property_trees; } void LayerTreeHost::SetNeedsDisplayOnAllLayers() { @@ -1997,11 +1784,11 @@ void LayerTreeHost::RequestBeginMainFrameNotExpected(bool new_state) { void LayerTreeHost::SetSourceURL(ukm::SourceId source_id, const GURL& url) { // Clears image caches and resets the scheduling history for the content // produced by this host so far. - clear_caches_on_next_commit_ = true; + pending_commit_state()->clear_caches_on_next_commit = true; proxy_->SetSourceURL(source_id, url); // If this is not used as a common web page, don't show HUD. if (!url.SchemeIsHTTPOrHTTPS()) - debug_state_.TurnOffHudInfoDisplay(); + pending_commit_state()->debug_state.TurnOffHudInfoDisplay(); } base::ReadOnlySharedMemoryRegion @@ -2020,12 +1807,6 @@ void LayerTreeHost::SetRenderFrameObserver( proxy_->SetRenderFrameObserver(std::move(observer)); } -bool LayerTreeHost::TakeForceSendMetadataRequest() { - bool force_send_metadata_request = force_send_metadata_request_; - force_send_metadata_request_ = false; - return force_send_metadata_request; -} - void LayerTreeHost::SetEnableFrameRateThrottling( bool enable_frame_rate_throttling) { proxy_->SetEnableFrameRateThrottling(enable_frame_rate_throttling); @@ -2033,24 +1814,21 @@ void LayerTreeHost::SetEnableFrameRateThrottling( void LayerTreeHost::SetDelegatedInkMetadata( std::unique_ptr<gfx::DelegatedInkMetadata> metadata) { - delegated_ink_metadata_ = std::move(metadata); + pending_commit_state()->delegated_ink_metadata = std::move(metadata); SetNeedsCommit(); } -gfx::RenderingPipeline* LayerTreeHost::TakeMainPipeline() { - auto* pipeline = main_thread_pipeline_; - main_thread_pipeline_ = nullptr; - return pipeline; +std::vector<base::OnceClosure> +LayerTreeHost::TakeDocumentTransitionCallbacksForTesting() { + std::vector<base::OnceClosure> result; + for (auto& item : document_transition_callbacks_) + result.push_back(std::move(item.second)); + document_transition_callbacks_.clear(); + return result; } -gfx::RenderingPipeline* LayerTreeHost::TakeCompositorPipeline() { - auto* pipeline = compositor_thread_pipeline_; - compositor_thread_pipeline_ = nullptr; - return pipeline; +uint32_t LayerTreeHost::GetAverageThroughput() const { + return proxy_->GetAverageThroughput(); } -std::vector<std::unique_ptr<DocumentTransitionRequest>> -LayerTreeHost::TakeDocumentTransitionRequestsForTesting() { - return std::move(document_transition_requests_); -} } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index 54b293d4761..23c6b4a92ba 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -20,10 +20,11 @@ #include "base/cancelable_callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "cc/base/completion_event.h" #include "cc/benchmarks/micro_benchmark.h" @@ -35,6 +36,7 @@ #include "cc/input/input_handler.h" #include "cc/input/layer_selection_bound.h" #include "cc/input/scrollbar.h" +#include "cc/layers/layer.h" #include "cc/layers/layer_collections.h" #include "cc/layers/layer_list_iterator.h" #include "cc/metrics/begin_main_frame_metrics.h" @@ -42,19 +44,22 @@ #include "cc/metrics/frame_sequence_tracker.h" #include "cc/metrics/web_vital_metrics.h" #include "cc/paint/node_id.h" -#include "cc/trees//presentation_time_callback_buffer.h" +#include "cc/resources/ui_resource_request.h" #include "cc/trees/browser_controls_params.h" +#include "cc/trees/commit_state.h" #include "cc/trees/compositor_mode.h" #include "cc/trees/layer_tree_frame_sink.h" #include "cc/trees/layer_tree_host_client.h" #include "cc/trees/layer_tree_settings.h" #include "cc/trees/mutator_host.h" #include "cc/trees/paint_holding_reason.h" +#include "cc/trees/presentation_time_callback_buffer.h" #include "cc/trees/proxy.h" #include "cc/trees/swap_promise.h" #include "cc/trees/swap_promise_manager.h" #include "cc/trees/target_property.h" #include "cc/trees/viewport_layers.h" +#include "cc/trees/viewport_property_ids.h" #include "components/viz/common/resources/resource_format.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -64,14 +69,12 @@ namespace gfx { struct PresentationFeedback; -class RenderingPipeline; } namespace cc { class DocumentTransitionRequest; class HeadsUpDisplayLayer; -class Layer; class LayerTreeHostImpl; class LayerTreeHostImplClient; class LayerTreeHostSingleThreadClient; @@ -86,9 +89,9 @@ class TaskGraphRunner; class UIResourceManager; class UkmRecorderFactory; +struct CommitState; struct CompositorCommitData; struct OverscrollBehavior; -struct PendingPageScaleAnimation; struct RenderingStats; // Returned from LayerTreeHost::DeferMainFrameUpdate. Automatically un-defers on @@ -111,15 +114,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { InitParams(InitParams&&); InitParams& operator=(InitParams&&); - LayerTreeHostClient* client = nullptr; - LayerTreeHostSchedulingClient* scheduling_client = nullptr; - TaskGraphRunner* task_graph_runner = nullptr; - LayerTreeSettings const* settings = nullptr; + raw_ptr<LayerTreeHostClient> client = nullptr; + raw_ptr<LayerTreeHostSchedulingClient> scheduling_client = nullptr; + raw_ptr<TaskGraphRunner> task_graph_runner = nullptr; + raw_ptr<const LayerTreeSettings> settings = nullptr; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner; - MutatorHost* mutator_host = nullptr; - RasterDarkModeFilter* dark_mode_filter = nullptr; - gfx::RenderingPipeline* main_thread_pipeline = nullptr; - gfx::RenderingPipeline* compositor_thread_pipeline = nullptr; + raw_ptr<MutatorHost> mutator_host = nullptr; + raw_ptr<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 @@ -154,6 +155,26 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Returns the process global unique identifier for this LayerTreeHost. int GetId() const; + // The commit state for the frame being assembled by the compositor host. + const CommitState* pending_commit_state() const { + DCHECK(task_runner_provider_->IsMainThread()); + return pending_commit_state_.get(); + } + + // Additional state required for commit. Unlike pending_commit_state(), this + // state is *not* snapshotted. Both the compositor and the host access a + // single live version, so care must be taken to avoid collisions. + const ThreadUnsafeCommitState& thread_unsafe_commit_state() const { + // TODO(szager): DCHECK(task_runner_provider_->IsMainThread()); + return thread_unsafe_commit_state_; + } + // This should only be used to get a reference to ThreadUnsafeCommitState for + // the purpose of passing to the commit code. All other locations should use + // thread_unsafe_commit_state() instead. + ThreadUnsafeCommitState& GetUnsafeStateForCommit() { + return thread_unsafe_commit_state(); + } + // The current source frame number. This is incremented for each main frame // update(commit) pushed to the compositor thread. The initial frame number // is 0, and it is incremented once commit is completed (which is before the @@ -162,11 +183,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Returns the UIResourceManager used to create UIResources for // UIResourceLayers pushed to the LayerTree. - UIResourceManager* GetUIResourceManager() const; + UIResourceManager* GetUIResourceManager(); // Returns the TaskRunnerProvider used to access the main and compositor // thread task runners. - TaskRunnerProvider* GetTaskRunnerProvider() const; + TaskRunnerProvider* GetTaskRunnerProvider(); // Returns the settings used by this host. These settings are constants given // at startup. @@ -201,6 +222,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { return events_metrics_manager_.saved_events_metrics_count_for_testing(); } + std::unique_ptr<BeginMainFrameMetrics> TakeBeginMainFrameMetrics() { + return std::move(pending_commit_state()->begin_main_frame_metrics); + } + // Visibility and LayerTreeFrameSink ------------------------------- // Sets or gets if the LayerTreeHost is visible. When not visible it will: @@ -254,7 +279,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Returns true after SetNeedsAnimate(), SetNeedsUpdateLayers() or // SetNeedsCommit(), until it is satisfied. - bool RequestedMainFramePendingForTesting() const; + bool RequestedMainFramePending() const; // Requests that the next frame re-chooses crisp raster scales for all layers. void SetNeedsRecalculateRasterScales(); @@ -358,28 +383,21 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // attached to it and will be added/removed along with the root Layer. The // LayerTreeHost retains ownership of a reference to the root Layer. void SetRootLayer(scoped_refptr<Layer> root_layer); - Layer* root_layer() { return root_layer_.get(); } - const Layer* root_layer() const { return root_layer_.get(); } - - struct ViewportPropertyIds { - int overscroll_elasticity_transform = TransformTree::kInvalidNodeId; - ElementId overscroll_elasticity_effect; - int page_scale_transform = TransformTree::kInvalidNodeId; - int inner_scroll = ScrollTree::kInvalidNodeId; - int outer_clip = ClipTree::kInvalidNodeId; - int outer_scroll = ScrollTree::kInvalidNodeId; - }; + Layer* root_layer() { return thread_unsafe_commit_state().root_layer.get(); } + const Layer* root_layer() const { + return thread_unsafe_commit_state().root_layer.get(); + } // Sets the collection of viewport property ids, defined to allow viewport // pinch-zoom etc. on the compositor thread. This is set only on the // main-frame's compositor, i.e., will be unset in OOPIF and UI compositors. void RegisterViewportPropertyIds(const ViewportPropertyIds&); - LayerTreeHost::ViewportPropertyIds ViewportPropertyIdsForTesting() const { - return viewport_property_ids_; + ViewportPropertyIds ViewportPropertyIdsForTesting() const { + return pending_commit_state()->viewport_property_ids; } - Layer* InnerViewportScrollLayerForTesting() const; - Layer* OuterViewportScrollLayerForTesting() const; + Layer* InnerViewportScrollLayerForTesting(); + Layer* OuterViewportScrollLayerForTesting(); ElementId OuterViewportScrollElementId() const; @@ -389,7 +407,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // handles are a UI widget above, and not clipped to, the viewport of this // LayerTreeHost. void RegisterSelection(const LayerSelection& selection); - const LayerSelection& selection() const { return selection_; } + const LayerSelection& selection() const { + return pending_commit_state()->selection; + } // Sets or gets if the client has any scroll event handlers registered. This // allows the threaded compositor to prioritize main frames even when @@ -397,7 +417,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // event handler a chance to be part of each frame. void SetHaveScrollEventHandlers(bool have_event_handlers); bool have_scroll_event_handlers() const { - return have_scroll_event_handlers_; + return pending_commit_state()->have_scroll_event_handlers; } // Set or get what event handlers exist on the layer tree in order to inform @@ -409,7 +429,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { EventListenerProperties event_properties); EventListenerProperties event_listener_properties( EventListenerClass event_class) const { - return event_listener_properties_[static_cast<size_t>(event_class)]; + DCHECK(task_runner_provider_->IsMainThread()); + return pending_commit_state() + ->event_listener_properties[static_cast<size_t>(event_class)]; } // Indicates that its acceptable to throttle the frame rate for this content @@ -438,7 +460,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // compositors. This is specified in device viewport coordinate space. void SetVisualDeviceViewportSize(const gfx::Size&); - gfx::Rect device_viewport_rect() const { return device_viewport_rect_; } + gfx::Rect device_viewport_rect() const { + return pending_commit_state()->device_viewport_rect; + } void UpdateViewportIsMobileOptimized(bool is_viewport_mobile_optimized); @@ -455,47 +479,58 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void SetOverscrollBehavior(const OverscrollBehavior& overscroll_behavior); const OverscrollBehavior& overscroll_behavior() const { - return overscroll_behavior_; + return pending_commit_state()->overscroll_behavior; } void SetPageScaleFactorAndLimits(float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor); - float page_scale_factor() const { return page_scale_factor_; } - float min_page_scale_factor() const { return min_page_scale_factor_; } - float max_page_scale_factor() const { return max_page_scale_factor_; } + float page_scale_factor() const { + return pending_commit_state()->page_scale_factor; + } + float min_page_scale_factor() const { + return pending_commit_state()->min_page_scale_factor; + } + float max_page_scale_factor() const { + return pending_commit_state()->max_page_scale_factor; + } - void set_background_color(SkColor color) { background_color_ = color; } - SkColor background_color() const { return background_color_; } + void set_background_color(SkColor color) { + pending_commit_state()->background_color = color; + } + SkColor background_color() const { + return pending_commit_state()->background_color; + } void set_display_transform_hint(gfx::OverlayTransform hint) { - display_transform_hint_ = hint; + pending_commit_state()->display_transform_hint = hint; } gfx::OverlayTransform display_transform_hint() const { - return display_transform_hint_; + return pending_commit_state()->display_transform_hint; } - void StartPageScaleAnimation(const gfx::Vector2d& target_offset, + void StartPageScaleAnimation(const gfx::Point& target_offset, bool use_anchor, float scale, base::TimeDelta duration); bool HasPendingPageScaleAnimation() const; - float device_scale_factor() const { return device_scale_factor_; } - - void SetRecordingScaleFactor(float recording_scale_factor); - + float device_scale_factor() const { + return pending_commit_state()->device_scale_factor; + } float painted_device_scale_factor() const { - return painted_device_scale_factor_; + return pending_commit_state()->painted_device_scale_factor; } + void SetRecordingScaleFactor(float recording_scale_factor); + // If this LayerTreeHost needs a valid viz::LocalSurfaceId then commits will // be deferred until a valid viz::LocalSurfaceId is provided. void SetLocalSurfaceIdFromParent( const viz::LocalSurfaceId& local_surface_id_from_parent); const viz::LocalSurfaceId& local_surface_id_from_parent() const { - return local_surface_id_from_parent_; + return pending_commit_state()->local_surface_id_from_parent; } // Requests the allocation of a new LocalSurfaceId on the compositor thread. @@ -503,9 +538,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Returns the current state of the new LocalSurfaceId request and resets // the state. - bool TakeNewLocalSurfaceIdRequest(); bool new_local_surface_id_request_for_testing() const { - return new_local_surface_id_request_; + return pending_commit_state()->new_local_surface_id_request; } // Records the amount of time spent performing an update in response to new @@ -516,7 +550,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void SetDisplayColorSpaces( const gfx::DisplayColorSpaces& display_color_spaces); const gfx::DisplayColorSpaces& display_color_spaces() const { - return display_color_spaces_; + return pending_commit_state()->display_color_spaces; } bool HasCompositorDrivenScrollAnimationForTesting() const { @@ -531,11 +565,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void SetExternalPageScaleFactor(float page_scale_factor, bool is_external_pinch_gesture_active); bool is_external_pinch_gesture_active_for_testing() { - return is_external_pinch_gesture_active_; + return pending_commit_state()->is_external_pinch_gesture_active; } // Requests that we force send RenderFrameMetadata with the next frame. - void RequestForceSendMetadata() { force_send_metadata_request_ = true; } + void RequestForceSendMetadata() { + pending_commit_state()->force_send_metadata_request = true; + } // Returns the state of |force_send_metadata_request_| and resets the // variable to false. @@ -543,8 +579,18 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Used externally by blink for setting the PropertyTrees when // UseLayerLists() is true. - PropertyTrees* property_trees() { return &property_trees_; } - const PropertyTrees* property_trees() const { return &property_trees_; } + PropertyTrees* property_trees() { + return &thread_unsafe_commit_state().property_trees; + } + const PropertyTrees* property_trees() const { + return &thread_unsafe_commit_state().property_trees; + } + MutatorHost* mutator_host() { + return thread_unsafe_commit_state().mutator_host; + } + const MutatorHost* mutator_host() const { + return thread_unsafe_commit_state().mutator_host; + } void SetPropertyTreesForTesting(const PropertyTrees* property_trees); @@ -552,60 +598,52 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void RegisterLayer(Layer* layer); void UnregisterLayer(Layer* layer); - Layer* LayerById(int id) const; + Layer* LayerById(int id); bool PaintContent(const LayerList& update_layer_list); bool in_paint_layer_contents() const { return in_paint_layer_contents_; } + bool in_commit() const { + return commit_completion_event_ && !commit_completion_event_->IsSignaled(); + } + void SetHasCopyRequest(bool has_copy_request); bool has_copy_request() const { return has_copy_request_; } void AddSurfaceRange(const viz::SurfaceRange& surface_range); void RemoveSurfaceRange(const viz::SurfaceRange& surface_range); - base::flat_set<viz::SurfaceRange> SurfaceRanges() const; // Marks or unmarks a layer are needing PushPropertiesTo in the next commit. // These are internal methods, called from the Layer itself when changing a // property or completing a PushPropertiesTo. void AddLayerShouldPushProperties(Layer* layer); - void ClearLayersThatShouldPushProperties(); - // The current set of all Layers attached to the LayerTreeHost's tree that - // have been marked as needing PushPropertiesTo in the next commit. - const base::flat_set<Layer*>& LayersThatShouldPushProperties() { - return layers_that_should_push_properties_; - } void SetPageScaleFromImplSide(float page_scale); void SetElasticOverscrollFromImplSide(gfx::Vector2dF elastic_overscroll); - gfx::Vector2dF elastic_overscroll() const { return elastic_overscroll_; } + gfx::Vector2dF elastic_overscroll() const { + return pending_commit_state()->elastic_overscroll; + } // Ensures a HUD layer exists if it is needed, and updates the HUD bounds and // position. If a HUD layer exists but is no longer needed, it is destroyed. void UpdateHudLayer(bool show_hud_info); - HeadsUpDisplayLayer* hud_layer() const { return hud_layer_.get(); } + HeadsUpDisplayLayer* hud_layer() { return hud_layer_.get(); } + const HeadsUpDisplayLayer* hud_layer() const { return hud_layer_.get(); } bool is_hud_layer(const Layer*) const; virtual void SetNeedsFullTreeSync(); - bool needs_full_tree_sync() const { return needs_full_tree_sync_; } - - bool needs_surface_ranges_sync() const { return needs_surface_ranges_sync_; } - void set_needs_surface_ranges_sync(bool needs_surface_ranges_sync) { - needs_surface_ranges_sync_ = needs_surface_ranges_sync; + void ResetNeedsFullTreeSyncForTesting(); + bool needs_full_tree_sync() const { + return pending_commit_state()->needs_full_tree_sync; } void SetPropertyTreesNeedRebuild(); - void PushPropertyTreesTo(LayerTreeImpl* tree_impl); - void PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl); - void PushSurfaceRangesTo(LayerTreeImpl* tree_impl); - void PushLayerTreeHostPropertiesTo(LayerTreeHostImpl* host_impl); - void MoveChangeTrackingToLayers(LayerTreeImpl* tree_impl); - - MutatorHost* mutator_host() const { return mutator_host_; } - // Returns the layer with the given |element_id|. In layer-list mode, only // scrollable layers are registered in this map. - Layer* LayerByElementId(ElementId element_id) const; + Layer* LayerByElementId(ElementId element_id); + const Layer* LayerByElementId(ElementId element_id) const; + void RegisterElement(ElementId element_id, Layer* layer); void UnregisterElement(ElementId element_id); @@ -614,14 +652,17 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void UpdateActiveElements(); void SetElementIdsForTesting(); - void BuildPropertyTreesForTesting(); // Layer iterators. - LayerListIterator begin() const; - LayerListIterator end() const; + LayerListIterator begin(); + LayerListConstIterator begin() const; + LayerListIterator end(); + LayerListConstIterator end() const; LayerListReverseIterator rbegin(); + LayerListReverseConstIterator rbegin() const; LayerListReverseIterator rend(); + LayerListReverseConstIterator rend() const; // LayerTreeHost interface to Proxy. void WillBeginMainFrame(); @@ -630,20 +671,19 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void BeginMainFrameNotExpectedSoon(); void BeginMainFrameNotExpectedUntil(base::TimeTicks time); void AnimateLayers(base::TimeTicks monotonic_frame_begin_time); - void RequestMainFrameUpdate(bool report_cc_metrics); - void FinishCommitOnImplThread( - LayerTreeHostImpl* host_impl, - std::vector<std::unique_ptr<SwapPromise>> swap_promises); - void WillCommit(std::unique_ptr<CompletionEvent> completion); - bool in_commit() const { - return commit_completion_event_ && !commit_completion_event_->IsSignaled(); - } + void RequestMainFrameUpdate(bool report_metrics); + // If has_updates is true, returns the CommitState that will drive the commit. + // Otherwise, returns nullptr. + std::unique_ptr<CommitState> WillCommit( + std::unique_ptr<CompletionEvent> completion, + bool has_updates); + std::unique_ptr<CommitState> ActivateCommitState(); void WaitForCommitCompletion(); - void CommitComplete(); + void CommitComplete(const CommitTimestamps&); void RequestNewLayerTreeFrameSink(); void DidInitializeLayerTreeFrameSink(); void DidFailToInitializeLayerTreeFrameSink(); - virtual std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl( + std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl( LayerTreeHostImplClient* client); void DidLoseLayerTreeFrameSink(); void DidCommitAndDrawFrame() { client_->DidCommitAndDrawFrame(); } @@ -665,26 +705,19 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void NotifyThroughputTrackerResults(CustomTrackerResults results); void NotifyTransitionRequestsFinished( const std::vector<uint32_t>& sequence_ids); - // Called during impl side initialization. - gfx::RenderingPipeline* TakeMainPipeline(); - gfx::RenderingPipeline* TakeCompositorPipeline(); LayerTreeHostClient* client() { return client_; } LayerTreeHostSchedulingClient* scheduling_client() { return scheduling_client_; } - bool gpu_rasterization_histogram_recorded() const { - return gpu_rasterization_histogram_recorded_; - } - void CollectRenderingStats(RenderingStats* stats) const; RenderingStatsInstrumentation* rendering_stats_instrumentation() const { return rendering_stats_instrumentation_.get(); } - Proxy* proxy() const { return proxy_.get(); } + Proxy* proxy() { return proxy_.get(); } bool IsSingleThreaded() const; bool IsThreaded() const; @@ -712,10 +745,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void SetElementTransformMutated(ElementId element_id, ElementListType list_type, const gfx::Transform& transform) override; - void SetElementScrollOffsetMutated( - ElementId element_id, - ElementListType list_type, - const gfx::Vector2dF& scroll_offset) override; + void SetElementScrollOffsetMutated(ElementId element_id, + ElementListType list_type, + const gfx::PointF& scroll_offset) override; void ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map, ElementListType list_type, @@ -730,8 +762,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { PaintWorkletInput::PropertyValue property_value) override {} void ScrollOffsetAnimationFinished() override {} - gfx::Vector2dF GetScrollOffsetForAnimation( - ElementId element_id) const override; void NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state, ElementListType tree_type) override {} @@ -754,26 +784,12 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Captures the on-screen text content, if success, fills the associated // NodeInfo in |content| and return true, otherwise return false. - bool CaptureContent(std::vector<NodeInfo>* content); - - std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics() { - return std::move(begin_main_frame_metrics_); - } - - // Set the the impl proxy when a commit from the main thread begins - // processing. Used in metrics to determine the time spent waiting on thread - // synchronization. - void SetImplCommitStartTime(base::TimeTicks commit_start_time) { - impl_commit_start_time_ = commit_start_time; - } - void SetImplCommitFinishTime(base::TimeTicks commit_finish_time) { - impl_commit_finish_time_ = commit_finish_time; - } + bool CaptureContent(std::vector<NodeInfo>* content) const; void SetDelegatedInkMetadata( std::unique_ptr<gfx::DelegatedInkMetadata> metadata); gfx::DelegatedInkMetadata* DelegatedInkMetadataForTesting() { - return delegated_ink_metadata_.get(); + return pending_commit_state()->delegated_ink_metadata.get(); } void DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay, @@ -782,8 +798,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void AddDocumentTransitionRequest( std::unique_ptr<DocumentTransitionRequest> request); - std::vector<std::unique_ptr<DocumentTransitionRequest>> - TakeDocumentTransitionRequestsForTesting(); + std::vector<base::OnceClosure> TakeDocumentTransitionCallbacksForTesting(); + + // Returns a percentage representing average throughput of last X seconds. + uint32_t GetAverageThroughput() const; protected: LayerTreeHost(InitParams params, CompositorMode mode); @@ -806,9 +824,17 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // is created in CreateLayerTreeHostImpl(). TaskGraphRunner* task_graph_runner() const { return task_graph_runner_; } - void OnCommitForSwapPromises(); + CommitState* pending_commit_state() { + DCHECK(task_runner_provider_->IsMainThread()); + return pending_commit_state_.get(); + } + ThreadUnsafeCommitState& thread_unsafe_commit_state() { + // TODO(szager): DCHECK(task_runner_provider_->IsMainThread()); + // TODO(szager): WaitForCommitCompletion(); + return thread_unsafe_commit_state_; + } - void RecordGpuRasterizationHistogram(const LayerTreeHostImpl* host_impl); + void OnCommitForSwapPromises(); MicroBenchmarkController micro_benchmark_controller_; @@ -827,6 +853,20 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // free of slow-paths before toggling the flag. enum { kNumFramesToConsiderBeforeRemovingSlowPathFlag = 60 }; + virtual std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImplInternal( + LayerTreeHostImplClient* client, + MutatorHost* mutator_host, + const LayerTreeSettings& settings, + TaskRunnerProvider* task_runner_provider, + raw_ptr<RasterDarkModeFilter>& dark_mode_filter, + int id, + raw_ptr<TaskGraphRunner>& task_graph_runner, + scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, + LayerTreeHostSchedulingClient* scheduling_client, + RenderingStatsInstrumentation* rendering_stats_instrumentation, + std::unique_ptr<UkmRecorderFactory>& ukm_recorder_factory, + base::WeakPtr<CompositorDelegateForInput>& compositor_delegate_weak_ptr); + void ApplyViewportChanges(const CompositorCommitData& commit_data); void ApplyPageScaleDeltaFromImplSide(float page_scale_delta); void InitializeProxy(std::unique_ptr<Proxy> proxy); @@ -846,15 +886,17 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { std::unique_ptr<UIResourceManager> ui_resource_manager_; - LayerTreeHostClient* client_; - LayerTreeHostSchedulingClient* scheduling_client_; + raw_ptr<LayerTreeHostClient> client_; + raw_ptr<LayerTreeHostSchedulingClient> scheduling_client_; std::unique_ptr<Proxy> proxy_; std::unique_ptr<TaskRunnerProvider> task_runner_provider_; - int source_frame_number_ = 0U; std::unique_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_; + std::unique_ptr<CommitState> pending_commit_state_; + ThreadUnsafeCommitState thread_unsafe_commit_state_; + SwapPromiseManager swap_promise_manager_; // |current_layer_tree_frame_sink_| can't be updated until we've successfully @@ -866,105 +908,31 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { std::unique_ptr<LayerTreeFrameSink> current_layer_tree_frame_sink_; const LayerTreeSettings settings_; - LayerTreeDebugState debug_state_; bool visible_ = false; - bool gpu_rasterization_histogram_recorded_ = false; - // If set, then page scale animation has completed, but the client hasn't been // notified about it yet. bool did_complete_scale_animation_ = false; - int id_; - bool next_commit_forces_redraw_ = false; - bool next_commit_forces_recalculate_raster_scales_ = false; + const int id_; // Track when we're inside a main frame to see if compositor is being // destroyed midway which causes a crash. crbug.com/654672 bool inside_main_frame_ = false; // State cached until impl side is initialized. - TaskGraphRunner* task_graph_runner_; - gfx::RenderingPipeline* main_thread_pipeline_; - gfx::RenderingPipeline* compositor_thread_pipeline_; - - uint32_t num_consecutive_frames_without_slow_paths_ = 0; - - scoped_refptr<Layer> root_layer_; - - ViewportPropertyIds viewport_property_ids_; - - OverscrollBehavior overscroll_behavior_; + raw_ptr<TaskGraphRunner> task_graph_runner_; - BrowserControlsParams browser_controls_params_; - float top_controls_shown_ratio_ = 0.f; - float bottom_controls_shown_ratio_ = 0.f; - - float device_scale_factor_ = 1.f; - float painted_device_scale_factor_ = 1.f; float recording_scale_factor_ = 1.f; - float page_scale_factor_ = 1.f; - float min_page_scale_factor_ = 1.f; - float max_page_scale_factor_ = 1.f; - float external_page_scale_factor_ = 1.f; - bool is_external_pinch_gesture_active_ = false; // Used to track the out-bound state for ApplyViewportChanges. bool is_pinch_gesture_active_from_impl_ = false; - gfx::DisplayColorSpaces display_color_spaces_; - - bool clear_caches_on_next_commit_ = false; - viz::LocalSurfaceId local_surface_id_from_parent_; - bool new_local_surface_id_request_ = false; - base::TimeDelta visual_properties_update_duration_; uint32_t defer_main_frame_update_count_ = 0; - SkColor background_color_ = SK_ColorWHITE; - - // Display transform hint to tag generated compositor frames. - gfx::OverlayTransform display_transform_hint_ = gfx::OVERLAY_TRANSFORM_NONE; - - LayerSelection selection_; - - gfx::Rect device_viewport_rect_; gfx::Rect visual_device_viewport_intersection_rect_; - gfx::Size visual_device_viewport_size_; - - // Set to true if viewport is mobile optimized by using meta tag - // <meta name="viewport" content="width=device-width"> - // or - // <meta name="viewport" content="initial-scale=1.0"> - bool is_viewport_mobile_optimized_ = false; - - bool prefers_reduced_motion_ = false; - bool may_throttle_if_undrawn_frames_ = true; - bool have_scroll_event_handlers_ = false; - EventListenerProperties event_listener_properties_ - [static_cast<size_t>(EventListenerClass::kLast) + 1]; - - std::unique_ptr<PendingPageScaleAnimation> pending_page_scale_animation_; - - // Whether we have a pending request to force send RenderFrameMetadata with - // the next frame. - bool force_send_metadata_request_ = false; - - PropertyTrees property_trees_; - - bool needs_full_tree_sync_ = true; - - bool needs_surface_ranges_sync_ = false; - - gfx::Vector2dF elastic_overscroll_; scoped_refptr<HeadsUpDisplayLayer> hud_layer_; - // The number of SurfaceLayers that have (fallback,primary) set to - // viz::SurfaceRange. - base::flat_map<viz::SurfaceRange, int> surface_ranges_; - - // Set of layers that need to push properties. - base::flat_set<Layer*> layers_that_should_push_properties_; - // Layer id to Layer map. std::unordered_map<int, Layer*> layer_id_map_; @@ -978,20 +946,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // for every layer during property tree building. bool has_copy_request_ = false; - MutatorHost* mutator_host_; + raw_ptr<MutatorHost> mutator_host_; - RasterDarkModeFilter* dark_mode_filter_; + raw_ptr<RasterDarkModeFilter> dark_mode_filter_; - std::vector<std::pair<PaintImage, base::OnceCallback<void(bool)>>> - queued_image_decodes_; std::unordered_map<int, base::OnceCallback<void(bool)>> pending_image_decodes_; - // Presentation time callbacks requested for the next frame are initially - // added here. - std::vector<PresentationTimeCallbackBuffer::MainCallback> - pending_presentation_time_callbacks_; - struct ScrollAnimationState { ScrollAnimationState(); ~ScrollAnimationState(); @@ -1003,33 +964,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { base::OnceClosure end_notification; } scroll_animation_; - // Latency information for work done in ProxyMain::BeginMainFrame. The - // unique_ptr is allocated in RequestMainFrameUpdate, and passed to Blink's - // LocalFrameView that fills in the fields. This object adds the timing for - // UpdateLayers. CC reads the data during commit, and clears the unique_ptr. - std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics_; - - // The time that the impl thread started processing the most recent commit - // sent from the main thread. Zero if the most recent BeginMainFrame did not - // result in a commit (due to no change in content). - base::TimeTicks impl_commit_start_time_; - base::TimeTicks impl_commit_finish_time_; - std::unique_ptr<CompletionEvent> commit_completion_event_; EventsMetricsManager events_metrics_manager_; - // Metadata required for drawing a delegated ink trail onto the end of a - // stroke. std::unique_ptr was specifically chosen so that it would be cleared - // as it is forwarded along the pipeline to avoid old information incorrectly - // sticking around and potentially being reused. - std::unique_ptr<gfx::DelegatedInkMetadata> delegated_ink_metadata_; - - // A list of document transitions that need to be transported from Blink to - // Viz, as a CompositorFrameTransitionDirective. - std::vector<std::unique_ptr<DocumentTransitionRequest>> - document_transition_requests_; - // A list of callbacks that need to be invoked when they are processed. base::flat_map<uint32_t, base::OnceClosure> document_transition_callbacks_; diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index 9fcde930ea4..44aad4b8eb4 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -25,6 +25,7 @@ struct BeginFrameArgs; namespace cc { struct BeginMainFrameMetrics; +struct CommitState; struct WebVitalMetrics; struct ApplyViewportChangesArgs { @@ -151,7 +152,7 @@ class LayerTreeHostClient { virtual void RequestNewLayerTreeFrameSink() = 0; virtual void DidInitializeLayerTreeFrameSink() = 0; virtual void DidFailToInitializeLayerTreeFrameSink() = 0; - virtual void WillCommit() = 0; + virtual void WillCommit(const CommitState&) = 0; // Report that a commit to the impl thread has completed. The // commit_start_time is the time that the impl thread began processing the // commit, or base::TimeTicks() if the commit did not require action by the diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index f898c7dd71e..11014b76df8 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -34,6 +34,7 @@ #include "base/system/sys_info.h" #include "base/trace_event/traced_value.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "cc/base/devtools_instrumentation.h" #include "cc/base/features.h" #include "cc/base/histograms.h" @@ -276,13 +277,14 @@ DEFINE_SCOPED_UMA_HISTOGRAM_TIMER(PendingTreeRasterDurationHistogramTimer, "Scheduling.%s.PendingTreeRasterDuration") void LayerTreeHostImpl::DidUpdateScrollAnimationCurve() { - // Because we updated the animation target, notify the SwapPromiseMonitor - // to tell it that something happened that will cause a swap in the future. - // This will happen within the scope of the dispatch of a gesture scroll - // update input event. If we don't notify during the handling of the input - // event, the LatencyInfo associated with the input event will not be - // added as a swap promise and we won't get any swap results. - NotifySwapPromiseMonitorsOfSetNeedsRedraw(); + // Because we updated the animation target, notify the + // `LatencyInfoSwapPromiseMonitor` to tell it that something happened that + // will cause a swap in the future. This will happen within the scope of the + // dispatch of a gesture scroll update input event. If we don't notify during + // the handling of the input event, the `LatencyInfo` associated with the + // input event will not be added as a swap promise and we won't get any swap + // results. + NotifyLatencyInfoSwapPromiseMonitors(); events_metrics_manager_.SaveActiveEventMetrics(); } @@ -441,7 +443,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( // LTHI always has an active tree. active_tree_ = std::make_unique<LayerTreeImpl>( - this, new SyncedProperty<ScaleGroup>, new SyncedBrowserControls, + this, new SyncedScale, new SyncedBrowserControls, new SyncedBrowserControls, new SyncedElasticOverscroll); active_tree_->property_trees()->is_active = true; @@ -464,6 +466,17 @@ LayerTreeHostImpl::LayerTreeHostImpl( SetDebugState(settings.initial_debug_state); compositor_frame_reporting_controller_->SetDroppedFrameCounter( &dropped_frame_counter_); + compositor_frame_reporting_controller_->SetFrameSequenceTrackerCollection( + &frame_trackers_); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + const bool is_ui = settings.is_layer_tree_for_ui; + if (is_ui) { + dropped_frame_counter_.EnableReporForUI(); + compositor_frame_reporting_controller_->SetThreadAffectsSmoothness( + FrameInfo::SmoothEffectDrivingThread::kMain, true); + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) dropped_frame_counter_.set_total_counter(&total_frame_counter_); frame_trackers_.set_custom_tracker_results_added_callback( @@ -539,7 +552,7 @@ void LayerTreeHostImpl::BeginMainFrameAborted( bool scroll_and_viewport_changes_synced) { if (reason == CommitEarlyOutReason::ABORTED_NOT_VISIBLE || reason == CommitEarlyOutReason::FINISHED_NO_UPDATES) { - frame_trackers_.NotifyMainFrameCausedNoDamage(args); + frame_trackers_.NotifyMainFrameCausedNoDamage(args, true); } else { frame_trackers_.NotifyMainFrameProcessed(args); } @@ -552,8 +565,11 @@ void LayerTreeHostImpl::BeginMainFrameAborted( if (pending_tree_) { pending_tree_->AppendSwapPromises(std::move(swap_promises)); } else { - for (const auto& swap_promise : swap_promises) - swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE); + for (const auto& swap_promise : swap_promises) { + SwapPromise::DidNotSwapAction action = + swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE); + DCHECK_EQ(action, SwapPromise::DidNotSwapAction::BREAK_PROMISE); + } } } @@ -589,6 +605,77 @@ void LayerTreeHostImpl::BeginCommit(int source_frame_number) { sync_tree()->set_source_frame_number(source_frame_number); } +// This function commits the LayerTreeHost, as represented by CommitState, to an +// impl tree. When modifying this function -- and all code that it calls into +// -- care must be taken to avoid using LayerTreeHost directly (e.g., via +// state.root_layer->layer_tree_host()) as that will likely introduce thread +// safety violations. Any information that is needed from LayerTreeHost should +// instead be plumbed through CommitState (see +// LayerTreeHost::ActivateCommitState() for reference). +void LayerTreeHostImpl::FinishCommit(CommitState& state, + ThreadUnsafeCommitState& unsafe_state) { + TRACE_EVENT0("cc,benchmark", "LayerTreeHostImpl::FinishCommit"); + LayerTreeImpl* tree = sync_tree(); + tree->PullPropertiesFrom(state, unsafe_state); + PullLayerTreeHostPropertiesFrom(state); + + // Transfer image decode requests to the impl thread. + for (auto& entry : state.queued_image_decodes) + QueueImageDecode(entry.first, *entry.second); + + for (auto& benchmark : state.benchmarks) + ScheduleMicroBenchmark(std::move(benchmark)); + + unsafe_state.property_trees.ResetAllChangeTracking(); + + // Dump property trees and layers if run with: + // --vmodule=layer_tree_host=3 + if (VLOG_IS_ON(3)) { + const char* client_name = GetClientNameForMetrics(); + if (!client_name) + client_name = "<unknown client>"; + VLOG(3) << "After finishing (" << client_name + << ") commit on impl, the sync tree:" + << "\nproperty_trees:\n" + << tree->property_trees()->ToString() << "\n" + << "cc::LayerImpls:\n" + << tree->LayerListAsJson(); + } +} + +void LayerTreeHostImpl::PullLayerTreeHostPropertiesFrom( + const CommitState& commit_state) { + // TODO(bokan): The |external_pinch_gesture_active| should not be going + // through the LayerTreeHost but directly from InputHandler to InputHandler. + SetExternalPinchGestureActive(commit_state.is_external_pinch_gesture_active); + if (commit_state.needs_gpu_rasterization_histogram) + RecordGpuRasterizationHistogram(); + SetDebugState(commit_state.debug_state); + SetVisualDeviceViewportSize(commit_state.visual_device_viewport_size); + set_viewport_mobile_optimized(commit_state.is_viewport_mobile_optimized); + SetPrefersReducedMotion(commit_state.prefers_reduced_motion); + SetMayThrottleIfUndrawnFrames(commit_state.may_throttle_if_undrawn_frames); +} + +void LayerTreeHostImpl::RecordGpuRasterizationHistogram() { + bool gpu_rasterization_enabled = false; + if (layer_tree_frame_sink()) { + viz::ContextProvider* compositor_context_provider = + layer_tree_frame_sink()->context_provider(); + if (compositor_context_provider) { + gpu_rasterization_enabled = + compositor_context_provider->ContextCapabilities().gpu_rasterization; + } + } + + // Record how widely gpu rasterization is enabled. + // This number takes device/gpu allowlist/denylist into account. + // Note that we do not consider the forced gpu rasterization mode, which is + // mostly used for debugging purposes. + UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationEnabled", + gpu_rasterization_enabled); +} + void LayerTreeHostImpl::CommitComplete() { TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete"); @@ -937,11 +1024,10 @@ bool LayerTreeHostImpl::PrepareTiles() { return did_prepare_tiles; } -void LayerTreeHostImpl::StartPageScaleAnimation( - const gfx::Vector2d& target_offset, - bool anchor_point, - float page_scale, - base::TimeDelta duration) { +void LayerTreeHostImpl::StartPageScaleAnimation(const gfx::Point& target_offset, + bool anchor_point, + float page_scale, + base::TimeDelta duration) { // Temporary crash logging for https://crbug.com/845097. static bool has_dumped_without_crashing = false; if (settings().is_layer_tree_for_subframe && !has_dumped_without_crashing) { @@ -958,7 +1044,7 @@ void LayerTreeHostImpl::StartPageScaleAnimation( if (!InnerViewportScrollNode()) return; - gfx::Vector2dF scroll_total = active_tree_->TotalScrollOffset(); + gfx::PointF scroll_total = active_tree_->TotalScrollOffset(); gfx::SizeF scrollable_size = active_tree_->ScrollableSize(); gfx::SizeF viewport_size( active_tree_->InnerViewportScrollNode()->container_bounds); @@ -969,11 +1055,11 @@ void LayerTreeHostImpl::StartPageScaleAnimation( scrollable_size); if (anchor_point) { - gfx::Vector2dF anchor(target_offset); + gfx::PointF anchor(target_offset); page_scale_animation_->ZoomWithAnchor(anchor, page_scale, duration.InSecondsF()); } else { - gfx::Vector2dF scaled_target_offset = target_offset; + gfx::PointF scaled_target_offset(target_offset); page_scale_animation_->ZoomTo(scaled_target_offset, page_scale, duration.InSecondsF()); } @@ -987,10 +1073,10 @@ void LayerTreeHostImpl::SetNeedsAnimateInput() { SetNeedsOneBeginImplFrame(); } -std::unique_ptr<SwapPromiseMonitor> +std::unique_ptr<LatencyInfoSwapPromiseMonitor> LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency) { - return base::WrapUnique(new LatencyInfoSwapPromiseMonitor(latency, this)); + return std::make_unique<LatencyInfoSwapPromiseMonitor>(latency, this); } std::unique_ptr<EventsMetricsManager::ScopedMonitor> @@ -1173,15 +1259,15 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { // Create the render passes in dependency order. size_t render_surface_list_size = frame->render_surface_list->size(); for (size_t i = 0; i < render_surface_list_size; ++i) { - size_t surface_index = render_surface_list_size - 1 - i; + const size_t surface_index = render_surface_list_size - 1 - i; RenderSurfaceImpl* render_surface = (*frame->render_surface_list)[surface_index]; const auto& shared_element_id = render_surface->GetDocumentTransitionSharedElementId(); - bool is_root_surface = + const bool is_root_surface = render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId; - bool should_draw_into_render_pass = + const bool should_draw_into_render_pass = is_root_surface || render_surface->contributes_to_drawn_surface() || render_surface->CopyOfOutputRequired() || shared_element_id.valid(); if (should_draw_into_render_pass) @@ -1328,6 +1414,8 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { } frame->use_default_lower_bound_deadline |= append_quads_data.use_default_lower_bound_deadline; + frame->has_shared_element_resources |= + append_quads_data.has_shared_element_resources; } if (GetActivelyScrollingType() != ActivelyScrollingType::kNone && @@ -1623,7 +1711,10 @@ void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) { if (pass->quad_list.empty() && pass->copy_requests.empty() && !pass->subtree_capture_id.is_valid() && pass->filters.IsEmpty() && - pass->backdrop_filters.IsEmpty()) { + pass->backdrop_filters.IsEmpty() && + // TODO(khushalsagar) : Send information about no-op passes to viz to + // retain this optimization for shared elements. See crbug.com/1265178. + !pass->shared_element_resource_id.IsValid()) { // Remove the pass and decrement |i| to counter the for loop's increment, // so we don't skip the next pass in the loop. frame->render_passes.erase(frame->render_passes.begin() + i); @@ -1642,8 +1733,10 @@ void LayerTreeHostImpl::RemoveRenderPasses(FrameData* frame) { // drop references to earlier RenderPasses allowing them to be removed to. viz::CompositorRenderPass* pass = frame->render_passes[frame->render_passes.size() - 2 - i].get(); - if (!pass->copy_requests.empty()) + if (!pass->copy_requests.empty() || + pass->shared_element_resource_id.IsValid()) { continue; + } if (pass_references[pass->id]) continue; @@ -2192,6 +2285,32 @@ void LayerTreeHostImpl::OnCanDrawStateChangedForTree() { client_->OnCanDrawStateChanged(CanDraw()); } +viz::RegionCaptureBounds LayerTreeHostImpl::CollectRegionCaptureBounds() { + viz::RegionCaptureBounds bounds; + for (const auto* layer : base::Reversed(*active_tree())) { + if (!layer->capture_bounds()) + continue; + + for (const auto& bounds_pair : layer->capture_bounds()->bounds()) { + // Perform transformation from the coordinate system of this |layer| + // to that of the root render surface. + gfx::Rect bounds_in_screen_space = MathUtil::ProjectEnclosingClippedRect( + layer->ScreenSpaceTransform(), bounds_pair.second); + + const RenderSurfaceImpl* root_surface = + active_tree()->RootRenderSurface(); + const gfx::Rect content_rect_in_screen_space = gfx::ToEnclosedRect( + MathUtil::MapClippedRect(root_surface->screen_space_transform(), + root_surface->DrawableContentRect())); + + // The transformed bounds may be partially or entirely offscreen. + bounds_in_screen_space.Intersect(content_rect_in_screen_space); + bounds.Set(bounds_pair.first, bounds_in_screen_space); + } + } + return bounds; +} + viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { viz::CompositorFrameMetadata metadata; metadata.frame_token = ++next_frame_token_; @@ -2248,6 +2367,8 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { delegated_ink_metadata->ToString()); metadata.delegated_ink_metadata = std::move(delegated_ink_metadata); } + + metadata.capture_bounds = CollectRegionCaptureBounds(); return metadata; } @@ -2298,7 +2419,7 @@ RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata( if (last_draw_render_frame_metadata_) { const float last_root_scroll_offset_y = last_draw_render_frame_metadata_->root_scroll_offset - .value_or(gfx::Vector2dF()) + .value_or(gfx::PointF()) .y(); const float new_root_scroll_offset_y = @@ -2366,6 +2487,8 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { DCHECK(!resourceless_software_draw_); frame_trackers_.NotifyImplFrameCausedNoDamage(frame->begin_frame_ack); + frame_trackers_.NotifyMainFrameCausedNoDamage( + frame->origin_begin_main_frame_args, false); TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoDamage", TRACE_EVENT_SCOPE_THREAD); active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS); active_tree()->ResetAllChangeTracking(); @@ -2514,7 +2637,8 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( viz::CompositorFrameMetadata metadata = MakeCompositorFrameMetadata(); - std::map<DocumentTransitionSharedElementId, viz::CompositorRenderPassId> + std::map<DocumentTransitionSharedElementId, + DocumentTransitionRequest::SharedElementInfo> shared_element_render_pass_id_map; for (RenderSurfaceImpl* render_surface : *frame->render_surface_list) { const auto& shared_element_id = @@ -2523,8 +2647,10 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( continue; DCHECK( !base::Contains(shared_element_render_pass_id_map, shared_element_id)); - shared_element_render_pass_id_map[shared_element_id] = + shared_element_render_pass_id_map[shared_element_id].render_pass_id = render_surface->render_pass_id(); + shared_element_render_pass_id_map[shared_element_id].resource_id = + render_surface->OwningEffectNode()->shared_element_resource_id; } for (auto& request : active_tree_->TakeDocumentTransitionRequests()) { @@ -2533,6 +2659,7 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( } PopulateMetadataContentColorUsage(frame, &metadata); + metadata.has_shared_element_resources = frame->has_shared_element_resources; metadata.may_contain_video = frame->may_contain_video; metadata.deadline = viz::FrameDeadline( CurrentBeginFrameArgs().frame_time, @@ -3034,9 +3161,8 @@ absl::optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { continue; } - gfx::Rect content_rect( - gfx::ScaleToEnclosingRect(gfx::Rect(surface_layer->bounds()), - device_scale_factor, device_scale_factor)); + gfx::Rect content_rect(gfx::ScaleToEnclosingRect( + gfx::Rect(surface_layer->bounds()), device_scale_factor)); gfx::Rect layer_screen_space_rect = MathUtil::MapEnclosingClippedRect( surface_layer->ScreenSpaceTransform(), @@ -3418,16 +3544,13 @@ void LayerTreeHostImpl::SetVisible(bool visible) { } void LayerTreeHostImpl::SetNeedsOneBeginImplFrame() { - // TODO(miletus): This is just the compositor-thread-side call to the - // SwapPromiseMonitor to say something happened that may cause a swap in the - // future. The name should not refer to SetNeedsRedraw but it does for now. - NotifySwapPromiseMonitorsOfSetNeedsRedraw(); + NotifyLatencyInfoSwapPromiseMonitors(); events_metrics_manager_.SaveActiveEventMetrics(); client_->SetNeedsOneBeginImplFrameOnImplThread(); } void LayerTreeHostImpl::SetNeedsRedraw() { - NotifySwapPromiseMonitorsOfSetNeedsRedraw(); + NotifyLatencyInfoSwapPromiseMonitors(); events_metrics_manager_.SaveActiveEventMetrics(); client_->SetNeedsRedrawOnImplThread(); } @@ -3628,6 +3751,14 @@ LayerTreeHostImpl::TakeFinishedTransitionRequestSequenceIds() { return result; } +void LayerTreeHostImpl::ClearHistory() { + client_->ClearHistory(); +} + +size_t LayerTreeHostImpl::CommitDurationSampleCountForTesting() const { + return client_->CommitDurationSampleCountForTesting(); // IN-TEST +} + void LayerTreeHostImpl::ClearCaches() { // It is safe to clear the decode policy tracking on navigations since it // comes with an invalidation and the image ids are never re-used. @@ -3882,35 +4013,38 @@ float LayerTreeHostImpl::CurrentBottomControlsShownRatio() const { return active_tree_->CurrentBottomControlsShownRatio(); } -gfx::Vector2dF LayerTreeHostImpl::ViewportScrollOffset() const { +gfx::PointF LayerTreeHostImpl::ViewportScrollOffset() const { return viewport_->TotalScrollOffset(); } -bool LayerTreeHostImpl::AutoScrollAnimationCreate(const ScrollNode& scroll_node, - const gfx::Vector2dF& delta, - float autoscroll_velocity) { - return ScrollAnimationCreateInternal(scroll_node, delta, base::TimeDelta(), - autoscroll_velocity); +void LayerTreeHostImpl::AutoScrollAnimationCreate( + const ScrollNode& scroll_node, + const gfx::PointF& target_offset, + float autoscroll_velocity) { + // Start the animation one full frame in. Without any offset, the animation + // doesn't start until next frame, increasing latency, and preventing our + // input latency tracking architecture from working. + base::TimeDelta animation_start_offset = CurrentBeginFrameArgs().interval; + + ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; + gfx::PointF current_offset = + scroll_tree.current_scroll_offset(scroll_node.element_id); + + mutator_host_->ImplOnlyAutoScrollAnimationCreate( + scroll_node.element_id, target_offset, current_offset, + autoscroll_velocity, animation_start_offset); + + SetNeedsOneBeginImplFrame(); } bool LayerTreeHostImpl::ScrollAnimationCreate(const ScrollNode& scroll_node, const gfx::Vector2dF& delta, base::TimeDelta delayed_by) { - return ScrollAnimationCreateInternal(scroll_node, delta, delayed_by, - absl::nullopt); -} - -bool LayerTreeHostImpl::ScrollAnimationCreateInternal( - const ScrollNode& scroll_node, - const gfx::Vector2dF& delta, - base::TimeDelta delayed_by, - absl::optional<float> autoscroll_velocity) { ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; const float kEpsilon = 0.1f; bool scroll_animated = - (std::abs(delta.x()) > kEpsilon || std::abs(delta.y()) > kEpsilon) || - autoscroll_velocity; + std::abs(delta.x()) > kEpsilon || std::abs(delta.y()) > kEpsilon; if (!scroll_animated) { scroll_tree.ScrollBy(scroll_node, delta, active_tree()); TRACE_EVENT_INSTANT0("cc", "no scroll animation due to small delta", @@ -3918,9 +4052,9 @@ bool LayerTreeHostImpl::ScrollAnimationCreateInternal( return false; } - gfx::Vector2dF current_offset = + gfx::PointF current_offset = scroll_tree.current_scroll_offset(scroll_node.element_id); - gfx::Vector2dF target_offset = scroll_tree.ClampScrollOffsetToLimits( + gfx::PointF target_offset = scroll_tree.ClampScrollOffsetToLimits( current_offset + delta, scroll_node); // Start the animation one full frame in. Without any offset, the animation @@ -3928,15 +4062,9 @@ bool LayerTreeHostImpl::ScrollAnimationCreateInternal( // input latency tracking architecture from working. base::TimeDelta animation_start_offset = CurrentBeginFrameArgs().interval; - if (autoscroll_velocity) { - mutator_host_->ImplOnlyAutoScrollAnimationCreate( - scroll_node.element_id, delta, current_offset, - autoscroll_velocity.value(), animation_start_offset); - } else { - mutator_host_->ImplOnlyScrollAnimationCreate( - scroll_node.element_id, target_offset, current_offset, delayed_by, - animation_start_offset); - } + mutator_host_->ImplOnlyScrollAnimationCreate( + scroll_node.element_id, target_offset, current_offset, delayed_by, + animation_start_offset); SetNeedsOneBeginImplFrame(); @@ -4099,15 +4227,15 @@ bool LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) { if (!page_scale_animation_) return false; - gfx::Vector2dF scroll_total = active_tree_->TotalScrollOffset(); + gfx::PointF scroll_total = active_tree_->TotalScrollOffset(); if (!page_scale_animation_->IsAnimationStarted()) page_scale_animation_->StartAnimation(monotonic_time); active_tree_->SetPageScaleOnActiveTree( page_scale_animation_->PageScaleFactorAtTime(monotonic_time)); - gfx::Vector2dF next_scroll = - gfx::Vector2dF(page_scale_animation_->ScrollOffsetAtTime(monotonic_time)); + gfx::PointF next_scroll = + page_scale_animation_->ScrollOffsetAtTime(monotonic_time); viewport().ScrollByInnerFirst(next_scroll - scroll_total); @@ -4732,18 +4860,19 @@ void LayerTreeHostImpl::ScheduleMicroBenchmark( micro_benchmark_controller_.ScheduleRun(std::move(benchmark)); } -void LayerTreeHostImpl::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) { - swap_promise_monitor_.insert(monitor); +void LayerTreeHostImpl::InsertLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor) { + latency_info_swap_promise_monitor_.insert(monitor); } -void LayerTreeHostImpl::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) { - swap_promise_monitor_.erase(monitor); +void LayerTreeHostImpl::RemoveLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor) { + latency_info_swap_promise_monitor_.erase(monitor); } -void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfSetNeedsRedraw() { - auto it = swap_promise_monitor_.begin(); - for (; it != swap_promise_monitor_.end(); it++) - (*it)->OnSetNeedsRedrawOnImpl(); +void LayerTreeHostImpl::NotifyLatencyInfoSwapPromiseMonitors() { + for (auto* monitor : latency_info_swap_promise_monitor_) + monitor->OnSetNeedsRedrawOnImpl(); } bool LayerTreeHostImpl::IsElementInPropertyTrees( @@ -4765,7 +4894,7 @@ void LayerTreeHostImpl::SetMutatorsNeedRebuildPropertyTrees() {} void LayerTreeHostImpl::SetTreeLayerScrollOffsetMutated( ElementId element_id, LayerTreeImpl* tree, - const gfx::Vector2dF& scroll_offset) { + const gfx::PointF& scroll_offset) { if (!tree) return; @@ -4847,7 +4976,7 @@ void LayerTreeHostImpl::SetElementTransformMutated( void LayerTreeHostImpl::SetElementScrollOffsetMutated( ElementId element_id, ElementListType list_type, - const gfx::Vector2dF& scroll_offset) { + const gfx::PointF& scroll_offset) { if (list_type == ElementListType::ACTIVE) { SetTreeLayerScrollOffsetMutated(element_id, active_tree(), scroll_offset); ShowScrollbarsForImplScroll(element_id); @@ -4902,16 +5031,6 @@ void LayerTreeHostImpl::NotifyAnimationWorkletStateChange( } } -gfx::Vector2dF LayerTreeHostImpl::GetScrollOffsetForAnimation( - ElementId element_id) const { - if (active_tree()) { - return active_tree()->property_trees()->scroll_tree.current_scroll_offset( - element_id); - } - - return gfx::Vector2dF(); -} - bool LayerTreeHostImpl::CommitToActiveTree() const { return settings_.commit_to_active_tree; } diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 47fab7de3a4..0a76f247dd6 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,10 +17,11 @@ #include "base/callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" -#include "base/containers/mru_cache.h" +#include "base/containers/lru_cache.h" #include "base/memory/memory_pressure_listener.h" +#include "base/memory/raw_ptr.h" #include "base/memory/shared_memory_mapping.h" -#include "base/sequenced_task_runner.h" +#include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "cc/base/synced_property.h" #include "cc/benchmarks/micro_benchmark_controller_impl.h" @@ -70,6 +71,7 @@ #include "components/viz/common/quads/compositor_render_pass.h" #include "components/viz/common/surfaces/child_local_surface_id_allocator.h" #include "components/viz/common/surfaces/local_surface_id.h" +#include "components/viz/common/surfaces/region_capture_bounds.h" #include "components/viz/common/surfaces/surface_id.h" #include "components/viz/common/surfaces/surface_range.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -77,7 +79,7 @@ #include "ui/gfx/geometry/rect.h" namespace gfx { -class Vector2dF; +class PointF; } namespace viz { @@ -97,6 +99,7 @@ class EvictionTilePriorityQueue; class DroppedFrameCounter; class ImageAnimationController; class LCDTextMetricsReporter; +class LatencyInfoSwapPromiseMonitor; class LayerImpl; class LayerTreeFrameSink; class LayerTreeImpl; @@ -112,7 +115,6 @@ class RenderFrameMetadataObserver; class RenderingStatsInstrumentation; class ResourcePool; class SwapPromise; -class SwapPromiseMonitor; class SynchronousTaskGraphRunner; class TaskGraphRunner; class UIResourceBitmap; @@ -194,6 +196,10 @@ class LayerTreeHostImplClient { virtual void FrameSinksToThrottleUpdated( const base::flat_set<viz::FrameSinkId>& ids) = 0; + virtual void ClearHistory() = 0; + + virtual size_t CommitDurationSampleCountForTesting() const = 0; + protected: virtual ~LayerTreeHostImplClient() = default; }; @@ -231,7 +237,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, absl::optional<uint32_t> deadline_in_frames; bool use_default_lower_bound_deadline = false; viz::CompositorRenderPassList render_passes; - const RenderSurfaceList* render_surface_list = nullptr; + raw_ptr<const RenderSurfaceList> render_surface_list = nullptr; LayerImplList will_draw_layers; bool has_no_damage = false; bool may_contain_video = false; @@ -239,6 +245,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // The original BeginFrameArgs that triggered the latest update from the // main thread. viz::BeginFrameArgs origin_begin_main_frame_args; + bool has_shared_element_resources = false; }; // A struct of data for a single UIResource, including the backing @@ -288,13 +295,13 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, ThreadedInputHandler& GetInputHandler(); const ThreadedInputHandler& GetInputHandler() const; - void StartPageScaleAnimation(const gfx::Vector2d& target_offset, + void StartPageScaleAnimation(const gfx::Point& target_offset, bool anchor_point, float page_scale, base::TimeDelta duration); void SetNeedsAnimateInput(); - std::unique_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( - ui::LatencyInfo* latency); + std::unique_ptr<LatencyInfoSwapPromiseMonitor> + CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency); std::unique_ptr<EventsMetricsManager::ScopedMonitor> GetScopedEventMetricsMonitor( EventsMetricsManager::ScopedMonitor::DoneCallback done_callback); @@ -309,7 +316,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, float bottom_ratio) override; float CurrentTopControlsShownRatio() const override; float CurrentBottomControlsShownRatio() const override; - gfx::Vector2dF ViewportScrollOffset() const override; + gfx::PointF ViewportScrollOffset() const override; void DidChangeBrowserControlsPosition() override; void DidObserveScrollDelay(base::TimeDelta scroll_delay, base::TimeTicks scroll_timestamp); @@ -346,8 +353,12 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, const viz::BeginFrameArgs& commit_args, const BeginMainFrameMetrics* begin_main_frame_metrics); virtual void BeginCommit(int source_frame_number); + virtual void FinishCommit(CommitState& commit_state, + ThreadUnsafeCommitState& unsafe_state); virtual void CommitComplete(); virtual void UpdateAnimationState(bool start_ready_animations); + void PullLayerTreeHostPropertiesFrom(const CommitState&); + void RecordGpuRasterizationHistogram(); bool Mutate(base::TimeTicks monotonic_time); void ActivateAnimations(); void Animate(); @@ -420,7 +431,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, void SetTreeLayerScrollOffsetMutated(ElementId element_id, LayerTreeImpl* tree, - const gfx::Vector2dF& scroll_offset); + const gfx::PointF& scroll_offset); void SetNeedUpdateGpuRasterizationStatus(); bool NeedUpdateGpuRasterizationStatusForTesting() const { return need_update_gpu_rasterization_status_; @@ -444,10 +455,9 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, void SetElementTransformMutated(ElementId element_id, ElementListType list_type, const gfx::Transform& transform) override; - void SetElementScrollOffsetMutated( - ElementId element_id, - ElementListType list_type, - const gfx::Vector2dF& scroll_offset) override; + void SetElementScrollOffsetMutated(ElementId element_id, + ElementListType list_type, + const gfx::PointF& scroll_offset) override; void ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, @@ -460,8 +470,6 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, PaintWorkletInput::PropertyValue property_value) override; void ScrollOffsetAnimationFinished() override; - gfx::Vector2dF GetScrollOffsetForAnimation( - ElementId element_id) const override; void NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state, ElementListType tree_type) override; @@ -748,6 +756,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, void ScheduleMicroBenchmark(std::unique_ptr<MicroBenchmarkImpl> benchmark); + viz::RegionCaptureBounds CollectRegionCaptureBounds(); + viz::CompositorFrameMetadata MakeCompositorFrameMetadata(); RenderFrameMetadata MakeRenderFrameMetadata(FrameData* frame); @@ -759,12 +769,14 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, return viewport_rect_for_tile_priority_; } - // When a SwapPromiseMonitor is created on the impl thread, it calls - // InsertSwapPromiseMonitor() to register itself with LayerTreeHostImpl. - // When the monitor is destroyed, it calls RemoveSwapPromiseMonitor() - // to unregister itself. - void InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor); - void RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor); + // When a `LatencyInfoSwapPromiseMonitor` is created on the impl thread, it + // calls `InsertLatencyInfoSwapPromiseMonitor()` to register itself with + // `LayerTreeHostImpl`. When the monitor is destroyed, it calls + // `RemoveLatencyInfoSwapPromiseMonitor()` to unregister itself. + void InsertLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor); + void RemoveLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor); // TODO(weiliangc): Replace RequiresHighResToDraw with scheduler waits for // ReadyToDraw. crbug.com/469175 @@ -794,8 +806,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, bool ScrollAnimationCreate(const ScrollNode& scroll_node, const gfx::Vector2dF& scroll_amount, base::TimeDelta delayed_by); - bool AutoScrollAnimationCreate(const ScrollNode& scroll_node, - const gfx::Vector2dF& scroll_amount, + void AutoScrollAnimationCreate(const ScrollNode& scroll_node, + const gfx::PointF& target_offset, float autoscroll_velocity); void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator); @@ -814,6 +826,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // Returns all of the transition request sequence ids that were finished. std::vector<uint32_t> TakeFinishedTransitionRequestSequenceIds(); + void ClearHistory(); + size_t CommitDurationSampleCountForTesting() const; void ClearCaches(); void UpdateImageDecodingHints( @@ -904,9 +918,9 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // Removes empty or orphan RenderPasses from the frame. static void RemoveRenderPasses(FrameData* frame); - LayerTreeHostImplClient* const client_; - LayerTreeHostSchedulingClient* const scheduling_client_; - TaskRunnerProvider* const task_runner_provider_; + const raw_ptr<LayerTreeHostImplClient> client_; + const raw_ptr<LayerTreeHostSchedulingClient> scheduling_client_; + const raw_ptr<TaskRunnerProvider> task_runner_provider_; BeginFrameTracker current_begin_frame_tracker_; @@ -916,10 +930,6 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, private: void CollectScrollbarUpdatesForCommit( CompositorCommitData* commit_data) const; - bool ScrollAnimationCreateInternal(const ScrollNode& scroll_node, - const gfx::Vector2dF& delta, - base::TimeDelta delayed_by, - absl::optional<float> autoscroll_velocity); void CleanUpTileManagerResources(); void CreateTileManagerResources(); @@ -986,7 +996,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, const gpu::SyncToken& sync_token, bool lost); - void NotifySwapPromiseMonitorsOfSetNeedsRedraw(); + void NotifyLatencyInfoSwapPromiseMonitors(); private: void SetContextVisibility(bool is_visible); @@ -1050,7 +1060,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // // A pointer used for communicating with and submitting output to the display // compositor. - LayerTreeFrameSink* layer_tree_frame_sink_ = nullptr; + raw_ptr<LayerTreeFrameSink> layer_tree_frame_sink_ = nullptr; // The maximum size (either width or height) that any texture can be. Also // holds a reasonable value for software compositing bitmaps. int max_texture_size_ = 0; @@ -1137,7 +1147,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_; + const raw_ptr<RasterDarkModeFilter> dark_mode_filter_; // Map from scroll element ID to scrollbar animation controller. // There is one animation controller per pair of overlay scrollbars. @@ -1146,7 +1156,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, ElementIdHash> scrollbar_animation_controllers_; - RenderingStatsInstrumentation* rendering_stats_instrumentation_; + raw_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_; MicroBenchmarkControllerImpl micro_benchmark_controller_; std::unique_ptr<SynchronousTaskGraphRunner> single_thread_synchronous_task_graph_runner_; @@ -1154,10 +1164,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // Optional callback to notify of new tree activations. base::RepeatingClosure tree_activation_callback_; - TaskGraphRunner* task_graph_runner_; + raw_ptr<TaskGraphRunner> task_graph_runner_; int id_; - std::set<SwapPromiseMonitor*> swap_promise_monitor_; + std::set<LatencyInfoSwapPromiseMonitor*> latency_info_swap_promise_monitor_; bool requires_high_res_to_draw_ = false; bool is_likely_to_require_a_draw_ = false; @@ -1286,7 +1296,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient, // 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_; + mutable base::LRUCache<gfx::ColorSpace, bool> contains_srgb_cache_; // When enabled, calculates which frame sinks can be throttled based on // some pre-defined criteria. diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index a904c8aeba6..873ef092d9a 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -18,6 +18,7 @@ #include "base/location.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" @@ -49,6 +50,7 @@ #include "cc/resources/ui_resource_bitmap.h" #include "cc/resources/ui_resource_manager.h" #include "cc/test/animation_test_common.h" +#include "cc/test/fake_frame_info.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_layer_tree_host_impl.h" @@ -57,9 +59,9 @@ #include "cc/test/fake_raster_source.h" #include "cc/test/fake_recording_source.h" #include "cc/test/fake_video_frame_provider.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" #include "cc/test/layer_tree_test.h" +#include "cc/test/mock_latency_info_swap_promise_monitor.h" #include "cc/test/skia_common.h" #include "cc/test/test_layer_tree_frame_sink.h" #include "cc/test/test_paint_worklet_layer_painter.h" @@ -85,6 +87,7 @@ #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/region_capture_bounds.h" #include "components/viz/service/display/gl_renderer.h" #include "components/viz/service/display/skia_output_surface.h" #include "components/viz/test/begin_frame_args_test.h" @@ -98,10 +101,13 @@ #include "third_party/skia/include/core/SkMallocPixelRef.h" #include "ui/events/types/scroll_input_type.h" #include "ui/gfx/geometry/angle_conversions.h" +#include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform_operations.h" #include "ui/gfx/geometry/vector2d_conversions.h" +#include "ui/latency/latency_info.h" #define EXPECT_SCOPED(statements) \ { \ @@ -115,6 +121,7 @@ using ::testing::AnyNumber; using ::testing::AtLeast; using ::testing::Mock; using ::testing::Return; +using ::testing::StrictMock; using ScrollThread = cc::InputHandler::ScrollThread; @@ -125,6 +132,8 @@ struct FrameTimingDetails; namespace cc { namespace { +constexpr gfx::Size kDefaultLayerSize(100, 100); + viz::SurfaceId MakeSurfaceId(const viz::FrameSinkId& frame_sink_id, uint32_t parent_id) { return viz::SurfaceId( @@ -284,6 +293,8 @@ class LayerTreeHostImplTest : public testing::Test, bool IsInSynchronousComposite() const override { return false; } void FrameSinksToThrottleUpdated( const base::flat_set<viz::FrameSinkId>& ids) override {} + void ClearHistory() override {} + size_t CommitDurationSampleCountForTesting() const override { return 0; } void set_reduce_memory_result(bool reduce_memory_result) { reduce_memory_result_ = reduce_memory_result; } @@ -342,7 +353,8 @@ class LayerTreeHostImplTest : public testing::Test, return static_cast<T*>(root); } - LayerImpl* SetupDefaultRootLayer(const gfx::Size& viewport_size) { + LayerImpl* SetupDefaultRootLayer( + const gfx::Size& viewport_size = kDefaultLayerSize) { return SetupRootLayer<LayerImpl>(host_impl_->active_tree(), viewport_size); } @@ -750,7 +762,7 @@ class LayerTreeHostImplTest : public testing::Test, OuterViewportScrollLayer(), gfx::Size(100, 100), overflow_size); SnapContainerData container_data( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 200, 200), gfx::Vector2dF(300, 300)); + gfx::RectF(0, 0, 200, 200), gfx::PointF(300, 300)); SnapAreaData area_data(ScrollSnapAlign(SnapAlignment::kStart), gfx::RectF(50, 50, 100, 100), false, ElementId(10)); container_data.AddSnapAreaData(area_data); @@ -769,8 +781,7 @@ class LayerTreeHostImplTest : public testing::Test, layer_tree_impl->SetRootLayerForTesting(nullptr); layer_tree_impl->DetachLayers(); layer_tree_impl->property_trees()->clear(); - layer_tree_impl->SetViewportPropertyIds( - LayerTreeImpl::ViewportPropertyIds()); + layer_tree_impl->SetViewportPropertyIds(ViewportPropertyIds()); } void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor); @@ -921,8 +932,8 @@ class TestInputHandlerClient : public InputHandlerClient { void ReconcileElasticOverscrollAndRootScroll() override {} void SetPrefersReducedMotion(bool prefers_reduced_motion) override {} void UpdateRootLayerStateForSynchronousInputHandler( - const gfx::Vector2dF& total_scroll_offset, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& total_scroll_offset, + const gfx::PointF& max_scroll_offset, const gfx::SizeF& scrollable_size, float page_scale_factor, float min_page_scale_factor, @@ -939,9 +950,9 @@ class TestInputHandlerClient : public InputHandlerClient { void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override {} void DeliverInputForHighLatencyMode() override {} - gfx::Vector2dF last_set_scroll_offset() { return last_set_scroll_offset_; } + gfx::PointF last_set_scroll_offset() { return last_set_scroll_offset_; } - gfx::Vector2dF max_scroll_offset() const { return max_scroll_offset_; } + gfx::PointF max_scroll_offset() const { return max_scroll_offset_; } gfx::SizeF scrollable_size() const { return scrollable_size_; } @@ -952,8 +963,8 @@ class TestInputHandlerClient : public InputHandlerClient { float max_page_scale_factor() const { return max_page_scale_factor_; } private: - gfx::Vector2dF last_set_scroll_offset_; - gfx::Vector2dF max_scroll_offset_; + gfx::PointF last_set_scroll_offset_; + gfx::PointF max_scroll_offset_; gfx::SizeF scrollable_size_; float page_scale_factor_; float min_page_scale_factor_; @@ -1079,7 +1090,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) { } TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) { - gfx::Vector2dF scroll_offset(20, 30); + gfx::PointF scroll_offset(20, 30); gfx::Vector2dF scroll_delta(11, -15); auto* root = SetupDefaultRootLayer(gfx::Size(110, 110)); @@ -1199,7 +1210,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollUpdateAndEndNoOpWithoutBegin) { UpdateState(gfx::Point(), gfx::Vector2d(0, 10), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 10), + EXPECT_POINTF_EQ(gfx::PointF(0, 10), CurrentScrollOffset(OuterViewportScrollLayer())); GetInputHandler().ScrollEnd(); @@ -1461,7 +1472,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PropertyTrees pending_property_trees; pending_property_trees.sequence_number = host_impl_->active_tree()->property_trees()->sequence_number + 1; - host_impl_->pending_tree()->SetPropertyTrees(&pending_property_trees); + host_impl_->pending_tree()->SetPropertyTrees(pending_property_trees); SetupRootLayer<LayerImpl>(host_impl_->pending_tree(), gfx::Size(100, 100)); host_impl_->ActivateSyncTree(); @@ -2488,7 +2499,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapOnX) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); @@ -2515,7 +2526,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapOnX) { start_time + base::Milliseconds(1000)); EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(50, 0), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(ElementId(10), ElementId()), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); } @@ -2532,7 +2543,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapOnY) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); @@ -2559,7 +2570,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapOnY) { start_time + base::Milliseconds(1000)); EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 50), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 50), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(ElementId(), ElementId(10)), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); } @@ -2576,7 +2587,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapOnBoth) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); @@ -2602,7 +2613,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapOnBoth) { start_time + base::Milliseconds(1000)); EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(ElementId(10), ElementId(10)), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); } @@ -2656,7 +2667,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapAfterAnimatedScroll) { BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(50)); EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing()); - gfx::Vector2dF current_offset = CurrentScrollOffset(overflow); + gfx::PointF current_offset = CurrentScrollOffset(overflow); EXPECT_LT(0, current_offset.x()); EXPECT_GT(20, current_offset.x()); EXPECT_LT(0, current_offset.y()); @@ -2676,7 +2687,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollSnapAfterAnimatedScroll) { // Finish the animation. BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(1500)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(overflow)); EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing()); EXPECT_EQ(TargetSnapAreaElementIds(ElementId(10), ElementId(10)), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); @@ -2694,7 +2705,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationTargetUpdated) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel) @@ -2714,7 +2725,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationTargetUpdated) { EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); - gfx::Vector2dF current_offset = CurrentScrollOffset(overflow); + gfx::PointF current_offset = CurrentScrollOffset(overflow); EXPECT_GT(50, current_offset.y()); EXPECT_LT(20, current_offset.y()); @@ -2745,7 +2756,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationTargetUpdated) { // TargetSnapAreaElementIds. EXPECT_EQ(TargetSnapAreaElementIds(ElementId(), ElementId(10)), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 50), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 50), CurrentScrollOffset(overflow)); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationCancelledByScroll) { @@ -2760,7 +2771,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationCancelledByScroll) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel) @@ -2780,7 +2791,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationCancelledByScroll) { EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); - gfx::Vector2dF current_offset = CurrentScrollOffset(overflow); + gfx::PointF current_offset = CurrentScrollOffset(overflow); EXPECT_GT(50, current_offset.x()); EXPECT_LT(20, current_offset.x()); EXPECT_EQ(0, current_offset.y()); @@ -2800,7 +2811,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SnapAnimationCancelledByScroll) { BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(150)); - EXPECT_VECTOR_EQ(current_offset, CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(current_offset, CurrentScrollOffset(overflow)); BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(1000)); // Ensure that the snap target was not updated at the end of the scroll @@ -2822,7 +2833,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // There is a snap target at 50, scroll to it directly. GetInputHandler().ScrollUpdate( @@ -2850,7 +2861,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(100)); EXPECT_FALSE(GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(50, 0), CurrentScrollOffset(overflow)); EXPECT_EQ(TargetSnapAreaElementIds(ElementId(10), ElementId()), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); } @@ -2871,20 +2882,20 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // Should be (20, 20) in the scroller's coordinate. InputHandlerScrollResult result = GetInputHandler().ScrollUpdate( UpdateState(pointer_position, delta, ui::ScrollInputType::kWheel).get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(overflow)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset); + EXPECT_POINTF_EQ(gfx::PointF(20, 20), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(4, 4), result.current_visual_offset); - gfx::Vector2dF initial_offset, target_offset; + gfx::PointF initial_offset, target_offset; EXPECT_TRUE(GetInputHandler().GetSnapFlingInfoAndSetAnimatingSnapTarget( gfx::Vector2dF(10, 10), &initial_offset, &target_offset)); EXPECT_TRUE(GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), initial_offset); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), target_offset); + EXPECT_POINTF_EQ(gfx::PointF(4, 4), initial_offset); + EXPECT_POINTF_EQ(gfx::PointF(10, 10), target_offset); // Snap targets shouldn't be set until the fling animation is complete. EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); @@ -2911,20 +2922,20 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // Should be (20, 20) in the scroller's coordinate. InputHandlerScrollResult result = GetInputHandler().ScrollUpdate( UpdateState(pointer_position, delta, ui::ScrollInputType::kWheel).get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(overflow)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), result.current_visual_offset); + EXPECT_POINTF_EQ(gfx::PointF(20, 20), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(4, 4), result.current_visual_offset); - gfx::Vector2dF initial_offset, target_offset; + gfx::PointF initial_offset, target_offset; EXPECT_TRUE(GetInputHandler().GetSnapFlingInfoAndSetAnimatingSnapTarget( gfx::Vector2dF(10, 10), &initial_offset, &target_offset)); EXPECT_TRUE(GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(4, 4), initial_offset); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), target_offset); + EXPECT_POINTF_EQ(gfx::PointF(4, 4), initial_offset); + EXPECT_POINTF_EQ(gfx::PointF(10, 10), target_offset); // Snap targets shouldn't be set until the fling animation is complete. EXPECT_EQ(TargetSnapAreaElementIds(), GetSnapContainerData(overflow)->GetTargetSnapAreaElementIds()); @@ -2947,7 +2958,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, gfx::Size overflow_size(400, 400); LayerImpl* overflow = AddScrollableLayer(OuterViewportScrollLayer(), gfx::Size(100, 100), overflow_size); - SetScrollOffset(scroll_layer, gfx::Vector2dF(30, 30)); + SetScrollOffset(scroll_layer, gfx::PointF(30, 30)); DrawFrame(); gfx::Point pointer_position(50, 50); @@ -2963,15 +2974,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(30, 30), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(30, 30), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 30), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetScrollNode(overflow)->overscroll_behavior = OverscrollBehavior( OverscrollBehavior::Type::kContain, OverscrollBehavior::Type::kAuto); @@ -2987,15 +2998,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 30), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 30), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // OverscrollBehaviorContain on x shouldn't prevent propagations of // scroll on y. @@ -3006,15 +3017,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 30), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 30), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // A scroll update with both x & y delta will adhere to the most restrictive // case. @@ -3025,15 +3036,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, diagonal_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // Changing scroll-boundary-behavior to y axis. GetScrollNode(overflow)->overscroll_behavior = OverscrollBehavior( @@ -3050,15 +3061,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(20, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // OverscrollBehaviorContain on y should prevent propagations of scroll // on y. @@ -3069,15 +3080,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, y_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // A scroll update with both x & y delta will adhere to the most restrictive // case. @@ -3088,15 +3099,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, diagonal_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); // Gesture scroll should latch to the first scroller that has non-auto // overscroll-behavior. @@ -3112,8 +3123,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(pointer_position, x_delta, ui::ScrollInputType::kWheel) @@ -3128,8 +3139,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, UpdateState(pointer_position, -y_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(10, 10), CurrentScrollOffset(overflow)); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { @@ -3154,15 +3165,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(scroll_position, scroll_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(10, 10), CurrentScrollOffset(overflow)); GetScrollNode(overflow)->user_scrollable_horizontal = false; @@ -3175,15 +3186,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(10, 10), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(scroll_position, scroll_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(overflow)); GetScrollNode(overflow)->user_scrollable_vertical = false; DrawFrame(); @@ -3195,15 +3206,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(overflow)); GetInputHandler().ScrollUpdate( UpdateState(scroll_position, scroll_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), CurrentScrollOffset(overflow)); + EXPECT_POINTF_EQ(gfx::PointF(10, 10), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(10, 20), CurrentScrollOffset(overflow)); } // Test that if a scroll node doesn't have an associated Layer, scrolling @@ -3572,7 +3583,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ImplPinchZoom) { host_impl_->ProcessCompositorDeltas(); EXPECT_EQ(commit_data->page_scale_delta, page_scale_delta); - EXPECT_EQ(gfx::Vector2dF(75.0, 75.0), MaxScrollOffset(scroll_layer)); + EXPECT_EQ(gfx::PointF(75.0, 75.0), MaxScrollOffset(scroll_layer)); } // Scrolling after a pinch gesture should always be in local space. The @@ -3686,8 +3697,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportScrollOrder) { inner_scroll_layer->SetDrawsContent(true); UpdateDrawProperties(host_impl_->active_tree()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500), - MaxScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(500, 500), MaxScrollOffset(outer_scroll_layer)); GetInputHandler().ScrollBegin( BeginState(gfx::Point(250, 250), gfx::Vector2dF(), @@ -3700,10 +3710,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportScrollOrder) { GetInputHandler().ScrollEnd(); // Sanity check - we're zoomed in, starting from the origin. - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(inner_scroll_layer)); // Scroll down - only the inner viewport should scroll. GetInputHandler().ScrollBegin( @@ -3717,10 +3725,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportScrollOrder) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); // Scroll down - outer viewport should start scrolling after the inner is at // its maximum. @@ -3735,9 +3742,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportScrollOrder) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250), + EXPECT_POINTF_EQ(gfx::PointF(250, 250), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(300, 300), + EXPECT_POINTF_EQ(gfx::PointF(300, 300), CurrentScrollOffset(outer_scroll_layer)); } @@ -3758,10 +3765,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, UpdateDrawProperties(host_impl_->active_tree()); // Sanity checks. - EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500), - MaxScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(500, 500), MaxScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(inner_scroll_layer)); // Scroll only the layout viewport. GetInputHandler().ScrollBegin( @@ -3773,10 +3779,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, gfx::Vector2dF(0.125f, 0.125f), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0.125f, 0.125f), + CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(inner_scroll_layer)); GetInputHandler().ScrollEnd(); host_impl_->active_tree()->PushPageScaleFromMainThread(2, 1, 2); @@ -3791,10 +3796,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, gfx::Vector2dF(0.5f, 0.5f), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.125f, 0.125f), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0.25f, 0.25f), - CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0.125f, 0.125f), + CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0.25f, 0.25f), + CurrentScrollOffset(inner_scroll_layer)); GetInputHandler().ScrollEnd(); } @@ -3816,8 +3821,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDuringPinchGesture) { inner_scroll_layer->SetDrawsContent(true); UpdateDrawProperties(host_impl_->active_tree()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(500, 500), - MaxScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(500, 500), MaxScrollOffset(outer_scroll_layer)); GetInputHandler().ScrollBegin( BeginState(gfx::Point(250, 250), gfx::Vector2dF(), @@ -3827,9 +3831,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDuringPinchGesture) { GetInputHandler().PinchGestureBegin(); GetInputHandler().PinchGestureUpdate(2, gfx::Point(250, 250)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(125, 125), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(125, 125), CurrentScrollOffset(inner_scroll_layer)); // Needed so that the pinch is accounted for in draw properties. @@ -3839,9 +3842,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDuringPinchGesture) { gfx::Vector2dF(10, 10), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(130, 130), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(130, 130), CurrentScrollOffset(inner_scroll_layer)); DrawFrame(); @@ -3850,9 +3852,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDuringPinchGesture) { gfx::Vector2dF(400, 400), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(80, 80), + EXPECT_POINTF_EQ(gfx::PointF(80, 80), CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250), + EXPECT_POINTF_EQ(gfx::PointF(250, 250), CurrentScrollOffset(inner_scroll_layer)); GetInputHandler().PinchGestureEnd(gfx::Point(250, 250), true); @@ -3886,7 +3888,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) { GetInputHandler().PinchGestureEnd(anchor, true); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(250, 250), + EXPECT_POINTF_EQ(gfx::PointF(250, 250), CurrentScrollOffset(InnerViewportScrollLayer())); // Reset. @@ -3906,7 +3908,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) { GetInputHandler().PinchGestureEnd(anchor, true); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(InnerViewportScrollLayer())); // Reset. @@ -3926,7 +3928,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) { GetInputHandler().PinchGestureEnd(anchor, true); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(InnerViewportScrollLayer())); // Reset. @@ -3947,7 +3949,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) { GetInputHandler().PinchGestureEnd(anchor, true); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200), + EXPECT_POINTF_EQ(gfx::PointF(200, 200), CurrentScrollOffset(InnerViewportScrollLayer())); } @@ -3980,9 +3982,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10), - CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(5, 10), CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); // Scroll by the inner viewport's max scroll extent, the remainder // should bubble up to the outer viewport. @@ -3997,10 +3998,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10), - CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(5, 10), CurrentScrollOffset(outer_scroll_layer)); // Scroll by the outer viewport's max scroll extent, it should all go to the // outer viewport. @@ -4015,9 +4015,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100), + EXPECT_POINTF_EQ(gfx::PointF(100, 100), CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); } @@ -4046,7 +4046,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollWithSwapPromises) { std::unique_ptr<CompositorCommitData> commit_data = host_impl_->ProcessCompositorDeltas(); EXPECT_EQ(1u, commit_data->swap_promises.size()); - EXPECT_EQ(latency_info.trace_id(), commit_data->swap_promises[0]->TraceId()); + EXPECT_EQ(latency_info.trace_id(), + commit_data->swap_promises[0]->GetTraceId()); } // Test that scrolls targeting a layer with a non-null scroll_parent() don't @@ -4089,15 +4090,15 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDoesntBubble) { GetInputHandler().ScrollEnd(); // The child should be fully scrolled by the first ScrollUpdate. - EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), CurrentScrollOffset(scroll_child)); + EXPECT_POINTF_EQ(gfx::PointF(5, 5), CurrentScrollOffset(scroll_child)); // The scroll_parent shouldn't receive the second ScrollUpdate. - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(scroll_parent)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_parent)); // The viewport shouldn't have been scrolled at all. - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(InnerViewportScrollLayer())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(OuterViewportScrollLayer())); } @@ -4126,12 +4127,12 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollDoesntBubble) { GetInputHandler().ScrollEnd(); // The ScrollUpdate's should scroll the parent to its extent. - EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), CurrentScrollOffset(scroll_parent)); + EXPECT_POINTF_EQ(gfx::PointF(5, 5), CurrentScrollOffset(scroll_parent)); // The viewport shouldn't receive any scroll delta. - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(InnerViewportScrollLayer())); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(OuterViewportScrollLayer())); } } @@ -4204,7 +4205,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchGesture) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(50, 50)); + scroll_layer->element_id(), gfx::PointF(50, 50)); float page_scale_delta = 0.1f; GetInputHandler().ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(), @@ -4234,7 +4235,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchGesture) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(20, 20)); + scroll_layer->element_id(), gfx::PointF(20, 20)); float page_scale_delta = 1; GetInputHandler().ScrollBegin( @@ -4265,7 +4266,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchGesture) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(20, 20)); + scroll_layer->element_id(), gfx::PointF(20, 20)); float page_scale_delta = 1; GetInputHandler().ScrollBegin( @@ -4300,7 +4301,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PinchGesture) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(0, 0)); + scroll_layer->element_id(), gfx::PointF(0, 0)); GetInputHandler().ScrollBegin(BeginState(gfx::Point(0, 0), gfx::Vector2dF(), ui::ScrollInputType::kTouchscreen) @@ -4348,7 +4349,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SyncSubpixelScrollDelta) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF(0, 20)); + gfx::PointF(0, 20)); float page_scale_delta = 1; GetInputHandler().ScrollBegin(BeginState(gfx::Point(10, 10), gfx::Vector2dF(), @@ -4375,8 +4376,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SyncSubpixelScrollDelta) { // scroll layer. draw_property_utils::ComputeTransforms( &scroll_layer->layer_tree_impl()->property_trees()->transform_tree); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, -19), - scroll_layer->ScreenSpaceTransform().To2dTranslation()); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, -19), + scroll_layer->ScreenSpaceTransform().To2dTranslation()); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, @@ -4394,7 +4395,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF(0, 20.5f)); + gfx::PointF(0, 20.5f)); GetInputHandler().ScrollBegin( BeginState(gfx::Point(10, 10), gfx::Vector2dF(0, -1), @@ -4407,16 +4408,16 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - gfx::Vector2dF active_base = host_impl_->active_tree() - ->property_trees() - ->scroll_tree.GetScrollOffsetBaseForTesting( - scroll_layer->element_id()); - EXPECT_VECTOR_EQ(active_base, gfx::Vector2dF(0, 20.5)); + gfx::PointF active_base = host_impl_->active_tree() + ->property_trees() + ->scroll_tree.GetScrollOffsetBaseForTesting( + scroll_layer->element_id()); + EXPECT_POINTF_EQ(active_base, gfx::PointF(0, 20.5)); // Fractional active base should not affect the scroll delta. std::unique_ptr<CompositorCommitData> commit_data = host_impl_->ProcessCompositorDeltas(); - EXPECT_VECTOR_EQ(commit_data->inner_viewport_scroll.scroll_delta, - gfx::Vector2dF(0, -1)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, -1), + commit_data->inner_viewport_scroll.scroll_delta); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, @@ -4565,12 +4566,12 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PageScaleAnimation) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(50, 50)); + scroll_layer->element_id(), gfx::PointF(50, 50)); did_request_redraw_ = false; did_request_next_frame_ = false; host_impl_->active_tree()->SetPendingPageScaleAnimation( - std::make_unique<PendingPageScaleAnimation>(gfx::Vector2d(), false, 2, + std::make_unique<PendingPageScaleAnimation>(gfx::Point(), false, 2, duration)); host_impl_->ActivateSyncTree(); EXPECT_FALSE(did_request_redraw_); @@ -4625,12 +4626,12 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PageScaleAnimation) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(50, 50)); + scroll_layer->element_id(), gfx::PointF(50, 50)); did_request_redraw_ = false; did_request_next_frame_ = false; host_impl_->active_tree()->SetPendingPageScaleAnimation( - std::make_unique<PendingPageScaleAnimation>(gfx::Vector2d(25, 25), true, + std::make_unique<PendingPageScaleAnimation>(gfx::Point(25, 25), true, min_page_scale, duration)); host_impl_->ActivateSyncTree(); EXPECT_FALSE(did_request_redraw_); @@ -4691,10 +4692,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PageScaleAnimationNoOp) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(50, 50)); + scroll_layer->element_id(), gfx::PointF(50, 50)); host_impl_->active_tree()->SetPendingPageScaleAnimation( - std::make_unique<PendingPageScaleAnimation>(gfx::Vector2d(), true, 1, + std::make_unique<PendingPageScaleAnimation>(gfx::Point(), true, 1, duration)); host_impl_->ActivateSyncTree(); begin_frame_args.frame_time = start_time; @@ -4755,12 +4756,12 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF(50, 50)); + gfx::PointF(50, 50)); // Make sure TakePageScaleAnimation works properly. host_impl_->sync_tree()->SetPendingPageScaleAnimation( - std::make_unique<PendingPageScaleAnimation>(gfx::Vector2d(), false, + std::make_unique<PendingPageScaleAnimation>(gfx::Point(), false, target_scale, duration)); std::unique_ptr<PendingPageScaleAnimation> psa = host_impl_->sync_tree()->TakePendingPageScaleAnimation(); @@ -4773,7 +4774,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, did_request_redraw_ = false; did_request_next_frame_ = false; host_impl_->sync_tree()->SetPendingPageScaleAnimation( - std::make_unique<PendingPageScaleAnimation>(gfx::Vector2d(), false, + std::make_unique<PendingPageScaleAnimation>(gfx::Point(), false, target_scale, duration)); begin_frame_args.frame_time = halfway_through_animation; begin_frame_args.frame_id.sequence_number++; @@ -4868,11 +4869,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF(50, 50)); + gfx::PointF(50, 50)); did_complete_page_scale_animation_ = false; host_impl_->active_tree()->SetPendingPageScaleAnimation( - std::make_unique<PendingPageScaleAnimation>(gfx::Vector2d(), false, 2, + std::make_unique<PendingPageScaleAnimation>(gfx::Point(), false, 2, duration)); host_impl_->ActivateSyncTree(); begin_frame_args.frame_time = start_time; @@ -4907,7 +4908,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, DCHECK(inner_scroll); EXPECT_EQ(gfx::SizeF(50, 50), host_impl_->active_tree()->ScrollableViewportSize()); - EXPECT_EQ(gfx::Vector2dF(50, 50), MaxScrollOffset(inner_scroll)); + EXPECT_EQ(gfx::PointF(50, 50), MaxScrollOffset(inner_scroll)); PropertyTrees* property_trees = host_impl_->active_tree()->property_trees(); property_trees->SetInnerViewportContainerBoundsDelta(gfx::Vector2dF(15, 15)); @@ -4915,7 +4916,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // Container grows in response to the inner viewport bounds delta. EXPECT_EQ(gfx::SizeF(65, 65), host_impl_->active_tree()->ScrollableViewportSize()); - EXPECT_EQ(gfx::Vector2dF(42, 42), MaxScrollOffset(inner_scroll)); + EXPECT_EQ(gfx::PointF(42, 42), MaxScrollOffset(inner_scroll)); property_trees->SetInnerViewportContainerBoundsDelta(gfx::Vector2dF()); property_trees->SetOuterViewportContainerBoundsDelta(gfx::Vector2dF()); @@ -4924,7 +4925,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, DrawFrame(); property_trees->SetOuterViewportContainerBoundsDelta(gfx::Vector2dF(60, 60)); - EXPECT_EQ(gfx::Vector2dF(10, 10), MaxScrollOffset(inner_scroll)); + EXPECT_EQ(gfx::PointF(10, 10), MaxScrollOffset(inner_scroll)); } // Ensures scroll gestures coming from scrollbars cause animations in the @@ -5254,7 +5255,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { if (host_impl_->active_tree() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - InnerViewportScrollLayer()->element_id(), gfx::Vector2dF(5, 5))) + InnerViewportScrollLayer()->element_id(), gfx::PointF(5, 5))) host_impl_->active_tree()->DidUpdateScrollOffset( InnerViewportScrollLayer()->element_id()); EXPECT_FALSE(did_request_next_frame_); @@ -5444,8 +5445,8 @@ class LayerTreeHostImplTestMultiScrollable } void ResetScrollbars() { - GetEffectNode(scrollbar_1_)->opacity = 0; - GetEffectNode(scrollbar_2_)->opacity = 0; + GetEffectNode(scrollbar_1_.get())->opacity = 0; + GetEffectNode(scrollbar_2_.get())->opacity = 0; UpdateDrawProperties(host_impl_->active_tree()); if (is_aura_scrollbar_) @@ -5453,8 +5454,8 @@ class LayerTreeHostImplTestMultiScrollable } bool is_aura_scrollbar_; - SolidColorScrollbarLayerImpl* scrollbar_1_; - SolidColorScrollbarLayerImpl* scrollbar_2_; + raw_ptr<SolidColorScrollbarLayerImpl> scrollbar_1_; + raw_ptr<SolidColorScrollbarLayerImpl> scrollbar_2_; }; INSTANTIATE_TEST_SUITE_P(All, @@ -6066,7 +6067,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, CompositorFrameMetadata) { { viz::CompositorFrameMetadata metadata = host_impl_->MakeCompositorFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(), metadata.root_scroll_offset); EXPECT_EQ(1, metadata.page_scale_factor); EXPECT_EQ(gfx::SizeF(50, 50), metadata.scrollable_viewport_size); EXPECT_EQ(0.5f, metadata.min_page_scale_factor); @@ -6086,13 +6087,13 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, CompositorFrameMetadata) { { viz::CompositorFrameMetadata metadata = host_impl_->MakeCompositorFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); } GetInputHandler().ScrollEnd(); { viz::CompositorFrameMetadata metadata = host_impl_->MakeCompositorFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); } // Page scale should update metadata correctly (shrinking only the viewport). @@ -6107,7 +6108,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, CompositorFrameMetadata) { { viz::CompositorFrameMetadata metadata = host_impl_->MakeCompositorFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); EXPECT_EQ(2, metadata.page_scale_factor); EXPECT_EQ(gfx::SizeF(25, 25), metadata.scrollable_viewport_size); EXPECT_EQ(0.5f, metadata.min_page_scale_factor); @@ -6120,7 +6121,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, CompositorFrameMetadata) { { viz::CompositorFrameMetadata metadata = host_impl_->MakeCompositorFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); EXPECT_EQ(4, metadata.page_scale_factor); EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size); EXPECT_EQ(0.5f, metadata.min_page_scale_factor); @@ -6652,7 +6653,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ClampingAfterActivation) { host_impl_->ActivateSyncTree(); CreatePendingTree(); - const gfx::Vector2dF pending_scroll = gfx::Vector2dF(-100, -100); + const gfx::PointF pending_scroll(-100, -100); LayerImpl* active_outer_layer = OuterViewportScrollLayer(); LayerImpl* pending_outer_layer = host_impl_->pending_tree()->OuterViewportScrollLayerForTesting(); @@ -6663,7 +6664,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ClampingAfterActivation) { host_impl_->ActivateSyncTree(); // Scrolloffsets on the active tree will be clamped after activation. - EXPECT_EQ(CurrentScrollOffset(active_outer_layer), gfx::Vector2dF(0, 0)); + EXPECT_EQ(CurrentScrollOffset(active_outer_layer), gfx::PointF(0, 0)); } class LayerTreeHostImplBrowserControlsTest @@ -7096,7 +7097,7 @@ TEST_P(LayerTreeHostImplBrowserControlsTest, .get()); EXPECT_EQ(50, CurrentScrollOffset(inner_scroll).y()); EXPECT_EQ(0, CurrentScrollOffset(outer_scroll).y()); - EXPECT_EQ(gfx::Vector2dF(), MaxScrollOffset(outer_scroll)); + EXPECT_EQ(gfx::PointF(), MaxScrollOffset(outer_scroll)); GetInputHandler().ScrollEnd(); @@ -7198,8 +7199,8 @@ TEST_P(LayerTreeHostImplBrowserControlsTest, FixedContainerDelta) { host_impl_->browser_controls_manager()->ScrollBy(top_controls_scroll_delta); host_impl_->browser_controls_manager()->ScrollBy(top_controls_scroll_delta); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ContentTopOffset()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_), - property_trees->outer_viewport_container_bounds_delta()); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, top_controls_height_), + property_trees->outer_viewport_container_bounds_delta()); GetInputHandler().ScrollEnd(); // Scroll in the direction to make the browser controls show. @@ -7215,7 +7216,7 @@ TEST_P(LayerTreeHostImplBrowserControlsTest, FixedContainerDelta) { host_impl_->browser_controls_manager()->ScrollBy(-top_controls_scroll_delta); EXPECT_EQ(top_controls_scroll_delta.y(), host_impl_->browser_controls_manager()->ContentTopOffset()); - EXPECT_VECTOR_EQ( + EXPECT_VECTOR2DF_EQ( gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()), property_trees->outer_viewport_container_bounds_delta()); host_impl_->browser_controls_manager()->ScrollEnd(); @@ -7472,8 +7473,7 @@ TEST_P(LayerTreeHostImplBrowserControlsTest, SetScrollOffsetDelta(outer_scroll, gfx::Vector2dF(0, 200)); SetScrollOffsetDelta(inner_scroll, gfx::Vector2dF(100, 100)); - gfx::Vector2dF viewport_offset = - host_impl_->active_tree()->TotalScrollOffset(); + gfx::PointF viewport_offset = host_impl_->active_tree()->TotalScrollOffset(); EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset); // Hide the browser controls by 25px. @@ -7704,7 +7704,7 @@ TEST_P(LayerTreeHostImplBrowserControlsTest, GetInputHandler().ScrollEnd(); // Verify the layer is once-again non-scrollable. - EXPECT_EQ(gfx::Vector2dF(), MaxScrollOffset(InnerViewportScrollLayer())); + EXPECT_EQ(gfx::PointF(), MaxScrollOffset(InnerViewportScrollLayer())); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() @@ -8008,7 +8008,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, gfx::Vector2d scroll_delta(0, 10); gfx::Vector2dF expected_scroll_delta(scroll_delta); LayerImpl* outer_scroll = OuterViewportScrollLayer(); - gfx::Vector2dF expected_max_scroll = MaxScrollOffset(outer_scroll); + gfx::PointF expected_max_scroll = MaxScrollOffset(outer_scroll); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() .ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta, @@ -8052,7 +8052,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, gfx::Vector2d scroll_delta(0, 10); gfx::Vector2dF expected_scroll_delta(scroll_delta); LayerImpl* outer_scroll = OuterViewportScrollLayer(); - gfx::Vector2dF expected_max_scroll = MaxScrollOffset(outer_scroll); + gfx::PointF expected_max_scroll = MaxScrollOffset(outer_scroll); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() .ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta, @@ -8153,7 +8153,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, gfx::Vector2d scroll_delta(0, 10); gfx::Vector2dF expected_scroll_delta(scroll_delta); - gfx::Vector2dF expected_max_scroll(MaxScrollOffset(outer_scroll)); + gfx::PointF expected_max_scroll(MaxScrollOffset(outer_scroll)); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() .ScrollBegin(BeginState(gfx::Point(5, 5), scroll_delta, @@ -8203,11 +8203,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollChildBeyondLimit) { grand_child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - grand_child_layer->element_id(), gfx::Vector2dF(0, 5)); + grand_child_layer->element_id(), gfx::PointF(0, 5)); child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->element_id(), - gfx::Vector2dF(3, 0)); + gfx::PointF(3, 0)); DrawFrame(); { @@ -8256,11 +8256,11 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { grand_child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - grand_child_layer->element_id(), gfx::Vector2dF(0, 30)); + grand_child_layer->element_id(), gfx::PointF(0, 30)); child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->element_id(), - gfx::Vector2dF(0, 50)); + gfx::PointF(0, 50)); DrawFrame(); @@ -8286,7 +8286,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { host_impl_->UpdateAnimationState(true); // Should have started scrolling. - EXPECT_NE(gfx::Vector2dF(0, 30), CurrentScrollOffset(grand_child_layer)); + EXPECT_NE(gfx::PointF(0, 30), CurrentScrollOffset(grand_child_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); begin_frame_args.frame_time = start_time + base::Milliseconds(200); @@ -8295,8 +8295,8 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(grand_child_layer)); - EXPECT_EQ(gfx::Vector2dF(0, 50), CurrentScrollOffset(child_layer)); + EXPECT_EQ(gfx::PointF(0, 0), CurrentScrollOffset(grand_child_layer)); + EXPECT_EQ(gfx::PointF(0, 50), CurrentScrollOffset(child_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); // Second ScrollAnimated should remain latched to the grand_child_layer. @@ -8316,8 +8316,8 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedLatchToChild) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_EQ(gfx::Vector2dF(0, 0), CurrentScrollOffset(grand_child_layer)); - EXPECT_EQ(gfx::Vector2dF(0, 50), CurrentScrollOffset(child_layer)); + EXPECT_EQ(gfx::PointF(0, 0), CurrentScrollOffset(grand_child_layer)); + EXPECT_EQ(gfx::PointF(0, 50), CurrentScrollOffset(child_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); // Tear down the LayerTreeHostImpl before the InputHandlerClient. @@ -8341,11 +8341,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollWithoutBubbling) { grand_child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - grand_child_layer->element_id(), gfx::Vector2dF(0, 2)); + grand_child_layer->element_id(), gfx::PointF(0, 2)); child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->element_id(), - gfx::Vector2dF(0, 3)); + gfx::PointF(0, 3)); DrawFrame(); { @@ -8864,7 +8864,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollViewportRounding) { host_impl_->active_tree()->PushPageScaleFromMainThread(1, 0.5f, 4); LayerImpl* inner_viewport_scroll_layer = InnerViewportScrollLayer(); - EXPECT_EQ(gfx::Vector2dF(0, 0), MaxScrollOffset(inner_viewport_scroll_layer)); + EXPECT_EQ(gfx::PointF(0, 0), MaxScrollOffset(inner_viewport_scroll_layer)); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { @@ -8879,19 +8879,20 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF()); + gfx::PointF()); SetScrollOffsetDelta(scroll_layer, initial_scroll_delta); - EXPECT_EQ(gfx::Vector2dF(), scroll_watcher.last_set_scroll_offset()); + EXPECT_EQ(gfx::PointF(), scroll_watcher.last_set_scroll_offset()); // Requesting an update results in the current scroll offset being set. GetInputHandler().RequestUpdateForSynchronousInputHandler(); - EXPECT_EQ(initial_scroll_delta, scroll_watcher.last_set_scroll_offset()); + EXPECT_EQ(initial_scroll_delta, + scroll_watcher.last_set_scroll_offset().OffsetFromOrigin()); // Setting the delegate results in the scrollable_size, max_scroll_offset, // page_scale_factor and {min|max}_page_scale_factor being set. EXPECT_EQ(gfx::SizeF(100, 100), scroll_watcher.scrollable_size()); - EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_watcher.max_scroll_offset()); + EXPECT_EQ(gfx::PointF(90, 80), scroll_watcher.max_scroll_offset()); EXPECT_EQ(1, scroll_watcher.page_scale_factor()); EXPECT_EQ(1, scroll_watcher.min_page_scale_factor()); EXPECT_EQ(1, scroll_watcher.max_page_scale_factor()); @@ -8910,7 +8911,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { // Animating page scale can change the root offset, so it should update the // delegate. Also resets the page scale to 1 for the rest of the test. host_impl_->LayerTreeHostImpl::StartPageScaleAnimation( - gfx::Vector2d(0, 0), false, 1, base::TimeDelta()); + gfx::Point(0, 0), false, 1, base::TimeDelta()); host_impl_->Animate(); EXPECT_EQ(1, scroll_watcher.page_scale_factor()); EXPECT_EQ(.5f, scroll_watcher.min_page_scale_factor()); @@ -8931,7 +8932,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { // Scrolling should be relative to the offset as given by the delegate. gfx::Vector2dF scroll_delta(0, 10); - gfx::Vector2dF current_offset(7, 8); + gfx::PointF current_offset(7, 8); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() @@ -8948,7 +8949,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { EXPECT_EQ(current_offset + scroll_delta, scroll_watcher.last_set_scroll_offset()); - current_offset = gfx::Vector2dF(42, 41); + current_offset = gfx::PointF(42, 41); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(current_offset); GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kTouchscreen) @@ -8956,8 +8957,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { EXPECT_EQ(current_offset + scroll_delta, scroll_watcher.last_set_scroll_offset()); GetInputHandler().ScrollEnd(); - GetInputHandler().SetSynchronousInputHandlerRootScrollOffset( - gfx::Vector2dF()); + GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(gfx::PointF()); // Forces a full tree synchronization and ensures that the scroll delegate // sees the correct size of the new tree. @@ -8975,14 +8975,14 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { host_impl_ = nullptr; } -void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) { +void CheckLayerScrollOffset(LayerImpl* layer, gfx::Point scroll_offset) { const gfx::Transform target_space_transform = layer->draw_properties().target_space_transform; EXPECT_TRUE(target_space_transform.IsScaleOrTranslation()); gfx::Point translated_point; target_space_transform.TransformPoint(&translated_point); - gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta); - EXPECT_EQ(expected_point.ToString(), translated_point.ToString()); + EXPECT_EQ(-scroll_offset.x(), translated_point.x()); + EXPECT_EQ(-scroll_offset.y(), translated_point.y()); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, @@ -8993,13 +8993,13 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // Draw first frame to clear any pending draws and check scroll. DrawFrame(); - CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0, 0)); + CheckLayerScrollOffset(scroll_layer, gfx::Point(0, 0)); EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties()); // Set external scroll delta on delegate and notify LayerTreeHost. - gfx::Vector2dF scroll_offset(10, 10); + gfx::PointF scroll_offset(10, 10); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(scroll_offset); - CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0, 0)); + CheckLayerScrollOffset(scroll_layer, gfx::Point(0, 0)); EXPECT_TRUE(host_impl_->active_tree()->needs_update_draw_properties()); // Check scroll delta reflected in layer. @@ -9013,7 +9013,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, host_impl_->DidDrawAllLayers(frame); host_impl_->DidFinishImplFrame(args); EXPECT_FALSE(frame.has_no_damage); - CheckLayerScrollDelta(scroll_layer, scroll_offset); + CheckLayerScrollOffset(scroll_layer, gfx::ToRoundedPoint(scroll_offset)); } // Ensure the viewport correctly handles the user_scrollable bits. That is, if @@ -9059,9 +9059,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { ui::ScrollInputType::kTouchscreen); GetInputHandler().ScrollUpdate(update_state.get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(30, 0), + EXPECT_POINTF_EQ(gfx::PointF(30, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); // Continue scrolling. The inner viewport should scroll until its extent, @@ -9076,17 +9076,17 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { ui::ScrollInputType::kTouchscreen); GetInputHandler().ScrollUpdate(update_state.get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), + EXPECT_POINTF_EQ(gfx::PointF(50, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); GetInputHandler().ScrollEnd(); } // Reset. Try the same test above but using animated scrolls. - SetScrollOffset(outer_scroll, gfx::Vector2dF(0, 0)); - SetScrollOffset(inner_scroll, gfx::Vector2dF(0, 0)); + SetScrollOffset(outer_scroll, gfx::PointF(0, 0)); + SetScrollOffset(inner_scroll, gfx::PointF(0, 0)); { auto begin_state = @@ -9118,9 +9118,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { ANIMATE(0); ANIMATE(200); - EXPECT_VECTOR_EQ(gfx::Vector2dF(30, 0), + EXPECT_POINTF_EQ(gfx::PointF(30, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); // Continue scrolling. The inner viewport should scroll until its extent, @@ -9130,9 +9130,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { ANIMATE(10); ANIMATE(200); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), + EXPECT_POINTF_EQ(gfx::PointF(50, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); // Continue scrolling. the outer viewport should still not scroll. @@ -9141,16 +9141,16 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { ANIMATE(10); ANIMATE(200); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 0), + EXPECT_POINTF_EQ(gfx::PointF(50, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); // Fully scroll the inner viewport. We'll now try to start an animation on // the outer viewport in the vertical direction, which is scrollable. We'll // then try to update the curve to scroll horizontally. Ensure that doesn't // allow any horizontal scroll. - SetScrollOffset(inner_scroll, gfx::Vector2dF(50, 50)); + SetScrollOffset(inner_scroll, gfx::PointF(50, 50)); update_state = AnimatedUpdateState(gfx::Point(), gfx::Vector2dF(0, 100)); GetInputHandler().ScrollUpdate(update_state.get()); ANIMATE(16); @@ -9161,7 +9161,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { ASSERT_LT(0, scroll_tree.current_scroll_offset(outer_element_id).y()); ASSERT_GT(50, scroll_tree.current_scroll_offset(outer_element_id).y()); ASSERT_EQ(0, scroll_tree.current_scroll_offset(outer_element_id).x()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), scroll_tree.current_scroll_offset(inner_element_id)); // Now when we scroll we should do so by updating the ongoing animation @@ -9170,9 +9170,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ViewportUserScrollable) { GetInputHandler().ScrollUpdate(update_state.get()); ANIMATE(200); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 100), + EXPECT_POINTF_EQ(gfx::PointF(0, 100), scroll_tree.current_scroll_offset(outer_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), scroll_tree.current_scroll_offset(inner_element_id)); #undef ANIMATE @@ -9212,11 +9212,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { GetScrollNode(inner_scroll)->user_scrollable_vertical = false; GetScrollNode(inner_scroll)->user_scrollable_horizontal = false; - gfx::Vector2dF scroll_offset(25, 30); + gfx::PointF scroll_offset(25, 30); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(scroll_offset); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(scroll_offset, + EXPECT_POINTF_EQ(scroll_offset, scroll_tree.current_scroll_offset(outer_element_id)); EXPECT_TRUE(did_request_redraw_); @@ -9224,7 +9224,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { did_request_redraw_ = false; GetScrollNode(inner_scroll)->user_scrollable_vertical = true; GetScrollNode(inner_scroll)->user_scrollable_horizontal = true; - SetScrollOffset(outer_scroll, gfx::Vector2dF(0, 0)); + SetScrollOffset(outer_scroll, gfx::PointF(0, 0)); } // Disable scrolling the outer viewport. The inner should scroll to its @@ -9234,11 +9234,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { GetScrollNode(outer_scroll)->user_scrollable_vertical = false; GetScrollNode(outer_scroll)->user_scrollable_horizontal = false; - gfx::Vector2dF scroll_offset(120, 140); + gfx::PointF scroll_offset(120, 140); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(scroll_offset); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); EXPECT_TRUE(did_request_redraw_); @@ -9246,7 +9246,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { did_request_redraw_ = false; GetScrollNode(outer_scroll)->user_scrollable_vertical = true; GetScrollNode(outer_scroll)->user_scrollable_horizontal = true; - SetScrollOffset(inner_scroll, gfx::Vector2dF(0, 0)); + SetScrollOffset(inner_scroll, gfx::PointF(0, 0)); } // Disable both viewports. No scrolling should take place, no redraw should @@ -9258,11 +9258,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { GetScrollNode(outer_scroll)->user_scrollable_vertical = false; GetScrollNode(outer_scroll)->user_scrollable_horizontal = false; - gfx::Vector2dF scroll_offset(60, 70); + gfx::PointF scroll_offset(60, 70); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(scroll_offset); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); EXPECT_FALSE(did_request_redraw_); @@ -9279,13 +9279,13 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { ASSERT_FALSE(did_request_redraw_); GetScrollNode(outer_scroll)->user_scrollable_vertical = false; GetScrollNode(outer_scroll)->user_scrollable_horizontal = false; - SetScrollOffset(inner_scroll, gfx::Vector2dF(50, 50)); + SetScrollOffset(inner_scroll, gfx::PointF(50, 50)); - gfx::Vector2dF scroll_offset(60, 70); + gfx::PointF scroll_offset(60, 70); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(scroll_offset); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), scroll_tree.current_scroll_offset(inner_element_id)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), scroll_tree.current_scroll_offset(outer_element_id)); EXPECT_FALSE(did_request_redraw_); @@ -9300,7 +9300,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { TEST_P(ScrollUnifiedLayerTreeHostImplTest, SetRootScrollOffsetNoViewportCrash) { auto* inner_scroll = InnerViewportScrollLayer(); ASSERT_FALSE(inner_scroll); - gfx::Vector2dF scroll_offset(25, 30); + gfx::PointF scroll_offset(25, 30); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset(scroll_offset); } @@ -9491,11 +9491,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, OverscrollChildWithoutBubbling) { child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(child_layer->element_id(), - gfx::Vector2dF(0, 3)); + gfx::PointF(0, 3)); grand_child_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - grand_child_layer->element_id(), gfx::Vector2dF(0, 2)); + grand_child_layer->element_id(), gfx::PointF(0, 2)); DrawFrame(); { @@ -9676,18 +9676,16 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { .get()); EXPECT_TRUE(scroll_result.did_scroll); EXPECT_FALSE(scroll_result.did_overscroll_root); - EXPECT_EQ( - gfx::Vector2dF().ToString(), - GetInputHandler().accumulated_root_overscroll_for_testing().ToString()); + EXPECT_EQ(gfx::Vector2dF(), + GetInputHandler().accumulated_root_overscroll_for_testing()); scroll_result = GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), gfx::Vector2dF(0, -2.30f), ui::ScrollInputType::kWheel) .get()); EXPECT_TRUE(scroll_result.did_scroll); EXPECT_FALSE(scroll_result.did_overscroll_root); - EXPECT_EQ( - gfx::Vector2dF().ToString(), - GetInputHandler().accumulated_root_overscroll_for_testing().ToString()); + EXPECT_EQ(gfx::Vector2dF(), + GetInputHandler().accumulated_root_overscroll_for_testing()); GetInputHandler().ScrollEnd(); // unusedrootDelta should be subtracted from applied delta so that // unwanted glow effect calls are not called. @@ -9735,9 +9733,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) { .get()); EXPECT_FALSE(scroll_result.did_scroll); EXPECT_FALSE(scroll_result.did_overscroll_root); - EXPECT_EQ( - gfx::Vector2dF().ToString(), - GetInputHandler().accumulated_root_overscroll_for_testing().ToString()); + EXPECT_EQ(gfx::Vector2dF(), + GetInputHandler().accumulated_root_overscroll_for_testing()); GetInputHandler().ScrollEnd(); } } @@ -9768,9 +9765,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) { ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100), - CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(100, 100), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); } @@ -9782,9 +9778,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) { ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200), - CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(200, 200), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); EXPECT_FALSE(result.did_overscroll_root); } @@ -9797,9 +9792,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) { ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200), - CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(200, 200), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); EXPECT_FALSE(result.did_overscroll_root); } @@ -9894,10 +9888,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollFromOuterViewportSibling) { GetInputHandler().ScrollEnd(); EXPECT_EQ(1, host_impl_->active_tree()->CurrentTopControlsShownRatio()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(300, 300), - CurrentScrollOffset(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(300, 300), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); } // Scrolling on the child now should chain up directly to the inner viewport. @@ -9914,7 +9909,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollFromOuterViewportSibling) { ui::ScrollInputType::kTouchscreen) .get()); EXPECT_EQ(0, host_impl_->active_tree()->CurrentTopControlsShownRatio()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(inner_scroll_layer)); GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), scroll_delta, @@ -9925,9 +9921,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollFromOuterViewportSibling) { ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 10), + EXPECT_POINTF_EQ(gfx::PointF(0, 10), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); GetInputHandler().ScrollEnd(); } } @@ -9976,7 +9973,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200), + EXPECT_POINTF_EQ(gfx::PointF(200, 200), CurrentScrollOffset(child_scroll_layer)); GetInputHandler().ScrollBegin( @@ -9990,11 +9987,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(200, 200), - CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(200, 200), CurrentScrollOffset(scroll_layer)); } // Now that the nested scrolling layers are fully scrolled, further scrolls @@ -10012,7 +10008,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); } // Zoom into the page by a 2X factor so that the inner viewport becomes @@ -10025,7 +10022,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // Reset the parent scrolling layer (i.e. the current outer viewport) so that // we can ensure viewport scrolling works correctly. - scroll_layer->SetCurrentScrollOffset(gfx::Vector2dF(0, 0)); + scroll_layer->SetCurrentScrollOffset(gfx::PointF(0, 0)); // Scrolling the content layer should now scroll the inner viewport first, // and then chain up to the current outer viewport (i.e. the parent scroll @@ -10042,7 +10039,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); GetInputHandler().ScrollBegin( @@ -10056,9 +10053,9 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(scroll_layer)); } } @@ -10110,9 +10107,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(600, 600), + EXPECT_POINTF_EQ(gfx::PointF(600, 600), CurrentScrollOffset(sibling_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); // Scrolling now should chain up but, since the outer viewport is a sibling // rather than an ancestor, we shouldn't chain to it. @@ -10127,9 +10125,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(600, 600), + EXPECT_POINTF_EQ(gfx::PointF(600, 600), CurrentScrollOffset(sibling_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); } float min_page_scale = 1, max_page_scale = 4; @@ -10137,11 +10136,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { host_impl_->active_tree()->PushPageScaleFromMainThread( page_scale_factor, min_page_scale, max_page_scale); - gfx::Vector2dF viewport_size_vec(viewport_size.width(), - viewport_size.height()); + gfx::PointF viewport_bottom_right(viewport_size.width(), + viewport_size.height()); // Reset the scroll offset. - sibling_scroll_layer->SetCurrentScrollOffset(gfx::Vector2dF()); + sibling_scroll_layer->SetCurrentScrollOffset(gfx::PointF()); // Now pinch-zoom in. Anchoring should cause scrolling only on the inner // viewport layer. @@ -10158,31 +10157,32 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { GetInputHandler().PinchGestureUpdate(page_scale_factor, anchor); GetInputHandler().PinchGestureEnd(anchor, true); - EXPECT_VECTOR_EQ(gfx::Vector2dF(anchor.x() / 2, anchor.y() / 2), + EXPECT_POINTF_EQ(gfx::PointF(anchor.x() / 2, anchor.y() / 2), CurrentScrollOffset(inner_scroll_layer)); GetInputHandler().ScrollUpdate( - UpdateState(anchor, viewport_size_vec, + UpdateState(anchor, viewport_bottom_right.OffsetFromOrigin(), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(ScaleVector2d(viewport_size_vec, 1 / page_scale_factor), - CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ( + gfx::ScalePoint(viewport_bottom_right, 1 / page_scale_factor), + CurrentScrollOffset(inner_scroll_layer)); // TODO(bokan): This doesn't yet work but we'll probably want to fix this // at some point. - // EXPECT_VECTOR_EQ( + // EXPECT_VECTOR2DF_EQ( // gfx::Vector2dF(), // CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(sibling_scroll_layer)); GetInputHandler().ScrollEnd(); } // Reset the scroll offsets - sibling_scroll_layer->SetCurrentScrollOffset(gfx::Vector2dF()); - inner_scroll_layer->SetCurrentScrollOffset(gfx::Vector2dF()); - outer_scroll_layer->SetCurrentScrollOffset(gfx::Vector2dF()); + sibling_scroll_layer->SetCurrentScrollOffset(gfx::PointF()); + inner_scroll_layer->SetCurrentScrollOffset(gfx::PointF()); + outer_scroll_layer->SetCurrentScrollOffset(gfx::PointF()); // Scrolls over the sibling while pinched in should scroll the sibling first, // but then chain up to the inner viewport so that the user can still pan @@ -10201,9 +10201,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(600, 600), + EXPECT_POINTF_EQ(gfx::PointF(600, 600), CurrentScrollOffset(sibling_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(inner_scroll_layer)); // Scrolling now should chain up to the inner viewport. GetInputHandler().ScrollBegin( @@ -10217,9 +10218,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(ScaleVector2d(viewport_size_vec, 1 / page_scale_factor), + EXPECT_POINTF_EQ(ScalePoint(viewport_bottom_right, 1 / page_scale_factor), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); // No more scrolling should be possible. GetInputHandler().ScrollBegin( @@ -10233,7 +10235,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RootScrollerScrollNonDescendant) { .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), + CurrentScrollOffset(outer_scroll_layer)); } } @@ -10358,10 +10361,10 @@ class BlendStateCheckLayer : public LayerImpl { } private: - viz::ClientResourceProvider* resource_provider_; + raw_ptr<viz::ClientResourceProvider> resource_provider_; bool blend_; bool has_render_surface_; - LayerImpl* comparison_layer_; + raw_ptr<LayerImpl> comparison_layer_; bool quads_appended_; gfx::Rect quad_rect_; gfx::Rect opaque_content_rect_; @@ -10811,7 +10814,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { viz::DrawQuad::Material gutter_quad_material_; gfx::Size gutter_texture_size_; gfx::Size viewport_size_; - BlendStateCheckLayer* child_; + raw_ptr<BlendStateCheckLayer> child_; bool did_activate_pending_tree_; }; @@ -10943,8 +10946,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->DidDrawAllLayers(frame); layer_tree_host_impl->DidFinishImplFrame(args); gfx::Rect expected_swap_rect(500, 500); - EXPECT_EQ(expected_swap_rect.ToString(), - fake_layer_tree_frame_sink->last_swap_rect().ToString()); + EXPECT_EQ(expected_swap_rect, fake_layer_tree_frame_sink->last_swap_rect()); // Second frame, only the damaged area should get swapped. Damage should be // the union of old and new child rects: gfx::Rect(26, 28). @@ -10960,8 +10962,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->DidFinishImplFrame(args); expected_swap_rect = gfx::Rect(26, 28); - EXPECT_EQ(expected_swap_rect.ToString(), - fake_layer_tree_frame_sink->last_swap_rect().ToString()); + EXPECT_EQ(expected_swap_rect, fake_layer_tree_frame_sink->last_swap_rect()); layer_tree_host_impl->active_tree()->SetDeviceViewportRect(gfx::Rect(10, 10)); // This will damage everything. @@ -10976,8 +10977,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PartialSwapReceivesDamageRect) { layer_tree_host_impl->DidFinishImplFrame(args); expected_swap_rect = gfx::Rect(10, 10); - EXPECT_EQ(expected_swap_rect.ToString(), - fake_layer_tree_frame_sink->last_swap_rect().ToString()); + EXPECT_EQ(expected_swap_rect, fake_layer_tree_frame_sink->last_swap_rect()); layer_tree_host_impl->ReleaseLayerTreeFrameSink(); } @@ -11235,7 +11235,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { UpdateDrawProperties(host_impl_->pending_tree()); - gfx::Vector2dF scroll_offset(100000, 0); + gfx::PointF scroll_offset(100000, 0); scrolling_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( @@ -11493,7 +11493,7 @@ class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest { host_impl_->active_tree()->SetDeviceViewportRect(gfx::Rect(10, 10)); } - FakeLayerTreeHostImpl* fake_host_impl_; + raw_ptr<FakeLayerTreeHostImpl> fake_host_impl_; }; TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) { @@ -11937,73 +11937,39 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, HiddenSelectionBoundsStayHidden) { } #endif // defined(OS_ANDROID) -class SimpleSwapPromiseMonitor : public SwapPromiseMonitor { - public: - SimpleSwapPromiseMonitor(LayerTreeHostImpl* layer_tree_host_impl, - int* set_needs_commit_count, - int* set_needs_redraw_count) - : SwapPromiseMonitor(layer_tree_host_impl), - set_needs_commit_count_(set_needs_commit_count), - set_needs_redraw_count_(set_needs_redraw_count) {} - - ~SimpleSwapPromiseMonitor() override = default; - - void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; } - - void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; } - - private: - int* set_needs_commit_count_; - int* set_needs_redraw_count_; -}; - TEST_P(ScrollUnifiedLayerTreeHostImplTest, SimpleSwapPromiseMonitor) { - int set_needs_commit_count = 0; - int set_needs_redraw_count = 0; - { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(host_impl_.get(), &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(host_impl_.get()); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(1); + host_impl_->SetNeedsRedraw(); - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(1, set_needs_redraw_count); } - // Now the monitor is destroyed, SetNeedsRedraw() is no longer being - // monitored. - host_impl_->SetNeedsRedraw(); - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(1, set_needs_redraw_count); - { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(host_impl_.get(), &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(host_impl_.get()); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(1); + // Redraw with damage. host_impl_->SetFullViewportDamage(); host_impl_->SetNeedsRedraw(); - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(2, set_needs_redraw_count); } { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(host_impl_.get(), &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(host_impl_.get()); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(1); + // Redraw without damage. host_impl_->SetNeedsRedraw(); - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(3, set_needs_redraw_count); } - set_needs_commit_count = 0; - set_needs_redraw_count = 0; - { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(host_impl_.get(), &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(host_impl_.get()); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(1); + SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100)); // Scrolling normally should not trigger any forwarding. @@ -12022,8 +11988,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SimpleSwapPromiseMonitor) { .did_scroll); GetInputHandler().ScrollEnd(); - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(1, set_needs_redraw_count); + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&monitor)); + + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(1); // Scrolling with a scroll handler should defer the swap to the main // thread. @@ -12042,9 +12010,6 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, SimpleSwapPromiseMonitor) { .get()) .did_scroll); GetInputHandler().ScrollEnd(); - - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(2, set_needs_redraw_count); } } @@ -12102,7 +12067,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, NoIdleAnimations) { scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF(0, 10)); + gfx::PointF(0, 10)); viz::BeginFrameArgs begin_frame_args = viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2); host_impl_->WillBeginImplFrame(begin_frame_args); @@ -12146,7 +12111,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(scroll_layer->element_id(), - gfx::Vector2dF(0, 10)); + gfx::PointF(0, 10)); host_impl_->DidChangeBrowserControlsPosition(); EXPECT_TRUE(did_request_next_frame_); EXPECT_TRUE(did_request_redraw_); @@ -12175,8 +12140,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .thread); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); result = GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), gfx::Vector2d(0, offset), @@ -12186,8 +12150,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, EXPECT_TRUE(result.did_scroll); EXPECT_FLOAT_EQ(-offset, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); // Scroll across the boundary const float content_scroll = 20; @@ -12200,8 +12163,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0)); EXPECT_EQ(-top_controls_height_, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, content_scroll), CurrentScrollOffset(scroll_layer)); // Now scroll back to the top of the content offset = -content_scroll; @@ -12213,8 +12175,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0)); EXPECT_EQ(-top_controls_height_, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); // And scroll the browser controls completely into view offset = -top_controls_height_; @@ -12225,8 +12186,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, EXPECT_TRUE(result.did_scroll); EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0)); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); // And attempt to scroll past the end result = GetInputHandler().ScrollUpdate( @@ -12236,8 +12196,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, EXPECT_FALSE(result.did_scroll); EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50)); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); GetInputHandler().ScrollEnd(); } @@ -12262,7 +12221,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kWheel) .thread); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(viewport_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(viewport_layer)); // Wheel scrolls should not affect the browser controls, and should pass // directly through to the viewport. @@ -12274,8 +12233,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, .did_scroll); EXPECT_FLOAT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta), - CurrentScrollOffset(viewport_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, delta), CurrentScrollOffset(viewport_layer)); EXPECT_TRUE( GetInputHandler() @@ -12285,7 +12243,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, .did_scroll); EXPECT_FLOAT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta * 2), + EXPECT_POINTF_EQ(gfx::PointF(0, delta * 2), CurrentScrollOffset(viewport_layer)); } @@ -12309,8 +12267,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .thread); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); // Scroll the browser controls partially. EXPECT_TRUE( @@ -12321,8 +12278,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, .did_scroll); EXPECT_FLOAT_EQ(-offset, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); did_request_redraw_ = false; did_request_next_frame_ = false; @@ -12351,8 +12307,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, begin_frame_args.frame_id.sequence_number++; host_impl_->WillBeginImplFrame(begin_frame_args); host_impl_->Animate(); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); float new_offset = host_impl_->browser_controls_manager()->ControlsTopOffset(); @@ -12385,7 +12340,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, scroll_layer->layer_tree_impl() ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting( - scroll_layer->element_id(), gfx::Vector2dF(0, initial_scroll_offset)); + scroll_layer->element_id(), gfx::PointF(0, initial_scroll_offset)); DrawFrame(); const float residue = 15; @@ -12398,8 +12353,8 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .thread); EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, initial_scroll_offset), + CurrentScrollOffset(scroll_layer)); // Scroll the browser controls partially. EXPECT_TRUE( @@ -12410,8 +12365,8 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, .did_scroll); EXPECT_FLOAT_EQ(-offset, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, initial_scroll_offset), + CurrentScrollOffset(scroll_layer)); did_request_redraw_ = false; did_request_next_frame_ = false; @@ -12484,8 +12439,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, .did_scroll); EXPECT_EQ(-offset, host_impl_->browser_controls_manager()->ControlsTopOffset()); - EXPECT_EQ(gfx::Vector2dF().ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(), CurrentScrollOffset(scroll_layer)); EXPECT_TRUE( GetInputHandler() @@ -12493,8 +12447,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .get()) .did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, offset), CurrentScrollOffset(scroll_layer)); EXPECT_TRUE( GetInputHandler() @@ -12504,8 +12457,8 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, .did_scroll); // Should have fully scrolled - EXPECT_EQ(gfx::Vector2dF(0, MaxScrollOffset(scroll_layer).y()).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, MaxScrollOffset(scroll_layer).y()), + CurrentScrollOffset(scroll_layer)); float overscrollamount = 10; @@ -12516,11 +12469,9 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .get()) .did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); - EXPECT_EQ( - gfx::Vector2dF(0, overscrollamount).ToString(), - GetInputHandler().accumulated_root_overscroll_for_testing().ToString()); + EXPECT_EQ(gfx::PointF(0, 2 * offset), CurrentScrollOffset(scroll_layer)); + EXPECT_EQ(gfx::Vector2dF(0, overscrollamount), + GetInputHandler().accumulated_root_overscroll_for_testing()); EXPECT_TRUE( GetInputHandler() @@ -12528,8 +12479,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .get()) .did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); EXPECT_EQ(-offset, host_impl_->browser_controls_manager()->ControlsTopOffset()); @@ -12539,8 +12489,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ui::ScrollInputType::kTouchscreen) .get()) .did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(), - CurrentScrollOffset(scroll_layer).ToString()); + EXPECT_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); // Browser controls should be fully visible EXPECT_EQ(0, host_impl_->browser_controls_manager()->ControlsTopOffset()); @@ -12678,9 +12627,8 @@ TEST_P(LayerTreeHostImplBrowserControlsTest, .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 50), - CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll)); + EXPECT_POINTF_EQ(gfx::PointF(100, 50), CurrentScrollOffset(scroll_layer)); EXPECT_EQ(0, layer_tree_impl->CurrentTopControlsShownRatio()); } } @@ -12700,22 +12648,22 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, RootScrollBothInnerAndOuterLayer) { DrawFrame(); { - gfx::Vector2dF inner_expected; - gfx::Vector2dF outer_expected; + gfx::PointF inner_expected; + gfx::PointF outer_expected; EXPECT_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); EXPECT_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); - gfx::Vector2dF current_offset(70, 100); + gfx::PointF current_offset(70, 100); GetInputHandler().SetSynchronousInputHandlerRootScrollOffset( current_offset); - EXPECT_EQ(gfx::Vector2dF(25, 40), MaxScrollOffset(inner_scroll)); - EXPECT_EQ(gfx::Vector2dF(50, 80), MaxScrollOffset(outer_scroll)); + EXPECT_EQ(gfx::PointF(25, 40), MaxScrollOffset(inner_scroll)); + EXPECT_EQ(gfx::PointF(50, 80), MaxScrollOffset(outer_scroll)); // Inner viewport scrolls first. Then the rest is applied to the outer // viewport. - EXPECT_EQ(gfx::Vector2dF(25, 40), CurrentScrollOffset(inner_scroll)); - EXPECT_EQ(gfx::Vector2dF(45, 60), CurrentScrollOffset(outer_scroll)); + EXPECT_EQ(gfx::PointF(25, 40), CurrentScrollOffset(inner_scroll)); + EXPECT_EQ(gfx::PointF(45, 60), CurrentScrollOffset(outer_scroll)); } } @@ -12733,13 +12681,13 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, DrawFrame(); { - gfx::Vector2dF inner_expected; - gfx::Vector2dF outer_expected; - EXPECT_VECTOR_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); - EXPECT_VECTOR_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); + gfx::PointF inner_expected; + gfx::PointF outer_expected; + EXPECT_POINTF_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); + EXPECT_POINTF_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); - gfx::Vector2d scroll_delta(inner_viewport.width() / 2, - inner_viewport.height() / 2); + gfx::Vector2dF scroll_delta(inner_viewport.width() / 2, + inner_viewport.height() / 2); // Make sure the scroll goes to the inner viewport first. EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, @@ -12757,8 +12705,8 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, .get()); inner_expected += scroll_delta; - EXPECT_VECTOR_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); - EXPECT_VECTOR_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); + EXPECT_POINTF_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); + EXPECT_POINTF_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); // Now diagonal scroll across the outer viewport boundary in a single event. // The entirety of the scroll should be consumed, as bubbling between inner @@ -12771,8 +12719,8 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, inner_expected += scroll_delta; GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); - EXPECT_VECTOR_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); + EXPECT_POINTF_EQ(inner_expected, CurrentScrollOffset(inner_scroll)); + EXPECT_POINTF_EQ(outer_expected, CurrentScrollOffset(outer_scroll)); } } @@ -12830,7 +12778,7 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, DrawFrame(); // Ensure inner viewport doesn't react to scrolls (test it's unscrollable). - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(inner_scroll)); EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() .ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 100), @@ -12842,7 +12790,7 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, UpdateState(gfx::Point(), gfx::Vector2dF(0, 100), ui::ScrollInputType::kTouchscreen) .get()); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(inner_scroll)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(inner_scroll)); // When inner viewport is unscrollable, a fling gives zero overscroll. EXPECT_FALSE(scroll_result.did_overscroll_root); @@ -12887,16 +12835,16 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, external_transform); host_impl_->OnDraw(external_transform, external_viewport, resourceless_software_draw, false); - EXPECT_TRANSFORMATION_MATRIX_EQ( - external_transform, layer->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(external_transform, + layer->draw_properties().target_space_transform); external_transform.Translate(20, 20); host_impl_->SetExternalTilePriorityConstraints(external_viewport, external_transform); host_impl_->OnDraw(external_transform, external_viewport, resourceless_software_draw, false); - EXPECT_TRANSFORMATION_MATRIX_EQ( - external_transform, layer->draw_properties().target_space_transform); + EXPECT_TRANSFORM_EQ(external_transform, + layer->draw_properties().target_space_transform); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, ExternalTransformSetNeedsRedraw) { @@ -13334,11 +13282,10 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimated) { { // Creating the animation should set 'needs redraw'. This is required // for LatencyInfo's to be propagated along with the CompositorFrame - int set_needs_commit_count = 0; - int set_needs_redraw_count = 0; - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(host_impl_.get(), &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(host_impl_.get()); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(AtLeast(1)); + EXPECT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, GetInputHandler() .ScrollBegin(BeginState(gfx::Point(), gfx::Vector2d(0, 50), @@ -13348,9 +13295,6 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimated) { .thread); GetInputHandler().ScrollUpdate( AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get()); - - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_GT(set_needs_redraw_count, 0); } LayerImpl* scrolling_layer = OuterViewportScrollLayer(); @@ -13363,7 +13307,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimated) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_NE(gfx::Vector2dF(), CurrentScrollOffset(scrolling_layer)); + EXPECT_NE(gfx::PointF(), CurrentScrollOffset(scrolling_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); begin_frame_args.frame_time = start_time + base::Milliseconds(50); @@ -13378,18 +13322,14 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimated) { { // Updating the animation should set 'needs redraw'. This is required // for LatencyInfo's to be propagated along with the CompositorFrame - int set_needs_commit_count = 0; - int set_needs_redraw_count = 0; - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(host_impl_.get(), &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(host_impl_.get()); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(1); + // Update target. GetInputHandler().ScrollUpdate( AnimatedUpdateState(gfx::Point(), gfx::Vector2d(0, 50)).get()); GetInputHandler().ScrollEnd(); - - EXPECT_EQ(0, set_needs_commit_count); - EXPECT_EQ(1, set_needs_redraw_count); } host_impl_->DidFinishImplFrame(begin_frame_args); @@ -13412,8 +13352,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimated) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 100), - CurrentScrollOffset(scrolling_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 100), CurrentScrollOffset(scrolling_layer)); EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingNode()); host_impl_->DidFinishImplFrame(begin_frame_args); } @@ -13456,7 +13395,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimatedLatching) { host_impl_->UpdateAnimationState(true); host_impl_->DidFinishImplFrame(begin_frame_args); - EXPECT_NE(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll)); + EXPECT_NE(gfx::PointF(), CurrentScrollOffset(outer_scroll)); EXPECT_TRUE(GetImplAnimationHost()->ImplOnlyScrollAnimatingElement()); } @@ -13743,7 +13682,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, /*jump_key_modifier*/ false); InputHandlerPointerResult result = GetInputHandler().MouseMoveAt(gfx::Point(350, 28)); - EXPECT_GT(result.scroll_offset.y(), 0u); + EXPECT_GT(result.scroll_delta.y(), 0u); GetInputHandler().MouseUp(gfx::PointF(350, 28)); // Scrolling shouldn't occur at opacity = 0. @@ -13752,7 +13691,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, GetInputHandler().MouseDown(gfx::PointF(350, 18), /*jump_key_modifier*/ false); result = GetInputHandler().MouseMoveAt(gfx::Point(350, 28)); - EXPECT_EQ(result.scroll_offset.y(), 0u); + EXPECT_EQ(result.scroll_delta.y(), 0u); GetInputHandler().MouseUp(gfx::PointF(350, 28)); // Tear down the LayerTreeHostImpl before the InputHandlerClient. @@ -13872,7 +13811,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PointerMoveOutOfSequence) { // on the result that is returned by ScrollbarController::HandlePointerMove. InputHandlerPointerResult result = GetInputHandler().MouseMoveAt(gfx::Point(350, 19)); - EXPECT_GT(result.scroll_offset.y(), 0u); + EXPECT_GT(result.scroll_delta.y(), 0u); // GSB gets dispatched at VSync. viz::BeginFrameArgs begin_frame_args = @@ -13890,7 +13829,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PointerMoveOutOfSequence) { // The PointerMove(s) that follow should be handled and are expected to have a // scroll_offset > 0. result = GetInputHandler().MouseMoveAt(gfx::Point(350, 20)); - EXPECT_GT(result.scroll_offset.y(), 0u); + EXPECT_GT(result.scroll_delta.y(), 0u); // End the scroll. GetInputHandler().MouseUp(gfx::PointF(350, 20)); @@ -13938,14 +13877,14 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, FadedOutPaintedScrollbarHitTest) { scrollbar->SetScrollbarPaintedOpacity(0); InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 100), /*jump_key_modifier*/ false); - EXPECT_EQ(result.scroll_offset.y(), 0u); + EXPECT_EQ(result.scroll_delta.y(), 0u); // MouseDown on the track of a scrollbar with opacity > 0 should produce a // scroll. scrollbar->SetScrollbarPaintedOpacity(1); result = GetInputHandler().MouseDown(gfx::PointF(350, 100), /*jump_key_modifier*/ false); - EXPECT_GT(result.scroll_offset.y(), 0u); + EXPECT_GT(result.scroll_delta.y(), 0u); // Tear down the LayerTreeHostImpl before the InputHandlerClient. host_impl_->ReleaseLayerTreeFrameSink(); @@ -14004,11 +13943,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // MouseDown on the thumb should not produce a scroll. InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 18), /*jump_key_modifier*/ false); - EXPECT_EQ(result.scroll_offset.y(), 0u); + EXPECT_EQ(result.scroll_delta.y(), 0u); // The first request for a GSU should be processed as expected. result = GetInputHandler().MouseMoveAt(gfx::Point(350, 19)); - EXPECT_GT(result.scroll_offset.y(), 0u); + EXPECT_GT(result.scroll_delta.y(), 0u); // A second request for a GSU within the same frame should be ignored as it // will cause the thumb drag to become jittery. The reason this happens is @@ -14017,7 +13956,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // calculating an incorrect delta (as ComputeThumbQuadRect would not have // accounted for the delta in the first GSU that was not yet dispatched). result = GetInputHandler().MouseMoveAt(gfx::Point(350, 20)); - EXPECT_EQ(result.scroll_offset.y(), 0u); + EXPECT_EQ(result.scroll_delta.y(), 0u); host_impl_->DidFinishImplFrame(begin_frame_args); // ------------------------- Start frame 1 ------------------------- @@ -14027,11 +13966,11 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, // MouseMove for a new frame gets processed as usual. result = GetInputHandler().MouseMoveAt(gfx::Point(350, 21)); - EXPECT_GT(result.scroll_offset.y(), 0u); + EXPECT_GT(result.scroll_delta.y(), 0u); // MouseUp is not expected to have a delta. result = GetInputHandler().MouseUp(gfx::PointF(350, 21)); - EXPECT_EQ(result.scroll_offset.y(), 0u); + EXPECT_EQ(result.scroll_delta.y(), 0u); // Tear down the LayerTreeHostImpl before the InputHandlerClient. host_impl_->ReleaseLayerTreeFrameSink(); @@ -14110,7 +14049,8 @@ TEST_F(LayerTreeHostImplTest, FrameCounterReset) { BEGINFRAME_FROM_HERE, 1u /*source_id*/, 2u /*sequence_number*/, now, deadline, interval, viz::BeginFrameArgs::NORMAL); - dropped_frame_counter->OnEndFrame(args, true); + dropped_frame_counter->OnEndFrame( + args, CreateFakeFrameInfo(FrameInfo::FrameFinalState::kDropped)); // FCP not received, so the total_smoothness_dropped_ won't increase. EXPECT_EQ(dropped_frame_counter->total_smoothness_dropped(), 0u); @@ -14118,7 +14058,8 @@ TEST_F(LayerTreeHostImplTest, FrameCounterReset) { begin_frame_metrics.should_measure_smoothness = true; host_impl_->ReadyToCommit(args, &begin_frame_metrics); dropped_frame_counter->SetTimeFcpReceivedForTesting(args.frame_time); - dropped_frame_counter->OnEndFrame(args, true); + dropped_frame_counter->OnEndFrame( + args, CreateFakeFrameInfo(FrameInfo::FrameFinalState::kDropped)); EXPECT_EQ(dropped_frame_counter->total_smoothness_dropped(), 1u); total_frame_counter->set_total_frames_for_testing(1u); @@ -14288,10 +14229,10 @@ TEST_F(LayerTreeHostImplTest, JumpOnScrollbarClick) { InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 400), /*jump_key_modifier*/ false); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_EQ(result.scroll_offset.y(), 525); + EXPECT_EQ(result.scroll_delta.y(), 525); result = GetInputHandler().MouseUp(gfx::PointF(350, 400)); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_EQ(result.scroll_offset.y(), 0); + EXPECT_EQ(result.scroll_delta.y(), 0); } { @@ -14301,10 +14242,10 @@ TEST_F(LayerTreeHostImplTest, JumpOnScrollbarClick) { InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 400), /*jump_key_modifier*/ true); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_FLOAT_EQ(result.scroll_offset.y(), 2194.2856f); + EXPECT_FLOAT_EQ(result.scroll_delta.y(), 2194.2856f); result = GetInputHandler().MouseUp(gfx::PointF(350, 400)); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_EQ(result.scroll_offset.y(), 0); + EXPECT_EQ(result.scroll_delta.y(), 0); } { @@ -14314,10 +14255,10 @@ TEST_F(LayerTreeHostImplTest, JumpOnScrollbarClick) { InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 400), /*jump_key_modifier*/ false); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_FLOAT_EQ(result.scroll_offset.y(), 2194.2856f); + EXPECT_FLOAT_EQ(result.scroll_delta.y(), 2194.2856f); result = GetInputHandler().MouseUp(gfx::PointF(350, 400)); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_EQ(result.scroll_offset.y(), 0); + EXPECT_EQ(result.scroll_delta.y(), 0); } { @@ -14327,10 +14268,10 @@ TEST_F(LayerTreeHostImplTest, JumpOnScrollbarClick) { InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 400), /*jump_key_modifier*/ true); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_EQ(result.scroll_offset.y(), 525); + EXPECT_EQ(result.scroll_delta.y(), 525); result = GetInputHandler().MouseUp(gfx::PointF(350, 400)); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); - EXPECT_EQ(result.scroll_offset.y(), 0); + EXPECT_EQ(result.scroll_delta.y(), 0); } // Tear down the LayerTreeHostImpl before the InputHandlerClient. @@ -14391,8 +14332,8 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ThumbDragAfterJumpClick) { gfx::PointF(350, 560), /*jump_key_modifier*/ true); // This verifies that the jump click took place as expected. - EXPECT_EQ(0, result.scroll_offset.x()); - EXPECT_FLOAT_EQ(result.scroll_offset.y(), 243.80952f); + EXPECT_EQ(0, result.scroll_delta.x()); + EXPECT_FLOAT_EQ(result.scroll_delta.y(), 243.80952f); // This verifies that the drag_state_ was initialized when a jump click // occurred. @@ -14651,7 +14592,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ThumbDragScrollerLengthIncrease) { host_impl_->WillBeginImplFrame(begin_frame_args); InputHandlerPointerResult result = GetInputHandler().MouseDown( gfx::PointF(350, 18), /*jump_key_modifier*/ false); - EXPECT_EQ(result.scroll_offset.y(), 0); + EXPECT_EQ(result.scroll_delta.y(), 0); EXPECT_EQ(result.type, PointerResultType::kScrollbarScroll); host_impl_->DidFinishImplFrame(begin_frame_args); @@ -14661,7 +14602,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ThumbDragScrollerLengthIncrease) { host_impl_->WillBeginImplFrame(begin_frame_args); result = GetInputHandler().MouseMoveAt(gfx::Point(350, 20)); - EXPECT_FLOAT_EQ(result.scroll_offset.y(), 12.190476f); + EXPECT_FLOAT_EQ(result.scroll_delta.y(), 12.190476f); // This is intentional. The thumb drags that follow will test the behavior // *after* the scroller length expansion. @@ -14677,7 +14618,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ThumbDragScrollerLengthIncrease) { begin_frame_args.frame_id.sequence_number++; host_impl_->WillBeginImplFrame(begin_frame_args); result = GetInputHandler().MouseMoveAt(gfx::Point(350, 22)); - EXPECT_EQ(result.scroll_offset.y(), 0); + EXPECT_EQ(result.scroll_delta.y(), 0); host_impl_->DidFinishImplFrame(begin_frame_args); // ----------------------------- Start frame 3 ----------------------------- @@ -14692,7 +14633,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ThumbDragScrollerLengthIncrease) { begin_frame_args.frame_id.sequence_number++; host_impl_->WillBeginImplFrame(begin_frame_args); result = GetInputHandler().MouseMoveAt(gfx::Point(350, 26)); - EXPECT_FLOAT_EQ(result.scroll_offset.y(), 48.761906f); + EXPECT_FLOAT_EQ(result.scroll_delta.y(), 48.761906f); GetInputHandler().MouseUp(gfx::PointF(350, 26)); host_impl_->DidFinishImplFrame(begin_frame_args); @@ -14740,7 +14681,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, MainThreadFallback) { GetInputHandler().MouseDown(gfx::PointF(350, 500), /*jump_key_modifier*/ false); GetInputHandler().MouseUp(gfx::PointF(350, 500)); - EXPECT_EQ(compositor_threaded_scrolling_result.scroll_offset.y(), 525u); + EXPECT_EQ(compositor_threaded_scrolling_result.scroll_delta.y(), 525u); EXPECT_FALSE(GetScrollNode(scroll_layer)->main_thread_scrolling_reasons); // If the scroll_node has a main_thread_scrolling_reason, the @@ -14751,7 +14692,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, MainThreadFallback) { compositor_threaded_scrolling_result = GetInputHandler().MouseDown( gfx::PointF(350, 500), /*jump_key_modifier*/ false); GetInputHandler().MouseUp(gfx::PointF(350, 500)); - EXPECT_EQ(compositor_threaded_scrolling_result.scroll_offset.y(), 0u); + EXPECT_EQ(compositor_threaded_scrolling_result.scroll_delta.y(), 0u); // Tear down the LayerTreeHostImpl before the InputHandlerClient. host_impl_->ReleaseLayerTreeFrameSink(); @@ -14874,7 +14815,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, ScrollAnimatedWithDelay) { begin_frame_args.frame_id.sequence_number++; host_impl_->WillBeginImplFrame(begin_frame_args); host_impl_->UpdateAnimationState(true); - EXPECT_NE(gfx::Vector2dF(), CurrentScrollOffset(scrolling_layer)); + EXPECT_NE(gfx::PointF(), CurrentScrollOffset(scrolling_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); // Second tick after 50ms, animation should be half way done since the @@ -14944,7 +14885,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) { EXPECT_TRUE(GetImplAnimationHost()->HasAnyAnimationTargetingProperty( scrolling_layer->element_id(), TargetProperty::SCROLL_OFFSET)); - EXPECT_NE(gfx::Vector2dF(), CurrentScrollOffset(scrolling_layer)); + EXPECT_NE(gfx::PointF(), CurrentScrollOffset(scrolling_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); begin_frame_args.frame_time = start_time + base::Milliseconds(50); @@ -14981,8 +14922,8 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) { EXPECT_FALSE(GetImplAnimationHost()->HasTickingKeyframeModelForTesting( scrolling_layer->element_id())); - EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(0, y + 50), - CurrentScrollOffset(scrolling_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, y + 50), + CurrentScrollOffset(scrolling_layer)); EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingNode()); host_impl_->DidFinishImplFrame(begin_frame_args); } @@ -15020,7 +14961,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_NE(gfx::Vector2dF(), CurrentScrollOffset(scrolling_layer)); + EXPECT_NE(gfx::PointF(), CurrentScrollOffset(scrolling_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); begin_frame_args.frame_time = start_time + base::Milliseconds(50); @@ -15056,8 +14997,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 100), - CurrentScrollOffset(scrolling_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 100), CurrentScrollOffset(scrolling_layer)); EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingNode()); host_impl_->DidFinishImplFrame(begin_frame_args); } @@ -15102,11 +15042,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimated) { begin_frame_args.frame_id.sequence_number++; BeginImplFrameAndAnimate(begin_frame_args, start_time); - EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10), - CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(5, 10), CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); // Scroll by the inner viewport's max scroll extent, the remainder // should bubble up to the outer viewport. @@ -15120,10 +15058,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimated) { begin_frame_args.frame_id.sequence_number++; BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(350)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 10), - CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(5, 10), CurrentScrollOffset(outer_scroll_layer)); // Scroll by the outer viewport's max scroll extent, it should all go to the // outer viewport. @@ -15137,9 +15074,9 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimated) { begin_frame_args.frame_id.sequence_number++; BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(850)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(100, 100), + EXPECT_POINTF_EQ(gfx::PointF(100, 100), CurrentScrollOffset(outer_scroll_layer)); // Scroll upwards by the max scroll extent. The inner viewport should animate @@ -15154,9 +15091,8 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimated) { begin_frame_args.frame_id.sequence_number++; BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(1200)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(95, 90), + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(inner_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(95, 90), CurrentScrollOffset(outer_scroll_layer)); } @@ -15203,8 +15139,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimatedUpdate) { float inner_y = CurrentScrollOffset(inner_scroll_layer).y(); EXPECT_TRUE(inner_x > 0 && inner_x < 45); EXPECT_TRUE(inner_y > 0 && inner_y < 45); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); // Update target. GetInputHandler().ScrollUpdate( @@ -15219,11 +15154,10 @@ TEST_F(LayerTreeHostImplTimelinesTest, ImplPinchZoomScrollAnimatedUpdate) { begin_frame_args.frame_id.sequence_number++; BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(350)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(50, 50), + EXPECT_POINTF_EQ(gfx::PointF(50, 50), CurrentScrollOffset(inner_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), - CurrentScrollOffset(outer_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(outer_scroll_layer)); } // Test that smooth scroll offset animation doesn't happen for non user @@ -15263,7 +15197,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedNotUserScrollable) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_NE(gfx::Vector2dF(), CurrentScrollOffset(scrolling_layer)); + EXPECT_NE(gfx::PointF(), CurrentScrollOffset(scrolling_layer)); host_impl_->DidFinishImplFrame(begin_frame_args); begin_frame_args.frame_time = start_time + base::Milliseconds(50); @@ -15300,8 +15234,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedNotUserScrollable) { host_impl_->Animate(); host_impl_->UpdateAnimationState(true); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 100), - CurrentScrollOffset(scrolling_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 100), CurrentScrollOffset(scrolling_layer)); // The CurrentlyScrollingNode shouldn't be cleared until a GestureScrollEnd. EXPECT_EQ(scrolling_layer->scroll_tree_index(), host_impl_->CurrentlyScrollingNode()->id); @@ -15356,7 +15289,7 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedChangingBounds) { host_impl_->UpdateAnimationState(true); host_impl_->DidFinishImplFrame(begin_frame_args); - EXPECT_EQ(gfx::Vector2dF(250, 250), CurrentScrollOffset(scrolling_layer)); + EXPECT_EQ(gfx::PointF(250, 250), CurrentScrollOffset(scrolling_layer)); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) { @@ -15463,13 +15396,13 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, .get(), ui::ScrollInputType::kWheel) .thread); - EXPECT_VECTOR_EQ(gfx::Vector2dF(), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 0), CurrentScrollOffset(scroll_layer)); GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), scroll_delta, ui::ScrollInputType::kWheel) .get()); GetInputHandler().ScrollEnd(); - EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5), CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(0, 2.5), CurrentScrollOffset(scroll_layer)); } } @@ -16592,7 +16525,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RenderFrameMetadata) { // Check initial metadata is correct. RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(), metadata.root_scroll_offset); EXPECT_EQ(1, metadata.page_scale_factor); #if defined(OS_ANDROID) @@ -16617,12 +16550,12 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RenderFrameMetadata) { .get()); { RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); } GetInputHandler().ScrollEnd(); { RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); } #if defined(OS_ANDROID) @@ -16686,7 +16619,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RenderFrameMetadata) { { RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); EXPECT_EQ(2, metadata.page_scale_factor); #if defined(OS_ANDROID) @@ -16704,7 +16637,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, RenderFrameMetadata) { { RenderFrameMetadata metadata = StartDrawAndProduceRenderFrameMetadata(); - EXPECT_EQ(gfx::Vector2dF(0, 10), metadata.root_scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), metadata.root_scroll_offset); EXPECT_EQ(4, metadata.page_scale_factor); #if defined(OS_ANDROID) @@ -16999,8 +16932,7 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { child1_transform.Translate(-250, -350); EXPECT_TRUE(child1_transform.ApproximatelyEqual( hit_test_region_list->regions[1].transform)); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - hit_test_region_list->regions[1].rect.ToString()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), hit_test_region_list->regions[1].rect); EXPECT_EQ(child_surface_id.frame_sink_id(), hit_test_region_list->regions[0].frame_sink_id); @@ -17013,8 +16945,7 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { child2_transform.Translate(-450, -300); EXPECT_TRUE(child2_transform.ApproximatelyEqual( hit_test_region_list->regions[0].transform)); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - hit_test_region_list->regions[0].rect.ToString()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), hit_test_region_list->regions[0].rect); } TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, PointerEvents) { @@ -17081,8 +17012,7 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, PointerEvents) { gfx::Transform child1_transform; EXPECT_TRUE(child1_transform.ApproximatelyEqual( hit_test_region_list->regions[0].transform)); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - hit_test_region_list->regions[0].rect.ToString()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), hit_test_region_list->regions[0].rect); } TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, ComplexPage) { @@ -17149,8 +17079,7 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, ComplexPage) { gfx::Transform child1_transform; EXPECT_TRUE(child1_transform.ApproximatelyEqual( hit_test_region_list->regions[0].transform)); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - hit_test_region_list->regions[0].rect.ToString()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), hit_test_region_list->regions[0].rect); } TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, InvalidFrameSinkId) { @@ -17221,8 +17150,7 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, InvalidFrameSinkId) { gfx::Transform child1_transform; EXPECT_TRUE(child1_transform.ApproximatelyEqual( hit_test_region_list->regions[0].transform)); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - hit_test_region_list->regions[0].rect.ToString()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), hit_test_region_list->regions[0].rect); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, @@ -17524,7 +17452,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PercentBasedScrollbarDeltasDSF3) { GetInputHandler().MouseDown(gfx::PointF(190, 490), false); GetInputHandler().MouseUp(gfx::PointF(190, 490)); - EXPECT_EQ(scroll_result.scroll_offset.y(), expected_delta); + EXPECT_EQ(scroll_result.scroll_delta.y(), expected_delta); EXPECT_FALSE(GetScrollNode(scroll_layer)->main_thread_scrolling_reasons); // Test with DSF = 1. As the scrollable layers aren't rescaled by the DSF, @@ -17535,7 +17463,7 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PercentBasedScrollbarDeltasDSF3) { GetInputHandler().MouseDown(gfx::PointF(190, 490), false); GetInputHandler().MouseUp(gfx::PointF(190, 490)); - EXPECT_EQ(scroll_with_dsf_1.scroll_offset.y(), expected_delta); + EXPECT_EQ(scroll_with_dsf_1.scroll_delta.y(), expected_delta); EXPECT_FALSE(GetScrollNode(scroll_layer)->main_thread_scrolling_reasons); // Tear down the LayerTreeHostImpl before the InputHandlerClient. @@ -17579,16 +17507,16 @@ TEST_P(ScrollUnifiedLayerTreeHostImplTest, PageBasedScroll) { BeginImplFrameAndAnimate(begin_frame_args, start_time + base::Milliseconds(2000)); - const gfx::Vector2dF kExpectedDelta( + const gfx::PointF kExpectedOffset( kPageDelta.x() * kViewportSize.width() * kMinFractionToStepWhenPaging, kPageDelta.y() * kViewportSize.height() * kMinFractionToStepWhenPaging); - const gfx::Vector2dF kCurrentDelta = + const gfx::PointF kCurrentOffset = host_impl_->active_tree() ->property_trees() ->scroll_tree.current_scroll_offset( host_impl_->OuterViewportScrollNode()->element_id); - EXPECT_EQ(kExpectedDelta.ToString(), kCurrentDelta.ToString()); + EXPECT_EQ(kExpectedOffset, kCurrentOffset); GetInputHandler().ScrollEnd(); } @@ -17709,12 +17637,12 @@ class UnifiedScrollingTest : public LayerTreeHostImplTest { host_impl_->DidFinishImplFrame(begin_frame_args_); } - gfx::Vector2dF GetScrollOffset(ScrollNode* node) { + gfx::PointF GetScrollOffset(ScrollNode* node) { return GetPropertyTrees()->scroll_tree.current_scroll_offset( node->element_id); } - gfx::Vector2dF ScrollerOffset() { + gfx::PointF ScrollerOffset() { return GetPropertyTrees()->scroll_tree.current_scroll_offset( ScrollerElementId()); } @@ -17746,7 +17674,7 @@ class UnifiedScrollingTest : public LayerTreeHostImplTest { void TestUncompositedScrollingState(bool mutates_transform_tree); private: - LayerImpl* scroller_layer_ = nullptr; + raw_ptr<LayerImpl> scroller_layer_ = nullptr; base::TimeTicks cur_time_; viz::BeginFrameArgs begin_frame_args_; @@ -17791,19 +17719,19 @@ TEST_F(UnifiedScrollingTest, UnifiedScrollNonFastScrollableRegion) { // mutate the associated transform node. { EXPECT_TRUE(ScrollUpdate(gfx::Vector2d(0, 10)).did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, 10), ScrollerOffset()); + EXPECT_EQ(gfx::PointF(0, 10), ScrollerOffset()); } // Try to scroll past the end. Ensure the max scrolling bounds are respected. { EXPECT_TRUE(ScrollUpdate(gfx::Vector2d(0, 1000)).did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, 50), ScrollerOffset()); + EXPECT_EQ(gfx::PointF(0, 50), ScrollerOffset()); } // Overscrolling should cause the scroll update to be dropped. { EXPECT_FALSE(ScrollUpdate(gfx::Vector2d(0, 10)).did_scroll); - EXPECT_EQ(gfx::Vector2dF(0, 50), ScrollerOffset()); + EXPECT_EQ(gfx::PointF(0, 50), ScrollerOffset()); } GetInputHandler().ScrollEnd(); @@ -17821,7 +17749,7 @@ TEST_F(UnifiedScrollingTest, MainThreadHitTestLatchBubbling) { ContinuedScrollBegin(ScrollerElementId()); ScrollUpdate(gfx::Vector2d(0, 1000)); ScrollEnd(); - ASSERT_EQ(gfx::Vector2dF(0, 50), ScrollerOffset()); + ASSERT_EQ(gfx::PointF(0, 50), ScrollerOffset()); } { @@ -17941,7 +17869,7 @@ void UnifiedScrollingTest::TestUncompositedScrollingState( ASSERT_EQ(transform_node->element_id, ScrollerElementId()); ASSERT_TRUE(transform_node->scrolls); - ASSERT_EQ(gfx::Vector2dF(0, 0), transform_node->scroll_offset); + ASSERT_EQ(gfx::PointF(0, 0), transform_node->scroll_offset); ASSERT_FALSE(transform_node->transform_changed); ASSERT_FALSE(transform_node->needs_local_transform_update); ASSERT_FALSE(tree.needs_update()); @@ -17960,14 +17888,14 @@ void UnifiedScrollingTest::TestUncompositedScrollingState( did_request_commit_ = false; ScrollUpdate(gfx::Vector2d(0, 10)); - ASSERT_EQ(gfx::Vector2dF(0, 10), ScrollerOffset()); + ASSERT_EQ(gfx::PointF(0, 10), ScrollerOffset()); EXPECT_TRUE(did_request_commit_); // Ensure the transform tree was updated only if expected. if (mutates_transform_tree) - EXPECT_EQ(gfx::Vector2dF(0, 10), transform_node->scroll_offset); + EXPECT_EQ(gfx::PointF(0, 10), transform_node->scroll_offset); else - EXPECT_EQ(gfx::Vector2dF(0, 0), transform_node->scroll_offset); + EXPECT_EQ(gfx::PointF(0, 0), transform_node->scroll_offset); EXPECT_EQ(mutates_transform_tree, transform_node->transform_changed); EXPECT_EQ(mutates_transform_tree, transform_node->needs_local_transform_update); @@ -17980,20 +17908,20 @@ void UnifiedScrollingTest::TestUncompositedScrollingState( AnimatedScrollUpdate(gfx::Vector2d(0, 10)); ASSERT_TRUE(host_impl_->mutator_host()->ImplOnlyScrollAnimatingElement()); - ASSERT_EQ(gfx::Vector2dF(0, 10), ScrollerOffset()); + ASSERT_EQ(gfx::PointF(0, 10), ScrollerOffset()); StartAnimation(); BeginFrame(kFrameInterval); BeginFrame(base::Milliseconds(500)); BeginFrame(kFrameInterval); - ASSERT_EQ(gfx::Vector2dF(0, 20), ScrollerOffset()); + ASSERT_EQ(gfx::PointF(0, 20), ScrollerOffset()); EXPECT_TRUE(did_request_commit_); if (mutates_transform_tree) - EXPECT_EQ(gfx::Vector2dF(0, 20), transform_node->scroll_offset); + EXPECT_EQ(gfx::PointF(0, 20), transform_node->scroll_offset); else - EXPECT_EQ(gfx::Vector2dF(0, 0), transform_node->scroll_offset); + EXPECT_EQ(gfx::PointF(0, 0), transform_node->scroll_offset); EXPECT_EQ(mutates_transform_tree, transform_node->transform_changed); EXPECT_EQ(mutates_transform_tree, transform_node->needs_local_transform_update); @@ -18026,10 +17954,10 @@ TEST_F(UnifiedScrollingTest, MainThreadReasonsScrollDoesntAffectTransform) { host_impl_->active_tree()->DidBecomeActive(); ScrollUpdate(gfx::Vector2d(0, 10)); - ASSERT_EQ(gfx::Vector2dF(0, 30), ScrollerOffset()); + ASSERT_EQ(gfx::PointF(0, 30), ScrollerOffset()); // The transform node should now be updated by the scroll. - EXPECT_EQ(gfx::Vector2dF(0, 30), transform_node->scroll_offset); + EXPECT_EQ(gfx::PointF(0, 30), transform_node->scroll_offset); EXPECT_TRUE(transform_node->transform_changed); EXPECT_TRUE(transform_node->needs_local_transform_update); EXPECT_TRUE(tree.needs_update()); @@ -18057,10 +17985,10 @@ TEST_F(UnifiedScrollingTest, UncompositedScrollerDoesntAffectTransform) { host_impl_->active_tree()->DidBecomeActive(); ScrollUpdate(gfx::Vector2d(0, 10)); - ASSERT_EQ(gfx::Vector2dF(0, 30), ScrollerOffset()); + ASSERT_EQ(gfx::PointF(0, 30), ScrollerOffset()); // The transform node should now be updated by the scroll. - EXPECT_EQ(gfx::Vector2dF(0, 30), transform_node->scroll_offset); + EXPECT_EQ(gfx::PointF(0, 30), transform_node->scroll_offset); EXPECT_TRUE(transform_node->transform_changed); EXPECT_TRUE(transform_node->needs_local_transform_update); EXPECT_TRUE(tree.needs_update()); @@ -18108,7 +18036,7 @@ TEST_F(OccludedSurfaceThrottlingLayerTreeHostImplTest, } TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestSimple) { - SetupDefaultRootLayer(gfx::Size(100, 100)); + SetupDefaultRootLayer(); LayerImpl* frame_layer = AddLayer(); frame_layer->SetBounds(gfx::Size(50, 50)); @@ -18124,7 +18052,7 @@ TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestSimple) { } TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestInheritance) { - SetupDefaultRootLayer(gfx::Size(100, 100)); + SetupDefaultRootLayer(); LayerImpl* frame_layer = AddLayer(); frame_layer->SetBounds(gfx::Size(50, 50)); @@ -18157,7 +18085,7 @@ TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestInheritance) { } TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlap) { - SetupDefaultRootLayer(gfx::Size(100, 100)); + SetupDefaultRootLayer(); LayerImpl* frame_layer = AddLayer(); frame_layer->SetBounds(gfx::Size(50, 50)); @@ -18186,7 +18114,7 @@ TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlap) { } TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlapSimpleClip) { - SetupDefaultRootLayer(gfx::Size(100, 100)); + SetupDefaultRootLayer(); LayerImpl* frame_layer = AddLayer(); frame_layer->SetBounds(gfx::Size(50, 50)); @@ -18214,7 +18142,7 @@ TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlapSimpleClip) { } TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlapRoundedCorners) { - SetupDefaultRootLayer(gfx::Size(100, 100)); + SetupDefaultRootLayer(); LayerImpl* frame_layer = AddLayer(); frame_layer->SetBounds(gfx::Size(50, 50)); @@ -18244,7 +18172,7 @@ TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlapRoundedCorners) { } TEST_F(LayerTreeHostImplTest, FrameElementIdHitTestOverlapSibling) { - SetupDefaultRootLayer(gfx::Size(100, 100)); + SetupDefaultRootLayer(); LayerImpl* frame_layer = AddLayer(); frame_layer->SetBounds(gfx::Size(50, 50)); @@ -18309,4 +18237,74 @@ TEST_F(LayerTreeHostImplTest, DocumentTransitionRequestCausesDamage) { EXPECT_FALSE(last_on_draw_frame_->has_no_damage); } +TEST_F(LayerTreeHostImplTest, CollectRegionCaptureBounds) { + const auto kFirstId = viz::RegionCaptureCropId::CreateRandom(); + const auto kSecondId = viz::RegionCaptureCropId::CreateRandom(); + const auto kThirdId = viz::RegionCaptureCropId::CreateRandom(); + const auto kFourthId = viz::RegionCaptureCropId::CreateRandom(); + + const viz::RegionCaptureBounds kRootBounds{ + {{kFirstId, gfx::Rect{0, 0, 250, 250}}, {kSecondId, gfx::Rect{}}}}; + const viz::RegionCaptureBounds kChildBounds{ + {{kThirdId, gfx::Rect{5, 6, 300, 400}}}}; + const viz::RegionCaptureBounds kSecondChildBounds{ + {{kFourthId, gfx::Rect{20, 10, 400, 500}}}}; + + // Set up the root layer. + LayerImpl* root_layer = SetupDefaultRootLayer(gfx::Size(350, 360)); + root_layer->SetCaptureBounds( + std::make_unique<viz::RegionCaptureBounds>(kRootBounds)); + + // Set up a child layer, with a scaling transform. + LayerImpl* child_layer = AddLayer(); + CopyProperties(root_layer, child_layer); + child_layer->SetCaptureBounds( + std::make_unique<viz::RegionCaptureBounds>(kChildBounds)); + gfx::Transform child_layer_transform; + child_layer_transform.Scale(2.0, 3.0); + child_layer->draw_properties().screen_space_transform = + std::move(child_layer_transform); + + // Set up another child layer, with a rotation transform. + LayerImpl* second_child_layer = AddLayer(); + CopyProperties(root_layer, second_child_layer); + second_child_layer->SetCaptureBounds( + std::make_unique<viz::RegionCaptureBounds>(kSecondChildBounds)); + gfx::Transform second_layer_transform; + second_layer_transform.Rotate(45); + second_child_layer->draw_properties().screen_space_transform = + std::move(second_layer_transform); + + // Set up the drawable content rect and transforms for the root surface. + // Drawing the frame sets up the RenderSurfaceImpl in the backend. + UpdateDrawProperties(host_impl_->active_tree()); + DrawFrame(); + + // NOTE: setting contribution has to be done after updating and drawing, and + // causes the layers to use draw_properties().screen_screen_transform instead + // of using values from the transform tree. + child_layer->set_contributes_to_drawn_render_surface(true); + second_child_layer->set_contributes_to_drawn_render_surface(true); + + // Actually collect the region capture bounds. + const viz::RegionCaptureBounds collected_bounds = + host_impl_->CollectRegionCaptureBounds(); + EXPECT_EQ(4u, collected_bounds.bounds().size()); + + // Validate expectations. + EXPECT_EQ((gfx::Rect{0, 0, 250, 250}), + collected_bounds.bounds().find(kFirstId)->second); + EXPECT_EQ((gfx::Rect{}), collected_bounds.bounds().find(kSecondId)->second); + + // The third case is more interesting: the bounds are scaled 2x and 3x, + // which changes the origin but also causes both bounds to clip at the + // content rect. + EXPECT_EQ((gfx::Rect{10, 18, 340, 342}), + collected_bounds.bounds().find(kThirdId)->second); + + // Finally, test a rotation instead of a simple scaling. + EXPECT_EQ((gfx::Rect{0, 21, 290, 339}), + collected_bounds.bounds().find(kFourthId)->second); +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 92759e7b123..903a4826092 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/trees/layer_tree_host.h" - #include <stdint.h> #include <sstream> @@ -11,6 +9,7 @@ #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "base/strings/string_piece.h" #include "base/time/time.h" @@ -23,6 +22,7 @@ #include "cc/test/layer_tree_json_parser.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_layer_tree_frame_sink.h" +#include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "components/viz/test/paths.h" #include "gpu/command_buffer/common/mailbox.h" @@ -228,7 +228,7 @@ class LayerTreeHostPerfTestLeafInvalidates } protected: - Layer* layer_to_invalidate_; + raw_ptr<Layer> layer_to_invalidate_; }; // Simulates a tab switcher scene with two stacks of 10 tabs each. Invalidate a @@ -314,7 +314,7 @@ class BrowserCompositorInvalidateLayerTreePerfTest ASSERT_TRUE(tab_contents_.get()); } - void WillCommit() override { + void WillCommit(const CommitState&) override { if (CleanUpStarted()) return; gpu::Mailbox gpu_mailbox; diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc index b734b02d11f..ca78ed155e9 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc @@ -88,8 +88,8 @@ class LayerTreeHostReadbackPixelTest void BeginTest() override { if (insert_copy_request_after_frame_count_ == 0) { - Layer* const target = - readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); + Layer* const target = readback_target_ ? readback_target_.get() + : layer_tree_host()->root_layer(); target->RequestCopyOfOutput(CreateCopyOutputRequest()); } PostSetNeedsCommitToMainThread(); @@ -98,8 +98,8 @@ class LayerTreeHostReadbackPixelTest void DidCommitAndDrawFrame() override { if (insert_copy_request_after_frame_count_ == layer_tree_host()->SourceFrameNumber()) { - Layer* const target = - readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); + Layer* const target = readback_target_ ? readback_target_.get() + : layer_tree_host()->root_layer(); target->RequestCopyOfOutput(CreateCopyOutputRequest()); } } diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index c82cf696f1c..eb222dffeb8 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -44,8 +44,8 @@ class LayerTreeHostTilesPixelTest } void DoReadback() { - Layer* target = - readback_target_ ? readback_target_ : layer_tree_host()->root_layer(); + Layer* target = readback_target_ ? readback_target_.get() + : layer_tree_host()->root_layer(); target->RequestCopyOfOutput(CreateCopyOutputRequest()); } diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 22c72b81428..42dadea3f19 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -15,8 +15,9 @@ #include "base/callback_helpers.h" #include "base/containers/contains.h" #include "base/location.h" -#include "base/single_thread_task_runner.h" +#include "base/memory/raw_ptr.h" #include "base/synchronization/lock.h" +#include "base/task/single_thread_task_runner.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_tick_clock.h" @@ -38,6 +39,7 @@ #include "cc/paint/image_animation_count.h" #include "cc/resources/ui_resource_manager.h" #include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_frame_info.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_paint_image_generator.h" #include "cc/test/fake_painted_scrollbar_layer.h" @@ -47,9 +49,9 @@ #include "cc/test/fake_recording_source.h" #include "cc/test/fake_scoped_ui_resource.h" #include "cc/test/fake_video_frame_provider.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" #include "cc/test/layer_tree_test.h" +#include "cc/test/mock_latency_info_swap_promise_monitor.h" #include "cc/test/push_properties_counting_layer.h" #include "cc/test/push_properties_counting_layer_impl.h" #include "cc/test/render_pass_test_utils.h" @@ -88,6 +90,7 @@ #include "ui/gfx/animation/keyframe/timing_function.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/vector2d_conversions.h" #define EXPECT_SCOPED(statements) \ @@ -100,6 +103,7 @@ using testing::_; using testing::AnyNumber; using testing::AtLeast; using testing::Mock; +using testing::StrictMock; namespace cc { namespace { @@ -115,6 +119,12 @@ bool LayerSubtreeHasCopyRequest(Layer* layer) { return node->subtree_has_copy_request; } +FrameInfo CreateFakeImplDroppedFrameInfo() { + auto info = CreateFakeFrameInfo(FrameInfo::FrameFinalState::kDropped); + info.main_thread_response = FrameInfo::MainThreadResponse::kMissing; + return info; +} + using LayerTreeHostTest = LayerTreeTest; class LayerTreeHostTestHasImplThreadTest : public LayerTreeHostTest { @@ -273,7 +283,7 @@ class LayerTreeHostTestRequestedMainFrame : public LayerTreeHostTest { void NextStep() { // The MainFrame request is cleared once a MainFrame happens. - EXPECT_FALSE(layer_tree_host()->RequestedMainFramePendingForTesting()); + EXPECT_FALSE(layer_tree_host()->RequestedMainFramePending()); switch (layer_tree_host()->SourceFrameNumber()) { case 0: ADD_FAILURE() @@ -293,7 +303,7 @@ class LayerTreeHostTestRequestedMainFrame : public LayerTreeHostTest { return; } // SetNeeds{Animate,UpdateLayers,Commit}() will mean a MainFrame is pending. - EXPECT_TRUE(layer_tree_host()->RequestedMainFramePendingForTesting()); + EXPECT_TRUE(layer_tree_host()->RequestedMainFramePending()); } }; @@ -605,8 +615,8 @@ class LayerTreeHostContextCacheTest : public LayerTreeHostTest { void(bool aggressively_free_resources)); }; - MockContextSupport* mock_main_context_support_; - MockContextSupport* mock_worker_context_support_; + raw_ptr<MockContextSupport> mock_main_context_support_; + raw_ptr<MockContextSupport> mock_worker_context_support_; }; // Test if the LTH successfully frees resources on the main/worker @@ -1023,6 +1033,17 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void WillCommit(const CommitState&) override { + root_transform_index_ = root_->transform_tree_index(); + child_transform_index_ = child_->transform_tree_index(); + root_effect_index_ = root_->effect_tree_index(); + child_effect_index_ = child_->effect_tree_index(); + root_clip_index_ = root_->clip_tree_index(); + child_clip_index_ = child_->clip_tree_index(); + root_scroll_index_ = root_->scroll_tree_index(); + child_scroll_index_ = child_->scroll_tree_index(); + } + void DidCommit() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: @@ -1049,21 +1070,21 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { PropertyTrees* property_trees = impl->sync_tree()->property_trees(); const TransformNode* root_transform_node = - property_trees->transform_tree.Node(root_->transform_tree_index()); + property_trees->transform_tree.Node(root_transform_index_); const TransformNode* child_transform_node = - property_trees->transform_tree.Node(child_->transform_tree_index()); + property_trees->transform_tree.Node(child_transform_index_); const EffectNode* root_effect_node = - property_trees->effect_tree.Node(root_->effect_tree_index()); + property_trees->effect_tree.Node(root_effect_index_); const EffectNode* child_effect_node = - property_trees->effect_tree.Node(child_->effect_tree_index()); + property_trees->effect_tree.Node(child_effect_index_); const ClipNode* root_clip_node = - property_trees->clip_tree.Node(root_->clip_tree_index()); + property_trees->clip_tree.Node(root_clip_index_); const ClipNode* child_clip_node = - property_trees->clip_tree.Node(child_->clip_tree_index()); + property_trees->clip_tree.Node(child_clip_index_); const ScrollNode* root_scroll_node = - property_trees->scroll_tree.Node(root_->scroll_tree_index()); + property_trees->scroll_tree.Node(root_scroll_index_); const ScrollNode* child_scroll_node = - property_trees->scroll_tree.Node(child_->scroll_tree_index()); + property_trees->scroll_tree.Node(child_scroll_index_); switch (impl->sync_tree()->source_frame_number()) { case 0: // root_ should create transform, scroll and effect tree nodes but not @@ -1109,6 +1130,14 @@ class LayerTreeHostTestPushNodeOwnerToNodeIdMap : public LayerTreeHostTest { private: scoped_refptr<Layer> root_; scoped_refptr<Layer> child_; + int root_transform_index_ = TransformTree::kInvalidNodeId; + int child_transform_index_ = TransformTree::kInvalidNodeId; + int root_effect_index_ = EffectTree::kInvalidNodeId; + int child_effect_index_ = EffectTree::kInvalidNodeId; + int root_clip_index_ = ClipTree::kInvalidNodeId; + int child_clip_index_ = ClipTree::kInvalidNodeId; + int root_scroll_index_ = ScrollTree::kInvalidNodeId; + int child_scroll_index_ = ScrollTree::kInvalidNodeId; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPushNodeOwnerToNodeIdMap); @@ -1443,7 +1472,7 @@ class LayerTreeHostTestLayerListSurfaceDamage : public LayerTreeHostTest { } private: - Layer* root_; + raw_ptr<Layer> root_; scoped_refptr<Layer> child_a_; scoped_refptr<Layer> child_b_; scoped_refptr<Layer> child_c_; @@ -2037,9 +2066,14 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void WillCommit(const CommitState&) override { + root_effect_tree_index_ = + layer_tree_host()->root_layer()->effect_tree_index(); + } + void DidCommit() override { EffectTree& effect_tree = layer_tree_host()->property_trees()->effect_tree; - EffectNode* node = effect_tree.Node(root_->effect_tree_index()); + EffectNode* node = effect_tree.Node(root_effect_tree_index_); switch (layer_tree_host()->SourceFrameNumber()) { case 1: node->opacity = 0.5f; @@ -2075,7 +2109,7 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { EffectTree& effect_tree = impl->sync_tree()->property_trees()->effect_tree; LayerImpl* root = impl->sync_tree()->root_layer(); - EffectNode* node = effect_tree.Node(root->effect_tree_index()); + EffectNode* node = effect_tree.Node(root_effect_tree_index_); switch (impl->sync_tree()->source_frame_number()) { case 0: impl->sync_tree()->SetOpacityMutated(root->element_id(), 0.75f); @@ -2123,6 +2157,7 @@ class LayerTreeHostTestEffectTreeSync : public LayerTreeHostTest { private: scoped_refptr<Layer> root_; + int root_effect_tree_index_ = EffectTree::kInvalidNodeId; FilterOperations blur_filter_; FilterOperations brightness_filter_; FilterOperations sepia_filter_; @@ -2146,10 +2181,14 @@ class LayerTreeHostTestTransformTreeSync : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void WillCommit(const CommitState&) override { + transform_tree_index_ = layer_->transform_tree_index(); + } + void DidCommit() override { TransformTree& transform_tree = layer_tree_host()->property_trees()->transform_tree; - TransformNode* node = transform_tree.Node(layer_->transform_tree_index()); + TransformNode* node = transform_tree.Node(transform_tree_index_); gfx::Transform rotate10; rotate10.Rotate(10.f); switch (layer_tree_host()->SourceFrameNumber()) { @@ -2206,6 +2245,7 @@ class LayerTreeHostTestTransformTreeSync : public LayerTreeHostTest { private: scoped_refptr<Layer> layer_; + int transform_tree_index_ = TransformTree::kInvalidNodeId; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestTransformTreeSync); @@ -3503,7 +3543,7 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest { scroll_layer_->SetBounds(gfx::Size(2 * root_layer->bounds().width(), 2 * root_layer->bounds().height())); - scroll_layer_->SetScrollOffset(gfx::Vector2dF()); + scroll_layer_->SetScrollOffset(gfx::PointF()); SetupViewport(root_layer, scroll_layer_, root_layer->bounds()); @@ -3514,7 +3554,7 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override { - gfx::Vector2dF offset = CurrentScrollOffset(scroll_layer_.get()); + gfx::PointF offset = CurrentScrollOffset(scroll_layer_.get()); SetScrollOffset(scroll_layer_.get(), offset + args.inner_delta); layer_tree_host()->SetPageScaleFactorAndLimits(args.page_scale_delta, 0.5f, 2.f); @@ -3546,8 +3586,8 @@ class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest { void DidCommitAndDrawFrame() override { switch (layer_tree_host()->SourceFrameNumber()) { case 1: - layer_tree_host()->StartPageScaleAnimation(gfx::Vector2d(), false, - 1.25f, base::TimeDelta()); + layer_tree_host()->StartPageScaleAnimation(gfx::Point(), false, 1.25f, + base::TimeDelta()); break; } } @@ -3595,12 +3635,12 @@ class ViewportDeltasAppliedDuringPinch : public LayerTreeHostTest, auto* scroll_layer = layer_tree_host()->InnerViewportScrollLayerForTesting(); EXPECT_EQ(scroll_layer->element_id(), last_scrolled_element_id_); - EXPECT_EQ(gfx::Vector2dF(50, 50), last_scrolled_offset_); + EXPECT_EQ(gfx::PointF(50, 50), last_scrolled_offset_); // The scroll offset in the scroll tree is typically updated from blink // which doesn't exist in this test. Because we preemptively apply the // scroll offset in LayerTreeHost::UpdateScrollOffsetFromImpl, the current // scroll offset will still be updated. - EXPECT_EQ(gfx::Vector2dF(50, 50), CurrentScrollOffset(scroll_layer)); + EXPECT_EQ(gfx::PointF(50, 50), CurrentScrollOffset(scroll_layer)); EndTest(); } @@ -3608,7 +3648,7 @@ class ViewportDeltasAppliedDuringPinch : public LayerTreeHostTest, // ScrollCallbacks void DidCompositorScroll(ElementId element_id, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, const absl::optional<TargetSnapAreaElementIds>& snap_target_ids) override { last_scrolled_element_id_ = element_id; @@ -3619,7 +3659,7 @@ class ViewportDeltasAppliedDuringPinch : public LayerTreeHostTest, private: bool sent_gesture_; ElementId last_scrolled_element_id_; - gfx::Vector2dF last_scrolled_offset_; + gfx::PointF last_scrolled_offset_; base::WeakPtrFactory<ViewportDeltasAppliedDuringPinch> weak_ptr_factory_{ this}; }; @@ -3634,7 +3674,7 @@ class LayerTreeHostTestSetVisible : public LayerTreeHostTest { PostSetNeedsCommitToMainThread(); } - void WillCommit() override { + void WillCommit(const CommitState&) override { PostSetVisibleToMainThread(false); // This is suppressed while we're invisible. PostSetNeedsRedrawToMainThread(); @@ -3737,9 +3777,8 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers child_transform.Scale(child->MaximumTilingContentsScale(), child->MaximumTilingContentsScale()); - EXPECT_TRANSFORMATION_MATRIX_EQ(child_transform, child->DrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(child_transform, - child->ScreenSpaceTransform()); + EXPECT_TRANSFORM_EQ(child_transform, child->DrawTransform()); + EXPECT_TRANSFORM_EQ(child_transform, child->ScreenSpaceTransform()); EndTest(); } @@ -4373,7 +4412,7 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor } } - OnDrawLayerTreeFrameSink* layer_tree_frame_sink_ = nullptr; + raw_ptr<OnDrawLayerTreeFrameSink> layer_tree_frame_sink_ = nullptr; }; // TODO(crbug.com/1121690): Test is flaky. @@ -4653,36 +4692,49 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest { // The scrollbar layer always needs to be pushed. if (root_->layer_tree_host()) { EXPECT_FALSE(base::Contains( - root_->layer_tree_host()->LayersThatShouldPushProperties(), + static_cast<const LayerTreeHost*>(root_->layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, root_.get())); } if (child2_->layer_tree_host()) { EXPECT_FALSE(base::Contains( - child2_->layer_tree_host()->LayersThatShouldPushProperties(), + static_cast<const LayerTreeHost*>(child2_->layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, child2_.get())); } if (leaf_always_pushing_layer_->layer_tree_host()) { leaf_always_pushing_layer_->SetNeedsPushProperties(); - EXPECT_TRUE(base::Contains(leaf_always_pushing_layer_->layer_tree_host() - ->LayersThatShouldPushProperties(), - leaf_always_pushing_layer_.get())); + EXPECT_TRUE( + base::Contains(static_cast<const LayerTreeHost*>( + leaf_always_pushing_layer_->layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + leaf_always_pushing_layer_.get())); } // child_ and grandchild_ don't persist their need to push properties. if (child_->layer_tree_host()) { EXPECT_FALSE(base::Contains( - child_->layer_tree_host()->LayersThatShouldPushProperties(), + static_cast<const LayerTreeHost*>(child_->layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, child_.get())); } if (grandchild_->layer_tree_host()) { EXPECT_FALSE(base::Contains( - grandchild_->layer_tree_host()->LayersThatShouldPushProperties(), + static_cast<const LayerTreeHost*>(grandchild_->layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild_.get())); } if (other_root_->layer_tree_host()) { EXPECT_FALSE(base::Contains( - other_root_->layer_tree_host()->LayersThatShouldPushProperties(), + static_cast<const LayerTreeHost*>(other_root_->layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, other_root_.get())); } @@ -5033,7 +5085,9 @@ class LayerTreeHostTestPropertyChangesDuringUpdateArePushed scrollbar_layer_->SetBounds(gfx::Size(30, 30)); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, scrollbar_layer_.get())); layer_tree_host()->SetNeedsCommit(); @@ -5076,10 +5130,16 @@ class LayerTreeHostTestSetDrawableCausesCommit : public LayerTreeHostTest { // avoid causing a second commit to be scheduled. If a property change // is made during this, however, it needs to be pushed in the upcoming // commit. - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EXPECT_EQ(0, root_->NumDescendantsThatDrawContent()); root_->reset_push_properties_count(); child_->reset_push_properties_count(); @@ -5087,19 +5147,31 @@ class LayerTreeHostTestSetDrawableCausesCommit : public LayerTreeHostTest { EXPECT_EQ(1, root_->NumDescendantsThatDrawContent()); EXPECT_EQ(0u, root_->push_properties_count()); EXPECT_EQ(0u, child_->push_properties_count()); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); break; } case 2: EXPECT_EQ(1u, root_->push_properties_count()); EXPECT_EQ(1u, child_->push_properties_count()); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EndTest(); break; } @@ -5162,18 +5234,30 @@ class LayerTreeHostTestPushPropertiesAddingToTreeRequiresPush case 0: // All layers will need push properties as we set their layer tree host layer_tree_host()->SetRootLayer(root_); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); break; case 1: @@ -5195,82 +5279,140 @@ class LayerTreeHostTestPushPropertiesRemovingChildStopsRecursion layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); grandchild1_->RemoveFromParent(); grandchild1_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); child_->AddChild(grandchild1_); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); // grandchild2_ will still need a push properties. grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); // grandchild3_ does not need a push properties, so recursing should // no longer be needed. grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EndTest(); break; } @@ -5294,36 +5436,60 @@ class LayerTreeHostTestPushPropertiesRemovingChildStopsRecursionWithPersistence layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); // grandchild2_ will still need a push properties. grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); // grandchild3_ does not need a push properties, so recursing should // no longer be needed. grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EndTest(); break; } @@ -5343,18 +5509,30 @@ class LayerTreeHostTestPushPropertiesSetPropertiesWhileOutsideTree layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); // Change grandchildren while their parent is not in the tree. @@ -5363,40 +5541,70 @@ class LayerTreeHostTestPushPropertiesSetPropertiesWhileOutsideTree grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); root_->AddChild(child_); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); grandchild3_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EndTest(); break; @@ -5417,56 +5625,95 @@ class LayerTreeHostTestPushPropertiesSetPropertyInParentThenChild layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); child_->SetPosition(gfx::PointF(1.f, 1.f)); grandchild1_->SetPosition(gfx::PointF(1.f, 1.f)); grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); child_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); EndTest(); break; @@ -5487,56 +5734,95 @@ class LayerTreeHostTestPushPropertiesSetPropertyInChildThenParent layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); grandchild1_->SetPosition(gfx::PointF(1.f, 1.f)); grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); child_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild1_.get())); EXPECT_TRUE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild2_.get())); EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, grandchild3_.get())); grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); + EXPECT_TRUE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + child_.get())); child_->RemoveFromParent(); - EXPECT_FALSE(base::Contains( - layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); + EXPECT_FALSE( + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, + root_.get())); EndTest(); break; @@ -5698,7 +5984,9 @@ class LayerTreeHostTestPushHiddenLayer : public LayerTreeHostTest { case 1: // The layer type used does not need to push properties every frame. EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, child_layer_.get())); // Change the bounds of the child layer, but make it skipped @@ -5709,7 +5997,9 @@ class LayerTreeHostTestPushHiddenLayer : public LayerTreeHostTest { case 2: // The bounds of the child layer were pushed to the impl side. EXPECT_FALSE( - base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + base::Contains(const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties, child_layer_.get())); EndTest(); @@ -5861,8 +6151,8 @@ class LayerTreeHostTestElasticOverscroll : public LayerTreeHostTest { private: FakeContentLayerClient client_; - Layer* root_layer_; - ScrollElasticityHelper* scroll_elasticity_helper_; + raw_ptr<Layer> root_layer_; + raw_ptr<ScrollElasticityHelper> scroll_elasticity_helper_; int content_layer_id_; int num_draws_; }; @@ -5926,11 +6216,11 @@ class TestSwapPromise : public SwapPromise { void set_action(DidNotSwapAction action) { action_ = action; } - int64_t TraceId() const override { return 0; } + int64_t GetTraceId() const override { return 0; } private: // Not owned. - TestSwapPromiseResult* result_; + raw_ptr<TestSwapPromiseResult> result_; DidNotSwapAction action_ = DidNotSwapAction::BREAK_PROMISE; }; @@ -6349,28 +6639,6 @@ class LayerTreeHostTestDeferSwapPromiseForVisibility SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeferSwapPromiseForVisibility); -class SimpleSwapPromiseMonitor : public SwapPromiseMonitor { - public: - SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host, - int* set_needs_commit_count, - int* set_needs_redraw_count) - : SwapPromiseMonitor(layer_tree_host - ? layer_tree_host->GetSwapPromiseManager() - : nullptr), - set_needs_commit_count_(set_needs_commit_count) {} - - ~SimpleSwapPromiseMonitor() override = default; - - void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; } - - void OnSetNeedsRedrawOnImpl() override { - ADD_FAILURE() << "Should not get called on main thread."; - } - - private: - int* set_needs_commit_count_; -}; - class LayerTreeHostTestSwapPromiseDuringCommit : public LayerTreeHostTest { protected: LayerTreeHostTestSwapPromiseDuringCommit() = default; @@ -6379,20 +6647,19 @@ class LayerTreeHostTestSwapPromiseDuringCommit : public LayerTreeHostTest { if (TestEnded()) return; - std::unique_ptr<SwapPromise> swap_promise( - new TestSwapPromise(&swap_promise_result_[0])); - int set_needs_commit_count = 0; - int set_needs_redraw_count = 0; + std::unique_ptr<SwapPromise> swap_promise = + std::make_unique<TestSwapPromise>(&swap_promise_result_[0]); { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(layer_tree_host(), - &set_needs_commit_count, - &set_needs_redraw_count)); - layer_tree_host()->QueueSwapPromise(std::move(swap_promise)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor( + layer_tree_host()->GetSwapPromiseManager()); + // Queueing a swap promise from WillBeginMainFrame should not cause // another commit to be scheduled. - EXPECT_EQ(0, set_needs_commit_count); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(0); + + layer_tree_host()->QueueSwapPromise(std::move(swap_promise)); } } @@ -6402,20 +6669,19 @@ class LayerTreeHostTestSwapPromiseDuringCommit : public LayerTreeHostTest { if (TestEnded()) return; - std::unique_ptr<SwapPromise> swap_promise( - new TestSwapPromise(&swap_promise_result_[1])); - int set_needs_commit_count = 0; - int set_needs_redraw_count = 0; + std::unique_ptr<SwapPromise> swap_promise = + std::make_unique<TestSwapPromise>(&swap_promise_result_[1]); { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(layer_tree_host(), - &set_needs_commit_count, - &set_needs_redraw_count)); - layer_tree_host()->QueueSwapPromise(std::move(swap_promise)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor( + layer_tree_host()->GetSwapPromiseManager()); + // Queueing a swap promise from DidBeginMainFrame should not cause a // subsequent main frame to be scheduled. - EXPECT_EQ(0, set_needs_commit_count); + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(0); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(0); + + layer_tree_host()->QueueSwapPromise(std::move(swap_promise)); } EndTest(); @@ -6426,7 +6692,8 @@ class LayerTreeHostTestSwapPromiseDuringCommit : public LayerTreeHostTest { MULTI_THREAD_TEST_F(LayerTreeHostTestSwapPromiseDuringCommit); -class LayerTreeHostTestSimpleSwapPromiseMonitor : public LayerTreeHostTest { +class LayerTreeHostTestLatencyInfoSwapPromiseMonitor + : public LayerTreeHostTest { public: void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -6434,50 +6701,41 @@ class LayerTreeHostTestSimpleSwapPromiseMonitor : public LayerTreeHostTest { if (TestEnded()) return; - int set_needs_commit_count = 0; - int set_needs_redraw_count = 0; - { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(layer_tree_host(), - &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor( + layer_tree_host()->GetSwapPromiseManager()); + + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(1); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(0); + layer_tree_host()->SetNeedsCommit(); - EXPECT_EQ(1, set_needs_commit_count); - EXPECT_EQ(0, set_needs_redraw_count); } - // Now the monitor is destroyed, SetNeedsCommit() is no longer being - // monitored. - layer_tree_host()->SetNeedsCommit(); - EXPECT_EQ(1, set_needs_commit_count); - EXPECT_EQ(0, set_needs_redraw_count); - { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(layer_tree_host(), - &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor( + layer_tree_host()->GetSwapPromiseManager()); + + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(1); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(0); + layer_tree_host()->SetNeedsUpdateLayers(); - EXPECT_EQ(2, set_needs_commit_count); - EXPECT_EQ(0, set_needs_redraw_count); } { - std::unique_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor( - new SimpleSwapPromiseMonitor(layer_tree_host(), - &set_needs_commit_count, - &set_needs_redraw_count)); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor( + layer_tree_host()->GetSwapPromiseManager()); + + EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(1); + EXPECT_CALL(monitor, OnSetNeedsRedrawOnImpl()).Times(0); + layer_tree_host()->SetNeedsAnimate(); - EXPECT_EQ(3, set_needs_commit_count); - EXPECT_EQ(0, set_needs_redraw_count); } EndTest(); } }; -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSimpleSwapPromiseMonitor); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLatencyInfoSwapPromiseMonitor); class LayerTreeHostTestHighResRequiredAfterEvictingUIResources : public LayerTreeHostTest { @@ -6569,8 +6827,8 @@ class LayerTreeHostTestGpuRasterizationDisabled : public LayerTreeHostTest { } FakeContentLayerClient layer_client_; - FakePictureLayer* layer_; - FakeRecordingSource* recording_source_; + raw_ptr<FakePictureLayer> layer_; + raw_ptr<FakeRecordingSource> recording_source_; }; MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationDisabled); @@ -6621,8 +6879,8 @@ class LayerTreeHostTestGpuRasterizationSupportedButDisabled } FakeContentLayerClient layer_client_; - FakePictureLayer* layer_; - FakeRecordingSource* recording_source_; + raw_ptr<FakePictureLayer> layer_; + raw_ptr<FakeRecordingSource> recording_source_; }; MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationSupportedButDisabled); @@ -6670,8 +6928,8 @@ class LayerTreeHostTestGpuRasterizationEnabled : public LayerTreeHostTest { } FakeContentLayerClient layer_client_; - FakePictureLayer* layer_; - FakeRecordingSource* recording_source_; + raw_ptr<FakePictureLayer> layer_; + raw_ptr<FakeRecordingSource> recording_source_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationEnabled); @@ -6738,8 +6996,8 @@ class LayerTreeHostTestGpuRasterizationEnabledWithMSAA : public LayerTreeTest { } FakeContentLayerClient layer_client_; - FakePictureLayer* layer_; - FakeRecordingSource* recording_source_; + raw_ptr<FakePictureLayer> layer_; + raw_ptr<FakeRecordingSource> recording_source_; }; MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationEnabledWithMSAA); @@ -7723,7 +7981,7 @@ class LayerTreeHostTestNoTasksBetweenWillAndDidCommit void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void WillCommit() override { + void WillCommit(const CommitState&) override { MainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&LayerTreeHostTestNoTasksBetweenWillAndDidCommit:: @@ -7761,8 +8019,8 @@ class LayerTreeHostTestUpdateCopyRequests : public LayerTreeHostTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void WillCommit() override { - switch (layer_tree_host()->SourceFrameNumber()) { + void WillCommit(const CommitState& commit_state) override { + switch (commit_state.source_frame_number) { case 1: EXPECT_TRUE(LayerSubtreeHasCopyRequest(root.get())); break; @@ -8266,7 +8524,7 @@ class LayerTreeHostTestBeginFrameAcks : public LayerTreeHostTest { bool compositor_frame_submitted_ = false; bool layers_drawn_ = false; viz::BeginFrameArgs current_begin_frame_args_; - LayerTreeHostImpl::FrameData* frame_data_; + raw_ptr<LayerTreeHostImpl::FrameData> frame_data_; }; MULTI_THREAD_BLOCKNOTIFY_TEST_F(LayerTreeHostTestBeginFrameAcks); @@ -8930,7 +9188,7 @@ class LayerTreeHostTestRequestForceSendMetadata } private: - RenderFrameMetadataObserver* target_ = nullptr; + raw_ptr<RenderFrameMetadataObserver> target_ = nullptr; }; LayerTreeHostTestRequestForceSendMetadata() = default; @@ -9168,7 +9426,7 @@ class LayerTreeHostTestDelegatedInkMetadataOnAndOff } private: - RenderFrameMetadataObserver* target_ = nullptr; + raw_ptr<RenderFrameMetadataObserver> target_ = nullptr; }; void BeginTest() override { @@ -9698,7 +9956,8 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest { } // Mark every frame as a dropped frame affecting smoothness. - host_impl->dropped_frame_counter()->OnEndFrame(last_args_, true); + host_impl->dropped_frame_counter()->OnEndFrame( + last_args_, CreateFakeImplDroppedFrameInfo()); host_impl->SetNeedsRedraw(); --frames_counter_; } @@ -9750,8 +10009,11 @@ class LayerTreeHostUkmSmoothnessMemoryOwnership : public LayerTreeTest { return; } - // Mark every frame as a dropped frame affecting smoothness. - host_impl->dropped_frame_counter()->OnEndFrame(last_args_, true); + // Mark every frame as a dropped frame affecting smoothness. This happens + // entirely on the compositor thread, so mark it as not including + // main-thread update. + host_impl->dropped_frame_counter()->OnEndFrame( + last_args_, CreateFakeImplDroppedFrameInfo()); host_impl->SetNeedsRedraw(); --frames_counter_; } @@ -9845,5 +10107,34 @@ class LayerTreeHostTestDebugStateDowngrade : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDebugStateDowngrade); +class LayerTreeHostTestClearCaches : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { + if (host_impl->sync_tree()->source_frame_number() == 1) { + EXPECT_TRUE(host_impl->image_animation_controller()->did_navigate()); + EXPECT_EQ(1u, host_impl->CommitDurationSampleCountForTesting()); + } + } + + void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { + EXPECT_FALSE(host_impl->image_animation_controller()->did_navigate()); + } + + void DidCommit() override { + switch (layer_tree_host()->SourceFrameNumber()) { + case 1: + layer_tree_host()->SetNeedsCommit(); + layer_tree_host()->SetSourceURL(123, GURL("https://example.com")); + break; + case 2: + EndTest(); + break; + } + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestClearCaches); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc index 0d4169e740d..c02063431da 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc @@ -33,6 +33,7 @@ #include "components/viz/common/quads/compositor_frame.h" #include "ui/gfx/animation/keyframe/animation_curve.h" #include "ui/gfx/animation/keyframe/timing_function.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform_operations.h" namespace cc { @@ -779,7 +780,7 @@ class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated scroll_layer_->SetScrollable(gfx::Size(100, 100)); scroll_layer_->SetBounds(gfx::Size(1000, 1000)); client_.set_bounds(scroll_layer_->bounds()); - scroll_layer_->SetScrollOffset(gfx::Vector2dF(10, 20)); + scroll_layer_->SetScrollOffset(gfx::PointF(10, 20)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); AttachAnimationsToTimeline(); @@ -793,8 +794,7 @@ class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated case 1: { std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory:: - CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(500.f, 550.f))); + CreateEaseInOutAnimationForTesting(gfx::PointF(500.f, 550.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), 1, 0, KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); @@ -832,7 +832,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover scroll_layer_ = FakePictureLayer::Create(&client_); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); client_.set_bounds(scroll_layer_->bounds()); - scroll_layer_->SetScrollOffset(gfx::Vector2dF(10, 20)); + scroll_layer_->SetScrollOffset(gfx::PointF(10, 20)); scroll_layer_->SetScrollable(gfx::Size(10, 10)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); @@ -858,8 +858,8 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationTakeover void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { if (host_impl->sync_tree()->source_frame_number() == 0) { GetImplAnimationHost(host_impl)->ImplOnlyScrollAnimationCreate( - scroll_layer_->element_id(), gfx::Vector2dF(650.f, 750.f), - gfx::Vector2dF(10, 20), base::TimeDelta(), base::TimeDelta()); + scroll_layer_->element_id(), gfx::PointF(650.f, 750.f), + gfx::PointF(10, 20), base::TimeDelta(), base::TimeDelta()); } } @@ -893,7 +893,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted scroll_layer_ = FakePictureLayer::Create(&client_); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); client_.set_bounds(scroll_layer_->bounds()); - scroll_layer_->SetScrollOffset(gfx::Vector2dF(10, 20)); + scroll_layer_->SetScrollOffset(gfx::PointF(10, 20)); scroll_layer_->SetScrollable(gfx::Size(10, 10)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); @@ -947,16 +947,16 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted // Verifiy the initial and target position before the scroll offset // update from MT. - EXPECT_EQ(gfx::Vector2dF(10.f, 20.f), curve->GetValue(base::TimeDelta())); - EXPECT_EQ(gfx::Vector2dF(650.f, 750.f), curve->target_value()); + EXPECT_EQ(gfx::PointF(10.f, 20.f), curve->GetValue(base::TimeDelta())); + EXPECT_EQ(gfx::PointF(650.f, 750.f), curve->target_value()); } } void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { if (host_impl->sync_tree()->source_frame_number() == 0) { GetImplAnimationHost(host_impl)->ImplOnlyScrollAnimationCreate( - scroll_layer_->element_id(), gfx::Vector2dF(650.f, 750.f), - gfx::Vector2dF(10, 20), base::TimeDelta(), base::TimeDelta()); + scroll_layer_->element_id(), gfx::PointF(650.f, 750.f), + gfx::PointF(10, 20), base::TimeDelta(), base::TimeDelta()); } } @@ -972,9 +972,8 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationAdjusted // Verifiy the initial and target position after the scroll offset // update from MT EXPECT_EQ(KeyframeModel::RunState::STARTING, keyframe_model->run_state()); - EXPECT_EQ(gfx::Vector2dF(110.f, 120.f), - curve->GetValue(base::TimeDelta())); - EXPECT_EQ(gfx::Vector2dF(750.f, 850.f), curve->target_value()); + EXPECT_EQ(gfx::PointF(110.f, 120.f), curve->GetValue(base::TimeDelta())); + EXPECT_EQ(gfx::PointF(750.f, 850.f), curve->target_value()); EndTest(); } @@ -1000,12 +999,12 @@ class LayerTreeHostPresentationDuringAnimation scroll_layer_->SetScrollable(gfx::Size(100, 100)); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); client_.set_bounds(scroll_layer_->bounds()); - scroll_layer_->SetScrollOffset(gfx::Vector2dF(100.0, 200.0)); + scroll_layer_->SetScrollOffset(gfx::PointF(100.0, 200.0)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(6500.f, 7500.f))); + gfx::PointF(6500.f, 7500.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), 1, 0, KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); @@ -1020,14 +1019,18 @@ class LayerTreeHostPresentationDuringAnimation void BeginMainFrame(const viz::BeginFrameArgs& args) override { PostSetNeedsCommitToMainThread(); + if (const_cast<const LayerTreeHost*>(layer_tree_host()) + ->pending_commit_state() + ->source_frame_number == 2) { + layer_tree_host()->RequestPresentationTimeForNextFrame(base::BindOnce( + &LayerTreeHostPresentationDuringAnimation::OnPresentation, + base::Unretained(this))); + } } void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { if (host_impl->active_tree()->source_frame_number() == 1) { request_token_ = host_impl->next_frame_token(); - layer_tree_host()->RequestPresentationTimeForNextFrame(base::BindOnce( - &LayerTreeHostPresentationDuringAnimation::OnPresentation, - base::Unretained(this))); host_impl->BlockNotifyReadyToActivateForTesting(true); } } @@ -1085,12 +1088,12 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval scroll_layer_->SetScrollable(gfx::Size(100, 100)); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); client_.set_bounds(scroll_layer_->bounds()); - scroll_layer_->SetScrollOffset(gfx::Vector2dF(100.0, 200.0)); + scroll_layer_->SetScrollOffset(gfx::PointF(100.0, 200.0)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(6500.f, 7500.f))); + gfx::PointF(6500.f, 7500.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), 1, 0, KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); @@ -1189,7 +1192,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationRemoval FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> scroll_layer_; - const gfx::Vector2dF final_postion_; + const gfx::PointF final_postion_; }; MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestScrollOffsetAnimationRemoval); @@ -1212,7 +1215,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationCompletion scroll_layer_->SetScrollable(gfx::Size(100, 100)); scroll_layer_->SetBounds(gfx::Size(10000, 10000)); client_.set_bounds(scroll_layer_->bounds()); - scroll_layer_->SetScrollOffset(gfx::Vector2dF(100.0, 200.0)); + scroll_layer_->SetScrollOffset(gfx::PointF(100.0, 200.0)); layer_tree_host()->root_layer()->AddChild(scroll_layer_); std::unique_ptr<ScrollOffsetAnimationCurve> curve( @@ -1290,7 +1293,7 @@ class LayerTreeHostAnimationTestScrollOffsetAnimationCompletion private: FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> scroll_layer_; - const gfx::Vector2dF final_position_; + const gfx::PointF final_position_; bool ran_animation_ = false; }; @@ -1466,7 +1469,7 @@ class LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit // starting state which is 6,7. gfx::Transform expected_transform; expected_transform.Translate(6.0, 7.0); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, child->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, child->DrawTransform()); // And the sync tree layer should know it is animating. EXPECT_TRUE(child->screen_space_transform_is_animating()); @@ -1714,8 +1717,7 @@ class LayerTreeHostAnimationTestRemoveKeyframeModel // applied. gfx::Transform expected_transform; expected_transform.Translate(10.f, 10.f); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - child->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, child->DrawTransform()); EXPECT_FALSE(child->screen_space_transform_is_animating()); animation_stopped_ = true; PostSetNeedsCommitToMainThread(); @@ -1894,8 +1896,8 @@ class LayerTreeHostAnimationTestAnimationFinishesDuringCommit AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5); } - void WillCommit() override { - if (layer_tree_host()->SourceFrameNumber() == 2) { + void WillCommit(const CommitState& commit_state) override { + if (commit_state.source_frame_number == 2) { // Block until the animation finishes on the compositor thread. Since // animations have already been ticked on the main thread, when the commit // happens the state on the main thread will be consistent with having a @@ -1914,8 +1916,7 @@ class LayerTreeHostAnimationTestAnimationFinishesDuringCommit gfx::Transform expected_transform; expected_transform.Translate(5.f, 5.f); LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - layer_impl->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, layer_impl->DrawTransform()); EndTest(); break; } @@ -1965,8 +1966,8 @@ class LayerTreeHostAnimationTestImplSideInvalidation AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5); } - void WillCommit() override { - if (layer_tree_host()->SourceFrameNumber() == 2) { + void WillCommit(const CommitState& commit_state) override { + if (commit_state.source_frame_number == 2) { // Block until the animation finishes on the compositor thread. Since // animations have already been ticked on the main thread, when the commit // happens the state on the main thread will be consistent with having a @@ -2002,8 +2003,7 @@ class LayerTreeHostAnimationTestImplSideInvalidation gfx::Transform expected_transform; expected_transform.Translate(5.f, 5.f); LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - layer_impl->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, layer_impl->DrawTransform()); EndTest(); break; } @@ -2047,8 +2047,8 @@ class LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit EndTest(); } - void WillCommit() override { - if (layer_tree_host()->SourceFrameNumber() == 1) { + void WillCommit(const CommitState& commit_state) override { + if (commit_state.source_frame_number == 1) { // Block until the invalidation is done after animation finishes on the // compositor thread. We need to make sure the pending tree has valid // information based on invalidation only. @@ -2109,8 +2109,7 @@ class ImplSideInvalidationWithoutCommitTestTransform return; EXPECT_EQ(0, host_impl->active_tree()->source_frame_number()); LayerImpl* layer_impl = host_impl->active_tree()->LayerById(layer_->id()); - EXPECT_TRANSFORMATION_MATRIX_EQ(gfx::Transform(), - layer_impl->DrawTransform()); + EXPECT_TRANSFORM_EQ(gfx::Transform(), layer_impl->DrawTransform()); } void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override { @@ -2119,8 +2118,7 @@ class ImplSideInvalidationWithoutCommitTestTransform gfx::Transform expected_transform; expected_transform.Translate(5.f, 5.f); LayerImpl* layer_impl = host_impl->sync_tree()->LayerById(layer_->id()); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, - layer_impl->DrawTransform()); + EXPECT_TRANSFORM_EQ(expected_transform, layer_impl->DrawTransform()); LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit:: DidInvalidateContentOnImplSide(host_impl); } @@ -2174,13 +2172,13 @@ class ImplSideInvalidationWithoutCommitTestScroll layer_->SetScrollable(gfx::Size(100, 100)); layer_->SetBounds(gfx::Size(1000, 1000)); client_.set_bounds(layer_->bounds()); - layer_->SetScrollOffset(gfx::Vector2dF(10.f, 20.f)); + layer_->SetScrollOffset(gfx::PointF(10.f, 20.f)); } void BeginTest() override { std::unique_ptr<ScrollOffsetAnimationCurve> curve( ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( - gfx::Vector2dF(500.f, 550.f))); + gfx::PointF(500.f, 550.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), 1, 0, KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); @@ -2194,14 +2192,14 @@ class ImplSideInvalidationWithoutCommitTestScroll return; EXPECT_EQ(0, host_impl->active_tree()->source_frame_number()); LayerImpl* layer_impl = host_impl->active_tree()->LayerById(layer_->id()); - EXPECT_EQ(gfx::Vector2dF(10.f, 20.f), CurrentScrollOffset(layer_impl)); + EXPECT_EQ(gfx::PointF(10.f, 20.f), CurrentScrollOffset(layer_impl)); } void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override { ASSERT_TRUE(did_request_impl_side_invalidation_); EXPECT_EQ(0, host_impl->sync_tree()->source_frame_number()); LayerImpl* layer_impl = host_impl->pending_tree()->LayerById(layer_->id()); - EXPECT_EQ(gfx::Vector2dF(500.f, 550.f), CurrentScrollOffset(layer_impl)); + EXPECT_EQ(gfx::PointF(500.f, 550.f), CurrentScrollOffset(layer_impl)); LayerTreeHostAnimationTestImplSideInvalidationWithoutCommit:: DidInvalidateContentOnImplSide(host_impl); } @@ -2296,7 +2294,7 @@ class LayerTreeHostAnimationTestChangeAnimation translate.Translate(5, 5); switch (host_impl->sync_tree()->source_frame_number()) { case 2: - EXPECT_TRANSFORMATION_MATRIX_EQ(node->local, translate); + EXPECT_TRANSFORM_EQ(node->local, translate); EndTest(); break; default: diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index 6be30fcdbe9..c546ae724e2 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/cxx17_backports.h" +#include "base/memory/raw_ptr.h" #include "build/build_config.h" #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/layer_impl.h" @@ -164,8 +165,8 @@ class LayerTreeHostContextTest : public LayerTreeTest { // Protects use of gl_ so LoseContext and // CreateDisplayLayerTreeFrameSink can both use it on different threads. base::Lock gl_lock_; - viz::TestGLES2Interface* gl_ = nullptr; - viz::TestSharedImageInterface* sii_ = nullptr; + raw_ptr<viz::TestGLES2Interface> gl_ = nullptr; + raw_ptr<viz::TestSharedImageInterface> sii_ = nullptr; int times_to_fail_create_; int times_to_lose_during_commit_; @@ -695,7 +696,7 @@ class LayerTreeHostContextTestLostContextAndEvictTextures protected: bool lose_after_evict_; FakeContentLayerClient client_; - LayerTreeHostImpl* impl_host_; + raw_ptr<LayerTreeHostImpl> impl_host_; int num_commits_; bool lost_context_; }; diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index 02c23624f96..ce695f67d4a 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -6,8 +6,9 @@ #include "base/bind.h" #include "base/location.h" -#include "base/single_thread_task_runner.h" +#include "base/memory/raw_ptr.h" #include "base/synchronization/waitable_event.h" +#include "base/task/single_thread_task_runner.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -630,7 +631,7 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest viz::AggregatedRenderPassId parent_render_pass_id; viz::AggregatedRenderPassId copy_layer_render_pass_id; - TestLayerTreeFrameSink* frame_sink_ = nullptr; + raw_ptr<TestLayerTreeFrameSink> frame_sink_ = nullptr; bool did_swap_ = false; FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> root_; diff --git a/chromium/cc/trees/layer_tree_host_unittest_damage.cc b/chromium/cc/trees/layer_tree_host_unittest_damage.cc index 2201ad15515..5b73af4252b 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_damage.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_damage.cc @@ -341,7 +341,7 @@ class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest { // The size of the container in which scrolling contents are visible need // to be smaller than the bounds of the layer itself. content_layer_->SetScrollable(gfx::Size(80, 180)); - content_layer_->SetScrollOffset(gfx::Vector2dF(10, 20)); + content_layer_->SetScrollOffset(gfx::PointF(10, 20)); content_layer_->SetBounds(gfx::Size(100, 200)); content_layer_->SetIsDrawable(true); root_layer->AddChild(content_layer_); diff --git a/chromium/cc/trees/layer_tree_host_unittest_masks.cc b/chromium/cc/trees/layer_tree_host_unittest_masks.cc index 12de0442139..7f428b8f98e 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_masks.cc @@ -68,7 +68,7 @@ class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin scroll_layer->AddChild(content_layer); client_.set_bounds(root->bounds()); - scroll_layer->SetScrollOffset(gfx::Vector2dF(50, 50)); + scroll_layer->SetScrollOffset(gfx::PointF(50, 50)); } void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -132,7 +132,7 @@ class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOriginWithLayerList SetupViewport(root, gfx::Size(50, 50), layer_size); auto* scroll = layer_tree_host()->OuterViewportScrollLayerForTesting(); - SetScrollOffset(scroll, gfx::Vector2dF(50, 50)); + SetScrollOffset(scroll, gfx::PointF(50, 50)); client_.set_bounds(root->bounds()); auto content_layer = FakePictureLayer::Create(&client_); diff --git a/chromium/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc b/chromium/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc index 01a9d5adc35..694c2dc60d5 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc @@ -20,9 +20,17 @@ TEST(LayerTreeHostRecordGpuHistogramTest, SingleThreaded) { std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create( &host_client, &task_graph_runner, animation_host.get(), settings, CompositorMode::SINGLE_THREADED); + EXPECT_FALSE( + host->GetPendingCommitState()->needs_gpu_rasterization_histogram); host->CreateFakeLayerTreeHostImpl(); - host->RecordGpuRasterizationHistogram(host->host_impl()); - EXPECT_FALSE(host->gpu_rasterization_histogram_recorded()); + auto commit_state = + host->WillCommit(/*completion=*/nullptr, /*has_updates=*/true); + EXPECT_FALSE(commit_state->needs_gpu_rasterization_histogram); + EXPECT_FALSE( + host->GetPendingCommitState()->needs_gpu_rasterization_histogram); + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); + EXPECT_FALSE( + host->GetPendingCommitState()->needs_gpu_rasterization_histogram); } TEST(LayerTreeHostRecordGpuHistogramTest, Threaded) { @@ -33,9 +41,21 @@ TEST(LayerTreeHostRecordGpuHistogramTest, Threaded) { std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create( &host_client, &task_graph_runner, animation_host.get(), settings, CompositorMode::THREADED); + EXPECT_TRUE(host->GetPendingCommitState()->needs_gpu_rasterization_histogram); host->CreateFakeLayerTreeHostImpl(); - host->RecordGpuRasterizationHistogram(host->host_impl()); - EXPECT_TRUE(host->gpu_rasterization_histogram_recorded()); + auto commit_state = + host->WillCommit(/*completion=*/nullptr, /*has_updates=*/true); + EXPECT_TRUE(commit_state->needs_gpu_rasterization_histogram); + EXPECT_FALSE( + host->GetPendingCommitState()->needs_gpu_rasterization_histogram); + { + DebugScopedSetImplThread impl(host->GetTaskRunnerProvider()); + host->host_impl()->RecordGpuRasterizationHistogram(); + } + commit_state.reset(); + host->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); + EXPECT_FALSE( + host->GetPendingCommitState()->needs_gpu_rasterization_histogram); } } // namespace diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index 6dca2d18fa2..65b4720c186 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/raw_ptr.h" #include "cc/trees/layer_tree_host.h" #include "base/bind.h" -#include "base/containers/contains.h" #include "base/location.h" #include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "cc/animation/animation_host.h" @@ -23,7 +23,6 @@ #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/fake_picture_layer_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_ukm_recorder_factory.h" @@ -31,12 +30,14 @@ #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/scroll_node.h" +#include "cc/trees/single_thread_proxy.h" #include "cc/trees/transform_node.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/events/types/scroll_input_type.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/vector2d_conversions.h" using ::testing::Mock; @@ -88,7 +89,7 @@ class LayerTreeHostScrollTest : public LayerTreeTest, public ScrollCallbacks { // ScrollCallbacks void DidCompositorScroll(ElementId element_id, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, const absl::optional<TargetSnapAreaElementIds>& snap_target_ids) override { // Simulates cc client (e.g Blink) behavior when handling impl-side scrolls. @@ -110,7 +111,7 @@ class LayerTreeHostScrollTest : public LayerTreeTest, public ScrollCallbacks { } void DidChangeScrollbarsHidden(ElementId, bool) override {} - virtual void DidScrollOuterViewport(const gfx::Vector2dF& scroll_offset) { + virtual void DidScrollOuterViewport(const gfx::PointF& scroll_offset) { num_outer_viewport_scrolls_++; } @@ -135,10 +136,10 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { Layer* scroll_layer = layer_tree_host()->OuterViewportScrollLayerForTesting(); if (!layer_tree_host()->SourceFrameNumber()) { - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, GetTransformNode(scroll_layer)->scroll_offset); } else { - EXPECT_VECTOR_EQ(initial_scroll_ + scroll_amount_, + EXPECT_POINTF_EQ(initial_scroll_ + scroll_amount_, GetTransformNode(scroll_layer)->scroll_offset); // Pretend like Javascript updated the scroll position itself. @@ -150,7 +151,7 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { LayerImpl* root = impl->active_tree()->root_layer(); LayerImpl* scroll_layer = impl->active_tree()->OuterViewportScrollLayerForTesting(); - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); scroll_layer->SetBounds( gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100)); @@ -158,13 +159,13 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { switch (impl->active_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, ScrollDelta(scroll_layer)); PostSetNeedsCommitToMainThread(); break; case 1: - EXPECT_VECTOR_EQ(second_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(second_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, ScrollDelta(scroll_layer)); EndTest(); break; } @@ -173,8 +174,8 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { void AfterTest() override { EXPECT_EQ(1, num_outer_viewport_scrolls_); } private: - gfx::Vector2dF initial_scroll_; - gfx::Vector2dF second_scroll_; + gfx::PointF initial_scroll_; + gfx::PointF second_scroll_; gfx::Vector2dF scroll_amount_; }; @@ -195,12 +196,12 @@ class LayerTreeHostScrollTestScrollMultipleRedraw void BeginCommitOnThread(LayerTreeHostImpl* impl) override { switch (impl->sync_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer_.get())); break; case 1: case 2: - EXPECT_VECTOR_EQ(initial_scroll_ + scroll_amount_ + scroll_amount_, + EXPECT_POINTF_EQ(initial_scroll_ + scroll_amount_ + scroll_amount_, CurrentScrollOffset(scroll_layer_.get())); break; } @@ -212,27 +213,27 @@ class LayerTreeHostScrollTestScrollMultipleRedraw if (impl->active_tree()->source_frame_number() == 0 && impl->SourceAnimationFrameNumberForTesting() == 1) { // First draw after first commit. - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); scroll_layer->ScrollBy(scroll_amount_); - EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, ScrollDelta(scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); PostSetNeedsRedrawToMainThread(); } else if (impl->active_tree()->source_frame_number() == 0 && impl->SourceAnimationFrameNumberForTesting() == 2) { // Second draw after first commit. - EXPECT_VECTOR_EQ(ScrollDelta(scroll_layer), scroll_amount_); + EXPECT_VECTOR2DF_EQ(ScrollDelta(scroll_layer), scroll_amount_); scroll_layer->ScrollBy(scroll_amount_); - EXPECT_VECTOR_EQ(scroll_amount_ + scroll_amount_, - ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_ + scroll_amount_, + ScrollDelta(scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer_.get())); PostSetNeedsCommitToMainThread(); } else if (impl->active_tree()->source_frame_number() == 1) { // Third or later draw after second commit. EXPECT_GE(impl->SourceAnimationFrameNumberForTesting(), 3u); - EXPECT_VECTOR_EQ(initial_scroll_ + scroll_amount_ + scroll_amount_, + EXPECT_POINTF_EQ(initial_scroll_ + scroll_amount_ + scroll_amount_, CurrentScrollOffset(scroll_layer_.get())); EndTest(); } @@ -241,7 +242,7 @@ class LayerTreeHostScrollTestScrollMultipleRedraw void AfterTest() override { EXPECT_EQ(1, num_outer_viewport_scrolls_); } private: - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF scroll_amount_; scoped_refptr<Layer> scroll_layer_; }; @@ -286,7 +287,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit // This will not be aborted because of the initial prop changes. EXPECT_EQ(0, num_outer_viewport_scrolls_); EXPECT_EQ(0, layer_tree_host()->SourceFrameNumber()); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(root_scroll_layer)); EXPECT_EQ(1.f, layer_tree_host()->page_scale_factor()); break; @@ -295,7 +296,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit // initiated from the redraw. EXPECT_EQ(1, num_outer_viewport_scrolls_); EXPECT_EQ(1, layer_tree_host()->SourceFrameNumber()); - EXPECT_VECTOR_EQ(initial_scroll_ + impl_scroll_, + EXPECT_POINTF_EQ(initial_scroll_ + impl_scroll_, CurrentScrollOffset(root_scroll_layer)); EXPECT_EQ(impl_scale_, layer_tree_host()->page_scale_factor()); PostSetNeedsRedrawToMainThread(); @@ -305,7 +306,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit EXPECT_EQ(2, num_outer_viewport_scrolls_); // The source frame number still increases even with the abort. EXPECT_EQ(2, layer_tree_host()->SourceFrameNumber()); - EXPECT_VECTOR_EQ(initial_scroll_ + impl_scroll_ + impl_scroll_, + EXPECT_POINTF_EQ(initial_scroll_ + impl_scroll_ + impl_scroll_, CurrentScrollOffset(root_scroll_layer)); EXPECT_EQ(impl_scale_ * impl_scale_, layer_tree_host()->page_scale_factor()); @@ -319,7 +320,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit EXPECT_EQ(3, layer_tree_host()->SourceFrameNumber()); gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + delta, + EXPECT_POINTF_EQ(initial_scroll_ + delta, CurrentScrollOffset(root_scroll_layer)); // End the test by drawing to verify this commit is also aborted. @@ -330,7 +331,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit void DidBeginMainFrame() override { num_did_begin_main_frames_++; } - void WillCommit() override { num_will_commits_++; } + void WillCommit(const CommitState&) override { num_will_commits_++; } void DidCommit() override { num_did_commits_++; } @@ -345,10 +346,10 @@ class LayerTreeHostScrollTestScrollAbortedCommit if (impl->active_tree()->source_frame_number() == 0 && impl->SourceAnimationFrameNumberForTesting() == 1) { // First draw - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(root_scroll_layer)); root_scroll_layer->ScrollBy(impl_scroll_); - EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(root_scroll_layer)); EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta()); EXPECT_EQ(1.f, impl->active_tree()->current_page_scale_factor()); @@ -363,10 +364,10 @@ class LayerTreeHostScrollTestScrollAbortedCommit // Test a second draw after an aborted commit. // The scroll/scale values should be baked into the offset/scale factor // since the main thread consumed but aborted the begin frame. - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(root_scroll_layer)); root_scroll_layer->ScrollBy(impl_scroll_); - EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_ + impl_scroll_, + EXPECT_VECTOR2DF_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_ + impl_scroll_, ScrollOffsetBase(root_scroll_layer)); EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta()); @@ -386,17 +387,17 @@ class LayerTreeHostScrollTestScrollAbortedCommit EXPECT_EQ(ScrollDelta(root_scroll_layer), gfx::Vector2dF()); root_scroll_layer->ScrollBy(impl_scroll_); impl->SetNeedsCommit(); - EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + delta, + EXPECT_POINTF_EQ(initial_scroll_ + delta, ScrollOffsetBase(root_scroll_layer)); } else if (impl->active_tree()->source_frame_number() == 2 && impl->SourceAnimationFrameNumberForTesting() == 4) { // Final draw after the second aborted commit. - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(root_scroll_layer)); gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + delta, + EXPECT_POINTF_EQ(initial_scroll_ + delta, ScrollOffsetBase(root_scroll_layer)); EndTest(); } else { @@ -417,7 +418,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit } private: - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF impl_scroll_; gfx::Vector2dF second_main_scroll_; float impl_scale_; @@ -449,23 +450,23 @@ class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest { // multiple commits. switch (impl->active_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(gfx::Vector2d(0, 0), ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2d(0, 0), ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(gfx::PointF(), ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); PostSetNeedsCommitToMainThread(); break; case 1: - EXPECT_VECTOR_EQ(gfx::ToRoundedVector2d(scroll_amount_), - ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ( + EXPECT_VECTOR2DF_EQ(gfx::ToRoundedVector2d(scroll_amount_), + ScrollOffsetBase(scroll_layer).OffsetFromOrigin()); + EXPECT_VECTOR2DF_EQ( scroll_amount_ - gfx::ToRoundedVector2d(scroll_amount_), ScrollDelta(scroll_layer)); PostSetNeedsCommitToMainThread(); break; case 2: - EXPECT_VECTOR_EQ( + EXPECT_VECTOR2DF_EQ( gfx::ToRoundedVector2d(scroll_amount_ + scroll_amount_), - ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ( + ScrollOffsetBase(scroll_layer).OffsetFromOrigin()); + EXPECT_VECTOR2DF_EQ( scroll_amount_ + scroll_amount_ - gfx::ToRoundedVector2d(scroll_amount_ + scroll_amount_), ScrollDelta(scroll_layer)); @@ -606,16 +607,16 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void WillCommit() override { + void WillCommit(const CommitState& commit_state) override { // Keep the test committing (otherwise the early out for no update // will stall the test). - if (layer_tree_host()->SourceFrameNumber() < 2) { + if (commit_state.source_frame_number < 2) { layer_tree_host()->SetNeedsCommit(); } } void DidCompositorScroll(ElementId element_id, - const gfx::Vector2dF& offset, + const gfx::PointF& offset, const absl::optional<TargetSnapAreaElementIds>& snap_target_ids) override { LayerTreeHostScrollTest::DidCompositorScroll(element_id, offset, @@ -625,28 +626,28 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { EXPECT_EQ(offset, final_scroll_offset_); EXPECT_EQ(element_id, expected_scroll_layer_->element_id()); } else { - EXPECT_TRUE(offset.IsZero()); + EXPECT_TRUE(offset.IsOrigin()); } } void UpdateLayerTreeHost() override { - EXPECT_VECTOR_EQ(gfx::Vector2d(), + EXPECT_POINTF_EQ(gfx::PointF(), CurrentScrollOffset(expected_no_scroll_layer_)); switch (layer_tree_host()->SourceFrameNumber()) { case 0: - EXPECT_VECTOR_EQ(initial_offset_, + EXPECT_POINTF_EQ(initial_offset_, CurrentScrollOffset(expected_scroll_layer_)); break; case 1: - EXPECT_VECTOR_EQ(initial_offset_ + scroll_amount_, + EXPECT_POINTF_EQ(initial_offset_ + scroll_amount_, CurrentScrollOffset(expected_scroll_layer_)); // Pretend like Javascript updated the scroll position itself. SetScrollOffset(expected_scroll_layer_, javascript_scroll_); break; case 2: - EXPECT_VECTOR_EQ(javascript_scroll_ + scroll_amount_, + EXPECT_POINTF_EQ(javascript_scroll_ + scroll_amount_, CurrentScrollOffset(expected_scroll_layer_)); break; } @@ -671,9 +672,9 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { expected_no_scroll_layer_impl = child_layer_impl; } - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(inner_scroll)); - EXPECT_VECTOR_EQ(gfx::Vector2d(), - ScrollDelta(expected_no_scroll_layer_impl)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(inner_scroll)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), + ScrollDelta(expected_no_scroll_layer_impl)); // Ensure device scale factor matches the active tree. EXPECT_EQ(device_scale_factor_, impl->active_tree()->device_scale_factor()); @@ -698,10 +699,10 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { impl->active_tree()->LastScrolledScrollNodeIndex()); // Check the scroll is applied as a delta. - EXPECT_VECTOR_EQ(initial_offset_, + EXPECT_POINTF_EQ(initial_offset_, ScrollOffsetBase(expected_scroll_layer_impl)); - EXPECT_VECTOR_EQ(scroll_amount_, - ScrollDelta(expected_scroll_layer_impl)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, + ScrollDelta(expected_scroll_layer_impl)); break; } case 1: { @@ -718,18 +719,18 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { impl->GetInputHandler().ScrollEnd(); // Check the scroll is applied as a delta. - EXPECT_VECTOR_EQ(javascript_scroll_, + EXPECT_POINTF_EQ(javascript_scroll_, ScrollOffsetBase(expected_scroll_layer_impl)); - EXPECT_VECTOR_EQ(scroll_amount_, - ScrollDelta(expected_scroll_layer_impl)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, + ScrollDelta(expected_scroll_layer_impl)); break; } case 2: - EXPECT_VECTOR_EQ(javascript_scroll_ + scroll_amount_, + EXPECT_POINTF_EQ(javascript_scroll_ + scroll_amount_, ScrollOffsetBase(expected_scroll_layer_impl)); - EXPECT_VECTOR_EQ(gfx::Vector2d(), - ScrollDelta(expected_scroll_layer_impl)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2d(), + ScrollDelta(expected_scroll_layer_impl)); EndTest(); break; @@ -738,21 +739,21 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { void AfterTest() override { EXPECT_EQ(scroll_child_layer_ ? 0 : 2, num_outer_viewport_scrolls_); - EXPECT_VECTOR_EQ(javascript_scroll_ + scroll_amount_, final_scroll_offset_); + EXPECT_POINTF_EQ(javascript_scroll_ + scroll_amount_, final_scroll_offset_); } protected: float device_scale_factor_; bool scroll_child_layer_; - gfx::Vector2dF initial_offset_; - gfx::Vector2dF javascript_scroll_; + gfx::PointF initial_offset_; + gfx::PointF javascript_scroll_; gfx::Vector2d scroll_amount_; - gfx::Vector2dF final_scroll_offset_; + gfx::PointF final_scroll_offset_; scoped_refptr<Layer> child_layer_; - Layer* expected_scroll_layer_; - Layer* expected_no_scroll_layer_; + raw_ptr<Layer> expected_scroll_layer_; + raw_ptr<Layer> expected_no_scroll_layer_; }; TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollChild) { @@ -817,9 +818,9 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest { Layer* scroll_layer = layer_tree_host()->OuterViewportScrollLayerForTesting(); if (!layer_tree_host()->SourceFrameNumber()) { - EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer)); } else { - EXPECT_VECTOR_EQ(CurrentScrollOffset(scroll_layer), + EXPECT_POINTF_EQ(CurrentScrollOffset(scroll_layer), initial_scroll_ + impl_thread_scroll1_); // Pretend like Javascript updated the scroll position itself with a @@ -850,11 +851,11 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest { case 0: if (!impl->pending_tree()) { impl->BlockNotifyReadyToActivateForTesting(true); - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); scroll_layer->ScrollBy(impl_thread_scroll1_); - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll1_, ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll1_, ScrollDelta(scroll_layer)); PostSetNeedsCommitToMainThread(); // CommitCompleteOnThread will trigger this function again @@ -865,25 +866,25 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest { EXPECT_EQ(impl->pending_tree()->source_frame_number(), 1); scroll_layer->ScrollBy(impl_thread_scroll2_); - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll1_ + impl_thread_scroll2_, - ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll1_ + impl_thread_scroll2_, + ScrollDelta(scroll_layer)); LayerImpl* pending_scroll_layer = impl->pending_tree()->OuterViewportScrollLayerForTesting(); - EXPECT_VECTOR_EQ( + EXPECT_POINTF_EQ( initial_scroll_ + main_thread_scroll_ + impl_thread_scroll1_, ScrollOffsetBase(pending_scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll2_, - ScrollDelta(pending_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll2_, + ScrollDelta(pending_scroll_layer)); } break; case 1: EXPECT_FALSE(impl->pending_tree()); - EXPECT_VECTOR_EQ( + EXPECT_POINTF_EQ( initial_scroll_ + main_thread_scroll_ + impl_thread_scroll1_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll2_, ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll2_, ScrollDelta(scroll_layer)); EndTest(); break; } @@ -892,7 +893,7 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest { void AfterTest() override { EXPECT_EQ(1, num_outer_viewport_scrolls_); } private: - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF main_thread_scroll_; gfx::Vector2dF impl_thread_scroll1_; gfx::Vector2dF impl_thread_scroll2_; @@ -921,22 +922,24 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { PostSetNeedsCommitToMainThread(); } - void WillCommit() override { + void WillCommit(const CommitState& commit_state) override { Layer* scroll_layer = layer_tree_host()->OuterViewportScrollLayerForTesting(); - switch (layer_tree_host()->SourceFrameNumber()) { + switch (commit_state.source_frame_number) { case 0: - EXPECT_TRUE(base::Contains( - scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(), - scroll_layer)); + EXPECT_TRUE( + const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties.contains(scroll_layer)); break; case 1: // Even if this layer doesn't need push properties, it should // still pick up scrolls that happen on the active layer during // commit. - EXPECT_FALSE(base::Contains( - scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(), - scroll_layer)); + EXPECT_FALSE( + const_cast<const LayerTreeHost*>(layer_tree_host()) + ->thread_unsafe_commit_state() + .layers_that_should_push_properties.contains(scroll_layer)); break; } } @@ -969,28 +972,30 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { ASSERT_TRUE(pending_scroll_layer); switch (impl->pending_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(pending_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(pending_scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), + ScrollDelta(pending_scroll_layer)); EXPECT_FALSE(active_root); break; case 1: // Even though the scroll happened during the commit, both layers // should have the appropriate scroll delta. - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(pending_scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll_, - ScrollDelta(pending_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll_, + ScrollDelta(pending_scroll_layer)); ASSERT_TRUE(active_root); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(active_scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll_, ScrollDelta(active_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll_, + ScrollDelta(active_scroll_layer)); break; case 2: // On the next commit, this delta should have been sent and applied. - EXPECT_VECTOR_EQ(initial_scroll_ + impl_thread_scroll_, + EXPECT_POINTF_EQ(initial_scroll_ + impl_thread_scroll_, ScrollOffsetBase(pending_scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(pending_scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2d(), ScrollDelta(pending_scroll_layer)); break; } @@ -1001,9 +1006,9 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { LayerImpl* scroll_layer = impl->pending_tree()->OuterViewportScrollLayerForTesting(); - gfx::Vector2dF scroll_offset = CurrentScrollOffset(scroll_layer); + gfx::PointF scroll_offset = CurrentScrollOffset(scroll_layer); int transform_index = scroll_layer->transform_tree_index(); - gfx::Vector2dF transform_tree_scroll_offset = + gfx::PointF transform_tree_scroll_offset = impl->pending_tree() ->property_trees() ->transform_tree.Node(transform_index) @@ -1020,15 +1025,15 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { switch (impl->active_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta()); EXPECT_EQ(1.f, impl->active_tree()->current_page_scale_factor()); PostSetNeedsCommitToMainThread(); break; case 1: - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(impl_thread_scroll_, ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll_, ScrollDelta(scroll_layer)); EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta()); EXPECT_EQ(impl_scale_, impl->active_tree()->current_page_scale_factor()); @@ -1044,7 +1049,7 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { } private: - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF impl_thread_scroll_; float impl_scale_; }; @@ -1092,7 +1097,7 @@ class SmoothScrollAnimationEndNotification : public LayerTreeHostScrollTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void WillCommit() override { + void WillCommit(const CommitState&) override { if (TestEnded()) return; // Keep the test committing (otherwise the early out for no update @@ -1229,7 +1234,7 @@ class LayerTreeHostScrollTestImplOnlyScrollSnap // Set up snap container data. SnapContainerData snap_container_data( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 100, 100), gfx::Vector2dF(900, 900)); + gfx::RectF(0, 0, 100, 100), gfx::PointF(900, 900)); snap_container_data.AddSnapAreaData(snap_area_data); CreateScrollNode(scroller_.get(), container_->bounds()) .snap_container_data = snap_container_data; @@ -1257,7 +1262,7 @@ class LayerTreeHostScrollTestImplOnlyScrollSnap EXPECT_TRUE( host_impl->GetInputHandler().animating_for_snap_for_testing()); - EXPECT_VECTOR_EQ(impl_thread_scroll_, ScrollDelta(scroller_impl)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll_, ScrollDelta(scroller_impl)); } else { snap_animation_finished_ = !host_impl->GetInputHandler().animating_for_snap_for_testing(); @@ -1274,7 +1279,7 @@ class LayerTreeHostScrollTestImplOnlyScrollSnap // On the first BeginMainFrame scrolling has not happened yet. // Check that the scroll offset and scroll snap targets are at the initial // values on the main thread. - EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroller_.get())); + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroller_.get())); } if (snap_animation_finished_) { // After a snap target is set on the impl thread, the snap targets should @@ -1296,7 +1301,7 @@ class LayerTreeHostScrollTestImplOnlyScrollSnap scoped_refptr<Layer> scroller_; scoped_refptr<Layer> snap_area_; - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF impl_thread_scroll_; ElementId snap_area_id_; @@ -1367,7 +1372,7 @@ class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap // Set up snap container data. SnapContainerData snap_container_data_a( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 100, 100), gfx::Vector2dF(900, 900)); + gfx::RectF(0, 0, 100, 100), gfx::PointF(900, 900)); snap_container_data_a.AddSnapAreaData(snap_area_data_a); CreateScrollNode(scroller_a_.get(), container_->bounds()) .snap_container_data = snap_container_data_a; @@ -1375,7 +1380,7 @@ class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap // Set up snap container data. SnapContainerData snap_container_data_b( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), - gfx::RectF(0, 0, 100, 100), gfx::Vector2dF(900, 900)); + gfx::RectF(0, 0, 100, 100), gfx::PointF(900, 900)); snap_container_data_b.AddSnapAreaData(snap_area_data_b); CreateScrollNode(scroller_b_.get(), container_->bounds()) .snap_container_data = snap_container_data_b; @@ -1407,8 +1412,8 @@ class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap // values on the main thread. EXPECT_EQ(snap_target_ids_a, TargetSnapAreaElementIds()); EXPECT_EQ(snap_target_ids_b, TargetSnapAreaElementIds()); - EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroller_a_.get())); - EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroller_b_.get())); + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroller_a_.get())); + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroller_b_.get())); } else { // When scrolling happens on the impl thread, the snap targets of the // scrolled layers should be pushed to the main thread. @@ -1432,8 +1437,8 @@ class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap DoGestureScroll(host_impl, scroller_a_, impl_thread_scroll_a_); DoGestureScroll(host_impl, scroller_b_, impl_thread_scroll_b_); - EXPECT_VECTOR_EQ(impl_thread_scroll_a_, ScrollDelta(scroller_impl_a)); - EXPECT_VECTOR_EQ(impl_thread_scroll_b_, ScrollDelta(scroller_impl_b)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll_a_, ScrollDelta(scroller_impl_a)); + EXPECT_VECTOR2DF_EQ(impl_thread_scroll_b_, ScrollDelta(scroller_impl_b)); } PostSetNeedsCommitToMainThread(); } @@ -1445,7 +1450,7 @@ class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap scoped_refptr<Layer> snap_area_a_; scoped_refptr<Layer> snap_area_b_; - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF impl_thread_scroll_a_; gfx::Vector2dF impl_thread_scroll_b_; @@ -1479,6 +1484,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset CreateTransformNode(scroller_.get()); CreateScrollNode(scroller_.get(), layer_tree_host()->root_layer()->bounds()); + scroll_tree_index_ = scroller_->scroll_tree_index(); layer_tree_host()->root_layer()->AddChild(scroller_.get()); } @@ -1491,7 +1497,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset ++cur_step_; ScrollTree& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; - ScrollNode* scroll_node = scroll_tree.Node(scroller_->scroll_tree_index()); + ScrollNode* scroll_node = scroll_tree.Node(scroll_tree_index_); switch (cur_step_) { case 1: // Set max_scroll_offset = (100, 100). @@ -1517,7 +1523,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset ScrollTree& scroll_tree = impl->active_tree()->property_trees()->scroll_tree; - ScrollNode* scroll_node = scroll_tree.Node(scroller_->scroll_tree_index()); + ScrollNode* scroll_node = scroll_tree.Node(scroll_tree_index_); ScrollStateData scroll_state_data; scroll_state_data.is_beginning = true; @@ -1567,6 +1573,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset private: int cur_step_ = 0; + int scroll_tree_index_ = ScrollTree::kInvalidNodeId; scoped_refptr<Layer> scroller_; }; @@ -1585,7 +1592,7 @@ class LayerTreeHostScrollTestScrollNonDrawnLayer layer_tree_host()->OuterViewportScrollLayerForTesting()->SetIsDrawable( false); SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(), - gfx::Vector2dF(20.f, 20.f)); + gfx::PointF(20.f, 20.f)); layer_tree_host() ->OuterViewportScrollLayerForTesting() ->SetNonFastScrollableRegion(gfx::Rect(20, 20, 20, 20)); @@ -1647,14 +1654,14 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent CreateTransformNode(scroller_.get()); CreateScrollNode(scroller_.get(), layer_tree_host()->root_layer()->bounds()); + scroll_tree_index_ = scroller_->scroll_tree_index(); layer_tree_host()->root_layer()->AddChild(scroller_.get()); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { ScrollTree& scroll_tree = impl->active_tree()->property_trees()->scroll_tree; - ScrollNode* scroller_scroll_node = - scroll_tree.Node(scroller_->scroll_tree_index()); + ScrollNode* scroller_scroll_node = scroll_tree.Node(scroll_tree_index_); ScrollStateData scroll_state_data; scroll_state_data.is_beginning = true; @@ -1715,6 +1722,7 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent private: scoped_refptr<Layer> scroller_; + int scroll_tree_index_ = ScrollTree::kInvalidNodeId; }; // This test is flaky in the single threaded configuration, only on the @@ -1755,8 +1763,8 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient { void SetPrefersReducedMotion(bool prefers_reduced_motion) override {} void UpdateRootLayerStateForSynchronousInputHandler( - const gfx::Vector2dF& total_scroll_offset, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& total_scroll_offset, + const gfx::PointF& max_scroll_offset, const gfx::SizeF& scrollable_size, float page_scale_factor, float min_page_scale_factor, @@ -1780,8 +1788,8 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient { } private: - base::SingleThreadTaskRunner* task_runner_; - bool* received_stop_flinging_; + raw_ptr<base::SingleThreadTaskRunner> task_runner_; + raw_ptr<bool> received_stop_flinging_; }; class LayerTreeHostScrollTestLayerStructureChange @@ -1829,13 +1837,12 @@ class LayerTreeHostScrollTestLayerStructureChange void DidCompositorScroll( ElementId element_id, - const gfx::Vector2dF&, + const gfx::PointF&, const absl::optional<TargetSnapAreaElementIds>&) override { if (scroll_destroy_whole_tree_) { layer_tree_host()->SetRootLayer(nullptr); layer_tree_host()->property_trees()->clear(); - layer_tree_host()->RegisterViewportPropertyIds( - LayerTreeHost::ViewportPropertyIds()); + layer_tree_host()->RegisterViewportPropertyIds(ViewportPropertyIds()); EndTest(); return; } @@ -1930,10 +1937,10 @@ class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest { layer_tree_host()->OuterViewportScrollLayerForTesting(); switch (layer_tree_host()->SourceFrameNumber()) { case 0: - EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer)); break; case 1: - EXPECT_VECTOR_EQ(initial_scroll_ + scroll_amount_, + EXPECT_POINTF_EQ(initial_scroll_ + scroll_amount_, CurrentScrollOffset(scroll_layer)); // Pretend like Javascript updated the scroll position itself. SetScrollOffset(scroll_layer, second_scroll_); @@ -1941,7 +1948,7 @@ class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest { case 2: // Third frame does not see a scroll delta because we only did one // scroll for the second and third frames. - EXPECT_VECTOR_EQ(second_scroll_, CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(second_scroll_, CurrentScrollOffset(scroll_layer)); // Pretend like Javascript updated the scroll position itself. SetScrollOffset(scroll_layer, third_scroll_); break; @@ -1953,23 +1960,23 @@ class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest { impl->active_tree()->OuterViewportScrollLayerForTesting(); switch (impl->active_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); Scroll(impl); - EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, ScrollDelta(scroll_layer)); // Ask for commit after we've scrolled. impl->SetNeedsCommit(); break; case 1: - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer)); - EXPECT_VECTOR_EQ(second_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(second_scroll_, ScrollOffsetBase(scroll_layer)); Scroll(impl); - EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, ScrollDelta(scroll_layer)); break; case 2: // The scroll hasn't been consumed by the main thread. - EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer)); - EXPECT_VECTOR_EQ(third_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_VECTOR2DF_EQ(scroll_amount_, ScrollDelta(scroll_layer)); + EXPECT_POINTF_EQ(third_scroll_, ScrollOffsetBase(scroll_layer)); EndTest(); break; } @@ -1991,9 +1998,9 @@ class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest { scroll_layer->ScrollBy(scroll_amount_); } - gfx::Vector2dF initial_scroll_; - gfx::Vector2dF second_scroll_; - gfx::Vector2dF third_scroll_; + gfx::PointF initial_scroll_; + gfx::PointF second_scroll_; + gfx::PointF third_scroll_; gfx::Vector2dF scroll_amount_; int num_commits_; }; @@ -2044,14 +2051,14 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA // This will not be aborted because of the initial prop changes. EXPECT_EQ(0, num_outer_viewport_scrolls_); EXPECT_EQ(0, layer_tree_host()->SourceFrameNumber()); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(root_scroll_layer)); break; case 2: // This commit will not be aborted because of the scroll change. EXPECT_EQ(1, num_outer_viewport_scrolls_); EXPECT_EQ(1, layer_tree_host()->SourceFrameNumber()); - EXPECT_VECTOR_EQ(initial_scroll_ + impl_scroll_, + EXPECT_POINTF_EQ(initial_scroll_ + impl_scroll_, CurrentScrollOffset(root_scroll_layer)); SetScrollOffset( root_scroll_layer, @@ -2064,7 +2071,7 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA EXPECT_EQ(2, layer_tree_host()->SourceFrameNumber()); gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + delta, + EXPECT_POINTF_EQ(initial_scroll_ + delta, CurrentScrollOffset(root_scroll_layer)); break; } @@ -2074,7 +2081,7 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA EXPECT_EQ(3, layer_tree_host()->SourceFrameNumber()); gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + delta, + EXPECT_POINTF_EQ(initial_scroll_ + delta, CurrentScrollOffset(root_scroll_layer)); break; } @@ -2083,7 +2090,7 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA void DidBeginMainFrame() override { num_did_begin_main_frames_++; } - void WillCommit() override { num_will_commits_++; } + void WillCommit(const CommitState&) override { num_will_commits_++; } void DidCommit() override { num_did_commits_++; } @@ -2126,21 +2133,22 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA switch (num_impl_commits_) { case 1: { // First draw - EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(gfx::Vector2dF(), + ScrollDelta(root_scroll_layer)); root_scroll_layer->ScrollBy(impl_scroll_); - EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_VECTOR2DF_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(root_scroll_layer)); impl->SetNeedsCommit(); break; } case 2: { // Second draw but no new active tree because activation is blocked. - EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); root_scroll_layer->ScrollBy(impl_scroll_); - EXPECT_VECTOR_EQ(impl_scroll_ + impl_scroll_, - ScrollDelta(root_scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_VECTOR2DF_EQ(impl_scroll_ + impl_scroll_, + ScrollDelta(root_scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(root_scroll_layer)); // Ask for another commit (which will abort). impl->SetNeedsCommit(); @@ -2158,10 +2166,10 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA switch (num_aborted_commits_) { case 1: { root_scroll_layer->ScrollBy(impl_scroll_); - EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); + EXPECT_VECTOR2DF_EQ(impl_scroll_, ScrollDelta(root_scroll_layer)); gfx::Vector2dF prev_delta = impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + prev_delta, + EXPECT_POINTF_EQ(initial_scroll_ + prev_delta, ScrollOffsetBase(root_scroll_layer)); // Ask for another commit (which will abort). impl->SetNeedsCommit(); @@ -2170,7 +2178,7 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA case 2: { gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_; - EXPECT_VECTOR_EQ(initial_scroll_ + delta, + EXPECT_POINTF_EQ(initial_scroll_ + delta, ScrollOffsetBase(root_scroll_layer)); // End test after second aborted commit (fourth commit request). EndTest(); @@ -2199,7 +2207,7 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA } private: - gfx::Vector2dF initial_scroll_; + gfx::PointF initial_scroll_; gfx::Vector2dF impl_scroll_; gfx::Vector2dF second_main_scroll_; int num_will_begin_main_frames_; @@ -2223,8 +2231,8 @@ class MockInputHandlerClient : public InputHandlerClient { void Animate(base::TimeTicks) override {} void SetPrefersReducedMotion(bool prefers_reduced_motion) override {} void UpdateRootLayerStateForSynchronousInputHandler( - const gfx::Vector2dF& total_scroll_offset, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& total_scroll_offset, + const gfx::PointF& max_scroll_offset, const gfx::SizeF& scrollable_size, float page_scale_factor, float min_page_scale_factor, @@ -2380,7 +2388,7 @@ class LayerTreeHostScrollTestElasticOverscroll // These values should be used on the impl thread only. int num_begin_main_frames_impl_thread_; MockInputHandlerClient input_handler_client_; - ScrollElasticityHelper* scroll_elasticity_helper_; + raw_ptr<ScrollElasticityHelper> scroll_elasticity_helper_; // These values should be used on the main thread only. int num_begin_main_frames_main_thread_; @@ -2409,9 +2417,9 @@ class LayerTreeHostScrollTestPropertyTreeUpdate Layer* scroll_layer = layer_tree_host()->OuterViewportScrollLayerForTesting(); if (layer_tree_host()->SourceFrameNumber() == 0) { - EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer)); } else { - EXPECT_VECTOR_EQ(initial_scroll_ + scroll_amount_, + EXPECT_POINTF_EQ(initial_scroll_ + scroll_amount_, CurrentScrollOffset(scroll_layer)); SetScrollOffset(scroll_layer, second_scroll_); SetOpacity(scroll_layer, 0.5f); @@ -2424,14 +2432,14 @@ class LayerTreeHostScrollTestPropertyTreeUpdate switch (impl->active_tree()->source_frame_number()) { case 0: - EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(initial_scroll_, + EXPECT_POINTF_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_POINTF_EQ(initial_scroll_, GetTransformNode(scroll_layer)->scroll_offset); PostSetNeedsCommitToMainThread(); break; case 1: - EXPECT_VECTOR_EQ(second_scroll_, ScrollOffsetBase(scroll_layer)); - EXPECT_VECTOR_EQ(second_scroll_, + EXPECT_POINTF_EQ(second_scroll_, ScrollOffsetBase(scroll_layer)); + EXPECT_POINTF_EQ(second_scroll_, GetTransformNode(scroll_layer)->scroll_offset); EndTest(); break; @@ -2439,8 +2447,8 @@ class LayerTreeHostScrollTestPropertyTreeUpdate } private: - gfx::Vector2dF initial_scroll_; - gfx::Vector2dF second_scroll_; + gfx::PointF initial_scroll_; + gfx::PointF second_scroll_; gfx::Vector2dF scroll_amount_; }; @@ -2450,7 +2458,7 @@ class LayerTreeHostScrollTestImplSideInvalidation : public LayerTreeHostScrollTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void DidScrollOuterViewport(const gfx::Vector2dF& offset) override { + void DidScrollOuterViewport(const gfx::PointF& offset) override { LayerTreeHostScrollTest::DidScrollOuterViewport(offset); // Defer responding to the main frame until an impl-side pending tree is @@ -2505,9 +2513,9 @@ class LayerTreeHostScrollTestImplSideInvalidation LayerImpl* scroll_layer = host_impl->pending_tree()->OuterViewportScrollLayerForTesting(); - gfx::Vector2dF scroll_offset = CurrentScrollOffset(scroll_layer); + gfx::PointF scroll_offset = CurrentScrollOffset(scroll_layer); int transform_index = scroll_layer->transform_tree_index(); - gfx::Vector2dF transform_tree_scroll_offset = + gfx::PointF transform_tree_scroll_offset = host_impl->pending_tree() ->property_trees() ->transform_tree.Node(transform_index) @@ -2613,14 +2621,14 @@ class LayerTreeHostScrollTestImplSideInvalidation EXPECT_EQ(3, num_of_main_frames_); } - const gfx::Vector2dF outer_viewport_offsets_[3] = { - gfx::Vector2dF(20, 20), gfx::Vector2dF(50, 50), gfx::Vector2dF(70, 70)}; + const gfx::PointF outer_viewport_offsets_[3] = { + gfx::PointF(20, 20), gfx::PointF(50, 50), gfx::PointF(70, 70)}; // Impl thread. int num_of_activations_ = 0; int num_of_main_frames_ = 0; bool invalidated_on_impl_thread_ = false; - CompletionEvent* impl_side_invalidation_event_ = nullptr; + raw_ptr<CompletionEvent> impl_side_invalidation_event_ = nullptr; // Main thread. int num_of_deltas_ = 0; @@ -2674,13 +2682,18 @@ class NonScrollingNonFastScrollableRegion : public LayerTreeHostScrollTest { void BeginTest() override { PostSetNeedsCommitToMainThread(); } + void WillCommit(const CommitState&) override { + middle_scrollable_scroll_tree_index_ = + middle_scrollable_->scroll_tree_index(); + } + void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { if (TestEnded()) return; ScrollNode* scroll_node = impl->active_tree()->property_trees()->scroll_tree.Node( - middle_scrollable_->scroll_tree_index()); + middle_scrollable_scroll_tree_index_); // The top-left hit should immediately hit the top layer's non-fast region. { @@ -2751,6 +2764,7 @@ class NonScrollingNonFastScrollableRegion : public LayerTreeHostScrollTest { scoped_refptr<Layer> bottom_; scoped_refptr<Layer> middle_scrollable_; scoped_refptr<Layer> top_; + int middle_scrollable_scroll_tree_index_ = ScrollTree::kInvalidNodeId; }; SINGLE_THREAD_TEST_F(NonScrollingNonFastScrollableRegion); @@ -2780,6 +2794,10 @@ class UnifiedScrollingRepaintOnScroll : public LayerTreeTest { layer_tree_host()->root_layer()->AddChild(layer_); } + void WillCommit(const CommitState&) override { + scroll_tree_index_ = layer_->scroll_tree_index(); + } + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { if (is_done_) return; @@ -2797,8 +2815,7 @@ class UnifiedScrollingRepaintOnScroll : public LayerTreeTest { ui::ScrollInputType::kTouchscreen); ASSERT_EQ(ScrollThread::SCROLL_ON_IMPL_THREAD, status.thread); - ASSERT_EQ(layer_->scroll_tree_index(), - impl->CurrentlyScrollingNode()->id); + ASSERT_EQ(scroll_tree_index_, impl->CurrentlyScrollingNode()->id); impl->GetInputHandler().ScrollUpdate( UpdateState(gfx::Point(), gfx::Vector2dF(0, 10)).get()); @@ -2814,6 +2831,7 @@ class UnifiedScrollingRepaintOnScroll : public LayerTreeTest { private: bool is_done_ = false; scoped_refptr<Layer> layer_; + int scroll_tree_index_ = ScrollTree::kInvalidNodeId; FakeContentLayerClient client_; base::test::ScopedFeatureList scoped_feature_list; }; diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index cff5d1fd567..71a41797583 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -21,6 +21,7 @@ #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/json/json_writer.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "base/timer/elapsed_timer.h" @@ -50,6 +51,7 @@ #include "cc/trees/property_tree.h" #include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" +#include "cc/trees/tree_synchronizer.h" #include "components/viz/common/traced_value.h" #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/point_conversions.h" @@ -68,11 +70,15 @@ class ViewportAnchor { LayerTreeImpl* tree_impl) : inner_(inner_scroll), outer_(outer_scroll), tree_impl_(tree_impl) { viewport_in_content_coordinates_ = - scroll_tree().current_scroll_offset(inner_->element_id); + scroll_tree() + .current_scroll_offset(inner_->element_id) + .OffsetFromOrigin(); if (outer_) { viewport_in_content_coordinates_ += - scroll_tree().current_scroll_offset(outer_->element_id); + scroll_tree() + .current_scroll_offset(outer_->element_id) + .OffsetFromOrigin(); } } @@ -83,8 +89,12 @@ class ViewportAnchor { scroll_tree().ClampScrollToMaxScrollOffset(*outer_, tree_impl_); gfx::Vector2dF viewport_location = - scroll_tree().current_scroll_offset(inner_->element_id) + - scroll_tree().current_scroll_offset(outer_->element_id); + scroll_tree() + .current_scroll_offset(inner_->element_id) + .OffsetFromOrigin() + + scroll_tree() + .current_scroll_offset(outer_->element_id) + .OffsetFromOrigin(); gfx::Vector2dF delta = viewport_in_content_coordinates_ - viewport_location; @@ -97,9 +107,9 @@ class ViewportAnchor { return tree_impl_->property_trees()->scroll_tree; } - ScrollNode* inner_; - ScrollNode* outer_; - LayerTreeImpl* tree_impl_; + raw_ptr<ScrollNode> inner_; + raw_ptr<ScrollNode> outer_; + raw_ptr<LayerTreeImpl> tree_impl_; gfx::Vector2dF viewport_in_content_coordinates_; }; @@ -132,7 +142,7 @@ void LayerTreeLifecycle::AdvanceTo(LifecycleState next_state) { LayerTreeImpl::LayerTreeImpl( LayerTreeHostImpl* host_impl, - scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor, + scoped_refptr<SyncedScale> page_scale_factor, scoped_refptr<SyncedBrowserControls> top_controls_shown_ratio, scoped_refptr<SyncedBrowserControls> bottom_controls_shown_ratio, scoped_refptr<SyncedElasticOverscroll> elastic_overscroll) @@ -221,19 +231,14 @@ void LayerTreeImpl::DidUpdateScrollOffset(ElementId id) { // immediate changes in the compositor, we want the scroll to propagate // through Blink in a commit and have Blink update properties, paint, // compositing, etc. Thus, we avoid mutating the transform tree in this case. - // TODO(bokan): We SetNeedsCommit in LTHI when a scroll happens but in a - // normal compositor scroll there isn't much urgency for a commit to be - // scheduled. We should look into what we can do to make sure this is - // proritized accordingly. https://crbug.com/1082618. - bool can_realize_scroll_on_compositor = + bool should_realize_scroll_on_compositor = !base::FeatureList::IsEnabled(features::kScrollUnification) || - (scroll_node->is_composited && - !scroll_node->main_thread_scrolling_reasons); + scroll_tree.CanRealizeScrollsOnCompositor(*scroll_node); DCHECK(scroll_node->transform_id != TransformTree::kInvalidNodeId); TransformTree& transform_tree = property_trees()->transform_tree; auto* transform_node = transform_tree.Node(scroll_node->transform_id); - if (can_realize_scroll_on_compositor) { + if (should_realize_scroll_on_compositor) { if (transform_node->scroll_offset != scroll_tree.current_scroll_offset(id)) { transform_node->scroll_offset = scroll_tree.current_scroll_offset(id); @@ -273,7 +278,7 @@ void LayerTreeImpl::UpdateScrollbarGeometries() { auto* scroll_node = scroll_tree.FindNodeFromElementId(scrolling_element_id); if (!scroll_node) continue; - gfx::Vector2dF current_offset = + gfx::PointF current_offset = scroll_tree.current_scroll_offset(scrolling_element_id); gfx::SizeF scrolling_size(scroll_node->bounds); gfx::Size bounds_size(scroll_tree.container_bounds(scroll_node->id)); @@ -289,7 +294,8 @@ void LayerTreeImpl::UpdateScrollbarGeometries() { // Add offset and bounds contribution of outer viewport. current_offset += - scroll_tree.current_scroll_offset(outer_scroll_node->element_id); + scroll_tree.current_scroll_offset(outer_scroll_node->element_id) + .OffsetFromOrigin(); gfx::SizeF outer_viewport_bounds( scroll_tree.container_bounds(outer_scroll_node->id)); viewport_bounds.SetToMin(outer_viewport_bounds); @@ -301,7 +307,8 @@ void LayerTreeImpl::UpdateScrollbarGeometries() { DCHECK(inner_scroll_node); // Add offset and bounds contribution of inner viewport. current_offset += - scroll_tree.current_scroll_offset(inner_scroll_node->element_id); + scroll_tree.current_scroll_offset(inner_scroll_node->element_id) + .OffsetFromOrigin(); gfx::SizeF inner_viewport_bounds( scroll_tree.container_bounds(inner_scroll_node->id)); viewport_bounds.SetToMin(inner_viewport_bounds); @@ -468,31 +475,37 @@ bool LayerTreeImpl::IsRootLayer(const LayerImpl* layer) const { return !layer_list_.empty() && layer_list_[0].get() == layer; } -gfx::Vector2dF LayerTreeImpl::TotalScrollOffset() const { +gfx::PointF LayerTreeImpl::TotalScrollOffset() const { gfx::Vector2dF offset; const auto& scroll_tree = property_trees()->scroll_tree; if (auto* inner_scroll = InnerViewportScrollNode()) { - offset += scroll_tree.current_scroll_offset(inner_scroll->element_id); + offset += scroll_tree.current_scroll_offset(inner_scroll->element_id) + .OffsetFromOrigin(); DCHECK(OuterViewportScrollNode()); - offset += scroll_tree.current_scroll_offset( - OuterViewportScrollNode()->element_id); + offset += + scroll_tree.current_scroll_offset(OuterViewportScrollNode()->element_id) + .OffsetFromOrigin(); } - return offset; + return gfx::PointAtOffsetFromOrigin(offset); } -gfx::Vector2dF LayerTreeImpl::TotalMaxScrollOffset() const { +gfx::PointF LayerTreeImpl::TotalMaxScrollOffset() const { gfx::Vector2dF offset; const auto& scroll_tree = property_trees()->scroll_tree; - if (viewport_property_ids_.inner_scroll != ScrollTree::kInvalidNodeId) - offset += scroll_tree.MaxScrollOffset(viewport_property_ids_.inner_scroll); + if (viewport_property_ids_.inner_scroll != ScrollTree::kInvalidNodeId) { + offset += scroll_tree.MaxScrollOffset(viewport_property_ids_.inner_scroll) + .OffsetFromOrigin(); + } - if (viewport_property_ids_.outer_scroll != ScrollTree::kInvalidNodeId) - offset += scroll_tree.MaxScrollOffset(viewport_property_ids_.outer_scroll); + if (viewport_property_ids_.outer_scroll != ScrollTree::kInvalidNodeId) { + offset += scroll_tree.MaxScrollOffset(viewport_property_ids_.outer_scroll) + .OffsetFromOrigin(); + } - return offset; + return gfx::PointAtOffsetFromOrigin(offset); } OwnedLayerImplList LayerTreeImpl::DetachLayers() { @@ -507,7 +520,7 @@ OwnedLayerImplList LayerTreeImpl::DetachLayersKeepingRootLayerForTesting() { return layers; } -void LayerTreeImpl::SetPropertyTrees(PropertyTrees* property_trees) { +void LayerTreeImpl::SetPropertyTrees(PropertyTrees& property_trees) { // Updating the scroll tree shouldn't clobber the currently scrolling node so // stash it and restore it at the end of this method. To maintain the // current scrolling node we need to use element ids which are stable across @@ -520,13 +533,13 @@ void LayerTreeImpl::SetPropertyTrees(PropertyTrees* property_trees) { std::vector<std::unique_ptr<RenderSurfaceImpl>> old_render_surfaces; property_trees_.effect_tree.TakeRenderSurfaces(&old_render_surfaces); - property_trees_ = *property_trees; + property_trees_ = property_trees; bool render_surfaces_changed = property_trees_.effect_tree.CreateOrReuseRenderSurfaces( &old_render_surfaces, this); if (render_surfaces_changed) set_needs_update_draw_properties(); - property_trees->effect_tree.PushCopyRequestsTo(&property_trees_.effect_tree); + property_trees.effect_tree.PushCopyRequestsTo(&property_trees_.effect_tree); property_trees_.is_main_thread = false; property_trees_.is_active = IsActiveTree(); // The value of some effect node properties (like is_drawn) depends on @@ -543,6 +556,184 @@ void LayerTreeImpl::SetPropertyTrees(PropertyTrees* property_trees) { SetCurrentlyScrollingNode(scrolling_node); } +void LayerTreeImpl::PullPropertiesFrom(CommitState& commit_state, + ThreadUnsafeCommitState& unsafe_state) { + lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync); + + if (commit_state.next_commit_forces_redraw) + ForceRedrawNextActivation(); + if (commit_state.next_commit_forces_recalculate_raster_scales) + ForceRecalculateRasterScales(); + if (!commit_state.pending_presentation_time_callbacks.empty()) { + AddPresentationCallbacks( + std::move(commit_state.pending_presentation_time_callbacks)); + } + + if (commit_state.needs_full_tree_sync) + TreeSynchronizer::SynchronizeTrees(unsafe_state, this); + + if (commit_state.clear_caches_on_next_commit) { + host_impl_->ClearHistory(); + host_impl_->ClearCaches(); + } + + TRACE_EVENT0("cc", "LayerTreeImpl::PullProperties"); + + PullPropertyTreesFrom(unsafe_state.root_layer.get(), + unsafe_state.property_trees); + lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedPropertyTrees); + + if (commit_state.needs_surface_ranges_sync) { + ClearSurfaceRanges(); + SetSurfaceRanges(commit_state.SurfaceRanges()); + } + TreeSynchronizer::PushLayerProperties(commit_state, unsafe_state, this); + lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedLayerProperties); + + PullLayerTreePropertiesFrom(commit_state); + + PassSwapPromises(std::move(commit_state.swap_promises)); + AppendEventsMetricsFromMainThread(std::move(commit_state.event_metrics)); + + set_ui_resource_request_queue(commit_state.ui_resource_request_queue); + + // This must happen after synchronizing property trees and after pushing + // properties, which updates the clobber_active_value flag. + // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. + property_trees()->scroll_tree.PushScrollUpdatesFromMainThread( + &unsafe_state.property_trees, this, + settings().commit_fractional_scroll_deltas); + + // This must happen after synchronizing property trees and after push + // properties, which updates property tree indices, but before animation + // host pushes properties as animation host push properties can change + // KeyframeModel::InEffect and we want the old InEffect value for updating + // property tree scrolling and animation. + // TODO(pdr): Enforce this comment with DCHECKS and a lifecycle state. + UpdatePropertyTreeAnimationFromMainThread(); + + TRACE_EVENT0("cc", "LayerTreeHost::AnimationHost::PushProperties"); + DCHECK(mutator_host()); + unsafe_state.mutator_host->PushPropertiesTo(mutator_host(), + unsafe_state.property_trees); + + if (IsActiveTree() && property_trees()->changed) { + if (unsafe_state.root_layer) { + if (unsafe_state.property_trees.sequence_number == + property_trees()->sequence_number) { + property_trees()->PushChangeTrackingTo(&unsafe_state.property_trees); + } else { + MoveChangeTrackingToLayers(); + } + } + } else { + MoveChangeTrackingToLayers(); + } + + // Updating elements affects whether animations are in effect based on their + // properties so run after pushing updated animation properties. + host_impl_->UpdateElements(ElementListType::PENDING); + + lifecycle().AdvanceTo(LayerTreeLifecycle::kNotSyncing); +} + +void LayerTreeImpl::PullPropertyTreesFrom(Layer* root_layer, + PropertyTrees& property_trees) { + // Property trees may store damage status. We preserve the sync tree damage + // status by pushing the damage status from sync tree property trees to main + // thread property trees or by moving it onto the layers. + if (root_layer && IsActiveTree() && property_trees_.changed) { + if (property_trees.sequence_number == property_trees_.sequence_number) + property_trees_.PushChangeTrackingTo(&property_trees); + else + MoveChangeTrackingToLayers(); + } + + SetPropertyTrees(property_trees); +} + +void LayerTreeImpl::PullLayerTreePropertiesFrom(CommitState& commit_state) { + set_needs_full_tree_sync(commit_state.needs_full_tree_sync); + + if (commit_state.hud_layer_id != Layer::INVALID_ID) { + LayerImpl* hud_impl = LayerById(commit_state.hud_layer_id); + set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl)); + } else { + set_hud_layer(nullptr); + } + + set_background_color(commit_state.background_color); + set_have_scroll_event_handlers(commit_state.have_scroll_event_handlers); + set_event_listener_properties(EventListenerClass::kTouchStartOrMove, + commit_state.GetEventListenerProperties( + EventListenerClass::kTouchStartOrMove)); + set_event_listener_properties( + EventListenerClass::kMouseWheel, + commit_state.GetEventListenerProperties(EventListenerClass::kMouseWheel)); + set_event_listener_properties(EventListenerClass::kTouchEndOrCancel, + commit_state.GetEventListenerProperties( + EventListenerClass::kTouchEndOrCancel)); + + SetViewportPropertyIds(commit_state.viewport_property_ids); + + RegisterSelection(commit_state.selection); + + PushPageScaleFromMainThread(commit_state.page_scale_factor, + commit_state.min_page_scale_factor, + commit_state.max_page_scale_factor); + + SetBrowserControlsParams(commit_state.browser_controls_params); + set_overscroll_behavior(commit_state.overscroll_behavior); + PushBrowserControlsFromMainThread(commit_state.top_controls_shown_ratio, + commit_state.bottom_controls_shown_ratio); + elastic_overscroll()->PushMainToPending(commit_state.elastic_overscroll); + if (IsActiveTree()) + elastic_overscroll()->PushPendingToActive(); + + SetDisplayColorSpaces(commit_state.display_color_spaces); + SetExternalPageScaleFactor(commit_state.external_page_scale_factor); + + set_painted_device_scale_factor(commit_state.painted_device_scale_factor); + SetDeviceScaleFactor(commit_state.device_scale_factor); + SetDeviceViewportRect(commit_state.device_viewport_rect); + + if (commit_state.new_local_surface_id_request) + RequestNewLocalSurfaceId(); + + SetLocalSurfaceIdFromParent(commit_state.local_surface_id_from_parent); + SetVisualPropertiesUpdateDuration( + commit_state.visual_properties_update_duration); + + if (commit_state.pending_page_scale_animation) { + SetPendingPageScaleAnimation( + std::move(commit_state.pending_page_scale_animation)); + } + + if (commit_state.force_send_metadata_request) + RequestForceSendMetadata(); + + set_has_ever_been_drawn(false); + + // TODO(ericrk): The viewport changes caused by |top_controls_shown_ratio_| + // changes should propagate back to the main tree. This does not currently + // happen, so we must force the impl tree to update its viewports if + // |top_controls_shown_ratio_| is greater than 0.0f and less than 1.0f + // (partially shown). crbug.com/875943 + if (commit_state.top_controls_shown_ratio > 0.0f && + commit_state.top_controls_shown_ratio < 1.0f) { + UpdateViewportContainerSizes(); + } + + set_display_transform_hint(commit_state.display_transform_hint); + + if (commit_state.delegated_ink_metadata) + set_delegated_ink_metadata(std::move(commit_state.delegated_ink_metadata)); + + // Transfer page transition directives. + for (auto& request : commit_state.document_transition_requests) + AddDocumentTransitionRequest(std::move(request)); +} + void LayerTreeImpl::PushPropertyTreesTo(LayerTreeImpl* target_tree) { TRACE_EVENT0("cc", "LayerTreeImpl::PushPropertyTreesTo"); // Property trees may store damage status. We preserve the active tree @@ -556,7 +747,7 @@ void LayerTreeImpl::PushPropertyTreesTo(LayerTreeImpl* target_tree) { target_tree->MoveChangeTrackingToLayers(); } - target_tree->SetPropertyTrees(&property_trees_); + target_tree->SetPropertyTrees(property_trees_); EventMetrics::List events_metrics; events_metrics.swap(events_metrics_from_main_thread_); @@ -1238,11 +1429,11 @@ void LayerTreeImpl::SetExternalPageScaleFactor( DidUpdatePageScale(); } -SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() { +SyncedScale* LayerTreeImpl::page_scale_factor() { return page_scale_factor_.get(); } -const SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() const { +const SyncedScale* LayerTreeImpl::page_scale_factor() const { return page_scale_factor_.get(); } @@ -1401,6 +1592,8 @@ bool LayerTreeImpl::UpdateDrawProperties( layer->DrawTransform()); } + // TODO(khushalsagar) : Skip computing occlusion for shared elements. See + // crbug.com/1258058. if (it.state() == EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE) { const RenderSurfaceImpl* occlusion_surface = @@ -1761,12 +1954,12 @@ void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->BeginArray("swap_promise_trace_ids"); for (const auto& swap_promise : swap_promise_list_) - state->AppendDouble(swap_promise->TraceId()); + state->AppendDouble(swap_promise->GetTraceId()); state->EndArray(); state->BeginArray("pinned_swap_promise_trace_ids"); for (const auto& swap_promise : pinned_swap_promise_list_) - state->AppendDouble(swap_promise->TraceId()); + state->AppendDouble(swap_promise->GetTraceId()); state->EndArray(); state->BeginArray("layers"); @@ -2148,7 +2341,7 @@ struct FindClosestMatchingLayerState { FindClosestMatchingLayerState() : closest_match(nullptr), closest_distance(-std::numeric_limits<float>::infinity()) {} - LayerImpl* closest_match; + raw_ptr<LayerImpl> closest_match; // Note that the positive z-axis points towards the camera, so bigger means // closer in this case, counterintuitively. float closest_distance; @@ -2444,7 +2637,7 @@ static void FindClosestMatchingLayerForAttribution( // targeted frame so that we can properly attribute the (common) parent -> // child frame relationship. This is made possible since we can accurately // hit test within layerized subframes, but not for all occluders. - if (auto* layer = state->closest_match) { + if (auto* layer = state->closest_match.get()) { auto& transform_tree = layer->layer_tree_impl()->property_trees()->transform_tree; for (auto* node = transform_tree.Node(layer->transform_tree_index()); node; @@ -2471,7 +2664,7 @@ ElementId LayerTreeImpl::FindFrameElementIdAtPoint( FindClosestMatchingLayerForAttribution(screen_space_point, layer_list_[0].get(), &state); - if (const auto* layer = state.closest_match) { + if (const auto* layer = state.closest_match.get()) { // TODO(https://crbug.com/1058870): Permit hit testing only if the framed // element hit has a simple mask/clip. We don't have enough information // about complex masks/clips on the impl-side to do accurate hit testing. diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 76ea3c12451..2d0a86b288c 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -14,6 +14,7 @@ #include <vector> #include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/base/synced_property.h" #include "cc/input/browser_controls_offset_manager.h" @@ -64,9 +65,10 @@ class UIResourceRequest; class VideoFrameControllerClient; struct PendingPageScaleAnimation; -typedef std::vector<UIResourceRequest> UIResourceRequestQueue; -typedef SyncedProperty<AdditionGroup<float>> SyncedBrowserControls; -typedef SyncedProperty<AdditionGroup<gfx::Vector2dF>> SyncedElasticOverscroll; +using UIResourceRequestQueue = std::vector<UIResourceRequest>; +using SyncedScale = SyncedProperty<ScaleGroup>; +using SyncedBrowserControls = SyncedProperty<AdditionGroup<float>>; +using SyncedElasticOverscroll = SyncedProperty<AdditionGroup<gfx::Vector2dF>>; class LayerTreeLifecycle { public: @@ -104,7 +106,7 @@ class CC_EXPORT LayerTreeImpl { enum : int { kFixedPointHitsThreshold = 3 }; LayerTreeImpl( LayerTreeHostImpl* host_impl, - scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor, + scoped_refptr<SyncedScale> page_scale_factor, scoped_refptr<SyncedBrowserControls> top_controls_shown_ratio, scoped_refptr<SyncedBrowserControls> bottom_controls_shown_ratio, scoped_refptr<SyncedElasticOverscroll> elastic_overscroll); @@ -188,7 +190,7 @@ class CC_EXPORT LayerTreeImpl { OwnedLayerImplList DetachLayers(); OwnedLayerImplList DetachLayersKeepingRootLayerForTesting(); - void SetPropertyTrees(PropertyTrees* property_trees); + void SetPropertyTrees(PropertyTrees& property_trees); PropertyTrees* property_trees() { // TODO(pdr): We should enable this DCHECK because it will catch uses of // stale property trees, but it currently fails too many existing tests. @@ -197,6 +199,10 @@ class CC_EXPORT LayerTreeImpl { } const PropertyTrees* property_trees() const { return &property_trees_; } + void PullPropertiesFrom(CommitState& commit_state, + ThreadUnsafeCommitState& unsafe_state); + void PullPropertyTreesFrom(Layer* root_layer, PropertyTrees& property_trees); + void PullLayerTreePropertiesFrom(CommitState& commit_state); void PushPropertyTreesTo(LayerTreeImpl* tree_impl); void PushPropertiesTo(LayerTreeImpl* tree_impl); void PushSurfaceRangesTo(LayerTreeImpl* tree_impl); @@ -280,8 +286,8 @@ class CC_EXPORT LayerTreeImpl { hud_layer_ = layer_impl; } - gfx::Vector2dF TotalScrollOffset() const; - gfx::Vector2dF TotalMaxScrollOffset() const; + gfx::PointF TotalScrollOffset() const; + gfx::PointF TotalMaxScrollOffset() const; void AddPresentationCallbacks( std::vector<PresentationTimeCallbackBuffer::MainCallback> callbacks); @@ -294,7 +300,6 @@ class CC_EXPORT LayerTreeImpl { // The following viewport related property nodes will only ever be set on the // main-frame's renderer (i.e. OOPIF and UI compositors will not have these // set. - using ViewportPropertyIds = LayerTreeHost::ViewportPropertyIds; void SetViewportPropertyIds(const ViewportPropertyIds& ids); const TransformNode* OverscrollElasticityTransformNode() const; @@ -325,7 +330,7 @@ class CC_EXPORT LayerTreeImpl { const_cast<const LayerTreeImpl*>(this)->OuterViewportScrollNode()); } - LayerTreeHost::ViewportPropertyIds ViewportPropertyIdsForTesting() const { + ViewportPropertyIds ViewportPropertyIdsForTesting() const { return viewport_property_ids_; } LayerImpl* InnerViewportScrollLayerForTesting() const; @@ -363,8 +368,8 @@ class CC_EXPORT LayerTreeImpl { float page_scale_delta() const { return page_scale_factor()->Delta(); } - SyncedProperty<ScaleGroup>* page_scale_factor(); - const SyncedProperty<ScaleGroup>* page_scale_factor() const; + SyncedScale* page_scale_factor(); + const SyncedScale* page_scale_factor() const; void SetDeviceScaleFactor(float device_scale_factor); float device_scale_factor() const { return device_scale_factor_; } @@ -517,7 +522,7 @@ class CC_EXPORT LayerTreeImpl { void AddLayerShouldPushProperties(LayerImpl* layer); void ClearLayersThatShouldPushProperties(); - const base::flat_set<LayerImpl*>& LayersThatShouldPushProperties() { + const base::flat_set<LayerImpl*>& LayersThatShouldPushProperties() const { return layers_that_should_push_properties_; } @@ -805,20 +810,20 @@ class CC_EXPORT LayerTreeImpl { const gfx::PointF& screen_space_point, const Functor& func); - LayerTreeHostImpl* host_impl_; + raw_ptr<LayerTreeHostImpl> host_impl_; int source_frame_number_; int is_first_frame_after_commit_tracker_; - HeadsUpDisplayLayerImpl* hud_layer_; + raw_ptr<HeadsUpDisplayLayerImpl> hud_layer_; PropertyTrees property_trees_; SkColor background_color_; int last_scrolled_scroll_node_index_; - LayerTreeHost::ViewportPropertyIds viewport_property_ids_; + ViewportPropertyIds viewport_property_ids_; LayerSelection selection_; - scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor_; + scoped_refptr<SyncedScale> page_scale_factor_; float min_page_scale_factor_; float max_page_scale_factor_; float external_page_scale_factor_; diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 9840506f62b..68bcca35815 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -5,16 +5,18 @@ #include "cc/trees/layer_tree_impl.h" #include "base/cxx17_backports.h" +#include "base/memory/raw_ptr.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_raster_source.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_impl_test_base.h" #include "cc/trees/clip_node.h" +#include "cc/trees/debug_rect_history.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/layer_tree_host_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/test/geometry_util.h" namespace cc { namespace { @@ -112,9 +114,9 @@ class LayerTreeImplTest : public LayerTreeImplTestBase, public testing::Test { } // These layers are created by HitTestSimpleTree(). - LayerImpl* top_ = nullptr; - LayerImpl* left_child_ = nullptr; - LayerImpl* right_child_ = nullptr; + raw_ptr<LayerImpl> top_ = nullptr; + raw_ptr<LayerImpl> left_child_ = nullptr; + raw_ptr<LayerImpl> right_child_ = nullptr; }; TEST_F(LayerTreeImplTest, HitTestingForSingleLayer) { @@ -1350,7 +1352,7 @@ TEST_F(LayerTreeImplTest, gfx::Rect(scaled_bounds_for_root)); host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor); - LayerTreeImpl::ViewportPropertyIds viewport_property_ids; + ViewportPropertyIds viewport_property_ids; viewport_property_ids.page_scale_transform = page_scale_layer->transform_tree_index(); host_impl().active_tree()->SetViewportPropertyIds(viewport_property_ids); @@ -1709,7 +1711,7 @@ TEST_F(LayerTreeImplTest, HitTestingTouchHandlerRegionsForLayerThatIsNotDrawn) { test_point); EXPECT_FALSE(result_layer); EXPECT_FALSE(test_layer->contributes_to_drawn_render_surface()); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( expected_screen_space_transform, draw_property_utils::ScreenSpaceTransform( test_layer, @@ -1729,7 +1731,7 @@ TEST_F(LayerTreeImplTest, HitTestingTouchHandlerRegionsForLayerThatIsNotDrawn) { ASSERT_TRUE(result_layer); ASSERT_EQ(test_layer, result_layer); EXPECT_FALSE(result_layer->contributes_to_drawn_render_surface()); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( expected_screen_space_transform, draw_property_utils::ScreenSpaceTransform( test_layer, @@ -2003,7 +2005,7 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) { gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize( root->bounds(), device_scale_factor * page_scale_factor); - LayerTreeImpl::ViewportPropertyIds viewport_property_ids; + ViewportPropertyIds viewport_property_ids; viewport_property_ids.page_scale_transform = page_scale_layer->transform_tree_index(); host_impl().active_tree()->SetViewportPropertyIds(viewport_property_ids); @@ -2254,6 +2256,17 @@ TEST_F(LayerTreeImplTest, HitTestingCorrectLayerWheelListener) { EXPECT_EQ(left_child, result_layer); } +TEST_F(LayerTreeImplTest, DebugRectHistoryLayoutShiftWithoutHud) { + LayerTreeDebugState state; + state.show_layout_shift_regions = true; + + auto history = DebugRectHistory::Create(); + history->SaveDebugRectsForCurrentFrame(host_impl().active_tree(), nullptr, + RenderSurfaceList{}, state); + + EXPECT_EQ(0u, history->debug_rects().size()); +} + namespace { class PersistentSwapPromise @@ -2270,9 +2283,7 @@ class PersistentSwapPromise DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override { return DidNotSwapAction::KEEP_ACTIVE; } - - void OnCommit() override {} - int64_t TraceId() const override { return 0; } + int64_t GetTraceId() const override { return 0; } }; class NotPersistentSwapPromise @@ -2289,9 +2300,7 @@ class NotPersistentSwapPromise DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override { return DidNotSwapAction::BREAK_PROMISE; } - - void OnCommit() override {} - int64_t TraceId() const override { return 0; } + int64_t GetTraceId() const override { return 0; } }; } // namespace diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index e38646f8834..86180d4f001 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -198,6 +198,9 @@ class CC_EXPORT LayerTreeSettings { // LayerTreeHostSingleThreadClient::FrameSinksToThrottleUpdated() will be // called with candidates. bool enable_compositing_based_throttling = false; + + // Whether it is a LayerTree for ui. + bool is_layer_tree_for_ui = false; }; class CC_EXPORT LayerListSettings : public LayerTreeSettings { diff --git a/chromium/cc/trees/mutator_host.h b/chromium/cc/trees/mutator_host.h index 6e9533bf089..86c536bf37e 100644 --- a/chromium/cc/trees/mutator_host.h +++ b/chromium/cc/trees/mutator_host.h @@ -13,6 +13,7 @@ #include "cc/trees/layer_tree_mutator.h" #include "cc/trees/mutator_host_client.h" #include "ui/gfx/geometry/box_f.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_f.h" namespace cc { @@ -20,6 +21,7 @@ namespace cc { class MutatorEvents; class MutatorHostClient; class LayerTreeMutator; +class PropertyTrees; class ScrollTree; // Used as the return value of GetAnimationScales() to indicate that there is @@ -54,7 +56,8 @@ class MutatorHost { virtual void SetLayerTreeMutator( std::unique_ptr<LayerTreeMutator> mutator) = 0; - virtual void PushPropertiesTo(MutatorHost* host_impl) = 0; + virtual void PushPropertiesTo(MutatorHost* host_impl, + const PropertyTrees& property_trees) = 0; virtual void SetScrollAnimationDurationForTesting( base::TimeDelta duration) = 0; @@ -125,20 +128,20 @@ class MutatorHost { virtual void ImplOnlyAutoScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, float autoscroll_velocity, base::TimeDelta animation_start_offset) = 0; virtual void ImplOnlyScrollAnimationCreate( ElementId element_id, - const gfx::Vector2dF& target_offset, - const gfx::Vector2dF& current_offset, + const gfx::PointF& target_offset, + const gfx::PointF& current_offset, base::TimeDelta delayed_by, base::TimeDelta animation_start_offset) = 0; virtual bool ImplOnlyScrollAnimationUpdateTarget( const gfx::Vector2dF& scroll_delta, - const gfx::Vector2dF& max_scroll_offset, + const gfx::PointF& max_scroll_offset, base::TimeTicks frame_monotonic_time, base::TimeDelta delayed_by) = 0; @@ -149,7 +152,8 @@ class MutatorHost { virtual ElementId ImplOnlyScrollAnimatingElement() const = 0; virtual size_t MainThreadAnimationsCount() const = 0; - virtual bool HasCustomPropertyAnimations() const = 0; + virtual bool HasInvalidationAnimation() const = 0; + virtual bool HasNativePropertyAnimation() const = 0; virtual bool CurrentFrameHadRAF() const = 0; virtual bool NextFrameHasPendingRAF() const = 0; virtual bool HasCanvasInvalidation() const = 0; diff --git a/chromium/cc/trees/mutator_host_client.h b/chromium/cc/trees/mutator_host_client.h index 5f995ff13ba..a9fa96a1f30 100644 --- a/chromium/cc/trees/mutator_host_client.h +++ b/chromium/cc/trees/mutator_host_client.h @@ -12,7 +12,7 @@ namespace gfx { class Transform; -class Vector2dF; +class PointF; } namespace cc { @@ -52,7 +52,7 @@ class MutatorHostClient { virtual void SetElementScrollOffsetMutated( ElementId element_id, ElementListType list_type, - const gfx::Vector2dF& scroll_offset) = 0; + const gfx::PointF& scroll_offset) = 0; // Allows to change IsAnimating value for a set of properties. virtual void ElementIsAnimatingChanged( @@ -66,8 +66,6 @@ class MutatorHostClient { float maximum_scale) = 0; virtual void ScrollOffsetAnimationFinished() = 0; - virtual gfx::Vector2dF GetScrollOffsetForAnimation( - ElementId element_id) const = 0; virtual void NotifyAnimationWorkletStateChange( AnimationWorkletMutationState state, diff --git a/chromium/cc/trees/occlusion_tracker.h b/chromium/cc/trees/occlusion_tracker.h index c734beff463..f55c8e94034 100644 --- a/chromium/cc/trees/occlusion_tracker.h +++ b/chromium/cc/trees/occlusion_tracker.h @@ -7,6 +7,7 @@ #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/base/simple_enclosed_region.h" #include "cc/cc_export.h" #include "cc/layers/effect_tree_layer_list_iterator.h" @@ -61,7 +62,7 @@ class CC_EXPORT OcclusionTracker { struct StackObject { StackObject() : target(nullptr) {} explicit StackObject(const RenderSurfaceImpl* target) : target(target) {} - const RenderSurfaceImpl* target; + raw_ptr<const RenderSurfaceImpl> target; SimpleEnclosedRegion occlusion_from_outside_target; SimpleEnclosedRegion occlusion_from_inside_target; bool ignores_parent_occlusion = false; diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index d2719e1b21e..5bfd1076891 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -20,7 +20,6 @@ #include "cc/test/fake_layer_tree_frame_sink.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" #include "cc/test/property_tree_test_utils.h" #include "cc/test/test_occlusion_tracker.h" diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index 1dab2a9427a..4a5399940c4 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -23,6 +23,7 @@ #include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" #include "components/viz/common/frame_sinks/copy_output_request.h" +#include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/transform_util.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -316,8 +317,18 @@ gfx::Vector2dF TransformTree::StickyPositionOffset(TransformNode* node) { property_trees()->scroll_tree.Node(sticky_data->scroll_ancestor); TransformNode* transform_node = Node(scroll_node->transform_id); const auto& scroll_offset = transform_node->scroll_offset; - DCHECK(property_trees()->scroll_tree.current_scroll_offset( - scroll_node->element_id) == scroll_offset); + // TODO(crbug.com/1206694): Understand why these values are not exactly equal + // and which one we should be using here. +#if DCHECK_IS_ON() + { + const auto& scroll_offset_delta = + property_trees()->scroll_tree.current_scroll_offset( + scroll_node->element_id) - + scroll_offset; + DCHECK_LE(std::abs(scroll_offset_delta.x()), 0.5); + DCHECK_LE(std::abs(scroll_offset_delta.y()), 0.5); + } +#endif gfx::PointF scroll_position(scroll_offset.x(), scroll_offset.y()); if (transform_node->scrolls) { // The scroll position does not include snapping which shifts the scroll @@ -1260,6 +1271,10 @@ bool ScrollTree::IsComposited(const ScrollNode& node) const { return node.is_composited; } +bool ScrollTree::CanRealizeScrollsOnCompositor(const ScrollNode& node) const { + return node.is_composited && !node.main_thread_scrolling_reasons; +} + void ScrollTree::clear() { PropertyTree<ScrollNode>::clear(); @@ -1281,12 +1296,12 @@ void ScrollTree::clear() { #endif } -gfx::Vector2dF ScrollTree::MaxScrollOffset(int scroll_node_id) const { +gfx::PointF ScrollTree::MaxScrollOffset(int scroll_node_id) const { const ScrollNode* scroll_node = Node(scroll_node_id); gfx::SizeF scroll_bounds = this->scroll_bounds(scroll_node_id); if (!scroll_node->scrollable || scroll_bounds.IsEmpty()) - return gfx::Vector2dF(); + return gfx::PointF(); TransformTree& transform_tree = property_trees()->transform_tree; float scale_factor = 1.f; @@ -1299,12 +1314,12 @@ gfx::Vector2dF ScrollTree::MaxScrollOffset(int scroll_node_id) const { gfx::Size clip_layer_bounds = container_bounds(scroll_node->id); - gfx::Vector2dF max_offset( + gfx::PointF max_offset( scaled_scroll_bounds.width() - clip_layer_bounds.width(), scaled_scroll_bounds.height() - clip_layer_bounds.height()); max_offset.Scale(1 / scale_factor); - max_offset.SetToMax(gfx::Vector2dF()); + max_offset.SetToMax(gfx::PointF()); return max_offset; } @@ -1320,7 +1335,7 @@ gfx::SizeF ScrollTree::scroll_bounds(int scroll_node_id) const { void ScrollTree::OnScrollOffsetAnimated(ElementId id, int scroll_tree_index, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, LayerTreeImpl* layer_tree_impl) { // Only active tree needs to be updated, pending tree will find out about // these changes as a result of the shared SyncedProperty. @@ -1408,29 +1423,29 @@ const SyncedScrollOffset* ScrollTree::GetSyncedScrollOffset( gfx::Vector2dF ScrollTree::ClampScrollToMaxScrollOffset( const ScrollNode& node, LayerTreeImpl* layer_tree_impl) { - gfx::Vector2dF old_offset = current_scroll_offset(node.element_id); - gfx::Vector2dF clamped_offset = ClampScrollOffsetToLimits(old_offset, node); + gfx::PointF old_offset = current_scroll_offset(node.element_id); + gfx::PointF clamped_offset = ClampScrollOffsetToLimits(old_offset, node); gfx::Vector2dF delta = clamped_offset - old_offset; if (!delta.IsZero()) ScrollBy(node, delta, layer_tree_impl); return delta; } -const gfx::Vector2dF ScrollTree::current_scroll_offset(ElementId id) const { +const gfx::PointF ScrollTree::current_scroll_offset(ElementId id) const { if (property_trees()->is_main_thread) { auto it = scroll_offset_map_.find(id); - return it != scroll_offset_map_.end() ? it->second : gfx::Vector2dF(); + return it != scroll_offset_map_.end() ? it->second : gfx::PointF(); } - return GetSyncedScrollOffset(id) - ? GetSyncedScrollOffset(id)->Current(property_trees()->is_active) - : gfx::Vector2dF(); + if (const auto* synced_scroll_offset = GetSyncedScrollOffset(id)) + return synced_scroll_offset->Current(property_trees()->is_active); + return gfx::PointF(); } -const gfx::Vector2dF ScrollTree::GetPixelSnappedScrollOffset( +const gfx::PointF ScrollTree::GetPixelSnappedScrollOffset( int scroll_node_id) const { const ScrollNode* scroll_node = Node(scroll_node_id); DCHECK(scroll_node); - gfx::Vector2dF offset = current_scroll_offset(scroll_node->element_id); + gfx::PointF offset = current_scroll_offset(scroll_node->element_id); const TransformNode* transform_node = property_trees()->transform_tree.Node(scroll_node->transform_id); @@ -1474,14 +1489,14 @@ gfx::Vector2dF ScrollTree::PullDeltaForMainThread( // TODO(flackr): We should ideally round the fractional scrolls in the same // direction as the scroll will be snapped but for common cases this is // equivalent to rounding to the nearest integer offset. - gfx::Vector2dF current_offset = + gfx::PointF current_offset = scroll_offset->Current(/* is_active_tree */ true); - gfx::Vector2dF rounded_offset = gfx::ToRoundedVector2d(current_offset); + gfx::PointF rounded_offset(gfx::ToRoundedPoint(current_offset)); // The calculation of the difference from the rounded active base is to // represent the integer delta that the main thread should know about. - gfx::Vector2dF active_base = scroll_offset->ActiveBase(); + gfx::PointF active_base = scroll_offset->ActiveBase(); gfx::Vector2dF diff_active_base = - active_base - gfx::ToRoundedVector2d(active_base); + active_base - gfx::PointF(gfx::ToRoundedPoint(active_base)); scroll_offset->SetCurrent(rounded_offset + diff_active_base); gfx::Vector2dF delta = scroll_offset->PullDeltaForMainThread(); scroll_offset->SetCurrent(current_offset); @@ -1567,8 +1582,8 @@ void ScrollTree::PushScrollUpdatesFromMainThread( // PullDeltaForMainThread where only an integer delta is extracted and // prevents unnecessary property change in this case. if (!use_fractional_deltas) { - gfx::Vector2dF pending_offset = synced_scroll_offset->Current(false); - gfx::Vector2dF rounded_offset = gfx::ToRoundedVector2d(pending_offset); + gfx::PointF pending_offset = synced_scroll_offset->Current(false); + gfx::PointF rounded_offset(gfx::ToRoundedPoint(pending_offset)); needs_scroll_update = map_entry.second != rounded_offset; } @@ -1612,7 +1627,7 @@ void ScrollTree::ApplySentScrollDeltasFromAbortedCommit() { } void ScrollTree::SetBaseScrollOffset(ElementId id, - const gfx::Vector2dF& scroll_offset) { + const gfx::PointF& scroll_offset) { if (property_trees()->is_main_thread) { scroll_offset_map_[id] = scroll_offset; return; @@ -1625,7 +1640,7 @@ void ScrollTree::SetBaseScrollOffset(ElementId id, } bool ScrollTree::SetScrollOffset(ElementId id, - const gfx::Vector2dF& scroll_offset) { + const gfx::PointF& scroll_offset) { // TODO(crbug.com/1087088): Remove TRACE_EVENT call when the bug is fixed TRACE_EVENT2("cc", "ScrollTree::SetScrollOffset", "x", scroll_offset.x(), "y", scroll_offset.y()); @@ -1636,16 +1651,14 @@ bool ScrollTree::SetScrollOffset(ElementId id, return true; } - if (property_trees()->is_active) { + if (property_trees()->is_active) return GetOrCreateSyncedScrollOffset(id)->SetCurrent(scroll_offset); - } return false; } -bool ScrollTree::UpdateScrollOffsetBaseForTesting( - ElementId id, - const gfx::Vector2dF& offset) { +bool ScrollTree::UpdateScrollOffsetBaseForTesting(ElementId id, + const gfx::PointF& offset) { DCHECK(!property_trees()->is_main_thread); SyncedScrollOffset* synced_scroll_offset = GetOrCreateSyncedScrollOffset(id); bool changed = synced_scroll_offset->PushMainToPending(offset); @@ -1660,7 +1673,7 @@ bool ScrollTree::SetScrollOffsetDeltaForTesting(ElementId id, GetOrCreateSyncedScrollOffset(id)->ActiveBase() + delta); } -const gfx::Vector2dF ScrollTree::GetScrollOffsetBaseForTesting( +const gfx::PointF ScrollTree::GetScrollOffsetBaseForTesting( ElementId id) const { DCHECK(!property_trees()->is_main_thread); if (GetSyncedScrollOffset(id)) { @@ -1668,7 +1681,7 @@ const gfx::Vector2dF ScrollTree::GetScrollOffsetBaseForTesting( ? GetSyncedScrollOffset(id)->ActiveBase() : GetSyncedScrollOffset(id)->PendingBase(); } - return gfx::Vector2dF(); + return gfx::PointF(); } const gfx::Vector2dF ScrollTree::GetScrollOffsetDeltaForTesting( @@ -1677,7 +1690,7 @@ const gfx::Vector2dF ScrollTree::GetScrollOffsetDeltaForTesting( if (GetSyncedScrollOffset(id)) { return property_trees()->is_active ? GetSyncedScrollOffset(id)->Delta() - : GetSyncedScrollOffset(id)->PendingDelta().get(); + : GetSyncedScrollOffset(id)->PendingDelta(); } return gfx::Vector2dF(); } @@ -1691,8 +1704,8 @@ gfx::Vector2dF ScrollTree::ScrollBy(const ScrollNode& scroll_node, if (!scroll_node.user_scrollable_vertical) adjusted_scroll.set_y(0); DCHECK(scroll_node.scrollable); - gfx::Vector2dF old_offset = current_scroll_offset(scroll_node.element_id); - gfx::Vector2dF new_offset = + gfx::PointF old_offset = current_scroll_offset(scroll_node.element_id); + gfx::PointF new_offset = ClampScrollOffsetToLimits(old_offset + adjusted_scroll, scroll_node); if (SetScrollOffset(scroll_node.element_id, new_offset)) layer_tree_impl->DidUpdateScrollOffset(scroll_node.element_id); @@ -1701,11 +1714,11 @@ gfx::Vector2dF ScrollTree::ScrollBy(const ScrollNode& scroll_node, return old_offset + scroll - new_offset; } -gfx::Vector2dF ScrollTree::ClampScrollOffsetToLimits( - gfx::Vector2dF offset, +gfx::PointF ScrollTree::ClampScrollOffsetToLimits( + gfx::PointF offset, const ScrollNode& scroll_node) const { offset.SetToMin(MaxScrollOffset(scroll_node.id)); - offset.SetToMax(gfx::Vector2dF()); + offset.SetToMax(gfx::PointF()); return offset; } @@ -1716,7 +1729,7 @@ void ScrollTree::SetScrollCallbacks(base::WeakPtr<ScrollCallbacks> callbacks) { void ScrollTree::NotifyDidCompositorScroll( ElementId scroll_element_id, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, const absl::optional<TargetSnapAreaElementIds>& snap_target_ids) { DCHECK(property_trees()->is_main_thread); if (callbacks_) { diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index 892ae75148c..d67757701c3 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -15,6 +15,7 @@ #include "base/callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "cc/base/synced_property.h" #include "cc/cc_export.h" @@ -24,6 +25,7 @@ #include "cc/trees/mutator_host.h" #include "cc/trees/sticky_position_constraint.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/transform.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -49,7 +51,8 @@ struct ScrollNode; struct TransformNode; struct TransformCachedNodeData; -typedef SyncedProperty<AdditionGroup<gfx::Vector2dF>> SyncedScrollOffset; +using SyncedScrollOffset = + SyncedProperty<AdditionGroup<gfx::PointF, gfx::Vector2dF>>; class PropertyTrees; @@ -111,7 +114,7 @@ class CC_EXPORT PropertyTree { protected: std::vector<T> nodes_; bool needs_update_; - PropertyTrees* property_trees_; + raw_ptr<PropertyTrees> property_trees_; }; struct StickyPositionNodeData; @@ -383,7 +386,7 @@ class ScrollCallbacks { // Called after the composited scroll offset changed. virtual void DidCompositorScroll( ElementId scroll_element_id, - const gfx::Vector2dF&, + const gfx::PointF&, const absl::optional<TargetSnapAreaElementIds>&) = 0; // Called after the hidden status of composited scrollbars changed. Note that // |scroll_element_id| is the element id of the scroll not of the scrollbars. @@ -407,10 +410,10 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { void clear(); - gfx::Vector2dF MaxScrollOffset(int scroll_node_id) const; + gfx::PointF MaxScrollOffset(int scroll_node_id) const; void OnScrollOffsetAnimated(ElementId id, int scroll_tree_index, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, LayerTreeImpl* layer_tree_impl); gfx::Size container_bounds(int scroll_node_id) const; gfx::SizeF scroll_bounds(int scroll_node_id) const; @@ -429,7 +432,7 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { // Returns the current scroll offset. On the main thread this would return the // value for the LayerTree while on the impl thread this is the current value // on the active tree. - const gfx::Vector2dF current_scroll_offset(ElementId id) const; + const gfx::PointF current_scroll_offset(ElementId id) const; // Returns the scroll offset taking into account any adjustments that may be // included due to pixel snapping. @@ -441,7 +444,7 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { // simple cases but we really should update the whole transform tree otherwise // we are ignoring any parent transform node that needs updating and thus our // snap amount can be incorrect. - const gfx::Vector2dF GetPixelSnappedScrollOffset(int scroll_node_id) const; + const gfx::PointF GetPixelSnappedScrollOffset(int scroll_node_id) const; // Collects deltas for scroll changes on the impl thread that need to be // reported to the main thread during the main frame. As such, should only be @@ -468,25 +471,25 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { void PushScrollUpdatesFromPendingTree(PropertyTrees* pending_property_trees, LayerTreeImpl* active_tree); - void SetBaseScrollOffset(ElementId id, const gfx::Vector2dF& scroll_offset); + void SetBaseScrollOffset(ElementId id, const gfx::PointF& scroll_offset); // Returns true if the scroll offset is changed. - bool SetScrollOffset(ElementId id, const gfx::Vector2dF& scroll_offset); + bool SetScrollOffset(ElementId id, const gfx::PointF& scroll_offset); void SetScrollOffsetClobberActiveValue(ElementId id) { GetOrCreateSyncedScrollOffset(id)->set_clobber_active_value(); } bool UpdateScrollOffsetBaseForTesting(ElementId id, - const gfx::Vector2dF& offset); + const gfx::PointF& offset); bool SetScrollOffsetDeltaForTesting(ElementId id, const gfx::Vector2dF& delta); - const gfx::Vector2dF GetScrollOffsetBaseForTesting(ElementId id) const; + const gfx::PointF GetScrollOffsetBaseForTesting(ElementId id) const; const gfx::Vector2dF GetScrollOffsetDeltaForTesting(ElementId id) const; void CollectScrollDeltasForTesting(bool use_fractional_deltas = false); gfx::Vector2dF ScrollBy(const ScrollNode& scroll_node, const gfx::Vector2dF& scroll, LayerTreeImpl* layer_tree_impl); - gfx::Vector2dF ClampScrollOffsetToLimits(gfx::Vector2dF offset, - const ScrollNode& scroll_node) const; + gfx::PointF ClampScrollOffsetToLimits(gfx::PointF offset, + const ScrollNode& scroll_node) const; const SyncedScrollOffset* GetSyncedScrollOffset(ElementId id) const; @@ -501,7 +504,7 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { void NotifyDidCompositorScroll( ElementId scroll_element_id, - const gfx::Vector2dF& scroll_offset, + const gfx::PointF& scroll_offset, const absl::optional<TargetSnapAreaElementIds>& snap_target_ids); void NotifyDidChangeScrollbarsHidden(ElementId scroll_element_id, bool hidden); @@ -511,12 +514,16 @@ class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> { // repainting. bool IsComposited(const ScrollNode& node) const; + // Returns true iff the node is composited and does not have any non-transient + // main-thread scrolling reasons (see main_thread_scrolling_reason.h). + bool CanRealizeScrollsOnCompositor(const ScrollNode& node) const; + private: // ScrollTree doesn't use the needs_update flag. using PropertyTree::needs_update; using PropertyTree::set_needs_update; - using ScrollOffsetMap = base::flat_map<ElementId, gfx::Vector2dF>; + using ScrollOffsetMap = base::flat_map<ElementId, gfx::PointF>; using SyncedScrollOffsetMap = base::flat_map<ElementId, scoped_refptr<SyncedScrollOffset>>; diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index 99083b30235..78d01dfb6d0 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -13,6 +13,7 @@ #include <vector> #include "base/auto_reset.h" +#include "base/memory/raw_ptr.h" #include "cc/base/math_util.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" @@ -91,8 +92,8 @@ class PropertyTreeBuilderContext { bool subtree_has_rounded_corner, bool created_transform_node) const; - LayerTreeHost* layer_tree_host_; - Layer* root_layer_; + raw_ptr<LayerTreeHost> layer_tree_host_; + raw_ptr<Layer> root_layer_; MutatorHost& mutator_host_; PropertyTrees& property_trees_; TransformTree& transform_tree_; diff --git a/chromium/cc/trees/property_tree_builder_unittest.cc b/chromium/cc/trees/property_tree_builder_unittest.cc index 6e92fa0325e..0bda315570b 100644 --- a/chromium/cc/trees/property_tree_builder_unittest.cc +++ b/chromium/cc/trees/property_tree_builder_unittest.cc @@ -19,6 +19,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/animation/keyframe/keyframed_animation_curve.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform.h" #include "ui/gfx/geometry/vector2d_conversions.h" @@ -52,8 +53,8 @@ class PropertyTreeBuilderTest : public LayerTreeImplTestBase, // TODO(https://crbug.com/939968) This call should be handled by // FakeLayerTreeHost instead of manually pushing the properties from the // layer tree host to the pending tree. - host()->PushLayerTreePropertiesTo(host_impl()->pending_tree()); - + host_impl()->pending_tree()->PullLayerTreePropertiesFrom( + *host()->GetPendingCommitState()); UpdateDrawProperties(host_impl()->pending_tree()); } @@ -452,8 +453,7 @@ TEST_F(PropertyTreeBuilderTest, TextureLayerSnapping) { auto child_screen_space_transform = ImplOf(child)->ScreenSpaceTransform(); EXPECT_NE(child_screen_space_transform, fractional_translate); fractional_translate.RoundTranslationComponents(); - EXPECT_TRANSFORMATION_MATRIX_EQ(child_screen_space_transform, - fractional_translate); + EXPECT_TRANSFORM_EQ(child_screen_space_transform, fractional_translate); gfx::RectF layer_bounds_in_screen_space = MathUtil::MapClippedRect( child_screen_space_transform, gfx::RectF(gfx::SizeF(child->bounds()))); EXPECT_EQ(layer_bounds_in_screen_space, gfx::RectF(11.f, 20.f, 100.f, 100.f)); diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc index df8918eb854..ad7d9dc7678 100644 --- a/chromium/cc/trees/property_tree_unittest.cc +++ b/chromium/cc/trees/property_tree_unittest.cc @@ -9,7 +9,6 @@ #include "cc/input/main_thread_scrolling_reason.h" #include "cc/test/fake_impl_task_runner_provider.h" #include "cc/test/fake_layer_tree_host_impl.h" -#include "cc/test/geometry_test_utils.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" @@ -19,6 +18,7 @@ #include "cc/trees/transform_node.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/test/geometry_util.h" namespace cc { namespace { @@ -35,14 +35,14 @@ TEST(PropertyTreeTest, ComputeTransformRoot) { gfx::Transform transform; expected.Translate(2, 2); tree.CombineTransformsBetween(1, 0, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); transform.MakeIdentity(); expected.MakeIdentity(); expected.Translate(-2, -2); bool success = tree.CombineInversesBetween(0, 1, &transform); EXPECT_TRUE(success); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); } TEST(PropertyTreeTest, SetNeedsUpdate) { @@ -78,27 +78,27 @@ TEST(PropertyTreeTest, ComputeTransformChild) { expected.Translate(3, 3); tree.CombineTransformsBetween(2, 1, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); transform.MakeIdentity(); expected.MakeIdentity(); expected.Translate(-3, -3); bool success = tree.CombineInversesBetween(1, 2, &transform); EXPECT_TRUE(success); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); transform.MakeIdentity(); expected.MakeIdentity(); expected.Translate(5, 5); tree.CombineTransformsBetween(2, 0, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); transform.MakeIdentity(); expected.MakeIdentity(); expected.Translate(-5, -5); success = tree.CombineInversesBetween(0, 2, &transform); EXPECT_TRUE(success); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); } TEST(PropertyTreeTest, ComputeTransformSibling) { @@ -125,14 +125,14 @@ TEST(PropertyTreeTest, ComputeTransformSibling) { expected.Translate(4, 4); tree.CombineTransformsBetween(3, 2, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); transform.MakeIdentity(); expected.MakeIdentity(); expected.Translate(-4, -4); bool success = tree.CombineInversesBetween(2, 3, &transform); EXPECT_TRUE(success); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); } TEST(PropertyTreeTest, ComputeTransformSiblingSingularAncestor) { @@ -173,14 +173,14 @@ TEST(PropertyTreeTest, ComputeTransformSiblingSingularAncestor) { expected.Translate(4, 4); tree.CombineTransformsBetween(4, 3, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); transform.MakeIdentity(); expected.MakeIdentity(); expected.Translate(-4, -4); bool success = tree.CombineInversesBetween(3, 4, &transform); EXPECT_TRUE(success); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); } TEST(PropertyTreeTest, TransformsWithFlattening) { @@ -225,23 +225,21 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { gfx::Transform to_target; property_trees.GetToTarget(child, effect_parent, &to_target); - EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_about_x, to_target); + EXPECT_TRANSFORM_EQ(rotation_about_x, to_target); - EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_x * rotation_about_x, - tree.ToScreen(child)); + EXPECT_TRANSFORM_EQ(flattened_rotation_about_x * rotation_about_x, + tree.ToScreen(child)); property_trees.GetToTarget(grand_child, effect_parent, &to_target); - EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_x * rotation_about_x, - to_target); + EXPECT_TRANSFORM_EQ(flattened_rotation_about_x * rotation_about_x, to_target); - EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_x * - flattened_rotation_about_x * - rotation_about_x, - tree.ToScreen(grand_child)); + EXPECT_TRANSFORM_EQ(flattened_rotation_about_x * flattened_rotation_about_x * + rotation_about_x, + tree.ToScreen(grand_child)); gfx::Transform grand_child_to_child; tree.CombineTransformsBetween(grand_child, child, &grand_child_to_child); - EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_about_x, grand_child_to_child); + EXPECT_TRANSFORM_EQ(rotation_about_x, grand_child_to_child); // Remove flattening at grand_child, and recompute transforms. tree.Node(grand_child)->flattens_inherited_transform = false; @@ -249,16 +247,15 @@ TEST(PropertyTreeTest, TransformsWithFlattening) { draw_property_utils::ComputeTransforms(&tree); property_trees.GetToTarget(grand_child, effect_parent, &to_target); - EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_about_x * rotation_about_x, - to_target); + EXPECT_TRANSFORM_EQ(rotation_about_x * rotation_about_x, to_target); - EXPECT_TRANSFORMATION_MATRIX_EQ( + EXPECT_TRANSFORM_EQ( flattened_rotation_about_x * rotation_about_x * rotation_about_x, tree.ToScreen(grand_child)); grand_child_to_child.MakeIdentity(); tree.CombineTransformsBetween(grand_child, child, &grand_child_to_child); - EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_about_x, grand_child_to_child); + EXPECT_TRANSFORM_EQ(rotation_about_x, grand_child_to_child); } TEST(PropertyTreeTest, MultiplicationOrder) { @@ -283,14 +280,14 @@ TEST(PropertyTreeTest, MultiplicationOrder) { gfx::Transform inverse; tree.CombineTransformsBetween(2, 0, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); bool success = tree.CombineInversesBetween(0, 2, &inverse); EXPECT_TRUE(success); transform = transform * inverse; expected.MakeIdentity(); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); } TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) { @@ -313,7 +310,7 @@ TEST(PropertyTreeTest, ComputeTransformWithUninvertibleTransform) { gfx::Transform inverse; tree.CombineTransformsBetween(2, 1, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected, transform); + EXPECT_TRANSFORM_EQ(expected, transform); // To compute this would require inverting the 0 matrix, so we cannot // succeed. @@ -348,7 +345,7 @@ TEST(PropertyTreeTest, ComputeTransformToTargetWithZeroSurfaceContentsScale) { gfx::Transform transform; tree.CombineTransformsBetween(child_id, grand_parent_id, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); + EXPECT_TRANSFORM_EQ(expected_transform, transform); tree.Node(grand_parent_id)->local.MakeIdentity(); tree.Node(grand_parent_id)->local.Scale(0.f, 2.f); @@ -359,7 +356,7 @@ TEST(PropertyTreeTest, ComputeTransformToTargetWithZeroSurfaceContentsScale) { transform.MakeIdentity(); tree.CombineTransformsBetween(child_id, grand_parent_id, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); + EXPECT_TRANSFORM_EQ(expected_transform, transform); tree.Node(grand_parent_id)->local.MakeIdentity(); tree.Node(grand_parent_id)->local.Scale(0.f, 0.f); @@ -370,7 +367,7 @@ TEST(PropertyTreeTest, ComputeTransformToTargetWithZeroSurfaceContentsScale) { transform.MakeIdentity(); tree.CombineTransformsBetween(child_id, grand_parent_id, &transform); - EXPECT_TRANSFORMATION_MATRIX_EQ(expected_transform, transform); + EXPECT_TRANSFORM_EQ(expected_transform, transform); } TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { @@ -400,8 +397,7 @@ TEST(PropertyTreeTest, FlatteningWhenDestinationHasOnlyFlatAncestors) { gfx::Transform grand_child_to_parent; tree.CombineTransformsBetween(grand_child, parent, &grand_child_to_parent); - EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_x, - grand_child_to_parent); + EXPECT_TRANSFORM_EQ(flattened_rotation_about_x, grand_child_to_parent); } TEST(PropertyTreeTest, ScreenSpaceOpacityUpdateTest) { @@ -618,18 +614,16 @@ TEST(ScrollTreeTest, GetPixelSnappedScrollOffsetNegativeOffset) { scroll_tree.Node(scroll_node_id)->element_id = element_id; // Set a scroll value close to 0. - scroll_tree.SetScrollOffset(element_id, gfx::Vector2dF(0, 0.1)); + scroll_tree.SetScrollOffset(element_id, gfx::PointF(0, 0.1)); transform_tree.Node(transform_node_id)->scrolls = true; - transform_tree.Node(transform_node_id)->scroll_offset = - gfx::Vector2dF(0, 0.1); + transform_tree.Node(transform_node_id)->scroll_offset = gfx::PointF(0, 0.1); // Pretend that the snap amount was slightly larger than 0.1. transform_tree.Node(transform_node_id)->snap_amount = gfx::Vector2dF(0, 0.2); transform_tree.Node(transform_node_id)->needs_local_transform_update = false; // The returned offset should be clamped at a minimum of 0. - gfx::Vector2dF offset = - scroll_tree.GetPixelSnappedScrollOffset(scroll_node_id); + gfx::PointF offset = scroll_tree.GetPixelSnappedScrollOffset(scroll_node_id); EXPECT_EQ(offset.y(), 0); } @@ -672,7 +666,7 @@ TEST(ScrollTreeTest, PushScrollUpdatesFromMainThreadIntegerDelta) { scroll_node_id; // Push main scroll to pending. - main_scroll_tree.SetScrollOffset(element_id, gfx::Vector2dF(0, 1)); + main_scroll_tree.SetScrollOffset(element_id, gfx::PointF(0, 1)); pending_scroll_tree.PushScrollUpdatesFromMainThread( &property_trees, host_impl.pending_tree(), use_fractional_deltas); const SyncedScrollOffset* scroll_offset = @@ -684,7 +678,7 @@ TEST(ScrollTreeTest, PushScrollUpdatesFromMainThreadIntegerDelta) { pending_scroll_tree.SetScrollOffsetDeltaForTesting(element_id, gfx::Vector2dF(0, 0.25)); main_scroll_tree.CollectScrollDeltasForTesting(use_fractional_deltas); - EXPECT_EQ(gfx::Vector2dF(0, 1), + EXPECT_EQ(gfx::PointF(0, 1), main_scroll_tree.current_scroll_offset(element_id)); // Rounding logic turned on should not cause property change on push. diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index 316fbd1a25e..ce648e1d98c 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -49,7 +49,6 @@ class CC_EXPORT Proxy { virtual void SetNeedsUpdateLayers() = 0; virtual void SetNeedsCommit() = 0; virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0; - virtual void SetNextCommitWaitsForActivation() = 0; virtual void SetTargetLocalSurfaceId( const viz::LocalSurfaceId& target_local_surface_id) = 0; @@ -99,13 +98,15 @@ class CC_EXPORT Proxy { virtual void SetUkmSmoothnessDestination( base::WritableSharedMemoryMapping ukm_smoothness_data) = 0; - virtual void ClearHistory() = 0; - virtual void SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer) = 0; virtual void SetEnableFrameRateThrottling( bool enable_frame_rate_throttling) = 0; + + // Returns a percentage representing average throughput of last X seconds. + // Only implemenented for single threaded proxy. + virtual uint32_t GetAverageThroughput() const = 0; }; } // namespace cc diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index 2d740e3d878..16e18534ae1 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -14,6 +14,7 @@ #include "base/auto_reset.h" #include "base/bind.h" +#include "base/memory/raw_ptr.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "cc/base/devtools_instrumentation.h" @@ -58,14 +59,17 @@ class ScopedCompletionEvent { ScopedCompletionEvent& operator=(const ScopedCompletionEvent&) = delete; private: - CompletionEvent* const event_; + const raw_ptr<CompletionEvent> event_; }; -ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, - LayerTreeHost* layer_tree_host, - TaskRunnerProvider* task_runner_provider) - : layer_tree_host_id_(layer_tree_host->GetId()), - commit_completion_waits_for_activation_(false), +ProxyImpl::ProxyImpl( + base::WeakPtr<ProxyMain> proxy_main_weak_ptr, + LayerTreeHost* layer_tree_host, + int id, + const LayerTreeSettings* settings, + RenderingStatsInstrumentation* rendering_stats_instrumentation, + TaskRunnerProvider* task_runner_provider) + : layer_tree_host_id_(id), next_frame_is_newly_committed_frame_(false), inside_draw_(false), task_runner_provider_(task_runner_provider), @@ -80,33 +84,26 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, DCHECK(IsMainThreadBlocked()); host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this); - const LayerTreeSettings& settings = layer_tree_host->GetSettings(); - send_compositor_frame_ack_ = settings.send_compositor_frame_ack; + send_compositor_frame_ack_ = settings->send_compositor_frame_ack; last_raster_priority_ = SAME_PRIORITY_FOR_BOTH_TREES; - SchedulerSettings scheduler_settings(settings.ToSchedulerSettings()); + SchedulerSettings scheduler_settings(settings->ToSchedulerSettings()); std::unique_ptr<CompositorTimingHistory> compositor_timing_history( new CompositorTimingHistory( scheduler_settings.using_synchronous_renderer_compositor, CompositorTimingHistory::RENDERER_UMA, - layer_tree_host->rendering_stats_instrumentation())); + rendering_stats_instrumentation)); scheduler_ = std::make_unique<Scheduler>( this, scheduler_settings, layer_tree_host_id_, task_runner_provider_->ImplThreadTaskRunner(), - std::move(compositor_timing_history), layer_tree_host->TakeMainPipeline(), - layer_tree_host->TakeCompositorPipeline(), + std::move(compositor_timing_history), host_impl_->compositor_frame_reporting_controller(), power_scheduler::PowerModeArbiter::GetInstance()); DCHECK_EQ(scheduler_->visible(), host_impl_->visible()); } -ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly() - : layer_tree_host(nullptr) {} - -ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() = default; - ProxyImpl::~ProxyImpl() { TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl"); DCHECK(IsImplThread()); @@ -270,46 +267,39 @@ void ProxyImpl::FrameSinksToThrottleUpdated( } void ProxyImpl::NotifyReadyToCommitOnImpl( - CompletionEvent* completion, - LayerTreeHost* layer_tree_host, + CompletionEvent* completion_event, + std::unique_ptr<CommitState> commit_state, + ThreadUnsafeCommitState* unsafe_state, base::TimeTicks main_thread_start_time, const viz::BeginFrameArgs& commit_args, - int source_frame_number, - std::vector<std::unique_ptr<SwapPromise>> swap_promises, - bool hold_commit_for_activation) { + CommitTimestamps* commit_timestamps) { TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToCommitOnImpl"); - DCHECK(!commit_completion_event_); + DCHECK(!data_for_commit_.get()); DCHECK(IsImplThread() && IsMainThreadBlocked()); DCHECK(scheduler_); DCHECK(scheduler_->CommitPending()); + // Inform the layer tree host that the commit has started, so that metrics + // can determine how long we waited for thread synchronization. + commit_timestamps->start = base::TimeTicks::Now(); + if (!host_impl_) { TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD); - completion->Signal(); + completion_event->Signal(); return; } - source_frame_number_ = source_frame_number; - swap_promises_ = std::move(swap_promises); - // Ideally, we should inform to impl thread when BeginMainFrame is started. // But, we can avoid a PostTask in here. scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time); - auto begin_main_frame_metrics = layer_tree_host->begin_main_frame_metrics(); + auto& begin_main_frame_metrics = commit_state->begin_main_frame_metrics; host_impl_->ReadyToCommit(commit_args, begin_main_frame_metrics.get()); - commit_completion_event_ = - std::make_unique<ScopedCompletionEvent>(completion); - commit_completion_waits_for_activation_ = hold_commit_for_activation; - - DCHECK(!blocked_main_commit().layer_tree_host); - blocked_main_commit().layer_tree_host = layer_tree_host; - - // Inform the layer tree host that the commit has started, so that metrics - // can determine how long we waited for thread synchronization. - layer_tree_host->SetImplCommitStartTime(base::TimeTicks::Now()); + data_for_commit_ = std::make_unique<DataForCommit>( + std::make_unique<ScopedCompletionEvent>(completion_event), + std::move(commit_state), unsafe_state, commit_timestamps); // Extract metrics data from the layer tree host and send them to the // scheduler to pass them to the compositor_timing_history object. @@ -397,8 +387,8 @@ void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) { scheduler_->SetVideoNeedsBeginFrames(needs_begin_frames); } -bool ProxyImpl::HasCustomPropertyAnimations() const { - return host_impl_->mutator_host()->HasCustomPropertyAnimations(); +bool ProxyImpl::HasInvalidationAnimation() const { + return host_impl_->mutator_host()->HasInvalidationAnimation(); } bool ProxyImpl::IsInsideDraw() { @@ -677,7 +667,8 @@ void ProxyImpl::ScheduledActionCommit() { TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionCommit"); DCHECK(IsImplThread()); DCHECK(IsMainThreadBlocked()); - DCHECK(commit_completion_event_); + DCHECK(data_for_commit_.get()); + DCHECK(data_for_commit_->IsValid()); // Relax the cross-thread access restriction to non-thread-safe RefCount. // It's safe since the main thread is blocked while a main-thread-bound @@ -685,28 +676,23 @@ void ProxyImpl::ScheduledActionCommit() { base::ScopedAllowCrossThreadRefCountAccess allow_cross_thread_ref_count_access; - host_impl_->BeginCommit(source_frame_number_); - blocked_main_commit().layer_tree_host->FinishCommitOnImplThread( - host_impl_.get(), std::move(swap_promises_)); - - // Remove the LayerTreeHost reference before the completion event is signaled - // and cleared. This is necessary since blocked_main_commit() allows access - // only while we have the completion event to ensure the main thread is - // blocked for a commit. - blocked_main_commit().layer_tree_host = nullptr; + auto* commit_state = data_for_commit_->commit_state.get(); + auto* unsafe_state = data_for_commit_->unsafe_state; + host_impl_->BeginCommit(commit_state->source_frame_number); + host_impl_->FinishCommit(*commit_state, *unsafe_state); + data_for_commit_->commit_timestamps->finish = base::TimeTicks::Now(); - if (commit_completion_waits_for_activation_) { + if (commit_state->commit_waits_for_activation) { // For some layer types in impl-side painting, the commit is held until the // sync tree is activated. It's also possible that the sync tree has // already activated if there was no work to be done. TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD); - commit_completion_waits_for_activation_ = false; - activation_completion_event_ = std::move(commit_completion_event_); + activation_completion_event_ = + std::move(data_for_commit_->commit_completion_event); } - commit_completion_event_ = nullptr; + data_for_commit_.reset(); scheduler_->DidCommit(); - // Delay this step until afer the main thread has been released as it's // often a good bit of work to update the tree and prepare the new frame. host_impl_->CommitComplete(); @@ -837,11 +823,6 @@ bool ProxyImpl::IsMainThreadBlocked() const { return task_runner_provider_->IsMainThreadBlocked(); } -ProxyImpl::BlockedMainCommitOnly& ProxyImpl::blocked_main_commit() { - DCHECK(IsMainThreadBlocked() && commit_completion_event_); - return main_thread_blocked_commit_vars_unsafe_; -} - base::SingleThreadTaskRunner* ProxyImpl::MainThreadTaskRunner() { return task_runner_provider_->MainThreadTaskRunner(); } @@ -860,10 +841,13 @@ void ProxyImpl::SetUkmSmoothnessDestination( void ProxyImpl::ClearHistory() { DCHECK(IsImplThread()); - DCHECK(IsMainThreadBlocked()); scheduler_->ClearHistory(); } +size_t ProxyImpl::CommitDurationSampleCountForTesting() const { + return scheduler_->CommitDurationSampleCountForTesting(); // IN-TEST +} + void ProxyImpl::SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer) { host_impl_->SetRenderFrameObserver(std::move(observer)); @@ -874,4 +858,21 @@ void ProxyImpl::SetEnableFrameRateThrottling( host_impl_->SetEnableFrameRateThrottling(enable_frame_rate_throttling); } +ProxyImpl::DataForCommit::DataForCommit( + std::unique_ptr<ScopedCompletionEvent> commit_completion_event, + std::unique_ptr<CommitState> commit_state, + ThreadUnsafeCommitState* unsafe_state, + CommitTimestamps* commit_timestamps) + : commit_completion_event(std::move(commit_completion_event)), + commit_state(std::move(commit_state)), + unsafe_state(unsafe_state), + commit_timestamps(commit_timestamps) {} + +ProxyImpl::DataForCommit::~DataForCommit() = default; + +bool ProxyImpl::DataForCommit::IsValid() const { + return commit_completion_event.get() && commit_state.get() && unsafe_state && + commit_timestamps; +} + } // namespace cc diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index 771ecfbfb41..c2f457a2e80 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -6,8 +6,10 @@ #define CC_TREES_PROXY_IMPL_H_ #include <memory> +#include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "cc/base/completion_event.h" #include "cc/base/delayed_unique_notifier.h" @@ -36,6 +38,9 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, public: ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, LayerTreeHost* layer_tree_host, + int id, + const LayerTreeSettings* settings, + RenderingStatsInstrumentation* rendering_stats_instrumentation, TaskRunnerProvider* task_runner_provider); ProxyImpl(const ProxyImpl&) = delete; ~ProxyImpl() override; @@ -64,18 +69,15 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, void SetVisibleOnImpl(bool visible); void ReleaseLayerTreeFrameSinkOnImpl(CompletionEvent* completion); void FinishGLOnImpl(CompletionEvent* completion); - void NotifyReadyToCommitOnImpl( - CompletionEvent* completion, - LayerTreeHost* layer_tree_host, - base::TimeTicks main_thread_start_time, - const viz::BeginFrameArgs& commit_args, - int source_frame_number, - std::vector<std::unique_ptr<SwapPromise>> swap_promises, - bool hold_commit_for_activation); + void NotifyReadyToCommitOnImpl(CompletionEvent* completion_event, + std::unique_ptr<CommitState> commit_state, + ThreadUnsafeCommitState* unsafe_state, + base::TimeTicks main_thread_start_time, + const viz::BeginFrameArgs& commit_args, + CommitTimestamps* commit_timestamps); void SetSourceURL(ukm::SourceId source_id, const GURL& url); void SetUkmSmoothnessDestination( base::WritableSharedMemoryMapping ukm_smoothness_data); - void ClearHistory(); void SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer); void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling); @@ -84,16 +86,10 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, bool* main_frame_will_happen); void RequestBeginMainFrameNotExpected(bool new_state) override; + void ClearHistory() override; + size_t CommitDurationSampleCountForTesting() const override; private: - // The members of this struct should be accessed on the impl thread only when - // the main thread is blocked for a commit. - struct BlockedMainCommitOnly { - BlockedMainCommitOnly(); - ~BlockedMainCommitOnly(); - LayerTreeHost* layer_tree_host; - }; - // LayerTreeHostImplClient implementation void DidLoseLayerTreeFrameSinkOnImplThread() override; void SetBeginFrameSource(viz::BeginFrameSource* source) override; @@ -159,7 +155,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, void ScheduledActionBeginMainFrameNotExpectedUntil( base::TimeTicks time) override; void FrameIntervalUpdated(base::TimeDelta interval) override {} - bool HasCustomPropertyAnimations() const override; + bool HasInvalidationAnimation() const override; DrawResult DrawInternal(bool forced_draw); @@ -171,14 +167,27 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, std::unique_ptr<Scheduler> scheduler_; - int source_frame_number_ = -1; - std::vector<std::unique_ptr<SwapPromise>> swap_promises_; + struct DataForCommit { + DataForCommit( + std::unique_ptr<ScopedCompletionEvent> commit_completion_event, + std::unique_ptr<CommitState> commit_state, + ThreadUnsafeCommitState* unsafe_state, + CommitTimestamps* commit_timestamps); - // Set when the main thread is waiting on a pending tree activation. - bool commit_completion_waits_for_activation_; + ~DataForCommit(); - // Set when the main thread is waiting on a commit to complete. - std::unique_ptr<ScopedCompletionEvent> commit_completion_event_; + bool IsValid() const; + + // Set when the main thread is waiting on a commit to complete. + std::unique_ptr<ScopedCompletionEvent> commit_completion_event; + std::unique_ptr<CommitState> commit_state; + ThreadUnsafeCommitState* unsafe_state; + // This is passed from the main thread so the impl thread can record + // timestamps at the beginning and end of commit. + CommitTimestamps* commit_timestamps = nullptr; + }; + + std::unique_ptr<DataForCommit> data_for_commit_; // Set when the main thread is waiting for activation to complete. std::unique_ptr<ScopedCompletionEvent> activation_completion_event_; @@ -195,16 +204,12 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, TreePriority last_raster_priority_; - TaskRunnerProvider* task_runner_provider_; + raw_ptr<TaskRunnerProvider> task_runner_provider_; DelayedUniqueNotifier smoothness_priority_expiration_notifier_; std::unique_ptr<LayerTreeHostImpl> host_impl_; - // Use accessors instead of this variable directly. - BlockedMainCommitOnly main_thread_blocked_commit_vars_unsafe_; - BlockedMainCommitOnly& blocked_main_commit(); - bool is_jank_injection_enabled_ = false; // Used to post tasks to ProxyMain on the main thread. diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index e4a323b4fee..07394e032bb 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -40,7 +40,6 @@ ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host, current_pipeline_stage_(NO_PIPELINE_STAGE), final_pipeline_stage_(NO_PIPELINE_STAGE), deferred_final_pipeline_stage_(NO_PIPELINE_STAGE), - commit_waits_for_activation_(false), started_(false), defer_main_frame_update_(false) { TRACE_EVENT0("cc", "ProxyMain::ProxyMain"); @@ -54,11 +53,16 @@ ProxyMain::~ProxyMain() { DCHECK(!started_); } -void ProxyMain::InitializeOnImplThread(CompletionEvent* completion_event) { +void ProxyMain::InitializeOnImplThread( + CompletionEvent* completion_event, + int id, + const LayerTreeSettings* settings, + RenderingStatsInstrumentation* rendering_stats_instrumentation) { DCHECK(task_runner_provider_->IsImplThread()); DCHECK(!proxy_impl_); proxy_impl_ = std::make_unique<ProxyImpl>( - weak_factory_.GetWeakPtr(), layer_tree_host_, task_runner_provider_); + weak_factory_.GetWeakPtr(), layer_tree_host_, id, settings, + rendering_stats_instrumentation, task_runner_provider_); completion_event->Signal(); } @@ -122,6 +126,7 @@ void ProxyMain::BeginMainFrame( std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) { DCHECK(IsMainThread()); DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_); + DCHECK(!layer_tree_host_->in_commit()); base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now(); @@ -312,23 +317,27 @@ void ProxyMain::BeginMainFrame( if (updated) final_pipeline_stage_ = COMMIT_PIPELINE_STAGE; - int source_frame_number = layer_tree_host_->SourceFrameNumber(); - - auto completion_event_ptr = std::make_unique<CompletionEvent>( - base::WaitableEvent::ResetPolicy::MANUAL); - auto* completion_event = completion_event_ptr.get(); - layer_tree_host_->WillCommit(std::move(completion_event_ptr)); - devtools_instrumentation::ScopedCommitTrace commit_task( layer_tree_host_->GetId(), begin_main_frame_state->begin_frame_args.frame_id.sequence_number); + auto completion_event_ptr = std::make_unique<CompletionEvent>( + base::WaitableEvent::ResetPolicy::MANUAL); + auto* completion_event = completion_event_ptr.get(); + bool has_updates = (final_pipeline_stage_ == COMMIT_PIPELINE_STAGE); + // Must get unsafe_state before calling WillCommit() to avoid deadlock. + auto& unsafe_state = layer_tree_host_->GetUnsafeStateForCommit(); + std::unique_ptr<CommitState> commit_state = layer_tree_host_->WillCommit( + std::move(completion_event_ptr), has_updates); + DCHECK_EQ(has_updates, (bool)commit_state.get()); current_pipeline_stage_ = COMMIT_PIPELINE_STAGE; - if (final_pipeline_stage_ < COMMIT_PIPELINE_STAGE) { - current_pipeline_stage_ = NO_PIPELINE_STAGE; + + if (!has_updates) { completion_event->Signal(); + current_pipeline_stage_ = NO_PIPELINE_STAGE; layer_tree_host_->DidBeginMainFrame(); - TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_INSTANT0("cc,raf_investigation", "EarlyOut_NoUpdates", + TRACE_EVENT_SCOPE_THREAD); std::vector<std::unique_ptr<SwapPromise>> swap_promises = layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises(); @@ -350,8 +359,8 @@ void ProxyMain::BeginMainFrame( // Although the commit is internally aborted, this is because it has been // detected to be a no-op. From the perspective of an embedder, this commit // went through, and input should no longer be throttled, etc. - layer_tree_host_->SetImplCommitFinishTime(base::TimeTicks::Now()); - layer_tree_host_->CommitComplete(); + layer_tree_host_->CommitComplete( + {base::TimeTicks(), base::TimeTicks::Now()}); layer_tree_host_->RecordEndOfFrameMetrics( begin_main_frame_start_time, begin_main_frame_state->active_sequence_trackers); @@ -364,24 +373,19 @@ void ProxyMain::BeginMainFrame( // begin the commit process, which is blocking from the main thread's // point of view, but asynchronously performed on the impl thread, // coordinated by the Scheduler. + CommitTimestamps commit_timestamps; { - TRACE_EVENT0("cc", "ProxyMain::BeginMainFrame::commit"); + TRACE_EVENT0("cc,raf_investigation", "ProxyMain::BeginMainFrame::commit"); DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); - std::vector<std::unique_ptr<SwapPromise>> swap_promises = - layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises(); - - bool hold_commit_for_activation = commit_waits_for_activation_; - commit_waits_for_activation_ = false; ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&ProxyImpl::NotifyReadyToCommitOnImpl, - base::Unretained(proxy_impl_.get()), completion_event, - layer_tree_host_, begin_main_frame_start_time, - begin_main_frame_state->begin_frame_args, - source_frame_number, std::move(swap_promises), - hold_commit_for_activation)); + FROM_HERE, base::BindOnce(&ProxyImpl::NotifyReadyToCommitOnImpl, + base::Unretained(proxy_impl_.get()), + completion_event, std::move(commit_state), + &unsafe_state, begin_main_frame_start_time, + begin_main_frame_state->begin_frame_args, + &commit_timestamps)); layer_tree_host_->WaitForCommitCompletion(); } @@ -390,9 +394,7 @@ void ProxyMain::BeginMainFrame( // but *not* script-created IntersectionObserver. See // blink::LocalFrameView::RunPostLifecycleSteps. layer_tree_host_->DidBeginMainFrame(); - - layer_tree_host_->CommitComplete(); - + layer_tree_host_->CommitComplete(commit_timestamps); layer_tree_host_->RecordEndOfFrameMetrics( begin_main_frame_start_time, begin_main_frame_state->active_sequence_trackers); @@ -485,11 +487,6 @@ void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) { base::Unretained(proxy_impl_.get()), damage_rect)); } -void ProxyMain::SetNextCommitWaitsForActivation() { - DCHECK(IsMainThread()); - commit_waits_for_activation_ = true; -} - void ProxyMain::SetTargetLocalSurfaceId( const viz::LocalSurfaceId& target_local_surface_id) { DCHECK(IsMainThread()); @@ -582,8 +579,12 @@ void ProxyMain::Start() { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); CompletionEvent completion; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&ProxyMain::InitializeOnImplThread, - base::Unretained(this), &completion)); + FROM_HERE, + base::BindOnce(&ProxyMain::InitializeOnImplThread, + base::Unretained(this), &completion, + layer_tree_host_->GetId(), + &layer_tree_host_->GetSettings(), + layer_tree_host_->rendering_stats_instrumentation())); completion.Wait(); } @@ -729,13 +730,6 @@ void ProxyMain::SetUkmSmoothnessDestination( std::move(ukm_smoothness_data))); } -void ProxyMain::ClearHistory() { - // Must only be called from the impl thread during commit. - DCHECK(task_runner_provider_->IsImplThread()); - DCHECK(task_runner_provider_->IsMainThreadBlocked()); - proxy_impl_->ClearHistory(); -} - void ProxyMain::SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer) { ImplThreadTaskRunner()->PostTask( @@ -752,4 +746,9 @@ void ProxyMain::SetEnableFrameRateThrottling( enable_frame_rate_throttling)); } +uint32_t ProxyMain::GetAverageThroughput() const { + NOTIMPLEMENTED(); + return 0u; +} + } // namespace cc diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h index 1157b1adcfb..3d0daf4a989 100644 --- a/chromium/cc/trees/proxy_main.h +++ b/chromium/cc/trees/proxy_main.h @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/trees/layer_tree_host.h" @@ -85,7 +86,6 @@ class CC_EXPORT ProxyMain : public Proxy { void SetNeedsUpdateLayers() override; void SetNeedsCommit() override; void SetNeedsRedraw(const gfx::Rect& damage_rect) override; - void SetNextCommitWaitsForActivation() override; void SetTargetLocalSurfaceId( const viz::LocalSurfaceId& target_local_surface_id) override; bool RequestedAnimatePending() override; @@ -109,10 +109,10 @@ class CC_EXPORT ProxyMain : public Proxy { void SetSourceURL(ukm::SourceId source_id, const GURL& url) override; void SetUkmSmoothnessDestination( base::WritableSharedMemoryMapping ukm_smoothness_data) override; - void ClearHistory() override; void SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer) override; void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling) override; + uint32_t GetAverageThroughput() const override; // Returns |true| if the request was actually sent, |false| if one was // already outstanding. @@ -122,12 +122,16 @@ class CC_EXPORT ProxyMain : public Proxy { bool IsImplThread() const; base::SingleThreadTaskRunner* ImplThreadTaskRunner(); - void InitializeOnImplThread(CompletionEvent* completion_event); + void InitializeOnImplThread( + CompletionEvent* completion_event, + int id, + const LayerTreeSettings* settings, + RenderingStatsInstrumentation* rendering_stats_instrumentation); void DestroyProxyImplOnImplThread(CompletionEvent* completion_event); - LayerTreeHost* layer_tree_host_; + raw_ptr<LayerTreeHost> layer_tree_host_; - TaskRunnerProvider* task_runner_provider_; + raw_ptr<TaskRunnerProvider> task_runner_provider_; const int layer_tree_host_id_; @@ -144,8 +148,6 @@ class CC_EXPORT ProxyMain : public Proxy { // deferred. CommitPipelineStage deferred_final_pipeline_stage_; - bool commit_waits_for_activation_; - // Set when the Proxy is started using Proxy::Start() and reset when it is // stopped using Proxy::Stop(). bool started_; diff --git a/chromium/cc/trees/render_frame_metadata.h b/chromium/cc/trees/render_frame_metadata.h index 3fa95d3a241..98b371bd544 100644 --- a/chromium/cc/trees/render_frame_metadata.h +++ b/chromium/cc/trees/render_frame_metadata.h @@ -67,7 +67,7 @@ class CC_EXPORT RenderFrameMetadata { SkColor root_background_color = SK_ColorWHITE; // Scroll offset of the root layer. - absl::optional<gfx::Vector2dF> root_scroll_offset; + absl::optional<gfx::PointF> root_scroll_offset; // Selection region relative to the current viewport. If the selection is // empty or otherwise unused, the bound types will indicate such. diff --git a/chromium/cc/trees/scoped_abort_remaining_swap_promises.h b/chromium/cc/trees/scoped_abort_remaining_swap_promises.h index af9cd7905ad..dd359a9d62b 100644 --- a/chromium/cc/trees/scoped_abort_remaining_swap_promises.h +++ b/chromium/cc/trees/scoped_abort_remaining_swap_promises.h @@ -5,6 +5,7 @@ #ifndef CC_TREES_SCOPED_ABORT_REMAINING_SWAP_PROMISES_H_ #define CC_TREES_SCOPED_ABORT_REMAINING_SWAP_PROMISES_H_ +#include "base/memory/raw_ptr.h" #include "cc/trees/swap_promise.h" #include "cc/trees/swap_promise_manager.h" @@ -26,7 +27,7 @@ class ScopedAbortRemainingSwapPromises { const ScopedAbortRemainingSwapPromises&) = delete; private: - SwapPromiseManager* swap_promise_manager_; + raw_ptr<SwapPromiseManager> swap_promise_manager_; }; } // namespace cc diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 4117db0036e..4f0d50c315d 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/trace_event/trace_event.h" +#include "build/chromeos_buildflags.h" #include "cc/base/completion_event.h" #include "cc/base/devtools_instrumentation.h" #include "cc/benchmarks/benchmark_instrumentation.h" @@ -78,7 +79,10 @@ void SingleThreadProxy::Start() { DCHECK(settings.single_thread_proxy_scheduler || !settings.enable_checker_imaging) << "Checker-imaging is not supported in synchronous single threaded mode"; - host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); + { + DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); + host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); + } if (settings.single_thread_proxy_scheduler && !scheduler_on_impl_thread_) { SchedulerSettings scheduler_settings(settings.ToSchedulerSettings()); scheduler_settings.commit_to_active_tree = true; @@ -92,8 +96,6 @@ void SingleThreadProxy::Start() { this, scheduler_settings, layer_tree_host_->GetId(), task_runner_provider_->MainThreadTaskRunner(), std::move(compositor_timing_history), - layer_tree_host_->TakeMainPipeline(), - layer_tree_host_->TakeCompositorPipeline(), host_impl_->compositor_frame_reporting_controller(), power_scheduler::PowerModeArbiter::GetInstance()); } @@ -193,8 +195,20 @@ void SingleThreadProxy::DoCommit(const viz::BeginFrameArgs& commit_args) { TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit"); DCHECK(task_runner_provider_->IsMainThread()); - int source_frame_number = layer_tree_host_->SourceFrameNumber(); - layer_tree_host_->WillCommit(nullptr); + if (host_impl_->EvictedUIResourcesExist()) + layer_tree_host_->GetUIResourceManager()->RecreateUIResources(); + + // Strictly speaking, it's not necessary to pass a CompletionEvent to + // WillCommit, since we can't have thread contention issues. The benefit to + // creating one here is that it simplifies LayerTreeHost::in_commit(), which + // useful in DCHECKs sprinkled throughout the code. + auto completion_event_ptr = std::make_unique<CompletionEvent>( + base::WaitableEvent::ResetPolicy::MANUAL); + auto* completion_event = completion_event_ptr.get(); + auto& unsafe_state = layer_tree_host_->GetUnsafeStateForCommit(); + std::unique_ptr<CommitState> commit_state = + layer_tree_host_->WillCommit(std::move(completion_event_ptr), + /*has_updates=*/true); devtools_instrumentation::ScopedCommitTrace commit_task( layer_tree_host_->GetId(), commit_args.frame_id.sequence_number); @@ -203,15 +217,10 @@ void SingleThreadProxy::DoCommit(const viz::BeginFrameArgs& commit_args) { DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); DebugScopedSetImplThread impl(task_runner_provider_); - host_impl_->ReadyToCommit(commit_args, nullptr); - host_impl_->BeginCommit(source_frame_number); + host_impl_->BeginCommit(commit_state->source_frame_number); - if (host_impl_->EvictedUIResourcesExist()) - layer_tree_host_->GetUIResourceManager()->RecreateUIResources(); - - layer_tree_host_->FinishCommitOnImplThread( - host_impl_.get(), - layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises()); + host_impl_->FinishCommit(*commit_state, unsafe_state); + completion_event->Signal(); if (scheduler_on_impl_thread_) { scheduler_on_impl_thread_->DidCommit(); @@ -247,7 +256,7 @@ void SingleThreadProxy::CommitComplete() { DebugScopedSetMainThread main(task_runner_provider_); layer_tree_host_->DidBeginMainFrame(); - layer_tree_host_->CommitComplete(); + layer_tree_host_->CommitComplete({base::TimeTicks(), base::TimeTicks::Now()}); next_frame_is_newly_committed_frame_ = true; } @@ -270,11 +279,6 @@ void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) { SetNeedsRedrawOnImplThread(); } -void SingleThreadProxy::SetNextCommitWaitsForActivation() { - // Activation always forced in commit, so nothing to do. - DCHECK(task_runner_provider_->IsMainThread()); -} - void SingleThreadProxy::SetTargetLocalSurfaceId( const viz::LocalSurfaceId& target_local_surface_id) { if (!scheduler_on_impl_thread_) @@ -450,7 +454,7 @@ void SingleThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) { scheduler_on_impl_thread_->SetVideoNeedsBeginFrames(needs_begin_frames); } -bool SingleThreadProxy::HasCustomPropertyAnimations() const { +bool SingleThreadProxy::HasInvalidationAnimation() const { return false; } @@ -649,7 +653,7 @@ void SingleThreadProxy::CompositeImmediatelyForTest( StopDeferringCommits(PaintHoldingCommitTrigger::kFeatureDisabled); DoBeginMainFrame(begin_frame_args); commit_requested_ = false; - DoPainting(); + DoPainting(begin_frame_args); DoCommit(begin_frame_args); DCHECK_EQ( @@ -770,11 +774,22 @@ void SingleThreadProxy::ClearHistory() { scheduler_on_impl_thread_->ClearHistory(); } +size_t SingleThreadProxy::CommitDurationSampleCountForTesting() const { + DCHECK(scheduler_on_impl_thread_); + return scheduler_on_impl_thread_ + ->CommitDurationSampleCountForTesting(); // IN-TEST +} + void SingleThreadProxy::SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer) { host_impl_->SetRenderFrameObserver(std::move(observer)); } +uint32_t SingleThreadProxy::GetAverageThroughput() const { + DebugScopedSetImplThread impl(task_runner_provider_); + return host_impl_->dropped_frame_counter()->GetAverageThroughput(); +} + void SingleThreadProxy::UpdateBrowserControlsState( BrowserControlsState constraints, BrowserControlsState current, @@ -889,7 +904,7 @@ void SingleThreadProxy::BeginMainFrame( return; } - DoPainting(); + DoPainting(begin_frame_args); } void SingleThreadProxy::DoBeginMainFrame( @@ -909,21 +924,33 @@ void SingleThreadProxy::DoBeginMainFrame( layer_tree_host_->WillBeginMainFrame(); layer_tree_host_->BeginMainFrame(begin_frame_args); layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); - layer_tree_host_->RequestMainFrameUpdate(false /* record_cc_metrics */); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + const bool record_metrics = + layer_tree_host_->GetSettings().is_layer_tree_for_ui; +#else + constexpr bool record_metrics = false; +#endif + layer_tree_host_->RequestMainFrameUpdate(record_metrics); + // Reset the flag for the next time around. It has been used for this frame. did_apply_compositor_deltas_ = false; } -void SingleThreadProxy::DoPainting() { +void SingleThreadProxy::DoPainting(const viz::BeginFrameArgs& commit_args) { layer_tree_host_->UpdateLayers(); update_layers_requested_ = false; + std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics = + layer_tree_host_->TakeBeginMainFrameMetrics(); + host_impl_->ReadyToCommit(commit_args, begin_main_frame_metrics.get()); + // TODO(enne): SingleThreadProxy does not support cancelling commits yet, // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside // thread_proxy.cc if (scheduler_on_impl_thread_) { scheduler_on_impl_thread_->NotifyReadyToCommit( - layer_tree_host_->begin_main_frame_metrics()); + std::move(begin_main_frame_metrics)); } } diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index a0e2b01fe56..445b3596dc4 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -11,6 +11,7 @@ #include "base/cancelable_callback.h" #include "base/containers/flat_set.h" +#include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "cc/scheduler/scheduler.h" #include "cc/trees/layer_tree_host_impl.h" @@ -54,7 +55,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void SetNeedsUpdateLayers() override; void SetNeedsCommit() override; void SetNeedsRedraw(const gfx::Rect& damage_rect) override; - void SetNextCommitWaitsForActivation() override; void SetTargetLocalSurfaceId( const viz::LocalSurfaceId& target_local_surface_id) override; bool RequestedAnimatePending() override; @@ -77,11 +77,11 @@ class CC_EXPORT SingleThreadProxy : public Proxy, } void SetUkmSmoothnessDestination( base::WritableSharedMemoryMapping ukm_smoothness_data) override {} - void ClearHistory() override; void SetRenderFrameObserver( std::unique_ptr<RenderFrameMetadataObserver> observer) override; void SetEnableFrameRateThrottling( bool enable_frame_rate_throttling) override {} + uint32_t GetAverageThroughput() const override; void UpdateBrowserControlsState(BrowserControlsState constraints, BrowserControlsState current, @@ -108,7 +108,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void ScheduledActionBeginMainFrameNotExpectedUntil( base::TimeTicks time) override; void FrameIntervalUpdated(base::TimeDelta interval) override; - bool HasCustomPropertyAnimations() const override; + bool HasInvalidationAnimation() const override; // LayerTreeHostImplClient implementation void DidLoseLayerTreeFrameSinkOnImplThread() override; @@ -149,6 +149,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, bool IsInSynchronousComposite() const override; void FrameSinksToThrottleUpdated( const base::flat_set<viz::FrameSinkId>& ids) override; + void ClearHistory() override; + size_t CommitDurationSampleCountForTesting() const override; void RequestNewLayerTreeFrameSink(); @@ -174,7 +176,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void BeginMainFrame(const viz::BeginFrameArgs& begin_frame_args); void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason); void DoBeginMainFrame(const viz::BeginFrameArgs& begin_frame_args); - void DoPainting(); + void DoPainting(const viz::BeginFrameArgs& commit_args); void DoCommit(const viz::BeginFrameArgs& commit_args); DrawResult DoComposite(LayerTreeHostImpl::FrameData* frame); void DoSwap(); @@ -188,10 +190,10 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void DidReceiveCompositorFrameAck(); // Accessed on main thread only. - LayerTreeHost* layer_tree_host_; - LayerTreeHostSingleThreadClient* single_thread_client_; + raw_ptr<LayerTreeHost> layer_tree_host_; + raw_ptr<LayerTreeHostSingleThreadClient> single_thread_client_; - TaskRunnerProvider* task_runner_provider_; + raw_ptr<TaskRunnerProvider> task_runner_provider_; // Used on the Thread, but checked on main thread during // initialization/shutdown. @@ -269,7 +271,7 @@ class DebugScopedSetImplThread { private: bool previous_value_; - TaskRunnerProvider* task_runner_provider_; + raw_ptr<TaskRunnerProvider> task_runner_provider_; #endif }; @@ -301,7 +303,7 @@ class DebugScopedSetMainThread { private: bool previous_value_; - TaskRunnerProvider* task_runner_provider_; + raw_ptr<TaskRunnerProvider> task_runner_provider_; #endif }; diff --git a/chromium/cc/trees/swap_promise.h b/chromium/cc/trees/swap_promise.h index b5638c9e391..2276ba30b01 100644 --- a/chromium/cc/trees/swap_promise.h +++ b/chromium/cc/trees/swap_promise.h @@ -63,16 +63,18 @@ class CC_EXPORT SwapPromise { virtual void DidActivate() = 0; virtual void WillSwap(viz::CompositorFrameMetadata* metadata) = 0; virtual void DidSwap() = 0; - // Return |KEEP_ACTIVE| if this promise should remain active (should not be - // broken by the owner). + + // Return `DidNotSwapAction::KEEP_ACTIVE` if this promise should remain active + // (should not be broken by the owner). virtual DidNotSwapAction DidNotSwap(DidNotSwapReason reason) = 0; + // This is called when the main thread starts a (blocking) commit virtual void OnCommit() {} // A non-zero trace id identifies a trace flow object that is embedded in the // swap promise. This can be used for registering additional flow steps to // visualize the object's path through the system. - virtual int64_t TraceId() const = 0; + virtual int64_t GetTraceId() const = 0; }; } // namespace cc diff --git a/chromium/cc/trees/swap_promise_manager.cc b/chromium/cc/trees/swap_promise_manager.cc index 76c2488d2e0..06889394335 100644 --- a/chromium/cc/trees/swap_promise_manager.cc +++ b/chromium/cc/trees/swap_promise_manager.cc @@ -4,15 +4,17 @@ #include "cc/trees/swap_promise_manager.h" +#include <utility> + +#include "cc/trees/latency_info_swap_promise_monitor.h" #include "cc/trees/swap_promise.h" -#include "cc/trees/swap_promise_monitor.h" namespace cc { SwapPromiseManager::SwapPromiseManager() = default; SwapPromiseManager::~SwapPromiseManager() { - DCHECK(swap_promise_monitors_.empty()); + DCHECK(latency_info_swap_promise_monitors_.empty()); BreakSwapPromises(SwapPromise::COMMIT_FAILS); } @@ -22,18 +24,19 @@ void SwapPromiseManager::QueueSwapPromise( swap_promise_list_.push_back(std::move(swap_promise)); } -void SwapPromiseManager::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) { - swap_promise_monitors_.insert(monitor); +void SwapPromiseManager::InsertLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor) { + latency_info_swap_promise_monitors_.insert(monitor); } -void SwapPromiseManager::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) { - swap_promise_monitors_.erase(monitor); +void SwapPromiseManager::RemoveLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor) { + latency_info_swap_promise_monitors_.erase(monitor); } -void SwapPromiseManager::NotifySwapPromiseMonitorsOfSetNeedsCommit() { - for (auto* swap_promise_monitor : swap_promise_monitors_) { - swap_promise_monitor->OnSetNeedsCommitOnMain(); - } +void SwapPromiseManager::NotifyLatencyInfoSwapPromiseMonitors() { + for (auto* monitor : latency_info_swap_promise_monitors_) + monitor->OnSetNeedsCommitOnMain(); } void SwapPromiseManager::WillCommit() { @@ -51,6 +54,7 @@ SwapPromiseManager::TakeSwapPromises() { void SwapPromiseManager::BreakSwapPromises( SwapPromise::DidNotSwapReason reason) { std::vector<std::unique_ptr<SwapPromise>> keep_active_swap_promises; + keep_active_swap_promises.reserve(swap_promise_list_.size()); for (auto& swap_promise : swap_promise_list_) { if (swap_promise->DidNotSwap(reason) == SwapPromise::DidNotSwapAction::KEEP_ACTIVE) { diff --git a/chromium/cc/trees/swap_promise_manager.h b/chromium/cc/trees/swap_promise_manager.h index f2dc6e4069c..abcb7c04099 100644 --- a/chromium/cc/trees/swap_promise_manager.h +++ b/chromium/cc/trees/swap_promise_manager.h @@ -5,6 +5,7 @@ #ifndef CC_TREES_SWAP_PROMISE_MANAGER_H_ #define CC_TREES_SWAP_PROMISE_MANAGER_H_ +#include <memory> #include <set> #include <vector> @@ -12,8 +13,8 @@ #include "cc/trees/swap_promise.h" namespace cc { +class LatencyInfoSwapPromiseMonitor; class SwapPromise; -class SwapPromiseMonitor; class CC_EXPORT SwapPromiseManager { public: @@ -27,15 +28,17 @@ class CC_EXPORT SwapPromiseManager { // See swap_promise.h for how to use SwapPromise. void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise); - // When a SwapPromiseMonitor is created on the main thread, it calls - // InsertSwapPromiseMonitor() to register itself with LayerTreeHost. - // When the monitor is destroyed, it calls RemoveSwapPromiseMonitor() - // to unregister itself. - void InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor); - void RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor); + // When a `LatencyInfoSwapPromiseMonitor` is created on the main thread, it + // calls `InsertLatencyInfoSwapPromiseMonitor()` to register itself with + // `LayerTreeHost`. When the monitor is destroyed, it calls + // `RemoveLatencyInfoSwapPromiseMonitor()` to unregister itself. + void InsertLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor); + void RemoveLatencyInfoSwapPromiseMonitor( + LatencyInfoSwapPromiseMonitor* monitor); // Called when a commit request is made on the LayerTreeHost. - void NotifySwapPromiseMonitorsOfSetNeedsCommit(); + void NotifyLatencyInfoSwapPromiseMonitors(); // Called before the commit of the main thread state will be started. void WillCommit(); @@ -50,7 +53,7 @@ class CC_EXPORT SwapPromiseManager { private: std::vector<std::unique_ptr<SwapPromise>> swap_promise_list_; - std::set<SwapPromiseMonitor*> swap_promise_monitors_; + std::set<LatencyInfoSwapPromiseMonitor*> latency_info_swap_promise_monitors_; }; } // namespace cc diff --git a/chromium/cc/trees/swap_promise_manager_unittest.cc b/chromium/cc/trees/swap_promise_manager_unittest.cc index b18c5a200b4..354e9d24855 100644 --- a/chromium/cc/trees/swap_promise_manager_unittest.cc +++ b/chromium/cc/trees/swap_promise_manager_unittest.cc @@ -7,7 +7,7 @@ #include <memory> #include <utility> -#include "cc/trees/swap_promise_monitor.h" +#include "cc/test/mock_latency_info_swap_promise_monitor.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,16 +16,6 @@ using ::testing::StrictMock; namespace cc { namespace { -class MockSwapPromiseMonitor : public SwapPromiseMonitor { - public: - explicit MockSwapPromiseMonitor(SwapPromiseManager* manager) - : SwapPromiseMonitor(manager) {} - ~MockSwapPromiseMonitor() override = default; - - MOCK_METHOD0(OnSetNeedsCommitOnMain, void()); - void OnSetNeedsRedrawOnImpl() override {} -}; - class MockSwapPromise : public SwapPromise { public: MockSwapPromise() = default; @@ -38,17 +28,17 @@ class MockSwapPromise : public SwapPromise { return DidNotSwapAction::BREAK_PROMISE; } MOCK_METHOD0(OnCommit, void()); - int64_t TraceId() const override { return 0; } + int64_t GetTraceId() const override { return 0; } }; TEST(SwapPromiseManagerTest, SwapPromiseMonitors) { SwapPromiseManager manager; - StrictMock<MockSwapPromiseMonitor> monitor(&manager); + StrictMock<MockLatencyInfoSwapPromiseMonitor> monitor(&manager); EXPECT_CALL(monitor, OnSetNeedsCommitOnMain()).Times(2); - manager.NotifySwapPromiseMonitorsOfSetNeedsCommit(); - manager.NotifySwapPromiseMonitorsOfSetNeedsCommit(); + manager.NotifyLatencyInfoSwapPromiseMonitors(); + manager.NotifyLatencyInfoSwapPromiseMonitors(); } TEST(SwapPromiseManagerTest, SwapPromises) { diff --git a/chromium/cc/trees/swap_promise_monitor.cc b/chromium/cc/trees/swap_promise_monitor.cc deleted file mode 100644 index b8fce20cdb5..00000000000 --- a/chromium/cc/trees/swap_promise_monitor.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/trees/swap_promise_monitor.h" -#include "base/check.h" -#include "cc/trees/layer_tree_host_impl.h" -#include "cc/trees/swap_promise_manager.h" - -namespace cc { - -SwapPromiseMonitor::SwapPromiseMonitor(SwapPromiseManager* swap_promise_manager) - : swap_promise_manager_(swap_promise_manager), host_impl_(nullptr) { - DCHECK(swap_promise_manager); - swap_promise_manager_->InsertSwapPromiseMonitor(this); -} - -SwapPromiseMonitor::SwapPromiseMonitor(LayerTreeHostImpl* host_impl) - : swap_promise_manager_(nullptr), host_impl_(host_impl) { - DCHECK(host_impl); - host_impl_->InsertSwapPromiseMonitor(this); -} - -SwapPromiseMonitor::~SwapPromiseMonitor() { - if (swap_promise_manager_) - swap_promise_manager_->RemoveSwapPromiseMonitor(this); - if (host_impl_) - host_impl_->RemoveSwapPromiseMonitor(this); -} - -} // namespace cc diff --git a/chromium/cc/trees/swap_promise_monitor.h b/chromium/cc/trees/swap_promise_monitor.h deleted file mode 100644 index 29a2bf85f63..00000000000 --- a/chromium/cc/trees/swap_promise_monitor.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_TREES_SWAP_PROMISE_MONITOR_H_ -#define CC_TREES_SWAP_PROMISE_MONITOR_H_ - -#include "cc/cc_export.h" - -namespace cc { - -class SwapPromiseManager; -class LayerTreeHostImpl; - -// A SwapPromiseMonitor is used to monitor compositor state change that should -// be associated with a SwapPromise, e.g. SetNeedsCommit() is called on main -// thread or SetNeedsRedraw() is called on impl thread. -// -// Creating a SwapPromiseMonitor will insert itself into a SwapPromiseManager -// or LayerTreeHostImpl. You must provide a pointer to the appropriate -// structure to the monitor (and only one of the two). -// -// Notification of compositor state change will be sent through -// OnSetNeedsCommitOnMain() or OnSetNeedsRedrawOnImpl(). Note that multiple -// notifications of the same type to the same monitor will only queue one -// SwapPromise. -// -// When SwapPromiseMonitor is destroyed, it will unregister itself from -// SwapPromiseManager or LayerTreeHostImpl. -class CC_EXPORT SwapPromiseMonitor { - public: - // If the monitor lives on the main thread, pass in |swap_promise_manager| - // tied to the LayerTreeHost. If the monitor lives on the impl thread, pass in - // |host_impl|. - explicit SwapPromiseMonitor(SwapPromiseManager* swap_promise_managaer); - explicit SwapPromiseMonitor(LayerTreeHostImpl* host_impl); - virtual ~SwapPromiseMonitor(); - - virtual void OnSetNeedsCommitOnMain() = 0; - virtual void OnSetNeedsRedrawOnImpl() = 0; - - protected: - SwapPromiseManager* swap_promise_manager_; - LayerTreeHostImpl* host_impl_; -}; - -} // namespace cc - -#endif // CC_TREES_SWAP_PROMISE_MONITOR_H_ diff --git a/chromium/cc/trees/task_runner_provider.cc b/chromium/cc/trees/task_runner_provider.cc index ebe7dd0c55f..8b88a246dce 100644 --- a/chromium/cc/trees/task_runner_provider.cc +++ b/chromium/cc/trees/task_runner_provider.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/single_thread_task_runner.h" #include "cc/trees/task_runner_provider.h" +#include "base/task/single_thread_task_runner.h" namespace cc { diff --git a/chromium/cc/trees/task_runner_provider.h b/chromium/cc/trees/task_runner_provider.h index f32995a2ad5..ec63350645f 100644 --- a/chromium/cc/trees/task_runner_provider.h +++ b/chromium/cc/trees/task_runner_provider.h @@ -10,8 +10,9 @@ #include "base/check.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/platform_thread.h" #include "cc/cc_export.h" @@ -92,7 +93,7 @@ class DebugScopedSetMainThreadBlocked { const DebugScopedSetMainThreadBlocked&) = delete; private: - TaskRunnerProvider* task_runner_provider_; + raw_ptr<TaskRunnerProvider> task_runner_provider_; }; #else class DebugScopedSetMainThreadBlocked { diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h index 319212acb2e..44a9c03e9be 100644 --- a/chromium/cc/trees/transform_node.h +++ b/chromium/cc/trees/transform_node.h @@ -116,7 +116,7 @@ struct CC_EXPORT TransformNode { // Set to true, if the node or it's parent |will_change_transform| is true. bool node_or_ancestors_will_change_transform : 1; - gfx::Vector2dF scroll_offset; + gfx::PointF scroll_offset; // This value stores the snapped amount whenever we snap. If the snap is due // to a scroll, we need it to calculate fixed-pos elements adjustment, even diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index 243bda83187..dac8c828004 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -6,7 +6,9 @@ #include <stddef.h> +#include <memory> #include <set> +#include <utility> #include "base/check_op.h" #include "base/containers/contains.h" @@ -24,8 +26,18 @@ namespace cc { namespace { #if DCHECK_IS_ON() -template <typename LayerType> -static void AssertValidPropertyTreeIndices(LayerType* layer) { +static void AssertValidPropertyTreeIndices( + const Layer* layer, + const PropertyTrees& property_trees) { + DCHECK(layer); + DCHECK(layer->transform_tree_index_is_valid(property_trees)); + DCHECK(layer->effect_tree_index_is_valid(property_trees)); + DCHECK(layer->clip_tree_index_is_valid(property_trees)); + DCHECK(layer->scroll_tree_index_is_valid(property_trees)); +} + +static void AssertValidPropertyTreeIndices(const LayerImpl* layer, + const PropertyTrees&) { DCHECK(layer); DCHECK_NE(layer->transform_tree_index(), TransformTree::kInvalidNodeId); DCHECK_NE(layer->effect_tree_index(), EffectTree::kInvalidNodeId); @@ -33,7 +45,7 @@ static void AssertValidPropertyTreeIndices(LayerType* layer) { DCHECK_NE(layer->scroll_tree_index(), ScrollTree::kInvalidNodeId); } -static bool LayerHasValidPropertyTreeIndices(LayerImpl* layer) { +static bool LayerHasValidPropertyTreeIndices(const LayerImpl* layer) { DCHECK(layer); return layer->transform_tree_index() != TransformTree::kInvalidNodeId && layer->effect_tree_index() != EffectTree::kInvalidNodeId && @@ -41,11 +53,13 @@ static bool LayerHasValidPropertyTreeIndices(LayerImpl* layer) { layer->scroll_tree_index() != ScrollTree::kInvalidNodeId; } -static bool LayerWillPushProperties(LayerTreeHost* host, Layer* layer) { - return base::Contains(host->LayersThatShouldPushProperties(), layer); +static bool LayerWillPushProperties(const ThreadUnsafeCommitState* unsafe_state, + const Layer* layer) { + return unsafe_state->layers_that_should_push_properties.contains(layer); } -static bool LayerWillPushProperties(LayerTreeImpl* tree, LayerImpl* layer) { +static bool LayerWillPushProperties(const LayerTreeImpl* tree, + const LayerImpl* layer) { return base::Contains(tree->LayersThatShouldPushProperties(), layer) || // TODO(crbug.com/303943): Stop always pushing PictureLayerImpl // properties. @@ -68,7 +82,8 @@ std::unique_ptr<LayerImpl> ReuseOrCreateLayerImpl(OwnedLayerImplMap* old_layers, template <typename LayerTreeType> void PushLayerList(OwnedLayerImplMap* old_layers, LayerTreeType* host, - LayerTreeImpl* tree_impl) { + LayerTreeImpl* tree_impl, + const PropertyTrees& property_trees) { DCHECK(tree_impl->LayerListIsEmpty()); for (auto* layer : *host) { std::unique_ptr<LayerImpl> layer_impl( @@ -76,7 +91,7 @@ void PushLayerList(OwnedLayerImplMap* old_layers, #if DCHECK_IS_ON() // Every layer should have valid property tree indices - AssertValidPropertyTreeIndices(layer); + AssertValidPropertyTreeIndices(layer, property_trees); // Every layer_impl should either have valid property tree indices already // or the corresponding layer should push them onto layer_impl. DCHECK(LayerHasValidPropertyTreeIndices(layer_impl.get()) || @@ -90,7 +105,8 @@ void PushLayerList(OwnedLayerImplMap* old_layers, template <typename LayerTreeType> void SynchronizeTreesInternal(LayerTreeType* source_tree, - LayerTreeImpl* tree_impl) { + LayerTreeImpl* tree_impl, + const PropertyTrees& property_trees) { DCHECK(tree_impl); TRACE_EVENT0("cc", "TreeSynchronizer::SynchronizeTrees"); @@ -102,17 +118,19 @@ void SynchronizeTreesInternal(LayerTreeType* source_tree, old_layer_map[it->id()] = std::move(it); } - PushLayerList(&old_layer_map, source_tree, tree_impl); + PushLayerList(&old_layer_map, source_tree, tree_impl, property_trees); } } // namespace -void TreeSynchronizer::SynchronizeTrees(Layer* layer_root, - LayerTreeImpl* tree_impl) { - if (!layer_root) { +void TreeSynchronizer::SynchronizeTrees( + const ThreadUnsafeCommitState& unsafe_state, + LayerTreeImpl* tree_impl) { + if (!unsafe_state.root_layer) { tree_impl->DetachLayers(); } else { - SynchronizeTreesInternal(layer_root->layer_tree_host(), tree_impl); + SynchronizeTreesInternal(&unsafe_state, tree_impl, + unsafe_state.property_trees); } } @@ -121,53 +139,8 @@ void TreeSynchronizer::SynchronizeTrees(LayerTreeImpl* pending_tree, if (pending_tree->LayerListIsEmpty()) { active_tree->DetachLayers(); } else { - SynchronizeTreesInternal(pending_tree, active_tree); - } -} - -template <typename Iterator> -static void PushLayerPropertiesInternal(Iterator source_layers_begin, - Iterator source_layers_end, - LayerTreeHost* host_tree, - LayerTreeImpl* target_impl_tree) { - for (Iterator it = source_layers_begin; it != source_layers_end; ++it) { - auto* source_layer = *it; - LayerImpl* target_layer = target_impl_tree->LayerById(source_layer->id()); - DCHECK(target_layer); - // TODO(enne): http://crbug.com/918126 debugging - CHECK(source_layer); - if (!target_layer) { - bool host_set_on_source = source_layer->layer_tree_host() == host_tree; - - bool source_found_by_iterator = false; - for (auto host_tree_it = host_tree->begin(); - host_tree_it != host_tree->end(); ++it) { - if (*host_tree_it == source_layer) { - source_found_by_iterator = true; - break; - } - } - - bool root_layer_valid = !!host_tree->root_layer(); - bool found_root = false; - Layer* layer = source_layer; - while (layer) { - if (layer == host_tree->root_layer()) { - found_root = true; - break; - } - layer = layer->parent(); - } - - auto str = base::StringPrintf( - "hs: %d, sf: %d, rlv: %d, fr: %d", host_set_on_source, - source_found_by_iterator, root_layer_valid, found_root); - static auto* crash_key = base::debug::AllocateCrashKeyString( - "cc_null_layer_sync", base::debug::CrashKeySize::Size32); - base::debug::SetCrashKeyString(crash_key, str); - base::debug::DumpWithoutCrashing(); - } - source_layer->PushPropertiesTo(target_layer); + SynchronizeTreesInternal(pending_tree, active_tree, + *pending_tree->property_trees()); } } @@ -196,14 +169,24 @@ void TreeSynchronizer::PushLayerProperties(LayerTreeImpl* pending_tree, pending_tree->ClearLayersThatShouldPushProperties(); } -void TreeSynchronizer::PushLayerProperties(LayerTreeHost* host_tree, - LayerTreeImpl* impl_tree) { - auto layers = host_tree->LayersThatShouldPushProperties(); +void TreeSynchronizer::PushLayerProperties( + const CommitState& commit_state, + ThreadUnsafeCommitState& unsafe_state, + LayerTreeImpl* impl_tree) { TRACE_EVENT1("cc", "TreeSynchronizer::PushLayerPropertiesTo.Main", - "layer_count", layers.size()); - PushLayerPropertiesInternal(layers.begin(), layers.end(), host_tree, - impl_tree); - host_tree->ClearLayersThatShouldPushProperties(); + "layer_count", + unsafe_state.layers_that_should_push_properties.size()); + auto source_layers_begin = + unsafe_state.layers_that_should_push_properties.begin(); + auto source_layers_end = + unsafe_state.layers_that_should_push_properties.end(); + for (auto it = source_layers_begin; it != source_layers_end; ++it) { + auto* source_layer = *it; + LayerImpl* target_layer = impl_tree->LayerById(source_layer->id()); + DCHECK(target_layer); + source_layer->PushPropertiesTo(target_layer, commit_state, unsafe_state); + } + unsafe_state.layers_that_should_push_properties.clear(); } } // namespace cc diff --git a/chromium/cc/trees/tree_synchronizer.h b/chromium/cc/trees/tree_synchronizer.h index 560e62bb7b4..27df11487d7 100644 --- a/chromium/cc/trees/tree_synchronizer.h +++ b/chromium/cc/trees/tree_synchronizer.h @@ -6,11 +6,11 @@ #define CC_TREES_TREE_SYNCHRONIZER_H_ #include "cc/cc_export.h" +#include "cc/trees/layer_tree_host.h" namespace cc { class LayerImpl; -class LayerTreeHost; class LayerTreeImpl; class Layer; @@ -22,14 +22,18 @@ class CC_EXPORT TreeSynchronizer { // Accepts a Layer tree and returns a reference to a LayerImpl tree that // duplicates the structure of the Layer tree, reusing the LayerImpls in the // tree provided by old_layer_impl_root if possible. - static void SynchronizeTrees(Layer* layer_root, LayerTreeImpl* tree_impl); + static void SynchronizeTrees(const ThreadUnsafeCommitState& unsafe_state, + LayerTreeImpl* tree_impl); + static void SynchronizeTrees(LayerTreeImpl* pending_tree, LayerTreeImpl* active_tree); + static void PushLayerProperties(const CommitState& commit_state, + ThreadUnsafeCommitState& unsafe_state, + LayerTreeImpl* impl_tree); + static void PushLayerProperties(LayerTreeImpl* pending_tree, LayerTreeImpl* active_tree); - static void PushLayerProperties(LayerTreeHost* host_tree, - LayerTreeImpl* impl_tree); }; } // namespace cc diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc index f556fd1a8bb..922faec11bf 100644 --- a/chromium/cc/trees/tree_synchronizer_unittest.cc +++ b/chromium/cc/trees/tree_synchronizer_unittest.cc @@ -15,6 +15,7 @@ #include "base/containers/contains.h" #include "base/format_macros.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" #include "cc/layers/layer.h" @@ -41,7 +42,7 @@ bool AreScrollOffsetsEqual(const SyncedScrollOffset* a, const SyncedScrollOffset* b) { return a->ActiveBase() == b->ActiveBase() && a->PendingBase() == b->PendingBase() && a->Delta() == b->Delta() && - a->PendingDelta().get() == b->PendingDelta().get(); + a->PendingDelta() == b->PendingDelta(); } class MockLayerImpl : public LayerImpl { @@ -63,7 +64,7 @@ class MockLayerImpl : public LayerImpl { MockLayerImpl(LayerTreeImpl* tree_impl, int layer_id) : LayerImpl(tree_impl, layer_id), layer_impl_destruction_list_(nullptr) {} - std::vector<int>* layer_impl_destruction_list_; + raw_ptr<std::vector<int>> layer_impl_destruction_list_; }; class MockLayer : public Layer { @@ -78,8 +79,10 @@ class MockLayer : public Layer { return MockLayerImpl::Create(tree_impl, id()); } - void PushPropertiesTo(LayerImpl* layer_impl) override { - Layer::PushPropertiesTo(layer_impl); + void PushPropertiesTo(LayerImpl* layer_impl, + const CommitState& commit_state, + const ThreadUnsafeCommitState& unsafe_state) override { + Layer::PushPropertiesTo(layer_impl, commit_state, unsafe_state); MockLayerImpl* mock_layer_impl = static_cast<MockLayerImpl*>(layer_impl); mock_layer_impl->SetLayerImplDestructionList(layer_impl_destruction_list_); @@ -90,7 +93,7 @@ class MockLayer : public Layer { : layer_impl_destruction_list_(layer_impl_destruction_list) {} ~MockLayer() override = default; - std::vector<int>* layer_impl_destruction_list_; + raw_ptr<std::vector<int>> layer_impl_destruction_list_; }; void ExpectTreesAreIdentical(Layer* root_layer, @@ -166,7 +169,7 @@ class TreeSynchronizerTest : public testing::Test { // Attempts to synchronizes a null tree. This should not crash, and should // return a null tree. TEST_F(TreeSynchronizerTest, SyncNullTree) { - TreeSynchronizer::SynchronizeTrees(static_cast<Layer*>(nullptr), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->pending_tree()); EXPECT_TRUE(!host_->pending_tree()->root_layer()); } @@ -181,7 +184,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeFromEmpty) { host_->SetRootLayer(layer_tree_root); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->pending_tree()); LayerImpl* root = host_->pending_tree()->root_layer(); @@ -204,7 +207,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndPushPropertiesFromEmpty) { host_->SetRootLayer(layer_tree_root); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->pending_tree()); // First time the main thread layers are synced to pending tree, and all the @@ -219,7 +222,9 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndPushPropertiesFromEmpty) { host_->pending_tree()); // Push properties to make pending tree have valid property tree index. - TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree()); + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), + host_->pending_tree()); // Now sync from pending tree to active tree. This would clear the map of // layers that need push properties. @@ -232,14 +237,17 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndPushPropertiesFromEmpty) { // Set the main thread root layer needs push properties. layer_tree_root->SetNeedsPushProperties(); - EXPECT_TRUE(base::Contains(host_->LayersThatShouldPushProperties(), - layer_tree_root.get())); + EXPECT_TRUE(base::Contains( + host_->GetThreadUnsafeCommitState().layers_that_should_push_properties, + layer_tree_root.get())); // When sync from main thread, the needs push properties status is carried // over to pending tree. - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->pending_tree()); - TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree()); + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), + host_->pending_tree()); EXPECT_TRUE(base::Contains( host_->pending_tree()->LayersThatShouldPushProperties(), root)); } @@ -258,7 +266,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { host_->SetRootLayer(layer_tree_root); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->pending_tree()); LayerImpl* layer_impl_tree_root = host_->pending_tree()->root_layer(); EXPECT_TRUE( @@ -269,7 +277,9 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { host_->pending_tree()); // We have to push properties to pick up the destruction list pointer. - TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree()); + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), + host_->pending_tree()); // Add a new layer to the Layer side layer_tree_root->children()[0]->AddChild( @@ -280,7 +290,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { // Synchronize again. After the sync the trees should be equivalent and we // should have created and destroyed one LayerImpl. host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->pending_tree()); layer_impl_tree_root = host_->pending_tree()->root_layer(); @@ -311,31 +321,32 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndTrackStackingOrderChange) { host_->SetRootLayer(layer_tree_root); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root, host_->active_tree()); // We have to push properties to pick up the destruction list pointer. - TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(), + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), host_->active_tree()); - host_->active_tree()->ResetAllChangeTracking(); // re-insert the layer and sync again. child2->RemoveFromParent(); layer_tree_root->AddChild(child2); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root, host_->active_tree()); host_->active_tree()->SetPropertyTrees( - layer_tree_root->layer_tree_host()->property_trees()); - TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(), + *layer_tree_root->layer_tree_host()->property_trees()); + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), host_->active_tree()); // Check that the impl thread properly tracked the change. @@ -370,13 +381,14 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndProperties) { int second_child_id = layer_tree_root->children()[1]->id(); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root, host_->active_tree()); - TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(), + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), host_->active_tree()); // Check that the property values we set on the Layer tree are reflected in @@ -417,14 +429,15 @@ TEST_F(TreeSynchronizerTest, ReuseLayerImplsAfterStructuralChange) { host_->SetRootLayer(layer_tree_root); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root, host_->active_tree()); // We have to push properties to pick up the destruction list pointer. - TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(), + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), host_->active_tree()); // Now restructure the tree to look like this: @@ -444,7 +457,7 @@ TEST_F(TreeSynchronizerTest, ReuseLayerImplsAfterStructuralChange) { // After another synchronize our trees should match and we should not have // destroyed any LayerImpls host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root, @@ -474,14 +487,15 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { int old_tree_second_child_layer_id = old_layer_tree_root->children()[1]->id(); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(old_layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(old_layer_tree_root.get(), layer_impl_tree_root, host_->active_tree()); // We have to push properties to pick up the destruction list pointer. - TreeSynchronizer::PushLayerProperties(old_layer_tree_root->layer_tree_host(), + TreeSynchronizer::PushLayerProperties(*host_->GetPendingCommitState(), + host_->GetThreadUnsafeCommitState(), host_->active_tree()); // Remove all children on the Layer side. @@ -493,7 +507,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { host_->SetRootLayer(new_layer_tree_root); host_->BuildPropertyTreesForTesting(); - TreeSynchronizer::SynchronizeTrees(new_layer_tree_root.get(), + TreeSynchronizer::SynchronizeTrees(host_->GetThreadUnsafeCommitState(), host_->active_tree()); layer_impl_tree_root = host_->active_tree()->root_layer(); ExpectTreesAreIdentical(new_layer_tree_root.get(), layer_impl_tree_root, @@ -616,8 +630,8 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) { transient_scroll_layer->SetScrollable(gfx::Size(1, 1)); scroll_layer->SetScrollable(gfx::Size(1, 1)); - transient_scroll_layer->SetScrollOffset(gfx::Vector2dF(1, 2)); - scroll_layer->SetScrollOffset(gfx::Vector2dF(10, 20)); + transient_scroll_layer->SetScrollOffset(gfx::PointF(1, 2)); + scroll_layer->SetScrollOffset(gfx::PointF(10, 20)); host_->SetRootLayer(layer_tree_root); host_->BuildPropertyTreesForTesting(); @@ -653,13 +667,13 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) { ->scroll_tree.GetSyncedScrollOffset( transient_scroll_layer->element_id()))); - // Set ScrollOffset active delta: gfx::Vector2dF(10, 10) + // Set ScrollOffset active delta: gfx::PointF(10, 10) LayerImpl* scroll_layer_impl = host_impl->active_tree()->LayerById(scroll_layer->id()); ScrollTree& scroll_tree = host_impl->active_tree()->property_trees()->scroll_tree; scroll_tree.SetScrollOffset(scroll_layer_impl->element_id(), - gfx::Vector2dF(20, 30)); + gfx::PointF(20, 30)); // Pull ScrollOffset delta for main thread, and change offset on main thread std::unique_ptr<CompositorCommitData> commit_data(new CompositorCommitData()); @@ -668,12 +682,12 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) { base::flat_map<ElementId, TargetSnapAreaElementIds>()); host_->proxy()->SetNeedsCommit(); host_->ApplyCompositorChanges(commit_data.get()); - EXPECT_EQ(gfx::Vector2dF(20, 30), scroll_layer->scroll_offset()); - scroll_layer->SetScrollOffset(gfx::Vector2dF(100, 100)); + EXPECT_EQ(gfx::PointF(20, 30), scroll_layer->scroll_offset()); + scroll_layer->SetScrollOffset(gfx::PointF(100, 100)); // More update to ScrollOffset active delta: gfx::Vector2dF(20, 20) scroll_tree.SetScrollOffset(scroll_layer_impl->element_id(), - gfx::Vector2dF(40, 50)); + gfx::PointF(40, 50)); host_impl->active_tree()->SetCurrentlyScrollingNode( scroll_tree.Node(scroll_layer_impl->scroll_tree_index())); @@ -688,10 +702,10 @@ TEST_F(TreeSynchronizerTest, SynchronizeScrollTreeScrollOffsetMap) { EXPECT_EQ(scroll_layer->scroll_tree_index(), host_impl->active_tree()->CurrentlyScrollingNode()->id); - scroll_layer_offset->SetCurrent(gfx::Vector2dF(20, 30)); + scroll_layer_offset->SetCurrent(gfx::PointF(20, 30)); scroll_layer_offset->PullDeltaForMainThread(); - scroll_layer_offset->SetCurrent(gfx::Vector2dF(40, 50)); - scroll_layer_offset->PushMainToPending(gfx::Vector2dF(100, 100)); + scroll_layer_offset->SetCurrent(gfx::PointF(40, 50)); + scroll_layer_offset->PushMainToPending(gfx::PointF(100, 100)); scroll_layer_offset->PushPendingToActive(); EXPECT_TRUE(AreScrollOffsetsEqual( scroll_layer_offset.get(), diff --git a/chromium/cc/trees/ukm_manager.cc b/chromium/cc/trees/ukm_manager.cc index ffe21a315fe..eb814d7cbaa 100644 --- a/chromium/cc/trees/ukm_manager.cc +++ b/chromium/cc/trees/ukm_manager.cc @@ -98,11 +98,11 @@ void UkmManager::RecordRenderingUkm() { void UkmManager::RecordThroughputUKM( FrameSequenceTrackerType tracker_type, - FrameSequenceMetrics::ThreadType thread_type, + FrameInfo::SmoothEffectDrivingThread thread_type, int64_t throughput) const { ukm::builders::Graphics_Smoothness_PercentDroppedFrames builder(source_id_); switch (thread_type) { - case FrameSequenceMetrics::ThreadType::kMain: { + case FrameInfo::SmoothEffectDrivingThread::kMain: { switch (tracker_type) { #define CASE_FOR_MAIN_THREAD_TRACKER(name) \ case FrameSequenceTrackerType::k##name: \ @@ -127,7 +127,7 @@ void UkmManager::RecordThroughputUKM( break; } - case FrameSequenceMetrics::ThreadType::kCompositor: { + case FrameInfo::SmoothEffectDrivingThread::kCompositor: { switch (tracker_type) { #define CASE_FOR_COMPOSITOR_THREAD_TRACKER(name) \ case FrameSequenceTrackerType::k##name: \ @@ -149,7 +149,7 @@ void UkmManager::RecordThroughputUKM( break; } - case FrameSequenceMetrics::ThreadType::kUnknown: + case FrameInfo::SmoothEffectDrivingThread::kUnknown: NOTREACHED(); break; } @@ -174,7 +174,7 @@ void UkmManager::RecordAggregateThroughput(AggregationType aggregation_type, } void UkmManager::RecordCompositorLatencyUKM( - CompositorFrameReporter::FrameReportType report_type, + const CompositorFrameReporter::FrameReportTypes& report_types, const std::vector<CompositorFrameReporter::StageData>& stage_history, const ActiveTrackers& active_trackers, const CompositorFrameReporter::ProcessedBlinkBreakdown& @@ -185,7 +185,8 @@ void UkmManager::RecordCompositorLatencyUKM( ukm::builders::Graphics_Smoothness_Latency builder(source_id_); - if (report_type == CompositorFrameReporter::FrameReportType::kDroppedFrame) { + if (report_types.test(static_cast<size_t>( + CompositorFrameReporter::FrameReportType::kDroppedFrame))) { builder.SetMissedFrame(true); } diff --git a/chromium/cc/trees/ukm_manager.h b/chromium/cc/trees/ukm_manager.h index 0f9a4b28378..1345e2482f1 100644 --- a/chromium/cc/trees/ukm_manager.h +++ b/chromium/cc/trees/ukm_manager.h @@ -48,12 +48,12 @@ class CC_EXPORT UkmManager { void AddCheckerboardedImages(int num_of_checkerboarded_images); void RecordThroughputUKM(FrameSequenceTrackerType tracker_type, - FrameSequenceMetrics::ThreadType thread_type, + FrameInfo::SmoothEffectDrivingThread thread_type, int64_t throughput) const; void RecordAggregateThroughput(AggregationType aggregation_type, int64_t throughput_percent) const; void RecordCompositorLatencyUKM( - CompositorFrameReporter::FrameReportType report_type, + const CompositorFrameReporter::FrameReportTypes& report_types, const std::vector<CompositorFrameReporter::StageData>& stage_history, const ActiveTrackers& active_trackers, const CompositorFrameReporter::ProcessedBlinkBreakdown& diff --git a/chromium/cc/trees/ukm_manager_unittest.cc b/chromium/cc/trees/ukm_manager_unittest.cc index 78afffacc23..4f658e680d7 100644 --- a/chromium/cc/trees/ukm_manager_unittest.cc +++ b/chromium/cc/trees/ukm_manager_unittest.cc @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" #include "cc/metrics/begin_main_frame_metrics.h" @@ -229,7 +230,7 @@ class UkmManagerTest : public testing::Test { return breakdown; } - ukm::TestUkmRecorder* test_ukm_recorder_; + raw_ptr<ukm::TestUkmRecorder> test_ukm_recorder_; std::unique_ptr<UkmManager> manager_; base::SimpleTestTickClock test_tick_clock_; }; @@ -297,16 +298,26 @@ class UkmManagerCompositorLatencyTest public testing::WithParamInterface< CompositorFrameReporter::FrameReportType> { public: - UkmManagerCompositorLatencyTest() : report_type_(GetParam()) {} + UkmManagerCompositorLatencyTest() { + report_types_.set(static_cast<size_t>(GetParam())); + } ~UkmManagerCompositorLatencyTest() override = default; protected: CompositorFrameReporter::FrameReportType report_type() const { - return report_type_; + for (size_t type = 0; type < report_types_.size(); ++type) { + if (!report_types_.test(type)) + continue; + return static_cast<CompositorFrameReporter::FrameReportType>(type); + } + return CompositorFrameReporter::FrameReportType::kNonDroppedFrame; + } + const CompositorFrameReporter::FrameReportTypes& report_types() const { + return report_types_; } private: - CompositorFrameReporter::FrameReportType report_type_; + CompositorFrameReporter::FrameReportTypes report_types_; }; INSTANTIATE_TEST_SUITE_P( @@ -392,7 +403,7 @@ TEST_P(UkmManagerCompositorLatencyTest, CompositorLatency) { CompositorFrameReporter::ProcessedVizBreakdown processed_viz_breakdown( submit_time, viz_breakdown); manager_->RecordCompositorLatencyUKM( - report_type(), stage_history, active_trackers, processed_blink_breakdown, + report_types(), stage_history, active_trackers, processed_blink_breakdown, processed_viz_breakdown); const auto& entries = diff --git a/chromium/cc/trees/viewport_property_ids.h b/chromium/cc/trees/viewport_property_ids.h new file mode 100644 index 00000000000..51f9866d1ca --- /dev/null +++ b/chromium/cc/trees/viewport_property_ids.h @@ -0,0 +1,24 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TREES_VIEWPORT_PROPERTY_IDS_H_ +#define CC_TREES_VIEWPORT_PROPERTY_IDS_H_ + +#include "cc/paint/element_id.h" +#include "cc/trees/property_tree.h" + +namespace cc { + +struct ViewportPropertyIds { + int overscroll_elasticity_transform = TransformTree::kInvalidNodeId; + ElementId overscroll_elasticity_effect; + int page_scale_transform = TransformTree::kInvalidNodeId; + int inner_scroll = ScrollTree::kInvalidNodeId; + int outer_clip = ClipTree::kInvalidNodeId; + int outer_scroll = ScrollTree::kInvalidNodeId; +}; + +} // namespace cc + +#endif // CC_TREES_VIEWPORT_PROPERTY_IDS_H_ |