diff options
Diffstat (limited to 'chromium/cc')
282 files changed, 6088 insertions, 2582 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn index eae26dc29ab..0878b2fdfea 100644 --- a/chromium/cc/BUILD.gn +++ b/chromium/cc/BUILD.gn @@ -49,6 +49,8 @@ cc_component("cc") { "input/scroll_state_data.h", "input/scrollbar_animation_controller.cc", "input/scrollbar_animation_controller.h", + "input/scrollbar_controller.cc", + "input/scrollbar_controller.h", "input/single_scrollbar_animation_controller_thinning.cc", "input/single_scrollbar_animation_controller_thinning.h", "input/snap_fling_controller.cc", @@ -200,6 +202,10 @@ cc_component("cc") { "scheduler/begin_frame_tracker.cc", "scheduler/begin_frame_tracker.h", "scheduler/commit_earlyout_reason.h", + "scheduler/compositor_frame_reporter.cc", + "scheduler/compositor_frame_reporter.h", + "scheduler/compositor_frame_reporting_controller.cc", + "scheduler/compositor_frame_reporting_controller.h", "scheduler/compositor_timing_history.cc", "scheduler/compositor_timing_history.h", "scheduler/draw_result.h", @@ -388,6 +394,8 @@ cc_test_static_library("test_support") { "test/animation_test_common.h", "test/animation_timelines_test_common.cc", "test/animation_timelines_test_common.h", + "test/fake_compositor_frame_reporting_controller.cc", + "test/fake_compositor_frame_reporting_controller.h", "test/fake_content_layer_client.cc", "test/fake_content_layer_client.h", "test/fake_impl_task_runner_provider.h", @@ -642,6 +650,7 @@ cc_test("cc_unittests") { "raster/synchronous_task_graph_runner_unittest.cc", "raster/task_graph_work_queue_unittest.cc", "resources/resource_pool_unittest.cc", + "scheduler/compositor_frame_reporting_controller_unittest.cc", "scheduler/compositor_timing_history_unittest.cc", "scheduler/scheduler_state_machine_unittest.cc", "scheduler/scheduler_unittest.cc", diff --git a/chromium/cc/PRESUBMIT.py b/chromium/cc/PRESUBMIT.py index 89f5675b100..0b6761a28f8 100644 --- a/chromium/cc/PRESUBMIT.py +++ b/chromium/cc/PRESUBMIT.py @@ -275,6 +275,27 @@ def CheckForUseOfWrongClock(input_api, else: return [] +def CheckForDisallowMacros(input_api, output_api, white_list=CC_SOURCE_FILES, black_list=None): + black_list = tuple(black_list or input_api.DEFAULT_BLACK_LIST) + source_file_filter = lambda x: input_api.FilterSourceFile(x, white_list, black_list) + + 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) @@ -286,4 +307,5 @@ 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/README.md b/chromium/cc/animation/README.md index 9ff425457ce..07ed15c9a8b 100644 --- a/chromium/cc/animation/README.md +++ b/chromium/cc/animation/README.md @@ -172,8 +172,12 @@ the animating element into a layer. The Blink document describes how composited animations are created in blink. Once a compositor animation is created it is pushed through the commit cycle. +![new animation] + The lifetime of a newly started cc::Animation is roughly the following: +1. An update to style or a new animation triggers a new [BeginMainFrame][] via + [ScheduleVisualUpdate][]. 1. [blink::DocumentAnimations::UpdateAnimations][] calls [blink::Animation::PreCommit][] on each pending blink::Animation constructing the corresponding cc::Animation via [blink::Animation::CreateCompositorAnimation][] (attaching @@ -213,6 +217,9 @@ The lifetime of a newly started cc::Animation is roughly the following: 1. Subsequent animation ticks will now update the property nodes on the active tree. +[new animation]: images/new-animation.png +[BeginMainFrame]: https://cs.chromium.org/chromium/src/cc/trees/proxy_main.cc?type=cs&q=file:proxy_main%5C.cc+RequestMainFrameUpdate +[ScheduleVisualUpdate]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/frame/local_frame.cc?type=cs&q=file:local_frame%5C.cc+ScheduleVisualUpdate [blink::DocumentAnimations::UpdateAnimations]: https://cs.chromium.org/search?q=function:blink::DocumentAnimations::UpdateAnimations+GetPendingAnimations [blink::Animation::PreCommit]: https://cs.chromium.org/search?q=function:blink::PendingAnimations::Update+%5C-%5C>PreCommit%5C(&g=0&l=57 [blink::Animation::CreateCompositorAnimation]: https://cs.chromium.org/search?q=function:blink::Animation::CreateCompositorAnimation+%5E%5B+%5D*AttachCompositorTimeline diff --git a/chromium/cc/animation/animation.h b/chromium/cc/animation/animation.h index a4033d412e6..feb33026e2a 100644 --- a/chromium/cc/animation/animation.h +++ b/chromium/cc/animation/animation.h @@ -8,7 +8,6 @@ #include <vector> #include <memory> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation_curve.h" @@ -43,6 +42,9 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { static scoped_refptr<Animation> Create(int id); virtual scoped_refptr<Animation> CreateImplInstance() const; + Animation(const Animation&) = delete; + Animation& operator=(const Animation&) = delete; + int id() const { return id_; } typedef size_t KeyframeEffectId; ElementId element_id_of_keyframe_effect( @@ -168,8 +170,6 @@ class CC_ANIMATION_EXPORT Animation : public base::RefCounted<Animation> { KeyframeEffects keyframe_effects_; int ticking_keyframe_effects_count; - - DISALLOW_COPY_AND_ASSIGN(Animation); }; } // namespace cc diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc index 96010f94cf8..8be2eef3d07 100644 --- a/chromium/cc/animation/animation_host.cc +++ b/chromium/cc/animation/animation_host.cc @@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/trace_event/trace_event.h" @@ -130,6 +129,11 @@ void AnimationHost::RemoveAnimationTimeline( SetNeedsPushProperties(); } +void AnimationHost::InitClientAnimationState() { + for (auto map_entry : element_to_animations_map_) + map_entry.second->InitClientAnimationState(); +} + void AnimationHost::RegisterElement(ElementId element_id, ElementListType list_type) { scoped_refptr<ElementAnimations> element_animations = @@ -330,8 +334,8 @@ void AnimationHost::TickMutator(base::TimeTicks monotonic_time, weak_factory_.GetWeakPtr(), tree_type); MutateQueuingStrategy queuing_strategy = - is_active_tree ? MutateQueuingStrategy::kDrop - : MutateQueuingStrategy::kQueueAndReplace; + is_active_tree ? MutateQueuingStrategy::kQueueAndReplaceNormalPriority + : MutateQueuingStrategy::kQueueHighPriority; if (mutator_->Mutate(std::move(state), queuing_strategy, std::move(on_done))) { mutator_host_client_->NotifyAnimationWorkletStateChange( @@ -409,8 +413,8 @@ void AnimationHost::TickScrollAnimations(base::TimeTicks monotonic_time, TickMutator(monotonic_time, scroll_tree, true /* is_active_tree */); } -void AnimationHost::TickWorkletAnimations(base::TimeTicks monotonic_time) { - TickAnimationsIf(ticking_animations_, monotonic_time, +void AnimationHost::TickWorkletAnimations() { + TickAnimationsIf(ticking_animations_, base::TimeTicks(), [](const Animation& animation) { return animation.IsWorkletAnimation(); }); @@ -591,24 +595,18 @@ bool AnimationHost::AnimationsPreserveAxisAlignment( : true; } -bool AnimationHost::MaximumTargetScale(ElementId element_id, - ElementListType list_type, - float* max_scale) const { - *max_scale = 0.f; +float AnimationHost::MaximumTargetScale(ElementId element_id, + ElementListType list_type) const { auto element_animations = GetElementAnimationsForElementId(element_id); - return element_animations - ? element_animations->MaximumTargetScale(list_type, max_scale) - : true; + return element_animations ? element_animations->MaximumTargetScale(list_type) + : kNotScaled; } -bool AnimationHost::AnimationStartScale(ElementId element_id, - ElementListType list_type, - float* start_scale) const { - *start_scale = 0.f; +float AnimationHost::AnimationStartScale(ElementId element_id, + ElementListType list_type) const { auto element_animations = GetElementAnimationsForElementId(element_id); - return element_animations - ? element_animations->AnimationStartScale(list_type, start_scale) - : true; + return element_animations ? element_animations->AnimationStartScale(list_type) + : kNotScaled; } bool AnimationHost::IsElementAnimating(ElementId element_id) const { @@ -658,6 +656,11 @@ void AnimationHost::ScrollAnimationAbort() { false /* needs_completion */); } +bool AnimationHost::IsImplOnlyScrollAnimating() const { + DCHECK(scroll_offset_animations_impl_); + return scroll_offset_animations_impl_->IsAnimating(); +} + void AnimationHost::AddToTicking(scoped_refptr<Animation> animation) { DCHECK(!base::ContainsValue(ticking_animations_, animation)); ticking_animations_.push_back(animation); diff --git a/chromium/cc/animation/animation_host.h b/chromium/cc/animation/animation_host.h index 70a33e858bc..b5bff9ac843 100644 --- a/chromium/cc/animation/animation_host.h +++ b/chromium/cc/animation/animation_host.h @@ -9,7 +9,6 @@ #include <unordered_map> #include <vector> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" @@ -56,8 +55,12 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, static std::unique_ptr<AnimationHost> CreateMainInstance(); static std::unique_ptr<AnimationHost> CreateForTesting( ThreadInstance thread_instance); + + AnimationHost(const AnimationHost&) = delete; ~AnimationHost() override; + AnimationHost& operator=(const AnimationHost&) = delete; + void AddAnimationTimeline(scoped_refptr<AnimationTimeline> timeline); void RemoveAnimationTimeline(scoped_refptr<AnimationTimeline> timeline); AnimationTimeline* GetTimelineById(int timeline_id) const; @@ -87,6 +90,8 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, bool supports_impl_scrolling) const override; void ClearMutators() override; + void InitClientAnimationState() override; + void RegisterElement(ElementId element_id, ElementListType list_type) override; void UnregisterElement(ElementId element_id, @@ -108,7 +113,7 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, bool is_active_tree) override; void TickScrollAnimations(base::TimeTicks monotonic_time, const ScrollTree& scroll_tree) override; - void TickWorkletAnimations(base::TimeTicks monotonic_time) override; + void TickWorkletAnimations() override; bool UpdateAnimationState(bool start_ready_animations, MutatorEvents* events) override; void PromoteScrollTimelinesPendingToActive() override; @@ -143,12 +148,10 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, ElementListType list_type) const override; bool AnimationsPreserveAxisAlignment(ElementId element_id) const override; - bool MaximumTargetScale(ElementId element_id, - ElementListType list_type, - float* max_scale) const override; - bool AnimationStartScale(ElementId element_id, - ElementListType list_type, - float* start_scale) const override; + float MaximumTargetScale(ElementId element_id, + ElementListType list_type) const override; + float AnimationStartScale(ElementId element_id, + ElementListType list_type) const override; bool IsElementAnimating(ElementId element_id) const override; bool HasTickingKeyframeModelForTesting(ElementId element_id) const override; @@ -168,6 +171,8 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, void ScrollAnimationAbort() override; + bool IsImplOnlyScrollAnimating() const override; + // This should only be called from the main thread. ScrollOffsetAnimations& scroll_offset_animations() const; @@ -224,6 +229,10 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, MutatorHostClient* mutator_host_client_; + // Exactly one of scroll_offset_animations_ and scroll_offset_animations_impl_ + // will be non-null for a given AnimationHost instance (the former if + // thread_instance_ == ThreadInstance::MAIN, the latter if thread_instance_ == + // ThreadInstance::IMPL). std::unique_ptr<ScrollOffsetAnimations> scroll_offset_animations_; std::unique_ptr<ScrollOffsetAnimationsImpl> scroll_offset_animations_impl_; @@ -239,8 +248,6 @@ class CC_ANIMATION_EXPORT AnimationHost : public MutatorHost, bool next_frame_has_pending_raf_ = false; base::WeakPtrFactory<AnimationHost> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(AnimationHost); }; } // namespace cc diff --git a/chromium/cc/animation/animation_host_unittest.cc b/chromium/cc/animation/animation_host_unittest.cc index adf646e3217..f2f4bd650ed 100644 --- a/chromium/cc/animation/animation_host_unittest.cc +++ b/chromium/cc/animation/animation_host_unittest.cc @@ -182,7 +182,7 @@ TEST_F(AnimationHostTest, FastLayerTreeMutatorUpdateTakesEffectInSameFrame) { // Emulate behavior in PrepareToDraw. Animation worklet updates are best // effort, and the animation tick is deferred until draw to allow time for the // updates to arrive. - host_impl_->TickWorkletAnimations(base::TimeTicks()); + host_impl_->TickWorkletAnimations(); TestLayer* layer = client_.FindTestLayer(element_id_, ElementListType::ACTIVE); diff --git a/chromium/cc/animation/animation_id_provider.h b/chromium/cc/animation/animation_id_provider.h index 62823bee502..cb7a84b29dc 100644 --- a/chromium/cc/animation/animation_id_provider.h +++ b/chromium/cc/animation/animation_id_provider.h @@ -5,21 +5,19 @@ #ifndef CC_ANIMATION_ANIMATION_ID_PROVIDER_H_ #define CC_ANIMATION_ANIMATION_ID_PROVIDER_H_ -#include "base/macros.h" #include "cc/animation/animation_export.h" namespace cc { class CC_ANIMATION_EXPORT AnimationIdProvider { public: + AnimationIdProvider() = delete; + // These functions each return monotonically increasing values. static int NextKeyframeModelId(); static int NextGroupId(); static int NextTimelineId(); static int NextAnimationId(); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(AnimationIdProvider); }; } // namespace cc diff --git a/chromium/cc/animation/animation_timeline.h b/chromium/cc/animation/animation_timeline.h index 8b36e621873..aebbef7e0fb 100644 --- a/chromium/cc/animation/animation_timeline.h +++ b/chromium/cc/animation/animation_timeline.h @@ -8,7 +8,6 @@ #include <memory> #include <unordered_map> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/animation/animation_export.h" @@ -27,6 +26,9 @@ class CC_ANIMATION_EXPORT AnimationTimeline static scoped_refptr<AnimationTimeline> Create(int id); scoped_refptr<AnimationTimeline> CreateImplInstance() const; + AnimationTimeline(const AnimationTimeline&) = delete; + AnimationTimeline& operator=(const AnimationTimeline&) = delete; + int id() const { return id_; } // Parent AnimationHost. @@ -73,8 +75,6 @@ class CC_ANIMATION_EXPORT AnimationTimeline // Impl-only AnimationTimeline has no main thread instance and lives on // it's own. bool is_impl_only_; - - DISALLOW_COPY_AND_ASSIGN(AnimationTimeline); }; } // namespace cc diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc index 7162033a337..797464ee5e8 100644 --- a/chromium/cc/animation/element_animations.cc +++ b/chromium/cc/animation/element_animations.cc @@ -8,7 +8,6 @@ #include <algorithm> -#include "base/macros.h" #include "base/numerics/ranges.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/animation_events.h" @@ -51,7 +50,11 @@ ElementAnimations::ElementAnimations(AnimationHost* host, ElementId element_id) element_id_(element_id), has_element_in_active_list_(false), has_element_in_pending_list_(false), - needs_push_properties_(false) { + needs_push_properties_(false), + active_maximum_scale_(kNotScaled), + active_starting_scale_(kNotScaled), + pending_maximum_scale_(kNotScaled), + pending_starting_scale_(kNotScaled) { InitAffectedElementTypes(); } @@ -226,38 +229,40 @@ bool ElementAnimations::AnimationsPreserveAxisAlignment() const { return true; } -bool ElementAnimations::AnimationStartScale(ElementListType list_type, - float* start_scale) const { - *start_scale = 0.f; +float ElementAnimations::AnimationStartScale(ElementListType list_type) const { + float start_scale = kNotScaled; for (auto& keyframe_effect : keyframe_effects_list_) { - float keyframe_effect_start_scale = 0.f; + if (keyframe_effect.HasOnlyTranslationTransforms(list_type)) + continue; + float keyframe_effect_start_scale = kNotScaled; bool success = keyframe_effect.AnimationStartScale( list_type, &keyframe_effect_start_scale); if (!success) - return false; + return kNotScaled; // Union: a maximum. - *start_scale = std::max(*start_scale, keyframe_effect_start_scale); + start_scale = std::max(start_scale, keyframe_effect_start_scale); } - return true; + return start_scale; } -bool ElementAnimations::MaximumTargetScale(ElementListType list_type, - float* max_scale) const { - *max_scale = 0.f; +float ElementAnimations::MaximumTargetScale(ElementListType list_type) const { + float max_scale = kNotScaled; for (auto& keyframe_effect : keyframe_effects_list_) { - float keyframe_effect_max_scale = 0.f; + if (keyframe_effect.HasOnlyTranslationTransforms(list_type)) + continue; + float keyframe_effect_max_scale = kNotScaled; bool success = keyframe_effect.MaximumTargetScale( list_type, &keyframe_effect_max_scale); if (!success) - return false; + return kNotScaled; // Union: a maximum. - *max_scale = std::max(*max_scale, keyframe_effect_max_scale); + max_scale = std::max(max_scale, keyframe_effect_max_scale); } - return true; + return max_scale; } bool ElementAnimations::ScrollOffsetAnimationWasInterrupted() const { @@ -313,6 +318,14 @@ void ElementAnimations::NotifyClientScrollOffsetAnimated( keyframe_model); } +void ElementAnimations::InitClientAnimationState() { + // Clear current states so that UpdateClientAnimationState() will send all + // (instead of only changed) recalculated current states to the client. + pending_state_.Clear(); + active_state_.Clear(); + UpdateClientAnimationState(); +} + void ElementAnimations::UpdateClientAnimationState() { if (!element_id()) return; @@ -347,16 +360,45 @@ void ElementAnimations::UpdateClientAnimationState() { DCHECK(active_state_.IsValid()); PropertyToElementIdMap element_id_map = GetPropertyToElementIdMap(); + ElementId transform_element_id = element_id_map[TargetProperty::TRANSFORM]; - if (has_element_in_active_list() && prev_active != active_state_) { - PropertyAnimationState diff_active = prev_active ^ active_state_; - animation_host_->mutator_host_client()->ElementIsAnimatingChanged( - element_id_map, ElementListType::ACTIVE, diff_active, active_state_); + if (has_element_in_active_list()) { + if (prev_active != active_state_) { + PropertyAnimationState diff_active = prev_active ^ active_state_; + animation_host_->mutator_host_client()->ElementIsAnimatingChanged( + element_id_map, ElementListType::ACTIVE, diff_active, active_state_); + } + + float maximum_scale = MaximumTargetScale(ElementListType::ACTIVE); + float starting_scale = AnimationStartScale(ElementListType::ACTIVE); + if (maximum_scale != active_maximum_scale_ || + starting_scale != active_starting_scale_) { + animation_host_->mutator_host_client()->AnimationScalesChanged( + transform_element_id, ElementListType::ACTIVE, maximum_scale, + starting_scale); + active_maximum_scale_ = maximum_scale; + active_starting_scale_ = starting_scale; + } } - if (has_element_in_pending_list() && prev_pending != pending_state_) { - PropertyAnimationState diff_pending = prev_pending ^ pending_state_; - animation_host_->mutator_host_client()->ElementIsAnimatingChanged( - element_id_map, ElementListType::PENDING, diff_pending, pending_state_); + + if (has_element_in_pending_list()) { + if (prev_pending != pending_state_) { + PropertyAnimationState diff_pending = prev_pending ^ pending_state_; + animation_host_->mutator_host_client()->ElementIsAnimatingChanged( + element_id_map, ElementListType::PENDING, diff_pending, + pending_state_); + } + + float maximum_scale = MaximumTargetScale(ElementListType::PENDING); + float starting_scale = AnimationStartScale(ElementListType::PENDING); + if (maximum_scale != pending_maximum_scale_ || + starting_scale != pending_starting_scale_) { + animation_host_->mutator_host_client()->AnimationScalesChanged( + transform_element_id, ElementListType::PENDING, maximum_scale, + starting_scale); + pending_maximum_scale_ = maximum_scale; + pending_starting_scale_ = starting_scale; + } } } diff --git a/chromium/cc/animation/element_animations.h b/chromium/cc/animation/element_animations.h index 5270c95ecf0..911106b04d8 100644 --- a/chromium/cc/animation/element_animations.h +++ b/chromium/cc/animation/element_animations.h @@ -8,7 +8,6 @@ #include <memory> #include <vector> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "cc/animation/animation_export.h" @@ -41,6 +40,9 @@ class CC_ANIMATION_EXPORT ElementAnimations static scoped_refptr<ElementAnimations> Create(AnimationHost* host, ElementId element_id); + ElementAnimations(const ElementAnimations&) = delete; + ElementAnimations& operator=(const ElementAnimations&) = delete; + bool AnimationHostIs(AnimationHost* host) const { return animation_host_ == host; } @@ -109,19 +111,26 @@ class CC_ANIMATION_EXPORT ElementAnimations bool AnimationsPreserveAxisAlignment() const; - // Sets |start_scale| to the maximum of starting animation scale along any - // dimension at any destination in active animations. Returns false if the - // starting scale cannot be computed. - bool AnimationStartScale(ElementListType list_type, float* start_scale) const; + // Returns the maximum of starting animation scale along any dimension at any + // destination in active scale animations, or kNotScaled if there is no active + // scale animation or the starting scale cannot be computed. + float AnimationStartScale(ElementListType list_type) const; - // Sets |max_scale| to the maximum scale along any dimension at any - // destination in active animations. Returns false if the maximum scale cannot - // be computed. - bool MaximumTargetScale(ElementListType list_type, float* max_scale) const; + // Returns the maximum scale along any dimension at any destination in active + // scale animations, or kNotScaled if there is no active scale animation or + // the maximum scale cannot be computed. + float MaximumTargetScale(ElementListType list_type) const; bool ScrollOffsetAnimationWasInterrupted() const; void SetNeedsPushProperties(); + + // Initializes client animation state by calling client's + // ElementIsAnimatingChanged() method with the current animation state. + void InitClientAnimationState(); + // Updates client animation state by calling client's + // ElementIsAnimatingChanged() method with the state containing properties + // that have changed since the last update. void UpdateClientAnimationState(); void NotifyClientFloatAnimated(float opacity, @@ -199,8 +208,10 @@ class CC_ANIMATION_EXPORT ElementAnimations PropertyAnimationState active_state_; PropertyAnimationState pending_state_; - - DISALLOW_COPY_AND_ASSIGN(ElementAnimations); + float active_maximum_scale_; + float active_starting_scale_; + float pending_maximum_scale_; + float pending_starting_scale_; }; } // namespace cc diff --git a/chromium/cc/animation/images/new-animation.png b/chromium/cc/animation/images/new-animation.png Binary files differnew file mode 100644 index 00000000000..f18e18e15a2 --- /dev/null +++ b/chromium/cc/animation/images/new-animation.png diff --git a/chromium/cc/animation/images/new-animation.png.dot b/chromium/cc/animation/images/new-animation.png.dot new file mode 100644 index 00000000000..257a6f1c19e --- /dev/null +++ b/chromium/cc/animation/images/new-animation.png.dot @@ -0,0 +1,53 @@ +// dot -Tpng cc/animation/images/new-animation.png.dot > cc/animation/images/new-animation.png +// When making modifications run the above command to regenerate the diagram. + +digraph G { + label = "Starting a new composited animation"; + + subgraph cluster_main { + label = "Main thread"; + + subgraph cluster_blink { + node [style=filled]; + ScheduleVisualUpdate + UpdateLifecycle -> RunPaintLifecyclePhase -> UpdateAnimations -> PreCommit -> CreateCompositorAnimation -> AttachCompositorTimeline; + RunPaintLifecyclePhase -> PushPaintArtifactToCompositor; + label = "third_party/blink/"; + } + + subgraph cluster_cc_main { + node [style=filled]; + AttachAnimation -> SetAnimationTimeline -> RegisterKeyframeEffect; + RegisterElement -> UpdateKeyframeEffectsTickingState; + BeginMainFrame -> RequestMainFrameUpdate -> UpdateLifecycle; + label = "cc/"; + } + color=red; + } + + subgraph cluster_impl { + label = "Compositor thread"; + + subgraph cluster_cc_impl { + node [style=filled]; + ScheduledActionCommit -> FinishCommitOnImplThread -> PushPropertiesTo -> PushAttachedAnimationsToImplThread; + ScheduledActionCommit -> CommitComplete -> ActivateAnimations; + label = "cc/"; + } + color=blue + } + + ScheduleVisualUpdate -> BeginMainFrame [style=dashed]; + AttachCompositorTimeline -> AttachAnimation; + PushPaintArtifactToCompositor -> RegisterElement; + BeginMainFrame -> ScheduledActionCommit [style=dashed]; + + subgraph cluster_legend { + label = "Legend"; + node [shape=plaintext]; + sync -> L1; + async -> L2 [style=dashed]; + L1 [label = ""]; + L2 [label = ""]; + } +} diff --git a/chromium/cc/animation/keyframe_effect.cc b/chromium/cc/animation/keyframe_effect.cc index 0d8d13c48e9..6a6dc76a121 100644 --- a/chromium/cc/animation/keyframe_effect.cc +++ b/chromium/cc/animation/keyframe_effect.cc @@ -83,6 +83,9 @@ void KeyframeEffect::BindElementAnimations( DCHECK(!element_animations_); element_animations_ = element_animations; + DCHECK(element_id_); + DCHECK(element_id_ == element_animations->element_id()); + if (has_any_keyframe_model()) KeyframeModelAdded(); SetNeedsPushProperties(); diff --git a/chromium/cc/animation/keyframe_effect.h b/chromium/cc/animation/keyframe_effect.h index c41fef5e79f..500f0bd5352 100644 --- a/chromium/cc/animation/keyframe_effect.h +++ b/chromium/cc/animation/keyframe_effect.h @@ -5,7 +5,6 @@ #ifndef CC_ANIMATION_KEYFRAME_EFFECT_H_ #define CC_ANIMATION_KEYFRAME_EFFECT_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation_events.h" @@ -41,8 +40,11 @@ typedef size_t KeyframeEffectId; class CC_ANIMATION_EXPORT KeyframeEffect { public: explicit KeyframeEffect(KeyframeEffectId id); + KeyframeEffect(const KeyframeEffect&) = delete; virtual ~KeyframeEffect(); + KeyframeEffect& operator=(const KeyframeEffect&) = delete; + static std::unique_ptr<KeyframeEffect> Create(KeyframeEffectId id); std::unique_ptr<KeyframeEffect> CreateImplInstance() const; @@ -202,8 +204,6 @@ class CC_ANIMATION_EXPORT KeyframeEffect { base::TimeTicks last_tick_time_; bool needs_push_properties_; - - DISALLOW_COPY_AND_ASSIGN(KeyframeEffect); }; } // namespace cc diff --git a/chromium/cc/animation/keyframe_model.h b/chromium/cc/animation/keyframe_model.h index cdbb2d5c236..43a22d883ec 100644 --- a/chromium/cc/animation/keyframe_model.h +++ b/chromium/cc/animation/keyframe_model.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/optional.h" #include "base/time/time.h" #include "cc/animation/animation_export.h" @@ -67,8 +66,11 @@ class CC_ANIMATION_EXPORT KeyframeModel { std::unique_ptr<KeyframeModel> CreateImplInstance( RunState initial_run_state) const; + KeyframeModel(const KeyframeModel&) = delete; virtual ~KeyframeModel(); + KeyframeModel& operator=(const KeyframeModel&) = delete; + int id() const { return id_; } int group() const { return group_; } int target_property_id() const { return target_property_id_; } @@ -279,8 +281,6 @@ class CC_ANIMATION_EXPORT KeyframeModel { // longer affect any elements, and are deleted. bool affects_active_elements_; bool affects_pending_elements_; - - DISALLOW_COPY_AND_ASSIGN(KeyframeModel); }; } // namespace cc diff --git a/chromium/cc/animation/keyframed_animation_curve.h b/chromium/cc/animation/keyframed_animation_curve.h index 582a26c2f6c..27e87ba3648 100644 --- a/chromium/cc/animation/keyframed_animation_curve.h +++ b/chromium/cc/animation/keyframed_animation_curve.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "base/time/time.h" #include "cc/animation/animation_curve.h" #include "cc/animation/animation_export.h" @@ -19,6 +18,9 @@ namespace cc { class CC_ANIMATION_EXPORT Keyframe { public: + Keyframe(const Keyframe&) = delete; + Keyframe& operator=(const Keyframe&) = delete; + base::TimeDelta Time() const; const TimingFunction* timing_function() const { return timing_function_.get(); @@ -32,8 +34,6 @@ class CC_ANIMATION_EXPORT Keyframe { private: base::TimeDelta time_; std::unique_ptr<TimingFunction> timing_function_; - - DISALLOW_COPY_AND_ASSIGN(Keyframe); }; class CC_ANIMATION_EXPORT ColorKeyframe : public Keyframe { @@ -142,8 +142,12 @@ class CC_ANIMATION_EXPORT KeyframedColorAnimationCurve // It is required that the keyframes be sorted by time. static std::unique_ptr<KeyframedColorAnimationCurve> Create(); + KeyframedColorAnimationCurve(const KeyframedColorAnimationCurve&) = delete; ~KeyframedColorAnimationCurve() override; + KeyframedColorAnimationCurve& operator=(const KeyframedColorAnimationCurve&) = + delete; + void AddKeyframe(std::unique_ptr<ColorKeyframe> keyframe); void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) { timing_function_ = std::move(timing_function); @@ -168,8 +172,6 @@ class CC_ANIMATION_EXPORT KeyframedColorAnimationCurve std::vector<std::unique_ptr<ColorKeyframe>> keyframes_; std::unique_ptr<TimingFunction> timing_function_; double scaled_duration_; - - DISALLOW_COPY_AND_ASSIGN(KeyframedColorAnimationCurve); }; class CC_ANIMATION_EXPORT KeyframedFloatAnimationCurve @@ -178,8 +180,12 @@ class CC_ANIMATION_EXPORT KeyframedFloatAnimationCurve // It is required that the keyframes be sorted by time. static std::unique_ptr<KeyframedFloatAnimationCurve> Create(); + KeyframedFloatAnimationCurve(const KeyframedFloatAnimationCurve&) = delete; ~KeyframedFloatAnimationCurve() override; + KeyframedFloatAnimationCurve& operator=(const KeyframedFloatAnimationCurve&) = + delete; + void AddKeyframe(std::unique_ptr<FloatKeyframe> keyframe); void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) { @@ -211,8 +217,6 @@ class CC_ANIMATION_EXPORT KeyframedFloatAnimationCurve Keyframes keyframes_; std::unique_ptr<TimingFunction> timing_function_; double scaled_duration_; - - DISALLOW_COPY_AND_ASSIGN(KeyframedFloatAnimationCurve); }; class CC_ANIMATION_EXPORT KeyframedTransformAnimationCurve @@ -221,8 +225,13 @@ class CC_ANIMATION_EXPORT KeyframedTransformAnimationCurve // It is required that the keyframes be sorted by time. static std::unique_ptr<KeyframedTransformAnimationCurve> Create(); + KeyframedTransformAnimationCurve(const KeyframedTransformAnimationCurve&) = + delete; ~KeyframedTransformAnimationCurve() override; + KeyframedTransformAnimationCurve& operator=( + const KeyframedTransformAnimationCurve&) = delete; + void AddKeyframe(std::unique_ptr<TransformKeyframe> keyframe); void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) { timing_function_ = std::move(timing_function); @@ -253,8 +262,6 @@ class CC_ANIMATION_EXPORT KeyframedTransformAnimationCurve std::vector<std::unique_ptr<TransformKeyframe>> keyframes_; std::unique_ptr<TimingFunction> timing_function_; double scaled_duration_; - - DISALLOW_COPY_AND_ASSIGN(KeyframedTransformAnimationCurve); }; class CC_ANIMATION_EXPORT KeyframedFilterAnimationCurve @@ -263,8 +270,12 @@ class CC_ANIMATION_EXPORT KeyframedFilterAnimationCurve // It is required that the keyframes be sorted by time. static std::unique_ptr<KeyframedFilterAnimationCurve> Create(); + KeyframedFilterAnimationCurve(const KeyframedFilterAnimationCurve&) = delete; ~KeyframedFilterAnimationCurve() override; + KeyframedFilterAnimationCurve& operator=( + const KeyframedFilterAnimationCurve&) = delete; + void AddKeyframe(std::unique_ptr<FilterKeyframe> keyframe); void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) { timing_function_ = std::move(timing_function); @@ -290,8 +301,6 @@ class CC_ANIMATION_EXPORT KeyframedFilterAnimationCurve std::vector<std::unique_ptr<FilterKeyframe>> keyframes_; std::unique_ptr<TimingFunction> timing_function_; double scaled_duration_; - - DISALLOW_COPY_AND_ASSIGN(KeyframedFilterAnimationCurve); }; class CC_ANIMATION_EXPORT KeyframedSizeAnimationCurve @@ -300,8 +309,12 @@ class CC_ANIMATION_EXPORT KeyframedSizeAnimationCurve // It is required that the keyframes be sorted by time. static std::unique_ptr<KeyframedSizeAnimationCurve> Create(); + KeyframedSizeAnimationCurve(const KeyframedSizeAnimationCurve&) = delete; ~KeyframedSizeAnimationCurve() override; + KeyframedSizeAnimationCurve& operator=(const KeyframedSizeAnimationCurve&) = + delete; + void AddKeyframe(std::unique_ptr<SizeKeyframe> keyframe); void SetTimingFunction(std::unique_ptr<TimingFunction> timing_function) { timing_function_ = std::move(timing_function); @@ -326,8 +339,6 @@ class CC_ANIMATION_EXPORT KeyframedSizeAnimationCurve std::vector<std::unique_ptr<SizeKeyframe>> keyframes_; std::unique_ptr<TimingFunction> timing_function_; double scaled_duration_; - - DISALLOW_COPY_AND_ASSIGN(KeyframedSizeAnimationCurve); }; } // namespace cc diff --git a/chromium/cc/animation/scroll_offset_animation_curve.h b/chromium/cc/animation/scroll_offset_animation_curve.h index 978fe82f01b..fca9af6942b 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve.h +++ b/chromium/cc/animation/scroll_offset_animation_curve.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/time/time.h" #include "cc/animation/animation_curve.h" #include "cc/animation/animation_export.h" @@ -47,8 +46,12 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve { DurationBehavior behavior, base::TimeDelta delayed_by); + ScrollOffsetAnimationCurve(const ScrollOffsetAnimationCurve&) = delete; ~ScrollOffsetAnimationCurve() override; + ScrollOffsetAnimationCurve& operator=(const ScrollOffsetAnimationCurve&) = + delete; + void SetInitialValue(const gfx::ScrollOffset& initial_value, base::TimeDelta delayed_by = base::TimeDelta()); bool HasSetInitialValue() const; @@ -93,8 +96,6 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve : public AnimationCurve { bool has_set_initial_value_; static base::Optional<double> animation_duration_for_testing_; - - DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimationCurve); }; } // namespace cc diff --git a/chromium/cc/animation/scroll_offset_animations_impl.cc b/chromium/cc/animation/scroll_offset_animations_impl.cc index ec4bafbd264..896e17440be 100644 --- a/chromium/cc/animation/scroll_offset_animations_impl.cc +++ b/chromium/cc/animation/scroll_offset_animations_impl.cc @@ -59,7 +59,6 @@ void ScrollOffsetAnimationsImpl::ScrollAnimationCreate( DCHECK(scroll_offset_animation_->animation_timeline()); ReattachScrollOffsetAnimationIfNeeded(element_id); - scroll_offset_animation_->AddKeyframeModel(std::move(keyframe_model)); } @@ -183,6 +182,29 @@ void ScrollOffsetAnimationsImpl::NotifyAnimationFinished( TRACE_EVENT_SCOPE_THREAD); } +bool ScrollOffsetAnimationsImpl::IsAnimating() const { + if (!scroll_offset_animation_->has_element_animations()) + return false; + + KeyframeModel* keyframe_model = + scroll_offset_animation_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET); + if (!keyframe_model) + return false; + + switch (keyframe_model->run_state()) { + case KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY: + case KeyframeModel::STARTING: + case KeyframeModel::RUNNING: + case KeyframeModel::PAUSED: + return true; + case KeyframeModel::WAITING_FOR_DELETION: + case KeyframeModel::FINISHED: + case KeyframeModel::ABORTED: + case KeyframeModel::ABORTED_BUT_NEEDS_COMPLETION: + return false; + } +} + void ScrollOffsetAnimationsImpl::ReattachScrollOffsetAnimationIfNeeded( ElementId element_id) { if (scroll_offset_animation_->element_id() != element_id) { diff --git a/chromium/cc/animation/scroll_offset_animations_impl.h b/chromium/cc/animation/scroll_offset_animations_impl.h index e64456eb9f0..39d72f18cd6 100644 --- a/chromium/cc/animation/scroll_offset_animations_impl.h +++ b/chromium/cc/animation/scroll_offset_animations_impl.h @@ -5,7 +5,6 @@ #ifndef CC_ANIMATION_SCROLL_OFFSET_ANIMATIONS_IMPL_H_ #define CC_ANIMATION_SCROLL_OFFSET_ANIMATIONS_IMPL_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/animation/animation_delegate.h" #include "cc/animation/scroll_offset_animation_curve.h" @@ -27,9 +26,12 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationsImpl : public AnimationDelegate { public: explicit ScrollOffsetAnimationsImpl(AnimationHost* animation_host); - + ScrollOffsetAnimationsImpl(const ScrollOffsetAnimationsImpl&) = delete; ~ScrollOffsetAnimationsImpl() override; + ScrollOffsetAnimationsImpl& operator=(const ScrollOffsetAnimationsImpl&) = + delete; + // |delayed_by| shrinks the duration of the // animation. |animation_start_offset| causes us to start the animation // partway through. @@ -68,6 +70,8 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationsImpl std::unique_ptr<AnimationCurve> curve) override { } + bool IsAnimating() const; + private: void ReattachScrollOffsetAnimationIfNeeded(ElementId element_id); @@ -78,8 +82,6 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationsImpl // I.e. only one element can have an impl-only scroll offset animation at // any given time. scoped_refptr<SingleKeyframeEffectAnimation> scroll_offset_animation_; - - DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimationsImpl); }; } // namespace cc diff --git a/chromium/cc/animation/single_keyframe_effect_animation.h b/chromium/cc/animation/single_keyframe_effect_animation.h index 6baeb7669c8..474250c8a9a 100644 --- a/chromium/cc/animation/single_keyframe_effect_animation.h +++ b/chromium/cc/animation/single_keyframe_effect_animation.h @@ -8,7 +8,6 @@ #include <vector> #include <memory> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/animation/animation.h" @@ -37,6 +36,10 @@ class CC_ANIMATION_EXPORT SingleKeyframeEffectAnimation : public Animation { static scoped_refptr<SingleKeyframeEffectAnimation> Create(int id); scoped_refptr<Animation> CreateImplInstance() const override; + SingleKeyframeEffectAnimation(const SingleKeyframeEffectAnimation&) = delete; + SingleKeyframeEffectAnimation& operator=( + const SingleKeyframeEffectAnimation&) = delete; + ElementId element_id() const; void AttachElement(ElementId element_id); @@ -64,8 +67,6 @@ class CC_ANIMATION_EXPORT SingleKeyframeEffectAnimation : public Animation { std::unique_ptr<KeyframeEffect>); ~SingleKeyframeEffectAnimation() override; - - DISALLOW_COPY_AND_ASSIGN(SingleKeyframeEffectAnimation); }; } // namespace cc diff --git a/chromium/cc/animation/timing_function.h b/chromium/cc/animation/timing_function.h index f5dc7f89e5a..77969ac4188 100644 --- a/chromium/cc/animation/timing_function.h +++ b/chromium/cc/animation/timing_function.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "cc/animation/animation_export.h" #include "ui/gfx/geometry/cubic_bezier.h" @@ -18,6 +17,8 @@ class CC_ANIMATION_EXPORT TimingFunction { public: virtual ~TimingFunction(); + TimingFunction& operator=(const TimingFunction&) = delete; + // Note that LINEAR is a nullptr TimingFunction (for now). enum class Type { LINEAR, CUBIC_BEZIER, STEPS, FRAMES }; @@ -28,8 +29,6 @@ class CC_ANIMATION_EXPORT TimingFunction { protected: TimingFunction(); - - DISALLOW_ASSIGN(TimingFunction); }; class CC_ANIMATION_EXPORT CubicBezierTimingFunction : public TimingFunction { @@ -44,6 +43,9 @@ class CC_ANIMATION_EXPORT CubicBezierTimingFunction : public TimingFunction { double y2); ~CubicBezierTimingFunction() override; + CubicBezierTimingFunction& operator=(const CubicBezierTimingFunction&) = + delete; + // TimingFunction implementation. Type GetType() const override; double GetValue(double time) const override; @@ -62,8 +64,6 @@ class CC_ANIMATION_EXPORT CubicBezierTimingFunction : public TimingFunction { gfx::CubicBezier bezier_; EaseType ease_type_; - - DISALLOW_ASSIGN(CubicBezierTimingFunction); }; class CC_ANIMATION_EXPORT StepsTimingFunction : public TimingFunction { @@ -77,6 +77,8 @@ class CC_ANIMATION_EXPORT StepsTimingFunction : public TimingFunction { StepPosition step_position); ~StepsTimingFunction() override; + StepsTimingFunction& operator=(const StepsTimingFunction&) = delete; + // TimingFunction implementation. Type GetType() const override; double GetValue(double t) const override; @@ -94,8 +96,6 @@ class CC_ANIMATION_EXPORT StepsTimingFunction : public TimingFunction { int steps_; StepPosition step_position_; - - DISALLOW_ASSIGN(StepsTimingFunction); }; class CC_ANIMATION_EXPORT FramesTimingFunction : public TimingFunction { @@ -103,6 +103,8 @@ class CC_ANIMATION_EXPORT FramesTimingFunction : public TimingFunction { static std::unique_ptr<FramesTimingFunction> Create(int frames); ~FramesTimingFunction() override; + FramesTimingFunction& operator=(const FramesTimingFunction&) = delete; + // TimingFunction implementation. Type GetType() const override; double GetValue(double t) const override; @@ -116,8 +118,6 @@ class CC_ANIMATION_EXPORT FramesTimingFunction : public TimingFunction { explicit FramesTimingFunction(int frames); int frames_; - - DISALLOW_ASSIGN(FramesTimingFunction); }; } // namespace cc diff --git a/chromium/cc/animation/transform_operations.h b/chromium/cc/animation/transform_operations.h index 4a6706d75d6..f8e89ca62ce 100644 --- a/chromium/cc/animation/transform_operations.h +++ b/chromium/cc/animation/transform_operations.h @@ -11,7 +11,6 @@ #include "base/gtest_prod_util.h" #include "base/logging.h" -#include "base/macros.h" #include "cc/animation/animation_export.h" #include "cc/animation/transform_operation.h" #include "ui/gfx/transform.h" diff --git a/chromium/cc/base/delayed_unique_notifier.h b/chromium/cc/base/delayed_unique_notifier.h index 4a7486e099a..16669879d00 100644 --- a/chromium/cc/base/delayed_unique_notifier.h +++ b/chromium/cc/base/delayed_unique_notifier.h @@ -6,7 +6,6 @@ #define CC_BASE_DELAYED_UNIQUE_NOTIFIER_H_ #include "base/callback.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "cc/base/base_export.h" @@ -23,11 +22,14 @@ class CC_BASE_EXPORT DelayedUniqueNotifier { DelayedUniqueNotifier(base::SequencedTaskRunner* task_runner, base::RepeatingClosure closure, const base::TimeDelta& delay); + DelayedUniqueNotifier(const DelayedUniqueNotifier&) = delete; // Destroying the notifier will ensure that no further notifications will // happen from this class. virtual ~DelayedUniqueNotifier(); + DelayedUniqueNotifier& operator=(const DelayedUniqueNotifier&) = delete; + // Schedule a notification to be run. If another notification is already // pending, then it will happen in (at least) given delay from now. That is, // if delay is 16ms and a notification has been scheduled 10ms ago (ie, it @@ -66,8 +68,6 @@ class CC_BASE_EXPORT DelayedUniqueNotifier { bool notification_pending_; base::WeakPtrFactory<DelayedUniqueNotifier> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(DelayedUniqueNotifier); }; } // namespace cc diff --git a/chromium/cc/base/devtools_instrumentation.h b/chromium/cc/base/devtools_instrumentation.h index 0697422a428..56077e041e4 100644 --- a/chromium/cc/base/devtools_instrumentation.h +++ b/chromium/cc/base/devtools_instrumentation.h @@ -9,7 +9,6 @@ #include <memory> -#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" @@ -53,14 +52,15 @@ class CC_BASE_EXPORT ScopedLayerTask { TRACE_EVENT_BEGIN1(internal::CategoryName::kTimeline, event_name_, internal::kLayerId, layer_id); } + ScopedLayerTask(const ScopedLayerTask&) = delete; ~ScopedLayerTask() { TRACE_EVENT_END0(internal::CategoryName::kTimeline, event_name_); } + ScopedLayerTask& operator=(const ScopedLayerTask&) = delete; + private: const char* event_name_; - - DISALLOW_COPY_AND_ASSIGN(ScopedLayerTask); }; class CC_BASE_EXPORT ScopedImageDecodeTask { @@ -71,13 +71,15 @@ class CC_BASE_EXPORT ScopedImageDecodeTask { ScopedImageDecodeTask(const void* image_ptr, DecodeType decode_type, TaskType task_type); + ScopedImageDecodeTask(const ScopedImageDecodeTask&) = delete; ~ScopedImageDecodeTask(); + ScopedImageDecodeTask& operator=(const ScopedImageDecodeTask&) = delete; + private: const DecodeType decode_type_; const TaskType task_type_; const base::TimeTicks start_time_; - DISALLOW_COPY_AND_ASSIGN(ScopedImageDecodeTask); }; class CC_BASE_EXPORT ScopedLayerTreeTask { @@ -90,14 +92,15 @@ class CC_BASE_EXPORT ScopedLayerTreeTask { internal::kLayerId, layer_id, internal::kLayerTreeId, layer_tree_host_id); } + ScopedLayerTreeTask(const ScopedLayerTreeTask&) = delete; ~ScopedLayerTreeTask() { TRACE_EVENT_END0(internal::CategoryName::kTimeline, event_name_); } + ScopedLayerTreeTask& operator=(const ScopedLayerTreeTask&) = delete; + private: const char* event_name_; - - DISALLOW_COPY_AND_ASSIGN(ScopedLayerTreeTask); }; struct CC_BASE_EXPORT ScopedCommitTrace { @@ -107,13 +110,13 @@ struct CC_BASE_EXPORT ScopedCommitTrace { internal::kCompositeLayers, internal::kLayerTreeId, layer_tree_host_id); } + ScopedCommitTrace(const ScopedCommitTrace&) = delete; ~ScopedCommitTrace() { TRACE_EVENT_END0(internal::CategoryName::kTimeline, internal::kCompositeLayers); } - private: - DISALLOW_COPY_AND_ASSIGN(ScopedCommitTrace); + ScopedCommitTrace& operator=(const ScopedCommitTrace&) = delete; }; struct CC_BASE_EXPORT ScopedLayerObjectTracker @@ -124,9 +127,8 @@ struct CC_BASE_EXPORT ScopedLayerObjectTracker TraceScopedTrackableObject<int, internal::CategoryName::kTimeline>( internal::kLayerId, layer_id) {} - - private: - DISALLOW_COPY_AND_ASSIGN(ScopedLayerObjectTracker); + ScopedLayerObjectTracker(const ScopedLayerObjectTracker&) = delete; + ScopedLayerObjectTracker& operator=(const ScopedLayerObjectTracker&) = delete; }; inline void CC_BASE_EXPORT DidActivateLayerTree(int layer_tree_host_id, diff --git a/chromium/cc/base/histograms.h b/chromium/cc/base/histograms.h index dd88f8c04d4..d4f8a23dd5c 100644 --- a/chromium/cc/base/histograms.h +++ b/chromium/cc/base/histograms.h @@ -6,7 +6,6 @@ #define CC_BASE_HISTOGRAMS_H_ #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_math.h" @@ -92,6 +91,11 @@ CC_BASE_EXPORT const char* GetClientNameForMetrics(); class CC_BASE_EXPORT ScopedUMAHistogramAreaTimerBase { public: + ScopedUMAHistogramAreaTimerBase(const ScopedUMAHistogramAreaTimerBase&) = + delete; + ScopedUMAHistogramAreaTimerBase& operator=( + const ScopedUMAHistogramAreaTimerBase&) = delete; + void AddArea(const base::CheckedNumeric<int>& area) { area_ += area; } void SetArea(const base::CheckedNumeric<int>& area) { area_ = area; } @@ -115,7 +119,6 @@ class CC_BASE_EXPORT ScopedUMAHistogramAreaTimerBase { base::CheckedNumeric<int> area_; friend class ScopedUMAHistogramAreaTimerBaseTest; - DISALLOW_COPY_AND_ASSIGN(ScopedUMAHistogramAreaTimerBase); }; } // namespace cc diff --git a/chromium/cc/base/list_container.h b/chromium/cc/base/list_container.h index 0c20831e1c7..2c480e65773 100644 --- a/chromium/cc/base/list_container.h +++ b/chromium/cc/base/list_container.h @@ -10,7 +10,6 @@ #include <memory> #include "base/logging.h" -#include "base/macros.h" #include "cc/base/list_container_helper.h" namespace cc { @@ -35,6 +34,7 @@ class ListContainer { : helper_(max_alignment, max_size_for_derived_class, num_of_elements_to_reserve_for) {} + ListContainer(const ListContainer&) = delete; ~ListContainer() { for (Iterator i = begin(); i != end(); ++i) { @@ -42,6 +42,8 @@ class ListContainer { } } + ListContainer& operator=(const ListContainer&) = delete; + class Iterator; class ConstIterator; class ReverseIterator; @@ -358,8 +360,6 @@ class ListContainer { private: ListContainerHelper helper_; - - DISALLOW_COPY_AND_ASSIGN(ListContainer); }; } // namespace cc diff --git a/chromium/cc/base/list_container_helper.cc b/chromium/cc/base/list_container_helper.cc index 380ad3dd187..3a4c0b6a2f9 100644 --- a/chromium/cc/base/list_container_helper.cc +++ b/chromium/cc/base/list_container_helper.cc @@ -10,7 +10,6 @@ #include <vector> #include "base/logging.h" -#include "base/macros.h" #include "base/memory/aligned_memory.h" namespace { @@ -30,6 +29,9 @@ class ListContainerHelper::CharAllocator { // This class holds the raw memory chunk, as well as information about its // size and availability. struct InnerList { + InnerList(const InnerList&) = delete; + InnerList& operator=(const InnerList&) = delete; + std::unique_ptr<char[], base::AlignedFreeDeleter> data; // The number of elements in total the memory can hold. The difference // between capacity and size is the how many more elements this list can @@ -99,9 +101,6 @@ class ListContainerHelper::CharAllocator { char* End() const { return data.get() + size * step; } char* LastElement() const { return data.get() + (size - 1) * step; } char* ElementAt(size_t index) const { return data.get() + index * step; } - - private: - DISALLOW_COPY_AND_ASSIGN(InnerList); }; CharAllocator(size_t alignment, size_t element_size, size_t element_count) @@ -119,8 +118,11 @@ class ListContainerHelper::CharAllocator { last_list_ = storage_[last_list_index_].get(); } + CharAllocator(const CharAllocator&) = delete; ~CharAllocator() = default; + CharAllocator& operator=(const CharAllocator&) = delete; + void* Allocate() { if (last_list_->IsFull()) { // Only allocate a new list if there isn't a spare one still there from @@ -261,8 +263,6 @@ class ListContainerHelper::CharAllocator { // This is equivalent to |storage_[last_list_index_]|. InnerList* last_list_; - - DISALLOW_COPY_AND_ASSIGN(CharAllocator); }; // PositionInCharAllocator diff --git a/chromium/cc/base/list_container_helper.h b/chromium/cc/base/list_container_helper.h index c79cf1f1884..31658bc8486 100644 --- a/chromium/cc/base/list_container_helper.h +++ b/chromium/cc/base/list_container_helper.h @@ -9,7 +9,6 @@ #include <memory> -#include "base/macros.h" #include "cc/base/base_export.h" namespace cc { @@ -25,8 +24,11 @@ class CC_BASE_EXPORT ListContainerHelper final { explicit ListContainerHelper(size_t alignment, size_t max_size_for_derived_class, size_t num_of_elements_to_reserve_for); + ListContainerHelper(const ListContainerHelper&) = delete; ~ListContainerHelper(); + ListContainerHelper& operator=(const ListContainerHelper&) = delete; + // This class deals only with char* and void*. It does allocation and passing // out raw pointers, as well as memory deallocation when being destroyed. class CharAllocator; @@ -170,8 +172,6 @@ class CC_BASE_EXPORT ListContainerHelper final { void* Allocate(size_t alignment, size_t size_of_actual_element_in_bytes); std::unique_ptr<CharAllocator> data_; - - DISALLOW_COPY_AND_ASSIGN(ListContainerHelper); }; } // namespace cc diff --git a/chromium/cc/base/math_util.h b/chromium/cc/base/math_util.h index 2674b83e796..c3d8179820e 100644 --- a/chromium/cc/base/math_util.h +++ b/chromium/cc/base/math_util.h @@ -316,13 +316,16 @@ class CC_BASE_EXPORT MathUtil { class CC_BASE_EXPORT ScopedSubnormalFloatDisabler { public: ScopedSubnormalFloatDisabler(); + ScopedSubnormalFloatDisabler(const ScopedSubnormalFloatDisabler&) = delete; ~ScopedSubnormalFloatDisabler(); - private: + ScopedSubnormalFloatDisabler& operator=(const ScopedSubnormalFloatDisabler&) = + delete; + #if defined(ARCH_CPU_X86_FAMILY) + private: unsigned int orig_state_; #endif - DISALLOW_COPY_AND_ASSIGN(ScopedSubnormalFloatDisabler); }; } // namespace cc diff --git a/chromium/cc/base/rolling_time_delta_history.h b/chromium/cc/base/rolling_time_delta_history.h index f23d583d8ef..75832323278 100644 --- a/chromium/cc/base/rolling_time_delta_history.h +++ b/chromium/cc/base/rolling_time_delta_history.h @@ -11,7 +11,6 @@ #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" -#include "base/macros.h" #include "base/time/time.h" #include "cc/base/base_export.h" @@ -22,9 +21,12 @@ namespace cc { class CC_BASE_EXPORT RollingTimeDeltaHistory { public: explicit RollingTimeDeltaHistory(size_t max_size); + RollingTimeDeltaHistory(const RollingTimeDeltaHistory&) = delete; ~RollingTimeDeltaHistory(); + RollingTimeDeltaHistory& operator=(const RollingTimeDeltaHistory&) = delete; + void InsertSample(base::TimeDelta time); size_t sample_count() const { return sample_set_.size(); } @@ -44,8 +46,6 @@ class CC_BASE_EXPORT RollingTimeDeltaHistory { size_t max_size_; mutable base::flat_map<double, base::TimeDelta> percentile_cache_; - - DISALLOW_COPY_AND_ASSIGN(RollingTimeDeltaHistory); }; } // namespace cc diff --git a/chromium/cc/base/rtree.h b/chromium/cc/base/rtree.h index 840eaabe079..24909814298 100644 --- a/chromium/cc/base/rtree.h +++ b/chromium/cc/base/rtree.h @@ -10,6 +10,7 @@ #include <algorithm> #include <cmath> +#include <map> #include <vector> #include "base/logging.h" @@ -42,8 +43,11 @@ template <typename T> class RTree { public: RTree(); + RTree(const RTree&) = delete; ~RTree(); + RTree& operator=(const RTree&) = delete; + // Constructs the rtree from a given container of gfx::Rects. Queries using // Search will then return indices into this container. template <typename Container> @@ -73,7 +77,7 @@ class RTree { // Returns respective bounds of all items in this rtree in the order of items. // Production code except tracing should not use this method. - std::vector<gfx::Rect> GetAllBoundsForTracing() const; + std::map<T, gfx::Rect> GetAllBoundsForTracing() const; void Reset(); @@ -123,14 +127,12 @@ class RTree { Node<T>* AllocateNodeAtLevel(int level); void GetAllBoundsRecursive(Node<T>* root, - std::vector<gfx::Rect>* results) const; + std::map<T, gfx::Rect>* results) const; // This is the count of data elements (rather than total nodes in the tree) size_t num_data_elements_ = 0u; Branch<T> root_; std::vector<Node<T>> nodes_; - - DISALLOW_COPY_AND_ASSIGN(RTree); }; template <typename T> @@ -336,8 +338,8 @@ gfx::Rect RTree<T>::GetBounds() const { } template <typename T> -std::vector<gfx::Rect> RTree<T>::GetAllBoundsForTracing() const { - std::vector<gfx::Rect> results; +std::map<T, gfx::Rect> RTree<T>::GetAllBoundsForTracing() const { + std::map<T, gfx::Rect> results; if (num_data_elements_ > 0) GetAllBoundsRecursive(root_.subtree, &results); return results; @@ -345,10 +347,10 @@ std::vector<gfx::Rect> RTree<T>::GetAllBoundsForTracing() const { template <typename T> void RTree<T>::GetAllBoundsRecursive(Node<T>* node, - std::vector<gfx::Rect>* results) const { + std::map<T, gfx::Rect>* results) const { for (uint16_t i = 0; i < node->num_children; ++i) { if (node->level == 0) - results->push_back(node->children[i].bounds); + (*results)[node->children[i].payload] = node->children[i].bounds; else GetAllBoundsRecursive(node->children[i].subtree, results); } diff --git a/chromium/cc/base/rtree_unittest.cc b/chromium/cc/base/rtree_unittest.cc index e5b937942d9..0ac0bc3a702 100644 --- a/chromium/cc/base/rtree_unittest.cc +++ b/chromium/cc/base/rtree_unittest.cc @@ -128,7 +128,9 @@ TEST(RTreeTest, GetBoundsNonOverlapping) { rtree.Build(rects); EXPECT_EQ(gfx::Rect(5, 6, 19, 20), rtree.GetBounds()); - EXPECT_EQ(rects, rtree.GetAllBoundsForTracing()); + std::map<size_t, gfx::Rect> expected_all_bounds = {{0, rects[0]}, + {1, rects[1]}}; + EXPECT_EQ(expected_all_bounds, rtree.GetAllBoundsForTracing()); } TEST(RTreeTest, GetBoundsOverlapping) { @@ -140,7 +142,22 @@ TEST(RTreeTest, GetBoundsOverlapping) { rtree.Build(rects); EXPECT_EQ(gfx::Rect(0, 0, 10, 10), rtree.GetBounds()); - EXPECT_EQ(rects, rtree.GetAllBoundsForTracing()); + std::map<size_t, gfx::Rect> expected_all_bounds = {{0, rects[0]}, + {1, rects[1]}}; + EXPECT_EQ(expected_all_bounds, rtree.GetAllBoundsForTracing()); +} + +TEST(RTreeTest, GetBoundsWithEmptyRect) { + std::vector<gfx::Rect> rects; + rects.push_back(gfx::Rect()); + rects.push_back(gfx::Rect(5, 5, 5, 5)); + + RTree<size_t> rtree; + rtree.Build(rects); + + EXPECT_EQ(gfx::Rect(5, 5, 5, 5), rtree.GetBounds()); + std::map<size_t, gfx::Rect> expected_all_bounds = {{1, rects[1]}}; + EXPECT_EQ(expected_all_bounds, rtree.GetAllBoundsForTracing()); } TEST(RTreeTest, BuildAfterReset) { @@ -161,7 +178,9 @@ TEST(RTreeTest, BuildAfterReset) { // Should be able to rebuild from a reset rtree. rtree.Build(rects); EXPECT_EQ(gfx::Rect(0, 0, 10, 10), rtree.GetBounds()); - EXPECT_EQ(rects, rtree.GetAllBoundsForTracing()); + std::map<size_t, gfx::Rect> expected_all_bounds = { + {0, rects[0]}, {1, rects[1]}, {2, rects[2]}, {3, rects[3]}}; + EXPECT_EQ(expected_all_bounds, rtree.GetAllBoundsForTracing()); } TEST(RTreeTest, Payload) { diff --git a/chromium/cc/base/unique_notifier.h b/chromium/cc/base/unique_notifier.h index ff129c8b525..ad2172b4213 100644 --- a/chromium/cc/base/unique_notifier.h +++ b/chromium/cc/base/unique_notifier.h @@ -6,7 +6,6 @@ #define CC_BASE_UNIQUE_NOTIFIER_H_ #include "base/callback.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "cc/base/base_export.h" @@ -23,11 +22,14 @@ class CC_BASE_EXPORT UniqueNotifier { // Configure this notifier to issue the |closure| notification when scheduled. UniqueNotifier(base::SequencedTaskRunner* task_runner, base::RepeatingClosure closure); + UniqueNotifier(const UniqueNotifier&) = delete; // Destroying the notifier will ensure that no further notifications will // happen from this class. ~UniqueNotifier(); + UniqueNotifier& operator=(const UniqueNotifier&) = delete; + // Schedule a notification to be run. If another notification is already // pending, then only one notification will take place. void Schedule(); @@ -47,8 +49,6 @@ class CC_BASE_EXPORT UniqueNotifier { bool notification_pending_; base::WeakPtrFactory<UniqueNotifier> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(UniqueNotifier); }; } // namespace cc diff --git a/chromium/cc/benchmarks/benchmark_instrumentation.h b/chromium/cc/benchmarks/benchmark_instrumentation.h index d946c6e6b25..d2bc0627d95 100644 --- a/chromium/cc/benchmarks/benchmark_instrumentation.h +++ b/chromium/cc/benchmarks/benchmark_instrumentation.h @@ -5,7 +5,6 @@ #ifndef CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_ #define CC_BENCHMARKS_BENCHMARK_INSTRUMENTATION_H_ -#include "base/macros.h" #include "base/trace_event/trace_event.h" #include "cc/cc_export.h" #include "cc/debug/rendering_stats.h" @@ -38,14 +37,15 @@ class ScopedBeginFrameTask { TRACE_EVENT_BEGIN1(internal::Category(), event_name_, internal::kBeginFrameId, begin_frame_id); } + ScopedBeginFrameTask(const ScopedBeginFrameTask&) = delete; ~ScopedBeginFrameTask() { TRACE_EVENT_END0(internal::Category(), event_name_); } + ScopedBeginFrameTask& operator=(const ScopedBeginFrameTask&) = delete; + private: const char* event_name_; - - DISALLOW_COPY_AND_ASSIGN(ScopedBeginFrameTask); }; void IssueImplThreadRenderingStatsEvent(const RenderingStats& stats); diff --git a/chromium/cc/benchmarks/micro_benchmark_controller.h b/chromium/cc/benchmarks/micro_benchmark_controller.h index e5eb7b27375..ab5ce66f292 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller.h +++ b/chromium/cc/benchmarks/micro_benchmark_controller.h @@ -9,7 +9,6 @@ #include <vector> #include "base/callback.h" -#include "base/macros.h" #include "cc/benchmarks/micro_benchmark.h" namespace base { @@ -24,8 +23,11 @@ class LayerTreeHostImpl; class CC_EXPORT MicroBenchmarkController { public: explicit MicroBenchmarkController(LayerTreeHost* host); + MicroBenchmarkController(const MicroBenchmarkController&) = delete; ~MicroBenchmarkController(); + MicroBenchmarkController& operator=(const MicroBenchmarkController&) = delete; + void DidUpdateLayers(); // Returns the id of the benchmark on success, 0 otherwise. @@ -45,8 +47,6 @@ class CC_EXPORT MicroBenchmarkController { std::vector<std::unique_ptr<MicroBenchmark>> benchmarks_; static int next_id_; scoped_refptr<base::SingleThreadTaskRunner> main_controller_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkController); }; } // namespace cc diff --git a/chromium/cc/benchmarks/micro_benchmark_controller_impl.h b/chromium/cc/benchmarks/micro_benchmark_controller_impl.h index 79482436486..fc1b91c673e 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller_impl.h +++ b/chromium/cc/benchmarks/micro_benchmark_controller_impl.h @@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "cc/benchmarks/micro_benchmark_impl.h" namespace cc { @@ -17,8 +16,12 @@ class LayerTreeHostImpl; class CC_EXPORT MicroBenchmarkControllerImpl { public: explicit MicroBenchmarkControllerImpl(LayerTreeHostImpl* host); + MicroBenchmarkControllerImpl(const MicroBenchmarkControllerImpl&) = delete; ~MicroBenchmarkControllerImpl(); + MicroBenchmarkControllerImpl& operator=(const MicroBenchmarkControllerImpl&) = + delete; + void DidCompleteCommit(); void ScheduleRun(std::unique_ptr<MicroBenchmarkImpl> benchmark); @@ -28,8 +31,6 @@ class CC_EXPORT MicroBenchmarkControllerImpl { LayerTreeHostImpl* host_; std::vector<std::unique_ptr<MicroBenchmarkImpl>> benchmarks_; - - DISALLOW_COPY_AND_ASSIGN(MicroBenchmarkControllerImpl); }; } // namespace cc diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc index cf7f706eb87..6f2da14d012 100644 --- a/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark_impl.cc @@ -71,8 +71,7 @@ void RunBenchmark(RasterSource* raster_source, settings.image_provider = &image_provider; raster_source->PlaybackToCanvas( - &canvas, gfx::ColorSpace(), - raster_source->GetContentSize(contents_scale), content_rect, + &canvas, raster_source->GetContentSize(contents_scale), content_rect, content_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), settings); diff --git a/chromium/cc/debug/debug_colors.cc b/chromium/cc/debug/debug_colors.cc index eef3fcb7bd6..d8fc52a0da8 100644 --- a/chromium/cc/debug/debug_colors.cc +++ b/chromium/cc/debug/debug_colors.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/logging.h" -#include "base/macros.h" #include "cc/debug/debug_colors.h" diff --git a/chromium/cc/debug/debug_colors.h b/chromium/cc/debug/debug_colors.h index d45e0dc0909..69a73b1d47d 100644 --- a/chromium/cc/debug/debug_colors.h +++ b/chromium/cc/debug/debug_colors.h @@ -6,7 +6,6 @@ #define CC_DEBUG_DEBUG_COLORS_H_ #include "base/containers/span.h" -#include "base/macros.h" #include "cc/debug/debug_export.h" #include "third_party/skia/include/core/SkColor.h" @@ -14,6 +13,8 @@ namespace cc { class CC_DEBUG_EXPORT DebugColors { public: + DebugColors() = delete; + static SkColor TiledContentLayerBorderColor(); static int TiledContentLayerBorderWidth(float device_scale_factor); @@ -119,9 +120,6 @@ class CC_DEBUG_EXPORT DebugColors { static SkColor FPSDisplayTextAndGraphColor(); static SkColor MemoryDisplayTextColor(); static SkColor PaintTimeDisplayTextAndGraphColor(); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(DebugColors); }; } // namespace cc diff --git a/chromium/cc/debug/rendering_stats_instrumentation.h b/chromium/cc/debug/rendering_stats_instrumentation.h index 3f656dbe8d8..98ba79b0526 100644 --- a/chromium/cc/debug/rendering_stats_instrumentation.h +++ b/chromium/cc/debug/rendering_stats_instrumentation.h @@ -9,7 +9,6 @@ #include <memory> -#include "base/macros.h" #include "base/synchronization/lock.h" #include "cc/debug/rendering_stats.h" @@ -20,8 +19,12 @@ namespace cc { class CC_DEBUG_EXPORT RenderingStatsInstrumentation { public: static std::unique_ptr<RenderingStatsInstrumentation> Create(); + RenderingStatsInstrumentation(const RenderingStatsInstrumentation&) = delete; virtual ~RenderingStatsInstrumentation(); + RenderingStatsInstrumentation& operator=( + const RenderingStatsInstrumentation&) = delete; + // Return copy of current impl thread rendering stats, and resets the current // stats. RenderingStats TakeImplThreadRenderingStats(); @@ -58,8 +61,6 @@ class CC_DEBUG_EXPORT RenderingStatsInstrumentation { bool record_rendering_stats_; base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(RenderingStatsInstrumentation); }; } // namespace cc diff --git a/chromium/cc/input/browser_controls_offset_manager.h b/chromium/cc/input/browser_controls_offset_manager.h index 8d0435d2808..af00d337961 100644 --- a/chromium/cc/input/browser_controls_offset_manager.h +++ b/chromium/cc/input/browser_controls_offset_manager.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/time/time.h" #include "cc/input/browser_controls_state.h" #include "cc/layers/layer_impl.h" @@ -27,8 +26,12 @@ class CC_EXPORT BrowserControlsOffsetManager { BrowserControlsOffsetManagerClient* client, float controls_show_threshold, float controls_hide_threshold); + BrowserControlsOffsetManager(const BrowserControlsOffsetManager&) = delete; virtual ~BrowserControlsOffsetManager(); + BrowserControlsOffsetManager& operator=(const BrowserControlsOffsetManager&) = + delete; + // The offset from the window top to the top edge of the controls. Runs from 0 // (controls fully shown) to negative values (down is positive). float ControlsTopOffset() const; @@ -115,8 +118,6 @@ class CC_EXPORT BrowserControlsOffsetManager { // Used to track whether the constraint has changed and we need up reflect // the changes to Blink. bool constraint_changed_since_commit_; - - DISALLOW_COPY_AND_ASSIGN(BrowserControlsOffsetManager); }; } // namespace cc diff --git a/chromium/cc/input/input_handler.cc b/chromium/cc/input/input_handler.cc index 336d0d4896d..7105340cbbe 100644 --- a/chromium/cc/input/input_handler.cc +++ b/chromium/cc/input/input_handler.cc @@ -10,4 +10,6 @@ InputHandlerScrollResult::InputHandlerScrollResult() : did_scroll(false), did_overscroll_root(false) { } +InputHandlerPointerResult::InputHandlerPointerResult() : type(kUnhandled) {} + } // namespace cc diff --git a/chromium/cc/input/input_handler.h b/chromium/cc/input/input_handler.h index e8626f8d32d..6b39c27ef56 100644 --- a/chromium/cc/input/input_handler.h +++ b/chromium/cc/input/input_handler.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/input/event_listener_properties.h" @@ -34,6 +33,26 @@ namespace cc { class ScrollElasticityHelper; +enum PointerResultType { kUnhandled = 0, kScrollbarScroll }; + +struct CC_EXPORT InputHandlerPointerResult { + InputHandlerPointerResult(); + // Tells what type of processing occurred in the input handler as a result of + // the pointer event. + PointerResultType type; + + // If the input handler processed the event as a scrollbar scroll, it will + // return a gfx::ScrollOffset that produces the necessary scroll. However, + // it is still the client's responsibility to generate the gesture scrolls + // 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::ScrollOffset scroll_offset; + + // TODO(arakeri): Extend this structure to contain scroll_units and + // element_id. For now, assume kPrecisePixels and root layer scroll. +}; + struct CC_EXPORT InputHandlerScrollResult { InputHandlerScrollResult(); // Did any layer scroll as a result this ScrollBy call? @@ -59,7 +78,10 @@ struct CC_EXPORT InputHandlerScrollResult { class CC_EXPORT InputHandlerClient { public: - virtual ~InputHandlerClient() {} + InputHandlerClient(const InputHandlerClient&) = delete; + virtual ~InputHandlerClient() = default; + + InputHandlerClient& operator=(const InputHandlerClient&) = delete; virtual void WillShutdown() = 0; virtual void Animate(base::TimeTicks time) = 0; @@ -74,10 +96,7 @@ class CC_EXPORT InputHandlerClient { virtual void DeliverInputForBeginFrame() = 0; protected: - InputHandlerClient() {} - - private: - DISALLOW_COPY_AND_ASSIGN(InputHandlerClient); + InputHandlerClient() = default; }; // The InputHandler is a way for the embedders to interact with the impl thread @@ -96,6 +115,9 @@ class CC_EXPORT InputHandler { LAST_SCROLL_STATUS = SCROLL_UNKNOWN }; + InputHandler(const InputHandler&) = delete; + InputHandler& operator=(const InputHandler&) = delete; + struct ScrollStatus { ScrollStatus() : thread(SCROLL_ON_IMPL_THREAD), @@ -110,7 +132,13 @@ class CC_EXPORT InputHandler { bool bubble; }; - enum ScrollInputType { TOUCHSCREEN, WHEEL, AUTOSCROLL, SCROLL_INPUT_UNKNOWN }; + enum ScrollInputType { + TOUCHSCREEN, + WHEEL, + AUTOSCROLL, + SCROLLBAR, + SCROLL_INPUT_UNKNOWN + }; enum class TouchStartOrMoveEventListenerType { NO_HANDLER, @@ -161,8 +189,10 @@ class CC_EXPORT InputHandler { virtual InputHandlerScrollResult ScrollBy(ScrollState* scroll_state) = 0; virtual void MouseMoveAt(const gfx::Point& mouse_position) = 0; - virtual void MouseDown() = 0; - virtual void MouseUp() = 0; + virtual InputHandlerPointerResult MouseDown( + const gfx::PointF& mouse_position) = 0; + virtual InputHandlerPointerResult MouseUp( + const gfx::PointF& mouse_position) = 0; virtual void MouseLeave() = 0; // Stop scrolling the selected layer. Should only be called if ScrollBegin() @@ -244,11 +274,8 @@ class CC_EXPORT InputHandler { gfx::Vector2dF* target_offset) const = 0; protected: - InputHandler() {} - virtual ~InputHandler() {} - - private: - DISALLOW_COPY_AND_ASSIGN(InputHandler); + InputHandler() = default; + virtual ~InputHandler() = default; }; } // namespace cc diff --git a/chromium/cc/input/main_thread_scrolling_reason.cc b/chromium/cc/input/main_thread_scrolling_reason.cc index 5d1a6b9c5a9..4b5cac239f0 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.cc +++ b/chromium/cc/input/main_thread_scrolling_reason.cc @@ -39,8 +39,6 @@ void MainThreadScrollingReason::AddToTracedValue( traced_value.AppendString("Frame overlay"); if (reasons & kHandlingScrollFromMainThread) traced_value.AppendString("Handling scroll from main thread"); - if (reasons & kCustomScrollbarScrolling) - traced_value.AppendString("Custom scrollbar scrolling"); if (reasons & kHasOpacityAndLCDText) traced_value.AppendString("Has opacity and LCD text"); if (reasons & kHasTransformAndLCDText) diff --git a/chromium/cc/input/main_thread_scrolling_reason.h b/chromium/cc/input/main_thread_scrolling_reason.h index 6878928bfe7..cf7e840b2be 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.h +++ b/chromium/cc/input/main_thread_scrolling_reason.h @@ -36,7 +36,6 @@ struct CC_EXPORT MainThreadScrollingReason { // animation. Note that a scroll handled by the main thread can result in an // animation running on the main thread or on the compositor thread. kHandlingScrollFromMainThread = 1 << 13, - kCustomScrollbarScrolling = 1 << 15, // Style-related scrolling on main reasons. // These *AndLCDText reasons are due to subpixel text rendering which can @@ -80,8 +79,7 @@ struct CC_EXPORT MainThreadScrollingReason { uint32_t reasons_set_by_main_thread = kNotScrollingOnMain | kHasBackgroundAttachmentFixedObjects | kHasNonLayerViewportConstrainedObjects | kThreadedScrollingDisabled | - kScrollbarScrolling | kFrameOverlay | kHandlingScrollFromMainThread | - kCustomScrollbarScrolling; + kScrollbarScrolling | kFrameOverlay | kHandlingScrollFromMainThread; return (reasons & reasons_set_by_main_thread) == reasons; } diff --git a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc index c6ab9e4a61f..3970af2eade 100644 --- a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc +++ b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc @@ -19,7 +19,6 @@ TEST_F(MainThreadScrollingReasonTest, AsText) { "Scrollbar scrolling," "Frame overlay," "Handling scroll from main thread," - "Custom scrollbar scrolling," "Has opacity and LCD text," "Has transform and LCD text," "Background is not opaque in rect and LCD text," diff --git a/chromium/cc/input/page_scale_animation.h b/chromium/cc/input/page_scale_animation.h index 9d66923e76b..be4515a2c1e 100644 --- a/chromium/cc/input/page_scale_animation.h +++ b/chromium/cc/input/page_scale_animation.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "ui/gfx/geometry/cubic_bezier.h" @@ -51,8 +50,11 @@ class CC_EXPORT PageScaleAnimation { const gfx::SizeF& viewport_size, const gfx::SizeF& root_layer_size); + PageScaleAnimation(const PageScaleAnimation&) = delete; ~PageScaleAnimation(); + PageScaleAnimation& operator=(const PageScaleAnimation&) = delete; + // The following methods initialize the animation. Call one of them // immediately after construction to set the final scroll and page scale. @@ -123,8 +125,6 @@ class CC_EXPORT PageScaleAnimation { base::TimeDelta duration_; const gfx::CubicBezier timing_function_; - - DISALLOW_COPY_AND_ASSIGN(PageScaleAnimation); }; } // namespace cc diff --git a/chromium/cc/input/scroll_snap_data.cc b/chromium/cc/input/scroll_snap_data.cc index de776f31f7c..b09ded1e84f 100644 --- a/chromium/cc/input/scroll_snap_data.cc +++ b/chromium/cc/input/scroll_snap_data.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/input/scroll_snap_data.h" +#include "base/numerics/ranges.h" #include "cc/input/snap_selection_strategy.h" #include <algorithm> @@ -61,10 +62,10 @@ void SnapSearchResult::set_visible_range(const gfx::RangeF& range) { } void SnapSearchResult::Clip(float max_snap, float max_visible) { - snap_offset_ = std::max(std::min(snap_offset_, max_snap), 0.0f); + snap_offset_ = base::ClampToRange(snap_offset_, 0.0f, max_snap); visible_range_ = - gfx::RangeF(std::max(std::min(visible_range_.start(), max_visible), 0.0f), - std::max(std::min(visible_range_.end(), max_visible), 0.0f)); + gfx::RangeF(base::ClampToRange(visible_range_.start(), 0.0f, max_visible), + base::ClampToRange(visible_range_.end(), 0.0f, max_visible)); } void SnapSearchResult::Union(const SnapSearchResult& other) { @@ -124,16 +125,20 @@ bool SnapContainerData::FindSnapPosition( // A region that includes every reachable scroll position. gfx::RectF scrollable_region(0, 0, max_position_.x(), max_position_.y()); if (should_snap_on_x) { - // Start from current position in the cross axis and assume it's always - // visible. + // Start from current position in the cross axis. The search algorithm + // expects the cross axis position to be inside scroller bounds. But since + // we cannot always assume that the incoming value fits this criteria we + // clamp it to the bounds to ensure this variant. SnapSearchResult initial_snap_position_y = { - base_position.y(), gfx::RangeF(0, max_position_.x())}; + base::ClampToRange(base_position.y(), 0.f, max_position_.y()), + gfx::RangeF(0, max_position_.x())}; closest_x = FindClosestValidArea(SearchAxis::kX, strategy, initial_snap_position_y); } if (should_snap_on_y) { SnapSearchResult initial_snap_position_x = { - base_position.x(), gfx::RangeF(0, max_position_.y())}; + base::ClampToRange(base_position.x(), 0.f, max_position_.x()), + gfx::RangeF(0, max_position_.y())}; closest_y = FindClosestValidArea(SearchAxis::kY, strategy, initial_snap_position_x); } @@ -170,9 +175,9 @@ bool SnapContainerData::FindSnapPosition( base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea( SearchAxis axis, const SnapSelectionStrategy& strategy, - const SnapSearchResult& cros_axis_snap_result) const { + const SnapSearchResult& cross_axis_snap_result) const { base::Optional<SnapSearchResult> result = - FindClosestValidAreaInternal(axis, strategy, cros_axis_snap_result); + FindClosestValidAreaInternal(axis, strategy, cross_axis_snap_result); // For EndAndDirectionStrategy, if there is a snap area with snap-stop:always, // and is between the starting position and the above result, we should choose @@ -189,7 +194,7 @@ base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea( SnapStopAlwaysFilter::kRequire); base::Optional<SnapSearchResult> must_only_result = FindClosestValidAreaInternal(axis, *must_only_strategy, - cros_axis_snap_result, false); + cross_axis_snap_result, false); result = ClosestSearchResult(strategy.current_position(), axis, result, must_only_result); } @@ -209,15 +214,21 @@ base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea( strategy.ShouldSnapOnX(), strategy.ShouldSnapOnY()); return FindClosestValidAreaInternal(axis, *relaxed_strategy, - cros_axis_snap_result); + cross_axis_snap_result); } base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidAreaInternal( SearchAxis axis, const SnapSelectionStrategy& strategy, - const SnapSearchResult& cros_axis_snap_result, + const SnapSearchResult& cross_axis_snap_result, bool should_consider_covering) const { + // The cross axis result is expected to be within bounds otherwise no snap + // area will meet the mutual visibility requirement. + DCHECK(cross_axis_snap_result.snap_offset() >= 0 && + cross_axis_snap_result.snap_offset() <= + (axis == SearchAxis::kX ? max_position_.y() : max_position_.x())); + // The search result from the snap area that's closest to the search origin. base::Optional<SnapSearchResult> closest; // The search result with the intended position if it makes a snap area cover @@ -251,7 +262,7 @@ SnapContainerData::FindClosestValidAreaInternal( // position as a valid snap position. SnapSearchResult covering_candidate = candidate; covering_candidate.set_snap_offset(intended_position); - if (IsMutualVisible(covering_candidate, cros_axis_snap_result)) + if (IsMutualVisible(covering_candidate, cross_axis_snap_result)) SetOrUpdateResult(covering_candidate, &covering); // Even if a snap area covers the snapport, we need to continue this // search to find previous and next snap positions and also to have @@ -259,7 +270,7 @@ SnapContainerData::FindClosestValidAreaInternal( // rejected. And this covering snap area has its own alignment that may // generates a snap position rejecting the current inplace candidate. } - if (!IsMutualVisible(candidate, cros_axis_snap_result)) + if (!IsMutualVisible(candidate, cross_axis_snap_result)) continue; float distance = std::abs(candidate.snap_offset() - base_position); diff --git a/chromium/cc/input/scrollbar.h b/chromium/cc/input/scrollbar.h index ab67bce81c0..bd785ff779b 100644 --- a/chromium/cc/input/scrollbar.h +++ b/chromium/cc/input/scrollbar.h @@ -10,13 +10,21 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" +static const int kPixelsPerLineStep = 40; + namespace cc { enum ScrollbarOrientation { HORIZONTAL, VERTICAL }; enum ScrollDirection { SCROLL_BACKWARD, SCROLL_FORWARD }; -// For now, TRACK includes everything but the thumb including background and -// buttons. -enum ScrollbarPart { THUMB, TRACK, TICKMARKS }; + +enum ScrollbarPart { + THUMB, + TRACK, + TICKMARKS, + BACK_BUTTON, + FORWARD_BUTTON, + NO_PART +}; class Scrollbar { public: @@ -30,6 +38,8 @@ class Scrollbar { virtual int ThumbThickness() const = 0; virtual int ThumbLength() const = 0; virtual gfx::Rect TrackRect() const = 0; + virtual gfx::Rect BackButtonRect() const = 0; + virtual gfx::Rect ForwardButtonRect() const = 0; virtual float ThumbOpacity() const = 0; virtual bool HasTickmarks() const = 0; virtual bool NeedsPaintPart(ScrollbarPart part) const = 0; diff --git a/chromium/cc/input/scrollbar_controller.cc b/chromium/cc/input/scrollbar_controller.cc new file mode 100644 index 00000000000..403d3ceaaf8 --- /dev/null +++ b/chromium/cc/input/scrollbar_controller.cc @@ -0,0 +1,89 @@ +// Copyright 2019 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/scrollbar_layer_impl_base.h" + +#include <algorithm> + +#include "cc/input/scrollbar.h" +#include "cc/input/scrollbar_controller.h" +#include "cc/trees/layer_tree_impl.h" + +namespace cc { +ScrollbarController::ScrollbarController( + LayerTreeHostImpl* layer_tree_host_impl) + : layer_tree_host_impl_(layer_tree_host_impl), + scrollbar_scroll_is_active_(false) {} + +// Performs hit test and prepares scroll deltas that will be used by GSB and +// GSU. +InputHandlerPointerResult ScrollbarController::HandleMouseDown( + const gfx::PointF position_in_widget) { + InputHandlerPointerResult scroll_result; + LayerImpl* layer_impl = GetLayerHitByPoint(position_in_widget); + if (layer_impl && layer_impl->is_scrollbar()) { + scrollbar_scroll_is_active_ = true; + scroll_result.type = PointerResultType::kScrollbarScroll; + scroll_result.scroll_offset = + GetScrollStateBasedOnHitTest(layer_impl, position_in_widget); + } + return scroll_result; +} + +// Performs hit test and prepares scroll deltas that will be used by GSE. +InputHandlerPointerResult ScrollbarController::HandleMouseUp( + const gfx::PointF position_in_widget) { + InputHandlerPointerResult scroll_result; + if (scrollbar_scroll_is_active_) { + scrollbar_scroll_is_active_ = false; + scroll_result.type = PointerResultType::kScrollbarScroll; + } + return scroll_result; +} + +// Returns the layer that is hit by the position_in_widget. +LayerImpl* ScrollbarController::GetLayerHitByPoint( + const gfx::PointF position_in_widget) { + LayerTreeImpl* active_tree = layer_tree_host_impl_->active_tree(); + gfx::Point viewport_point(position_in_widget.x(), position_in_widget.y()); + + gfx::PointF device_viewport_point = gfx::ScalePoint( + gfx::PointF(viewport_point), active_tree->device_scale_factor()); + LayerImpl* layer_impl = + active_tree->FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( + device_viewport_point); + + return layer_impl; +} + +// Determines the scroll offsets based on hit test results. +gfx::ScrollOffset ScrollbarController::GetScrollStateBasedOnHitTest( + const LayerImpl* scrollbar_layer_impl, + const gfx::PointF position_in_widget) { + const ScrollbarLayerImplBase* scrollbar_layer = + static_cast<const ScrollbarLayerImplBase*>(scrollbar_layer_impl); + const ScrollbarOrientation orientation = scrollbar_layer->orientation(); + + ScrollbarPart scrollbar_part = + scrollbar_layer->IdentifyScrollbarPart(position_in_widget); + + float scroll_delta = + layer_tree_host_impl_->active_tree()->device_scale_factor() * + kPixelsPerLineStep; + + // See CreateScrollStateForGesture for more information on how these values + // will be interpreted. + if (scrollbar_part == ScrollbarPart::BACK_BUTTON) { + return orientation == ScrollbarOrientation::VERTICAL + ? gfx::ScrollOffset(0, -scroll_delta) // Up arrow + : gfx::ScrollOffset(-scroll_delta, 0); // Left arrow + } else if (scrollbar_part == ScrollbarPart::FORWARD_BUTTON) { + return orientation == ScrollbarOrientation::VERTICAL + ? gfx::ScrollOffset(0, scroll_delta) // Down arrow + : gfx::ScrollOffset(scroll_delta, 0); // Right arrow + } + return gfx::ScrollOffset(0, 0); +} + +} // namespace cc diff --git a/chromium/cc/input/scrollbar_controller.h b/chromium/cc/input/scrollbar_controller.h new file mode 100644 index 00000000000..0434f78bd11 --- /dev/null +++ b/chromium/cc/input/scrollbar_controller.h @@ -0,0 +1,40 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_INPUT_SCROLLBAR_CONTROLLER_H_ +#define CC_INPUT_SCROLLBAR_CONTROLLER_H_ + +#include "cc/cc_export.h" +#include "cc/input/input_handler.h" +#include "cc/input/scrollbar.h" +#include "cc/layers/layer_impl.h" +#include "cc/layers/painted_scrollbar_layer_impl.h" + +namespace cc { + +// This class is responsible for hit testing composited scrollbars, event +// handling and creating gesture scroll deltas. +class CC_EXPORT ScrollbarController { + public: + explicit ScrollbarController(LayerTreeHostImpl*); + virtual ~ScrollbarController() = default; + + InputHandlerPointerResult HandleMouseDown( + const gfx::PointF position_in_widget); + InputHandlerPointerResult HandleMouseUp(const gfx::PointF position_in_widget); + + private: + // Returns a gfx::ScrollOffset object which contains scroll deltas for the + // synthetic Gesture events. + gfx::ScrollOffset GetScrollStateBasedOnHitTest( + const LayerImpl* scrollbar_layer_impl, + const gfx::PointF position_in_widget); + LayerImpl* GetLayerHitByPoint(const gfx::PointF position_in_widget); + LayerTreeHostImpl* layer_tree_host_impl_; + bool scrollbar_scroll_is_active_; +}; + +} // namespace cc + +#endif // CC_INPUT_SCROLLBAR_CONTROLLER_H_ diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning.h b/chromium/cc/input/single_scrollbar_animation_controller_thinning.h index 20c06835b3e..80a267db105 100644 --- a/chromium/cc/input/single_scrollbar_animation_controller_thinning.h +++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" @@ -31,7 +30,12 @@ class CC_EXPORT SingleScrollbarAnimationControllerThinning { ScrollbarAnimationControllerClient* client, base::TimeDelta thinning_duration); - ~SingleScrollbarAnimationControllerThinning() {} + SingleScrollbarAnimationControllerThinning( + const SingleScrollbarAnimationControllerThinning&) = delete; + ~SingleScrollbarAnimationControllerThinning() = default; + + SingleScrollbarAnimationControllerThinning& operator=( + const SingleScrollbarAnimationControllerThinning&) = delete; bool mouse_is_over_scrollbar_thumb() const { return mouse_is_over_scrollbar_thumb_; @@ -96,8 +100,6 @@ class CC_EXPORT SingleScrollbarAnimationControllerThinning { AnimationChange thickness_change_; base::TimeDelta thinning_duration_; - - DISALLOW_COPY_AND_ASSIGN(SingleScrollbarAnimationControllerThinning); }; } // namespace cc diff --git a/chromium/cc/input/snap_fling_controller.h b/chromium/cc/input/snap_fling_controller.h index eb07106796c..c5ad511d91c 100644 --- a/chromium/cc/input/snap_fling_controller.h +++ b/chromium/cc/input/snap_fling_controller.h @@ -53,8 +53,11 @@ class CC_EXPORT SnapFlingController { SnapFlingClient* client, std::unique_ptr<SnapFlingCurve> curve); + SnapFlingController(const SnapFlingController&) = delete; ~SnapFlingController(); + SnapFlingController& operator=(const SnapFlingController&) = delete; + // Returns true if the event should be consumed for snapping and should not be // processed further. bool FilterEventForSnap(GestureScrollType gesture_scroll_type); @@ -97,8 +100,6 @@ class CC_EXPORT SnapFlingController { SnapFlingClient* client_; State state_ = State::kIdle; std::unique_ptr<SnapFlingCurve> curve_; - - DISALLOW_COPY_AND_ASSIGN(SnapFlingController); }; } // namespace cc diff --git a/chromium/cc/layers/deadline_policy.h b/chromium/cc/layers/deadline_policy.h index 268ca233b98..6c3b0063046 100644 --- a/chromium/cc/layers/deadline_policy.h +++ b/chromium/cc/layers/deadline_policy.h @@ -8,7 +8,6 @@ #include <cstdint> #include "base/logging.h" -#include "base/macros.h" #include "base/optional.h" #include "cc/cc_export.h" diff --git a/chromium/cc/layers/draw_properties.h b/chromium/cc/layers/draw_properties.h index f5c7a6cfead..1b96435e988 100644 --- a/chromium/cc/layers/draw_properties.h +++ b/chromium/cc/layers/draw_properties.h @@ -11,6 +11,7 @@ #include "cc/trees/occlusion.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/rrect_f.h" #include "ui/gfx/transform.h" namespace cc { @@ -44,6 +45,10 @@ struct CC_EXPORT DrawProperties { // True if the layer needs to be clipped by clip_rect. bool is_clipped; + // If set, it makes the layer's rounded corner not trigger a render surface if + // possible. + bool is_fast_rounded_corner; + // This rect is a bounding box around what part of the layer is visible, in // the layer's coordinate space. gfx::Rect visible_layer_rect; @@ -55,6 +60,10 @@ struct CC_EXPORT DrawProperties { // In target surface space, the original rect that clipped this layer. This // value is used to avoid unnecessarily changing GL scissor state. gfx::Rect clip_rect; + + // Contains a rounded corner rect to clip this layer when drawing. This rrect + // is in the target space of the layer. + gfx::RRectF rounded_corner_bounds; }; } // namespace cc diff --git a/chromium/cc/layers/heads_up_display_layer.h b/chromium/cc/layers/heads_up_display_layer.h index 2936a975c80..1337fb639fb 100644 --- a/chromium/cc/layers/heads_up_display_layer.h +++ b/chromium/cc/layers/heads_up_display_layer.h @@ -8,7 +8,6 @@ #include <memory> #include <string> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "third_party/skia/include/core/SkRefCnt.h" @@ -20,6 +19,9 @@ class CC_EXPORT HeadsUpDisplayLayer : public Layer { public: static scoped_refptr<HeadsUpDisplayLayer> Create(); + HeadsUpDisplayLayer(const HeadsUpDisplayLayer&) = delete; + HeadsUpDisplayLayer& operator=(const HeadsUpDisplayLayer&) = delete; + void UpdateLocationAndSize(const gfx::Size& device_viewport, float device_scale_factor); @@ -36,8 +38,6 @@ class CC_EXPORT HeadsUpDisplayLayer : public Layer { ~HeadsUpDisplayLayer() override; sk_sp<SkTypeface> typeface_; - - DISALLOW_COPY_AND_ASSIGN(HeadsUpDisplayLayer); }; } // namespace cc diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc index 16705fa8ab0..0a9ea808774 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl.cc @@ -378,7 +378,8 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture( { ScopedGpuRaster gpu_raster(context_provider); viz::ClientResourceProvider::ScopedSkSurface scoped_surface( - context_provider->GrContext(), mailbox_texture_id, + context_provider->GrContext(), + pool_resource.color_space().ToSkColorSpace(), mailbox_texture_id, backing->texture_target, pool_resource.size(), pool_resource.format(), false /* can_use_lcd_text */, 0 /* msaa_sample_count */); @@ -838,8 +839,8 @@ SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(PaintCanvas* canvas, const SkScalar pos[] = {SkFloatToScalar(0.2f), SkFloatToScalar(0.4f), SkFloatToScalar(0.6f), SkFloatToScalar(0.8f), SkFloatToScalar(1.0f)}; - flags.setShader(PaintShader::MakeSweepGradient( - cx, cy, colors, pos, 5, SkShader::kClamp_TileMode, 0, 360)); + flags.setShader(PaintShader::MakeSweepGradient(cx, cy, colors, pos, 5, + SkTileMode::kClamp, 0, 360)); flags.setAntiAlias(true); // Draw current status. diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h index 0315c2c7295..7f209eb7267 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.h +++ b/chromium/cc/layers/heads_up_display_layer_impl.h @@ -9,7 +9,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/time/time.h" #include "cc/cc_export.h" @@ -41,8 +40,11 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl { int id) { return base::WrapUnique(new HeadsUpDisplayLayerImpl(tree_impl, id)); } + HeadsUpDisplayLayerImpl(const HeadsUpDisplayLayerImpl&) = delete; ~HeadsUpDisplayLayerImpl() override; + HeadsUpDisplayLayerImpl& operator=(const HeadsUpDisplayLayerImpl&) = delete; + std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; bool WillDraw(DrawMode draw_mode, @@ -157,8 +159,6 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl { std::vector<DebugRect> paint_rects_; base::TimeTicks time_of_last_graph_update_; - - DISALLOW_COPY_AND_ASSIGN(HeadsUpDisplayLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc index 3aab7c86a71..54907feef3d 100644 --- a/chromium/cc/layers/layer.cc +++ b/chromium/cc/layers/layer.cc @@ -8,6 +8,8 @@ #include <stdint.h> #include <algorithm> +#include <utility> +#include <vector> #include "base/atomic_sequence_num.h" #include "base/location.h" @@ -45,7 +47,7 @@ Layer::Inputs::Inputs(int layer_id) opacity(1.f), blend_mode(SkBlendMode::kSrcOver), is_root_for_isolated_group(false), - hit_testable_without_draws_content(false), + hit_testable(false), contents_opaque(false), is_drawable(false), double_sided(true), @@ -55,6 +57,7 @@ Layer::Inputs::Inputs(int layer_id) background_color(0), backdrop_filter_quality(1.0f), corner_radii({0, 0, 0, 0}), + is_fast_rounded_corner(false), scrollable(false), is_scrollbar(false), user_scrollable_horizontal(true), @@ -271,6 +274,27 @@ void Layer::RemoveChildOrDependent(Layer* child) { } } +void Layer::ReorderChildren(LayerList* new_children_order) { +#if DCHECK_IS_ON() + base::flat_set<Layer*> children_set; + for (const auto& child : *new_children_order) { + DCHECK_EQ(child->parent(), this); + children_set.insert(child.get()); + } + for (const auto& child : inputs_.children) + DCHECK_GT(children_set.count(child.get()), 0u); +#endif + inputs_.children = std::move(*new_children_order); + + // We do not need to call SetSubtreePropertyChanged for each child here + // since SetSubtreePropertyChanged includes SetNeedsPushProperties, but this + // change is not included in properties pushing. + for (const auto& child : inputs_.children) + child->subtree_property_changed_ = true; + + SetNeedsFullTreeSync(); +} + void Layer::ReplaceChild(Layer* reference, scoped_refptr<Layer> new_layer) { DCHECK(reference); DCHECK_EQ(reference->parent(), this); @@ -602,6 +626,22 @@ void Layer::SetRoundedCorner(const std::array<uint32_t, 4>& corner_radii) { SetPropertyTreesNeedRebuild(); } +void Layer::SetIsFastRoundedCorner(bool enable) { + DCHECK(IsPropertyChangeAllowed()); + if (inputs_.is_fast_rounded_corner == enable) + return; + inputs_.is_fast_rounded_corner = enable; + + // If this layer does not have a rounded corner, then modifying this flag is + // going to have no effect. + if (!HasRoundedCorner()) + return; + + SetSubtreePropertyChanged(); + SetNeedsCommit(); + SetPropertyTreesNeedRebuild(); +} + void Layer::SetOpacity(float opacity) { DCHECK(IsPropertyChangeAllowed()); DCHECK_GE(opacity, 0.f); @@ -701,15 +741,19 @@ void Layer::SetIsRootForIsolatedGroup(bool root) { SetNeedsCommit(); } -void Layer::SetHitTestableWithoutDrawsContent(bool should_hit_test) { +void Layer::SetHitTestable(bool should_hit_test) { DCHECK(IsPropertyChangeAllowed()); - if (inputs_.hit_testable_without_draws_content == should_hit_test) + if (inputs_.hit_testable == should_hit_test) return; - inputs_.hit_testable_without_draws_content = should_hit_test; + inputs_.hit_testable = should_hit_test; SetPropertyTreesNeedRebuild(); SetNeedsCommit(); } +bool Layer::HitTestable() const { + return inputs_.hit_testable; +} + void Layer::SetContentsOpaque(bool opaque) { DCHECK(IsPropertyChangeAllowed()); if (inputs_.contents_opaque == opaque) @@ -1286,6 +1330,11 @@ void Layer::SetNeedsDisplayRect(const gfx::Rect& dirty_rect) { } bool Layer::DescendantIsFixedToContainerLayer() const { + // Because position constraints are not set when using layer lists (see: + // Layer::SetPositionConstraint), this should only be called when not using + // layer lists. + DCHECK(!layer_tree_host_ || !layer_tree_host_->IsUsingLayerLists()); + for (size_t i = 0; i < inputs_.children.size(); ++i) { if (inputs_.children[i]->inputs_.position_constraint.is_fixed_position() || inputs_.children[i]->DescendantIsFixedToContainerLayer()) @@ -1307,6 +1356,11 @@ bool Layer::IsResizedByBrowserControls() const { } void Layer::SetIsContainerForFixedPositionLayers(bool container) { + // |inputs_.is_container_for_fixed_position_layers| is only used by the cc + // property tree builder to build property trees and is not needed when using + // layer lists. + DCHECK(!layer_tree_host_ || !layer_tree_host_->IsUsingLayerLists()); + if (inputs_.is_container_for_fixed_position_layers == container) return; inputs_.is_container_for_fixed_position_layers = container; @@ -1322,6 +1376,10 @@ void Layer::SetIsContainerForFixedPositionLayers(bool container) { } void Layer::SetPositionConstraint(const LayerPositionConstraint& constraint) { + // Position constraints are only used by the cc property tree builder to build + // property trees and are not needed when using layer lists. + DCHECK(!layer_tree_host_ || !layer_tree_host_->IsUsingLayerLists()); + DCHECK(IsPropertyChangeAllowed()); if (inputs_.position_constraint == constraint) return; @@ -1369,8 +1427,7 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetScrollTreeIndex(scroll_tree_index()); layer->SetOffsetToTransformParent(offset_to_transform_parent_); layer->SetDrawsContent(DrawsContent()); - layer->SetHitTestableWithoutDrawsContent( - hit_testable_without_draws_content()); + layer->SetHitTestable(HitTestable()); // subtree_property_changed_ is propagated to all descendants while building // property trees. So, it is enough to check it only for the current layer. if (subtree_property_changed_) diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h index ace3acc52e0..5a2fa5bff11 100644 --- a/chromium/cc/layers/layer.h +++ b/chromium/cc/layers/layer.h @@ -15,7 +15,6 @@ #include <vector> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "cc/base/region.h" @@ -84,6 +83,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // Factory to create a new Layer, with a unique id. static scoped_refptr<Layer> Create(); + Layer(const Layer&) = delete; + Layer& operator=(const Layer&) = delete; + // Sets an optional client on this layer, that will be called when relevant // events happen. The client is a WeakPtr so it can be destroyed without // unsetting itself as the client. @@ -173,6 +175,12 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void SetPosition(const gfx::PointF& position); const gfx::PointF& position() const { return inputs_.position; } + // Reorder the entirety of the children() vector to follow new_children_order. + // All elements inside new_children_order must be inside children(), and vice + // versa. Will empty the |new_children_order| LayerList passed into this + // method. + void ReorderChildren(LayerList* new_children_order); + // Set and get the layers bounds. This is specified in layer space, which // excludes device scale and page scale factors, and ignoring transforms for // this layer or ancestor layers. @@ -223,7 +231,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // for each matching pixel. void SetMaskLayer(PictureLayer* mask_layer); PictureLayer* mask_layer() { return inputs_.mask_layer.get(); } - const PictureLayer* mask_layer() const { return inputs_.mask_layer.get(); } // Marks the |dirty_rect| as being changed, which will cause a commit and // the compositor to submit a new frame with a damage rect that includes the @@ -247,6 +254,19 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { return inputs_.corner_radii; } + // Returns true if any of the corner has a non-zero radius set. + bool HasRoundedCorner() const { + return corner_radii()[0] + corner_radii()[1] + corner_radii()[2] + + corner_radii()[3]; + } + + // Set or get the flag that disables the requirement of a render surface for + // this layer due to it having rounded corners. This improves performance at + // the cost of maybe having some blending artifacts. Not having a render + // surface is not guaranteed however. + void SetIsFastRoundedCorner(bool enable); + bool is_fast_rounded_corner() const { return inputs_.is_fast_rounded_corner; } + // Set or get the opacity which should be applied to the contents of the layer // and its subtree (together as a single composited entity) when blending them // into their target. Note that this does not speak to the contents of this @@ -315,15 +335,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void SetContentsOpaque(bool opaque); bool contents_opaque() const { return inputs_.contents_opaque; } - // Set or get whether this layer should be a hit test target even if not - // visible. Normally if DrawsContent() is false, making the layer not - // contribute to the final composited output, the layer will not be eligable - // for hit testing since it is invisible. Set this to true to allow the layer - // to be hit tested regardless. - void SetHitTestableWithoutDrawsContent(bool should_hit_test); - bool hit_testable_without_draws_content() const { - return inputs_.hit_testable_without_draws_content; - } + // Set or get whether this layer should be a hit test target + void SetHitTestable(bool should_hit_test); + bool HitTestable() const; // Set or gets if this layer is a container for fixed position layers in its // subtree. Such layers will be positioned and transformed relative to this @@ -340,6 +354,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // of the layer are fixed to the same edges of the container ancestor. When // fixed position, this layer's transform will be appended to the container // ancestor's transform instead of to this layer's direct parent's. + // Position constraints are only used by the cc property tree builder to build + // property trees and are not needed when using layer lists. void SetPositionConstraint(const LayerPositionConstraint& constraint); const LayerPositionConstraint& position_constraint() const { return inputs_.position_constraint; @@ -362,6 +378,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // IsContainerForFixedPositionLayers() is true for this layer, these set and // get whether fixed position descendants of this layer should have this // adjustment to their position applied during such a viewport resize. + // This value is only used by the cc property tree builder to build property + // trees and is not needed when using layer lists. void SetIsResizedByBrowserControls(bool resized); bool IsResizedByBrowserControls() const; @@ -890,12 +908,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // they are marked as needing to be rebuilt. void UpdateScrollOffset(const gfx::ScrollOffset&); - // Returns true if any of the corner has a non-zero radius set. - bool HasRoundedCorner() const { - return corner_radii()[0] + corner_radii()[1] + corner_radii()[2] + - corner_radii()[3]; - } - // Encapsulates all data, callbacks or interfaces received from the embedder. struct Inputs { explicit Inputs(int layer_id); @@ -917,10 +929,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { bool is_root_for_isolated_group : 1; - // Hit testing depends on draws_content (see: |LayerImpl::should_hit_test|) - // and this bit can be set to cause the LayerImpl to be hit testable without - // draws_content. - bool hit_testable_without_draws_content : 1; + // Hit testing depends on this bit. + bool hit_testable : 1; bool contents_opaque : 1; @@ -952,6 +962,10 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // top left, top right, bottom right, bottom left std::array<uint32_t, 4> corner_radii; + // If set, disables this layer's rounded corner from triggering a render + // surface on itself if possible. + bool is_fast_rounded_corner : 1; + gfx::ScrollOffset scroll_offset; // Size of the scroll container that this layer scrolls in. @@ -980,6 +994,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // layer. In the case of a non-default rootScroller, all iframes in the // rootScroller ancestor chain will also have it set on their scroll // layers. + // TODO(pdr): These values are only used by blink and only when blink does + // not generate property trees. Remove these values when + // BlinkGenPropertyTrees ships. bool is_resized_by_browser_controls : 1; bool is_container_for_fixed_position_layers : 1; LayerPositionConstraint position_constraint; @@ -1043,8 +1060,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { int owner_node_id_; std::unique_ptr<std::set<Layer*>> clip_children_; - - DISALLOW_COPY_AND_ASSIGN(Layer); }; } // namespace cc diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc index b036dd80344..36a262b3c93 100644 --- a/chromium/cc/layers/layer_impl.cc +++ b/chromium/cc/layers/layer_impl.cc @@ -63,7 +63,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, should_check_backface_visibility_(false), draws_content_(false), contributes_to_drawn_render_surface_(false), - hit_testable_without_draws_content_(false), + hit_testable_(false), is_resized_by_browser_controls_(false), viewport_layer_type_(NOT_VIEWPORT_LAYER), background_color_(0), @@ -139,12 +139,14 @@ void LayerImpl::PopulateSharedQuadState(viz::SharedQuadState* state, bool contents_opaque) const { EffectNode* effect_node = GetEffectTree().Node(effect_tree_index_); state->SetAll(draw_properties_.target_space_transform, gfx::Rect(bounds()), - draw_properties_.visible_layer_rect, draw_properties_.clip_rect, - draw_properties_.is_clipped, contents_opaque, - draw_properties_.opacity, + draw_properties_.visible_layer_rect, + draw_properties_.rounded_corner_bounds, + draw_properties_.clip_rect, draw_properties_.is_clipped, + contents_opaque, draw_properties_.opacity, effect_node->has_render_surface ? SkBlendMode::kSrcOver : effect_node->blend_mode, GetSortingContextId()); + state->is_fast_rounded_corner = draw_properties_.is_fast_rounded_corner; } void LayerImpl::PopulateScaledSharedQuadState(viz::SharedQuadState* state, @@ -163,12 +165,14 @@ void LayerImpl::PopulateScaledSharedQuadState(viz::SharedQuadState* state, EffectNode* effect_node = GetEffectTree().Node(effect_tree_index_); state->SetAll(scaled_draw_transform, gfx::Rect(scaled_bounds), - scaled_visible_layer_rect, draw_properties().clip_rect, - draw_properties().is_clipped, contents_opaque, - draw_properties().opacity, + scaled_visible_layer_rect, + draw_properties().rounded_corner_bounds, + draw_properties().clip_rect, draw_properties().is_clipped, + contents_opaque, draw_properties().opacity, effect_node->has_render_surface ? SkBlendMode::kSrcOver : effect_node->blend_mode, GetSortingContextId()); + state->is_fast_rounded_corner = draw_properties().is_fast_rounded_corner; } bool LayerImpl::WillDraw(DrawMode draw_mode, @@ -320,8 +324,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->use_parent_backface_visibility_ = use_parent_backface_visibility_; layer->should_check_backface_visibility_ = should_check_backface_visibility_; layer->draws_content_ = draws_content_; - layer->hit_testable_without_draws_content_ = - hit_testable_without_draws_content_; + layer->hit_testable_ = hit_testable_; layer->non_fast_scrollable_region_ = non_fast_scrollable_region_; layer->touch_action_region_ = touch_action_region_; layer->wheel_event_handler_region_ = wheel_event_handler_region_; @@ -409,8 +412,7 @@ std::unique_ptr<base::DictionaryValue> LayerImpl::LayerAsJson() const { result->Set("Transform", std::move(list)); result->SetBoolean("DrawsContent", draws_content_); - result->SetBoolean("HitTestableWithoutDrawsContent", - hit_testable_without_draws_content_); + result->SetBoolean("HitTestable", hit_testable_); result->SetBoolean("Is3dSorted", Is3dSorted()); result->SetDouble("Opacity", Opacity()); result->SetBoolean("ContentsOpaque", contents_opaque_); @@ -603,20 +605,25 @@ void LayerImpl::SetDrawsContent(bool draws_content) { NoteLayerPropertyChanged(); } -void LayerImpl::SetHitTestableWithoutDrawsContent(bool should_hit_test) { - if (hit_testable_without_draws_content_ == should_hit_test) +void LayerImpl::SetHitTestable(bool should_hit_test) { + if (hit_testable_ == should_hit_test) return; - hit_testable_without_draws_content_ = should_hit_test; + hit_testable_ = should_hit_test; NoteLayerPropertyChanged(); } -bool LayerImpl::ShouldHitTest() const { - bool should_hit_test = draws_content_; - if (GetEffectTree().Node(effect_tree_index())) - should_hit_test &= - !GetEffectTree().Node(effect_tree_index())->subtree_hidden; - should_hit_test |= hit_testable_without_draws_content_; +bool LayerImpl::HitTestable() const { + EffectTree& effect_tree = GetEffectTree(); + bool should_hit_test = hit_testable_; + // TODO(sunxd): remove or refactor SetHideLayerAndSubtree, or move this logic + // to subclasses of Layer. See https://crbug.com/595843 and + // https://crbug.com/931865. + // The bit |subtree_hidden| can only be true for ui::Layers. Other layers are + // not supposed to set this bit. + if (effect_tree.Node(effect_tree_index())) { + should_hit_test &= !effect_tree.Node(effect_tree_index())->subtree_hidden; + } return should_hit_test; } @@ -860,6 +867,9 @@ bool LayerImpl::CanUseLCDText() const { if (static_cast<int>(offset_to_transform_parent().y()) != offset_to_transform_parent().y()) return false; + + if (has_will_change_transform_hint()) + return false; return true; } diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h index d3f3d6e1448..b98cfd6ad3c 100644 --- a/chromium/cc/layers/layer_impl.h +++ b/chromium/cc/layers/layer_impl.h @@ -15,7 +15,6 @@ #include <vector> #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/values.h" #include "cc/base/region.h" @@ -79,8 +78,11 @@ class CC_EXPORT LayerImpl { return base::WrapUnique(new LayerImpl(tree_impl, id)); } + LayerImpl(const LayerImpl&) = delete; virtual ~LayerImpl(); + LayerImpl& operator=(const LayerImpl&) = delete; + int id() const { return layer_id_; } // Whether this layer is on the active tree, return false if it's on the @@ -163,15 +165,9 @@ class CC_EXPORT LayerImpl { void SetDrawsContent(bool draws_content); bool DrawsContent() const { return draws_content_; } - // Make the layer hit test (see: |should_hit_test|) even if !draws_content_. - void SetHitTestableWithoutDrawsContent(bool should_hit_test); - bool hit_testable_without_draws_content() const { - return hit_testable_without_draws_content_; - } - - // True if either the layer draws content or has been marked as hit testable - // without draws_content. - bool ShouldHitTest() const; + // Make the layer hit testable. + void SetHitTestable(bool should_hit_test); + bool HitTestable() const; LayerImplTestProperties* test_properties() { if (!test_properties_) @@ -534,10 +530,8 @@ class CC_EXPORT LayerImpl { bool draws_content_ : 1; bool contributes_to_drawn_render_surface_ : 1; - // Hit testing depends on draws_content (see: |LayerImpl::should_hit_test|) - // and this bit can be set to cause the layer to be hit testable without - // draws_content. - bool hit_testable_without_draws_content_ : 1; + // Tracks if this layer should participate in hit testing. + bool hit_testable_ : 1; bool is_resized_by_browser_controls_ : 1; // TODO(bokan): This can likely be removed after blink-gen-property-trees @@ -604,8 +598,6 @@ class CC_EXPORT LayerImpl { bool raster_even_if_not_drawn_ : 1; bool has_transform_node_ : 1; - - DISALLOW_COPY_AND_ASSIGN(LayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/layer_sticky_position_constraint.cc b/chromium/cc/layers/layer_sticky_position_constraint.cc index 718d567a5d8..4da9089aff6 100644 --- a/chromium/cc/layers/layer_sticky_position_constraint.cc +++ b/chromium/cc/layers/layer_sticky_position_constraint.cc @@ -17,9 +17,7 @@ LayerStickyPositionConstraint::LayerStickyPositionConstraint() left_offset(0.f), right_offset(0.f), top_offset(0.f), - bottom_offset(0.f), - nearest_element_shifting_sticky_box(kInvalidElementId), - nearest_element_shifting_containing_block(kInvalidElementId) {} + bottom_offset(0.f) {} LayerStickyPositionConstraint::LayerStickyPositionConstraint( const LayerStickyPositionConstraint& other) = default; diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc index 2b5c09842e7..9a6e33429b5 100644 --- a/chromium/cc/layers/layer_unittest.cc +++ b/chromium/cc/layers/layer_unittest.cc @@ -360,6 +360,14 @@ TEST_F(LayerTest, LayerPropertyChangedForSubtree) { grand_child->PushPropertiesTo(grand_child_impl.get())); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); + EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetIsFastRoundedCorner(true)); + EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( + root->PushPropertiesTo(root_impl.get()); + child->PushPropertiesTo(child_impl.get()); + child2->PushPropertiesTo(child2_impl.get()); + grand_child->PushPropertiesTo(grand_child_impl.get())); + + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetRoundedCorner({0, 0, 0, 0})); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( root->PushPropertiesTo(root_impl.get()); @@ -516,6 +524,41 @@ TEST_F(LayerTest, AddSameChildTwice) { EXPECT_EQ(parent.get(), child->parent()); } +TEST_F(LayerTest, ReorderChildren) { + EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(AtLeast(1)); + + scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> child1 = Layer::Create(); + scoped_refptr<Layer> child2 = Layer::Create(); + scoped_refptr<Layer> child3 = Layer::Create(); + + layer_tree_host_->SetRootLayer(parent); + + parent->AddChild(child1); + parent->AddChild(child2); + parent->AddChild(child3); + EXPECT_EQ(child1, parent->children()[0]); + EXPECT_EQ(child2, parent->children()[1]); + EXPECT_EQ(child3, parent->children()[2]); + + layer_tree_host_->ClearLayersThatShouldPushProperties(); + + LayerList new_children_order; + new_children_order.emplace_back(child3); + new_children_order.emplace_back(child1); + new_children_order.emplace_back(child2); + parent->ReorderChildren(&new_children_order); + EXPECT_EQ(child3, parent->children()[0]); + EXPECT_EQ(child1, parent->children()[1]); + EXPECT_EQ(child2, parent->children()[2]); + + for (const auto& child : parent->children()) { + EXPECT_FALSE(base::ContainsKey( + layer_tree_host_->LayersThatShouldPushProperties(), child.get())); + EXPECT_TRUE(child->subtree_property_changed()); + } +} + TEST_F(LayerTest, InsertChild) { scoped_refptr<Layer> parent = Layer::Create(); scoped_refptr<Layer> child1 = Layer::Create(); @@ -879,7 +922,6 @@ TEST_F(LayerTest, TestSettingMainThreadScrollingReason) { reasons |= MainThreadScrollingReason::kScrollbarScrolling; reasons_to_clear |= MainThreadScrollingReason::kHandlingScrollFromMainThread; - reasons_to_clear |= MainThreadScrollingReason::kCustomScrollbarScrolling; reasons_after_clearing |= MainThreadScrollingReason::kThreadedScrollingDisabled; @@ -905,7 +947,6 @@ TEST_F(LayerTest, TestSettingMainThreadScrollingReason) { // Check that clearing non-set reasons doesn't set needs commit. reasons_to_clear = 0; - reasons_to_clear |= MainThreadScrollingReason::kCustomScrollbarScrolling; reasons_to_clear |= MainThreadScrollingReason::kFrameOverlay; EXPECT_SET_NEEDS_COMMIT( 0, test_layer->ClearMainThreadScrollingReasons(reasons_to_clear)); @@ -938,6 +979,7 @@ TEST_F(LayerTest, CheckPropertyChangeCausesCorrectBehavior) { EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBackgroundColor(SK_ColorLTGRAY)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetMasksToBounds(true)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetRoundedCorner({1, 2, 3, 4})); + EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetIsFastRoundedCorner(true)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetOpacity(0.5f)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendMode(SkBlendMode::kHue)); EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetIsRootForIsolatedGroup(true)); @@ -1378,30 +1420,29 @@ TEST_F(LayerTest, PushUpdatesShouldHitTest) { LayerImpl::Create(host_impl_.active_tree(), 1); EXPECT_SET_NEEDS_FULL_TREE_SYNC(1, layer_tree_host_->SetRootLayer(root_layer)); - EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(3); + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(5); // A layer that draws content should be hit testable. root_layer->SetIsDrawable(true); + root_layer->SetHitTestable(true); root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_TRUE(impl_layer->DrawsContent()); - EXPECT_FALSE(impl_layer->hit_testable_without_draws_content()); - EXPECT_TRUE(impl_layer->ShouldHitTest()); + EXPECT_TRUE(impl_layer->HitTestable()); // A layer that does not draw content and does not hit test without drawing // content should not be hit testable. root_layer->SetIsDrawable(false); + root_layer->SetHitTestable(false); root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); - EXPECT_FALSE(impl_layer->hit_testable_without_draws_content()); - EXPECT_FALSE(impl_layer->ShouldHitTest()); + EXPECT_FALSE(impl_layer->HitTestable()); // |SetHitTestableWithoutDrawsContent| should cause a layer to become hit // testable even though it does not draw content. - root_layer->SetHitTestableWithoutDrawsContent(true); + root_layer->SetHitTestable(true); root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); - EXPECT_TRUE(impl_layer->hit_testable_without_draws_content()); - EXPECT_TRUE(impl_layer->ShouldHitTest()); + EXPECT_TRUE(impl_layer->HitTestable()); } void ReceiveCopyOutputResult(int* result_count, diff --git a/chromium/cc/layers/nine_patch_generator.h b/chromium/cc/layers/nine_patch_generator.h index f413e4f5d9c..afdcb27bff8 100644 --- a/chromium/cc/layers/nine_patch_generator.h +++ b/chromium/cc/layers/nine_patch_generator.h @@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/resources/ui_resource_client.h" #include "ui/gfx/geometry/rect.h" diff --git a/chromium/cc/layers/nine_patch_layer.h b/chromium/cc/layers/nine_patch_layer.h index ca9fb929eb5..f492e6e4c49 100644 --- a/chromium/cc/layers/nine_patch_layer.h +++ b/chromium/cc/layers/nine_patch_layer.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/ui_resource_layer.h" @@ -20,6 +19,9 @@ class CC_EXPORT NinePatchLayer : public UIResourceLayer { public: static scoped_refptr<NinePatchLayer> Create(); + NinePatchLayer(const NinePatchLayer&) = delete; + NinePatchLayer& operator=(const NinePatchLayer&) = delete; + void PushPropertiesTo(LayerImpl* layer) override; // |border| is the space around the center rectangular region in layer space @@ -60,8 +62,6 @@ class CC_EXPORT NinePatchLayer : public UIResourceLayer { // The occluded region in layer space set by SetLayerOcclusion. It is // usually larger than |image_aperture_|. gfx::Rect layer_occlusion_; - - DISALLOW_COPY_AND_ASSIGN(NinePatchLayer); }; } // namespace cc diff --git a/chromium/cc/layers/nine_patch_layer_impl.h b/chromium/cc/layers/nine_patch_layer_impl.h index 5e01501d4ee..d63163df9c8 100644 --- a/chromium/cc/layers/nine_patch_layer_impl.h +++ b/chromium/cc/layers/nine_patch_layer_impl.h @@ -7,7 +7,6 @@ #include <string> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" @@ -29,8 +28,11 @@ class CC_EXPORT NinePatchLayerImpl : public UIResourceLayerImpl { int id) { return base::WrapUnique(new NinePatchLayerImpl(tree_impl, id)); } + NinePatchLayerImpl(const NinePatchLayerImpl&) = delete; ~NinePatchLayerImpl() override; + NinePatchLayerImpl& operator=(const NinePatchLayerImpl&) = delete; + // For parameter meanings, see the declaration of NinePatchGenerator. void SetLayout(const gfx::Rect& image_aperture, const gfx::Rect& border, @@ -53,8 +55,6 @@ class CC_EXPORT NinePatchLayerImpl : public UIResourceLayerImpl { const char* LayerTypeAsString() const override; NinePatchGenerator quad_generator_; - - DISALLOW_COPY_AND_ASSIGN(NinePatchLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer.h b/chromium/cc/layers/painted_overlay_scrollbar_layer.h index 674a7266f71..931d96cc810 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer.h +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_ #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" @@ -20,6 +19,9 @@ class CC_EXPORT PaintedOverlayScrollbarLayer : public ScrollbarLayerInterface, public: std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; + PaintedOverlayScrollbarLayer(const PaintedOverlayScrollbarLayer&) = delete; + PaintedOverlayScrollbarLayer& operator=(const PaintedOverlayScrollbarLayer&) = + delete; static scoped_refptr<PaintedOverlayScrollbarLayer> Create( std::unique_ptr<Scrollbar> scrollbar, ElementId scroll_element_id = ElementId()); @@ -66,8 +68,6 @@ class CC_EXPORT PaintedOverlayScrollbarLayer : public ScrollbarLayerInterface, std::unique_ptr<ScopedUIResource> thumb_resource_; std::unique_ptr<ScopedUIResource> track_resource_; - - DISALLOW_COPY_AND_ASSIGN(PaintedOverlayScrollbarLayer); }; } // namespace cc diff --git a/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h b/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h index 37bdce9eda1..36b29003e08 100644 --- a/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h +++ b/chromium/cc/layers/painted_overlay_scrollbar_layer_impl.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_IMPL_H_ #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_IMPL_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/nine_patch_generator.h" @@ -24,6 +23,10 @@ class CC_EXPORT PaintedOverlayScrollbarLayerImpl int id, ScrollbarOrientation orientation, bool is_left_side_vertical_scrollbar); + PaintedOverlayScrollbarLayerImpl(const PaintedOverlayScrollbarLayerImpl&) = + delete; + PaintedOverlayScrollbarLayerImpl& operator=( + const PaintedOverlayScrollbarLayerImpl&) = delete; ~PaintedOverlayScrollbarLayerImpl() override; // LayerImpl implementation. @@ -89,8 +92,6 @@ class CC_EXPORT PaintedOverlayScrollbarLayerImpl gfx::Rect aperture_; NinePatchGenerator quad_generator_; - - DISALLOW_COPY_AND_ASSIGN(PaintedOverlayScrollbarLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc index 11f22ae1c9f..ddf202b095a 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_scrollbar_layer.cc @@ -70,6 +70,8 @@ void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { internal_contents_scale_, internal_content_bounds_); scrollbar_layer->SetThumbThickness(thumb_thickness_); + scrollbar_layer->SetBackButtonRect(back_button_rect_); + scrollbar_layer->SetForwardButtonRect(forward_button_rect_); scrollbar_layer->SetThumbLength(thumb_length_); if (scrollbar_->Orientation() == HORIZONTAL) { scrollbar_layer->SetTrackStart( @@ -133,6 +135,8 @@ gfx::Rect PaintedScrollbarLayer::OriginThumbRect() const { void PaintedScrollbarLayer::UpdateThumbAndTrackGeometry() { UpdateProperty(scrollbar_->TrackRect(), &track_rect_); + UpdateProperty(scrollbar_->BackButtonRect(), &back_button_rect_); + UpdateProperty(scrollbar_->ForwardButtonRect(), &forward_button_rect_); UpdateProperty(scrollbar_->Location(), &location_); UpdateProperty(scrollbar_->IsOverlay(), &is_overlay_); UpdateProperty(scrollbar_->HasThumb(), &has_thumb_); diff --git a/chromium/cc/layers/painted_scrollbar_layer.h b/chromium/cc/layers/painted_scrollbar_layer.h index 6f293bf5029..1062ada84d6 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.h +++ b/chromium/cc/layers/painted_scrollbar_layer.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_ #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" @@ -24,6 +23,9 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, std::unique_ptr<Scrollbar> scrollbar, ElementId element_id = ElementId()); + PaintedScrollbarLayer(const PaintedScrollbarLayer&) = delete; + PaintedScrollbarLayer& operator=(const PaintedScrollbarLayer&) = delete; + bool OpacityCanAnimateOnImplThread() const override; // ScrollbarLayerInterface @@ -82,6 +84,8 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, int thumb_length_; gfx::Point location_; gfx::Rect track_rect_; + gfx::Rect back_button_rect_; + gfx::Rect forward_button_rect_; bool is_overlay_; bool has_thumb_; @@ -89,8 +93,6 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, std::unique_ptr<ScopedUIResource> thumb_resource_; float thumb_opacity_; - - DISALLOW_COPY_AND_ASSIGN(PaintedScrollbarLayer); }; } // namespace cc diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl.cc b/chromium/cc/layers/painted_scrollbar_layer_impl.cc index 09febcc0984..66275d92f98 100644 --- a/chromium/cc/layers/painted_scrollbar_layer_impl.cc +++ b/chromium/cc/layers/painted_scrollbar_layer_impl.cc @@ -46,7 +46,9 @@ PaintedScrollbarLayerImpl::PaintedScrollbarLayerImpl( thumb_thickness_(0), thumb_length_(0), track_start_(0), - track_length_(0) {} + track_length_(0), + back_button_rect_(gfx::Rect(0, 0)), + forward_button_rect_(gfx::Rect(0, 0)) {} PaintedScrollbarLayerImpl::~PaintedScrollbarLayerImpl() = default; @@ -70,6 +72,8 @@ void PaintedScrollbarLayerImpl::PushPropertiesTo(LayerImpl* layer) { scrollbar_layer->SetThumbLength(thumb_length_); scrollbar_layer->SetTrackStart(track_start_); scrollbar_layer->SetTrackLength(track_length_); + scrollbar_layer->SetBackButtonRect(back_button_rect_); + scrollbar_layer->SetForwardButtonRect(forward_button_rect_); scrollbar_layer->set_track_ui_resource_id(track_ui_resource_id_); scrollbar_layer->set_thumb_ui_resource_id(thumb_ui_resource_id_); @@ -190,6 +194,29 @@ int PaintedScrollbarLayerImpl::TrackStart() const { return track_start_; } +void PaintedScrollbarLayerImpl::SetBackButtonRect(gfx::Rect back_button_rect) { + if (back_button_rect_ == back_button_rect) + return; + back_button_rect_ = back_button_rect; + NoteLayerPropertyChanged(); +} + +gfx::Rect PaintedScrollbarLayerImpl::BackButtonRect() const { + return back_button_rect_; +} + +void PaintedScrollbarLayerImpl::SetForwardButtonRect( + gfx::Rect forward_button_rect) { + if (forward_button_rect_ == forward_button_rect) + return; + forward_button_rect_ = forward_button_rect; + NoteLayerPropertyChanged(); +} + +gfx::Rect PaintedScrollbarLayerImpl::ForwardButtonRect() const { + return forward_button_rect_; +} + void PaintedScrollbarLayerImpl::SetTrackLength(int track_length) { if (track_length_ == track_length) return; diff --git a/chromium/cc/layers/painted_scrollbar_layer_impl.h b/chromium/cc/layers/painted_scrollbar_layer_impl.h index a76b642f30e..13a9b4f41db 100644 --- a/chromium/cc/layers/painted_scrollbar_layer_impl.h +++ b/chromium/cc/layers/painted_scrollbar_layer_impl.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_PAINTED_SCROLLBAR_LAYER_IMPL_H_ #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_IMPL_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/scrollbar_layer_impl_base.h" @@ -23,8 +22,12 @@ class CC_EXPORT PaintedScrollbarLayerImpl : public ScrollbarLayerImplBase { ScrollbarOrientation orientation, bool is_left_side_vertical_scrollbar, bool is_overlay); + PaintedScrollbarLayerImpl(const PaintedScrollbarLayerImpl&) = delete; ~PaintedScrollbarLayerImpl() override; + PaintedScrollbarLayerImpl& operator=(const PaintedScrollbarLayerImpl&) = + delete; + // LayerImpl implementation. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void PushPropertiesTo(LayerImpl* layer) override; @@ -35,6 +38,8 @@ class CC_EXPORT PaintedScrollbarLayerImpl : public ScrollbarLayerImplBase { AppendQuadsData* append_quads_data) override; gfx::Rect GetEnclosingRectInTargetSpace() const override; + void SetBackButtonRect(gfx::Rect back_button_rect); + void SetForwardButtonRect(gfx::Rect forward_button_rect); void SetThumbThickness(int thumb_thickness); void SetThumbLength(int thumb_length); void SetTrackStart(int track_start); @@ -55,6 +60,8 @@ class CC_EXPORT PaintedScrollbarLayerImpl : public ScrollbarLayerImplBase { internal_content_bounds_ = content_bounds; } + gfx::Rect BackButtonRect() const override; + gfx::Rect ForwardButtonRect() const override; int ThumbThickness() const override; LayerTreeSettings::ScrollbarAnimator GetScrollbarAnimator() const override; @@ -87,8 +94,8 @@ class CC_EXPORT PaintedScrollbarLayerImpl : public ScrollbarLayerImplBase { int thumb_length_; int track_start_; int track_length_; - - DISALLOW_COPY_AND_ASSIGN(PaintedScrollbarLayerImpl); + gfx::Rect back_button_rect_; + gfx::Rect forward_button_rect_; }; } // namespace cc diff --git a/chromium/cc/layers/picture_image_layer.h b/chromium/cc/layers/picture_image_layer.h index c51da8b7ff4..b9a424f2a08 100644 --- a/chromium/cc/layers/picture_image_layer.h +++ b/chromium/cc/layers/picture_image_layer.h @@ -7,7 +7,6 @@ #include <stddef.h> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_layer.h" @@ -21,6 +20,9 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient { public: static scoped_refptr<PictureImageLayer> Create(); + PictureImageLayer(const PictureImageLayer&) = delete; + PictureImageLayer& operator=(const PictureImageLayer&) = delete; + void SetImage(PaintImage image, const SkMatrix& matrix, bool uses_width_as_height); @@ -46,8 +48,6 @@ class CC_EXPORT PictureImageLayer : public PictureLayer, ContentLayerClient { PaintImage image_; SkMatrix matrix_; bool uses_width_as_height_; - - DISALLOW_COPY_AND_ASSIGN(PictureImageLayer); }; } // namespace cc diff --git a/chromium/cc/layers/picture_layer.h b/chromium/cc/layers/picture_layer.h index dc536966b81..48ea87225a1 100644 --- a/chromium/cc/layers/picture_layer.h +++ b/chromium/cc/layers/picture_layer.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "cc/base/devtools_instrumentation.h" #include "cc/base/invalidation_region.h" #include "cc/benchmarks/micro_benchmark_controller.h" @@ -23,6 +22,9 @@ class CC_EXPORT PictureLayer : public Layer { public: static scoped_refptr<PictureLayer> Create(ContentLayerClient* client); + PictureLayer(const PictureLayer&) = delete; + PictureLayer& operator=(const PictureLayer&) = delete; + void ClearClient(); void SetNearestNeighbor(bool nearest_neighbor); @@ -98,8 +100,6 @@ class CC_EXPORT PictureLayer : public Layer { int update_source_frame_number_; LayerMaskType mask_type_; - - DISALLOW_COPY_AND_ASSIGN(PictureLayer); }; } // namespace cc diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc index 1babd640d78..9f53aa0cb72 100644 --- a/chromium/cc/layers/picture_layer_impl.cc +++ b/chromium/cc/layers/picture_layer_impl.cc @@ -1309,7 +1309,7 @@ void PictureLayerImpl::RecalculateRasterScales() { transform_tree_index(), layer_tree_impl()); float maximum_scale = animation_scales.maximum_animation_scale; float starting_scale = animation_scales.starting_animation_scale; - if (maximum_scale) { + if (maximum_scale != kNotScaled) { gfx::Size bounds_at_maximum_scale = gfx::ScaleToCeiledSize(raster_source_->GetSize(), maximum_scale); int64_t maximum_area = @@ -1328,7 +1328,7 @@ void PictureLayerImpl::RecalculateRasterScales() { if (maximum_area <= squared_viewport_area) can_raster_at_maximum_scale = true; } - if (starting_scale && starting_scale > maximum_scale) { + if (starting_scale != kNotScaled && starting_scale > maximum_scale) { gfx::Size bounds_at_starting_scale = gfx::ScaleToCeiledSize(raster_source_->GetSize(), starting_scale); int64_t start_area = diff --git a/chromium/cc/layers/picture_layer_impl.h b/chromium/cc/layers/picture_layer_impl.h index 6f850859e72..82309bd8d4c 100644 --- a/chromium/cc/layers/picture_layer_impl.h +++ b/chromium/cc/layers/picture_layer_impl.h @@ -11,7 +11,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" @@ -37,8 +36,11 @@ class CC_EXPORT PictureLayerImpl Create(LayerTreeImpl* tree_impl, int id, Layer::LayerMaskType mask_type) { return base::WrapUnique(new PictureLayerImpl(tree_impl, id, mask_type)); } + PictureLayerImpl(const PictureLayerImpl&) = delete; ~PictureLayerImpl() override; + PictureLayerImpl& operator=(const PictureLayerImpl&) = delete; + Layer::LayerMaskType mask_type() const { return mask_type_; } void SetLayerMaskType(Layer::LayerMaskType type); @@ -205,8 +207,6 @@ class CC_EXPORT PictureLayerImpl // of comparing pointers, since objects pointed to are not guaranteed to // exist. std::vector<PictureLayerTiling*> last_append_quads_tilings_; - - DISALLOW_COPY_AND_ASSIGN(PictureLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/picture_layer_impl_perftest.cc b/chromium/cc/layers/picture_layer_impl_perftest.cc index 281beab9f1d..443203e0a0b 100644 --- a/chromium/cc/layers/picture_layer_impl_perftest.cc +++ b/chromium/cc/layers/picture_layer_impl_perftest.cc @@ -4,7 +4,6 @@ #include "cc/layers/picture_layer_impl.h" -#include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" #include "base/timer/lap_timer.h" #include "cc/test/fake_impl_task_runner_provider.h" @@ -50,6 +49,9 @@ class PictureLayerImplPerfTest : public testing::Test { base::TimeDelta::FromMilliseconds(kTimeLimitMillis), kTimeCheckInterval) {} + PictureLayerImplPerfTest(const PictureLayerImplPerfTest&) = delete; + PictureLayerImplPerfTest& operator=(const PictureLayerImplPerfTest&) = delete; + void SetUp() override { host_impl_.SetVisible(true); host_impl_.InitializeFrameSink(layer_tree_frame_sink_.get()); @@ -175,9 +177,6 @@ class PictureLayerImplPerfTest : public testing::Test { FakeLayerTreeHostImpl host_impl_; FakePictureLayerImpl* pending_layer_; base::LapTimer timer_; - - private: - DISALLOW_COPY_AND_ASSIGN(PictureLayerImplPerfTest); }; TEST_F(PictureLayerImplPerfTest, TilingSetRasterQueueConstructAndIterate) { diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc index dbf4a5a42af..1ecd3df1423 100644 --- a/chromium/cc/layers/picture_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_layer_impl_unittest.cc @@ -12,7 +12,6 @@ #include <utility> #include "base/location.h" -#include "base/macros.h" #include "base/stl_util.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" diff --git a/chromium/cc/layers/recording_source.h b/chromium/cc/layers/recording_source.h index 7469a115038..a67d51b319c 100644 --- a/chromium/cc/layers/recording_source.h +++ b/chromium/cc/layers/recording_source.h @@ -9,7 +9,6 @@ #include <memory> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/base/invalidation_region.h" #include "cc/cc_export.h" @@ -36,8 +35,11 @@ class CC_EXPORT RecordingSource { }; RecordingSource(); + RecordingSource(const RecordingSource&) = delete; virtual ~RecordingSource(); + RecordingSource& operator=(const RecordingSource&) = delete; + bool UpdateAndExpandInvalidation(Region* invalidation, const gfx::Size& layer_size, const gfx::Rect& new_recorded_viewport); @@ -82,8 +84,6 @@ class CC_EXPORT RecordingSource { void DetermineIfSolidColor(); InvalidationRegion invalidation_; - - DISALLOW_COPY_AND_ASSIGN(RecordingSource); }; } // namespace cc diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc index 62724618c97..ea81934163c 100644 --- a/chromium/cc/layers/render_surface_impl.cc +++ b/chromium/cc/layers/render_surface_impl.cc @@ -403,7 +403,7 @@ void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, viz::SharedQuadState* shared_quad_state = render_pass->CreateAndAppendSharedQuadState(); shared_quad_state->SetAll( - draw_transform(), content_rect(), content_rect(), + draw_transform(), content_rect(), content_rect(), rounded_corner_bounds(), draw_properties_.clip_rect, draw_properties_.is_clipped, contents_opaque, draw_properties_.draw_opacity, BlendMode(), sorting_context_id); diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h index 58ae7f85a9e..15dd8c98384 100644 --- a/chromium/cc/layers/render_surface_impl.h +++ b/chromium/cc/layers/render_surface_impl.h @@ -11,7 +11,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/draw_mode.h" #include "cc/layers/layer_collections.h" @@ -35,8 +34,11 @@ class LayerTreeImpl; class CC_EXPORT RenderSurfaceImpl { public: RenderSurfaceImpl(LayerTreeImpl* layer_tree_impl, uint64_t stable_id); + RenderSurfaceImpl(const RenderSurfaceImpl&) = delete; virtual ~RenderSurfaceImpl(); + RenderSurfaceImpl& operator=(const RenderSurfaceImpl&) = delete; + // Returns the RenderSurfaceImpl that this render surface contributes to. Root // render surface's render_target is itself. RenderSurfaceImpl* render_target(); @@ -51,6 +53,13 @@ class CC_EXPORT RenderSurfaceImpl { } float draw_opacity() const { return draw_properties_.draw_opacity; } + void SetRoundedCornerRRect(const gfx::RRectF& rounded_corner_bounds) { + draw_properties_.rounded_corner_bounds = rounded_corner_bounds; + } + const gfx::RRectF& rounded_corner_bounds() const { + return draw_properties_.rounded_corner_bounds; + } + SkBlendMode BlendMode() const; bool UsesDefaultBlendMode() const; @@ -218,6 +227,11 @@ class CC_EXPORT RenderSurfaceImpl { // True if the surface needs to be clipped by clip_rect. bool is_clipped : 1; + + // Contains a rounded corner rect to clip this render surface by when + // drawing. This rrect is in the target space of the render surface. The + // root render surface will never have this set. + gfx::RRectF rounded_corner_bounds; }; DrawProperties draw_properties_; @@ -240,8 +254,6 @@ class CC_EXPORT RenderSurfaceImpl { const RenderSurfaceImpl* nearest_occlusion_immune_ancestor_; std::unique_ptr<DamageTracker> damage_tracker_; - - DISALLOW_COPY_AND_ASSIGN(RenderSurfaceImpl); }; } // namespace cc diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc index 768048fefa7..fb4ed8fb758 100644 --- a/chromium/cc/layers/scrollbar_layer_impl_base.cc +++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc @@ -282,4 +282,29 @@ bool ScrollbarLayerImplBase::HasFindInPageTickmarks() const { return false; } +gfx::Rect ScrollbarLayerImplBase::BackButtonRect() const { + return gfx::Rect(0, 0); +} + +gfx::Rect ScrollbarLayerImplBase::ForwardButtonRect() const { + return gfx::Rect(0, 0); +} + +// This manages identifying which part of a composited scrollbar got hit based +// on the position_in_widget. +ScrollbarPart ScrollbarLayerImplBase::IdentifyScrollbarPart( + const gfx::PointF position_in_widget) const { + const gfx::Point pointer_location(position_in_widget.x(), + position_in_widget.y()); + if (BackButtonRect().Contains(pointer_location)) + return ScrollbarPart::BACK_BUTTON; + if (ForwardButtonRect().Contains(pointer_location)) + return ScrollbarPart::FORWARD_BUTTON; + + // TODO(arakeri): Once crbug.com/952314 is fixed, add a DCHECK to verify that + // the point that is passed in is within the TrackRect. Also, please note that + // hit testing other scrollbar parts is not yet implemented. + return ScrollbarPart::NO_PART; +} + } // namespace cc diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.h b/chromium/cc/layers/scrollbar_layer_impl_base.h index 8c38e0e1584..5255f520e4f 100644 --- a/chromium/cc/layers/scrollbar_layer_impl_base.h +++ b/chromium/cc/layers/scrollbar_layer_impl_base.h @@ -6,7 +6,6 @@ #define CC_LAYERS_SCROLLBAR_LAYER_IMPL_BASE_H_ #include "base/containers/flat_set.h" -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" #include "cc/layers/layer.h" @@ -19,6 +18,9 @@ class LayerTreeImpl; class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { public: + ScrollbarLayerImplBase(const ScrollbarLayerImplBase&) = delete; + ScrollbarLayerImplBase& operator=(const ScrollbarLayerImplBase&) = delete; + ElementId scroll_element_id() const { return scroll_element_id_; } void SetScrollElementId(ElementId scroll_element_id); @@ -64,6 +66,10 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { virtual LayerTreeSettings::ScrollbarAnimator GetScrollbarAnimator() const; + virtual gfx::Rect BackButtonRect() const; + virtual gfx::Rect ForwardButtonRect() const; + virtual ScrollbarPart IdentifyScrollbarPart( + const gfx::PointF position_in_widget) const; // Only PaintedOverlayScrollbar(Aura Overlay Scrollbar) need to know // tickmarks's state. virtual bool HasFindInPageTickmarks() const; @@ -103,8 +109,6 @@ class CC_EXPORT ScrollbarLayerImplBase : public LayerImpl { FRIEND_TEST_ALL_PREFIXES(ScrollbarLayerTest, ScrollElementIdPushedAcrossCommit); - - DISALLOW_COPY_AND_ASSIGN(ScrollbarLayerImplBase); }; using ScrollbarSet = base::flat_set<ScrollbarLayerImplBase*>; diff --git a/chromium/cc/layers/scrollbar_layer_interface.h b/chromium/cc/layers/scrollbar_layer_interface.h index a246fca9fb5..661028e4a9a 100644 --- a/chromium/cc/layers/scrollbar_layer_interface.h +++ b/chromium/cc/layers/scrollbar_layer_interface.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_SCROLLBAR_LAYER_INTERFACE_H_ #define CC_LAYERS_SCROLLBAR_LAYER_INTERFACE_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/scrollbar.h" @@ -13,14 +12,14 @@ namespace cc { class CC_EXPORT ScrollbarLayerInterface { public: + ScrollbarLayerInterface(const ScrollbarLayerInterface&) = delete; + ScrollbarLayerInterface& operator=(const ScrollbarLayerInterface&) = delete; + virtual void SetScrollElementId(ElementId element_id) = 0; protected: ScrollbarLayerInterface() {} virtual ~ScrollbarLayerInterface() {} - - private: - DISALLOW_COPY_AND_ASSIGN(ScrollbarLayerInterface); }; } // namespace cc diff --git a/chromium/cc/layers/solid_color_layer.h b/chromium/cc/layers/solid_color_layer.h index 653dd8a8717..7b97ac0466d 100644 --- a/chromium/cc/layers/solid_color_layer.h +++ b/chromium/cc/layers/solid_color_layer.h @@ -6,7 +6,6 @@ #ifndef CC_LAYERS_SOLID_COLOR_LAYER_H_ #define CC_LAYERS_SOLID_COLOR_LAYER_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" @@ -18,6 +17,9 @@ class CC_EXPORT SolidColorLayer : public Layer { public: static scoped_refptr<SolidColorLayer> Create(); + SolidColorLayer(const SolidColorLayer&) = delete; + SolidColorLayer& operator=(const SolidColorLayer&) = delete; + std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetBackgroundColor(SkColor color) override; @@ -27,8 +29,6 @@ class CC_EXPORT SolidColorLayer : public Layer { private: ~SolidColorLayer() override; - - DISALLOW_COPY_AND_ASSIGN(SolidColorLayer); }; } // namespace cc diff --git a/chromium/cc/layers/solid_color_layer_impl.h b/chromium/cc/layers/solid_color_layer_impl.h index 78a35a4aaac..68d1e1a8d1b 100644 --- a/chromium/cc/layers/solid_color_layer_impl.h +++ b/chromium/cc/layers/solid_color_layer_impl.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" @@ -21,6 +20,9 @@ class CC_EXPORT SolidColorLayerImpl : public LayerImpl { return base::WrapUnique(new SolidColorLayerImpl(tree_impl, id)); } + SolidColorLayerImpl(const SolidColorLayerImpl&) = delete; + SolidColorLayerImpl& operator=(const SolidColorLayerImpl&) = delete; + static void AppendSolidQuads(viz::RenderPass* render_pass, const Occlusion& occlusion_in_layer_space, viz::SharedQuadState* shared_quad_state, @@ -42,8 +44,6 @@ class CC_EXPORT SolidColorLayerImpl : public LayerImpl { private: const char* LayerTypeAsString() const override; - - DISALLOW_COPY_AND_ASSIGN(SolidColorLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/solid_color_scrollbar_layer.h b/chromium/cc/layers/solid_color_scrollbar_layer.h index 69bcc4f1440..67c4adb2463 100644 --- a/chromium/cc/layers/solid_color_scrollbar_layer.h +++ b/chromium/cc/layers/solid_color_scrollbar_layer.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_H_ #define CC_LAYERS_SOLID_COLOR_SCROLLBAR_LAYER_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/layers/scrollbar_layer_interface.h" @@ -24,6 +23,9 @@ class CC_EXPORT SolidColorScrollbarLayer : public ScrollbarLayerInterface, bool is_left_side_vertical_scrollbar, ElementId scroll_element_id); + SolidColorScrollbarLayer(const SolidColorScrollbarLayer&) = delete; + SolidColorScrollbarLayer& operator=(const SolidColorScrollbarLayer&) = delete; + // Layer overrides. bool OpacityCanAnimateOnImplThread() const override; @@ -63,8 +65,6 @@ class CC_EXPORT SolidColorScrollbarLayer : public ScrollbarLayerInterface, }; SolidColorScrollbarLayerInputs solid_color_scrollbar_layer_inputs_; - - DISALLOW_COPY_AND_ASSIGN(SolidColorScrollbarLayer); }; } // namespace cc diff --git a/chromium/cc/layers/surface_layer.cc b/chromium/cc/layers/surface_layer.cc index afe7d8e6cd7..f2750e47cf6 100644 --- a/chromium/cc/layers/surface_layer.cc +++ b/chromium/cc/layers/surface_layer.cc @@ -6,7 +6,6 @@ #include <stdint.h> -#include "base/macros.h" #include "base/trace_event/trace_event.h" #include "cc/layers/surface_layer_impl.h" #include "cc/trees/layer_tree_host.h" @@ -75,12 +74,6 @@ void SurfaceLayer::SetOldestAcceptableFallback( !surface_range_.start()->IsNewerThan(surface_id)); if (surface_range_.start() == surface_id) return; - TRACE_EVENT_WITH_FLOW2( - TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), - "LocalSurfaceId.Submission.Flow", - TRACE_ID_GLOBAL(surface_id.local_surface_id().submission_trace_id()), - TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", - "SetOldestAcceptableFallback", "surface_id", surface_id.ToString()); if (layer_tree_host() && surface_range_.IsValid()) layer_tree_host()->RemoveSurfaceRange(surface_range_); diff --git a/chromium/cc/layers/surface_layer.h b/chromium/cc/layers/surface_layer.h index 61c78304062..9d15812f813 100644 --- a/chromium/cc/layers/surface_layer.h +++ b/chromium/cc/layers/surface_layer.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_SURFACE_LAYER_H_ #define CC_LAYERS_SURFACE_LAYER_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/deadline_policy.h" #include "cc/layers/layer.h" @@ -27,6 +26,9 @@ class CC_EXPORT SurfaceLayer : public Layer { static scoped_refptr<SurfaceLayer> Create(); static scoped_refptr<SurfaceLayer> Create(UpdateSubmissionStateCB); + SurfaceLayer(const SurfaceLayer&) = delete; + SurfaceLayer& operator=(const SurfaceLayer&) = delete; + void SetSurfaceId(const viz::SurfaceId& surface_id, const DeadlinePolicy& deadline_policy); void SetOldestAcceptableFallback(const viz::SurfaceId& surface_id); @@ -88,8 +90,6 @@ class CC_EXPORT SurfaceLayer : public Layer { // TODO(sunxd): consider renaming it to oopif_has_pointer_events_none_ for // disambiguation. bool has_pointer_events_none_ = false; - - DISALLOW_COPY_AND_ASSIGN(SurfaceLayer); }; } // namespace cc diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc index 9f9bd25d211..299d343bcf7 100644 --- a/chromium/cc/layers/surface_layer_impl.cc +++ b/chromium/cc/layers/surface_layer_impl.cc @@ -54,19 +54,6 @@ void SurfaceLayerImpl::SetRange(const viz::SurfaceRange& surface_range, "ImplSetSurfaceId", "surface_id", surface_range.end().ToString()); } - if (surface_range.start() && - surface_range_.start() != surface_range.start() && - surface_range.start()->local_surface_id().is_valid()) { - TRACE_EVENT_WITH_FLOW2( - TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), - "LocalSurfaceId.Submission.Flow", - TRACE_ID_GLOBAL( - surface_range.start()->local_surface_id().submission_trace_id()), - TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", - "ImplSetOldestAcceptableFallback", "surface_id", - surface_range.start()->ToString()); - } - surface_range_ = surface_range; deadline_in_frames_ = deadline_in_frames; NoteLayerPropertyChanged(); @@ -131,7 +118,7 @@ void SurfaceLayerImpl::AppendQuads(viz::RenderPass* render_pass, return; auto* primary = CreateSurfaceDrawQuad(render_pass, surface_range_); - if (primary && surface_range_.end() != surface_range_.start()) { + if (primary) { // Add the primary surface ID as a dependency. append_quads_data->activation_dependencies.push_back(surface_range_.end()); if (deadline_in_frames_) { diff --git a/chromium/cc/layers/surface_layer_impl.h b/chromium/cc/layers/surface_layer_impl.h index d00a8ba807c..1c3849f95a0 100644 --- a/chromium/cc/layers/surface_layer_impl.h +++ b/chromium/cc/layers/surface_layer_impl.h @@ -8,7 +8,6 @@ #include <memory> #include "base/bind.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" @@ -38,8 +37,11 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { new SurfaceLayerImpl(tree_impl, id, base::BindRepeating([](bool) {}))); } + SurfaceLayerImpl(const SurfaceLayerImpl&) = delete; ~SurfaceLayerImpl() override; + SurfaceLayerImpl& operator=(const SurfaceLayerImpl&) = delete; + void SetRange(const viz::SurfaceRange& surface_range, base::Optional<uint32_t> deadline_in_frames); const viz::SurfaceRange& range() const { return surface_range_; } @@ -54,9 +56,7 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { } void SetSurfaceHitTestable(bool surface_hit_testable); - bool ShouldGenerateSurfaceHitTestData() const { - return surface_hit_testable_ && !has_pointer_events_none_; - } + bool surface_hit_testable() const { return surface_hit_testable_; } void SetHasPointerEventsNone(bool has_pointer_events_none); bool has_pointer_events_none() const { return has_pointer_events_none_; } @@ -92,8 +92,6 @@ class CC_EXPORT SurfaceLayerImpl : public LayerImpl { bool surface_hit_testable_ = false; bool has_pointer_events_none_ = false; bool will_draw_ = false; - - DISALLOW_COPY_AND_ASSIGN(SurfaceLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/surface_layer_impl_unittest.cc b/chromium/cc/layers/surface_layer_impl_unittest.cc index 9442d3f938a..50ab0f01570 100644 --- a/chromium/cc/layers/surface_layer_impl_unittest.cc +++ b/chromium/cc/layers/surface_layer_impl_unittest.cc @@ -243,13 +243,8 @@ TEST(SurfaceLayerImplTest, SurfaceLayerImplWithMatchingPrimaryAndFallback) { std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); AppendQuadsData data; surface_layer_impl->AppendQuads(render_pass.get(), &data); - // As the primary and fallback SurfaceInfos match, there is no reason to - // add the primary surface ID to |activation_dependencies| because it is not - // an unresolved dependency. The fallback surface will already be added as a - // reference in referenced_surfaces. Since the primary and fallback surface - // IDs match, there is no reason to propagate the deadline. - EXPECT_THAT(data.activation_dependencies, testing::IsEmpty()); - EXPECT_EQ(base::nullopt, data.deadline_in_frames); + EXPECT_THAT(data.activation_dependencies, UnorderedElementsAre(surface_id1)); + EXPECT_EQ(2u, data.deadline_in_frames); ASSERT_EQ(1u, render_pass->quad_list.size()); const viz::SurfaceDrawQuad* surface_draw_quad1 = diff --git a/chromium/cc/layers/texture_layer.h b/chromium/cc/layers/texture_layer.h index b5d5993179c..dc9bd63f500 100644 --- a/chromium/cc/layers/texture_layer.h +++ b/chromium/cc/layers/texture_layer.h @@ -8,7 +8,6 @@ #include <string> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -43,14 +42,21 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { class CC_EXPORT MainThreadReference { public: explicit MainThreadReference(TransferableResourceHolder* holder); + MainThreadReference(const MainThreadReference&) = delete; ~MainThreadReference(); + + MainThreadReference& operator=(const MainThreadReference&) = delete; + TransferableResourceHolder* holder() { return holder_.get(); } private: scoped_refptr<TransferableResourceHolder> holder_; - DISALLOW_COPY_AND_ASSIGN(MainThreadReference); }; + TransferableResourceHolder(const TransferableResourceHolder&) = delete; + TransferableResourceHolder& operator=(const TransferableResourceHolder&) = + delete; + const viz::TransferableResource& resource() const { return resource_; } void Return(const gpu::SyncToken& sync_token, bool is_lost); @@ -102,13 +108,15 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { gpu::SyncToken sync_token_; bool is_lost_ = false; base::ThreadChecker main_thread_checker_; - DISALLOW_COPY_AND_ASSIGN(TransferableResourceHolder); }; // Used when mailbox names are specified instead of texture IDs. static scoped_refptr<TextureLayer> CreateForMailbox( TextureLayerClient* client); + TextureLayer(const TextureLayer&) = delete; + TextureLayer& operator=(const TextureLayer&) = delete; + // Resets the client, which also resets the texture. void ClearClient(); @@ -215,8 +223,6 @@ class CC_EXPORT TextureLayer : public Layer, SharedBitmapIdRegistrar { std::vector<viz::SharedBitmapId> to_unregister_bitmap_ids_; base::WeakPtrFactory<TextureLayer> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(TextureLayer); }; } // namespace cc diff --git a/chromium/cc/layers/texture_layer_impl.h b/chromium/cc/layers/texture_layer_impl.h index 51da8cd851b..d2ae0db25a6 100644 --- a/chromium/cc/layers/texture_layer_impl.h +++ b/chromium/cc/layers/texture_layer_impl.h @@ -9,7 +9,6 @@ #include "base/callback.h" #include "base/containers/flat_map.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" @@ -28,8 +27,11 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { int id) { return base::WrapUnique(new TextureLayerImpl(tree_impl, id)); } + TextureLayerImpl(const TextureLayerImpl&) = delete; ~TextureLayerImpl() override; + TextureLayerImpl& operator=(const TextureLayerImpl&) = delete; + std::unique_ptr<LayerImpl> CreateLayerImpl( LayerTreeImpl* layer_tree_impl) override; bool IsSnappedToPixelGridInTarget() override; @@ -123,8 +125,6 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { // As a pending layer, the set of SharedBitmapIds that the active layer should // unregister. std::vector<viz::SharedBitmapId> to_unregister_bitmap_ids_; - - DISALLOW_COPY_AND_ASSIGN(TextureLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc index c85b89e9247..64697a6c848 100644 --- a/chromium/cc/layers/texture_layer_unittest.cc +++ b/chromium/cc/layers/texture_layer_unittest.cc @@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/callback.h" #include "base/location.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" diff --git a/chromium/cc/layers/touch_action_region.cc b/chromium/cc/layers/touch_action_region.cc index c61b1377038..75da3cac02c 100644 --- a/chromium/cc/layers/touch_action_region.cc +++ b/chromium/cc/layers/touch_action_region.cc @@ -40,15 +40,15 @@ const Region& TouchActionRegion::GetRegionForTouchAction( return it->second; } -TouchAction TouchActionRegion::GetWhiteListedTouchAction( +TouchAction TouchActionRegion::GetAllowedTouchAction( const gfx::Point& point) const { - TouchAction white_listed_touch_action = kTouchActionAuto; + TouchAction allowed_touch_action = kTouchActionAuto; for (const auto& pair : map_) { if (!pair.second.Contains(point)) continue; - white_listed_touch_action &= pair.first; + allowed_touch_action &= pair.first; } - return white_listed_touch_action; + return allowed_touch_action; } TouchActionRegion& TouchActionRegion::operator=( diff --git a/chromium/cc/layers/touch_action_region.h b/chromium/cc/layers/touch_action_region.h index 5ad5c0c5aa7..4322646a36d 100644 --- a/chromium/cc/layers/touch_action_region.h +++ b/chromium/cc/layers/touch_action_region.h @@ -31,7 +31,7 @@ class CC_EXPORT TouchActionRegion { // given point. If the map is empty, |kTouchActionAuto| is returned since no // touch actions have been explicitly defined and the default touch action // is auto. - TouchAction GetWhiteListedTouchAction(const gfx::Point&) const; + TouchAction GetAllowedTouchAction(const gfx::Point&) const; TouchActionRegion& operator=(const TouchActionRegion& other); TouchActionRegion& operator=(TouchActionRegion&& other); bool operator==(const TouchActionRegion& other) const; diff --git a/chromium/cc/layers/touch_action_region_unittest.cc b/chromium/cc/layers/touch_action_region_unittest.cc index 7762f15c74b..1157982e6b6 100644 --- a/chromium/cc/layers/touch_action_region_unittest.cc +++ b/chromium/cc/layers/touch_action_region_unittest.cc @@ -9,58 +9,58 @@ namespace cc { namespace { -TEST(TouchActionRegionTest, GetWhiteListedTouchActionMapOverlapToZero) { +TEST(TouchActionRegionTest, GetAllowedTouchActionMapOverlapToZero) { TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionPanLeft, gfx::Rect(0, 0, 50, 50)); touch_action_region.Union(kTouchActionPanRight, gfx::Rect(25, 25, 25, 25)); // The point is only in PanLeft, so the result is PanLeft. EXPECT_EQ(kTouchActionPanLeft, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(10, 10))); + touch_action_region.GetAllowedTouchAction(gfx::Point(10, 10))); // The point is in both PanLeft and PanRight, and those actions have no // common components, so the result is None. EXPECT_EQ(kTouchActionNone, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(30, 30))); + touch_action_region.GetAllowedTouchAction(gfx::Point(30, 30))); // The point is in neither PanLeft nor PanRight, so the result is Auto since // the default touch action is auto. EXPECT_EQ(kTouchActionAuto, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(60, 60))); + touch_action_region.GetAllowedTouchAction(gfx::Point(60, 60))); } -TEST(TouchActionRegionTest, GetWhiteListedTouchActionMapOverlapToNonZero) { +TEST(TouchActionRegionTest, GetAllowedTouchActionMapOverlapToNonZero) { TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionPanX, gfx::Rect(0, 0, 50, 50)); touch_action_region.Union(kTouchActionPanRight, gfx::Rect(25, 25, 25, 25)); // The point is only in PanX, so the result is PanX. EXPECT_EQ(kTouchActionPanX, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(10, 10))); + touch_action_region.GetAllowedTouchAction(gfx::Point(10, 10))); // The point is in both PanX and PanRight, and PanRight is a common component, // so the result is PanRight. EXPECT_EQ(kTouchActionPanRight, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(30, 30))); + touch_action_region.GetAllowedTouchAction(gfx::Point(30, 30))); // The point is neither PanX nor PanRight, so the result is Auto since the // default touch action is auto. EXPECT_EQ(kTouchActionAuto, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(60, 60))); + touch_action_region.GetAllowedTouchAction(gfx::Point(60, 60))); } -TEST(TouchActionRegionTest, GetWhiteListedTouchActionEmptyMap) { +TEST(TouchActionRegionTest, GetAllowedTouchActionEmptyMap) { TouchActionRegion touch_action_region; // The result is Auto since the map is empty and the default touch // action is auto. EXPECT_EQ(kTouchActionAuto, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(10, 10))); + touch_action_region.GetAllowedTouchAction(gfx::Point(10, 10))); } -TEST(TouchActionRegionTest, GetWhiteListedTouchActionSingleMapEntry) { +TEST(TouchActionRegionTest, GetAllowedTouchActionSingleMapEntry) { TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionPanUp, gfx::Rect(0, 0, 50, 50)); // The point is only in PanUp, so the result is PanUp. EXPECT_EQ(kTouchActionPanUp, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(10, 10))); + touch_action_region.GetAllowedTouchAction(gfx::Point(10, 10))); // The point is not in PanUp, so the result is Auto since the default touch // action is auto. EXPECT_EQ(kTouchActionAuto, - touch_action_region.GetWhiteListedTouchAction(gfx::Point(60, 60))); + touch_action_region.GetAllowedTouchAction(gfx::Point(60, 60))); } TEST(TouchActionRegionTest, ConstructorFromMap) { diff --git a/chromium/cc/layers/ui_resource_layer.h b/chromium/cc/layers/ui_resource_layer.h index 57d2f031516..529ef85c69b 100644 --- a/chromium/cc/layers/ui_resource_layer.h +++ b/chromium/cc/layers/ui_resource_layer.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "cc/resources/ui_resource_client.h" @@ -21,6 +20,9 @@ class CC_EXPORT UIResourceLayer : public Layer { public: static scoped_refptr<UIResourceLayer> Create(); + UIResourceLayer(const UIResourceLayer&) = delete; + UIResourceLayer& operator=(const UIResourceLayer&) = delete; + void PushPropertiesTo(LayerImpl* layer) override; void SetLayerTreeHost(LayerTreeHost* host) override; @@ -66,8 +68,6 @@ class CC_EXPORT UIResourceLayer : public Layer { gfx::PointF uv_top_left_; gfx::PointF uv_bottom_right_; float vertex_opacity_[4]; - - DISALLOW_COPY_AND_ASSIGN(UIResourceLayer); }; } // namespace cc diff --git a/chromium/cc/layers/ui_resource_layer_impl.h b/chromium/cc/layers/ui_resource_layer_impl.h index 1283a23a9c3..f1ad51d00fa 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.h +++ b/chromium/cc/layers/ui_resource_layer_impl.h @@ -7,7 +7,6 @@ #include <string> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" @@ -31,8 +30,11 @@ class CC_EXPORT UIResourceLayerImpl : public LayerImpl { int id) { return base::WrapUnique(new UIResourceLayerImpl(tree_impl, id)); } + UIResourceLayerImpl(const UIResourceLayerImpl&) = delete; ~UIResourceLayerImpl() override; + UIResourceLayerImpl& operator=(const UIResourceLayerImpl&) = delete; + void SetUIResourceId(UIResourceId uid); void SetImageBounds(const gfx::Size& image_bounds); @@ -68,8 +70,6 @@ class CC_EXPORT UIResourceLayerImpl : public LayerImpl { private: const char* LayerTypeAsString() const override; - - DISALLOW_COPY_AND_ASSIGN(UIResourceLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/video_frame_provider_client_impl.h b/chromium/cc/layers/video_frame_provider_client_impl.h index 6c11f72b0a0..2798dd01cc8 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl.h +++ b/chromium/cc/layers/video_frame_provider_client_impl.h @@ -5,7 +5,6 @@ #ifndef CC_LAYERS_VIDEO_FRAME_PROVIDER_CLIENT_IMPL_H_ #define CC_LAYERS_VIDEO_FRAME_PROVIDER_CLIENT_IMPL_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" @@ -33,6 +32,10 @@ class CC_EXPORT VideoFrameProviderClientImpl VideoFrameProvider* provider, VideoFrameControllerClient* client); + VideoFrameProviderClientImpl(const VideoFrameProviderClientImpl&) = delete; + VideoFrameProviderClientImpl& operator=(const VideoFrameProviderClientImpl&) = + delete; + VideoLayerImpl* ActiveVideoLayer() const; void SetActiveVideoLayer(VideoLayerImpl* video_layer); @@ -82,8 +85,6 @@ class CC_EXPORT VideoFrameProviderClientImpl // from returning until the frame controller is done using the frame. base::Lock provider_lock_; base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameProviderClientImpl); }; } // namespace cc 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 32627b820e6..5d03c6700f2 100644 --- a/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc +++ b/chromium/cc/layers/video_frame_provider_client_impl_unittest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "cc/layers/video_frame_provider_client_impl.h" -#include "base/macros.h" #include "cc/layers/video_layer_impl.h" #include "cc/test/fake_video_frame_provider.h" #include "cc/test/layer_test_common.h" @@ -40,6 +39,8 @@ class VideoFrameProviderClientImplTest : public testing::Test, base::TimeDelta())) { DebugSetImplThreadAndMainThreadBlocked(impl_.task_runner_provider()); } + VideoFrameProviderClientImplTest(const VideoFrameProviderClientImplTest&) = + delete; ~VideoFrameProviderClientImplTest() override { if (!client_impl_->Stopped()) { @@ -51,6 +52,9 @@ class VideoFrameProviderClientImplTest : public testing::Test, provider_.SetVideoFrameProviderClient(nullptr); } + VideoFrameProviderClientImplTest& operator=( + const VideoFrameProviderClientImplTest&) = delete; + void StartRendering() { EXPECT_CALL(*this, AddVideoFrameController(_)); client_impl_->StartRendering(); @@ -92,9 +96,6 @@ class VideoFrameProviderClientImplTest : public testing::Test, scoped_refptr<VideoFrameProviderClientImpl> client_impl_; VideoLayerImpl* video_layer_impl_; scoped_refptr<media::VideoFrame> test_frame_; - - private: - DISALLOW_COPY_AND_ASSIGN(VideoFrameProviderClientImplTest); }; TEST_F(VideoFrameProviderClientImplTest, StartStopRendering) { diff --git a/chromium/cc/layers/video_layer.h b/chromium/cc/layers/video_layer.h index 02919b15273..0ae52c85ee1 100644 --- a/chromium/cc/layers/video_layer.h +++ b/chromium/cc/layers/video_layer.h @@ -6,7 +6,6 @@ #define CC_LAYERS_VIDEO_LAYER_H_ #include "base/callback.h" -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer.h" #include "media/base/video_rotation.h" @@ -24,6 +23,9 @@ class CC_EXPORT VideoLayer : public Layer { static scoped_refptr<VideoLayer> Create(VideoFrameProvider* provider, media::VideoRotation video_rotation); + VideoLayer(const VideoLayer&) = delete; + VideoLayer& operator=(const VideoLayer&) = delete; + std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; bool Update() override; @@ -40,8 +42,6 @@ class CC_EXPORT VideoLayer : public Layer { VideoFrameProvider* provider_; media::VideoRotation video_rotation_; - - DISALLOW_COPY_AND_ASSIGN(VideoLayer); }; } // namespace cc diff --git a/chromium/cc/layers/video_layer_impl.cc b/chromium/cc/layers/video_layer_impl.cc index eab1e6a145e..b76baeb77e0 100644 --- a/chromium/cc/layers/video_layer_impl.cc +++ b/chromium/cc/layers/video_layer_impl.cc @@ -159,8 +159,9 @@ void VideoLayerImpl::AppendQuads(viz::RenderPass* render_pass, return; updater_->AppendQuads( - render_pass, frame_, transform, quad_rect, visible_quad_rect, clip_rect(), - is_clipped(), contents_opaque(), draw_opacity(), GetSortingContextId()); + render_pass, frame_, transform, quad_rect, visible_quad_rect, + draw_properties().rounded_corner_bounds, clip_rect(), is_clipped(), + contents_opaque(), draw_opacity(), GetSortingContextId()); } void VideoLayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) { diff --git a/chromium/cc/layers/video_layer_impl.h b/chromium/cc/layers/video_layer_impl.h index 4b3646b0e16..0f715c7d319 100644 --- a/chromium/cc/layers/video_layer_impl.h +++ b/chromium/cc/layers/video_layer_impl.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer_impl.h" #include "components/viz/common/resources/release_callback.h" @@ -31,8 +30,11 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl { int id, VideoFrameProvider* provider, media::VideoRotation video_rotation); + VideoLayerImpl(const VideoLayerImpl&) = delete; ~VideoLayerImpl() override; + VideoLayerImpl& operator=(const VideoLayerImpl&) = delete; + // LayerImpl implementation. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; bool WillDraw(DrawMode draw_mode, @@ -63,8 +65,6 @@ class CC_EXPORT VideoLayerImpl : public LayerImpl { media::VideoRotation video_rotation_; std::unique_ptr<media::VideoResourceUpdater> updater_; - - DISALLOW_COPY_AND_ASSIGN(VideoLayerImpl); }; } // namespace cc diff --git a/chromium/cc/layers/viewport.cc b/chromium/cc/layers/viewport.cc index b99cee33e8a..c8985f23b49 100644 --- a/chromium/cc/layers/viewport.cc +++ b/chromium/cc/layers/viewport.cc @@ -49,21 +49,20 @@ Viewport::ScrollResult Viewport::ScrollBy(const gfx::Vector2dF& delta, gfx::Vector2dF pending_content_delta = content_delta; - ScrollNode* inner_node = InnerScrollNode(); + // Attempt to scroll inner viewport first. pending_content_delta -= host_impl_->ScrollSingleNode( - inner_node, pending_content_delta, viewport_point, is_direct_manipulation, - &scroll_tree()); - - ScrollResult result; + InnerScrollNode(), pending_content_delta, viewport_point, + is_direct_manipulation, &scroll_tree()); + // Now attempt to scroll the outer viewport. if (scroll_outer_viewport) { pending_content_delta -= host_impl_->ScrollSingleNode( OuterScrollNode(), pending_content_delta, viewport_point, is_direct_manipulation, &scroll_tree()); } + ScrollResult result; result.consumed_delta = delta - AdjustOverscroll(pending_content_delta); - result.content_scrolled_delta = content_delta - pending_content_delta; return result; } @@ -228,10 +227,19 @@ void Viewport::PinchEnd(const gfx::Point& anchor, bool snap_to_min) { pinch_zoom_active_ = false; } +bool Viewport::ShouldScroll(const ScrollNode& scroll_node) { + return scroll_node.scrolls_inner_viewport || + scroll_node.scrolls_outer_viewport; +} + LayerImpl* Viewport::MainScrollLayer() const { return host_impl_->OuterViewportScrollLayer(); } +ScrollNode* Viewport::MainScrollNode() const { + return host_impl_->OuterViewportScrollNode(); +} + gfx::Vector2dF Viewport::ScrollBrowserControls(const gfx::Vector2dF& delta) { gfx::Vector2dF excess_delta = host_impl_->browser_controls_manager()->ScrollBy(delta); @@ -279,6 +287,9 @@ gfx::ScrollOffset Viewport::MaxTotalScrollOffset() const { gfx::ScrollOffset Viewport::TotalScrollOffset() const { gfx::ScrollOffset offset; + if (!InnerScrollNode()) + return offset; + offset += scroll_tree().current_scroll_offset(InnerScrollNode()->element_id); if (auto* outer_node = OuterScrollNode()) diff --git a/chromium/cc/layers/viewport.h b/chromium/cc/layers/viewport.h index 275e826919f..b5c00b80d08 100644 --- a/chromium/cc/layers/viewport.h +++ b/chromium/cc/layers/viewport.h @@ -8,7 +8,6 @@ #include <memory> #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "cc/layers/layer_impl.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -38,6 +37,9 @@ class CC_EXPORT Viewport { static std::unique_ptr<Viewport> Create(LayerTreeHostImpl* host_impl); + Viewport(const Viewport&) = delete; + Viewport& operator=(const Viewport&) = delete; + // Differs from scrolling in that only the visual viewport is moved, without // affecting the browser controls or outer viewport. void Pan(const gfx::Vector2dF& delta); @@ -53,9 +55,7 @@ class CC_EXPORT Viewport { bool CanScroll(const ScrollState& scroll_state) const; - // Scrolls the viewport. Unlike the above method, scrolls the inner before - // the outer viewport. Doesn't affect browser controls or return a result - // since callers don't need it. + // TODO(bokan): Callers can now be replaced by ScrollBy. void ScrollByInnerFirst(const gfx::Vector2dF& delta); // Scrolls the viewport, bubbling the delta between the inner and outer @@ -68,10 +68,14 @@ class CC_EXPORT Viewport { void PinchUpdate(float magnify_delta, const gfx::Point& anchor); void PinchEnd(const gfx::Point& anchor, bool snap_to_min); - // Returns the "representative" viewport layer. That is, the one that's set - // as the currently scrolling layer when the viewport scrolls and the one used - // in the scrolling code to indicate scrolling should happen via this class. + // Returns true if the given scroll node should be scrolled via this class, + // false if it should be scrolled directly. + bool ShouldScroll(const ScrollNode& scroll_node); + + // Returns the "representative" viewport layer/node. That is, the one that's + // set as the currently scrolling layer/node when the viewport scrolls. LayerImpl* MainScrollLayer() const; + ScrollNode* MainScrollNode() const; private: explicit Viewport(LayerTreeHostImpl* host_impl); @@ -103,8 +107,6 @@ class CC_EXPORT Viewport { gfx::Vector2d pinch_anchor_adjustment_; FRIEND_TEST_ALL_PREFIXES(ViewportTest, ShouldAnimateViewport); - - DISALLOW_COPY_AND_ASSIGN(Viewport); }; } // namespace cc 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 812eda71393..4459afbbc22 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc @@ -319,7 +319,7 @@ void AsyncLayerTreeFrameSink::DidReceiveCompositorFrameAck( void AsyncLayerTreeFrameSink::OnBeginFrame( const viz::BeginFrameArgs& args, - const base::flat_map<uint32_t, gfx::PresentationFeedback>& feedbacks) { + const viz::PresentationFeedbackMap& feedbacks) { for (const auto& pair : feedbacks) { client_->DidPresentCompositorFrame(pair.first, pair.second); } 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 0750bcf231c..5ed49023a30 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h @@ -9,13 +9,13 @@ #include <string> #include <vector> -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "cc/mojo_embedder/mojo_embedder_export.h" #include "cc/trees/layer_tree_frame_sink.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/gpu/context_provider.h" +#include "components/viz/common/presentation_feedback_map.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/common/surfaces/surface_id.h" #include "mojo/public/cpp/bindings/binding.h" @@ -102,9 +102,11 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink scoped_refptr<viz::ContextProvider> context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider, InitParams* params); - + AsyncLayerTreeFrameSink(const AsyncLayerTreeFrameSink&) = delete; ~AsyncLayerTreeFrameSink() override; + AsyncLayerTreeFrameSink& operator=(const AsyncLayerTreeFrameSink&) = delete; + const viz::HitTestDataProvider* hit_test_data_provider() const { return hit_test_data_provider_.get(); } @@ -135,8 +137,7 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; void OnBeginFrame(const viz::BeginFrameArgs& begin_frame_args, - const base::flat_map<uint32_t, gfx::PresentationFeedback>& - feedbacks) override; + const viz::PresentationFeedbackMap& feedbacks) override; void OnBeginFramePausedChanged(bool paused) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; @@ -187,8 +188,6 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink // GraphicsPipeline.ClientName.SubmitCompositorFrameAfterBeginFrame base::HistogramBase* const submit_begin_frame_histogram_; base::WeakPtrFactory<AsyncLayerTreeFrameSink> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(AsyncLayerTreeFrameSink); }; } // namespace mojo_embedder 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 cc49361e62f..0a6f1d6ce29 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 @@ -39,8 +39,13 @@ class ThreadTrackingLayerTreeFrameSinkClient base::PlatformThreadId* called_thread_id, base::RunLoop* run_loop) : called_thread_id_(called_thread_id), run_loop_(run_loop) {} + ThreadTrackingLayerTreeFrameSinkClient( + const ThreadTrackingLayerTreeFrameSinkClient&) = delete; ~ThreadTrackingLayerTreeFrameSinkClient() override = default; + ThreadTrackingLayerTreeFrameSinkClient& operator=( + const ThreadTrackingLayerTreeFrameSinkClient&) = delete; + // FakeLayerTreeFrameSinkClient: void DidLoseLayerTreeFrameSink() override { EXPECT_FALSE(did_lose_layer_tree_frame_sink_called()); @@ -52,8 +57,6 @@ class ThreadTrackingLayerTreeFrameSinkClient private: base::PlatformThreadId* called_thread_id_; base::RunLoop* run_loop_; - - DISALLOW_COPY_AND_ASSIGN(ThreadTrackingLayerTreeFrameSinkClient); }; TEST(AsyncLayerTreeFrameSinkTest, @@ -190,7 +193,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, HitTestRegionListDuplicate) { gfx::Rect rect1(display_rect_); shared_quad_state1->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect1, - /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1, + /*visible_quad_layer_rect=*/rect1, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect1, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad1 = @@ -211,7 +215,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, HitTestRegionListDuplicate) { gfx::Rect rect2(display_rect_); shared_quad_state2->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect2, - /*visible_quad_layer_rect=*/rect2, /*clip_rect=*/rect2, + /*visible_quad_layer_rect=*/rect2, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad2 = @@ -239,7 +244,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, HitTestRegionListDuplicate) { transform3_0.Translate(-200, -100); shared_quad_state3_0->SetAll( transform3_0, /*quad_layer_rect=*/rect3_0, - /*visible_quad_layer_rect=*/rect3_0, /*clip_rect=*/rect3_0, + /*visible_quad_layer_rect=*/rect3_0, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3_0, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad3_0 = @@ -259,7 +265,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, HitTestRegionListDuplicate) { gfx::Rect rect3_1(display_rect_); shared_quad_state3_1->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect3_1, - /*visible_quad_layer_rect=*/rect3_1, /*clip_rect=*/rect3_1, + /*visible_quad_layer_rect=*/rect3_1, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3_1, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad3_1 = @@ -276,7 +283,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, HitTestRegionListDuplicate) { gfx::Rect rect3_root(display_rect_); shared_quad_state3_root->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect3_root, - /*visible_quad_layer_rect=*/rect3_root, /*clip_rect=*/rect3_root, + /*visible_quad_layer_rect=*/rect3_root, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3_root, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad3_root_1 = @@ -313,7 +321,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, gfx::Rect rect1(display_rect_); shared_quad_state1->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect1, - /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1, + /*visible_quad_layer_rect=*/rect1, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect1, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad1 = @@ -339,7 +348,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, transform2_0.Translate(-200, -100); shared_quad_state2_0->SetAll( transform2_0, /*quad_layer_rect=*/rect2_0, - /*visible_quad_layer_rect=*/rect2_0, /*clip_rect=*/rect2_0, + /*visible_quad_layer_rect=*/rect2_0, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2_0, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad2_0 = @@ -359,7 +369,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, gfx::Rect rect2_1(display_rect_); shared_quad_state2_1->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect2_1, - /*visible_quad_layer_rect=*/rect2_1, /*clip_rect=*/rect2_1, + /*visible_quad_layer_rect=*/rect2_1, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2_1, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad2_1 = @@ -376,7 +387,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, gfx::Rect rect2_root(display_rect_); shared_quad_state2_root->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect2_root, - /*visible_quad_layer_rect=*/rect2_root, /*clip_rect=*/rect2_root, + /*visible_quad_layer_rect=*/rect2_root, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect2_root, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad2_root_1 = @@ -411,7 +423,8 @@ TEST_F(AsyncLayerTreeFrameSinkSimpleTest, gfx::Rect rect3(display_rect_); shared_quad_state3->SetAll( gfx::Transform(), /*quad_layer_rect=*/rect3, - /*visible_quad_layer_rect=*/rect3, /*clip_rect=*/rect3, + /*visible_quad_layer_rect=*/rect3, + /*rounded_corner_bounds=*/gfx::RRectF(), /*clip_rect=*/rect3, /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); auto* quad3 = diff --git a/chromium/cc/paint/decode_stashing_image_provider.h b/chromium/cc/paint/decode_stashing_image_provider.h index 99a45d98758..e638d03fc2a 100644 --- a/chromium/cc/paint/decode_stashing_image_provider.h +++ b/chromium/cc/paint/decode_stashing_image_provider.h @@ -17,8 +17,12 @@ class CC_PAINT_EXPORT DecodeStashingImageProvider : public ImageProvider { public: // |source_provider| must outlive this class. explicit DecodeStashingImageProvider(ImageProvider* source_provider); + DecodeStashingImageProvider(const DecodeStashingImageProvider&) = delete; ~DecodeStashingImageProvider() override; + DecodeStashingImageProvider& operator=(const DecodeStashingImageProvider&) = + delete; + // ImageProvider implementation. ImageProvider::ScopedResult GetRasterContent( const DrawImage& draw_image) override; @@ -30,8 +34,6 @@ class CC_PAINT_EXPORT DecodeStashingImageProvider : public ImageProvider { private: ImageProvider* source_provider_; base::StackVector<ScopedResult, 1> decoded_images_; - - DISALLOW_COPY_AND_ASSIGN(DecodeStashingImageProvider); }; } // namespace cc diff --git a/chromium/cc/paint/discardable_image_map_unittest.cc b/chromium/cc/paint/discardable_image_map_unittest.cc index a83f1397874..2b9eee61fc1 100644 --- a/chromium/cc/paint/discardable_image_map_unittest.cc +++ b/chromium/cc/paint/discardable_image_map_unittest.cc @@ -565,9 +565,9 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInShader) { SkMatrix scale = SkMatrix::MakeScale(std::max(x * 0.5f, kMinScale), std::max(y * 0.5f, kMinScale)); PaintFlags flags; - flags.setShader(PaintShader::MakeImage( - discardable_image[y][x], SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, &scale)); + flags.setShader(PaintShader::MakeImage(discardable_image[y][x], + SkTileMode::kClamp, + SkTileMode::kClamp, &scale)); content_layer_client.add_draw_rect( gfx::Rect(x * 512 + 6, y * 512 + 6, 500, 500), flags); } @@ -749,8 +749,7 @@ TEST_F(DiscardableImageMapTest, CapturesImagesInPaintRecordShaders) { PaintFlags flags; SkRect tile = SkRect::MakeWH(100, 100); flags.setShader(PaintShader::MakePaintRecord( - shader_record, tile, SkShader::TileMode::kClamp_TileMode, - SkShader::TileMode::kClamp_TileMode, nullptr)); + shader_record, tile, SkTileMode::kClamp, SkTileMode::kClamp, nullptr)); display_list->push<DrawRectOp>(SkRect::MakeWH(200, 200), flags); display_list->EndPaintOfUnpaired(visible_rect); display_list->Finalize(); @@ -824,8 +823,8 @@ TEST_F(DiscardableImageMapTest, CapturesImagesInPaintFilters) { TEST_F(DiscardableImageMapTest, CapturesImagesInSaveLayers) { PaintFlags flags; PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100)); - flags.setShader(PaintShader::MakeImage(image, SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, nullptr)); + flags.setShader(PaintShader::MakeImage(image, SkTileMode::kClamp, + SkTileMode::kClamp, nullptr)); gfx::Rect visible_rect(500, 500); scoped_refptr<DisplayItemList> display_list = new DisplayItemList(); @@ -856,8 +855,7 @@ TEST_F(DiscardableImageMapTest, EmbeddedShaderWithAnimatedImages) { PaintImage animated_image = CreateAnimatedImage(gfx::Size(100, 100), frames); shader_record->push<DrawImageOp>(animated_image, 0.f, 0.f, nullptr); auto shader_with_image = PaintShader::MakePaintRecord( - shader_record, tile, SkShader::TileMode::kClamp_TileMode, - SkShader::TileMode::kClamp_TileMode, nullptr); + shader_record, tile, SkTileMode::kClamp, SkTileMode::kClamp, nullptr); // Create a second shader which uses the shader above. auto second_shader_record = sk_make_sp<PaintOpBuffer>(); @@ -865,8 +863,8 @@ TEST_F(DiscardableImageMapTest, EmbeddedShaderWithAnimatedImages) { flags.setShader(shader_with_image); second_shader_record->push<DrawRectOp>(SkRect::MakeWH(200, 200), flags); auto shader_with_shader_with_image = PaintShader::MakePaintRecord( - second_shader_record, tile, SkShader::TileMode::kClamp_TileMode, - SkShader::TileMode::kClamp_TileMode, nullptr); + second_shader_record, tile, SkTileMode::kClamp, SkTileMode::kClamp, + nullptr); gfx::Rect visible_rect(500, 500); scoped_refptr<DisplayItemList> display_list = new DisplayItemList(); diff --git a/chromium/cc/paint/display_item_list.cc b/chromium/cc/paint/display_item_list.cc index 5a467fb8a56..c82e1d2d13f 100644 --- a/chromium/cc/paint/display_item_list.cc +++ b/chromium/cc/paint/display_item_list.cc @@ -148,12 +148,15 @@ DisplayItemList::CreateTracedValue(bool include_items) const { state->BeginArray("items"); PlaybackParams params(nullptr, SkMatrix::I()); - const auto& bounds = rtree_.GetAllBoundsForTracing(); - size_t i = 0; + std::map<size_t, gfx::Rect> visual_rects = rtree_.GetAllBoundsForTracing(); for (const PaintOp* op : PaintOpBuffer::Iterator(&paint_op_buffer_)) { state->BeginDictionary(); state->SetString("name", PaintOpTypeToString(op->GetType())); - MathUtil::AddToTracedValue("visual_rect", bounds[i++], state.get()); + + MathUtil::AddToTracedValue( + "visual_rect", + visual_rects[paint_op_buffer_.GetOpOffsetForTracing(op)], + state.get()); SkPictureRecorder recorder; SkCanvas* canvas = diff --git a/chromium/cc/paint/display_item_list.h b/chromium/cc/paint/display_item_list.h index a61ed5c1adf..d11f49ad6a1 100644 --- a/chromium/cc/paint/display_item_list.h +++ b/chromium/cc/paint/display_item_list.h @@ -12,7 +12,6 @@ #include <vector> #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/trace_event/trace_event.h" #include "cc/base/rtree.h" @@ -58,6 +57,8 @@ class CC_PAINT_EXPORT DisplayItemList enum UsageHint { kTopLevelDisplayItemList, kToBeReleasedAsPaintOpBuffer }; explicit DisplayItemList(UsageHint = kTopLevelDisplayItemList); + DisplayItemList(const DisplayItemList&) = delete; + DisplayItemList& operator=(const DisplayItemList&) = delete; void Raster(SkCanvas* canvas, ImageProvider* image_provider = nullptr) const; @@ -105,12 +106,11 @@ class CC_PAINT_EXPORT DisplayItemList if (usage_hint_ == kToBeReleasedAsPaintOpBuffer) return; - while (visual_rects_.size() < paint_op_buffer_.size()) - visual_rects_.push_back(visual_rect); + visual_rects_.resize(paint_op_buffer_.size(), visual_rect); GrowCurrentBeginItemVisualRect(visual_rect); } - void EndPaintOfPairedBegin(const gfx::Rect& visual_rect = gfx::Rect()) { + void EndPaintOfPairedBegin() { #if DCHECK_IS_ON() DCHECK(IsPainting()); DCHECK_LT(current_range_start_, paint_op_buffer_.size()); @@ -121,8 +121,7 @@ class CC_PAINT_EXPORT DisplayItemList DCHECK_LT(visual_rects_.size(), paint_op_buffer_.size()); size_t count = paint_op_buffer_.size() - visual_rects_.size(); - for (size_t i = 0; i < count; ++i) - visual_rects_.push_back(visual_rect); + visual_rects_.resize(paint_op_buffer_.size()); begin_paired_indices_.push_back( std::make_pair(visual_rects_.size() - 1, count)); } @@ -154,8 +153,7 @@ class CC_PAINT_EXPORT DisplayItemList begin_paired_indices_.pop_back(); // Copy the visual rect of the matching begin item to the end item(s). - while (visual_rects_.size() < paint_op_buffer_.size()) - visual_rects_.push_back(visual_rect); + visual_rects_.resize(paint_op_buffer_.size(), visual_rect); // The block that ended needs to be included in the bounds of the enclosing // block. @@ -197,6 +195,7 @@ class CC_PAINT_EXPORT DisplayItemList int max_ops_to_analyze = 1); private: + FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, TraceEmptyVisualRect); FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithNoOps); FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithOps); friend gpu::raster::RasterImplementation; @@ -247,7 +246,6 @@ class CC_PAINT_EXPORT DisplayItemList friend class base::RefCountedThreadSafe<DisplayItemList>; FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, BytesUsed); - DISALLOW_COPY_AND_ASSIGN(DisplayItemList); }; } // namespace cc diff --git a/chromium/cc/paint/display_item_list_unittest.cc b/chromium/cc/paint/display_item_list_unittest.cc index 0abe50d535c..8124f7724b9 100644 --- a/chromium/cc/paint/display_item_list_unittest.cc +++ b/chromium/cc/paint/display_item_list_unittest.cc @@ -77,6 +77,54 @@ bool CompareN32Pixels(void* actual_pixels, EXPECT_EQ(height, d); \ } while (false) +// CreateTracedValue should not crash if there are different numbers of +// visual_rect are paint_op +TEST(DisplayItemListTest, TraceEmptyVisualRect) { + PaintFlags red_paint; + red_paint.setColor(SK_ColorRED); + auto list = base::MakeRefCounted<DisplayItemList>(); + + gfx::Point offset(8, 9); + + list->StartPaint(); + list->push<DrawRectOp>(SkRect::MakeEmpty(), red_paint); + // The rect is empty to cause rtree generation to skip it. + list->EndPaintOfUnpaired(gfx::Rect(offset, gfx::Size(0, 10))); + list->StartPaint(); + list->push<DrawRectOp>(SkRect::MakeXYWH(0, 0, 10, 10), red_paint); + // This rect is not empty. + list->EndPaintOfUnpaired(gfx::Rect(offset, gfx::Size(10, 10))); + list->Finalize(); + + // Pass: we don't crash + std::unique_ptr<base::Value> root = + list->CreateTracedValue(true)->ToBaseValue(); + + const base::DictionaryValue* root_dict; + ASSERT_TRUE(root->GetAsDictionary(&root_dict)); + const base::DictionaryValue* params_dict; + ASSERT_TRUE(root_dict->GetDictionary("params", ¶ms_dict)); + const base::ListValue* items; + ASSERT_TRUE(params_dict->GetList("items", &items)); + ASSERT_EQ(2u, items->GetSize()); + + const base::DictionaryValue* item_dict; + const base::ListValue* visual_rect; + std::string name; + + ASSERT_TRUE(items->GetDictionary(0, &item_dict)); + 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)); + 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)); + EXPECT_EQ("DrawRect", name); +} + TEST(DisplayItemListTest, SingleUnpairedRange) { gfx::Rect layer_rect(100, 100); PaintFlags blue_flags; diff --git a/chromium/cc/paint/image_provider.cc b/chromium/cc/paint/image_provider.cc index fa224ad5c86..e30c8bb5e7d 100644 --- a/chromium/cc/paint/image_provider.cc +++ b/chromium/cc/paint/image_provider.cc @@ -17,27 +17,24 @@ ImageProvider::ScopedResult::ScopedResult(DecodedDrawImage image, DestructionCallback callback) : image_(std::move(image)), destruction_callback_(std::move(callback)) {} -ImageProvider::ScopedResult::ScopedResult(const PaintRecord* record, +ImageProvider::ScopedResult::ScopedResult(sk_sp<PaintRecord> record, DestructionCallback callback) - : record_(record), destruction_callback_(std::move(callback)) { + : record_(std::move(record)), destruction_callback_(std::move(callback)) { DCHECK(!destruction_callback_.is_null()); } ImageProvider::ScopedResult::ScopedResult(ScopedResult&& other) : image_(std::move(other.image_)), - record_(other.record_), - destruction_callback_(std::move(other.destruction_callback_)) { - other.record_ = nullptr; -} + record_(std::move(other.record_)), + destruction_callback_(std::move(other.destruction_callback_)) {} ImageProvider::ScopedResult& ImageProvider::ScopedResult::operator=( ScopedResult&& other) { DestroyDecode(); image_ = std::move(other.image_); - record_ = other.record_; + record_ = std::move(other.record_); destruction_callback_ = std::move(other.destruction_callback_); - other.record_ = nullptr; return *this; } diff --git a/chromium/cc/paint/image_provider.h b/chromium/cc/paint/image_provider.h index 9ec5b3b8ee5..2b5e5f70713 100644 --- a/chromium/cc/paint/image_provider.h +++ b/chromium/cc/paint/image_provider.h @@ -10,6 +10,7 @@ #include "cc/paint/decoded_draw_image.h" #include "cc/paint/draw_image.h" #include "cc/paint/paint_export.h" +#include "cc/paint/paint_op_buffer.h" #include <vector> @@ -27,10 +28,12 @@ class CC_PAINT_EXPORT ImageProvider { ScopedResult(); explicit ScopedResult(DecodedDrawImage image); ScopedResult(DecodedDrawImage image, DestructionCallback callback); - ScopedResult(const PaintRecord* record, DestructionCallback callback); + ScopedResult(sk_sp<PaintRecord> record, DestructionCallback callback); + ScopedResult(const ScopedResult&) = delete; + ScopedResult(ScopedResult&& other); ~ScopedResult(); - ScopedResult(ScopedResult&& other); + ScopedResult& operator=(const ScopedResult&) = delete; ScopedResult& operator=(ScopedResult&& other); operator bool() const { return image_ || record_; } @@ -38,17 +41,15 @@ class CC_PAINT_EXPORT ImageProvider { bool needs_unlock() const { return !destruction_callback_.is_null(); } const PaintRecord* paint_record() { DCHECK(record_); - return record_; + return record_.get(); } private: void DestroyDecode(); DecodedDrawImage image_; - const PaintRecord* record_ = nullptr; + sk_sp<PaintRecord> record_; DestructionCallback destruction_callback_; - - DISALLOW_COPY_AND_ASSIGN(ScopedResult); }; virtual ~ImageProvider() {} diff --git a/chromium/cc/paint/image_transfer_cache_entry.cc b/chromium/cc/paint/image_transfer_cache_entry.cc index 2500e4e3ebf..ff7b98fcc86 100644 --- a/chromium/cc/paint/image_transfer_cache_entry.cc +++ b/chromium/cc/paint/image_transfer_cache_entry.cc @@ -108,6 +108,8 @@ uint32_t ClientImageTransferCacheEntry::Id() const { bool ClientImageTransferCacheEntry::Serialize(base::span<uint8_t> data) const { DCHECK_GE(data.size(), SerializedSize()); + DCHECK_GT(pixmap_->width(), 0); + DCHECK_GT(pixmap_->height(), 0); // We don't need to populate the SerializeOptions here since the writer is // only used for serializing primitives. @@ -153,7 +155,7 @@ bool ServiceImageTransferCacheEntry::BuildFromDecodedData( size_ = image_info.computeByteSize(row_bytes); if (size_ == SIZE_MAX) return false; - DCHECK_EQ(size_, decoded_image.size()); + DCHECK_LE(size_, decoded_image.size()); uint32_t width; uint32_t height; @@ -181,8 +183,14 @@ bool ServiceImageTransferCacheEntry::Deserialize( PaintOp::DeserializeOptions options(nullptr, nullptr, nullptr, &scratch_buffer); PaintOpReader reader(data.data(), data.size(), options); - SkColorType color_type; + SkColorType color_type = kUnknown_SkColorType; reader.Read(&color_type); + + if (color_type == kUnknown_SkColorType || + color_type == kRGB_101010x_SkColorType || + color_type > kLastEnum_SkColorType) + return false; + uint32_t width; reader.Read(&width); uint32_t height; @@ -192,7 +200,6 @@ bool ServiceImageTransferCacheEntry::Deserialize( has_mips_ = needs_mips; size_t pixel_size; reader.ReadSize(&pixel_size); - size_ = data.size(); sk_sp<SkColorSpace> pixmap_color_space; reader.Read(&pixmap_color_space); sk_sp<SkColorSpace> target_color_space; @@ -214,6 +221,13 @@ bool ServiceImageTransferCacheEntry::Deserialize( DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(pixel_data))); + if (width == 0 || height == 0) + return false; + + // Match GrTexture::onGpuMemorySize so that memory traces agree. + auto gr_mips = has_mips_ ? GrMipMapped::kYes : GrMipMapped::kNo; + size_ = GrContext::ComputeTextureSize(color_type, width, height, gr_mips); + // Const-cast away the "volatile" on |pixel_data|. We specifically understand // that a malicious caller may change our pixels under us, and are OK with // this as the worst case scenario is visual corruption. diff --git a/chromium/cc/paint/oop_pixeltest.cc b/chromium/cc/paint/oop_pixeltest.cc index c7df545cc68..c1cf6f7a30a 100644 --- a/chromium/cc/paint/oop_pixeltest.cc +++ b/chromium/cc/paint/oop_pixeltest.cc @@ -82,6 +82,8 @@ class OopPixelTest : public testing::Test, /*enable_oop_rasterization=*/false, /*support_locking=*/true); gpu::ContextResult result = gles2_context_provider_->BindToCurrentThread(); DCHECK_EQ(result, gpu::ContextResult::kSuccess); + CHECK_EQ(gles2_context_provider_->ContextCapabilities().max_texture_size, + raster_context_provider_->ContextCapabilities().max_texture_size); } // gpu::raster::GrShaderCache::Client implementation. @@ -298,7 +300,8 @@ class OopPixelTest : public testing::Test, SkSurfaceProps(flags, SkSurfaceProps::kLegacyFontHost_InitType); } SkImageInfo image_info = SkImageInfo::MakeN32Premul( - options.resource_size.width(), options.resource_size.height()); + options.resource_size.width(), options.resource_size.height(), + options.color_space.ToSkColorSpace()); auto surface = SkSurface::MakeRenderTarget( gles2_context_provider_->GrContext(), SkBudgeted::kYes, image_info); SkCanvas* canvas = surface->getCanvas(); @@ -310,10 +313,9 @@ class OopPixelTest : public testing::Test, gfx::AxisTransform2d raster_transform(options.post_scale, options.post_translate); raster_source->PlaybackToCanvas( - canvas, options.color_space, options.content_size, - options.full_raster_rect, options.playback_rect, raster_transform, - settings); - surface->prepareForExternalIO(); + canvas, options.content_size, options.full_raster_rect, + options.playback_rect, raster_transform, settings); + surface->flush(); EXPECT_EQ(gles2_context_provider_->ContextGL()->GetError(), static_cast<unsigned>(GL_NO_ERROR)); @@ -564,9 +566,8 @@ TEST_P(OopImagePixelTest, DrawImageShaderScaled) { auto builder = PaintImageBuilder::WithDefault().set_image(image, 0).set_id( PaintImage::GetNextId()); auto paint_image = builder.TakePaintImage(); - auto paint_image_shader = - PaintShader::MakeImage(paint_image, SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, nullptr); + auto paint_image_shader = PaintShader::MakeImage( + paint_image, SkTileMode::kRepeat, SkTileMode::kRepeat, nullptr); auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); @@ -610,8 +611,8 @@ TEST_P(OopImagePixelTest, DrawRecordShaderWithImageScaled) { flags.setFilterQuality(FilterQuality()); paint_record->push<DrawImageOp>(paint_image, 0.f, 0.f, &flags); auto paint_record_shader = PaintShader::MakePaintRecord( - paint_record, gfx::RectToSkRect(rect), SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, nullptr); + paint_record, gfx::RectToSkRect(rect), SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr); auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); @@ -654,9 +655,8 @@ TEST_F(OopImagePixelTest, DrawRecordShaderTranslatedTileRect) { SkRect tile_rect = SkRect::MakeXYWH(x_offset, y_offset, 2, 3); sk_sp<PaintShader> paint_record_shader = PaintShader::MakePaintRecord( - shader_buffer, tile_rect, SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, nullptr, - PaintShader::ScalingBehavior::kRasterAtScale); + shader_buffer, tile_rect, SkTileMode::kRepeat, SkTileMode::kRepeat, + nullptr, PaintShader::ScalingBehavior::kRasterAtScale); gfx::Size output_size(10, 10); @@ -1467,8 +1467,8 @@ class OopRecordShaderPixelTest : public OopPixelTest, paint_record->push<DrawTextBlobOp>( BuildTextBlob(SkTypeface::MakeDefault(), UseLcdText()), 0u, 0u, flags); auto paint_record_shader = PaintShader::MakePaintRecord( - paint_record, SkRect::MakeWH(25, 25), SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, nullptr); + paint_record, SkRect::MakeWH(25, 25), SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr); auto display_item_list = base::MakeRefCounted<DisplayItemList>(); display_item_list->StartPaint(); @@ -1658,6 +1658,40 @@ TEST_P(OopPathPixelTest, Basic) { RunTest(); } +TEST_F(OopPixelTest, RecordShaderExceedsMaxTextureSize) { + const int max_texture_size = + raster_context_provider_->ContextCapabilities().max_texture_size; + const SkRect rect = SkRect::MakeWH(max_texture_size + 10, 10); + + auto shader_record = sk_make_sp<PaintRecord>(); + shader_record->push<DrawColorOp>(SK_ColorWHITE, SkBlendMode::kSrc); + PaintFlags flags; + flags.setStyle(PaintFlags::kFill_Style); + flags.setColor(SK_ColorGREEN); + shader_record->push<DrawRectOp>(rect, flags); + auto shader = PaintShader::MakePaintRecord( + shader_record, rect, SkTileMode::kRepeat, SkTileMode::kRepeat, nullptr); + + RasterOptions options; + options.resource_size = gfx::Size(100, 100); + options.content_size = gfx::Size(rect.width(), rect.height()); + options.full_raster_rect = gfx::Rect(options.content_size); + options.playback_rect = options.full_raster_rect; + options.color_space = gfx::ColorSpace::CreateSRGB(); + + auto display_item_list = base::MakeRefCounted<DisplayItemList>(); + display_item_list->StartPaint(); + display_item_list->push<DrawColorOp>(SK_ColorWHITE, SkBlendMode::kSrc); + flags.setShader(shader); + display_item_list->push<DrawRectOp>(rect, flags); + display_item_list->EndPaintOfUnpaired(options.full_raster_rect); + display_item_list->Finalize(); + + auto expected = RasterExpectedBitmap(display_item_list, options); + auto actual = Raster(display_item_list, options); + ExpectEquals(actual, expected); +} + INSTANTIATE_TEST_SUITE_P(P, OopImagePixelTest, ::testing::Bool()); INSTANTIATE_TEST_SUITE_P(P, OopClearPixelTest, ::testing::Bool()); INSTANTIATE_TEST_SUITE_P(P, OopRecordShaderPixelTest, ::testing::Bool()); diff --git a/chromium/cc/paint/paint_cache.h b/chromium/cc/paint/paint_cache.h index 3413f439d11..f4467014ef3 100644 --- a/chromium/cc/paint/paint_cache.h +++ b/chromium/cc/paint/paint_cache.h @@ -50,8 +50,11 @@ constexpr size_t PaintCacheDataTypeCount = class CC_PAINT_EXPORT ClientPaintCache { public: explicit ClientPaintCache(size_t max_budget_bytes); + ClientPaintCache(const ClientPaintCache&) = delete; ~ClientPaintCache(); + ClientPaintCache& operator=(const ClientPaintCache&) = delete; + bool Get(PaintCacheDataType type, PaintCacheId id); void Put(PaintCacheDataType type, PaintCacheId id, size_t size); @@ -89,8 +92,6 @@ class CC_PAINT_EXPORT ClientPaintCache { // send them to the service-side cache. This is necessary to ensure we // maintain an accurate mirror of the service-side state. base::StackVector<CacheKey, 1> pending_entries_; - - DISALLOW_COPY_AND_ASSIGN(ClientPaintCache); }; class CC_PAINT_EXPORT ServicePaintCache { diff --git a/chromium/cc/paint/paint_canvas.h b/chromium/cc/paint/paint_canvas.h index 342e20e445f..0f0c694eff1 100644 --- a/chromium/cc/paint/paint_canvas.h +++ b/chromium/cc/paint/paint_canvas.h @@ -6,7 +6,6 @@ #define CC_PAINT_PAINT_CANVAS_H_ #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "cc/paint/paint_export.h" @@ -42,8 +41,11 @@ using PaintRecord = PaintOpBuffer; // from SkCanvas to PaintCanvas or from SkPicture back into PaintRecord. class CC_PAINT_EXPORT PaintCanvas { public: - PaintCanvas() {} - virtual ~PaintCanvas() {} + PaintCanvas() = default; + PaintCanvas(const PaintCanvas&) = delete; + virtual ~PaintCanvas() = default; + + PaintCanvas& operator=(const PaintCanvas&) = delete; // TODO(enne): this only appears to mostly be used to determine if this is // recording or not, so could be simplified or removed. @@ -193,8 +195,6 @@ class CC_PAINT_EXPORT PaintCanvas { private: printing::MetafileSkia* metafile_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(PaintCanvas); }; class CC_PAINT_EXPORT PaintCanvasAutoRestore { diff --git a/chromium/cc/paint/paint_filter.cc b/chromium/cc/paint/paint_filter.cc index d4c2e34e229..fed94c718ba 100644 --- a/chromium/cc/paint/paint_filter.cc +++ b/chromium/cc/paint/paint_filter.cc @@ -980,7 +980,7 @@ PaintFlagsPaintFilter::PaintFlagsPaintFilter(PaintFlags flags, : PaintFilter(kType, crop_rect, flags.HasDiscardableImages()), flags_(std::move(flags)) { if (image_provider) { - raster_flags_.emplace(&flags_, image_provider, SkMatrix::I(), 255u); + raster_flags_.emplace(&flags_, image_provider, SkMatrix::I(), 0, 255u); } cached_sk_filter_ = SkPaintImageFilter::Make( raster_flags_ ? raster_flags_->flags()->ToSkPaint() : flags_.ToSkPaint(), diff --git a/chromium/cc/paint/paint_filter.h b/chromium/cc/paint/paint_filter.h index 7710d501551..bdf724ab1e2 100644 --- a/chromium/cc/paint/paint_filter.h +++ b/chromium/cc/paint/paint_filter.h @@ -72,8 +72,11 @@ class CC_PAINT_EXPORT PaintFilter : public SkRefCnt { using MapDirection = SkImageFilter::MapDirection; using CropRect = SkImageFilter::CropRect; + PaintFilter(const PaintFilter&) = delete; ~PaintFilter() override; + PaintFilter& operator=(const PaintFilter&) = delete; + static std::string TypeToString(Type type); // Returns the size required to serialize the |filter|. Note that |filter| can @@ -156,8 +159,6 @@ class CC_PAINT_EXPORT PaintFilter : public SkRefCnt { const bool has_discardable_images_; ImageAnalysisState image_analysis_state_ = ImageAnalysisState::kNoAnalysis; - - DISALLOW_COPY_AND_ASSIGN(PaintFilter); }; class CC_PAINT_EXPORT ColorFilterPaintFilter final : public PaintFilter { diff --git a/chromium/cc/paint/paint_filter_unittest.cc b/chromium/cc/paint/paint_filter_unittest.cc index a6d5b529d68..1cf676527c6 100644 --- a/chromium/cc/paint/paint_filter_unittest.cc +++ b/chromium/cc/paint/paint_filter_unittest.cc @@ -114,9 +114,8 @@ sk_sp<PaintFilter> CreateTestFilter(PaintFilter::Type filter_type, 0.3f, nullptr, &crop_rect); case PaintFilter::Type::kPaintFlags: { PaintFlags flags; - flags.setShader(PaintShader::MakeImage(image, SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, - nullptr)); + flags.setShader(PaintShader::MakeImage(image, SkTileMode::kClamp, + SkTileMode::kClamp, nullptr)); return sk_make_sp<PaintFlagsPaintFilter>(flags, &crop_rect); } case PaintFilter::Type::kMatrix: diff --git a/chromium/cc/paint/paint_image.cc b/chromium/cc/paint/paint_image.cc index 08f0012d9e5..da3132062c8 100644 --- a/chromium/cc/paint/paint_image.cc +++ b/chromium/cc/paint/paint_image.cc @@ -7,7 +7,7 @@ #include <memory> #include "base/atomic_sequence_num.h" -#include "base/hash.h" +#include "base/hash/hash.h" #include "cc/paint/paint_image_builder.h" #include "cc/paint/paint_image_generator.h" #include "cc/paint/paint_record.h" @@ -152,6 +152,13 @@ void PaintImage::CreateSkImage() { } } +bool PaintImage::IsEligibleForAcceleratedDecoding() const { + if (!CanDecodeFromGenerator()) + return false; + DCHECK(paint_image_generator_); + return paint_image_generator_->IsEligibleForAcceleratedDecoding(); +} + SkISize PaintImage::GetSupportedDecodeSize( const SkISize& requested_size) const { // TODO(vmpstr): In some cases we do not support decoding to any other diff --git a/chromium/cc/paint/paint_image.h b/chromium/cc/paint/paint_image.h index 3320244605c..2f68f070c16 100644 --- a/chromium/cc/paint/paint_image.h +++ b/chromium/cc/paint/paint_image.h @@ -140,6 +140,18 @@ class CC_PAINT_EXPORT PaintImage { bool operator==(const PaintImage& other) const; bool operator!=(const PaintImage& other) const { return !(*this == other); } + // Returns true if the image is eligible for decoding using a hardware + // accelerator (which would require at least that all the encoded data has + // been received). Returns false otherwise or if the image cannot be decoded + // from a PaintImageGenerator. Notice that a return value of true does not + // guarantee that the hardware accelerator supports the image. It only + // indicates that the software decoder hasn't done any work with the image, so + // sending it to a hardware decoder is appropriate. + // + // TODO(andrescj): consider supporting the non-PaintImageGenerator path which + // is expected to be rare. + bool IsEligibleForAcceleratedDecoding() const; + // Returns the smallest size that is at least as big as the requested_size // such that we can decode to exactly that scale. If the requested size is // larger than the image, this returns the image size. Any returned value is diff --git a/chromium/cc/paint/paint_image_generator.h b/chromium/cc/paint/paint_image_generator.h index d0ce1c75c02..5e4f474296e 100644 --- a/chromium/cc/paint/paint_image_generator.h +++ b/chromium/cc/paint/paint_image_generator.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "cc/paint/frame_metadata.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_image.h" @@ -25,8 +24,19 @@ namespace cc { // be called from any thread. class CC_PAINT_EXPORT PaintImageGenerator : public SkRefCnt { public: + PaintImageGenerator(const PaintImageGenerator&) = delete; ~PaintImageGenerator() override; + PaintImageGenerator& operator=(const PaintImageGenerator&) = delete; + + // Returns true if we can guarantee that the software decoder hasn't done work + // on the image, so it's appropriate to send the encoded image to a hardware + // accelerator. False if we can't guarantee this or if not applicable. For + // example, if the encoded data comes incrementally, and the software decoder + // starts working with partial data, the image shouldn't later be sent to a + // hardware decoder. + virtual bool IsEligibleForAcceleratedDecoding() const = 0; + // Returns a reference to the encoded content of this image. virtual sk_sp<SkData> GetEncodedData() const = 0; @@ -87,8 +97,6 @@ class CC_PAINT_EXPORT PaintImageGenerator : public SkRefCnt { const SkImageInfo info_; const PaintImage::ContentId generator_content_id_; const std::vector<FrameMetadata> frames_; - - DISALLOW_COPY_AND_ASSIGN(PaintImageGenerator); }; } // namespace cc diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc index 8ab81477823..7c047cd1019 100644 --- a/chromium/cc/paint/paint_op_buffer.cc +++ b/chromium/cc/paint/paint_op_buffer.cc @@ -16,6 +16,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkRegion.h" #include "third_party/skia/include/core/SkSerialProcs.h" +#include "third_party/skia/include/gpu/GrContext.h" namespace cc { namespace { @@ -2245,7 +2246,7 @@ PaintOpBuffer::~PaintOpBuffer() { Reset(); } -void PaintOpBuffer::operator=(PaintOpBuffer&& other) { +PaintOpBuffer& PaintOpBuffer::operator=(PaintOpBuffer&& other) { data_ = std::move(other.data_); used_ = other.used_; reserved_ = other.reserved_; @@ -2260,6 +2261,7 @@ void PaintOpBuffer::operator=(PaintOpBuffer&& other) { other.used_ = 0; other.op_count_ = 0; other.reserved_ = 0; + return *this; } void PaintOpBuffer::Reset() { @@ -2425,9 +2427,10 @@ void PaintOpBuffer::Playback(SkCanvas* canvas, if (op->IsPaintOpWithFlags()) { const auto* flags_op = static_cast<const PaintOpWithFlags*>(op); + auto* context = canvas->getGrContext(); const ScopedRasterFlags scoped_flags( &flags_op->flags, new_params.image_provider, canvas->getTotalMatrix(), - iter.alpha()); + context ? context->maxTextureSize() : 0, iter.alpha()); if (const auto* raster_flags = scoped_flags.flags()) flags_op->RasterWithFlags(canvas, raster_flags, new_params); } else { diff --git a/chromium/cc/paint/paint_op_buffer.h b/chromium/cc/paint/paint_op_buffer.h index e7e36a5d59d..943fe9c9dd5 100644 --- a/chromium/cc/paint/paint_op_buffer.h +++ b/chromium/cc/paint/paint_op_buffer.h @@ -920,10 +920,12 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { } PaintOpBuffer(); + PaintOpBuffer(const PaintOpBuffer&) = delete; PaintOpBuffer(PaintOpBuffer&& other); ~PaintOpBuffer() override; - void operator=(PaintOpBuffer&& other); + PaintOpBuffer& operator=(const PaintOpBuffer&) = delete; + PaintOpBuffer& operator=(PaintOpBuffer&& other); void Reset(); @@ -1024,6 +1026,13 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { return nullptr; } + size_t GetOpOffsetForTracing(const PaintOp* op) const { + DCHECK_GE(reinterpret_cast<const char*>(op), data_.get()); + size_t result = reinterpret_cast<const char*>(op) - data_.get(); + DCHECK_LT(result, used_); + return result; + } + class CC_PAINT_EXPORT Iterator { public: explicit Iterator(const PaintOpBuffer* buffer) @@ -1230,8 +1239,6 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { bool has_non_aa_paint_ : 1; bool has_discardable_images_ : 1; - - DISALLOW_COPY_AND_ASSIGN(PaintOpBuffer); }; } // namespace cc diff --git a/chromium/cc/paint/paint_op_buffer_serializer.cc b/chromium/cc/paint/paint_op_buffer_serializer.cc index 8287247c5a4..d911d35e4b4 100644 --- a/chromium/cc/paint/paint_op_buffer_serializer.cc +++ b/chromium/cc/paint/paint_op_buffer_serializer.cc @@ -5,6 +5,7 @@ #include "cc/paint/paint_op_buffer_serializer.h" #include "base/bind.h" +#include "base/trace_event/trace_event.h" #include "cc/paint/scoped_raster_flags.h" #include "ui/gfx/skia_util.h" @@ -83,6 +84,8 @@ PaintOpBufferSerializer::PaintOpBufferSerializer( 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_bytes_(max_texture_bytes), text_blob_canvas_(kMaxExtent, kMaxExtent, ComputeSurfaceProps(can_use_lcd_text), @@ -314,8 +317,9 @@ bool PaintOpBufferSerializer::SerializeOpWithFlags( uint8_t alpha) { // We use a null |image_provider| here because images are decoded during // serialization. - const ScopedRasterFlags scoped_flags( - &flags_op->flags, nullptr, options->canvas->getTotalMatrix(), alpha); + const ScopedRasterFlags scoped_flags(&flags_op->flags, nullptr, + options->canvas->getTotalMatrix(), + max_texture_size_, alpha); const PaintFlags* flags_to_serialize = scoped_flags.flags(); if (!flags_to_serialize) return true; @@ -328,6 +332,9 @@ bool PaintOpBufferSerializer::SerializeOp( const PaintOp* op, const PaintOp::SerializeOptions& options, const PlaybackParams& params) { + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "PaintOpBufferSerializer::SerializeOp", "op", + PaintOpTypeToString(op->GetType())); if (!valid_) return false; diff --git a/chromium/cc/paint/paint_op_buffer_unittest.cc b/chromium/cc/paint/paint_op_buffer_unittest.cc index a2b1cbd4b50..0f6f7b74eca 100644 --- a/chromium/cc/paint/paint_op_buffer_unittest.cc +++ b/chromium/cc/paint/paint_op_buffer_unittest.cc @@ -58,8 +58,8 @@ class PaintOpSerializationTestUtils { shader->flags_ = 12345; shader->end_radius_ = 12.3f; shader->start_radius_ = 13.4f; - shader->tx_ = SkShader::kRepeat_TileMode; - shader->ty_ = SkShader::kMirror_TileMode; + shader->tx_ = SkTileMode::kRepeat; + shader->ty_ = SkTileMode::kMirror; shader->fallback_color_ = SkColorSetARGB(254, 252, 250, 248); shader->scaling_behavior_ = PaintShader::ScalingBehavior::kRasterAtScale; if (use_matrix) { @@ -452,9 +452,8 @@ TEST(PaintOpBufferTest, DiscardableImagesTracking_OpWithFlags) { PaintOpBuffer buffer; PaintFlags flags; auto image = CreateDiscardablePaintImage(gfx::Size(100, 100)); - flags.setShader(PaintShader::MakeImage(std::move(image), - SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode, nullptr)); + flags.setShader(PaintShader::MakeImage(std::move(image), SkTileMode::kClamp, + SkTileMode::kClamp, nullptr)); buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags); EXPECT_TRUE(buffer.HasDiscardableImages()); } @@ -1122,8 +1121,8 @@ std::vector<PaintFlags> test_flags = { SkColorSetARGB(4, 3, 2, 1), SkColorSetARGB(0, 10, 20, 30)}; SkScalar positions[3] = {0.f, 0.3f, 1.f}; - flags.setShader(PaintShader::MakeLinearGradient( - points, colors, positions, 3, SkShader::kMirror_TileMode)); + flags.setShader(PaintShader::MakeLinearGradient(points, colors, positions, + 3, SkTileMode::kMirror)); return flags; }(), @@ -1133,7 +1132,7 @@ std::vector<PaintFlags> test_flags = { SkColorSetARGB(4, 3, 2, 1), SkColorSetARGB(0, 10, 20, 30)}; flags.setShader(PaintShader::MakeSweepGradient( - 0.2f, -0.8f, colors, nullptr, 3, SkShader::kMirror_TileMode, 10, 20)); + 0.2f, -0.8f, colors, nullptr, 3, SkTileMode::kMirror, 10, 20)); return flags; }(), PaintFlags(), @@ -2743,7 +2742,7 @@ class MockImageProvider : public ImageProvider { quality_[i], true)); } - void SetRecord(PaintRecord* record) { record_ = record; } + void SetRecord(sk_sp<PaintRecord> record) { record_ = std::move(record); } private: std::vector<SkSize> src_rect_offset_; @@ -2751,7 +2750,7 @@ class MockImageProvider : public ImageProvider { std::vector<SkFilterQuality> quality_; size_t index_ = 0; bool fail_all_decodes_ = false; - PaintRecord* record_; + sk_sp<PaintRecord> record_; }; TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { @@ -2768,9 +2767,8 @@ TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); buffer.push<DrawImageOp>(paint_image, 105.0f, 105.0f, &flags); PaintFlags image_flags; - image_flags.setShader( - PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr)); + image_flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr)); buffer.push<DrawRectOp>(SkRect::MakeXYWH(110, 110, 100, 100), image_flags); SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100); @@ -2794,9 +2792,8 @@ TEST(PaintOpBufferTest, SkipsOpsWithFailedDecodes) { PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); buffer.push<DrawImageOp>(paint_image, 105.0f, 105.0f, &flags); PaintFlags image_flags; - image_flags.setShader( - PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr)); + image_flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr)); buffer.push<DrawRectOp>(SkRect::MakeXYWH(110, 110, 100, 100), image_flags); buffer.push<DrawColorOp>(SK_ColorRED, SkBlendMode::kSrcOver); @@ -2831,7 +2828,7 @@ MATCHER_P(MatchesQuality, quality, "") { MATCHER_P2(MatchesShader, flags, scale, "") { SkMatrix matrix; - SkShader::TileMode xy[2]; + SkTileMode xy[2]; SkImage* image = arg.getShader()->isAImage(&matrix, xy); EXPECT_FALSE(image->isLazyGenerated()); @@ -2848,18 +2845,18 @@ MATCHER_P2(MatchesShader, flags, scale, "") { } TEST(PaintOpBufferTest, RasterPaintWorkletImage1) { - PaintOpBuffer paint_worklet_buffer; + sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>(); PaintFlags noop_flags; SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 100, 100); - paint_worklet_buffer.push<TranslateOp>(8.0f, 8.0f); - paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags); + paint_worklet_buffer->push<TranslateOp>(8.0f, 8.0f); + paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags); PaintFlags draw_flags; draw_flags.setColor(0u); SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100); - paint_worklet_buffer.push<DrawRectOp>(rect, draw_flags); + paint_worklet_buffer->push<DrawRectOp>(rect, draw_flags); MockImageProvider provider; - provider.SetRecord(&paint_worklet_buffer); + provider.SetRecord(paint_worklet_buffer); PaintOpBuffer blink_buffer; scoped_refptr<TestPaintWorkletInput> input = @@ -2881,20 +2878,20 @@ TEST(PaintOpBufferTest, RasterPaintWorkletImage1) { } TEST(PaintOpBufferTest, RasterPaintWorkletImage2) { - PaintOpBuffer paint_worklet_buffer; + sk_sp<PaintOpBuffer> paint_worklet_buffer = sk_make_sp<PaintOpBuffer>(); PaintFlags noop_flags; SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 10, 10); - paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags); + paint_worklet_buffer->push<SaveLayerOp>(&savelayer_rect, &noop_flags); PaintFlags draw_flags; draw_flags.setFilterQuality(kLow_SkFilterQuality); PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10)); - paint_worklet_buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, &draw_flags); + paint_worklet_buffer->push<DrawImageOp>(paint_image, 0.0f, 0.0f, &draw_flags); std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()}; std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)}; std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality}; MockImageProvider provider(src_rect_offset, scale_adjustment, quality); - provider.SetRecord(&paint_worklet_buffer); + provider.SetRecord(paint_worklet_buffer); PaintOpBuffer blink_buffer; scoped_refptr<TestPaintWorkletInput> input = @@ -2939,9 +2936,8 @@ TEST(PaintOpBufferTest, ReplacesImagesFromProvider) { buffer.push<DrawImageRectOp>( paint_image, rect, rect, &flags, PaintCanvas::SrcRectConstraint::kFast_SrcRectConstraint); - flags.setShader( - PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr)); + flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr)); buffer.push<DrawOvalOp>(SkRect::MakeWH(10, 10), flags); testing::StrictMock<MockCanvas> canvas; @@ -2983,9 +2979,8 @@ TEST(PaintOpBufferTest, ReplacesImagesFromProviderOOP) { buffer.push<DrawImageRectOp>( paint_image, rect, rect, &flags, PaintCanvas::SrcRectConstraint::kFast_SrcRectConstraint); - flags.setShader( - PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr)); + flags.setShader(PaintShader::MakeImage(paint_image, SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr)); buffer.push<DrawOvalOp>(SkRect::MakeWH(10, 10), flags); std::unique_ptr<char, base::AlignedFreeDeleter> memory( @@ -3045,7 +3040,7 @@ TEST_P(PaintFilterSerializationTest, Basic) { SkScalar scalars[9] = {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}; std::vector<sk_sp<PaintFilter>> filters = { sk_sp<PaintFilter>{new ColorFilterPaintFilter( - SkColorFilter::MakeLinearToSRGBGamma(), nullptr)}, + SkColorFilters::LinearToSRGBGamma(), nullptr)}, sk_sp<PaintFilter>{new BlurPaintFilter( 0.5f, 0.3f, SkBlurImageFilter::kRepeat_TileMode, nullptr)}, sk_sp<PaintFilter>{new DropShadowPaintFilter( @@ -3133,8 +3128,8 @@ TEST(PaintOpBufferTest, PaintRecordShaderSerialization) { TestOptionsProvider options_provider; PaintFlags flags; flags.setShader(PaintShader::MakePaintRecord( - record_buffer, SkRect::MakeWH(10, 10), SkShader::kClamp_TileMode, - SkShader::kRepeat_TileMode, nullptr)); + record_buffer, SkRect::MakeWH(10, 10), SkTileMode::kClamp, + SkTileMode::kRepeat, nullptr)); PaintOpBuffer buffer; buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), flags); @@ -3280,9 +3275,8 @@ TEST(PaintOpBufferTest, RecordShadersSerializeScaledImages) { CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f, nullptr); auto shader = PaintShader::MakePaintRecord( - record_buffer, SkRect::MakeWH(10.f, 10.f), - SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr); + record_buffer, SkRect::MakeWH(10.f, 10.f), SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr); shader->set_has_animated_images(true); auto buffer = sk_make_sp<PaintOpBuffer>(); buffer->push<ScaleOp>(0.5f, 0.8f); @@ -3316,9 +3310,8 @@ TEST(PaintOpBufferTest, RecordShadersCached) { record_buffer->push<DrawImageOp>( CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f, nullptr); auto shader = PaintShader::MakePaintRecord( - record_buffer, SkRect::MakeWH(10.f, 10.f), - SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr); + record_buffer, SkRect::MakeWH(10.f, 10.f), SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr); shader->set_has_animated_images(false); auto shader_id = shader->paint_record_shader_id(); TestOptionsProvider options_provider; @@ -3437,9 +3430,8 @@ TEST(PaintOpBufferTest, RecordShadersCachedSize) { auto image = CreateBitmapImage(gfx::Size(30, 30)); record_buffer->push<DrawImageOp>(image, 0.f, 0.f, nullptr); auto shader = PaintShader::MakePaintRecord( - record_buffer, SkRect::MakeWH(10.f, 10.f), - SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr); + record_buffer, SkRect::MakeWH(10.f, 10.f), SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr); shader->set_has_animated_images(false); auto shader_id = shader->paint_record_shader_id(); TestOptionsProvider options_provider; diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc index fa234f8f0a1..74366585d97 100644 --- a/chromium/cc/paint/paint_op_reader.cc +++ b/chromium/cc/paint/paint_op_reader.cc @@ -33,16 +33,15 @@ bool IsValidPaintShaderType(PaintShader::Type type) { static_cast<uint8_t>(PaintShader::Type::kShaderCount); } -// SkShader::TileMode has no defined backing type, so read/write int32_t's. +// SkTileMode has no defined backing type, so read/write int32_t's. // If read_mode is a valid tile mode, this returns true and updates mode to the // equivalent enum value. Otherwise false is returned and mode is not modified. -bool ValidateAndGetSkShaderTileMode(int32_t read_mode, - SkShader::TileMode* mode) { - if (read_mode < 0 || read_mode >= SkShader::kTileModeCount) { +bool ValidateAndGetSkShaderTileMode(int32_t read_mode, SkTileMode* mode) { + if (read_mode < 0 || read_mode >= kSkTileModeCount) { return false; } - *mode = static_cast<SkShader::TileMode>(read_mode); + *mode = static_cast<SkTileMode>(read_mode); return true; } diff --git a/chromium/cc/paint/paint_op_writer.cc b/chromium/cc/paint/paint_op_writer.cc index f178bc59182..e94efb08399 100644 --- a/chromium/cc/paint/paint_op_writer.cc +++ b/chromium/cc/paint/paint_op_writer.cc @@ -368,8 +368,10 @@ sk_sp<PaintShader> PaintOpWriter::TransformShaderIfNecessary( &quality, paint_image_needs_mips); } - if (type == PaintShader::Type::kPaintRecord) - return original->CreateScaledPaintRecord(ctm, paint_record_post_scale); + if (type == PaintShader::Type::kPaintRecord) { + return original->CreateScaledPaintRecord(ctm, options_.max_texture_size, + paint_record_post_scale); + } return sk_ref_sp<PaintShader>(original); } @@ -406,7 +408,7 @@ void PaintOpWriter::Write(const PaintShader* shader, SkFilterQuality quality) { WriteSimple(shader->flags_); WriteSimple(shader->end_radius_); WriteSimple(shader->start_radius_); - // SkShader::TileMode does not have an explicitly defined backing type, so + // SkTileMode does not have an explicitly defined backing type, so // write a consistently sized value. Write(static_cast<int32_t>(shader->tx_)); Write(static_cast<int32_t>(shader->ty_)); diff --git a/chromium/cc/paint/paint_recorder.h b/chromium/cc/paint/paint_recorder.h index c8f1c8a0ab8..58b26fa3fb5 100644 --- a/chromium/cc/paint/paint_recorder.h +++ b/chromium/cc/paint/paint_recorder.h @@ -6,7 +6,6 @@ #define CC_PAINT_PAINT_RECORDER_H_ #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/optional.h" #include "cc/paint/paint_record.h" #include "cc/paint/record_paint_canvas.h" @@ -18,8 +17,11 @@ class DisplayItemList; class CC_PAINT_EXPORT PaintRecorder { public: PaintRecorder(); + PaintRecorder(const PaintRecorder&) = delete; ~PaintRecorder(); + PaintRecorder& operator=(const PaintRecorder&) = delete; + PaintCanvas* beginRecording(const SkRect& bounds); // TODO(enne): should make everything go through the non-rect version. @@ -38,7 +40,6 @@ class CC_PAINT_EXPORT PaintRecorder { private: scoped_refptr<DisplayItemList> display_item_list_; base::Optional<RecordPaintCanvas> canvas_; - DISALLOW_COPY_AND_ASSIGN(PaintRecorder); }; } // namespace cc diff --git a/chromium/cc/paint/paint_shader.cc b/chromium/cc/paint/paint_shader.cc index 23a677a7bee..ecd9f0a7c6d 100644 --- a/chromium/cc/paint/paint_shader.cc +++ b/chromium/cc/paint/paint_shader.cc @@ -48,6 +48,20 @@ bool CompareMatrices(const SkMatrix& a, return PaintOp::AreSkMatricesEqual(a_without_scale, b_without_scale); } +SkRect AdjustForMaxTextureSize(SkRect tile, int max_texture_size) { + if (max_texture_size == 0) + return tile; + + if (tile.width() < max_texture_size && tile.height() < max_texture_size) + return tile; + + float down_scale = max_texture_size / std::max(tile.width(), tile.height()); + tile = SkRect::MakeXYWH(tile.x(), tile.y(), + SkScalarFloorToScalar(tile.width() * down_scale), + SkScalarFloorToScalar(tile.height() * down_scale)); + return tile; +} + } // namespace const PaintShader::RecordShaderId PaintShader::kInvalidRecordShaderId = -1; @@ -73,7 +87,7 @@ sk_sp<PaintShader> PaintShader::MakeLinearGradient(const SkPoint points[], const SkColor colors[], const SkScalar pos[], int count, - SkShader::TileMode mode, + SkTileMode mode, uint32_t flags, const SkMatrix* local_matrix, SkColor fallback_color) { @@ -95,7 +109,7 @@ sk_sp<PaintShader> PaintShader::MakeRadialGradient(const SkPoint& center, const SkColor colors[], const SkScalar pos[], int count, - SkShader::TileMode mode, + SkTileMode mode, uint32_t flags, const SkMatrix* local_matrix, SkColor fallback_color) { @@ -119,7 +133,7 @@ sk_sp<PaintShader> PaintShader::MakeTwoPointConicalGradient( const SkColor colors[], const SkScalar pos[], int count, - SkShader::TileMode mode, + SkTileMode mode, uint32_t flags, const SkMatrix* local_matrix, SkColor fallback_color) { @@ -142,7 +156,7 @@ sk_sp<PaintShader> PaintShader::MakeSweepGradient(SkScalar cx, const SkColor colors[], const SkScalar pos[], int color_count, - SkShader::TileMode mode, + SkTileMode mode, SkScalar start_degrees, SkScalar end_degrees, uint32_t flags, @@ -162,8 +176,8 @@ sk_sp<PaintShader> PaintShader::MakeSweepGradient(SkScalar cx, } sk_sp<PaintShader> PaintShader::MakeImage(const PaintImage& image, - SkShader::TileMode tx, - SkShader::TileMode ty, + SkTileMode tx, + SkTileMode ty, const SkMatrix* local_matrix) { sk_sp<PaintShader> shader(new PaintShader(Type::kImage)); @@ -177,8 +191,8 @@ sk_sp<PaintShader> PaintShader::MakeImage(const PaintImage& image, sk_sp<PaintShader> PaintShader::MakePaintRecord( sk_sp<PaintRecord> record, const SkRect& tile, - SkShader::TileMode tx, - SkShader::TileMode ty, + SkTileMode tx, + SkTileMode ty, const SkMatrix* local_matrix, ScalingBehavior scaling_behavior) { sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); @@ -273,6 +287,7 @@ bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm, sk_sp<PaintShader> PaintShader::CreateScaledPaintRecord( const SkMatrix& ctm, + int max_texture_size, gfx::SizeF* raster_scale) const { DCHECK_EQ(shader_type_, Type::kPaintRecord); @@ -297,6 +312,7 @@ sk_sp<PaintShader> PaintShader::CreateScaledPaintRecord( SkRect tile_rect; if (!GetRasterizationTileRect(ctm, &tile_rect)) return nullptr; + tile_rect = AdjustForMaxTextureSize(tile_rect, max_texture_size); sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); shader->record_ = record_; @@ -381,7 +397,7 @@ void PaintShader::CreateSkShader(const gfx::SizeF* raster_scale, switch (shader_type_) { case Type::kEmpty: - cached_shader_ = SkShader::MakeEmptyShader(); + cached_shader_ = SkShaders::Empty(); break; case Type::kColor: // This will be handled by the fallback check below. @@ -430,9 +446,8 @@ void PaintShader::CreateSkShader(const gfx::SizeF* raster_scale, switch (scaling_behavior_) { // For raster scale, we create a picture shader directly. case ScalingBehavior::kRasterAtScale: - cached_shader_ = SkShader::MakePictureShader( - std::move(picture), tx_, ty_, - base::OptionalOrNullptr(local_matrix_), nullptr); + cached_shader_ = picture->makeShader( + tx_, ty_, base::OptionalOrNullptr(local_matrix_), nullptr); break; // For fixed scale, we create an image shader with an image backed by // the picture. @@ -456,7 +471,7 @@ void PaintShader::CreateSkShader(const gfx::SizeF* raster_scale, // If we didn't create a shader for whatever reason, create a fallback color // one. if (!cached_shader_) - cached_shader_ = SkShader::MakeColorShader(fallback_color_); + cached_shader_ = SkShaders::Color(fallback_color_); } void PaintShader::SetColorsAndPositions(const SkColor* colors, @@ -473,8 +488,8 @@ void PaintShader::SetColorsAndPositions(const SkColor* colors, } void PaintShader::SetMatrixAndTiling(const SkMatrix* matrix, - SkShader::TileMode tx, - SkShader::TileMode ty) { + SkTileMode tx, + SkTileMode ty) { if (matrix) local_matrix_ = *matrix; tx_ = tx; diff --git a/chromium/cc/paint/paint_shader.h b/chromium/cc/paint/paint_shader.h index 17cbd1f88b8..24fda29ceb7 100644 --- a/chromium/cc/paint/paint_shader.h +++ b/chromium/cc/paint/paint_shader.h @@ -55,7 +55,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { const SkColor* colors, const SkScalar* pos, int count, - SkShader::TileMode mode, + SkTileMode mode, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); @@ -66,7 +66,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { const SkColor colors[], const SkScalar pos[], int color_count, - SkShader::TileMode mode, + SkTileMode mode, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); @@ -79,7 +79,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { const SkColor colors[], const SkScalar pos[], int color_count, - SkShader::TileMode mode, + SkTileMode mode, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); @@ -90,7 +90,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { const SkColor colors[], const SkScalar pos[], int color_count, - SkShader::TileMode mode, + SkTileMode mode, SkScalar start_degrees, SkScalar end_degrees, uint32_t flags = 0, @@ -98,22 +98,25 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { SkColor fallback_color = SK_ColorTRANSPARENT); static sk_sp<PaintShader> MakeImage(const PaintImage& image, - SkShader::TileMode tx, - SkShader::TileMode ty, + SkTileMode tx, + SkTileMode ty, const SkMatrix* local_matrix); static sk_sp<PaintShader> MakePaintRecord( sk_sp<PaintRecord> record, const SkRect& tile, - SkShader::TileMode tx, - SkShader::TileMode ty, + SkTileMode tx, + SkTileMode ty, const SkMatrix* local_matrix, ScalingBehavior scaling_behavior = ScalingBehavior::kRasterAtScale); static size_t GetSerializedSize(const PaintShader* shader); + PaintShader(const PaintShader&) = delete; ~PaintShader() override; + PaintShader& operator=(const PaintShader&) = delete; + void set_has_animated_images(bool has_animated_images) { image_analysis_state_ = has_animated_images ? ImageAnalysisState::kAnimatedImages @@ -140,8 +143,8 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { const sk_sp<PaintRecord>& paint_record() const { return record_; } bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const; - SkShader::TileMode tx() const { return tx_; } - SkShader::TileMode ty() const { return ty_; } + SkTileMode tx() const { return tx_; } + SkTileMode ty() const { return ty_; } SkRect tile() const { return tile_; } bool IsOpaque() const; @@ -183,6 +186,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { // Note that this does not create a skia backing for the shader. // Valid only for PaintRecord backed shaders. sk_sp<PaintShader> CreateScaledPaintRecord(const SkMatrix& ctm, + int max_texture_size, gfx::SizeF* raster_scale) const; // Creates a PaintShader with images from |image_provider| to be rasterized @@ -202,9 +206,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { void SetColorsAndPositions(const SkColor* colors, const SkScalar* positions, int count); - void SetMatrixAndTiling(const SkMatrix* matrix, - SkShader::TileMode tx, - SkShader::TileMode ty); + void SetMatrixAndTiling(const SkMatrix* matrix, SkTileMode tx, SkTileMode ty); void SetFlagsAndFallback(uint32_t flags, SkColor fallback_color); Type shader_type_ = Type::kShaderCount; @@ -212,8 +214,8 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { uint32_t flags_ = 0; SkScalar end_radius_ = 0; SkScalar start_radius_ = 0; - SkShader::TileMode tx_ = SkShader::kClamp_TileMode; - SkShader::TileMode ty_ = SkShader::kClamp_TileMode; + SkTileMode tx_ = SkTileMode::kClamp; + SkTileMode ty_ = SkTileMode::kClamp; SkColor fallback_color_ = SK_ColorTRANSPARENT; ScalingBehavior scaling_behavior_ = ScalingBehavior::kRasterAtScale; @@ -244,8 +246,6 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt { sk_sp<SkShader> cached_shader_; ImageAnalysisState image_analysis_state_ = ImageAnalysisState::kNoAnalysis; - - DISALLOW_COPY_AND_ASSIGN(PaintShader); }; } // namespace cc diff --git a/chromium/cc/paint/paint_shader_unittest.cc b/chromium/cc/paint/paint_shader_unittest.cc index 831074813ef..f18200efb32 100644 --- a/chromium/cc/paint/paint_shader_unittest.cc +++ b/chromium/cc/paint/paint_shader_unittest.cc @@ -62,9 +62,8 @@ class MockImageProvider : public ImageProvider { TEST(PaintShaderTest, RasterizationRectForRecordShaders) { SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f); auto record_shader = PaintShader::MakePaintRecord( - sk_make_sp<PaintOpBuffer>(), SkRect::MakeWH(100, 100), - SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode, - &local_matrix); + sk_make_sp<PaintOpBuffer>(), SkRect::MakeWH(100, 100), SkTileMode::kClamp, + SkTileMode::kClamp, &local_matrix); SkRect tile_rect; SkMatrix ctm = SkMatrix::MakeScale(0.5f, 0.5f); @@ -88,8 +87,8 @@ TEST(PaintShaderTest, DecodePaintRecord) { record->push<DrawImageOp>(paint_image, 0.f, 0.f, nullptr); SkMatrix local_matrix = SkMatrix::MakeScale(0.5f, 0.5f); auto record_shader = PaintShader::MakePaintRecord( - record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode, - SkShader::TileMode::kClamp_TileMode, &local_matrix); + record, SkRect::MakeWH(100, 100), SkTileMode::kClamp, SkTileMode::kClamp, + &local_matrix); record_shader->set_has_animated_images(true); PaintOpBuffer buffer; @@ -106,7 +105,7 @@ TEST(PaintShaderTest, DecodePaintRecord) { SkShader* shader = canvas.paint_.getShader(); ASSERT_TRUE(shader); SkMatrix decoded_local_matrix; - SkShader::TileMode xy[2]; + SkTileMode xy[2]; SkImage* skia_image = shader->isAImage(&decoded_local_matrix, xy); ASSERT_TRUE(skia_image); EXPECT_TRUE(skia_image->isLazyGenerated()); diff --git a/chromium/cc/paint/paint_worklet_input.h b/chromium/cc/paint/paint_worklet_input.h index 165729147d0..94e2cfda4d0 100644 --- a/chromium/cc/paint/paint_worklet_input.h +++ b/chromium/cc/paint/paint_worklet_input.h @@ -15,6 +15,7 @@ class CC_EXPORT PaintWorkletInput : public base::RefCountedThreadSafe<PaintWorkletInput> { public: virtual gfx::SizeF GetSize() const = 0; + virtual int WorkletId() const = 0; protected: friend class base::RefCountedThreadSafe<PaintWorkletInput>; diff --git a/chromium/cc/paint/paint_worklet_layer_painter.h b/chromium/cc/paint/paint_worklet_layer_painter.h index c1a8e097921..6535432bff5 100644 --- a/chromium/cc/paint/paint_worklet_layer_painter.h +++ b/chromium/cc/paint/paint_worklet_layer_painter.h @@ -10,11 +10,13 @@ namespace cc { +class PaintWorkletInput; + class CC_EXPORT PaintWorkletLayerPainter { public: virtual ~PaintWorkletLayerPainter() {} - virtual sk_sp<PaintRecord> Paint() = 0; + virtual sk_sp<PaintRecord> Paint(PaintWorkletInput*) = 0; }; } // namespace cc diff --git a/chromium/cc/paint/record_paint_canvas.h b/chromium/cc/paint/record_paint_canvas.h index b0a75cc7d23..c32547f2810 100644 --- a/chromium/cc/paint/record_paint_canvas.h +++ b/chromium/cc/paint/record_paint_canvas.h @@ -9,7 +9,6 @@ #include "base/compiler_specific.h" #include "base/logging.h" -#include "base/macros.h" #include "base/optional.h" #include "build/build_config.h" #include "cc/paint/paint_canvas.h" @@ -25,8 +24,11 @@ class PaintFlags; class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas { public: RecordPaintCanvas(DisplayItemList* list, const SkRect& bounds); + RecordPaintCanvas(const RecordPaintCanvas&) = delete; ~RecordPaintCanvas() override; + RecordPaintCanvas& operator=(const RecordPaintCanvas&) = delete; + SkImageInfo imageInfo() const override; void flush() override; @@ -130,8 +132,6 @@ class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas { // lazy initialize the canvas can still be const. mutable base::Optional<SkNoDrawCanvas> canvas_; SkRect recording_bounds_; - - DISALLOW_COPY_AND_ASSIGN(RecordPaintCanvas); }; } // namespace cc diff --git a/chromium/cc/paint/render_surface_filters.cc b/chromium/cc/paint/render_surface_filters.cc index cb8a39fb4f7..d82fdd069fa 100644 --- a/chromium/cc/paint/render_surface_filters.cc +++ b/chromium/cc/paint/render_surface_filters.cc @@ -147,7 +147,7 @@ void GetSepiaMatrix(float amount, SkScalar matrix[20]) { sk_sp<PaintFilter> CreateMatrixImageFilter(const SkScalar matrix[20], sk_sp<PaintFilter> input) { return sk_make_sp<ColorFilterPaintFilter>( - SkColorFilter::MakeMatrixFilterRowMajor255(matrix), std::move(input)); + SkColorFilters::MatrixRowMajor255(matrix), std::move(input)); } } // namespace diff --git a/chromium/cc/paint/render_surface_filters.h b/chromium/cc/paint/render_surface_filters.h index 903ae2112f4..1ca44be595d 100644 --- a/chromium/cc/paint/render_surface_filters.h +++ b/chromium/cc/paint/render_surface_filters.h @@ -5,7 +5,6 @@ #ifndef CC_PAINT_RENDER_SURFACE_FILTERS_H_ #define CC_PAINT_RENDER_SURFACE_FILTERS_H_ -#include "base/macros.h" #include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -20,13 +19,12 @@ class FilterOperations; class CC_PAINT_EXPORT RenderSurfaceFilters { public: + RenderSurfaceFilters() = delete; + static sk_sp<PaintFilter> BuildImageFilter( const FilterOperations& filters, const gfx::SizeF& size, const gfx::Vector2dF& offset = gfx::Vector2dF(0, 0)); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(RenderSurfaceFilters); }; } // namespace cc diff --git a/chromium/cc/paint/scoped_raster_flags.cc b/chromium/cc/paint/scoped_raster_flags.cc index 960e6b3acb2..d51b6ab97f6 100644 --- a/chromium/cc/paint/scoped_raster_flags.cc +++ b/chromium/cc/paint/scoped_raster_flags.cc @@ -13,6 +13,7 @@ namespace cc { ScopedRasterFlags::ScopedRasterFlags(const PaintFlags* flags, ImageProvider* image_provider, const SkMatrix& ctm, + int max_texture_size, uint8_t alpha) : original_flags_(flags) { if (image_provider) { @@ -22,7 +23,7 @@ ScopedRasterFlags::ScopedRasterFlags(const PaintFlags* flags, DecodeImageShader(ctm); if (decode_failed_) return; - DecodeRecordShader(ctm); + DecodeRecordShader(ctm, max_texture_size); if (decode_failed_) return; DecodeFilter(); @@ -64,7 +65,8 @@ void ScopedRasterFlags::DecodeImageShader(const SkMatrix& ctm) { MutableFlags()->setShader(decoded_shader); } -void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm) { +void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm, + int max_texture_size) { if (!flags()->HasShader() || flags()->getShader()->shader_type() != PaintShader::Type::kPaintRecord) return; @@ -78,8 +80,8 @@ void ScopedRasterFlags::DecodeRecordShader(const SkMatrix& ctm) { } gfx::SizeF raster_scale(1.f, 1.f); - auto decoded_shader = - flags()->getShader()->CreateScaledPaintRecord(ctm, &raster_scale); + auto decoded_shader = flags()->getShader()->CreateScaledPaintRecord( + ctm, max_texture_size, &raster_scale); decoded_shader->CreateSkShader(&raster_scale, &*decode_stashing_image_provider_); MutableFlags()->setShader(std::move(decoded_shader)); diff --git a/chromium/cc/paint/scoped_raster_flags.h b/chromium/cc/paint/scoped_raster_flags.h index 91a6b871105..a5d452eae24 100644 --- a/chromium/cc/paint/scoped_raster_flags.h +++ b/chromium/cc/paint/scoped_raster_flags.h @@ -6,7 +6,6 @@ #define CC_PAINT_SCOPED_RASTER_FLAGS_H_ #include "base/containers/stack_container.h" -#include "base/macros.h" #include "cc/paint/decode_stashing_image_provider.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_flags.h" @@ -21,9 +20,13 @@ class CC_PAINT_EXPORT ScopedRasterFlags { ScopedRasterFlags(const PaintFlags* flags, ImageProvider* image_provider, const SkMatrix& ctm, + int max_texture_size, uint8_t alpha); + ScopedRasterFlags(const ScopedRasterFlags&) = delete; ~ScopedRasterFlags(); + ScopedRasterFlags& operator=(const ScopedRasterFlags&) = delete; + // The usage of these flags should not extend beyond the lifetime of this // object. const PaintFlags* flags() const { @@ -35,7 +38,7 @@ class CC_PAINT_EXPORT ScopedRasterFlags { private: void DecodeImageShader(const SkMatrix& ctm); - void DecodeRecordShader(const SkMatrix& ctm); + void DecodeRecordShader(const SkMatrix& ctm, int max_texture_size); void DecodeFilter(); void AdjustStrokeIfNeeded(const SkMatrix& ctm); @@ -50,8 +53,6 @@ class CC_PAINT_EXPORT ScopedRasterFlags { base::Optional<PaintFlags> modified_flags_; base::Optional<DecodeStashingImageProvider> decode_stashing_image_provider_; bool decode_failed_ = false; - - DISALLOW_COPY_AND_ASSIGN(ScopedRasterFlags); }; } // namespace cc diff --git a/chromium/cc/paint/scoped_raster_flags_unittest.cc b/chromium/cc/paint/scoped_raster_flags_unittest.cc index 3c8ffcb5052..52b407bca94 100644 --- a/chromium/cc/paint/scoped_raster_flags_unittest.cc +++ b/chromium/cc/paint/scoped_raster_flags_unittest.cc @@ -52,15 +52,15 @@ TEST(ScopedRasterFlagsTest, KeepsDecodesAlive) { record->push<DrawImageOp>(CreateDiscardablePaintImage(gfx::Size(10, 10)), 0.f, 0.f, nullptr); auto record_shader = PaintShader::MakePaintRecord( - record, SkRect::MakeWH(100, 100), SkShader::TileMode::kClamp_TileMode, - SkShader::TileMode::kClamp_TileMode, &SkMatrix::I()); + record, SkRect::MakeWH(100, 100), SkTileMode::kClamp, SkTileMode::kClamp, + &SkMatrix::I()); record_shader->set_has_animated_images(true); MockImageProvider provider; PaintFlags flags; flags.setShader(record_shader); { - ScopedRasterFlags scoped_flags(&flags, &provider, SkMatrix::I(), 255); + ScopedRasterFlags scoped_flags(&flags, &provider, SkMatrix::I(), 0, 255); ASSERT_TRUE(scoped_flags.flags()); EXPECT_NE(scoped_flags.flags(), &flags); SkPaint paint = scoped_flags.flags()->ToSkPaint(); @@ -74,10 +74,9 @@ TEST(ScopedRasterFlagsTest, NoImageProvider) { PaintFlags flags; flags.setAlpha(255); flags.setShader(PaintShader::MakeImage( - CreateDiscardablePaintImage(gfx::Size(10, 10)), - SkShader::TileMode::kClamp_TileMode, SkShader::TileMode::kClamp_TileMode, - &SkMatrix::I())); - ScopedRasterFlags scoped_flags(&flags, nullptr, SkMatrix::I(), 10); + CreateDiscardablePaintImage(gfx::Size(10, 10)), SkTileMode::kClamp, + SkTileMode::kClamp, &SkMatrix::I())); + ScopedRasterFlags scoped_flags(&flags, nullptr, SkMatrix::I(), 0, 10); EXPECT_NE(scoped_flags.flags(), &flags); EXPECT_EQ(scoped_flags.flags()->getAlpha(), SkMulDiv255Round(255, 10)); } @@ -108,7 +107,7 @@ TEST(ScopedRasterFlagsTest, ThinAliasedStroke) { }; for (const auto& test : tests) { - ScopedRasterFlags scoped_flags(&flags, nullptr, test.ctm, test.alpha); + ScopedRasterFlags scoped_flags(&flags, nullptr, test.ctm, 0, test.alpha); ASSERT_TRUE(scoped_flags.flags()); EXPECT_EQ(scoped_flags.flags() == &flags, test.expect_same_flags); diff --git a/chromium/cc/paint/skia_paint_canvas.cc b/chromium/cc/paint/skia_paint_canvas.cc index b5c5743d23a..17829b3eb1a 100644 --- a/chromium/cc/paint/skia_paint_canvas.cc +++ b/chromium/cc/paint/skia_paint_canvas.cc @@ -9,10 +9,6 @@ #include "cc/paint/paint_recorder.h" #include "cc/paint/scoped_raster_flags.h" #include "third_party/skia/include/core/SkAnnotation.h" -#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h" -#include "third_party/skia/include/core/SkRegion.h" -#include "third_party/skia/include/gpu/GrContext.h" -#include "third_party/skia/include/utils/SkNWayCanvas.h" namespace cc { @@ -36,27 +32,8 @@ SkiaPaintCanvas::SkiaPaintCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) : canvas_(new SkCanvas(bitmap, props)), owned_(canvas_) {} -SkiaPaintCanvas::SkiaPaintCanvas(SkCanvas* canvas, - sk_sp<SkColorSpace> target_color_space, - ImageProvider* image_provider, - ContextFlushes context_flushes) - : canvas_(canvas), - image_provider_(image_provider), - context_flushes_(context_flushes) { - WrapCanvasInColorSpaceXformCanvas(target_color_space); -} - SkiaPaintCanvas::~SkiaPaintCanvas() = default; -void SkiaPaintCanvas::WrapCanvasInColorSpaceXformCanvas( - sk_sp<SkColorSpace> target_color_space) { - if (target_color_space) { - color_space_xform_canvas_ = - SkCreateColorSpaceXformCanvas(canvas_, target_color_space); - canvas_ = color_space_xform_canvas_.get(); - } -} - SkImageInfo SkiaPaintCanvas::imageInfo() const { return canvas_->imageInfo(); } @@ -161,7 +138,8 @@ void SkiaPaintCanvas::drawLine(SkScalar x0, SkScalar y1, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -172,7 +150,8 @@ void SkiaPaintCanvas::drawLine(SkScalar x0, void SkiaPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -183,7 +162,8 @@ 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(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -194,7 +174,8 @@ 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(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -205,7 +186,8 @@ 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(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -218,7 +200,8 @@ void SkiaPaintCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -232,7 +215,8 @@ void SkiaPaintCanvas::drawRoundRect(const SkRect& rect, SkScalar ry, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -243,7 +227,8 @@ void SkiaPaintCanvas::drawRoundRect(const SkRect& rect, void SkiaPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -259,7 +244,7 @@ void SkiaPaintCanvas::drawImage(const PaintImage& image, base::Optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - 255u); + max_texture_size(), 255u); if (!scoped_flags->flags()) return; } @@ -279,7 +264,7 @@ void SkiaPaintCanvas::drawImageRect(const PaintImage& image, base::Optional<ScopedRasterFlags> scoped_flags; if (flags) { scoped_flags.emplace(flags, image_provider_, canvas_->getTotalMatrix(), - 255u); + max_texture_size(), 255u); if (!scoped_flags->flags()) return; } @@ -303,7 +288,8 @@ void SkiaPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob, SkScalar y, const PaintFlags& flags) { ScopedRasterFlags raster_flags(&flags, image_provider_, - canvas_->getTotalMatrix(), 255u); + canvas_->getTotalMatrix(), max_texture_size(), + 255u); if (!raster_flags.flags()) return; SkPaint paint = raster_flags.flags()->ToSkPaint(); @@ -372,11 +358,9 @@ void SkiaPaintCanvas::FlushAfterDrawIfNeeded() { if (++num_of_ops_ > context_flushes_.max_draws_before_flush) { num_of_ops_ = 0; - if (auto* context = canvas_->getGrContext()) { - TRACE_EVENT0("cc", - "SkiaPaintCanvas::FlushAfterDrawIfNeeded::FlushGrContext"); - context->flush(); - } + TRACE_EVENT0("cc", + "SkiaPaintCanvas::FlushAfterDrawIfNeeded::FlushGrContext"); + canvas_->flush(); } } diff --git a/chromium/cc/paint/skia_paint_canvas.h b/chromium/cc/paint/skia_paint_canvas.h index b3f665ae161..cf347d53a6e 100644 --- a/chromium/cc/paint/skia_paint_canvas.h +++ b/chromium/cc/paint/skia_paint_canvas.h @@ -9,12 +9,12 @@ #include "base/compiler_specific.h" #include "base/logging.h" -#include "base/macros.h" #include "build/build_config.h" #include "cc/paint/paint_canvas.h" #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/GrContext.h" namespace cc { class ImageProvider; @@ -44,8 +44,11 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { sk_sp<SkColorSpace> target_color_space, ImageProvider* image_provider = nullptr, ContextFlushes context_flushes = ContextFlushes()); + SkiaPaintCanvas(const SkiaPaintCanvas&) = delete; ~SkiaPaintCanvas() override; + SkiaPaintCanvas& operator=(const SkiaPaintCanvas&) = delete; + void reset_image_provider() { image_provider_ = nullptr; } SkImageInfo imageInfo() const override; @@ -141,19 +144,19 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { PlaybackParams::CustomDataRasterCallback custom_raster_callback); private: - void WrapCanvasInColorSpaceXformCanvas( - sk_sp<SkColorSpace> target_color_space); void FlushAfterDrawIfNeeded(); + int max_texture_size() const { + auto* context = canvas_->getGrContext(); + return context ? context->maxTextureSize() : 0; + } + SkCanvas* canvas_; std::unique_ptr<SkCanvas> owned_; - std::unique_ptr<SkCanvas> color_space_xform_canvas_; ImageProvider* image_provider_ = nullptr; const ContextFlushes context_flushes_; int num_of_ops_ = 0; - - DISALLOW_COPY_AND_ASSIGN(SkiaPaintCanvas); }; } // namespace cc diff --git a/chromium/cc/paint/skia_paint_canvas_unittest.cc b/chromium/cc/paint/skia_paint_canvas_unittest.cc index 81b0b85882e..dc03cfc60fe 100644 --- a/chromium/cc/paint/skia_paint_canvas_unittest.cc +++ b/chromium/cc/paint/skia_paint_canvas_unittest.cc @@ -7,8 +7,6 @@ #include "cc/paint/paint_recorder.h" #include "cc/test/test_skcanvas.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/gpu/GrContext.h" -#include "third_party/skia/include/gpu/gl/GrGLInterface.h" using ::testing::_; using ::testing::StrictMock; @@ -16,17 +14,9 @@ using ::testing::Return; namespace cc { -// The ContextFlush tests below use access to the GrContext on SkCanvas from -// getGrContext as a proxy to verify that context is flushed, since this is the -// only case where the context is accessed. - TEST(SkiaPaintCanvasTest, ContextFlushesDirect) { - sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface()); - auto context = GrContext::MakeGL(std::move(gl_interface)); StrictMock<MockCanvas> mock_canvas; - EXPECT_CALL(mock_canvas, getGrContext()) - .Times(2) - .WillRepeatedly(Return(context.get())); + EXPECT_CALL(mock_canvas, onFlush()).Times(2); EXPECT_CALL(mock_canvas, OnDrawRectWithColor(_)).Times(11); SkiaPaintCanvas::ContextFlushes context_flushes; @@ -40,12 +30,8 @@ TEST(SkiaPaintCanvasTest, ContextFlushesDirect) { } TEST(SkiaPaintCanvasTest, ContextFlushesRecording) { - sk_sp<const GrGLInterface> gl_interface(GrGLCreateNullInterface()); - auto context = GrContext::MakeGL(std::move(gl_interface)); StrictMock<MockCanvas> mock_canvas; - EXPECT_CALL(mock_canvas, getGrContext()) - .Times(2) - .WillRepeatedly(Return(context.get())); + EXPECT_CALL(mock_canvas, onFlush()).Times(2); EXPECT_CALL(mock_canvas, OnDrawRectWithColor(_)).Times(11); PaintRecorder recorder; diff --git a/chromium/cc/paint/skia_paint_image_generator.h b/chromium/cc/paint/skia_paint_image_generator.h index 55068c2f988..a3c2cedc957 100644 --- a/chromium/cc/paint/skia_paint_image_generator.h +++ b/chromium/cc/paint/skia_paint_image_generator.h @@ -5,7 +5,6 @@ #ifndef CC_PAINT_SKIA_PAINT_IMAGE_GENERATOR_H_ #define CC_PAINT_SKIA_PAINT_IMAGE_GENERATOR_H_ -#include "base/macros.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_image.h" #include "third_party/skia/include/core/SkImageGenerator.h" @@ -18,8 +17,11 @@ class CC_PAINT_EXPORT SkiaPaintImageGenerator final : public SkImageGenerator { SkiaPaintImageGenerator(sk_sp<PaintImageGenerator> paint_image_generator, size_t frame_index, PaintImage::GeneratorClientId client_id); + SkiaPaintImageGenerator(const SkiaPaintImageGenerator&) = delete; ~SkiaPaintImageGenerator() override; + SkiaPaintImageGenerator& operator=(const SkiaPaintImageGenerator&) = delete; + sk_sp<SkData> onRefEncodedData() override; bool onGetPixels(const SkImageInfo&, void* pixels, @@ -36,8 +38,6 @@ class CC_PAINT_EXPORT SkiaPaintImageGenerator final : public SkImageGenerator { sk_sp<PaintImageGenerator> paint_image_generator_; const size_t frame_index_; const PaintImage::GeneratorClientId client_id_; - - DISALLOW_COPY_AND_ASSIGN(SkiaPaintImageGenerator); }; } // namespace cc diff --git a/chromium/cc/paint/skottie_wrapper.h b/chromium/cc/paint/skottie_wrapper.h index f4e312ec029..76900590f23 100644 --- a/chromium/cc/paint/skottie_wrapper.h +++ b/chromium/cc/paint/skottie_wrapper.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "cc/paint/paint_export.h" @@ -32,6 +31,9 @@ class CC_PAINT_EXPORT SkottieWrapper explicit SkottieWrapper( const scoped_refptr<base::RefCountedMemory>& data_stream); explicit SkottieWrapper(std::unique_ptr<SkMemoryStream> stream); + SkottieWrapper(const SkottieWrapper&) = delete; + + SkottieWrapper& operator=(const SkottieWrapper&) = delete; // A thread safe call that will draw an image with bounds |rect| for the // frame at normalized time instant |t| onto the |canvas|. @@ -46,8 +48,6 @@ class CC_PAINT_EXPORT SkottieWrapper base::Lock lock_; sk_sp<skottie::Animation> animation_; - - DISALLOW_COPY_AND_ASSIGN(SkottieWrapper); }; } // namespace cc diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.cc b/chromium/cc/raster/bitmap_raster_buffer_provider.cc index e2713a24064..f94e220c0f0 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.cc +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.cc @@ -9,7 +9,6 @@ #include <algorithm> -#include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" @@ -54,6 +53,8 @@ class BitmapRasterBufferImpl : public RasterBuffer { resource_has_previous_content_( resource_content_id && resource_content_id == previous_content_id) { } + BitmapRasterBufferImpl(const BitmapRasterBufferImpl&) = delete; + BitmapRasterBufferImpl& operator=(const BitmapRasterBufferImpl&) = delete; // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, @@ -83,8 +84,6 @@ class BitmapRasterBufferImpl : public RasterBuffer { const gfx::ColorSpace color_space_; void* const pixels_; bool resource_has_previous_content_; - - DISALLOW_COPY_AND_ASSIGN(BitmapRasterBufferImpl); }; } // namespace diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.h b/chromium/cc/raster/bitmap_raster_buffer_provider.h index f9c1b9ed706..e91ac1a4248 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.h +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.h @@ -7,7 +7,6 @@ #include <stdint.h> -#include "base/macros.h" #include "base/values.h" #include "cc/raster/raster_buffer_provider.h" @@ -22,8 +21,12 @@ class LayerTreeFrameSink; class CC_EXPORT BitmapRasterBufferProvider : public RasterBufferProvider { public: + BitmapRasterBufferProvider(const BitmapRasterBufferProvider&) = delete; ~BitmapRasterBufferProvider() override; + BitmapRasterBufferProvider& operator=(const BitmapRasterBufferProvider&) = + delete; + explicit BitmapRasterBufferProvider(LayerTreeFrameSink* frame_sink); // Overridden from RasterBufferProvider: @@ -50,8 +53,6 @@ class CC_EXPORT BitmapRasterBufferProvider : public RasterBufferProvider { const; LayerTreeFrameSink* const frame_sink_; - - DISALLOW_COPY_AND_ASSIGN(BitmapRasterBufferProvider); }; } // namespace cc diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.cc b/chromium/cc/raster/gpu_raster_buffer_provider.cc index 079c5b7947a..45f9f93d6d9 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.cc +++ b/chromium/cc/raster/gpu_raster_buffer_provider.cc @@ -7,8 +7,8 @@ #include <stdint.h> #include <algorithm> +#include <utility> -#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/strings/stringprintf.h" @@ -45,6 +45,7 @@ class ScopedSkSurfaceForUnpremultiplyAndDither { public: ScopedSkSurfaceForUnpremultiplyAndDither( viz::RasterContextProvider* context_provider, + sk_sp<SkColorSpace> color_space, const gfx::Rect& playback_rect, const gfx::Rect& raster_full_rect, const gfx::Size& max_tile_size, @@ -72,8 +73,9 @@ class ScopedSkSurfaceForUnpremultiplyAndDither { // Allocate a 32-bit surface for raster. We will copy from that into our // actual surface in destruction. - SkImageInfo n32Info = SkImageInfo::MakeN32Premul( - intermediate_size.width(), intermediate_size.height()); + SkImageInfo n32Info = SkImageInfo::MakeN32Premul(intermediate_size.width(), + intermediate_size.height(), + std::move(color_space)); SkSurfaceProps surface_props = viz::ClientResourceProvider::ScopedSkSurface::ComputeSurfaceProps( can_use_lcd_text); @@ -208,16 +210,18 @@ static void RasterizeSource( base::Optional<ScopedSkSurfaceForUnpremultiplyAndDither> scoped_dither_surface; SkSurface* surface; + sk_sp<SkColorSpace> sk_color_space = color_space.ToSkColorSpace(); if (!unpremultiply_and_dither) { - scoped_surface.emplace(context_provider->GrContext(), texture_id, - texture_target, resource_size, resource_format, - playback_settings.use_lcd_text, msaa_sample_count); + scoped_surface.emplace(context_provider->GrContext(), sk_color_space, + texture_id, texture_target, resource_size, + resource_format, playback_settings.use_lcd_text, + msaa_sample_count); surface = scoped_surface->surface(); } else { scoped_dither_surface.emplace( - context_provider, playback_rect, raster_full_rect, max_tile_size, - texture_id, resource_size, playback_settings.use_lcd_text, - msaa_sample_count); + context_provider, sk_color_space, playback_rect, raster_full_rect, + max_tile_size, texture_id, resource_size, + playback_settings.use_lcd_text, msaa_sample_count); surface = scoped_dither_surface->surface(); } @@ -235,8 +239,8 @@ static void RasterizeSource( canvas->discard(); gfx::Size content_size = raster_source->GetContentSize(transform.scale()); - raster_source->PlaybackToCanvas(canvas, color_space, content_size, - raster_full_rect, playback_rect, transform, + raster_source->PlaybackToCanvas(canvas, content_size, raster_full_rect, + playback_rect, transform, playback_settings); } diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.h b/chromium/cc/raster/gpu_raster_buffer_provider.h index cf726868a6f..52fb765d560 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.h +++ b/chromium/cc/raster/gpu_raster_buffer_provider.h @@ -8,7 +8,6 @@ #include <stdint.h> #include <random> -#include "base/macros.h" #include "cc/raster/raster_buffer_provider.h" #include "gpu/command_buffer/common/sync_token.h" @@ -37,8 +36,11 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { bool unpremultiply_and_dither_low_bit_depth_tiles, bool enable_oop_rasterization, int raster_metric_frequency = kRasterMetricFrequency); + GpuRasterBufferProvider(const GpuRasterBufferProvider&) = delete; ~GpuRasterBufferProvider() override; + GpuRasterBufferProvider& operator=(const GpuRasterBufferProvider&) = delete; + // Overridden from RasterBufferProvider: std::unique_ptr<RasterBuffer> AcquireBufferForRaster( const ResourcePool::InUsePoolResource& resource, @@ -84,8 +86,11 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { const ResourcePool::InUsePoolResource& in_use_resource, GpuRasterBacking* backing, bool resource_has_previous_content); + RasterBufferImpl(const RasterBufferImpl&) = delete; ~RasterBufferImpl() override; + RasterBufferImpl& operator=(const RasterBufferImpl&) = delete; + // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, const gfx::Rect& raster_full_rect, @@ -113,8 +118,6 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { // A SyncToken to be returned from the worker thread, and waited on before // using the rastered resource. gpu::SyncToken after_raster_sync_token_; - - DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); }; struct PendingRasterQuery { @@ -163,8 +166,6 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { // Accessed with the worker context lock acquired. std::mt19937 random_generator_; std::uniform_int_distribution<int> uniform_distribution_; - - DISALLOW_COPY_AND_ASSIGN(GpuRasterBufferProvider); }; } // 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 f16e9083dcd..4a248642b8d 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.cc @@ -11,7 +11,6 @@ #include <utility> #include "base/debug/alias.h" -#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "base/trace_event/process_memory_dump.h" @@ -293,13 +292,12 @@ void OneCopyRasterBufferProvider::PlaybackToStagingBuffer( const RasterSource::PlaybackSettings& playback_settings, uint64_t previous_content_id, uint64_t new_content_id) { - // Allocate GpuMemoryBuffer if necessary. If using partial raster, we - // must allocate a buffer with BufferUsage CPU_READ_WRITE_PERSISTENT. + // Allocate GpuMemoryBuffer if necessary. if (!staging_buffer->gpu_memory_buffer) { staging_buffer->gpu_memory_buffer = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer( - staging_buffer->size, BufferFormat(format), StagingBufferUsage(), - gpu::kNullSurfaceHandle); + staging_buffer->size, BufferFormat(format), + gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gpu::kNullSurfaceHandle); } gfx::Rect playback_rect = raster_full_rect; @@ -484,12 +482,6 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( return out_sync_token; } -gfx::BufferUsage OneCopyRasterBufferProvider::StagingBufferUsage() const { - return use_partial_raster_ - ? gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT - : gfx::BufferUsage::GPU_READ_CPU_READ_WRITE; -} - bool OneCopyRasterBufferProvider::CheckRasterFinishedQueries() { return false; } diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.h b/chromium/cc/raster/one_copy_raster_buffer_provider.h index c2dec8e7d43..a307c01cfb6 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.h @@ -7,7 +7,6 @@ #include <stdint.h> -#include "base/macros.h" #include "base/sequenced_task_runner.h" #include "cc/raster/raster_buffer_provider.h" #include "cc/raster/staging_buffer_pool.h" @@ -39,8 +38,12 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { bool use_gpu_memory_buffer_resources, int max_staging_buffer_usage_in_bytes, viz::ResourceFormat tile_format); + OneCopyRasterBufferProvider(const OneCopyRasterBufferProvider&) = delete; ~OneCopyRasterBufferProvider() override; + OneCopyRasterBufferProvider& operator=(const OneCopyRasterBufferProvider&) = + delete; + // Overridden from RasterBufferProvider: std::unique_ptr<RasterBuffer> AcquireBufferForRaster( const ResourcePool::InUsePoolResource& resource, @@ -87,8 +90,11 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const ResourcePool::InUsePoolResource& in_use_resource, OneCopyGpuBacking* backing, uint64_t previous_content_id); + RasterBufferImpl(const RasterBufferImpl&) = delete; ~RasterBufferImpl() override; + RasterBufferImpl& operator=(const RasterBufferImpl&) = delete; + // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, const gfx::Rect& raster_full_rect, @@ -115,8 +121,6 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { // A SyncToken to be returned from the worker thread, and waited on before // using the rastered resource. gpu::SyncToken after_raster_sync_token_; - - DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); }; void PlaybackToStagingBuffer( @@ -140,7 +144,6 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { bool mailbox_texture_is_overlay_candidate, const gpu::SyncToken& sync_token, const gfx::ColorSpace& color_space); - gfx::BufferUsage StagingBufferUsage() const; viz::ContextProvider* const compositor_context_provider_; viz::RasterContextProvider* const worker_context_provider_; @@ -154,8 +157,6 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const viz::ResourceFormat tile_format_; StagingBufferPool staging_pool_; - - DISALLOW_COPY_AND_ASSIGN(OneCopyRasterBufferProvider); }; } // namespace cc diff --git a/chromium/cc/raster/paint_worklet_image_provider.cc b/chromium/cc/raster/paint_worklet_image_provider.cc index f33424d8547..7312ba3dced 100644 --- a/chromium/cc/raster/paint_worklet_image_provider.cc +++ b/chromium/cc/raster/paint_worklet_image_provider.cc @@ -25,9 +25,9 @@ PaintWorkletImageProvider& PaintWorkletImageProvider::operator=( ImageProvider::ScopedResult PaintWorkletImageProvider::GetPaintRecordResult( PaintWorkletInput* input) { - std::pair<PaintRecord*, base::OnceCallback<void()>> record_and_callback = - cache_->GetPaintRecordAndRef(input); - return ImageProvider::ScopedResult(record_and_callback.first, + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> + record_and_callback = cache_->GetPaintRecordAndRef(input); + return ImageProvider::ScopedResult(std::move(record_and_callback.first), std::move(record_and_callback.second)); } diff --git a/chromium/cc/raster/paint_worklet_image_provider.h b/chromium/cc/raster/paint_worklet_image_provider.h index fe67887cf9e..866a348efa3 100644 --- a/chromium/cc/raster/paint_worklet_image_provider.h +++ b/chromium/cc/raster/paint_worklet_image_provider.h @@ -17,17 +17,18 @@ class PaintWorkletInput; class CC_EXPORT PaintWorkletImageProvider { public: explicit PaintWorkletImageProvider(PaintWorkletImageCache* cache); + PaintWorkletImageProvider(const PaintWorkletImageProvider&) = delete; + PaintWorkletImageProvider(PaintWorkletImageProvider&& other); ~PaintWorkletImageProvider(); - PaintWorkletImageProvider(PaintWorkletImageProvider&& other); + PaintWorkletImageProvider& operator=(const PaintWorkletImageProvider&) = + delete; PaintWorkletImageProvider& operator=(PaintWorkletImageProvider&& other); ImageProvider::ScopedResult GetPaintRecordResult(PaintWorkletInput* input); private: PaintWorkletImageCache* cache_; - - DISALLOW_COPY_AND_ASSIGN(PaintWorkletImageProvider); }; } // namespace cc diff --git a/chromium/cc/raster/playback_image_provider.h b/chromium/cc/raster/playback_image_provider.h index 5e76746ed5a..864ec2568ac 100644 --- a/chromium/cc/raster/playback_image_provider.h +++ b/chromium/cc/raster/playback_image_provider.h @@ -23,6 +23,8 @@ class CC_EXPORT PlaybackImageProvider : public ImageProvider { Settings(const Settings&) = delete; Settings(Settings&&); ~Settings(); + + Settings& operator=(const Settings&) = delete; Settings& operator=(Settings&&); // The set of image ids to skip during raster. @@ -36,9 +38,11 @@ class CC_EXPORT PlaybackImageProvider : public ImageProvider { // If no settings are provided, all images are skipped during rasterization. PlaybackImageProvider(ImageDecodeCache* cache, base::Optional<Settings>&& settings); + PlaybackImageProvider(const PlaybackImageProvider&) = delete; + PlaybackImageProvider(PlaybackImageProvider&& other); ~PlaybackImageProvider() override; - PlaybackImageProvider(PlaybackImageProvider&& other); + PlaybackImageProvider& operator=(const PlaybackImageProvider&) = delete; PlaybackImageProvider& operator=(PlaybackImageProvider&& other); // ImageProvider implementation. @@ -48,8 +52,6 @@ class CC_EXPORT PlaybackImageProvider : public ImageProvider { private: ImageDecodeCache* cache_; base::Optional<Settings> settings_; - - DISALLOW_COPY_AND_ASSIGN(PlaybackImageProvider); }; } // namespace cc diff --git a/chromium/cc/raster/raster_buffer_provider.cc b/chromium/cc/raster/raster_buffer_provider.cc index 0e7d1c71eaa..f5935e2f90c 100644 --- a/chromium/cc/raster/raster_buffer_provider.cc +++ b/chromium/cc/raster/raster_buffer_provider.cc @@ -74,7 +74,8 @@ void RasterBufferProvider::PlaybackToMemory( // Uses kPremul_SkAlphaType since the result is not known to be opaque. SkImageInfo info = - SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType); + SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType, + target_color_space.ToSkColorSpace()); // Use unknown pixel geometry to disable LCD text. SkSurfaceProps surface_props(0, kUnknown_SkPixelGeometry); @@ -100,19 +101,18 @@ void RasterBufferProvider::PlaybackToMemory( // invalid content, just crash the renderer and try again. // See: http://crbug.com/721744. CHECK(surface); - raster_source->PlaybackToCanvas(surface->getCanvas(), target_color_space, - content_size, canvas_bitmap_rect, - canvas_playback_rect, transform, - playback_settings); + raster_source->PlaybackToCanvas(surface->getCanvas(), content_size, + canvas_bitmap_rect, canvas_playback_rect, + transform, playback_settings); return; } case viz::RGBA_4444: { sk_sp<SkSurface> surface = SkSurface::MakeRaster(info, &surface_props); // TODO(reveman): Improve partial raster support by reducing the size of // playback rect passed to PlaybackToCanvas. crbug.com/519070 - raster_source->PlaybackToCanvas( - surface->getCanvas(), target_color_space, content_size, - canvas_bitmap_rect, canvas_bitmap_rect, transform, playback_settings); + raster_source->PlaybackToCanvas(surface->getCanvas(), content_size, + canvas_bitmap_rect, canvas_bitmap_rect, + transform, playback_settings); TRACE_EVENT0("cc", "RasterBufferProvider::PlaybackToMemory::ConvertRGBA4444"); diff --git a/chromium/cc/raster/raster_buffer_provider_perftest.cc b/chromium/cc/raster/raster_buffer_provider_perftest.cc index 6eb36031837..541b22df9a8 100644 --- a/chromium/cc/raster/raster_buffer_provider_perftest.cc +++ b/chromium/cc/raster/raster_buffer_provider_perftest.cc @@ -5,7 +5,6 @@ #include <stddef.h> #include <stdint.h> -#include "base/macros.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" #include "base/timer/lap_timer.h" @@ -67,6 +66,8 @@ class PerfGLES2Interface : public gpu::gles2::GLES2InterfaceStub { if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) *params = 1; } + + // Overridden from gpu::InterfaceBase void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override { // Copy the data over after setting the data to ensure alignment. gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, @@ -182,6 +183,9 @@ class PerfTileTask : public TileTask { class PerfImageDecodeTaskImpl : public PerfTileTask { public: PerfImageDecodeTaskImpl() = default; + PerfImageDecodeTaskImpl(const PerfImageDecodeTaskImpl&) = delete; + + PerfImageDecodeTaskImpl& operator=(const PerfImageDecodeTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override {} @@ -191,9 +195,6 @@ class PerfImageDecodeTaskImpl : public PerfTileTask { protected: ~PerfImageDecodeTaskImpl() override = default; - - private: - DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl); }; class PerfRasterBufferProviderHelper { @@ -214,6 +215,8 @@ class PerfRasterTaskImpl : public PerfTileTask { pool_(pool), resource_(std::move(in_use_resource)), raster_buffer_(std::move(raster_buffer)) {} + PerfRasterTaskImpl(const PerfRasterTaskImpl&) = delete; + PerfRasterTaskImpl& operator=(const PerfRasterTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override {} @@ -236,8 +239,6 @@ class PerfRasterTaskImpl : public PerfTileTask { ResourcePool* const pool_; ResourcePool::InUsePoolResource resource_; std::unique_ptr<RasterBuffer> raster_buffer_; - - DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl); }; class RasterBufferProviderPerfTestBase { diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc index 89332a7c8e1..df22550ebdb 100644 --- a/chromium/cc/raster/raster_buffer_provider_unittest.cc +++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc @@ -15,7 +15,6 @@ #include "base/bind_helpers.h" #include "base/cancelable_callback.h" #include "base/location.h" -#include "base/macros.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/test/metrics/histogram_tester.h" @@ -72,6 +71,8 @@ class TestRasterTaskImpl : public TileTask { id_(id), raster_buffer_(std::move(raster_buffer)), raster_source_(FakeRasterSource::CreateFilled(gfx::Size(1, 1))) {} + TestRasterTaskImpl(const TestRasterTaskImpl&) = delete; + TestRasterTaskImpl& operator=(const TestRasterTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override { @@ -98,8 +99,6 @@ class TestRasterTaskImpl : public TileTask { std::unique_ptr<RasterBuffer> raster_buffer_; scoped_refptr<RasterSource> raster_source_; GURL url_; - - DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl); }; class BlockingTestRasterTaskImpl : public TestRasterTaskImpl { @@ -115,6 +114,9 @@ class BlockingTestRasterTaskImpl : public TestRasterTaskImpl { std::move(raster_buffer), dependencies), lock_(lock) {} + BlockingTestRasterTaskImpl(const BlockingTestRasterTaskImpl&) = delete; + BlockingTestRasterTaskImpl& operator=(const BlockingTestRasterTaskImpl&) = + delete; // Overridden from Task: void RunOnWorkerThread() override { @@ -127,8 +129,6 @@ class BlockingTestRasterTaskImpl : public TestRasterTaskImpl { private: base::Lock* lock_; - - DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl); }; class RasterBufferProviderTest diff --git a/chromium/cc/raster/raster_source.cc b/chromium/cc/raster/raster_source.cc index 8f510fadc4c..8c490e481d0 100644 --- a/chromium/cc/raster/raster_source.cc +++ b/chromium/cc/raster/raster_source.cc @@ -16,7 +16,6 @@ #include "cc/paint/skia_paint_canvas.h" #include "components/viz/common/traced_value.h" #include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -111,8 +110,7 @@ void RasterSource::ClearForOpaqueRaster( } void RasterSource::PlaybackToCanvas( - SkCanvas* input_canvas, - const gfx::ColorSpace& target_color_space, + SkCanvas* raster_canvas, const gfx::Size& content_size, const gfx::Rect& canvas_bitmap_rect, const gfx::Rect& canvas_playback_rect, @@ -125,15 +123,6 @@ void RasterSource::PlaybackToCanvas( // Treat all subnormal values as zero for performance. ScopedSubnormalFloatDisabler disabler; - // TODO(enne): color transform needs to be replicated in gles2_cmd_decoder - SkCanvas* raster_canvas = input_canvas; - std::unique_ptr<SkCanvas> color_transform_canvas; - if (target_color_space.IsValid()) { - color_transform_canvas = SkCreateColorSpaceXformCanvas( - input_canvas, target_color_space.ToSkColorSpace()); - raster_canvas = color_transform_canvas.get(); - } - bool is_partial_raster = canvas_bitmap_rect != canvas_playback_rect; if (!requires_clear_) { // Clear opaque raster sources. Opaque rasters sources guarantee that all diff --git a/chromium/cc/raster/raster_source.h b/chromium/cc/raster/raster_source.h index 880f9e688c1..4866e607fe7 100644 --- a/chromium/cc/raster/raster_source.h +++ b/chromium/cc/raster/raster_source.h @@ -10,7 +10,6 @@ #include <memory> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/layers/recording_source.h" @@ -42,6 +41,9 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { ImageProvider* image_provider = nullptr; }; + RasterSource(const RasterSource&) = delete; + RasterSource& operator=(const RasterSource&) = delete; + // Helper function to apply a few common operations before passing the canvas // to the shorter version. This is useful for rastering into tiles. // canvas is expected to be backed by a tile, with a default state. @@ -52,7 +54,6 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // canvas_playback_rect can be used to replay only part of the recording in, // the content space, so only a sub-rect of the tile gets rastered. void PlaybackToCanvas(SkCanvas* canvas, - const gfx::ColorSpace& target_color_space, const gfx::Size& content_size, const gfx::Rect& canvas_bitmap_rect, const gfx::Rect& canvas_playback_rect, @@ -153,8 +154,6 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { const gfx::Size size_; const int slow_down_raster_scale_factor_for_debug_; const float recording_scale_factor_; - - DISALLOW_COPY_AND_ASSIGN(RasterSource); }; } // namespace cc diff --git a/chromium/cc/raster/raster_source_unittest.cc b/chromium/cc/raster/raster_source_unittest.cc index c694083f3ca..21338cf9c19 100644 --- a/chromium/cc/raster/raster_source_unittest.cc +++ b/chromium/cc/raster/raster_source_unittest.cc @@ -30,10 +30,6 @@ using ::testing::Sequence; namespace cc { namespace { -gfx::ColorSpace ColorSpaceForTesting() { - return gfx::ColorSpace(); -} - TEST(RasterSourceTest, AnalyzeIsSolidUnscaled) { gfx::Size layer_bounds(400, 400); @@ -346,8 +342,8 @@ TEST(RasterSourceTest, RasterFullContents) { canvas.clear(SK_ColorTRANSPARENT); raster->PlaybackToCanvas( - &canvas, ColorSpaceForTesting(), content_bounds, canvas_rect, - canvas_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + &canvas, content_bounds, canvas_rect, canvas_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), RasterSource::PlaybackSettings()); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); @@ -398,8 +394,8 @@ TEST(RasterSourceTest, RasterPartialContents) { gfx::Rect raster_full_rect(content_bounds); gfx::Rect playback_rect(content_bounds); raster->PlaybackToCanvas( - &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect, - playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + &canvas, content_bounds, raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), RasterSource::PlaybackSettings()); { @@ -430,8 +426,8 @@ TEST(RasterSourceTest, RasterPartialContents) { // that touches the edge pixels of the recording. playback_rect.Inset(1, 2, 0, 1); raster->PlaybackToCanvas( - &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect, - playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + &canvas, content_bounds, raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), RasterSource::PlaybackSettings()); SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels()); @@ -495,8 +491,8 @@ TEST(RasterSourceTest, RasterPartialClear) { gfx::Rect raster_full_rect(content_bounds); gfx::Rect playback_rect(content_bounds); raster->PlaybackToCanvas( - &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect, - playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + &canvas, content_bounds, raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), RasterSource::PlaybackSettings()); { @@ -535,8 +531,8 @@ TEST(RasterSourceTest, RasterPartialClear) { playback_rect = gfx::Rect(gfx::ScaleToCeiledSize(partial_bounds, contents_scale)); raster->PlaybackToCanvas( - &canvas, ColorSpaceForTesting(), content_bounds, raster_full_rect, - playback_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), + &canvas, content_bounds, raster_full_rect, playback_rect, + gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), RasterSource::PlaybackSettings()); // Test that the whole playback_rect was cleared and repainted with new alpha. @@ -576,7 +572,7 @@ TEST(RasterSourceTest, RasterContentsTransparent) { SkCanvas canvas(bitmap); raster->PlaybackToCanvas( - &canvas, ColorSpaceForTesting(), content_bounds, canvas_rect, canvas_rect, + &canvas, content_bounds, canvas_rect, canvas_rect, gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), RasterSource::PlaybackSettings()); @@ -623,9 +619,8 @@ TEST(RasterSourceTest, RasterTransformWithoutRecordingScale) { EXPECT_CALL(mock_canvas, willRestore()).InSequence(s); gfx::Size small_size(50, 50); - raster_source->PlaybackToCanvas(&mock_canvas, ColorSpaceForTesting(), size, - gfx::Rect(small_size), gfx::Rect(small_size), - gfx::AxisTransform2d(), + raster_source->PlaybackToCanvas(&mock_canvas, size, gfx::Rect(small_size), + gfx::Rect(small_size), gfx::AxisTransform2d(), RasterSource::PlaybackSettings()); } diff --git a/chromium/cc/raster/scoped_gpu_raster.h b/chromium/cc/raster/scoped_gpu_raster.h index 9f4e0c84aac..0ccd91c0259 100644 --- a/chromium/cc/raster/scoped_gpu_raster.h +++ b/chromium/cc/raster/scoped_gpu_raster.h @@ -8,7 +8,6 @@ #include <memory> #include "base/logging.h" -#include "base/macros.h" #include "cc/cc_export.h" namespace viz { @@ -23,15 +22,16 @@ namespace cc { class CC_EXPORT ScopedGpuRaster { public: explicit ScopedGpuRaster(viz::ContextProvider* context_provider); + ScopedGpuRaster(const ScopedGpuRaster&) = delete; ~ScopedGpuRaster(); + ScopedGpuRaster& operator=(const ScopedGpuRaster&) = delete; + private: void BeginGpuRaster(); void EndGpuRaster(); viz::ContextProvider* context_provider_; - - DISALLOW_COPY_AND_ASSIGN(ScopedGpuRaster); }; } // namespace cc diff --git a/chromium/cc/raster/staging_buffer_pool.h b/chromium/cc/raster/staging_buffer_pool.h index d3331323d6f..4b2953b01a5 100644 --- a/chromium/cc/raster/staging_buffer_pool.h +++ b/chromium/cc/raster/staging_buffer_pool.h @@ -11,7 +11,6 @@ #include <set> #include "base/containers/circular_deque.h" -#include "base/macros.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" @@ -81,12 +80,15 @@ struct StagingBuffer { class CC_EXPORT StagingBufferPool : public base::trace_event::MemoryDumpProvider { public: - ~StagingBufferPool() final; - StagingBufferPool(scoped_refptr<base::SequencedTaskRunner> task_runner, viz::RasterContextProvider* worker_context_provider, bool use_partial_raster, int max_staging_buffer_usage_in_bytes); + StagingBufferPool(const StagingBufferPool&) = delete; + ~StagingBufferPool() final; + + StagingBufferPool& operator=(const StagingBufferPool&) = delete; + void Shutdown(); // Overridden from base::trace_event::MemoryDumpProvider: @@ -141,8 +143,6 @@ class CC_EXPORT StagingBufferPool std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; base::WeakPtrFactory<StagingBufferPool> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(StagingBufferPool); }; } // namespace cc diff --git a/chromium/cc/raster/task.h b/chromium/cc/raster/task.h index d67cb7ac055..53695431b3c 100644 --- a/chromium/cc/raster/task.h +++ b/chromium/cc/raster/task.h @@ -112,18 +112,17 @@ struct CC_EXPORT TaskGraph { uint16_t category, uint16_t priority, uint32_t dependencies); + Node(const Node&) = delete; Node(Node&& other); ~Node(); + Node& operator=(const Node&) = delete; Node& operator=(Node&& other) = default; scoped_refptr<Task> task; uint16_t category; uint16_t priority; uint32_t dependencies; - - private: - DISALLOW_COPY_AND_ASSIGN(Node); }; struct Edge { @@ -137,17 +136,18 @@ struct CC_EXPORT TaskGraph { }; TaskGraph(); + TaskGraph(const TaskGraph&) = delete; TaskGraph(TaskGraph&& other); ~TaskGraph(); + TaskGraph& operator=(const TaskGraph&) = delete; + TaskGraph& operator=(TaskGraph&&) = default; + void Swap(TaskGraph* other); void Reset(); Node::Vector nodes; Edge::Vector edges; - - private: - DISALLOW_COPY_AND_ASSIGN(TaskGraph); }; } // namespace cc diff --git a/chromium/cc/raster/task_graph_runner_perftest.cc b/chromium/cc/raster/task_graph_runner_perftest.cc index 36ee90fab57..d7f35a0b738 100644 --- a/chromium/cc/raster/task_graph_runner_perftest.cc +++ b/chromium/cc/raster/task_graph_runner_perftest.cc @@ -8,7 +8,6 @@ #include <memory> #include <vector> -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/time/time.h" #include "base/timer/lap_timer.h" @@ -29,6 +28,8 @@ class PerfTaskImpl : public Task { typedef std::vector<scoped_refptr<PerfTaskImpl>> Vector; PerfTaskImpl() = default; + PerfTaskImpl(const PerfTaskImpl&) = delete; + PerfTaskImpl& operator=(const PerfTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override {} @@ -37,8 +38,6 @@ class PerfTaskImpl : public Task { private: ~PerfTaskImpl() override = default; - - DISALLOW_COPY_AND_ASSIGN(PerfTaskImpl); }; class TaskGraphRunnerPerfTest : public testing::Test { diff --git a/chromium/cc/raster/task_graph_work_queue.h b/chromium/cc/raster/task_graph_work_queue.h index b1bbce8636a..3b739f7214d 100644 --- a/chromium/cc/raster/task_graph_work_queue.h +++ b/chromium/cc/raster/task_graph_work_queue.h @@ -35,18 +35,17 @@ class CC_EXPORT TaskGraphWorkQueue { TaskNamespace* task_namespace, uint16_t category, uint16_t priority); + PrioritizedTask(const PrioritizedTask&) = delete; PrioritizedTask(PrioritizedTask&& other); ~PrioritizedTask(); + PrioritizedTask& operator=(const PrioritizedTask&) = delete; PrioritizedTask& operator=(PrioritizedTask&& other) = default; scoped_refptr<Task> task; TaskNamespace* task_namespace; uint16_t category; uint16_t priority; - - private: - DISALLOW_COPY_AND_ASSIGN(PrioritizedTask); }; using CategorizedTask = std::pair<uint16_t, scoped_refptr<Task>>; @@ -56,9 +55,13 @@ class CC_EXPORT TaskGraphWorkQueue { typedef std::vector<TaskNamespace*> Vector; TaskNamespace(); + TaskNamespace(const TaskNamespace&) = delete; TaskNamespace(TaskNamespace&& other); ~TaskNamespace(); + TaskNamespace& operator=(const TaskNamespace&) = delete; + TaskNamespace& operator=(TaskNamespace&&) = default; + // Current task graph. TaskGraph graph; @@ -71,14 +74,14 @@ class CC_EXPORT TaskGraphWorkQueue { // This set contains all currently running tasks. std::vector<CategorizedTask> running_tasks; - - private: - DISALLOW_COPY_AND_ASSIGN(TaskNamespace); }; TaskGraphWorkQueue(); + TaskGraphWorkQueue(const TaskGraphWorkQueue&) = delete; virtual ~TaskGraphWorkQueue(); + TaskGraphWorkQueue& operator=(const TaskGraphWorkQueue&) = delete; + // Generates a NamespaceToken which is guaranteed to be unique within this // TaskGraphWorkQueue. NamespaceToken GenerateNamespaceToken(); @@ -192,8 +195,6 @@ class CC_EXPORT TaskGraphWorkQueue { // Provides a unique id to each NamespaceToken. int next_namespace_id_; - - DISALLOW_COPY_AND_ASSIGN(TaskGraphWorkQueue); }; } // namespace cc diff --git a/chromium/cc/raster/task_graph_work_queue_unittest.cc b/chromium/cc/raster/task_graph_work_queue_unittest.cc index 93455db7e23..ac78a6d0fd2 100644 --- a/chromium/cc/raster/task_graph_work_queue_unittest.cc +++ b/chromium/cc/raster/task_graph_work_queue_unittest.cc @@ -13,13 +13,15 @@ namespace { class FakeTaskImpl : public Task { public: FakeTaskImpl() = default; + FakeTaskImpl(const FakeTaskImpl&) = delete; + + FakeTaskImpl& operator=(const FakeTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override {} private: ~FakeTaskImpl() override = default; - DISALLOW_COPY_AND_ASSIGN(FakeTaskImpl); }; TEST(TaskGraphWorkQueueTest, TestChangingDependency) { diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc index 8e5eb1cf279..6f491eb7a47 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc @@ -8,7 +8,6 @@ #include <algorithm> -#include "base/macros.h" #include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" @@ -75,6 +74,7 @@ class ZeroCopyRasterBufferImpl : public RasterBuffer { resource_format_(in_use_resource.format()), resource_color_space_(in_use_resource.color_space()), gpu_memory_buffer_(std::move(backing_->gpu_memory_buffer)) {} + ZeroCopyRasterBufferImpl(const ZeroCopyRasterBufferImpl&) = delete; ~ZeroCopyRasterBufferImpl() override { // If GpuMemoryBuffer allocation failed (https://crbug.com/554541), then @@ -107,6 +107,8 @@ class ZeroCopyRasterBufferImpl : public RasterBuffer { backing_->gpu_memory_buffer = std::move(gpu_memory_buffer_); } + ZeroCopyRasterBufferImpl& operator=(const ZeroCopyRasterBufferImpl&) = delete; + // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, const gfx::Rect& raster_full_rect, @@ -154,8 +156,6 @@ class ZeroCopyRasterBufferImpl : public RasterBuffer { viz::ResourceFormat resource_format_; gfx::ColorSpace resource_color_space_; std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; - - DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterBufferImpl); }; } // namespace diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.h b/chromium/cc/raster/zero_copy_raster_buffer_provider.h index 680d6b02128..6bb0e333976 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.h @@ -7,7 +7,6 @@ #include <stdint.h> -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/values.h" #include "cc/raster/raster_buffer_provider.h" @@ -30,8 +29,12 @@ class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, viz::ContextProvider* compositor_context_provider, viz::ResourceFormat tile_format); + ZeroCopyRasterBufferProvider(const ZeroCopyRasterBufferProvider&) = delete; ~ZeroCopyRasterBufferProvider() override; + ZeroCopyRasterBufferProvider& operator=(const ZeroCopyRasterBufferProvider&) = + delete; + // Overridden from RasterBufferProvider: std::unique_ptr<RasterBuffer> AcquireBufferForRaster( const ResourcePool::InUsePoolResource& resource, @@ -58,8 +61,6 @@ class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; viz::ContextProvider* compositor_context_provider_; viz::ResourceFormat tile_format_; - - DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterBufferProvider); }; } // namespace cc diff --git a/chromium/cc/resources/memory_history.h b/chromium/cc/resources/memory_history.h index 14a2fbb2786..f5a7e9c8943 100644 --- a/chromium/cc/resources/memory_history.h +++ b/chromium/cc/resources/memory_history.h @@ -11,7 +11,6 @@ #include <memory> #include "base/containers/ring_buffer.h" -#include "base/macros.h" #include "base/time/time.h" namespace cc { @@ -21,6 +20,9 @@ class MemoryHistory { public: static std::unique_ptr<MemoryHistory> Create(); + MemoryHistory(const MemoryHistory&) = delete; + MemoryHistory& operator=(const MemoryHistory&) = delete; + size_t HistorySize() const { return ring_buffer_.BufferSize(); } struct Entry { @@ -44,8 +46,6 @@ class MemoryHistory { MemoryHistory(); RingBufferType ring_buffer_; - - DISALLOW_COPY_AND_ASSIGN(MemoryHistory); }; } // namespace cc diff --git a/chromium/cc/resources/resource_pool.h b/chromium/cc/resources/resource_pool.h index cd72eb84b7c..b7f2f8d9e77 100644 --- a/chromium/cc/resources/resource_pool.h +++ b/chromium/cc/resources/resource_pool.h @@ -12,7 +12,6 @@ #include <memory> #include "base/containers/circular_deque.h" -#include "base/macros.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" @@ -199,8 +198,11 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { const base::TimeDelta& expiration_delay, bool disallow_non_exact_reuse); + ResourcePool(const ResourcePool&) = delete; ~ResourcePool() override; + ResourcePool& operator=(const ResourcePool&) = delete; + // Tries to reuse a resource. If none are available, makes a new one. InUsePoolResource AcquireResource(const gfx::Size& size, viz::ResourceFormat format, @@ -407,8 +409,6 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { const base::TickClock* clock_; base::WeakPtrFactory<ResourcePool> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ResourcePool); }; } // namespace cc diff --git a/chromium/cc/resources/scoped_ui_resource.h b/chromium/cc/resources/scoped_ui_resource.h index 8b11f7ee7f0..e12dabd6b97 100644 --- a/chromium/cc/resources/scoped_ui_resource.h +++ b/chromium/cc/resources/scoped_ui_resource.h @@ -5,7 +5,6 @@ #ifndef CC_RESOURCES_SCOPED_UI_RESOURCE_H_ #define CC_RESOURCES_SCOPED_UI_RESOURCE_H_ -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/cc_export.h" #include "cc/resources/ui_resource_bitmap.h" @@ -26,8 +25,11 @@ class CC_EXPORT ScopedUIResource : public UIResourceClient { static std::unique_ptr<ScopedUIResource> Create( UIResourceManager* ui_resource_manager, const UIResourceBitmap& bitmap); + ScopedUIResource(const ScopedUIResource&) = delete; ~ScopedUIResource() override; + ScopedUIResource& operator=(const ScopedUIResource&) = delete; + // UIResourceClient implementation. UIResourceBitmap GetBitmap(UIResourceId uid, bool resource_lost) override; UIResourceId id() { return id_; } @@ -42,9 +44,6 @@ class CC_EXPORT ScopedUIResource : public UIResourceClient { UIResourceBitmap bitmap_; UIResourceManager* ui_resource_manager_; UIResourceId id_; - - private: - DISALLOW_COPY_AND_ASSIGN(ScopedUIResource); }; } // namespace cc diff --git a/chromium/cc/resources/shared_bitmap_id_registrar.h b/chromium/cc/resources/shared_bitmap_id_registrar.h index b3533defd53..6abb30ed420 100644 --- a/chromium/cc/resources/shared_bitmap_id_registrar.h +++ b/chromium/cc/resources/shared_bitmap_id_registrar.h @@ -49,9 +49,12 @@ class CC_EXPORT SharedBitmapIdRegistrar { class CC_EXPORT SharedBitmapIdRegistration { public: SharedBitmapIdRegistration(); + SharedBitmapIdRegistration(const SharedBitmapIdRegistration&) = delete; + SharedBitmapIdRegistration(SharedBitmapIdRegistration&&); ~SharedBitmapIdRegistration(); - SharedBitmapIdRegistration(SharedBitmapIdRegistration&&); + SharedBitmapIdRegistration& operator=(const SharedBitmapIdRegistration&) = + delete; SharedBitmapIdRegistration& operator=(SharedBitmapIdRegistration&&); private: @@ -63,8 +66,6 @@ class CC_EXPORT SharedBitmapIdRegistration { base::WeakPtr<TextureLayer> layer_ptr_; viz::SharedBitmapId id_; - - DISALLOW_COPY_AND_ASSIGN(SharedBitmapIdRegistration); }; } // namespace cc diff --git a/chromium/cc/resources/ui_resource_manager.h b/chromium/cc/resources/ui_resource_manager.h index 7f29ba61f30..e3e51204656 100644 --- a/chromium/cc/resources/ui_resource_manager.h +++ b/chromium/cc/resources/ui_resource_manager.h @@ -8,7 +8,6 @@ #include <unordered_map> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/resources/ui_resource_request.h" @@ -18,8 +17,11 @@ class ScopedUIResource; class CC_EXPORT UIResourceManager { public: UIResourceManager(); + UIResourceManager(const UIResourceManager&) = delete; virtual ~UIResourceManager(); + UIResourceManager& operator=(const UIResourceManager&) = delete; + // CreateUIResource creates a resource given a bitmap. The bitmap is // generated via an interface function, which is called when initializing the // resource and when the resource has been lost (due to lost context). The @@ -65,8 +67,6 @@ class CC_EXPORT UIResourceManager { // DeleteUIResource). std::unordered_map<SkPixelRef*, std::unique_ptr<ScopedUIResource>> owned_shared_resources_; - - DISALLOW_COPY_AND_ASSIGN(UIResourceManager); }; } // namespace cc diff --git a/chromium/cc/scheduler/compositor_frame_reporter.cc b/chromium/cc/scheduler/compositor_frame_reporter.cc new file mode 100644 index 00000000000..9b4c7ac2a5f --- /dev/null +++ b/chromium/cc/scheduler/compositor_frame_reporter.cc @@ -0,0 +1,56 @@ +// Copyright 2019 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/scheduler/compositor_frame_reporter.h" + +#include "base/trace_event/trace_event.h" + +namespace cc { + +CompositorFrameReporter::CompositorFrameReporter() { + TRACE_EVENT_ASYNC_BEGIN0("cc,benchmark", "PipelineReporter", this); +} + +CompositorFrameReporter::~CompositorFrameReporter() { + TerminateFrame(); +} + +void CompositorFrameReporter::StartStage(const char* stage_name) { + TRACE_EVENT_ASYNC_STEP_INTO0("cc,benchmark", "PipelineReporter", this, + TRACE_STR_COPY(stage_name)); +} + +void CompositorFrameReporter::SetFrameTerminationStatus( + FrameTerminationStatus termination_status) { + frame_termination_status_ = termination_status; +} + +void CompositorFrameReporter::TerminateFrame() { + const char* termination_status_str; + switch (frame_termination_status_) { + case FrameTerminationStatus::kSubmittedFrame: + termination_status_str = "submitted_frame"; + break; + case FrameTerminationStatus::kSubmittedFrameMissedDeadline: + termination_status_str = "missed_frame"; + break; + case FrameTerminationStatus::kMainFrameAborted: + termination_status_str = "main_frame_aborted"; + break; + case FrameTerminationStatus::kReplacedByNewReporter: + termination_status_str = "replaced_by_new_reporter_at_same_stage"; + break; + case FrameTerminationStatus::kDidNotProduceFrame: + termination_status_str = "did_not_produce_frame"; + break; + case FrameTerminationStatus::kUnknown: + NOTREACHED(); + break; + } + TRACE_EVENT_ASYNC_END1("cc,benchmark", "PipelineReporter", this, + "termination_status", + TRACE_STR_COPY(termination_status_str)); + // TODO(alsan): UMA histogram reporting +} +} // namespace cc diff --git a/chromium/cc/scheduler/compositor_frame_reporter.h b/chromium/cc/scheduler/compositor_frame_reporter.h new file mode 100644 index 00000000000..b122693b1d2 --- /dev/null +++ b/chromium/cc/scheduler/compositor_frame_reporter.h @@ -0,0 +1,67 @@ +// Copyright 2019 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_SCHEDULER_COMPOSITOR_FRAME_REPORTER_H_ +#define CC_SCHEDULER_COMPOSITOR_FRAME_REPORTER_H_ + +#include "cc/base/base_export.h" +#include "cc/cc_export.h" + +namespace cc { +// This is used for tracing the pipeline stages of a single frame. +// +// For each stage in the frame pipeline, calling StartStage will start tracing +// that stage (and end any currently running stages). +// TODO(alsan): Report stage durations to UMA. +class CC_EXPORT CompositorFrameReporter { + public: + enum FrameTerminationStatus { + // Compositor frame (with main thread updates) is submitted before a new + // BeginImplFrame is issued (i.e. BF -> BMF -> Commit -> Activate -> + // Submit). + kSubmittedFrame, + + // Same as SubmittedFrame, but with the condition that there is another + // frame being processed in the pipeline at an earlier stage. + // This would imply that a new BeginImplFrame was issued during the lifetime + // of this reporter, and therefore it missed its deadline + // (e.g. BF1 -> BMF1 -> Submit -> BF2 -> Commit1 -> Activate1 -> BMF2 -> + // Submit). + kSubmittedFrameMissedDeadline, + + // Main frame was aborted; the reporter will not continue reporting. + kMainFrameAborted, + + // Reporter that is currently at a stage is replaced by a new one (e.g. two + // BeginImplFrames can happen without issuing BeginMainFrame, so the first + // reporter would terminate with this status). + // TODO(alsan): Track impl-only frames. + kReplacedByNewReporter, + + // Frame that was being tracked did not end up being submitting (e.g. frame + // had no damage or LTHI was ended). + kDidNotProduceFrame, + + // Default termination status. Should not be reachable. + kUnknown + }; + + CompositorFrameReporter(); + CompositorFrameReporter(const CompositorFrameReporter& reporter) = delete; + ~CompositorFrameReporter(); + + CompositorFrameReporter& operator=(const CompositorFrameReporter& reporter) = + delete; + + void StartStage(const char* stage_name); + void SetFrameTerminationStatus(FrameTerminationStatus termination_status); + + private: + FrameTerminationStatus frame_termination_status_ = + FrameTerminationStatus::kUnknown; + void TerminateFrame(); +}; +} // namespace cc + +#endif // CC_SCHEDULER_COMPOSITOR_FRAME_REPORTER_H_" diff --git a/chromium/cc/scheduler/compositor_frame_reporting_controller.cc b/chromium/cc/scheduler/compositor_frame_reporting_controller.cc new file mode 100644 index 00000000000..f1587ed158d --- /dev/null +++ b/chromium/cc/scheduler/compositor_frame_reporting_controller.cc @@ -0,0 +1,123 @@ +// Copyright 2019 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/scheduler/compositor_frame_reporting_controller.h" + +#include "cc/scheduler/compositor_frame_reporter.h" + +namespace cc { +CompositorFrameReportingController::CompositorFrameReportingController() {} + +CompositorFrameReportingController::~CompositorFrameReportingController() { + for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) { + if (reporters_[i]) { + reporters_[i]->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame); + } + } +} + +void CompositorFrameReportingController::WillBeginImplFrame() { + std::unique_ptr<CompositorFrameReporter> reporter = + std::make_unique<CompositorFrameReporter>(); + reporter->StartStage("BeginImplFrameToSendBeginMainFrame"); + if (reporters_[PipelineStage::kBeginImplFrame]) + reporters_[PipelineStage::kBeginImplFrame]->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus:: + kReplacedByNewReporter); + reporters_[PipelineStage::kBeginImplFrame] = std::move(reporter); +} + +void CompositorFrameReportingController::WillBeginMainFrame() { + DCHECK(reporters_[PipelineStage::kBeginImplFrame]); + DCHECK_NE(reporters_[PipelineStage::kBeginMainFrame], + reporters_[PipelineStage::kBeginImplFrame]); + reporters_[PipelineStage::kBeginImplFrame]->StartStage( + "SendBeginMainFrameToCommit"); + AdvanceReporterStage(PipelineStage::kBeginImplFrame, + PipelineStage::kBeginMainFrame); +} + +void CompositorFrameReportingController::BeginMainFrameAborted() { + DCHECK(reporters_[PipelineStage::kBeginMainFrame]); + std::unique_ptr<CompositorFrameReporter> aborted_frame_reporter = + std::move(reporters_[PipelineStage::kBeginMainFrame]); + aborted_frame_reporter->StartStage("BeginMainFrameAborted"); + aborted_frame_reporter->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus::kMainFrameAborted); +} + +void CompositorFrameReportingController::WillCommit() { + DCHECK(reporters_[PipelineStage::kBeginMainFrame]); + reporters_[PipelineStage::kBeginMainFrame]->StartStage("Commit"); +} + +void CompositorFrameReportingController::DidCommit() { + DCHECK(reporters_[PipelineStage::kBeginMainFrame]); + reporters_[PipelineStage::kBeginMainFrame]->StartStage( + "EndCommitToActivation"); + AdvanceReporterStage(PipelineStage::kBeginMainFrame, PipelineStage::kCommit); +} + +void CompositorFrameReportingController::WillInvalidateOnImplSide() { + // Allows for activation without committing. + // TODO(alsan): Report latency of impl side invalidations. + next_activate_has_invalidation_ = true; +} +void CompositorFrameReportingController::WillActivate() { + DCHECK(reporters_[PipelineStage::kCommit] || next_activate_has_invalidation_); + if (!reporters_[PipelineStage::kCommit]) + return; + reporters_[PipelineStage::kCommit]->StartStage("Activation"); +} + +void CompositorFrameReportingController::DidActivate() { + DCHECK(reporters_[PipelineStage::kCommit] || next_activate_has_invalidation_); + next_activate_has_invalidation_ = false; + if (!reporters_[PipelineStage::kCommit]) + return; + reporters_[PipelineStage::kCommit]->StartStage( + "EndActivateToSubmitCompositorFrame"); + AdvanceReporterStage(PipelineStage::kCommit, PipelineStage::kActivate); +} + +void CompositorFrameReportingController::DidSubmitCompositorFrame() { + if (!reporters_[PipelineStage::kActivate]) + return; + std::unique_ptr<CompositorFrameReporter> submitted_reporter = + std::move(reporters_[PipelineStage::kActivate]); + submitted_reporter->StartStage("SubmitCompositorFrame"); + // If there are any other reporters active on the other stages of the + // pipeline then that means a new frame was started during the duration of + // this reporter and therefore the frame being tracked missed the deadline. + if (reporters_[PipelineStage::kBeginImplFrame] || + reporters_[PipelineStage::kBeginMainFrame] || + reporters_[PipelineStage::kCommit]) { + submitted_reporter->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus:: + kSubmittedFrameMissedDeadline); + } else { + submitted_reporter->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame); + } +} + +void CompositorFrameReportingController::DidNotProduceFrame() { + if (reporters_[PipelineStage::kActivate]) + reporters_[PipelineStage::kActivate]->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame); + reporters_[PipelineStage::kActivate] = nullptr; +} + +void CompositorFrameReportingController::AdvanceReporterStage( + PipelineStage start, + PipelineStage target) { + if (reporters_[target]) { + reporters_[target]->SetFrameTerminationStatus( + CompositorFrameReporter::FrameTerminationStatus:: + kReplacedByNewReporter); + } + reporters_[target] = std::move(reporters_[start]); +} +} // namespace cc diff --git a/chromium/cc/scheduler/compositor_frame_reporting_controller.h b/chromium/cc/scheduler/compositor_frame_reporting_controller.h new file mode 100644 index 00000000000..9b72cffc28d --- /dev/null +++ b/chromium/cc/scheduler/compositor_frame_reporting_controller.h @@ -0,0 +1,65 @@ +// Copyright 2019 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_SCHEDULER_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_ +#define CC_SCHEDULER_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_ + +#include <memory> + +#include "base/time/time.h" +#include "cc/base/base_export.h" +#include "cc/cc_export.h" + +namespace cc { +class CompositorFrameReporter; + +// This is used for managing simultaneous CompositorFrameReporter instances +// in the case that the compositor has high latency. Calling one of the +// event functions will begin recording the time of the corresponding +// phase and trace it. If the frame is eventually submitted, then the +// recorded times of each phase will be reported in UMA. +// See CompositorFrameReporter. +class CC_EXPORT CompositorFrameReportingController { + public: + // Used as indices for accessing CompositorFrameReporters. + enum PipelineStage { + kBeginImplFrame = 0, + kBeginMainFrame, + kCommit, + kActivate, + kNumPipelineStages + }; + + CompositorFrameReportingController(); + virtual ~CompositorFrameReportingController(); + + CompositorFrameReportingController( + const CompositorFrameReportingController&) = delete; + CompositorFrameReportingController& operator=( + const CompositorFrameReportingController&) = delete; + + // Events to signal Beginning/Ending of phases. + virtual void WillBeginImplFrame(); + virtual void WillBeginMainFrame(); + virtual void BeginMainFrameAborted(); + virtual void WillInvalidateOnImplSide(); + virtual void WillCommit(); + virtual void DidCommit(); + virtual void WillActivate(); + virtual void DidActivate(); + virtual void DidSubmitCompositorFrame(); + virtual void DidNotProduceFrame(); + + protected: + std::unique_ptr<CompositorFrameReporter> + reporters_[PipelineStage::kNumPipelineStages]; + + private: + void AdvanceReporterStage(PipelineStage start, PipelineStage target); + + bool next_activate_has_invalidation_ = false; +}; +} // namespace cc + +#endif // CC_SCHEDULER_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_ diff --git a/chromium/cc/scheduler/compositor_frame_reporting_controller_unittest.cc b/chromium/cc/scheduler/compositor_frame_reporting_controller_unittest.cc new file mode 100644 index 00000000000..94f6ffdfa66 --- /dev/null +++ b/chromium/cc/scheduler/compositor_frame_reporting_controller_unittest.cc @@ -0,0 +1,156 @@ +// Copyright 2015 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/scheduler/compositor_frame_reporting_controller.h" + +#include "base/macros.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class CompositorFrameReportingControllerTest; + +class TestCompositorFrameReportingController + : public CompositorFrameReportingController { + public: + TestCompositorFrameReportingController( + CompositorFrameReportingControllerTest* test) + : CompositorFrameReportingController(), test_(test) {} + + TestCompositorFrameReportingController( + const TestCompositorFrameReportingController& controller) = delete; + + TestCompositorFrameReportingController& operator=( + const TestCompositorFrameReportingController& controller) = delete; + + std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; } + + int ActiveReporters() { + int count = 0; + for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) { + if (reporters_[i]) + ++count; + } + return count; + } + + protected: + CompositorFrameReportingControllerTest* test_; +}; + +class CompositorFrameReportingControllerTest : public testing::Test { + public: + CompositorFrameReportingControllerTest() : reporting_controller_(this) {} + + // The following functions simulate the actions that would + // occur for each phase of the reporting controller. + void SimulateBeginImplFrame() { reporting_controller_.WillBeginImplFrame(); } + + void SimulateBeginMainFrame() { + if (!reporting_controller_.reporters()[CompositorFrameReportingController:: + PipelineStage::kBeginImplFrame]) + SimulateBeginImplFrame(); + CHECK( + reporting_controller_.reporters()[CompositorFrameReportingController:: + PipelineStage::kBeginImplFrame]); + reporting_controller_.WillBeginMainFrame(); + } + + void SimulateCommit() { + if (!reporting_controller_.reporters()[CompositorFrameReportingController:: + PipelineStage::kBeginMainFrame]) + SimulateBeginMainFrame(); + CHECK( + reporting_controller_.reporters()[CompositorFrameReportingController:: + PipelineStage::kBeginMainFrame]); + reporting_controller_.WillCommit(); + reporting_controller_.DidCommit(); + } + + void SimulateActivate() { + if (!reporting_controller_.reporters() + [CompositorFrameReportingController::PipelineStage::kCommit]) + SimulateCommit(); + CHECK(reporting_controller_.reporters() + [CompositorFrameReportingController::PipelineStage::kCommit]); + reporting_controller_.WillActivate(); + reporting_controller_.DidActivate(); + } + + void SimulateSubmitCompositorFrame() { + if (!reporting_controller_.reporters() + [CompositorFrameReportingController::PipelineStage::kActivate]) + SimulateActivate(); + CHECK(reporting_controller_.reporters() + [CompositorFrameReportingController::PipelineStage::kActivate]); + reporting_controller_.DidSubmitCompositorFrame(); + } + + protected: + TestCompositorFrameReportingController reporting_controller_; +}; + +TEST_F(CompositorFrameReportingControllerTest, ActiveReporterCounts) { + // Check that there are no leaks with the CompositorFrameReporter + // objects no matter what the sequence of scheduled actions is + // Note that due to DCHECKs in WillCommit(), WillActivate(), etc., it + // is impossible to have 2 reporters both in BMF or Commit + + // Tests Cases: + // - 2 Reporters at Activate phase + // - 2 back-to-back BeginImplFrames + // - 4 Simultaneous Reporters + + // BF + reporting_controller_.WillBeginImplFrame(); + EXPECT_EQ(1, reporting_controller_.ActiveReporters()); + + // BF -> BF + // Should replace previous reporter + reporting_controller_.WillBeginImplFrame(); + EXPECT_EQ(1, reporting_controller_.ActiveReporters()); + + // BF -> BMF -> BF + // Should add new reporter + reporting_controller_.WillBeginMainFrame(); + reporting_controller_.WillBeginImplFrame(); + EXPECT_EQ(2, reporting_controller_.ActiveReporters()); + + // BF -> BMF -> BF -> Commit + // Should stay same + reporting_controller_.WillCommit(); + reporting_controller_.DidCommit(); + EXPECT_EQ(2, reporting_controller_.ActiveReporters()); + + // BF -> BMF -> BF -> Commit -> BMF -> Activate -> Commit -> Activation + // Having two reporters at Activate phase should delete the older one + reporting_controller_.WillBeginMainFrame(); + reporting_controller_.WillActivate(); + reporting_controller_.DidActivate(); + reporting_controller_.WillCommit(); + reporting_controller_.DidCommit(); + reporting_controller_.WillActivate(); + reporting_controller_.DidActivate(); + EXPECT_EQ(1, reporting_controller_.ActiveReporters()); + + reporting_controller_.DidSubmitCompositorFrame(); + EXPECT_EQ(0, reporting_controller_.ActiveReporters()); + + // 4 simultaneous reporters + SimulateActivate(); + + SimulateCommit(); + + SimulateBeginMainFrame(); + + SimulateBeginImplFrame(); + EXPECT_EQ(4, reporting_controller_.ActiveReporters()); + + // Any additional BeginImplFrame's would be ignored + SimulateBeginImplFrame(); + EXPECT_EQ(4, reporting_controller_.ActiveReporters()); +} +} // namespace +} // namespace cc diff --git a/chromium/cc/scheduler/compositor_timing_history.cc b/chromium/cc/scheduler/compositor_timing_history.cc index affa7ac4ab7..6e1b3966f4f 100644 --- a/chromium/cc/scheduler/compositor_timing_history.cc +++ b/chromium/cc/scheduler/compositor_timing_history.cc @@ -12,6 +12,7 @@ #include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "cc/debug/rendering_stats_instrumentation.h" +#include "cc/scheduler/compositor_frame_reporting_controller.h" namespace cc { @@ -401,7 +402,8 @@ class NullUMAReporter : public CompositorTimingHistory::UMAReporter { CompositorTimingHistory::CompositorTimingHistory( bool using_synchronous_renderer_compositor, UMACategory uma_category, - RenderingStatsInstrumentation* rendering_stats_instrumentation) + RenderingStatsInstrumentation* rendering_stats_instrumentation, + CompositorFrameReportingController* compositor_frame_reporting_controller) : using_synchronous_renderer_compositor_( using_synchronous_renderer_compositor), enabled_(false), @@ -423,7 +425,9 @@ CompositorTimingHistory::CompositorTimingHistory( begin_main_frame_on_critical_path_(false), submit_ack_watchdog_enabled_(false), uma_reporter_(CreateUMAReporter(uma_category)), - rendering_stats_instrumentation_(rendering_stats_instrumentation) {} + rendering_stats_instrumentation_(rendering_stats_instrumentation), + compositor_frame_reporting_controller_( + compositor_frame_reporting_controller) {} CompositorTimingHistory::~CompositorTimingHistory() = default; @@ -559,10 +563,14 @@ void CompositorTimingHistory::DidCreateAndInitializeLayerTreeFrameSink() { } void CompositorTimingHistory::WillBeginImplFrame( + const viz::BeginFrameArgs& args, bool new_active_tree_is_likely, - base::TimeTicks frame_time, - viz::BeginFrameArgs::BeginFrameArgsType frame_type, base::TimeTicks now) { + viz::BeginFrameArgs::BeginFrameArgsType frame_type = args.type; + base::TimeTicks frame_time = args.frame_time; + + compositor_frame_reporting_controller_->WillBeginImplFrame(); + // The check for whether a BeginMainFrame was sent anytime between two // BeginImplFrames protects us from not detecting a fast main thread that // does all it's work and goes idle in between BeginImplFrames. @@ -605,6 +613,8 @@ void CompositorTimingHistory::WillBeginMainFrame( DCHECK_EQ(base::TimeTicks(), begin_main_frame_sent_time_); DCHECK_EQ(base::TimeTicks(), begin_main_frame_frame_time_); + compositor_frame_reporting_controller_->WillBeginMainFrame(); + begin_main_frame_on_critical_path_ = on_critical_path; begin_main_frame_sent_time_ = Now(); begin_main_frame_frame_time_ = main_frame_time; @@ -621,6 +631,7 @@ void CompositorTimingHistory::BeginMainFrameStarted( } void CompositorTimingHistory::BeginMainFrameAborted() { + compositor_frame_reporting_controller_->BeginMainFrameAborted(); SetBeginMainFrameCommittingContinuously(false); base::TimeTicks begin_main_frame_end_time = Now(); DidBeginMainFrame(begin_main_frame_end_time); @@ -635,6 +646,7 @@ void CompositorTimingHistory::NotifyReadyToCommit() { void CompositorTimingHistory::WillCommit() { DCHECK_NE(begin_main_frame_start_time_, base::TimeTicks()); + compositor_frame_reporting_controller_->WillCommit(); commit_start_time_ = Now(); } @@ -643,6 +655,8 @@ void CompositorTimingHistory::DidCommit() { DCHECK_EQ(pending_tree_creation_time_, base::TimeTicks()); DCHECK_NE(commit_start_time_, base::TimeTicks()); + compositor_frame_reporting_controller_->DidCommit(); + SetBeginMainFrameCommittingContinuously(true); base::TimeTicks begin_main_frame_end_time = Now(); DidBeginMainFrame(begin_main_frame_end_time); @@ -722,6 +736,7 @@ void CompositorTimingHistory::WillInvalidateOnImplSide() { DCHECK(!pending_tree_is_impl_side_); DCHECK_EQ(pending_tree_creation_time_, base::TimeTicks()); + compositor_frame_reporting_controller_->WillInvalidateOnImplSide(); pending_tree_is_impl_side_ = true; pending_tree_creation_time_ = base::TimeTicks::Now(); } @@ -777,6 +792,7 @@ void CompositorTimingHistory::ReadyToActivate() { void CompositorTimingHistory::WillActivate() { DCHECK_EQ(base::TimeTicks(), activate_start_time_); + compositor_frame_reporting_controller_->WillActivate(); activate_start_time_ = Now(); // Its possible to activate the pending tree before it is ready for @@ -796,6 +812,7 @@ void CompositorTimingHistory::WillActivate() { void CompositorTimingHistory::DidActivate() { DCHECK_NE(base::TimeTicks(), activate_start_time_); + compositor_frame_reporting_controller_->DidActivate(); base::TimeDelta activate_duration = Now() - activate_start_time_; uma_reporter_->AddActivateDuration(activate_duration); @@ -907,10 +924,15 @@ void CompositorTimingHistory::DidDraw( void CompositorTimingHistory::DidSubmitCompositorFrame() { DCHECK_EQ(base::TimeTicks(), submit_start_time_); + compositor_frame_reporting_controller_->DidSubmitCompositorFrame(); submit_start_time_ = Now(); submit_ack_watchdog_enabled_ = true; } +void CompositorTimingHistory::DidNotProduceFrame() { + compositor_frame_reporting_controller_->DidNotProduceFrame(); +} + void CompositorTimingHistory::DidReceiveCompositorFrameAck() { DCHECK_NE(base::TimeTicks(), submit_start_time_); base::TimeDelta submit_to_ack_duration = Now() - submit_start_time_; diff --git a/chromium/cc/scheduler/compositor_timing_history.h b/chromium/cc/scheduler/compositor_timing_history.h index 842583f1106..b5ae6cee06e 100644 --- a/chromium/cc/scheduler/compositor_timing_history.h +++ b/chromium/cc/scheduler/compositor_timing_history.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "cc/base/rolling_time_delta_history.h" #include "cc/cc_export.h" #include "cc/tiles/tile_priority.h" @@ -21,6 +20,7 @@ class TracedValue; namespace cc { +class CompositorFrameReportingController; class RenderingStatsInstrumentation; class CC_EXPORT CompositorTimingHistory { @@ -35,9 +35,14 @@ class CC_EXPORT CompositorTimingHistory { CompositorTimingHistory( bool using_synchronous_renderer_compositor, UMACategory uma_category, - RenderingStatsInstrumentation* rendering_stats_instrumentation); + RenderingStatsInstrumentation* rendering_stats_instrumentation, + CompositorFrameReportingController* + compositor_frame_reporting_controller); + CompositorTimingHistory(const CompositorTimingHistory&) = delete; virtual ~CompositorTimingHistory(); + CompositorTimingHistory& operator=(const CompositorTimingHistory&) = delete; + void AsValueInto(base::trace_event::TracedValue* state) const; // The main thread responsiveness depends heavily on whether or not the @@ -58,9 +63,8 @@ class CC_EXPORT CompositorTimingHistory { void DidCreateAndInitializeLayerTreeFrameSink(); // Events to be timed. - void WillBeginImplFrame(bool new_active_tree_is_likely, - base::TimeTicks frame_time, - viz::BeginFrameArgs::BeginFrameArgsType frame_type, + void WillBeginImplFrame(const viz::BeginFrameArgs& args, + bool new_active_tree_is_likely, base::TimeTicks now); void WillFinishImplFrame(bool needs_redraw); void BeginImplFrameNotExpectedSoon(); @@ -85,6 +89,7 @@ class CC_EXPORT CompositorTimingHistory { bool current_frame_had_raf, bool next_frame_has_pending_raf); void DidSubmitCompositorFrame(); + void DidNotProduceFrame(); void DidReceiveCompositorFrameAck(); void WillInvalidateOnImplSide(); void SetTreePriority(TreePriority priority); @@ -158,17 +163,20 @@ class CC_EXPORT CompositorTimingHistory { bool submit_ack_watchdog_enabled_; std::unique_ptr<UMAReporter> uma_reporter_; + + // Owned by LayerTreeHost and is destroyed when LayerTreeHost is destroyed. RenderingStatsInstrumentation* rendering_stats_instrumentation_; + // Owned by LayerTreeHostImpl and is destroyed when LayerTreeHostImpl is + // destroyed. + CompositorFrameReportingController* compositor_frame_reporting_controller_; + // Used only for reporting animation targeted UMA. bool previous_frame_had_composited_animations_ = false; bool previous_frame_had_main_thread_animations_ = false; bool previous_frame_had_raf_ = false; TreePriority tree_priority_ = SAME_PRIORITY_FOR_BOTH_TREES; - - private: - DISALLOW_COPY_AND_ASSIGN(CompositorTimingHistory); }; } // namespace cc diff --git a/chromium/cc/scheduler/compositor_timing_history_unittest.cc b/chromium/cc/scheduler/compositor_timing_history_unittest.cc index a5e8387d8b2..187c65b1a48 100644 --- a/chromium/cc/scheduler/compositor_timing_history_unittest.cc +++ b/chromium/cc/scheduler/compositor_timing_history_unittest.cc @@ -4,9 +4,9 @@ #include "cc/scheduler/compositor_timing_history.h" -#include "base/macros.h" #include "base/test/metrics/histogram_tester.h" #include "cc/debug/rendering_stats_instrumentation.h" +#include "cc/test/fake_compositor_frame_reporting_controller.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -16,25 +16,35 @@ class CompositorTimingHistoryTest; class TestCompositorTimingHistory : public CompositorTimingHistory { public: - TestCompositorTimingHistory(CompositorTimingHistoryTest* test, - RenderingStatsInstrumentation* rendering_stats) - : CompositorTimingHistory(false, RENDERER_UMA, rendering_stats), + TestCompositorTimingHistory( + CompositorTimingHistoryTest* test, + RenderingStatsInstrumentation* rendering_stats, + CompositorFrameReportingController* reporting_controller) + : CompositorTimingHistory(false, + RENDERER_UMA, + rendering_stats, + reporting_controller), test_(test) {} + TestCompositorTimingHistory(const TestCompositorTimingHistory&) = delete; + TestCompositorTimingHistory& operator=(const TestCompositorTimingHistory&) = + delete; + protected: base::TimeTicks Now() const override; CompositorTimingHistoryTest* test_; - - private: - DISALLOW_COPY_AND_ASSIGN(TestCompositorTimingHistory); }; class CompositorTimingHistoryTest : public testing::Test { public: CompositorTimingHistoryTest() : rendering_stats_(RenderingStatsInstrumentation::Create()), - timing_history_(this, rendering_stats_.get()) { + reporting_controller_( + std::make_unique<FakeCompositorFrameReportingController>()), + timing_history_(this, + rendering_stats_.get(), + reporting_controller_.get()) { AdvanceNowBy(base::TimeDelta::FromMilliseconds(1)); timing_history_.SetRecordingEnabled(true); } @@ -78,6 +88,7 @@ class CompositorTimingHistoryTest : public testing::Test { protected: std::unique_ptr<RenderingStatsInstrumentation> rendering_stats_; + std::unique_ptr<CompositorFrameReportingController> reporting_controller_; TestCompositorTimingHistory timing_history_; base::TimeTicks now_; }; diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc index 7d388c31205..5fdf97c2ebf 100644 --- a/chromium/cc/scheduler/scheduler.cc +++ b/chromium/cc/scheduler/scheduler.cc @@ -578,6 +578,7 @@ void Scheduler::SendDidNotProduceFrame(const viz::BeginFrameArgs& args) { if (last_begin_frame_ack_.source_id == args.source_id && last_begin_frame_ack_.sequence_number == args.sequence_number) return; + compositor_timing_history_->DidNotProduceFrame(); last_begin_frame_ack_ = viz::BeginFrameAck(args, false /* has_damage */); client_->DidNotProduceFrame(last_begin_frame_ack_); } @@ -601,7 +602,7 @@ void Scheduler::BeginImplFrame(const viz::BeginFrameArgs& args, args.animate_only); devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); compositor_timing_history_->WillBeginImplFrame( - state_machine_.NewActiveTreeLikely(), args.frame_time, args.type, now); + args, state_machine_.NewActiveTreeLikely(), now); bool has_damage = client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); @@ -932,6 +933,17 @@ bool Scheduler::ShouldDropBeginFrame(const viz::BeginFrameArgs& args) const { return true; } + // We shouldn't be handling missed frames in the browser process (i.e. where + // commit_to_active_tree is set) since we don't know if we should create a + // frame at this time. Doing so leads to issues like crbug.com/882907. This + // early-out is a short term fix to keep fling animations smooth. + // TODO(bokan): In the long term, the display compositor should decide + // whether to issue a missed frame; it is tracked in + // https://crbug.com/930890. + if (args.type == viz::BeginFrameArgs::MISSED && + settings_.commit_to_active_tree) + return true; + return false; } diff --git a/chromium/cc/scheduler/scheduler.h b/chromium/cc/scheduler/scheduler.h index 292a0f53512..a84943e7ee8 100644 --- a/chromium/cc/scheduler/scheduler.h +++ b/chromium/cc/scheduler/scheduler.h @@ -9,7 +9,6 @@ #include <string> #include "base/cancelable_callback.h" -#include "base/macros.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/scheduler/begin_frame_tracker.h" @@ -78,8 +77,11 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase { int layer_tree_host_id, base::SingleThreadTaskRunner* task_runner, std::unique_ptr<CompositorTimingHistory> compositor_timing_history); + Scheduler(const Scheduler&) = delete; ~Scheduler() override; + Scheduler& operator=(const Scheduler&) = delete; + // This is needed so that the scheduler doesn't perform spurious actions while // the compositor is being torn down. void Stop(); @@ -322,8 +324,6 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase { bool IsInsideAction(SchedulerStateMachine::Action action) { return inside_action_ == action; } - - DISALLOW_COPY_AND_ASSIGN(Scheduler); }; } // namespace cc diff --git a/chromium/cc/scheduler/scheduler_settings.cc b/chromium/cc/scheduler/scheduler_settings.cc index 9e488fc8725..5fb52494ae3 100644 --- a/chromium/cc/scheduler/scheduler_settings.cc +++ b/chromium/cc/scheduler/scheduler_settings.cc @@ -36,6 +36,8 @@ SchedulerSettings::AsValue() const { wait_for_all_pipeline_stages_before_draw); state->SetBoolean("enable_surface_synchronization", enable_surface_synchronization); + state->SetBoolean("compositor_threaded_scrollbar_scrolling", + compositor_threaded_scrollbar_scrolling); return std::move(state); } diff --git a/chromium/cc/scheduler/scheduler_settings.h b/chromium/cc/scheduler/scheduler_settings.h index 1896a544989..318820844fa 100644 --- a/chromium/cc/scheduler/scheduler_settings.h +++ b/chromium/cc/scheduler/scheduler_settings.h @@ -34,6 +34,7 @@ class CC_EXPORT SchedulerSettings { bool enable_latency_recovery = true; bool wait_for_all_pipeline_stages_before_draw = false; bool enable_surface_synchronization = false; + bool compositor_threaded_scrollbar_scrolling = false; int maximum_number_of_failed_draws_before_draw_is_forced = 3; base::TimeDelta background_frame_interval = base::TimeDelta::FromSeconds(1); diff --git a/chromium/cc/scheduler/scheduler_state_machine.cc b/chromium/cc/scheduler/scheduler_state_machine.cc index 7b75bd8fce0..a4433d47f1d 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.cc +++ b/chromium/cc/scheduler/scheduler_state_machine.cc @@ -365,6 +365,11 @@ bool SchedulerStateMachine::ShouldDraw() const { if (forced_redraw_state_ == ForcedRedrawOnTimeoutState::WAITING_FOR_DRAW) return true; + // Delay draws when we have pending animation worklet updates to give them + // time to produce output before we draw. + if (processing_animation_worklets_for_active_tree_) + return false; + return needs_redraw_; } @@ -1430,8 +1435,18 @@ void SchedulerStateMachine::NotifyAnimationWorkletStateChange( AnimationWorkletState state, TreeType tree) { if (tree == TreeType::ACTIVE) { - processing_animation_worklets_for_active_tree_ = - (state == AnimationWorkletState::PROCESSING); + switch (state) { + case AnimationWorkletState::PROCESSING: + DCHECK_GE(processing_animation_worklets_for_active_tree_, 0); + DCHECK_LE(processing_animation_worklets_for_active_tree_, 1); + processing_animation_worklets_for_active_tree_++; + break; + + case AnimationWorkletState::IDLE: + DCHECK_LE(processing_animation_worklets_for_active_tree_, 2); + DCHECK_GE(processing_animation_worklets_for_active_tree_, 1); + processing_animation_worklets_for_active_tree_--; + } } else { processing_animation_worklets_for_pending_tree_ = (state == AnimationWorkletState::PROCESSING); diff --git a/chromium/cc/scheduler/scheduler_state_machine.h b/chromium/cc/scheduler/scheduler_state_machine.h index f683e527c83..091f1af3b7c 100644 --- a/chromium/cc/scheduler/scheduler_state_machine.h +++ b/chromium/cc/scheduler/scheduler_state_machine.h @@ -10,7 +10,6 @@ #include <memory> #include <string> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/draw_result.h" @@ -48,8 +47,11 @@ class CC_EXPORT SchedulerStateMachine { public: // settings must be valid for the lifetime of this class. explicit SchedulerStateMachine(const SchedulerSettings& settings); + SchedulerStateMachine(const SchedulerStateMachine&) = delete; ~SchedulerStateMachine(); + SchedulerStateMachine& operator=(const SchedulerStateMachine&) = delete; + enum class LayerTreeFrameSinkState { NONE, ACTIVE, @@ -442,7 +444,12 @@ class CC_EXPORT SchedulerStateMachine { bool next_invalidation_needs_first_draw_on_activation_ = false; bool should_defer_invalidation_for_fast_main_frame_ = true; bool begin_frame_is_animate_only_ = false; - bool processing_animation_worklets_for_active_tree_ = false; + + // Number of async mutation cycles for the active tree that are in-flight or + // queued. Can be 0, 1 or 2. + int processing_animation_worklets_for_active_tree_ = 0; + // Indicates if an aysnc mutation cycle is in-flight or queued for the pending + // tree. Only one can be running or queued at any time. bool processing_animation_worklets_for_pending_tree_ = false; // Set to true if the main thread fails to respond with a commit or abort the @@ -457,9 +464,6 @@ class CC_EXPORT SchedulerStateMachine { // If set to true, the pending tree must be drawn at least once after // activation before a new tree can be activated. bool pending_tree_needs_first_draw_on_activation_ = false; - - private: - DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine); }; } // namespace cc diff --git a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc index 886529de57c..489cd110217 100644 --- a/chromium/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/chromium/cc/scheduler/scheduler_state_machine_unittest.cc @@ -161,9 +161,10 @@ class StateMachine : public SchedulerStateMachine { return needs_impl_side_invalidation_; } + using SchedulerStateMachine::ProactiveBeginFrameWanted; + using SchedulerStateMachine::ShouldDraw; using SchedulerStateMachine::ShouldPrepareTiles; using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately; - using SchedulerStateMachine::ProactiveBeginFrameWanted; using SchedulerStateMachine::WillCommit; protected: @@ -2741,18 +2742,51 @@ TEST(SchedulerStateMachineTest, BlockDrawIfAnimationWorkletsPending) { state.NotifyReadyToActivate(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE); EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); + EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE, + state.CurrentBeginImplFrameDeadlineMode()); + // Started async mutation cycle for animation worklets. + state.NotifyAnimationWorkletStateChange( + SchedulerStateMachine::AnimationWorkletState::PROCESSING, + SchedulerStateMachine::TreeType::ACTIVE); + EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); + EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR, + state.CurrentBeginImplFrameDeadlineMode()); + // Second queued state change. state.NotifyAnimationWorkletStateChange( SchedulerStateMachine::AnimationWorkletState::PROCESSING, SchedulerStateMachine::TreeType::ACTIVE); EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR, state.CurrentBeginImplFrameDeadlineMode()); + // First mutation cycle completes. Still waiting on queued mutation cycle + // before being ready to draw. + state.NotifyAnimationWorkletStateChange( + SchedulerStateMachine::AnimationWorkletState::IDLE, + SchedulerStateMachine::TreeType::ACTIVE); + EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); + EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR, + state.CurrentBeginImplFrameDeadlineMode()); + // Queued mutation cycle completes. Now ready to draw. state.NotifyAnimationWorkletStateChange( SchedulerStateMachine::AnimationWorkletState::IDLE, SchedulerStateMachine::TreeType::ACTIVE); EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE, state.CurrentBeginImplFrameDeadlineMode()); + + state.SetNeedsRedraw(true); + state.OnBeginImplFrameDeadline(); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BeginImplFrameState::INSIDE_DEADLINE); + EXPECT_TRUE(state.ShouldDraw()); + state.NotifyAnimationWorkletStateChange( + SchedulerStateMachine::AnimationWorkletState::PROCESSING, + SchedulerStateMachine::TreeType::ACTIVE); + EXPECT_FALSE(state.ShouldDraw()); + state.NotifyAnimationWorkletStateChange( + SchedulerStateMachine::AnimationWorkletState::IDLE, + SchedulerStateMachine::TreeType::ACTIVE); + EXPECT_TRUE(state.ShouldDraw()); } TEST(SchedulerStateMachineTest, BlockActivationIfAnimationWorkletsPending) { diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc index 2f5deee74de..35c81fd8416 100644 --- a/chromium/cc/scheduler/scheduler_unittest.cc +++ b/chromium/cc/scheduler/scheduler_unittest.cc @@ -639,6 +639,26 @@ TEST_F(SchedulerTest, VideoNeedsBeginFrames) { EXPECT_FALSE(scheduler_->begin_frames_expected()); } +// As a short term fix for https://crbug.com/882907, we should skip MISSED +// frames from the browser compositor. +// TODO(bokan): In the long term, the display compositor should decide +// whether to issue a missed frame; it is tracked in +// https://crbug.com/930890. +TEST_F(SchedulerTest, BrowserCompositorSkipsMissedBeginFrames) { + scheduler_settings_.commit_to_active_tree = true; + SetUpScheduler(EXTERNAL_BFS); + scheduler_->SetNeedsBeginMainFrame(); + + task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval()); + viz::BeginFrameArgs args = + fake_external_begin_frame_source_->CreateBeginFrameArgs( + BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock()); + args.type = viz::BeginFrameArgs::MISSED; + + fake_external_begin_frame_source_->TestOnBeginFrame(args); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); +} + TEST_F(SchedulerTest, RequestCommit) { SetUpScheduler(EXTERNAL_BFS); diff --git a/chromium/cc/tiles/checker_image_tracker.h b/chromium/cc/tiles/checker_image_tracker.h index 1a8229feaf5..f59f5a27620 100644 --- a/chromium/cc/tiles/checker_image_tracker.h +++ b/chromium/cc/tiles/checker_image_tracker.h @@ -55,8 +55,11 @@ class CC_EXPORT CheckerImageTracker { CheckerImageTrackerClient* client, bool enable_checker_imaging, size_t min_image_bytes_to_checker); + CheckerImageTracker(const CheckerImageTracker&) = delete; ~CheckerImageTracker(); + CheckerImageTracker& operator=(const CheckerImageTracker&) = delete; + // Returns true if the decode for |image| will be deferred to the image decode // service and it should be be skipped during raster. bool ShouldCheckerImage(const DrawImage& image, WhichTree tree); @@ -146,13 +149,14 @@ class CC_EXPORT CheckerImageTracker { ScopedDecodeHolder(ImageController* controller, ImageController::ImageDecodeRequestId request_id) : controller_(controller), request_id_(request_id) {} + ScopedDecodeHolder(const ScopedDecodeHolder&) = delete; ~ScopedDecodeHolder() { controller_->UnlockImageDecode(request_id_); } + ScopedDecodeHolder& operator=(const ScopedDecodeHolder&) = delete; + private: ImageController* controller_; ImageController::ImageDecodeRequestId request_id_; - - DISALLOW_COPY_AND_ASSIGN(ScopedDecodeHolder); }; void DidFinishImageDecode(PaintImage::Id image_id, @@ -204,8 +208,6 @@ class CC_EXPORT CheckerImageTracker { base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map_; base::WeakPtrFactory<CheckerImageTracker> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(CheckerImageTracker); }; } // namespace cc diff --git a/chromium/cc/tiles/decoded_image_tracker.h b/chromium/cc/tiles/decoded_image_tracker.h index c88bd2b593a..a5f99abe5dd 100644 --- a/chromium/cc/tiles/decoded_image_tracker.h +++ b/chromium/cc/tiles/decoded_image_tracker.h @@ -29,8 +29,11 @@ class CC_EXPORT DecodedImageTracker { explicit DecodedImageTracker( ImageController* controller, scoped_refptr<base::SequencedTaskRunner> task_runner); + DecodedImageTracker(const DecodedImageTracker&) = delete; ~DecodedImageTracker(); + DecodedImageTracker& operator=(const DecodedImageTracker&) = delete; + // Request that the given image be decoded. This issues a callback upon // completion. The callback takes a bool indicating whether the decode was // successful or not. @@ -71,14 +74,16 @@ class CC_EXPORT DecodedImageTracker { ImageLock(DecodedImageTracker* tracker, ImageController::ImageDecodeRequestId request_id, base::TimeTicks lock_time); + ImageLock(const ImageLock&) = delete; ~ImageLock(); + + ImageLock& operator=(const ImageLock&) = delete; base::TimeTicks lock_time() const { return lock_time_; } private: DecodedImageTracker* tracker_; ImageController::ImageDecodeRequestId request_id_; base::TimeTicks lock_time_; - DISALLOW_COPY_AND_ASSIGN(ImageLock); }; base::flat_map<PaintImage::Id, std::unique_ptr<ImageLock>> locked_images_; bool timeout_pending_ = false; @@ -88,8 +93,6 @@ class CC_EXPORT DecodedImageTracker { const base::TickClock* tick_clock_; base::WeakPtrFactory<DecodedImageTracker> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(DecodedImageTracker); }; } // namespace cc diff --git a/chromium/cc/tiles/eviction_tile_priority_queue.h b/chromium/cc/tiles/eviction_tile_priority_queue.h index 2e76ee8c619..49ee3ef8aec 100644 --- a/chromium/cc/tiles/eviction_tile_priority_queue.h +++ b/chromium/cc/tiles/eviction_tile_priority_queue.h @@ -9,7 +9,6 @@ #include <utility> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/tile_priority.h" @@ -21,8 +20,12 @@ class PrioritizedTile; class CC_EXPORT EvictionTilePriorityQueue { public: EvictionTilePriorityQueue(); + EvictionTilePriorityQueue(const EvictionTilePriorityQueue&) = delete; ~EvictionTilePriorityQueue(); + EvictionTilePriorityQueue& operator=(const EvictionTilePriorityQueue&) = + delete; + void Build(const std::vector<PictureLayerImpl*>& active_layers, const std::vector<PictureLayerImpl*>& pending_layers, TreePriority tree_priority); @@ -39,8 +42,6 @@ class CC_EXPORT EvictionTilePriorityQueue { std::vector<std::unique_ptr<TilingSetEvictionQueue>> active_queues_; std::vector<std::unique_ptr<TilingSetEvictionQueue>> pending_queues_; TreePriority tree_priority_; - - DISALLOW_COPY_AND_ASSIGN(EvictionTilePriorityQueue); }; } // namespace cc diff --git a/chromium/cc/tiles/frame_viewer_instrumentation.h b/chromium/cc/tiles/frame_viewer_instrumentation.h index 2f389bedbcb..7c4ad9df52f 100644 --- a/chromium/cc/tiles/frame_viewer_instrumentation.h +++ b/chromium/cc/tiles/frame_viewer_instrumentation.h @@ -5,7 +5,6 @@ #ifndef CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_ #define CC_TILES_FRAME_VIEWER_INSTRUMENTATION_H_ -#include "base/macros.h" #include "base/trace_event/trace_event.h" #include "cc/tiles/tile_priority.h" @@ -25,10 +24,10 @@ class ScopedAnalyzeTask { TileResolution tile_resolution, int source_frame_number, int layer_id); + ScopedAnalyzeTask(const ScopedAnalyzeTask&) = delete; ~ScopedAnalyzeTask(); - private: - DISALLOW_COPY_AND_ASSIGN(ScopedAnalyzeTask); + ScopedAnalyzeTask& operator=(const ScopedAnalyzeTask&) = delete; }; class ScopedRasterTask { @@ -37,10 +36,10 @@ class ScopedRasterTask { TileResolution tile_resolution, int source_frame_number, int layer_id); + ScopedRasterTask(const ScopedRasterTask&) = delete; ~ScopedRasterTask(); - private: - DISALLOW_COPY_AND_ASSIGN(ScopedRasterTask); + ScopedRasterTask& operator=(const ScopedRasterTask&) = delete; }; bool IsTracingLayerTreeSnapshots(); diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc index 89fc51908b9..eaff9df998b 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache.cc @@ -9,7 +9,7 @@ #include "base/auto_reset.h" #include "base/bind.h" #include "base/debug/alias.h" -#include "base/hash.h" +#include "base/hash/hash.h" #include "base/memory/discardable_memory_allocator.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_math.h" @@ -477,6 +477,9 @@ class GpuImageDecodeTaskImpl : public TileTask { task_type_(task_type) { DCHECK(!SkipImage(draw_image)); } + GpuImageDecodeTaskImpl(const GpuImageDecodeTaskImpl&) = delete; + + GpuImageDecodeTaskImpl& operator=(const GpuImageDecodeTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override { @@ -503,8 +506,6 @@ class GpuImageDecodeTaskImpl : public TileTask { DrawImage image_; const ImageDecodeCache::TracingInfo tracing_info_; const GpuImageDecodeCache::DecodeTaskType task_type_; - - DISALLOW_COPY_AND_ASSIGN(GpuImageDecodeTaskImpl); }; // Task which creates an image from decoded data. Typically this involves @@ -526,6 +527,9 @@ class ImageUploadTaskImpl : public TileTask { if (decode_dependency) dependencies_.push_back(std::move(decode_dependency)); } + ImageUploadTaskImpl(const ImageUploadTaskImpl&) = delete; + + ImageUploadTaskImpl& operator=(const ImageUploadTaskImpl&) = delete; // Override from Task: void RunOnWorkerThread() override { @@ -546,8 +550,6 @@ class ImageUploadTaskImpl : public TileTask { GpuImageDecodeCache* cache_; DrawImage image_; const ImageDecodeCache::TracingInfo tracing_info_; - - DISALLOW_COPY_AND_ASSIGN(ImageUploadTaskImpl); }; GpuImageDecodeCache::ImageDataBase::ImageDataBase() = default; @@ -1511,6 +1513,15 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, RemoveFromPersistentCache(found_persistent); } + // Don't keep discardable cpu memory for GPU backed images. The cache hit rate + // of the cpu fallback (in case we don't find this image in gpu memory) is + // too low to cache this data. + if (image_data->decode.ref_count == 0 && + image_data->mode != DecodedDataMode::kCpu && + image_data->HasUploadedData()) { + image_data->decode.ResetData(); + } + // If we have no refs on an uploaded image, it should be unlocked. Do this // before any attempts to delete the image. if (image_data->IsGpuOrTransferCache() && image_data->upload.ref_count == 0 && diff --git a/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc b/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc index 5d0f2e62871..f7d485e215e 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache_perftest.cc @@ -151,7 +151,7 @@ TEST_P(GpuImageDecodeCachePerfTestNoSw, DecodeWithMips) { surface->getCanvas()->drawImageRect(decoded_image.image().get(), SkRect::MakeWH(1024, 2048), SkRect::MakeWH(614, 1229), &paint); - surface->prepareForExternalIO(); + surface->flush(); } cache_->DrawWithImageFinished(image, decoded_image); diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc index e8418bfe53e..087f8b26620 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc @@ -2429,12 +2429,6 @@ TEST_P(GpuImageDecodeCacheTest, NonLazyImageUploadDownscaled) { EXPECT_TRUE(decoded_draw_image.image()); EXPECT_TRUE(decoded_draw_image.is_budgeted()); cache->DrawWithImageFinished(draw_image, decoded_draw_image); - // For non-lazy images which are downscaled, the scaled image should be - // cached. - auto sw_image = cache->GetSWImageDecodeForTesting(draw_image); - EXPECT_TRUE(sw_image); - EXPECT_EQ(sw_image->width(), (GetNormalImageSize().width() + 1) / 2); - EXPECT_EQ(sw_image->height(), (GetNormalImageSize().height() + 1) / 2); } TEST_P(GpuImageDecodeCacheTest, KeepOnlyLast2ContentIds) { diff --git a/chromium/cc/tiles/image_controller.cc b/chromium/cc/tiles/image_controller.cc index 844f8c42d65..919be166e5f 100644 --- a/chromium/cc/tiles/image_controller.cc +++ b/chromium/cc/tiles/image_controller.cc @@ -163,8 +163,8 @@ void ImageController::ConvertPaintWorkletImagesToTask( } scoped_refptr<TileTask> result = paint_worklet_image_cache_.GetTaskForPaintWorkletImage(*it); - DCHECK(result); - tasks->push_back(std::move(result)); + if (result) + tasks->push_back(std::move(result)); // Remove it so that there is no need to check whether an image is // PaintWorklet generated or not in TileManager's // work_to_schedule->extra_prepaint_images.insert. diff --git a/chromium/cc/tiles/image_controller.h b/chromium/cc/tiles/image_controller.h index d5540106f94..2533b6e50f2 100644 --- a/chromium/cc/tiles/image_controller.h +++ b/chromium/cc/tiles/image_controller.h @@ -10,7 +10,6 @@ #include "base/callback.h" #include "base/containers/flat_map.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" @@ -34,8 +33,11 @@ class CC_EXPORT ImageController { explicit ImageController( base::SequencedTaskRunner* origin_task_runner, scoped_refptr<base::SequencedTaskRunner> worker_task_runner); + ImageController(const ImageController&) = delete; virtual ~ImageController(); + ImageController& operator=(const ImageController&) = delete; + void SetImageDecodeCache(ImageDecodeCache* cache); void SetPaintWorkletLayerPainter( std::unique_ptr<PaintWorkletLayerPainter> painter); @@ -150,8 +152,6 @@ class CC_EXPORT ImageController { std::vector<ImageDecodeRequest> orphaned_decode_requests_; base::WeakPtrFactory<ImageController> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ImageController); }; } // namespace cc diff --git a/chromium/cc/tiles/image_controller_unittest.cc b/chromium/cc/tiles/image_controller_unittest.cc index ba11ee841aa..05c82a46340 100644 --- a/chromium/cc/tiles/image_controller_unittest.cc +++ b/chromium/cc/tiles/image_controller_unittest.cc @@ -161,6 +161,9 @@ class SimpleTask : public TileTask { SimpleTask() : TileTask(true /* supports_concurrent_execution */) { EXPECT_TRUE(thread_checker_.CalledOnValidThread()); } + SimpleTask(const SimpleTask&) = delete; + + SimpleTask& operator=(const SimpleTask&) = delete; void RunOnWorkerThread() override { EXPECT_FALSE(HasCompleted()); @@ -177,8 +180,6 @@ class SimpleTask : public TileTask { base::ThreadChecker thread_checker_; bool has_run_ = false; - - DISALLOW_COPY_AND_ASSIGN(SimpleTask); }; // A task that blocks until instructed otherwise. @@ -188,6 +189,9 @@ class BlockingTask : public TileTask { : TileTask(true /* supports_concurrent_execution */), run_cv_(&lock_) { EXPECT_TRUE(thread_checker_.CalledOnValidThread()); } + BlockingTask(const BlockingTask&) = delete; + + BlockingTask& operator=(const BlockingTask&) = delete; void RunOnWorkerThread() override { EXPECT_FALSE(HasCompleted()); @@ -219,8 +223,6 @@ class BlockingTask : public TileTask { base::Lock lock_; base::ConditionVariable run_cv_; bool can_run_ = false; - - DISALLOW_COPY_AND_ASSIGN(BlockingTask); }; // For tests that exercise image controller's thread, this is the timeout value diff --git a/chromium/cc/tiles/paint_worklet_image_cache.cc b/chromium/cc/tiles/paint_worklet_image_cache.cc index 1b9052f9ffa..639bf7d19b1 100644 --- a/chromium/cc/tiles/paint_worklet_image_cache.cc +++ b/chromium/cc/tiles/paint_worklet_image_cache.cc @@ -5,6 +5,7 @@ #include "cc/tiles/paint_worklet_image_cache.h" #include "base/bind.h" +#include "base/bind_helpers.h" #include "cc/paint/paint_worklet_layer_painter.h" namespace cc { @@ -14,6 +15,9 @@ class PaintWorkletTaskImpl : public TileTask { PaintWorkletTaskImpl(PaintWorkletImageCache* cache, const PaintImage& paint_image) : TileTask(true), cache_(cache), paint_image_(paint_image) {} + PaintWorkletTaskImpl(const PaintWorkletTaskImpl&) = delete; + + PaintWorkletTaskImpl& operator=(const PaintWorkletTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override { cache_->PaintImageInTask(paint_image_); } @@ -27,8 +31,6 @@ class PaintWorkletTaskImpl : public TileTask { private: PaintWorkletImageCache* cache_; PaintImage paint_image_; - - DISALLOW_COPY_AND_ASSIGN(PaintWorkletTaskImpl); }; PaintWorkletImageCache::PaintWorkletImageCache() {} @@ -40,27 +42,57 @@ PaintWorkletImageCache::~PaintWorkletImageCache() { void PaintWorkletImageCache::SetPaintWorkletLayerPainter( std::unique_ptr<PaintWorkletLayerPainter> painter) { + DCHECK(!painter_); painter_ = std::move(painter); } scoped_refptr<TileTask> PaintWorkletImageCache::GetTaskForPaintWorkletImage( const DrawImage& image) { + // As described in crbug.com/939192, the |painter_| could be null, and we + // should not create any raster task. + if (!painter_) + return nullptr; + DCHECK(image.paint_image().IsPaintWorklet()); return base::MakeRefCounted<PaintWorkletTaskImpl>(this, image.paint_image()); } -// TODO(xidachen): dispatch the work to a worklet thread, invoke JS callback. -// Do check the cache first. If there is already a cache entry for this input, -// then there is no need to call the Paint() function. +// TODO(xidachen): we might need to consider the animated property value and the +// PaintWorkletInput to decide whether we need to call Paint() function or not. void PaintWorkletImageCache::PaintImageInTask(const PaintImage& paint_image) { + // TODO(crbug.com/939009): When creating a TileTask for a given PaintImage at + // GetTaskForPaintWorkletImage, we should not create a new TileTask if there + // is already a TileTask for this PaintImage. + { + base::AutoLock hold(records_lock_); + if (records_.find(paint_image.paint_worklet_input()) != records_.end()) + return; + } + // Because the compositor could be waiting on the lock in NotifyPrepareTiles, + // we unlock here such that the compositor won't be blocked on potentially + // slow Paint function. // TODO(xidachen): ensure that the canvas operations in the PaintRecord // matches the PaintGeneratedImage::Draw. - sk_sp<PaintRecord> record = painter_->Paint(); - records_[paint_image.paint_worklet_input()] = - PaintWorkletImageCacheValue(std::move(record), 0); + sk_sp<PaintRecord> record = + painter_->Paint(paint_image.paint_worklet_input()); + { + base::AutoLock hold(records_lock_); + // It is possible for two or more threads to both pass through the first + // lock and arrive here. To avoid ref-count issues caused by potential + // racing among threads, we use insert such that if an entry already exists + // for a particular key, the value won't be overridden. + records_.insert( + std::make_pair(paint_image.paint_worklet_input(), + PaintWorkletImageCacheValue(std::move(record), 0))); + } } -std::pair<PaintRecord*, base::OnceCallback<void()>> +std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> PaintWorkletImageCache::GetPaintRecordAndRef(PaintWorkletInput* input) { + base::AutoLock hold(records_lock_); + // If the |painter_| was null when GetTaskForPaintWorkletImage was called + // there will be no cache entry for this input. + if (records_.find(input) == records_.end()) + return std::make_pair(sk_make_sp<PaintOpBuffer>(), base::DoNothing::Once()); records_[input].used_ref_count++; records_[input].num_of_frames_not_accessed = 0u; // The PaintWorkletImageCache object lives as long as the LayerTreeHostImpl, @@ -69,7 +101,7 @@ PaintWorkletImageCache::GetPaintRecordAndRef(PaintWorkletInput* input) { auto callback = base::BindOnce(&PaintWorkletImageCache::DecrementCacheRefCount, base::Unretained(this), base::Unretained(input)); - return std::make_pair(records_[input].record.get(), std::move(callback)); + return std::make_pair(records_[input].record, std::move(callback)); } void PaintWorkletImageCache::SetNumOfFramesToPurgeCacheEntryForTest( @@ -78,6 +110,7 @@ void PaintWorkletImageCache::SetNumOfFramesToPurgeCacheEntryForTest( } void PaintWorkletImageCache::DecrementCacheRefCount(PaintWorkletInput* input) { + base::AutoLock hold(records_lock_); auto it = records_.find(input); DCHECK(it != records_.end()); @@ -87,12 +120,14 @@ void PaintWorkletImageCache::DecrementCacheRefCount(PaintWorkletInput* input) { } void PaintWorkletImageCache::NotifyDidPrepareTiles() { + base::AutoLock hold(records_lock_); base::EraseIf( records_, [this]( const std::pair<PaintWorkletInput*, PaintWorkletImageCacheValue>& t) { return t.second.num_of_frames_not_accessed >= - num_of_frames_to_purge_cache_entry_; + num_of_frames_to_purge_cache_entry_ && + t.second.used_ref_count == 0; }); for (auto& pair : records_) pair.second.num_of_frames_not_accessed++; diff --git a/chromium/cc/tiles/paint_worklet_image_cache.h b/chromium/cc/tiles/paint_worklet_image_cache.h index 749233a468c..f9b976f357b 100644 --- a/chromium/cc/tiles/paint_worklet_image_cache.h +++ b/chromium/cc/tiles/paint_worklet_image_cache.h @@ -8,6 +8,7 @@ #include <utility> #include "base/containers/flat_map.h" +#include "base/synchronization/lock.h" #include "cc/cc_export.h" #include "cc/paint/draw_image.h" #include "cc/paint/paint_record.h" @@ -50,8 +51,8 @@ class CC_EXPORT PaintWorkletImageCache { void NotifyDidPrepareTiles(); // Returns a callback to decrement the ref count for the corresponding entry. - std::pair<PaintRecord*, base::OnceCallback<void()>> GetPaintRecordAndRef( - PaintWorkletInput* input); + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> + GetPaintRecordAndRef(PaintWorkletInput* input); const base::flat_map<PaintWorkletInput*, PaintWorkletImageCacheValue>& GetRecordsForTest() { @@ -62,12 +63,17 @@ class CC_EXPORT PaintWorkletImageCache { private: void DecrementCacheRefCount(PaintWorkletInput* input); + // This is a map of paint worklet inputs to a pair of paint record and a // reference count. The paint record is the representation of the worklet // output based on the input, and the reference count is the number of times // that it is used for tile rasterization. - // TODO(xidachen): use a struct instead of std::pair. base::flat_map<PaintWorkletInput*, PaintWorkletImageCacheValue> records_; + + // The |records_| can be accessed from compositor and raster worker threads at + // the same time. To prevent race, we need to lock on it. + base::Lock records_lock_; + // The PaintWorkletImageCache is owned by ImageController, which has the same // life time as the LayerTreeHostImpl, that guarantees that the painter will // live as long as the LayerTreeHostImpl. diff --git a/chromium/cc/tiles/paint_worklet_image_cache_unittest.cc b/chromium/cc/tiles/paint_worklet_image_cache_unittest.cc index e046b03cd2b..6ae3c0a0036 100644 --- a/chromium/cc/tiles/paint_worklet_image_cache_unittest.cc +++ b/chromium/cc/tiles/paint_worklet_image_cache_unittest.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 <memory> #include <utility> #include "cc/tiles/paint_worklet_image_cache.h" @@ -47,9 +48,6 @@ scoped_refptr<TileTask> GetTaskForPaintWorkletImage( paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), kNone_SkFilterQuality, CreateMatrix(SkSize::Make(1.f, 1.f), true), PaintImage::kDefaultFrameIndex); - std::unique_ptr<TestPaintWorkletLayerPainter> painter = - std::make_unique<TestPaintWorkletLayerPainter>(); - cache->SetPaintWorkletLayerPainter(std::move(painter)); return cache->GetTaskForPaintWorkletImage(draw_image); } @@ -64,6 +62,9 @@ void TestPaintRecord(const PaintRecord* record) { TEST(PaintWorkletImageCacheTest, GetTaskForImage) { TestPaintWorkletImageCache cache; + std::unique_ptr<TestPaintWorkletLayerPainter> painter = + std::make_unique<TestPaintWorkletLayerPainter>(); + cache.SetPaintWorkletLayerPainter(std::move(painter)); PaintImage paint_image = CreatePaintImage(100, 100); scoped_refptr<TileTask> task = GetTaskForPaintWorkletImage(paint_image, &cache); @@ -116,8 +117,39 @@ TEST(PaintWorkletImageCacheTest, GetTaskForImage) { EXPECT_EQ(records[paint_image.paint_worklet_input()].used_ref_count, 0u); } +TEST(PaintWorkletImageCacheTest, EntryWithNonZeroRefCountNotPurged) { + TestPaintWorkletImageCache cache; + std::unique_ptr<TestPaintWorkletLayerPainter> painter = + std::make_unique<TestPaintWorkletLayerPainter>(); + cache.SetPaintWorkletLayerPainter(std::move(painter)); + PaintImage paint_image = CreatePaintImage(100, 100); + scoped_refptr<TileTask> task = + GetTaskForPaintWorkletImage(paint_image, &cache); + EXPECT_TRUE(task); + + TestTileTaskRunner::ProcessTask(task.get()); + + PaintWorkletImageProvider provider(&cache); + ImageProvider::ScopedResult result = + provider.GetPaintRecordResult(paint_image.paint_worklet_input()); + base::flat_map<PaintWorkletInput*, + PaintWorkletImageCache::PaintWorkletImageCacheValue> + records = cache.GetRecordsForTest(); + EXPECT_EQ(records[paint_image.paint_worklet_input()].used_ref_count, 1u); + + cache.NotifyDidPrepareTiles(); + cache.NotifyDidPrepareTiles(); + cache.NotifyDidPrepareTiles(); + + records = cache.GetRecordsForTest(); + EXPECT_EQ(records.size(), 1u); +} + TEST(PaintWorkletImageCacheTest, MultipleRecordsInCache) { TestPaintWorkletImageCache cache; + std::unique_ptr<TestPaintWorkletLayerPainter> painter = + std::make_unique<TestPaintWorkletLayerPainter>(); + cache.SetPaintWorkletLayerPainter(std::move(painter)); PaintImage paint_image1 = CreatePaintImage(100, 100); scoped_refptr<TileTask> task1 = GetTaskForPaintWorkletImage(paint_image1, &cache); @@ -166,7 +198,7 @@ TEST(PaintWorkletImageCacheTest, MultipleRecordsInCache) { records[paint_image2.paint_worklet_input()].num_of_frames_not_accessed, 1u); - std::pair<PaintRecord*, base::OnceCallback<void()>> pair = + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> pair = cache.GetPaintRecordAndRef(paint_image1.paint_worklet_input()); // Run the callback to decrement the ref count. std::move(pair.second).Run(); @@ -186,5 +218,68 @@ TEST(PaintWorkletImageCacheTest, MultipleRecordsInCache) { 2u); } +// This test ensures that if an entry already exist, then the PaintImageInTask +// will not replace it with a new entry and reset its ref count. +TEST(PaintWorkletImageCacheTest, CacheEntryLookup) { + TestPaintWorkletImageCache cache; + std::unique_ptr<TestPaintWorkletLayerPainter> painter = + std::make_unique<TestPaintWorkletLayerPainter>(); + cache.SetPaintWorkletLayerPainter(std::move(painter)); + PaintImage paint_image = CreatePaintImage(100, 100); + scoped_refptr<TileTask> task = + GetTaskForPaintWorkletImage(paint_image, &cache); + EXPECT_TRUE(task); + PaintWorkletImageProvider provider(&cache); + + TestTileTaskRunner::ProcessTask(task.get()); + + { + ImageProvider::ScopedResult result = + provider.GetPaintRecordResult(paint_image.paint_worklet_input()); + EXPECT_TRUE(result.paint_record()); + TestPaintRecord(result.paint_record()); + + base::flat_map<PaintWorkletInput*, + PaintWorkletImageCache::PaintWorkletImageCacheValue> + records = cache.GetRecordsForTest(); + // Test the ref count. + EXPECT_EQ(records[paint_image.paint_worklet_input()].used_ref_count, 1u); + + // Create a new task with the same PaintWorkletInput as the previous task. + // Then ProcessTask will invoke PaintWorkletImageCache::PaintImageInTask, + // and it should early exit, without replacing the existing PaintRecord and + // resetting the ref count. + scoped_refptr<TileTask> task_with_the_same_input = + GetTaskForPaintWorkletImage(paint_image, &cache); + EXPECT_TRUE(task); + TestTileTaskRunner::ProcessTask(task_with_the_same_input.get()); + EXPECT_EQ(records[paint_image.paint_worklet_input()].used_ref_count, 1u); + } +} + +TEST(PaintWorkletImageCacheTest, TaskIsNullWhenPainterIsNull) { + TestPaintWorkletImageCache cache; + PaintImage paint_image = CreatePaintImage(100, 100); + scoped_refptr<TileTask> task = + GetTaskForPaintWorkletImage(paint_image, &cache); + EXPECT_EQ(task, nullptr); +} + +TEST(PaintWorkletImageCacheTest, + RecordAndCallbackAreEmptyWhenInputWasntPainted) { + TestPaintWorkletImageCache cache; + std::unique_ptr<TestPaintWorkletLayerPainter> painter = + std::make_unique<TestPaintWorkletLayerPainter>(); + cache.SetPaintWorkletLayerPainter(std::move(painter)); + + // We request a record and callback without ever painting the input. + PaintImage paint_image = CreatePaintImage(100, 100); + std::pair<sk_sp<PaintRecord>, base::OnceCallback<void()>> result = + cache.GetPaintRecordAndRef(paint_image.paint_worklet_input()); + EXPECT_EQ(result.first->total_op_count(), 0u); + // This is an empty callback, running it should not crash. + std::move(result.second).Run(); +} + } // namespace } // namespace cc diff --git a/chromium/cc/tiles/picture_layer_tiling.h b/chromium/cc/tiles/picture_layer_tiling.h index d9c33a0418a..4f66d992b35 100644 --- a/chromium/cc/tiles/picture_layer_tiling.h +++ b/chromium/cc/tiles/picture_layer_tiling.h @@ -14,7 +14,6 @@ #include <utility> #include <vector> -#include "base/macros.h" #include "cc/base/region.h" #include "cc/base/tiling_data.h" #include "cc/cc_export.h" @@ -95,8 +94,11 @@ class CC_EXPORT PictureLayerTiling { PictureLayerTilingClient* client, float min_preraster_distance, float max_preraster_distance); + PictureLayerTiling(const PictureLayerTiling&) = delete; ~PictureLayerTiling(); + PictureLayerTiling& operator=(const PictureLayerTiling&) = delete; + PictureLayerTilingClient* client() const { return client_; } void SetRasterSourceAndResize(scoped_refptr<RasterSource> raster_source); @@ -392,9 +394,6 @@ class CC_EXPORT PictureLayerTiling { bool has_soon_border_rect_tiles_ = false; bool has_eventually_rect_tiles_ = false; bool all_tiles_done_ = true; - - private: - DISALLOW_COPY_AND_ASSIGN(PictureLayerTiling); }; } // namespace cc diff --git a/chromium/cc/tiles/picture_layer_tiling_set.h b/chromium/cc/tiles/picture_layer_tiling_set.h index 78e426e4bab..b5b9c45323d 100644 --- a/chromium/cc/tiles/picture_layer_tiling_set.h +++ b/chromium/cc/tiles/picture_layer_tiling_set.h @@ -11,7 +11,6 @@ #include <set> #include <vector> -#include "base/macros.h" #include "cc/base/region.h" #include "cc/tiles/picture_layer_tiling.h" #include "ui/gfx/geometry/size.h" @@ -48,8 +47,11 @@ class CC_EXPORT PictureLayerTilingSet { int skewport_extrapolation_limit_in_screen_pixels, float max_preraster_distance); + PictureLayerTilingSet(const PictureLayerTilingSet&) = delete; ~PictureLayerTilingSet(); + PictureLayerTilingSet& operator=(const PictureLayerTilingSet&) = delete; + const PictureLayerTilingClient* client() const { return client_; } void CleanUpTilings(float min_acceptable_high_res_scale_key, @@ -262,9 +264,6 @@ class CC_EXPORT PictureLayerTilingSet { gfx::Rect eventually_rect_in_layer_space_; friend class Iterator; - - private: - DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingSet); }; } // namespace cc diff --git a/chromium/cc/tiles/picture_layer_tiling_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_unittest.cc index 4a98325ef56..424dc99f8b7 100644 --- a/chromium/cc/tiles/picture_layer_tiling_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_unittest.cc @@ -10,7 +10,6 @@ #include <set> #include "base/bind.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "cc/base/math_util.h" #include "cc/test/fake_output_surface_client.h" @@ -90,8 +89,13 @@ class PictureLayerTilingIteratorTest : public testing::Test { base::RepeatingCallback<void(Tile* tile, const gfx::Rect& geometry_rect)>; PictureLayerTilingIteratorTest() = default; + PictureLayerTilingIteratorTest(const PictureLayerTilingIteratorTest&) = + delete; ~PictureLayerTilingIteratorTest() override = default; + PictureLayerTilingIteratorTest& operator=( + const PictureLayerTilingIteratorTest&) = delete; + void Initialize(const gfx::Size& tile_size, float contents_scale, const gfx::Size& layer_bounds) { @@ -218,9 +222,6 @@ class PictureLayerTilingIteratorTest : public testing::Test { FakePictureLayerTilingClient client_; std::unique_ptr<TestablePictureLayerTiling> tiling_; bool loose_texel_extent_check_ = false; - - private: - DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingIteratorTest); }; TEST_F(PictureLayerTilingIteratorTest, ResizeDeletesTiles) { diff --git a/chromium/cc/tiles/raster_tile_priority_queue.h b/chromium/cc/tiles/raster_tile_priority_queue.h index 98860762d58..7bfc22965b6 100644 --- a/chromium/cc/tiles/raster_tile_priority_queue.h +++ b/chromium/cc/tiles/raster_tile_priority_queue.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/tile_priority.h" @@ -26,6 +25,9 @@ class CC_EXPORT RasterTilePriorityQueue { Type type); virtual ~RasterTilePriorityQueue() {} + RasterTilePriorityQueue(const RasterTilePriorityQueue&) = delete; + + RasterTilePriorityQueue& operator=(const RasterTilePriorityQueue&) = delete; virtual bool IsEmpty() const = 0; virtual const PrioritizedTile& Top() const = 0; @@ -33,9 +35,6 @@ class CC_EXPORT RasterTilePriorityQueue { protected: RasterTilePriorityQueue() {} - - private: - DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueue); }; } // namespace cc diff --git a/chromium/cc/tiles/raster_tile_priority_queue_all.h b/chromium/cc/tiles/raster_tile_priority_queue_all.h index 698dfe0319b..5aa6caf6973 100644 --- a/chromium/cc/tiles/raster_tile_priority_queue_all.h +++ b/chromium/cc/tiles/raster_tile_priority_queue_all.h @@ -9,7 +9,6 @@ #include <utility> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/raster_tile_priority_queue.h" @@ -21,8 +20,12 @@ namespace cc { class CC_EXPORT RasterTilePriorityQueueAll : public RasterTilePriorityQueue { public: RasterTilePriorityQueueAll(); + RasterTilePriorityQueueAll(const RasterTilePriorityQueueAll&) = delete; ~RasterTilePriorityQueueAll() override; + RasterTilePriorityQueueAll& operator=(const RasterTilePriorityQueueAll&) = + delete; + bool IsEmpty() const override; const PrioritizedTile& Top() const override; void Pop() override; @@ -41,8 +44,6 @@ class CC_EXPORT RasterTilePriorityQueueAll : public RasterTilePriorityQueue { std::vector<std::unique_ptr<TilingSetRasterQueueAll>> active_queues_; std::vector<std::unique_ptr<TilingSetRasterQueueAll>> pending_queues_; TreePriority tree_priority_; - - DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueueAll); }; } // namespace cc diff --git a/chromium/cc/tiles/raster_tile_priority_queue_required.h b/chromium/cc/tiles/raster_tile_priority_queue_required.h index a45a4baf878..c405e253658 100644 --- a/chromium/cc/tiles/raster_tile_priority_queue_required.h +++ b/chromium/cc/tiles/raster_tile_priority_queue_required.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "cc/layers/picture_layer_impl.h" #include "cc/tiles/raster_tile_priority_queue.h" #include "cc/tiles/tiling_set_raster_queue_required.h" @@ -18,8 +17,13 @@ class PrioritizedTile; class RasterTilePriorityQueueRequired : public RasterTilePriorityQueue { public: RasterTilePriorityQueueRequired(); + RasterTilePriorityQueueRequired(const RasterTilePriorityQueueRequired&) = + delete; ~RasterTilePriorityQueueRequired() override; + RasterTilePriorityQueueRequired& operator=( + const RasterTilePriorityQueueRequired&) = delete; + bool IsEmpty() const override; const PrioritizedTile& Top() const override; void Pop() override; @@ -37,8 +41,6 @@ class RasterTilePriorityQueueRequired : public RasterTilePriorityQueue { const std::vector<PictureLayerImpl*>& pending_layers); std::vector<std::unique_ptr<TilingSetRasterQueueRequired>> tiling_set_queues_; - - DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueueRequired); }; } // namespace cc diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc index 126cb37b5ae..c2bb32f6e81 100644 --- a/chromium/cc/tiles/software_image_decode_cache.cc +++ b/chromium/cc/tiles/software_image_decode_cache.cc @@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/format_macros.h" -#include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" @@ -64,6 +63,10 @@ class SoftwareImageDecodeTaskImpl : public TileTask { paint_image_(paint_image), task_type_(task_type), tracing_info_(tracing_info) {} + SoftwareImageDecodeTaskImpl(const SoftwareImageDecodeTaskImpl&) = delete; + + SoftwareImageDecodeTaskImpl& operator=(const SoftwareImageDecodeTaskImpl&) = + delete; // Overridden from Task: void RunOnWorkerThread() override { @@ -91,8 +94,6 @@ class SoftwareImageDecodeTaskImpl : public TileTask { PaintImage paint_image_; SoftwareImageDecodeCache::DecodeTaskType task_type_; const ImageDecodeCache::TracingInfo tracing_info_; - - DISALLOW_COPY_AND_ASSIGN(SoftwareImageDecodeTaskImpl); }; SkSize GetScaleAdjustment(const SoftwareImageDecodeCache::CacheKey& key) { diff --git a/chromium/cc/tiles/software_image_decode_cache_utils.cc b/chromium/cc/tiles/software_image_decode_cache_utils.cc index 16f5d11b30e..fac25c22ae6 100644 --- a/chromium/cc/tiles/software_image_decode_cache_utils.cc +++ b/chromium/cc/tiles/software_image_decode_cache_utils.cc @@ -5,7 +5,7 @@ #include "cc/tiles/software_image_decode_cache_utils.h" #include "base/atomic_sequence_num.h" -#include "base/hash.h" +#include "base/hash/hash.h" #include "base/memory/discardable_memory_allocator.h" #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" diff --git a/chromium/cc/tiles/tile.h b/chromium/cc/tiles/tile.h index d413c3c0bc6..84f68cb8c14 100644 --- a/chromium/cc/tiles/tile.h +++ b/chromium/cc/tiles/tile.h @@ -8,7 +8,6 @@ #include <stddef.h> #include <stdint.h> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/paint/draw_image.h" #include "cc/raster/tile_task.h" @@ -51,8 +50,11 @@ class CC_EXPORT Tile { typedef uint64_t Id; + Tile(const Tile&) = delete; ~Tile(); + Tile& operator=(const Tile&) = delete; + Id id() const { return id_; } @@ -180,8 +182,6 @@ class CC_EXPORT Tile { // rasterize a resource with checker images. bool raster_task_scheduled_with_checker_images_ = false; scoped_refptr<TileTask> raster_task_; - - DISALLOW_COPY_AND_ASSIGN(Tile); }; } // namespace cc diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc index 43d282e6d62..e797e6db4a4 100644 --- a/chromium/cc/tiles/tile_manager.cc +++ b/chromium/cc/tiles/tile_manager.cc @@ -14,7 +14,6 @@ #include "base/bind.h" #include "base/json/json_writer.h" #include "base/logging.h" -#include "base/macros.h" #include "base/metrics/histogram.h" #include "base/numerics/safe_conversions.h" #include "base/optional.h" @@ -83,8 +82,11 @@ class DispatchingImageProvider : public ImageProvider { : playback_image_provider_(std::move(playback_image_provider)), paint_worklet_image_provider_(std::move(paint_worklet_image_provider)) { } + DispatchingImageProvider(const DispatchingImageProvider&) = delete; ~DispatchingImageProvider() override = default; + DispatchingImageProvider& operator=(const DispatchingImageProvider&) = delete; + DispatchingImageProvider(DispatchingImageProvider&& other) = default; ImageProvider::ScopedResult GetRasterContent( @@ -98,8 +100,6 @@ class DispatchingImageProvider : public ImageProvider { private: PlaybackImageProvider playback_image_provider_; PaintWorkletImageProvider paint_worklet_image_provider_; - - DISALLOW_COPY_AND_ASSIGN(DispatchingImageProvider); }; class RasterTaskImpl : public TileTask { @@ -139,6 +139,8 @@ class RasterTaskImpl : public TileTask { DCHECK(origin_thread_checker_.CalledOnValidThread()); playback_settings_.image_provider = &image_provider_; } + RasterTaskImpl(const RasterTaskImpl&) = delete; + RasterTaskImpl& operator=(const RasterTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override { @@ -205,8 +207,6 @@ class RasterTaskImpl : public TileTask { std::unique_ptr<RasterBuffer> raster_buffer_; DispatchingImageProvider image_provider_; GURL url_; - - DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl); }; TaskCategory TaskCategoryForTileTask(TileTask* task, @@ -334,6 +334,8 @@ class TaskSetFinishedTaskImpl : public TileTask { task_runner_(task_runner), on_task_set_finished_callback_( std::move(on_task_set_finished_callback)) {} + TaskSetFinishedTaskImpl(const TaskSetFinishedTaskImpl&) = delete; + TaskSetFinishedTaskImpl& operator=(const TaskSetFinishedTaskImpl&) = delete; // Overridden from Task: void RunOnWorkerThread() override { @@ -354,8 +356,6 @@ class TaskSetFinishedTaskImpl : public TileTask { private: base::SequencedTaskRunner* task_runner_; const base::RepeatingClosure on_task_set_finished_callback_; - - DISALLOW_COPY_AND_ASSIGN(TaskSetFinishedTaskImpl); }; class DidFinishRunningAllTilesTask : public TileTask { diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h index c4024e2128e..30d55902837 100644 --- a/chromium/cc/tiles/tile_manager.h +++ b/chromium/cc/tiles/tile_manager.h @@ -14,7 +14,6 @@ #include <utility> #include <vector> -#include "base/macros.h" #include "base/sequenced_task_runner.h" #include "base/values.h" #include "cc/base/unique_notifier.h" @@ -135,8 +134,12 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, size_t scheduled_raster_task_limit, const TileManagerSettings& tile_manager_settings); + + TileManager(const TileManager&) = delete; ~TileManager() override; + TileManager& operator=(const TileManager&) = delete; + // Assigns tile memory and schedules work to prepare tiles for drawing. // This step occurs after Commit and at most once per BeginFrame. It can be // called on its own, that is, outside of Commit. @@ -470,8 +473,6 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { base::WeakPtrFactory<TileManager> task_set_finished_weak_ptr_factory_; // The |ready_to_draw_callback_weak_ptr_factory_| is never invalidated. base::WeakPtrFactory<TileManager> ready_to_draw_callback_weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(TileManager); }; } // namespace cc diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc index 3e9e4aff52f..43f7f2a354f 100644 --- a/chromium/cc/tiles/tile_manager_unittest.cc +++ b/chromium/cc/tiles/tile_manager_unittest.cc @@ -3429,6 +3429,10 @@ TEST_F(DecodedImageTrackerTileManagerTest, DecodedImageTrackerDropsLocksOnUse) { class TileManagerCheckRasterQueriesTest : public TileManagerTest { public: + ~TileManagerCheckRasterQueriesTest() override { + // Ensure that the host impl doesn't outlive |raster_buffer_provider_|. + TakeHostImpl(); + } void SetUp() override { TileManagerTest::SetUp(); host_impl()->tile_manager()->SetRasterBufferProviderForTesting( diff --git a/chromium/cc/tiles/tile_task_manager.h b/chromium/cc/tiles/tile_task_manager.h index 7f543c10d15..f77a4603b91 100644 --- a/chromium/cc/tiles/tile_task_manager.h +++ b/chromium/cc/tiles/tile_task_manager.h @@ -36,8 +36,11 @@ class CC_EXPORT TileTaskManager { class CC_EXPORT TileTaskManagerImpl : public TileTaskManager { public: + TileTaskManagerImpl(const TileTaskManagerImpl&) = delete; ~TileTaskManagerImpl() override; + TileTaskManagerImpl& operator=(const TileTaskManagerImpl&) = delete; + static std::unique_ptr<TileTaskManagerImpl> Create( TaskGraphRunner* task_graph_runner); @@ -51,9 +54,6 @@ class CC_EXPORT TileTaskManagerImpl : public TileTaskManager { TaskGraphRunner* task_graph_runner_; const NamespaceToken namespace_token_; - - private: - DISALLOW_COPY_AND_ASSIGN(TileTaskManagerImpl); }; } // namespace cc diff --git a/chromium/cc/tiles/tiling_set_raster_queue_all.h b/chromium/cc/tiles/tiling_set_raster_queue_all.h index e29736d8b02..7e9149f351c 100644 --- a/chromium/cc/tiles/tiling_set_raster_queue_all.h +++ b/chromium/cc/tiles/tiling_set_raster_queue_all.h @@ -8,7 +8,6 @@ #include <stddef.h> #include "base/containers/stack_container.h" -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/tiles/picture_layer_tiling_set.h" #include "cc/tiles/prioritized_tile.h" @@ -24,8 +23,11 @@ class CC_EXPORT TilingSetRasterQueueAll { TilingSetRasterQueueAll(PictureLayerTilingSet* tiling_set, bool prioritize_low_res, bool is_drawing_layer); + TilingSetRasterQueueAll(const TilingSetRasterQueueAll&) = delete; ~TilingSetRasterQueueAll(); + TilingSetRasterQueueAll& operator=(const TilingSetRasterQueueAll&) = delete; + const PrioritizedTile& Top() const; void Pop(); bool IsEmpty() const; @@ -193,8 +195,6 @@ class CC_EXPORT TilingSetRasterQueueAll { base::StackVector<IterationStage, 6> stages_; TilingIterator iterators_[NUM_ITERATORS]; bool is_drawing_layer_ = false; - - DISALLOW_COPY_AND_ASSIGN(TilingSetRasterQueueAll); }; } // namespace cc diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc index fc24565544b..f3ddee21062 100644 --- a/chromium/cc/trees/damage_tracker.cc +++ b/chromium/cc/trees/damage_tracker.cc @@ -365,7 +365,8 @@ void DamageTracker::AccumulateDamageFromLayer(LayerImpl* layer) { // This method is called when we want to consider how a layer contributes to // its target RenderSurface, even if that layer owns the target RenderSurface // itself. To consider how a layer's target surface contributes to the - // ancestor surface, ExtendDamageForRenderSurface() must be called instead. + // ancestor surface, AccumulateDamageFromRenderSurface() must be called + // instead. bool layer_is_new = false; LayerRectMapData& data = RectDataForLayer(layer->id(), &layer_is_new); gfx::Rect old_rect_in_target_space = data.rect_; diff --git a/chromium/cc/trees/damage_tracker.h b/chromium/cc/trees/damage_tracker.h index c320db43350..bda7579c9d9 100644 --- a/chromium/cc/trees/damage_tracker.h +++ b/chromium/cc/trees/damage_tracker.h @@ -8,7 +8,6 @@ #include <memory> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/layers/layer_collections.h" #include "ui/gfx/geometry/rect.h" @@ -30,8 +29,11 @@ class RenderSurfaceImpl; class CC_EXPORT DamageTracker { public: static std::unique_ptr<DamageTracker> Create(); + DamageTracker(const DamageTracker&) = delete; ~DamageTracker(); + DamageTracker& operator=(const DamageTracker&) = delete; + static void UpdateDamageTracking( LayerTreeImpl* layer_tree_impl, const RenderSurfaceList& render_surface_list); @@ -153,8 +155,6 @@ class CC_EXPORT DamageTracker { // Damage accumulated since the last call to PrepareForUpdate(). DamageAccumulator damage_for_this_update_; - - DISALLOW_COPY_AND_ASSIGN(DamageTracker); }; } // namespace cc diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 5623b6d0eaf..fcd75ca4f75 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -18,6 +18,7 @@ #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" +#include "cc/trees/transform_node.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -1364,6 +1365,46 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantLayer) { ->has_damage_from_contributing_content()); } +TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantSurface) { + // If descendant surface changes position, the ancestor surface should be + // damaged with the old and new descendant surface regions. + + LayerImpl* root = CreateAndSetUpTestTreeWithTwoSurfaces(); + LayerImpl* child1 = root->test_properties()->children[0]; + child1->SetDrawsContent(true); + EmulateDrawingOneFrame(root); + + gfx::Rect child_damage_rect; + gfx::Rect root_damage_rect; + + ClearDamageForAllSurfaces(root); + child1->test_properties()->position = gfx::PointF(105.f, 107.f); + child1->NoteLayerPropertyChanged(); + TransformNode* child1_transform = + root->layer_tree_impl()->property_trees()->transform_tree.Node( + child1->transform_tree_index()); + child1_transform->transform_changed = true; + EmulateDrawingOneFrame(root); + EXPECT_TRUE(GetRenderSurface(child1)->damage_tracker()->GetDamageRectIfValid( + &child_damage_rect)); + EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid( + &root_damage_rect)); + + // Damage to the root surface should be the union of child1's *entire* render + // surface (in target space), and its old exposed area (also in target + // space). + EXPECT_EQ(gfx::Rect(100, 100, 206, 208).ToString(), + root_damage_rect.ToString()); + // The child surface should also be damaged. + EXPECT_EQ(gfx::Rect(0, 0, 206, 208).ToString(), child_damage_rect.ToString()); + EXPECT_TRUE(GetRenderSurface(root) + ->damage_tracker() + ->has_damage_from_contributing_content()); + EXPECT_TRUE(GetRenderSurface(child1) + ->damage_tracker() + ->has_damage_from_contributing_content()); +} + TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromAncestorLayer) { // An ancestor/owning layer changes that affects the position/transform of // the render surface. Note that in this case, the layer_property_changed flag @@ -1763,7 +1804,7 @@ TEST_F(DamageTrackerTest, VerifyDamageAccumulatesUntilReset) { } TEST_F(DamageTrackerTest, HugeDamageRect) { - // This number is so large that we start losting floating point accuracy. + // This number is so large that we start losing floating point accuracy. const int kBigNumber = 900000000; // Walk over a range to find floating point inaccuracy boundaries that move // toward the wrong direction. diff --git a/chromium/cc/trees/debug_rect_history.h b/chromium/cc/trees/debug_rect_history.h index fb6b9021a69..94d1ee95c0e 100644 --- a/chromium/cc/trees/debug_rect_history.h +++ b/chromium/cc/trees/debug_rect_history.h @@ -8,7 +8,6 @@ #include <memory> #include <vector> -#include "base/macros.h" #include "cc/input/touch_action.h" #include "cc/layers/layer_collections.h" #include "ui/gfx/geometry/rect.h" @@ -71,8 +70,11 @@ class DebugRectHistory { public: static std::unique_ptr<DebugRectHistory> Create(); + DebugRectHistory(const DebugRectHistory&) = delete; ~DebugRectHistory(); + DebugRectHistory& operator=(const DebugRectHistory&) = delete; + // Note: Saving debug rects must happen before layers' change tracking is // reset. void SaveDebugRectsForCurrentFrame( @@ -99,8 +101,6 @@ class DebugRectHistory { void SaveNonFastScrollableRectsCallback(LayerImpl* layer); std::vector<DebugRect> debug_rects_; - - DISALLOW_COPY_AND_ASSIGN(DebugRectHistory); }; } // namespace cc diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index d719d9c52ee..e32fa24aa1c 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -664,6 +664,58 @@ static ConditionalClip LayerClipRect(PropertyTrees* property_trees, layer->clip_tree_index(), target_node->id); } +static std::pair<gfx::RRectF, bool> GetRoundedCornerRRect( + const PropertyTrees* property_trees, + int effect_tree_index, + bool for_render_surface) { + static const std::pair<gfx::RRectF, bool> kEmptyRoundedCornerInfo( + gfx::RRectF(), false); + const EffectTree* effect_tree = &property_trees->effect_tree; + const EffectNode* effect_node = effect_tree->Node(effect_tree_index); + const int target_id = effect_node->target_id; + + // Return empty rrect if this node has a render surface but the function call + // was made for a non render surface. + if (effect_node->has_render_surface && !for_render_surface) + return kEmptyRoundedCornerInfo; + + // Traverse the parent chain up to the render target to find a node which has + // a rounded corner bounds set. + const EffectNode* node = effect_node; + bool found_rounded_corner = false; + while (node) { + if (!node->rounded_corner_bounds.IsEmpty()) { + found_rounded_corner = true; + break; + } + + // Simply break if we reached a node that has a render surface or is the + // render target. + if (node->has_render_surface || node->id == target_id) + break; + + node = effect_tree->parent(node); + } + + // While traversing up the parent chain we did not find any node with a + // rounded corner. + if (!node || !found_rounded_corner) + return kEmptyRoundedCornerInfo; + + gfx::Transform to_target; + if (!property_trees->GetToTarget(node->transform_id, target_id, &to_target)) + return kEmptyRoundedCornerInfo; + + DCHECK(to_target.Preserves2dAxisAlignment()); + + SkRRect result; + if (!SkRRect(node->rounded_corner_bounds) + .transform(to_target.matrix(), &result)) { + return kEmptyRoundedCornerInfo; + } + return std::make_pair(gfx::RRectF(result), node->is_fast_rounded_corner); +} + static void UpdateRenderTarget(EffectTree* effect_tree) { for (int i = EffectTree::kContentsRootNodeId; i < static_cast<int>(effect_tree->size()); ++i) { @@ -897,6 +949,12 @@ void ComputeDrawPropertiesOfVisibleLayers(const LayerImplList* layer_list, layer, property_trees->transform_tree, property_trees->effect_tree); layer->draw_properties().screen_space_transform_is_animating = transform_node->to_screen_is_potentially_animated; + auto rounded_corner_info = + GetRoundedCornerRRect(property_trees, layer->effect_tree_index(), + /*from_render_surface*/ false); + layer->draw_properties().rounded_corner_bounds = rounded_corner_info.first; + layer->draw_properties().is_fast_rounded_corner = + rounded_corner_info.second; } // Compute effects and determine if render surfaces have contributing layers @@ -967,6 +1025,11 @@ void ComputeSurfaceDrawProperties(PropertyTrees* property_trees, SetSurfaceIsClipped(property_trees->clip_tree, render_surface); SetSurfaceDrawOpacity(property_trees->effect_tree, render_surface); SetSurfaceDrawTransform(property_trees, render_surface); + + render_surface->SetRoundedCornerRRect( + GetRoundedCornerRRect(property_trees, render_surface->EffectTreeIndex(), + /*for_render_surface*/ true) + .first); render_surface->SetScreenSpaceTransform( property_trees->ToScreenSpaceTransformWithoutSurfaceContentsScale( render_surface->TransformTreeIndex(), diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc index b8f8aebb4d5..3701e4c41f2 100644 --- a/chromium/cc/trees/effect_node.cc +++ b/chromium/cc/trees/effect_node.cc @@ -33,6 +33,7 @@ EffectNode::EffectNode() is_masked(false), effect_changed(false), subtree_has_copy_request(false), + is_fast_rounded_corner(false), transform_id(0), clip_id(0), target_id(1), @@ -54,6 +55,8 @@ bool EffectNode::operator==(const EffectNode& other) const { backdrop_filters == other.backdrop_filters && backdrop_filter_bounds == other.backdrop_filter_bounds && filters_origin == other.filters_origin && + rounded_corner_bounds == other.rounded_corner_bounds && + is_fast_rounded_corner == other.is_fast_rounded_corner && blend_mode == other.blend_mode && surface_contents_scale == other.surface_contents_scale && unscaled_mask_target_size == other.unscaled_mask_target_size && @@ -86,6 +89,7 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetInteger("stable_id", stable_id); value->SetDouble("opacity", opacity); value->SetDouble("backdrop_filter_quality", backdrop_filter_quality); + value->SetBoolean("is_fast_rounded_corner", is_fast_rounded_corner); value->SetString("blend_mode", SkBlendMode_Name(blend_mode)); value->SetBoolean("has_render_surface", has_render_surface); value->SetBoolean("cache_render_surface", cache_render_surface); @@ -97,6 +101,8 @@ void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { has_potential_filter_animation); value->SetBoolean("has_potential_opacity_animation", has_potential_opacity_animation); + value->SetBoolean("has_masking_child", has_masking_child); + value->SetBoolean("is_masked", is_masked); value->SetBoolean("effect_changed", effect_changed); value->SetInteger("subtree_has_copy_request", subtree_has_copy_request); value->SetInteger("transform_id", transform_id); diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index b184461bbcc..f9ad97132ad 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -45,6 +45,10 @@ struct CC_EXPORT EffectNode { float backdrop_filter_quality; gfx::PointF filters_origin; + // Bounds of rounded corner rrect in the space of the transform node + // associated with this effect node. + gfx::RRectF rounded_corner_bounds; + SkBlendMode blend_mode; gfx::Vector2dF surface_contents_scale; @@ -73,13 +77,15 @@ struct CC_EXPORT EffectNode { bool is_currently_animating_opacity : 1; // Whether this node has a child node with kDstIn blend mode. bool has_masking_child : 1; - // Whether this node has an ancestor with a mask layer or the node itself has - // a mask. + // Whether this node has a mask. This bit is not used when using layer lists. bool is_masked : 1; // Whether this node's effect has been changed since the last // frame. Needed in order to compute damage rect. bool effect_changed : 1; bool subtree_has_copy_request : 1; + // If set, the effect node tries to not trigger a render surface due to it + // having a rounded corner. + bool is_fast_rounded_corner; // The transform node index of the transform to apply to this effect // node's content when rendering to a surface. int transform_id; diff --git a/chromium/cc/trees/element_id.cc b/chromium/cc/trees/element_id.cc index b460a2e8675..6690378fc16 100644 --- a/chromium/cc/trees/element_id.cc +++ b/chromium/cc/trees/element_id.cc @@ -14,6 +14,8 @@ namespace cc { +const ElementIdType ElementId::kInvalidElementId = 0; + ElementId LayerIdToElementIdForTesting(int layer_id) { return ElementId(std::numeric_limits<int>::max() - layer_id); } diff --git a/chromium/cc/trees/element_id.h b/chromium/cc/trees/element_id.h index 482ed3e152b..e8275c521cc 100644 --- a/chromium/cc/trees/element_id.h +++ b/chromium/cc/trees/element_id.h @@ -12,7 +12,7 @@ #include <iosfwd> #include <memory> -#include "base/hash.h" +#include "base/hash/hash.h" #include "cc/cc_export.h" namespace base { @@ -26,8 +26,6 @@ namespace cc { using ElementIdType = uint64_t; -static const ElementIdType kInvalidElementId = 0; - // Element ids are chosen by cc's clients and can be used as a stable identifier // across updates. // @@ -47,14 +45,17 @@ static const ElementIdType kInvalidElementId = 0; // targets. A Layer's element id can change over the Layer's lifetime because // non-default ElementIds are only set during an animation's lifetime. struct CC_EXPORT ElementId { - explicit ElementId(ElementIdType id) : id_(id) {} - ElementId() : ElementId(kInvalidElementId) {} + explicit ElementId(ElementIdType id) : id_(id) { + DCHECK_NE(id, kInvalidElementId); + } + + ElementId() : id_(kInvalidElementId) {} bool operator==(const ElementId& o) const { return id_ == o.id_; } bool operator!=(const ElementId& o) const { return !(*this == o); } bool operator<(const ElementId& o) const { return id_ < o.id_; } - // An ElementId's conversion to a boolean value depends only on its primaryId. + // Returns true if the ElementId has been initialized with a valid id. explicit operator bool() const { return !!id_; } void AddToTracedValue(base::trace_event::TracedValue* res) const; @@ -66,6 +67,7 @@ struct CC_EXPORT ElementId { private: friend struct ElementIdHash; + static const ElementIdType kInvalidElementId; // The compositor treats this as an opaque handle and should not know how to // interpret these bits. Non-blink cc clients typically operate in terms of diff --git a/chromium/cc/trees/frame_rate_counter.h b/chromium/cc/trees/frame_rate_counter.h index 2eadf847d42..86461509f7a 100644 --- a/chromium/cc/trees/frame_rate_counter.h +++ b/chromium/cc/trees/frame_rate_counter.h @@ -10,7 +10,6 @@ #include <memory> #include "base/containers/ring_buffer.h" -#include "base/macros.h" #include "base/time/time.h" namespace cc { @@ -21,6 +20,9 @@ class FrameRateCounter { public: static std::unique_ptr<FrameRateCounter> Create(bool has_impl_thread); + FrameRateCounter(const FrameRateCounter&) = delete; + FrameRateCounter& operator=(const FrameRateCounter&) = delete; + size_t current_frame_number() const { return ring_buffer_.CurrentIndex(); } int dropped_frame_count() const { return dropped_frame_count_; } size_t time_stamp_history_size() const { return ring_buffer_.BufferSize(); } @@ -51,8 +53,6 @@ class FrameRateCounter { bool has_impl_thread_; int dropped_frame_count_; - - DISALLOW_COPY_AND_ASSIGN(FrameRateCounter); }; } // namespace cc diff --git a/chromium/cc/trees/image_animation_controller.h b/chromium/cc/trees/image_animation_controller.h index d6f6c3cecdb..a95ec12448e 100644 --- a/chromium/cc/trees/image_animation_controller.h +++ b/chromium/cc/trees/image_animation_controller.h @@ -133,10 +133,13 @@ class CC_EXPORT ImageAnimationController { class AnimationState { public: AnimationState(); + AnimationState(const AnimationState&) = delete; AnimationState(AnimationState&& other); - AnimationState& operator=(AnimationState&& other); ~AnimationState(); + AnimationState& operator=(const AnimationState&) = delete; + AnimationState& operator=(AnimationState&& other); + bool ShouldAnimate() const; bool AdvanceFrame(const viz::BeginFrameArgs& args, bool enable_image_animation_resync); @@ -224,8 +227,6 @@ class CC_EXPORT ImageAnimationController { // The number of frames skipped during catch-up the last time this animation // was advanced. size_t last_num_frames_skipped_ = 0u; - - DISALLOW_COPY_AND_ASSIGN(AnimationState); }; class InvalidationScheduler { diff --git a/chromium/cc/trees/latency_info_swap_promise.h b/chromium/cc/trees/latency_info_swap_promise.h index 2f2fdee234a..ecdd381fe14 100644 --- a/chromium/cc/trees/latency_info_swap_promise.h +++ b/chromium/cc/trees/latency_info_swap_promise.h @@ -13,6 +13,12 @@ namespace cc { +// Associates a |LatencyInfo| with a compositor frame's metadata before that +// frame is sent to the downstream display compositor. The |LatencyInfo| +// instances used here track latencies of pieces of the input handling +// pipeline. Compositor frame consumers can combine their internal latency +// measurements with these measurements to generate end-to-end reports of input +// latency. class CC_EXPORT LatencyInfoSwapPromise : public SwapPromise { public: explicit LatencyInfoSwapPromise(const ui::LatencyInfo& latency_info); diff --git a/chromium/cc/trees/layer_tree_frame_sink.cc b/chromium/cc/trees/layer_tree_frame_sink.cc index 024981ce300..71ed2774860 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.cc +++ b/chromium/cc/trees/layer_tree_frame_sink.cc @@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/location.h" -#include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "cc/trees/layer_tree_frame_sink_client.h" @@ -25,8 +24,11 @@ class LayerTreeFrameSink::ContextLostForwarder ContextLostForwarder(base::WeakPtr<LayerTreeFrameSink> frame_sink, scoped_refptr<base::SingleThreadTaskRunner> task_runner) : frame_sink_(frame_sink), task_runner_(std::move(task_runner)) {} + ContextLostForwarder(const ContextLostForwarder&) = delete; ~ContextLostForwarder() override = default; + ContextLostForwarder& operator=(const ContextLostForwarder&) = delete; + void OnContextLost() override { task_runner_->PostTask( FROM_HERE, @@ -36,7 +38,6 @@ class LayerTreeFrameSink::ContextLostForwarder private: base::WeakPtr<LayerTreeFrameSink> frame_sink_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - DISALLOW_COPY_AND_ASSIGN(ContextLostForwarder); }; LayerTreeFrameSink::LayerTreeFrameSink( diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h index 7ae114e3fe7..76634a79771 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.h +++ b/chromium/cc/trees/layer_tree_frame_sink.h @@ -8,7 +8,6 @@ #include <deque> #include <memory> -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -59,9 +58,12 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, scoped_refptr<viz::RasterContextProvider> worker_context_provider, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); + LayerTreeFrameSink(const LayerTreeFrameSink&) = delete; ~LayerTreeFrameSink() override; + LayerTreeFrameSink& operator=(const LayerTreeFrameSink&) = delete; + base::WeakPtr<LayerTreeFrameSink> GetWeakPtr(); // Called by the compositor on the compositor thread. This is a place where @@ -153,7 +155,6 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, private: THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<LayerTreeFrameSink> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(LayerTreeFrameSink); }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 4988a714475..313f92f57e7 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -663,10 +663,6 @@ bool LayerTreeHost::IsVisible() const { return visible_; } -void LayerTreeHost::NotifyInputThrottledUntilCommit() { - proxy_->NotifyInputThrottledUntilCommit(); -} - void LayerTreeHost::LayoutAndUpdateLayers() { DCHECK(IsSingleThreaded()); // This function is only valid when not using the scheduler. @@ -680,9 +676,7 @@ void LayerTreeHost::Composite(base::TimeTicks frame_begin_time, bool raster) { // This function is only valid when not using the scheduler. DCHECK(!settings_.single_thread_proxy_scheduler); SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get()); - - proxy->CompositeImmediately(frame_begin_time, - raster || next_commit_forces_redraw_); + proxy->CompositeImmediately(frame_begin_time, raster); } bool LayerTreeHost::UpdateLayers() { @@ -694,6 +688,7 @@ bool LayerTreeHost::UpdateLayers() { DCHECK(!root_layer()->parent()); base::ElapsedTimer timer; + client_->WillUpdateLayers(); bool result = DoUpdateLayers(); client_->DidUpdateLayers(); micro_benchmark_controller_.DidUpdateLayers(); @@ -886,9 +881,11 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) { if (inner_viewport_scroll_delta.IsZero() && info.page_scale_delta == 1.f && info.elastic_overscroll_delta.IsZero() && !info.top_controls_delta && !info.browser_controls_constraint_changed && - !info.scroll_gesture_did_end) { + !info.scroll_gesture_did_end && + info.is_pinch_gesture_active == is_pinch_gesture_active_from_impl_) { return; } + is_pinch_gesture_active_from_impl_ = info.is_pinch_gesture_active; // Preemptively apply the scroll offset and scale delta here before sending // it to the client. If the client comes back and sets it to the same @@ -906,8 +903,9 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) { // may be translated appropriately. client_->ApplyViewportChanges( {inner_viewport_scroll_delta, info.elastic_overscroll_delta, - info.page_scale_delta, info.top_controls_delta, - info.browser_controls_constraint, info.scroll_gesture_did_end}); + info.page_scale_delta, info.is_pinch_gesture_active, + info.top_controls_delta, info.browser_controls_constraint, + info.scroll_gesture_did_end}); SetNeedsUpdateLayers(); } @@ -1284,10 +1282,10 @@ void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor, DCHECK_GE(page_scale_factor, min_page_scale_factor); DCHECK_LE(page_scale_factor, max_page_scale_factor); // We should never process non-unit page_scale_delta for an OOPIF subframe. - // TODO(wjmaclean): Remove this check as a pre-condition to closing the bug. + // TODO(wjmaclean): Remove this dcheck as a pre-condition to closing the bug. // https://crbug.com/845097 - CHECK(!settings_.is_layer_tree_for_subframe || - page_scale_factor == page_scale_factor_) + DCHECK(!settings_.is_layer_tree_for_subframe || + page_scale_factor == page_scale_factor_) << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_ << ", new psf = " << page_scale_factor; @@ -1328,11 +1326,16 @@ void LayerTreeHost::SetRasterColorSpace( this, [](Layer* layer) { layer->SetNeedsDisplay(); }); } -void LayerTreeHost::SetExternalPageScaleFactor(float page_scale_factor) { - if (external_page_scale_factor_ == page_scale_factor) +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) { return; + } external_page_scale_factor_ = page_scale_factor; + is_external_pinch_gesture_active_ = is_external_pinch_gesture_active; SetNeedsCommit(); } @@ -1588,8 +1591,8 @@ void LayerTreeHost::PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl) { if (viewport_layers_.outer_viewport_scroll) ids.outer_viewport_scroll = viewport_layers_.outer_viewport_scroll->id(); tree_impl->SetViewportLayersFromIds(ids); - DCHECK(viewport_layers_.inner_viewport_scroll - ->IsContainerForFixedPositionLayers()); + DCHECK(IsUsingLayerLists() || viewport_layers_.inner_viewport_scroll + ->IsContainerForFixedPositionLayers()); } else { tree_impl->ClearViewportLayers(); } @@ -1653,6 +1656,8 @@ void LayerTreeHost::PushLayerTreeHostPropertiesTo( host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_); host_impl->SetContentHasSlowPaths(content_has_slow_paths_); host_impl->SetContentHasNonAAPaint(content_has_non_aa_paint_); + host_impl->set_external_pinch_gesture_active( + is_external_pinch_gesture_active_); RecordGpuRasterizationHistogram(host_impl); host_impl->SetDebugState(debug_state_); @@ -1828,8 +1833,17 @@ void LayerTreeHost::ElementIsAnimatingChanged( const PropertyAnimationState& mask, const PropertyAnimationState& state) { DCHECK_EQ(ElementListType::ACTIVE, list_type); - property_trees()->ElementIsAnimatingChanged(mutator_host(), element_id_map, - list_type, mask, state, true); + property_trees()->ElementIsAnimatingChanged(element_id_map, mask, state, + true); +} + +void LayerTreeHost::AnimationScalesChanged(ElementId element_id, + ElementListType list_type, + float maximum_scale, + float starting_scale) { + DCHECK_EQ(ElementListType::ACTIVE, list_type); + property_trees()->AnimationScalesChanged(element_id, maximum_scale, + starting_scale); } gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation( diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index ec6298d7e03..9d7d39f86b1 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -19,7 +19,6 @@ #include "base/cancelable_callback.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" @@ -57,6 +56,7 @@ struct PresentationFeedback; } namespace cc { + class HeadsUpDisplayLayer; class Layer; class LayerTreeHostClient; @@ -128,8 +128,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { LayerTreeHostSingleThreadClient* single_thread_client, InitParams params); + LayerTreeHost(const LayerTreeHost&) = delete; virtual ~LayerTreeHost(); + LayerTreeHost& operator=(const LayerTreeHost&) = delete; + // Returns the process global unique identifier for this LayerTreeHost. int GetId() const; @@ -273,11 +276,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Input Handling --------------------------------------------- - // Notifies the compositor that input from the browser is being throttled till - // the next commit. The compositor will prioritize activation of the pending - // tree so a commit can be performed. - void NotifyInputThrottledUntilCommit(); - // Sets the state of the browser controls. (Used for URL bar animations on // android). void UpdateBrowserControlsState(BrowserControlsState constraints, @@ -405,7 +403,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { float bottom_height, bool shrink); void SetBrowserControlsShownRatio(float ratio); + void SetOverscrollBehavior(const OverscrollBehavior& overscroll_behavior); + const OverscrollBehavior& overscroll_behavior() const { + return overscroll_behavior_; + } void SetPageScaleFactorAndLimits(float page_scale_factor, float min_page_scale_factor, @@ -474,7 +476,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // 'external_page_scale_factor', a value that affects raster scale in the // same way that page_scale_factor does, but doesn't affect any geometry // calculations. - void SetExternalPageScaleFactor(float page_scale_factor); + 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_; + } // Requests that we force send RenderFrameMetadata with the next frame. void RequestForceSendMetadata() { force_send_metadata_request_ = true; } @@ -659,6 +665,10 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) override; + void AnimationScalesChanged(ElementId element_id, + ElementListType list_type, + float maximum_scale, + float starting_scale) override; void ScrollOffsetAnimationFinished() override {} gfx::ScrollOffset GetScrollOffsetForAnimation( @@ -804,6 +814,9 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { 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; int raster_color_space_id_ = -1; gfx::ColorSpace raster_color_space_; @@ -893,8 +906,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Used to vend weak pointers to LayerTreeHost to ScopedDeferMainFrameUpdate // objects. base::WeakPtrFactory<LayerTreeHost> defer_main_frame_update_weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(LayerTreeHost); }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index 58094697211..b54c5c1a35b 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -37,6 +37,10 @@ struct ApplyViewportChangesArgs { // main_thread_scale * delta == impl_thread_scale. float page_scale_delta; + // Indicates that a pinch gesture is currently active or not; used to allow + // subframe compositors to throttle their re-rastering during the gesture. + bool is_pinch_gesture_active; + // How much the browser controls have been shown or hidden. The ratio runs // between 0 (hidden) and 1 (full-shown). This is additive. float browser_controls_delta; @@ -81,6 +85,7 @@ class LayerTreeHostClient { virtual void BeginMainFrameNotExpectedSoon() = 0; virtual void BeginMainFrameNotExpectedUntil(base::TimeTicks time) = 0; virtual void DidBeginMainFrame() = 0; + virtual void WillUpdateLayers() = 0; virtual void DidUpdateLayers() = 0; // Visual frame-based updates to the state of the LayerTreeHost are expected diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc index 92b83a2b450..cd56fec1beb 100644 --- a/chromium/cc/trees/layer_tree_host_common.cc +++ b/chromium/cc/trees/layer_tree_host_common.cc @@ -177,6 +177,7 @@ bool LayerTreeHostCommon::ScrollbarsUpdateInfo::operator==( ScrollAndScaleSet::ScrollAndScaleSet() : page_scale_delta(1.f), + is_pinch_gesture_active(false), top_controls_delta(0.f), browser_controls_constraint(BrowserControlsState::kBoth), browser_controls_constraint_changed(false), diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h index 235910b58d3..c27157a9939 100644 --- a/chromium/cc/trees/layer_tree_host_common.h +++ b/chromium/cc/trees/layer_tree_host_common.h @@ -11,7 +11,6 @@ #include <vector> #include "base/bind.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" @@ -158,8 +157,11 @@ class CC_EXPORT LayerTreeHostCommon { struct CC_EXPORT ScrollAndScaleSet { ScrollAndScaleSet(); + ScrollAndScaleSet(const ScrollAndScaleSet&) = delete; ~ScrollAndScaleSet(); + ScrollAndScaleSet& operator=(const ScrollAndScaleSet&) = delete; + // The inner viewport scroll delta is kept separate since it's special. // Because the inner (visual) viewport's maximum offset depends on the // current page scale, the two must be committed at the same time to prevent @@ -168,6 +170,7 @@ struct CC_EXPORT ScrollAndScaleSet { std::vector<LayerTreeHostCommon::ScrollUpdateInfo> scrolls; float page_scale_delta; + bool is_pinch_gesture_active; // Elastic overscroll effect offset delta. This is used only on Mac and shows // the pixels that the page is rubber-banned/stretched by. @@ -192,9 +195,6 @@ struct CC_EXPORT ScrollAndScaleSet { // Set to true when a scroll gesture being handled on the compositor has // ended. bool scroll_gesture_did_end; - - private: - DISALLOW_COPY_AND_ASSIGN(ScrollAndScaleSet); }; template <typename Function> diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc index 3718d87e89a..37d6f1c7bb0 100644 --- a/chromium/cc/trees/layer_tree_host_common_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc @@ -51,6 +51,8 @@ #include "components/viz/common/frame_sinks/copy_output_result.h" #include "testing/gtest/include/gtest/gtest.h" #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/vector2d_conversions.h" #include "ui/gfx/transform.h" @@ -113,6 +115,10 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { gfx::Size(root_layer->bounds().width() * device_scale_factor, root_layer->bounds().height() * device_scale_factor); + root_layer->layer_tree_host()->SetViewportSizeAndScale( + device_viewport_size, device_scale_factor, + viz::LocalSurfaceIdAllocation()); + // We are probably not testing what is intended if the root_layer bounds are // empty. DCHECK(!root_layer->bounds().IsEmpty()); @@ -4654,6 +4660,13 @@ TEST_P(LCDTextTest, CanUseLCDText) { EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText()); EXPECT_EQ(expect_lcd_text, child_->CanUseLCDText()); EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText()); + + // Case 11: will-change: transform + child_->SetHasWillChangeTransformHint(true); + ExecuteCalculateDrawProperties(root_, 1.f, 1.f, nullptr, nullptr, nullptr); + EXPECT_EQ(expect_lcd_text, root_->CanUseLCDText()); + EXPECT_EQ(expect_not_lcd_text, child_->CanUseLCDText()); + EXPECT_EQ(expect_lcd_text, grand_child_->CanUseLCDText()); } TEST_P(LCDTextTest, CanUseLCDTextWithAnimation) { @@ -7320,15 +7333,15 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { ExecuteCalculateDrawProperties(grand_parent_raw); // No layers have animations. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); TransformOperations translation; translation.AppendTranslate(1.f, 2.f, 3.f); @@ -7367,15 +7380,15 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { TransformOperations(), translation); // No layers have scale-affecting animations. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); TransformOperations scale; scale.AppendScale(5.f, 4.f, 3.f); @@ -7386,13 +7399,13 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { ExecuteCalculateDrawProperties(grand_parent_raw); // Only |child| has a scale-affecting animation. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); EXPECT_EQ(5.f, GetMaximumAnimationScale(child_raw)); EXPECT_EQ(5.f, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); EXPECT_EQ(1.f, GetStartingAnimationScale(child_raw)); EXPECT_EQ(1.f, GetStartingAnimationScale(grand_child_raw)); @@ -7406,13 +7419,13 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { EXPECT_EQ(5.f, GetMaximumAnimationScale(parent_raw)); // We don't support combining animated scales from two nodes; 0.f means // that the maximum scale could not be computed. - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); EXPECT_EQ(1.f, GetStartingAnimationScale(grand_parent_raw)); EXPECT_EQ(1.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); AddAnimatedTransformToAnimation(parent_animation.get(), 1.0, TransformOperations(), scale); @@ -7421,14 +7434,14 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { // |grand_parent|, |parent|, and |child| have scale-affecting animations. EXPECT_EQ(5.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); EXPECT_EQ(1.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); grand_parent_animation->AbortKeyframeModelsWithProperty( TargetProperty::TRANSFORM, false); @@ -7447,15 +7460,15 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { // |child| has a scale-affecting animation but computing the maximum of this // animation is not supported. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); child_animation->AbortKeyframeModelsWithProperty(TargetProperty::TRANSFORM, false); @@ -7472,12 +7485,12 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { // |grand_parent| and |parent| each have scale 2.f. |parent| has a scale // animation with maximum scale 5.f. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); EXPECT_EQ(10.f, GetMaximumAnimationScale(parent_raw)); EXPECT_EQ(10.f, GetMaximumAnimationScale(child_raw)); EXPECT_EQ(10.f, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); EXPECT_EQ(2.f, GetStartingAnimationScale(parent_raw)); EXPECT_EQ(2.f, GetStartingAnimationScale(child_raw)); EXPECT_EQ(2.f, GetStartingAnimationScale(grand_child_raw)); @@ -7489,15 +7502,15 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { ExecuteCalculateDrawProperties(grand_parent_raw); // |child| has a transform that's neither a translation nor a scale. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); EXPECT_EQ(10.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); EXPECT_EQ(2.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); parent_raw->test_properties()->transform = perspective_matrix; grand_parent_raw->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -7505,15 +7518,15 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { // |parent| and |child| have transforms that are neither translations nor // scales. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); parent_raw->test_properties()->transform = gfx::Transform(); child_raw->test_properties()->transform = gfx::Transform(); @@ -7523,15 +7536,15 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { ExecuteCalculateDrawProperties(grand_parent_raw); // |grand_parent| has a transform that's neither a translation nor a scale. - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetMaximumAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetMaximumAnimationScale(grand_child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(parent_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(child_raw)); - EXPECT_EQ(0.f, GetStartingAnimationScale(grand_child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(parent_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(child_raw)); + EXPECT_EQ(kNotScaled, GetStartingAnimationScale(grand_child_raw)); } static void GatherDrawnLayers(LayerTreeImpl* tree_impl, @@ -7834,8 +7847,8 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { child1_layer->test_properties()->mask_layer->GetIdealContentsScale()); EXPECT_FLOAT_EQ(5.f, child2_layer->GetIdealContentsScale()); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer)); EXPECT_FLOAT_EQ(8.f, GetMaximumAnimationScale(child2_layer)); // Changing page-scale would affect ideal_contents_scale and @@ -7864,8 +7877,8 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { child1_layer->test_properties()->mask_layer->GetIdealContentsScale()); EXPECT_FLOAT_EQ(15.f, child2_layer->GetIdealContentsScale()); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer)); EXPECT_FLOAT_EQ(24.f, GetMaximumAnimationScale(child2_layer)); // Changing device-scale would affect ideal_contents_scale and @@ -7884,8 +7897,8 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { child1_layer->test_properties()->mask_layer->GetIdealContentsScale()); EXPECT_FLOAT_EQ(60.f, child2_layer->GetIdealContentsScale()); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer)); EXPECT_FLOAT_EQ(96.f, GetMaximumAnimationScale(child2_layer)); } @@ -7937,12 +7950,12 @@ TEST_F(LayerTreeHostCommonTest, AnimationScales) { root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_layer); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child1_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child1_layer)); EXPECT_FLOAT_EQ(24.f, GetMaximumAnimationScale(child2_layer)); - EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(child1_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(child1_layer)); EXPECT_FLOAT_EQ(3.f, GetStartingAnimationScale(child2_layer)); // Correctly updates animation scale when layer property changes. @@ -8004,11 +8017,11 @@ TEST_F(LayerTreeHostCommonTest, root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root_layer); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetMaximumAnimationScale(child_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child_layer)); - EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(0.f, GetStartingAnimationScale(child_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(root_layer)); + EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(child_layer)); } TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) { @@ -8843,11 +8856,12 @@ TEST_F(LayerTreeHostCommonTest, SkippingLayerImpl) { KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::TRANSFORM)); scoped_refptr<SingleKeyframeEffectAnimation> animation( SingleKeyframeEffectAnimation::Create(1)); - timeline()->AttachAnimation(animation); - // TODO(smcgruer): Should attach a timeline and element rather than call this - // directly. See http://crbug.com/771316 - host_impl.animation_host()->RegisterKeyframeEffectForElement( - root_ptr->element_id(), animation->keyframe_effect()); + scoped_refptr<AnimationTimeline> timeline = + AnimationTimeline::Create(AnimationIdProvider::NextTimelineId()); + host_impl.animation_host()->AddAnimationTimeline(timeline); + timeline->AttachAnimation(animation); + animation->AttachElementForKeyframeEffect(root_ptr->element_id(), + animation->keyframe_effect()->id()); animation->AddKeyframeModel(std::move(transform_animation)); grandchild_ptr->set_visible_layer_rect(gfx::Rect()); root_ptr->test_properties()->transform = singular; @@ -8855,31 +8869,15 @@ TEST_F(LayerTreeHostCommonTest, SkippingLayerImpl) { root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr); EXPECT_EQ(gfx::Rect(0, 0), grandchild_ptr->visible_layer_rect()); - - host_impl.animation_host()->UnregisterKeyframeEffectForElement( - root_ptr->element_id(), animation->keyframe_effect()); - host_impl.animation_host()->RemoveFromTicking(animation.get()); - timeline()->DetachAnimation(animation); } +// This tests for correctness of an optimization. If a node in the tree +// maps all possible spaces to a single point (ie has a singular transform) +// we can ignore the size of all its children. We need to make sure that +// we don't do this if an animation can replace this transform in the +// compositor without recomputing the trees. TEST_F(LayerTreeHostCommonTest, LayerSkippingInSubtreeOfSingularTransform) { - LayerImpl* root = root_layer_for_testing(); - LayerImpl* child = AddChild<LayerImpl>(root); - LayerImpl* grand_child = AddChild<LayerImpl>(child); - - SetElementIdsForTesting(); - - gfx::Transform singular; - singular.matrix().set(0, 0, 0); - singular.matrix().set(0, 1, 1); - - root->SetBounds(gfx::Size(10, 10)); - child->test_properties()->transform = singular; - child->SetBounds(gfx::Size(10, 10)); - child->SetDrawsContent(true); - grand_child->SetBounds(gfx::Size(10, 10)); - grand_child->SetDrawsContent(true); - + // Set up a transform animation std::unique_ptr<KeyframedTransformAnimationCurve> curve( KeyframedTransformAnimationCurve::Create()); TransformOperations start; @@ -8896,23 +8894,72 @@ TEST_F(LayerTreeHostCommonTest, LayerSkippingInSubtreeOfSingularTransform) { KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::TRANSFORM)); scoped_refptr<SingleKeyframeEffectAnimation> animation( SingleKeyframeEffectAnimation::Create(1)); - timeline()->AttachAnimation(animation); - // TODO(smcgruer): Should attach a timeline and element rather than call this - // directly. See http://crbug.com/771316 - host_impl()->animation_host()->RegisterKeyframeEffectForElement( - grand_child->element_id(), animation->keyframe_effect()); + timeline_impl()->AttachAnimation(animation); animation->AddKeyframeModel(std::move(transform_animation)); + // Set up some layers to have a tree. + LayerImpl* root = root_layer_for_testing(); + LayerImpl* child = AddChild<LayerImpl>(root); + LayerImpl* grand_child = AddChild<LayerImpl>(child); + + SetElementIdsForTesting(); + + // If these are not on the same host we are doomed to fail. + ASSERT_EQ(timeline_impl()->animation_host(), + child->layer_tree_impl()->mutator_host()); + + // A non-invertible matrix for use later. + gfx::Transform singular; + singular.matrix().set(0, 0, 0); + singular.matrix().set(0, 1, 1); + + root->SetBounds(gfx::Size(10, 10)); + child->SetBounds(gfx::Size(10, 10)); + child->SetDrawsContent(true); + grand_child->SetBounds(gfx::Size(10, 10)); + grand_child->SetDrawsContent(true); + + // Check that we set the visible sizes as expected in CalculateDrawProperties + grand_child->set_visible_layer_rect(gfx::Rect()); + child->set_visible_layer_rect(gfx::Rect()); ExecuteCalculateDrawProperties(root); - EXPECT_EQ(gfx::Rect(0, 0), grand_child->visible_layer_rect()); - EXPECT_EQ(gfx::Rect(0, 0), child->visible_layer_rect()); + ASSERT_EQ(gfx::Rect(10, 10), grand_child->visible_layer_rect()); + ASSERT_EQ(gfx::Rect(10, 10), child->visible_layer_rect()); - host_impl()->animation_host()->UnregisterKeyframeEffectForElement( - grand_child->element_id(), animation->keyframe_effect()); - host_impl()->animation_host()->RemoveFromTicking(animation.get()); - timeline()->DetachAnimation(animation); + // See if we optimize out irrelevant pieces of work. + child->test_properties()->transform = singular; + grand_child->set_visible_layer_rect(gfx::Rect()); + child->set_visible_layer_rect(gfx::Rect()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; + ExecuteCalculateDrawProperties(root); + EXPECT_EQ(gfx::Rect(), grand_child->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(), child->visible_layer_rect()); + + // Check that undoing the transform is still valid (memoryless enough) + child->test_properties()->transform = gfx::Transform(); + grand_child->set_visible_layer_rect(gfx::Rect()); + child->set_visible_layer_rect(gfx::Rect()); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; + ExecuteCalculateDrawProperties(root); + ASSERT_EQ(gfx::Rect(10, 10), grand_child->visible_layer_rect()); + ASSERT_EQ(gfx::Rect(10, 10), child->visible_layer_rect()); + + // If the transform is singular, but there is an animation on it, we + // should not skip the subtree. Note that the animation has not started or + // ticked, there is also code along that path. This is not its test. + animation->AttachElementForKeyframeEffect(child->element_id(), + animation->keyframe_effect()->id()); + child->test_properties()->transform = singular; + grand_child->set_visible_layer_rect(gfx::Rect(1, 1)); + child->set_visible_layer_rect(gfx::Rect(1, 1)); + root->layer_tree_impl()->property_trees()->needs_rebuild = true; + ExecuteCalculateDrawProperties(root); + EXPECT_EQ(gfx::Rect(10, 10), grand_child->visible_layer_rect()); + EXPECT_EQ(gfx::Rect(10, 10), child->visible_layer_rect()); } +// This tests that we skip computing the visible areas for the subtree +// rooted at nodes with constant zero opacity. TEST_F(LayerTreeHostCommonTest, SkippingPendingLayerImpl) { FakeImplTaskRunnerProvider task_runner_provider; TestTaskGraphRunner task_graph_runner; @@ -8946,9 +8993,20 @@ TEST_F(LayerTreeHostCommonTest, SkippingPendingLayerImpl) { host_impl.pending_tree()->SetElementIdsForTesting(); // Check the non-skipped case. + root_ptr->test_properties()->opacity = 1.f; + grandchild_ptr->set_visible_layer_rect(gfx::Rect()); + root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr); - EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect()); + ASSERT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect()); + + // Check the skipped case. + root_ptr->test_properties()->opacity = 0.f; + grandchild_ptr->set_visible_layer_rect(gfx::Rect()); + root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true; + ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr); + EXPECT_EQ(gfx::Rect(), grandchild_ptr->visible_layer_rect()); + // Check the animated case is not skipped. std::unique_ptr<KeyframedFloatAnimationCurve> curve( KeyframedFloatAnimationCurve::Create()); std::unique_ptr<TimingFunction> func = @@ -8962,22 +9020,18 @@ TEST_F(LayerTreeHostCommonTest, SkippingPendingLayerImpl) { KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::OPACITY)); scoped_refptr<SingleKeyframeEffectAnimation> animation( SingleKeyframeEffectAnimation::Create(1)); - timeline()->AttachAnimation(animation); - // TODO(smcgruer): Should attach a timeline and element rather than call this - // directly. See http://crbug.com/771316 - host_impl.animation_host()->RegisterKeyframeEffectForElement( - root_ptr->element_id(), animation->keyframe_effect()); + scoped_refptr<AnimationTimeline> timeline = + AnimationTimeline::Create(AnimationIdProvider::NextTimelineId()); + host_impl.animation_host()->AddAnimationTimeline(timeline); + timeline->AttachAnimation(animation); animation->AddKeyframeModel(std::move(keyframe_model)); - root_ptr->test_properties()->opacity = 0.f; + animation->AttachElementForKeyframeEffect(root_ptr->element_id(), + animation->keyframe_effect()->id()); + // Repeat the calculation invocation. grandchild_ptr->set_visible_layer_rect(gfx::Rect()); root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr); EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect()); - - host_impl.animation_host()->UnregisterKeyframeEffectForElement( - root_ptr->element_id(), animation->keyframe_effect()); - host_impl.animation_host()->RemoveFromTicking(animation.get()); - timeline()->DetachAnimation(animation); } TEST_F(LayerTreeHostCommonTest, SkippingLayer) { @@ -10523,5 +10577,1105 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectClippedByViewport) { EXPECT_EQ(gfx::Rect(root_layer_size), root->drawable_content_rect()); } +TEST_F(LayerTreeHostCommonTest, RoundedCornerBounds) { + // Layer Tree: + // +root + // +--render surface + // +----rounded corner layer 1 [should trigger render surface] + // +----layer 1 + // +--rounded corner layer 2 [should trigger render surface] + // +----layer 2 + // +------rounded corner layer 3 [should trigger render surface] + // +--------rounded corner layer 4 [should trigger render surface] + + constexpr int kRoundedCorner1Radius = 2; + constexpr int kRoundedCorner2Radius = 5; + constexpr int kRoundedCorner3Radius = 1; + constexpr int kRoundedCorner4Radius = 1; + + constexpr gfx::RectF kRoundedCornerLayer1Bound(15.f, 15.f, 20.f, 20.f); + constexpr gfx::RectF kRoundedCornerLayer2Bound(40.f, 40.f, 60.f, 60.f); + constexpr gfx::RectF kRoundedCornerLayer3Bound(0.f, 15.f, 5.f, 5.f); + constexpr gfx::RectF kRoundedCornerLayer4Bound(1.f, 1.f, 3.f, 3.f); + + constexpr float kDeviceScale = 1.6f; + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> render_surface = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_1 = Layer::Create(); + scoped_refptr<Layer> layer_1 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_2 = Layer::Create(); + scoped_refptr<Layer> layer_2 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_3 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_4 = Layer::Create(); + + // Set up layer tree + root->AddChild(render_surface); + root->AddChild(rounded_corner_layer_2); + + render_surface->AddChild(rounded_corner_layer_1); + render_surface->AddChild(layer_1); + + rounded_corner_layer_2->AddChild(layer_2); + + layer_2->AddChild(rounded_corner_layer_3); + + rounded_corner_layer_3->AddChild(rounded_corner_layer_4); + + // Set the root layer on host. + host()->SetRootLayer(root); + + // Set layer positions. + render_surface->SetPosition(gfx::PointF(0, 0)); + rounded_corner_layer_1->SetPosition(kRoundedCornerLayer1Bound.origin()); + layer_1->SetPosition(gfx::PointF(10.f, 10.f)); + rounded_corner_layer_2->SetPosition(kRoundedCornerLayer2Bound.origin()); + layer_2->SetPosition(gfx::PointF(30.f, 30.f)); + rounded_corner_layer_3->SetPosition(kRoundedCornerLayer3Bound.origin()); + rounded_corner_layer_4->SetPosition(kRoundedCornerLayer4Bound.origin()); + + // Set up layer bounds. + root->SetBounds(gfx::Size(100, 100)); + render_surface->SetBounds(gfx::Size(50, 50)); + rounded_corner_layer_1->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer1Bound.size())); + layer_1->SetBounds(gfx::Size(10, 10)); + rounded_corner_layer_2->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer2Bound.size())); + layer_2->SetBounds(gfx::Size(25, 25)); + rounded_corner_layer_3->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer3Bound.size())); + rounded_corner_layer_4->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer4Bound.size())); + + // Add Layer transforms. + gfx::Transform layer_2_transform; + constexpr gfx::Vector2dF kLayer2Translation(10.f, 10.f); + layer_2_transform.Translate(kLayer2Translation); + layer_2->SetTransform(layer_2_transform); + + gfx::Transform rounded_corner_layer_3_transform; + constexpr float kRoundedCorner3Scale = 2.f; + rounded_corner_layer_3_transform.Scale(kRoundedCorner3Scale, + kRoundedCorner3Scale); + rounded_corner_layer_3->SetTransform(rounded_corner_layer_3_transform); + + // Set the layer properties + render_surface->SetForceRenderSurfaceForTesting(true); + + root->SetIsDrawable(true); + render_surface->SetIsDrawable(true); + rounded_corner_layer_1->SetIsDrawable(true); + layer_1->SetIsDrawable(true); + rounded_corner_layer_2->SetIsDrawable(true); + layer_2->SetIsDrawable(true); + rounded_corner_layer_3->SetIsDrawable(true); + rounded_corner_layer_4->SetIsDrawable(true); + + // Set Rounded corners + rounded_corner_layer_1->SetRoundedCorner( + {kRoundedCorner1Radius, kRoundedCorner1Radius, kRoundedCorner1Radius, + kRoundedCorner1Radius}); + rounded_corner_layer_2->SetRoundedCorner( + {kRoundedCorner2Radius, kRoundedCorner2Radius, kRoundedCorner2Radius, + kRoundedCorner2Radius}); + rounded_corner_layer_3->SetRoundedCorner( + {kRoundedCorner3Radius, kRoundedCorner3Radius, kRoundedCorner3Radius, + kRoundedCorner3Radius}); + rounded_corner_layer_4->SetRoundedCorner( + {kRoundedCorner4Radius, kRoundedCorner4Radius, kRoundedCorner4Radius, + kRoundedCorner4Radius}); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const EffectTree& effect_tree = + root->layer_tree_host()->property_trees()->effect_tree; + + // Since this effect node has no descendants that draw and no descendant that + // has a rounded corner, it does not need a render surface. + const EffectNode* effect_node = + effect_tree.Node(rounded_corner_layer_1->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), + kRoundedCorner1Radius); + EXPECT_EQ(rounded_corner_bounds_1.rect(), + gfx::RectF(kRoundedCornerLayer1Bound.size())); + + // Since this node has descendants with roudned corners, it needs a render + // surface. It also has 2 descendants that draw. + effect_node = effect_tree.Node(rounded_corner_layer_2->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), + kRoundedCorner2Radius); + EXPECT_EQ(rounded_corner_bounds_2.rect(), + gfx::RectF(kRoundedCornerLayer2Bound.size())); + + // Since this node has a descendant that has a rounded corner, it will trigger + // the creation of a render surface. + effect_node = effect_tree.Node(rounded_corner_layer_3->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_3 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_3.GetSimpleRadius(), + kRoundedCorner3Radius); + EXPECT_EQ(rounded_corner_bounds_3.rect(), + gfx::RectF(kRoundedCornerLayer3Bound.size())); + + // Since this node has no descendants that draw nor any descendant that has a + // rounded corner, it does not need a render surface. + effect_node = effect_tree.Node(rounded_corner_layer_4->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_4 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_4.GetSimpleRadius(), + kRoundedCorner4Radius); + EXPECT_EQ(rounded_corner_bounds_4.rect(), + gfx::RectF(kRoundedCornerLayer4Bound.size())); + + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + // 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. + root->layer_tree_host()->PushLayerTreePropertiesTo(host()->pending_tree()); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + // Get the layer impl for each Layer. + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* rounded_corner_layer_1_impl = + layer_tree_impl->LayerById(rounded_corner_layer_1->id()); + LayerImpl* rounded_corner_layer_2_impl = + layer_tree_impl->LayerById(rounded_corner_layer_2->id()); + LayerImpl* rounded_corner_layer_3_impl = + layer_tree_impl->LayerById(rounded_corner_layer_3->id()); + LayerImpl* rounded_corner_layer_4_impl = + layer_tree_impl->LayerById(rounded_corner_layer_4->id()); + + // Set the root layer on host. + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + // Rounded corner layer 1 + // The render target for this layer is |render_surface|, hence its target + // bounds are relative to |render_surface|. + // The offset from the origin of the render target is [15, 15] and the device + // scale factor is 1.6 thus giving the target space origin of [24, 24]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_rrect_1 = + rounded_corner_layer_1_impl->draw_properties().rounded_corner_bounds; + gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_rrect_1.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_rrect_1.GetSimpleRadius(), + kRoundedCorner1Radius * kDeviceScale); + + // Rounded corner layer 2 + // The render target for this layer is |root|. + // The offset from the origin of the render target is [40, 40] and the device + // scale factor is 1.6 thus giving the target space origin of [64, 64]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_2 = + rounded_corner_layer_2_impl->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_2.IsEmpty()); + + bounds_in_target_space = kRoundedCornerLayer2Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_2 = + rounded_corner_layer_2_impl->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_2.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_2.GetSimpleRadius(), + kRoundedCorner2Radius * kDeviceScale); + + // Rounded corner layer 3 + // The render target for this layer is |rounded_corner_2|. + // The net offset from the origin of the render target is [40, 55] and the + // device scale factor is 1.6 thus giving the target space origin of [64, 88]. + // The corner radius is also scaled by a factor of 1.6 * transform scale. + const gfx::RRectF actual_self_rrect_3 = + rounded_corner_layer_3_impl->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_3.IsEmpty()); + + bounds_in_target_space = kRoundedCornerLayer3Bound; + bounds_in_target_space += + layer_2->position().OffsetFromOrigin() + kLayer2Translation; + bounds_in_target_space.Scale(kDeviceScale); + gfx::SizeF transformed_size = bounds_in_target_space.size(); + transformed_size.Scale(kRoundedCorner3Scale); + bounds_in_target_space.set_size(transformed_size); + + const gfx::RRectF actual_render_target_rrect_3 = + rounded_corner_layer_3_impl->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_3.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_3.GetSimpleRadius(), + kRoundedCorner3Radius * kDeviceScale * kRoundedCorner3Scale); + + // Rounded corner layer 4 + // The render target for this layer is |rounded_corner_3|. + // The net offset from the origin of the render target is [1, 1] and the + // net scale is 1.6 * transform scale = 3.2 thus giving the target space o + // rigin of [3.2, 3.2]. + // The corner radius is also scaled by a factor of 3.2. + const gfx::RRectF actual_rrect_4 = + rounded_corner_layer_4_impl->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer4Bound; + bounds_in_target_space.Scale(kDeviceScale * kRoundedCorner3Scale); + EXPECT_EQ(actual_rrect_4.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_rrect_4.GetSimpleRadius(), + kRoundedCorner4Radius * kDeviceScale * kRoundedCorner3Scale); +} + +TEST_F(LayerTreeHostCommonTest, RoundedCornerBoundsInterveningRenderTarget) { + // Layer Tree: + // +root + // +--rounded corner layer 1 [should not trigger render surface] + // +----render surface [Does not draw] + // +------rounded corner layer 2 [should not trigger render surface] + + constexpr int kRoundedCorner1Radius = 2; + constexpr int kRoundedCorner2Radius = 5; + + constexpr gfx::RectF kRoundedCornerLayer1Bound(60.f, 0.f, 40.f, 30.f); + constexpr gfx::RectF kRoundedCornerLayer2Bound(0.f, 0.f, 30.f, 20.f); + + constexpr float kDeviceScale = 1.6f; + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> render_surface = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_1 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_2 = Layer::Create(); + + // Set up layer tree + root->AddChild(rounded_corner_layer_1); + rounded_corner_layer_1->AddChild(render_surface); + render_surface->AddChild(rounded_corner_layer_2); + + // Set the root layer on host. + host()->SetRootLayer(root); + + // Set layer positions. + rounded_corner_layer_1->SetPosition(kRoundedCornerLayer1Bound.origin()); + render_surface->SetPosition(gfx::PointF(0, 0)); + rounded_corner_layer_2->SetPosition(kRoundedCornerLayer2Bound.origin()); + + // Set up layer bounds. + root->SetBounds(gfx::Size(100, 100)); + rounded_corner_layer_1->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer1Bound.size())); + render_surface->SetBounds(gfx::Size(30, 30)); + rounded_corner_layer_2->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer2Bound.size())); + + // Set the layer properties + render_surface->SetForceRenderSurfaceForTesting(true); + + root->SetIsDrawable(true); + rounded_corner_layer_1->SetIsDrawable(true); + rounded_corner_layer_2->SetIsDrawable(true); + + // Set Rounded corners + rounded_corner_layer_1->SetRoundedCorner( + {kRoundedCorner1Radius, kRoundedCorner1Radius, kRoundedCorner1Radius, + kRoundedCorner1Radius}); + rounded_corner_layer_2->SetRoundedCorner( + {kRoundedCorner2Radius, kRoundedCorner2Radius, kRoundedCorner2Radius, + kRoundedCorner2Radius}); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const EffectTree& effect_tree = + root->layer_tree_host()->property_trees()->effect_tree; + + // Since this effect node has only 1 descendant that draws and no descendant + // that has a rounded corner before the render surface, it does not need a + // render surface. + const EffectNode* effect_node = + effect_tree.Node(rounded_corner_layer_1->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), + kRoundedCorner1Radius); + EXPECT_EQ(rounded_corner_bounds_1.rect(), + gfx::RectF(kRoundedCornerLayer1Bound.size())); + + // Since this effect node has no descendants that draw and no descendant that + // has a rounded corner, it does not need a render surface. + effect_node = effect_tree.Node(rounded_corner_layer_2->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), + kRoundedCorner2Radius); + EXPECT_EQ(rounded_corner_bounds_2.rect(), + gfx::RectF(kRoundedCornerLayer2Bound.size())); + + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + // 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. + root->layer_tree_host()->PushLayerTreePropertiesTo(host()->pending_tree()); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + // Get the layer impl for each Layer. + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* rounded_corner_layer_1_impl = + layer_tree_impl->LayerById(rounded_corner_layer_1->id()); + LayerImpl* rounded_corner_layer_2_impl = + layer_tree_impl->LayerById(rounded_corner_layer_2->id()); + + // Set the root layer on host. + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + // Rounded corner layer 1 + // The render target for this layer is |root|, hence its target + // bounds are relative to |root|. + // The offset from the origin of the render target is [60, 0] and the device + // scale factor is 1.6 thus giving the target space origin of [96, 0]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_rrect_1 = + rounded_corner_layer_1_impl->draw_properties().rounded_corner_bounds; + gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_rrect_1.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_rrect_1.GetSimpleRadius(), + kRoundedCorner1Radius * kDeviceScale); + + // Rounded corner layer 2 + // The render target for this layer is |render_surface|. + // The offset from the origin of the render target is [0, 0]. + const gfx::RRectF actual_rrect_2 = + rounded_corner_layer_2_impl->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer2Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_rrect_2.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_rrect_2.GetSimpleRadius(), + kRoundedCorner2Radius * kDeviceScale); +} + +TEST_F(LayerTreeHostCommonTest, RoundedCornerBoundsSiblingRenderTarget) { + // Layer Tree: + // +root + // +--rounded corner layer 1 [should trigger render surface] + // +----render surface [Does not draw] + // +----rounded corner layer 2 [should not trigger render surface] + + constexpr int kRoundedCorner1Radius = 2; + constexpr int kRoundedCorner2Radius = 5; + + constexpr gfx::RectF kRoundedCornerLayer1Bound(0.f, 60.f, 30.f, 40.f); + constexpr gfx::RectF kRoundedCornerLayer2Bound(0.f, 0.f, 20.f, 30.f); + + constexpr float kDeviceScale = 1.6f; + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> render_surface = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_1 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_2 = Layer::Create(); + + // Set up layer tree + root->AddChild(rounded_corner_layer_1); + rounded_corner_layer_1->AddChild(render_surface); + rounded_corner_layer_1->AddChild(rounded_corner_layer_2); + + // Set the root layer on host. + host()->SetRootLayer(root); + + // Set layer positions. + rounded_corner_layer_1->SetPosition(kRoundedCornerLayer1Bound.origin()); + render_surface->SetPosition(gfx::PointF(0, 0)); + rounded_corner_layer_2->SetPosition(kRoundedCornerLayer2Bound.origin()); + + // Set up layer bounds. + root->SetBounds(gfx::Size(100, 100)); + rounded_corner_layer_1->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer1Bound.size())); + render_surface->SetBounds(gfx::Size(30, 30)); + rounded_corner_layer_2->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer2Bound.size())); + + // Set the layer properties + render_surface->SetForceRenderSurfaceForTesting(true); + + root->SetIsDrawable(true); + rounded_corner_layer_1->SetIsDrawable(true); + rounded_corner_layer_2->SetIsDrawable(true); + + // Set Rounded corners + rounded_corner_layer_1->SetRoundedCorner( + {kRoundedCorner1Radius, kRoundedCorner1Radius, kRoundedCorner1Radius, + kRoundedCorner1Radius}); + rounded_corner_layer_2->SetRoundedCorner( + {kRoundedCorner2Radius, kRoundedCorner2Radius, kRoundedCorner2Radius, + kRoundedCorner2Radius}); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const EffectTree& effect_tree = + root->layer_tree_host()->property_trees()->effect_tree; + + // Since this effect node has 1 descendant with a rounded corner without a + // render surface along the chain, it need a render surface. + const EffectNode* effect_node = + effect_tree.Node(rounded_corner_layer_1->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), + kRoundedCorner1Radius); + EXPECT_EQ(rounded_corner_bounds_1.rect(), + gfx::RectF(kRoundedCornerLayer1Bound.size())); + + // Since this effect node has no descendants that draw and no descendant that + // has a rounded corner, it does not need a render surface. + effect_node = effect_tree.Node(rounded_corner_layer_2->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), + kRoundedCorner2Radius); + EXPECT_EQ(rounded_corner_bounds_2.rect(), + gfx::RectF(kRoundedCornerLayer2Bound.size())); + + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + // 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. + root->layer_tree_host()->PushLayerTreePropertiesTo(host()->pending_tree()); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + // Get the layer impl for each Layer. + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* rounded_corner_layer_1_impl = + layer_tree_impl->LayerById(rounded_corner_layer_1->id()); + LayerImpl* rounded_corner_layer_2_impl = + layer_tree_impl->LayerById(rounded_corner_layer_2->id()); + + // Set the root layer on host. + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + // Rounded corner layer 1 + // The render target for this layer is |root|, hence its target + // bounds are relative to |root|. + // The offset from the origin of the render target is [0, 60] and the device + // scale factor is 1.6 thus giving the target space origin of [0, 96]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_1 = + rounded_corner_layer_1_impl->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_1.IsEmpty()); + + gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_1 = + rounded_corner_layer_1_impl->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_1.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_1.GetSimpleRadius(), + kRoundedCorner1Radius * kDeviceScale); + + // Rounded corner layer 2 + // The render target for this layer is |render_surface|. + // The offset from the origin of the render target is [0, 0]. + const gfx::RRectF actual_rrect_2 = + rounded_corner_layer_2_impl->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer2Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_rrect_2.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_rrect_2.GetSimpleRadius(), + kRoundedCorner2Radius * kDeviceScale); +} + +TEST_F(LayerTreeHostCommonTest, FastRoundedCornerDoesNotTriggerRenderSurface) { + // Layer Tree: + // +root + // +--fast rounded corner layer [should not trigger render surface] + // +----layer 1 + // +----layer 2 + // +--rounded corner layer [should trigger render surface] + // +----layer 3 + // +----layer 4 + + constexpr int kRoundedCorner1Radius = 2; + constexpr int kRoundedCorner2Radius = 5; + + constexpr gfx::RectF kRoundedCornerLayer1Bound(0.f, 0.f, 50.f, 50.f); + constexpr gfx::RectF kRoundedCornerLayer2Bound(40.f, 40.f, 60.f, 60.f); + + constexpr float kDeviceScale = 1.6f; + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> fast_rounded_corner_layer = Layer::Create(); + scoped_refptr<Layer> layer_1 = Layer::Create(); + scoped_refptr<Layer> layer_2 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer = Layer::Create(); + scoped_refptr<Layer> layer_3 = Layer::Create(); + scoped_refptr<Layer> layer_4 = Layer::Create(); + + // Set up layer tree + root->AddChild(fast_rounded_corner_layer); + root->AddChild(rounded_corner_layer); + + fast_rounded_corner_layer->AddChild(layer_1); + fast_rounded_corner_layer->AddChild(layer_2); + + rounded_corner_layer->AddChild(layer_3); + rounded_corner_layer->AddChild(layer_4); + + // Set the root layer on host. + host()->SetRootLayer(root); + + // Set layer positions. + fast_rounded_corner_layer->SetPosition(kRoundedCornerLayer1Bound.origin()); + layer_1->SetPosition(gfx::PointF(0.f, 0.f)); + layer_2->SetPosition(gfx::PointF(25.f, 0.f)); + rounded_corner_layer->SetPosition(kRoundedCornerLayer2Bound.origin()); + layer_3->SetPosition(gfx::PointF(0.f, 0.f)); + layer_4->SetPosition(gfx::PointF(30.f, 0.f)); + + // Set up layer bounds. + root->SetBounds(gfx::Size(100, 100)); + fast_rounded_corner_layer->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer1Bound.size())); + layer_1->SetBounds(gfx::Size(25, 25)); + layer_2->SetBounds(gfx::Size(25, 25)); + rounded_corner_layer->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer2Bound.size())); + layer_3->SetBounds(gfx::Size(30, 60)); + layer_4->SetBounds(gfx::Size(30, 60)); + + root->SetIsDrawable(true); + fast_rounded_corner_layer->SetIsDrawable(true); + layer_1->SetIsDrawable(true); + layer_2->SetIsDrawable(true); + rounded_corner_layer->SetIsDrawable(true); + layer_3->SetIsDrawable(true); + layer_4->SetIsDrawable(true); + + // Set Rounded corners + fast_rounded_corner_layer->SetRoundedCorner( + {kRoundedCorner1Radius, kRoundedCorner1Radius, kRoundedCorner1Radius, + kRoundedCorner1Radius}); + rounded_corner_layer->SetRoundedCorner( + {kRoundedCorner2Radius, kRoundedCorner2Radius, kRoundedCorner2Radius, + kRoundedCorner2Radius}); + + fast_rounded_corner_layer->SetIsFastRoundedCorner(true); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const EffectTree& effect_tree = + root->layer_tree_host()->property_trees()->effect_tree; + + // Since this layer has a fast rounded corner, it should not have a render + // surface even though it has 2 layers in the subtree that draws content. + const EffectNode* effect_node = + effect_tree.Node(fast_rounded_corner_layer->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_TRUE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), + kRoundedCorner1Radius); + EXPECT_EQ(rounded_corner_bounds_1.rect(), + gfx::RectF(kRoundedCornerLayer1Bound.size())); + + // Since this node has 2 descendants that draw, it will have a rounded corner. + effect_node = effect_tree.Node(rounded_corner_layer->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), + kRoundedCorner2Radius); + EXPECT_EQ(rounded_corner_bounds_2.rect(), + gfx::RectF(kRoundedCornerLayer2Bound.size())); + + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + // 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. + root->layer_tree_host()->PushLayerTreePropertiesTo(host()->pending_tree()); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + // Get the layer impl for each Layer. + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* fast_rounded_corner_layer_impl = + layer_tree_impl->LayerById(fast_rounded_corner_layer->id()); + LayerImpl* layer_1_impl = layer_tree_impl->LayerById(layer_1->id()); + LayerImpl* layer_2_impl = layer_tree_impl->LayerById(layer_2->id()); + LayerImpl* rounded_corner_layer_impl = + layer_tree_impl->LayerById(rounded_corner_layer->id()); + LayerImpl* layer_3_impl = layer_tree_impl->LayerById(layer_3->id()); + LayerImpl* layer_4_impl = layer_tree_impl->LayerById(layer_4->id()); + + // Set the root layer on host. + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + // Fast rounded corner layer. + // The render target for this layer is |root|, hence its target bounds are + // relative to |root|. + // The offset from the origin of the render target is [0, 0] and the device + // scale factor is 1.6. + const gfx::RRectF actual_rrect_1 = + fast_rounded_corner_layer_impl->draw_properties().rounded_corner_bounds; + gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_rrect_1.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_rrect_1.GetSimpleRadius(), + kRoundedCorner1Radius * kDeviceScale); + + // Layer 1 and layer 2 rounded corner bounds + // This should have the same rounded corner boudns as fast rounded corner + // layer. + const gfx::RRectF layer_1_rrect = + layer_1_impl->draw_properties().rounded_corner_bounds; + const gfx::RRectF layer_2_rrect = + layer_2_impl->draw_properties().rounded_corner_bounds; + EXPECT_EQ(actual_rrect_1, layer_1_rrect); + EXPECT_EQ(actual_rrect_1, layer_2_rrect); + + // Rounded corner layer + // The render target for this layer is |root|. + // The offset from the origin of the render target is [40, 40] and the device + // scale factor is 1.6 thus giving the target space origin of [64, 64]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_2 = + rounded_corner_layer_impl->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_2.IsEmpty()); + + bounds_in_target_space = kRoundedCornerLayer2Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_2 = + rounded_corner_layer_impl->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_2.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_2.GetSimpleRadius(), + kRoundedCorner2Radius * kDeviceScale); + + // Layer 3 and layer 4 should have no rounded corner bounds set as their + // parent is a render surface. + const gfx::RRectF layer_3_rrect = + layer_3_impl->draw_properties().rounded_corner_bounds; + const gfx::RRectF layer_4_rrect = + layer_4_impl->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(layer_3_rrect.IsEmpty()); + EXPECT_TRUE(layer_4_rrect.IsEmpty()); +} + +TEST_F(LayerTreeHostCommonTest, + FastRoundedCornerTriggersRenderSurfaceInAncestor) { + // Layer Tree: + // +root + // +--rounded corner layer [1] [should trigger render surface] + // +----fast rounded corner layer [2] [should not trigger render surface] + // +--rounded corner layer [3] [should trigger render surface] + // +----rounded corner layer [4] [should not trigger render surface] + + constexpr int kRoundedCorner1Radius = 2; + constexpr int kRoundedCorner2Radius = 5; + constexpr int kRoundedCorner3Radius = 1; + constexpr int kRoundedCorner4Radius = 3; + + constexpr gfx::RectF kRoundedCornerLayer1Bound(5.f, 5.f, 50.f, 50.f); + constexpr gfx::RectF kRoundedCornerLayer2Bound(0.f, 0.f, 25.f, 25.f); + constexpr gfx::RectF kRoundedCornerLayer3Bound(40.f, 40.f, 60.f, 60.f); + constexpr gfx::RectF kRoundedCornerLayer4Bound(30.f, 0.f, 30.f, 60.f); + + constexpr float kDeviceScale = 1.6f; + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_1 = Layer::Create(); + scoped_refptr<Layer> fast_rounded_corner_layer_2 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_3 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_4 = Layer::Create(); + + // Set up layer tree + root->AddChild(rounded_corner_layer_1); + root->AddChild(rounded_corner_layer_3); + + rounded_corner_layer_1->AddChild(fast_rounded_corner_layer_2); + + rounded_corner_layer_3->AddChild(rounded_corner_layer_4); + + // Set the root layer on host. + host()->SetRootLayer(root); + + // Set layer positions. + rounded_corner_layer_1->SetPosition(kRoundedCornerLayer1Bound.origin()); + fast_rounded_corner_layer_2->SetPosition(kRoundedCornerLayer2Bound.origin()); + rounded_corner_layer_3->SetPosition(kRoundedCornerLayer3Bound.origin()); + rounded_corner_layer_4->SetPosition(kRoundedCornerLayer4Bound.origin()); + + // Set up layer bounds. + root->SetBounds(gfx::Size(100, 100)); + rounded_corner_layer_1->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer1Bound.size())); + fast_rounded_corner_layer_2->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer2Bound.size())); + rounded_corner_layer_3->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer3Bound.size())); + rounded_corner_layer_4->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer4Bound.size())); + + root->SetIsDrawable(true); + rounded_corner_layer_1->SetIsDrawable(true); + fast_rounded_corner_layer_2->SetIsDrawable(true); + rounded_corner_layer_3->SetIsDrawable(true); + rounded_corner_layer_4->SetIsDrawable(true); + + // Set Rounded corners + rounded_corner_layer_1->SetRoundedCorner( + {kRoundedCorner1Radius, kRoundedCorner1Radius, kRoundedCorner1Radius, + kRoundedCorner1Radius}); + fast_rounded_corner_layer_2->SetRoundedCorner( + {kRoundedCorner2Radius, kRoundedCorner2Radius, kRoundedCorner2Radius, + kRoundedCorner2Radius}); + rounded_corner_layer_3->SetRoundedCorner( + {kRoundedCorner3Radius, kRoundedCorner3Radius, kRoundedCorner3Radius, + kRoundedCorner3Radius}); + rounded_corner_layer_4->SetRoundedCorner( + {kRoundedCorner4Radius, kRoundedCorner4Radius, kRoundedCorner4Radius, + kRoundedCorner4Radius}); + + fast_rounded_corner_layer_2->SetIsFastRoundedCorner(true); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const EffectTree& effect_tree = + root->layer_tree_host()->property_trees()->effect_tree; + + // Since this layer has a descendant that has rounded corner, this node will + // require a render surface. + const EffectNode* effect_node = + effect_tree.Node(rounded_corner_layer_1->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), + kRoundedCorner1Radius); + EXPECT_EQ(rounded_corner_bounds_1.rect(), + gfx::RectF(kRoundedCornerLayer1Bound.size())); + + // Since this layer has no descendant with rounded corner or drawable, it will + // not have a render surface. + effect_node = + effect_tree.Node(fast_rounded_corner_layer_2->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_TRUE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), + kRoundedCorner2Radius); + EXPECT_EQ(rounded_corner_bounds_2.rect(), + gfx::RectF(kRoundedCornerLayer2Bound.size())); + + // Since this layer has 1 descendant with a rounded corner, it should have a + // render surface. + effect_node = effect_tree.Node(rounded_corner_layer_3->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_3 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_3.GetSimpleRadius(), + kRoundedCorner3Radius); + EXPECT_EQ(rounded_corner_bounds_3.rect(), + gfx::RectF(kRoundedCornerLayer3Bound.size())); + + // Since this layer no descendants, it would no thave a render pass. + effect_node = effect_tree.Node(rounded_corner_layer_4->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_4 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_4.GetSimpleRadius(), + kRoundedCorner4Radius); + EXPECT_EQ(rounded_corner_bounds_4.rect(), + gfx::RectF(kRoundedCornerLayer4Bound.size())); + + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + // 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. + root->layer_tree_host()->PushLayerTreePropertiesTo(host()->pending_tree()); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + // Get the layer impl for each Layer. + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* rounded_corner_layer_impl_1 = + layer_tree_impl->LayerById(rounded_corner_layer_1->id()); + LayerImpl* fast_rounded_corner_layer_impl_2 = + layer_tree_impl->LayerById(fast_rounded_corner_layer_2->id()); + LayerImpl* rounded_corner_layer_impl_3 = + layer_tree_impl->LayerById(rounded_corner_layer_3->id()); + LayerImpl* rounded_corner_layer_impl_4 = + layer_tree_impl->LayerById(rounded_corner_layer_4->id()); + + // Set the root layer on host. + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + // Rounded corner layer 1. + // The render target for this layer is |root|, hence its target bounds are + // relative to |root|. + // The offset from the origin of the render target is [5, 5] and the device + // scale factor is 1.6 giving a total offset of [8, 8]. + const gfx::RRectF actual_self_rrect_1 = + rounded_corner_layer_impl_1->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_1.IsEmpty()); + + gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_1 = + rounded_corner_layer_impl_1->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_1.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_1.GetSimpleRadius(), + kRoundedCorner1Radius * kDeviceScale); + + // Fast rounded corner layer 2 + // The render target for this layer is |rounded_corner_layer_1|. + // The offset from the origin of the render target is [0, 0] and the device + // scale factor is 1.6. The corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_2 = + fast_rounded_corner_layer_impl_2->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer2Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_self_rrect_2.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_self_rrect_2.GetSimpleRadius(), + kRoundedCorner2Radius * kDeviceScale); + + // Rounded corner layer 3 + // The render target for this layer is |root|. + // The offset from the origin of the render target is [40, 40] and the device + // scale factor is 1.6 thus giving the target space origin of [64, 64]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_3 = + rounded_corner_layer_impl_3->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_3.IsEmpty()); + + bounds_in_target_space = kRoundedCornerLayer3Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_3 = + rounded_corner_layer_impl_3->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_3.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_3.GetSimpleRadius(), + kRoundedCorner3Radius * kDeviceScale); + + // Rounded corner layer 4 + // The render target for this layer is |rounded_corner_layer_3|. + // The offset from the origin of the render target is [30, 0] and the device + // scale factor is 1.6 thus giving the target space origin of [48, 0]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_4 = + rounded_corner_layer_impl_4->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer4Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_self_rrect_4.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_self_rrect_4.GetSimpleRadius(), + kRoundedCorner4Radius * kDeviceScale); +} + +TEST_F(LayerTreeHostCommonTest, + FastRoundedCornerDoesNotTriggerRenderSurfaceFromSubtree) { + // Layer Tree: + // +root + // +--fast rounded corner layer 1 [should trigger render surface] + // +----rounded corner layer 1 [should not trigger render surface] + // +--rounded corner layer 2 [should trigger render surface] + // +----rounded corner layer 3 [should not trigger render surface] + constexpr int kRoundedCorner1Radius = 2; + constexpr int kRoundedCorner2Radius = 5; + constexpr int kRoundedCorner3Radius = 4; + constexpr int kRoundedCorner4Radius = 5; + + constexpr gfx::RectF kRoundedCornerLayer1Bound(10.f, 5.f, 45.f, 50.f); + constexpr gfx::RectF kRoundedCornerLayer2Bound(5.f, 5.f, 20.f, 20.f); + constexpr gfx::RectF kRoundedCornerLayer3Bound(60.f, 5.f, 40.f, 25.f); + constexpr gfx::RectF kRoundedCornerLayer4Bound(0.f, 10.f, 10.f, 20.f); + + constexpr float kDeviceScale = 1.6f; + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> fast_rounded_corner_layer_1 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_1 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_2 = Layer::Create(); + scoped_refptr<Layer> rounded_corner_layer_3 = Layer::Create(); + + // Set up layer tree + root->AddChild(fast_rounded_corner_layer_1); + root->AddChild(rounded_corner_layer_2); + + fast_rounded_corner_layer_1->AddChild(rounded_corner_layer_1); + rounded_corner_layer_2->AddChild(rounded_corner_layer_3); + + // Set the root layer on host. + host()->SetRootLayer(root); + + // Set layer positions. + fast_rounded_corner_layer_1->SetPosition(kRoundedCornerLayer1Bound.origin()); + rounded_corner_layer_1->SetPosition(kRoundedCornerLayer2Bound.origin()); + rounded_corner_layer_2->SetPosition(kRoundedCornerLayer3Bound.origin()); + rounded_corner_layer_3->SetPosition(kRoundedCornerLayer4Bound.origin()); + + // Set up layer bounds. + root->SetBounds(gfx::Size(100, 100)); + fast_rounded_corner_layer_1->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer1Bound.size())); + rounded_corner_layer_1->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer2Bound.size())); + rounded_corner_layer_2->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer3Bound.size())); + rounded_corner_layer_3->SetBounds( + gfx::ToRoundedSize(kRoundedCornerLayer4Bound.size())); + + root->SetIsDrawable(true); + fast_rounded_corner_layer_1->SetIsDrawable(true); + rounded_corner_layer_1->SetIsDrawable(true); + rounded_corner_layer_2->SetIsDrawable(true); + rounded_corner_layer_3->SetIsDrawable(true); + + // Set Rounded corners + fast_rounded_corner_layer_1->SetRoundedCorner( + {kRoundedCorner1Radius, kRoundedCorner1Radius, kRoundedCorner1Radius, + kRoundedCorner1Radius}); + rounded_corner_layer_1->SetRoundedCorner( + {kRoundedCorner2Radius, kRoundedCorner2Radius, kRoundedCorner2Radius, + kRoundedCorner2Radius}); + rounded_corner_layer_2->SetRoundedCorner( + {kRoundedCorner3Radius, kRoundedCorner3Radius, kRoundedCorner3Radius, + kRoundedCorner3Radius}); + rounded_corner_layer_3->SetRoundedCorner( + {kRoundedCorner4Radius, kRoundedCorner4Radius, kRoundedCorner4Radius, + kRoundedCorner4Radius}); + + fast_rounded_corner_layer_1->SetIsFastRoundedCorner(true); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const EffectTree& effect_tree = + root->layer_tree_host()->property_trees()->effect_tree; + + // Since this layer has a descendant with rounded corner, it needs a render + // surface. + const EffectNode* effect_node = + effect_tree.Node(fast_rounded_corner_layer_1->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_1 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_TRUE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_1.GetSimpleRadius(), + kRoundedCorner1Radius); + EXPECT_EQ(rounded_corner_bounds_1.rect(), + gfx::RectF(kRoundedCornerLayer1Bound.size())); + + // Since this layer has no descendant with rounded corner or drawable, it will + // not have a render surface. + effect_node = effect_tree.Node(rounded_corner_layer_1->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_2 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_2.GetSimpleRadius(), + kRoundedCorner2Radius); + EXPECT_EQ(rounded_corner_bounds_2.rect(), + gfx::RectF(kRoundedCornerLayer2Bound.size())); + + // Since this layer has a descendant with rounded corner, it should have a + // render surface. + effect_node = effect_tree.Node(rounded_corner_layer_2->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_3 = effect_node->rounded_corner_bounds; + EXPECT_TRUE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_3.GetSimpleRadius(), + kRoundedCorner3Radius); + EXPECT_EQ(rounded_corner_bounds_3.rect(), + gfx::RectF(kRoundedCornerLayer3Bound.size())); + + // Since this layer has no descendant, it does not need a render surface. + effect_node = effect_tree.Node(rounded_corner_layer_3->effect_tree_index()); + gfx::RRectF rounded_corner_bounds_4 = effect_node->rounded_corner_bounds; + EXPECT_FALSE(effect_node->has_render_surface); + EXPECT_FALSE(effect_node->is_fast_rounded_corner); + EXPECT_FLOAT_EQ(rounded_corner_bounds_4.GetSimpleRadius(), + kRoundedCorner4Radius); + EXPECT_EQ(rounded_corner_bounds_4.rect(), + gfx::RectF(kRoundedCornerLayer4Bound.size())); + + host()->host_impl()->CreatePendingTree(); + host()->CommitAndCreatePendingTree(); + // 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. + root->layer_tree_host()->PushLayerTreePropertiesTo(host()->pending_tree()); + host()->host_impl()->ActivateSyncTree(); + LayerTreeImpl* layer_tree_impl = host()->host_impl()->active_tree(); + + // Get the layer impl for each Layer. + LayerImpl* root_impl = layer_tree_impl->LayerById(root->id()); + LayerImpl* fast_rounded_corner_layer_impl_1 = + layer_tree_impl->LayerById(fast_rounded_corner_layer_1->id()); + LayerImpl* rounded_corner_layer_impl_1 = + layer_tree_impl->LayerById(rounded_corner_layer_1->id()); + LayerImpl* rounded_corner_layer_impl_2 = + layer_tree_impl->LayerById(rounded_corner_layer_2->id()); + LayerImpl* rounded_corner_layer_impl_3 = + layer_tree_impl->LayerById(rounded_corner_layer_3->id()); + + // Set the root layer on host. + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + // Fast rounded corner layer 1. + // The render target for this layer is |root|, hence its target bounds are + // relative to |root|. + // The offset from the origin of the render target is [5, 5] and the device + // scale factor is 1.6. + const gfx::RRectF actual_self_rrect_1 = + fast_rounded_corner_layer_impl_1->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_1.IsEmpty()); + + gfx::RectF bounds_in_target_space = kRoundedCornerLayer1Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_1 = + fast_rounded_corner_layer_impl_1->render_target() + ->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_1.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_1.GetSimpleRadius(), + kRoundedCorner1Radius * kDeviceScale); + + // Rounded corner layer 1 + // The render target for this layer is |fast_rounded_corner_layer_1|. + // The offset from the origin of the render target is [0, 0] and the device + // scale factor is 1.6. The corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_2 = + rounded_corner_layer_impl_1->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer2Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_self_rrect_2.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_self_rrect_2.GetSimpleRadius(), + kRoundedCorner2Radius * kDeviceScale); + + // Rounded corner layer 3 + // The render target for this layer is |root|. + // The offset from the origin of the render target is [5, 5] and the device + // scale factor is 1.6 thus giving the target space origin of [8, 8]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_3 = + rounded_corner_layer_impl_2->draw_properties().rounded_corner_bounds; + EXPECT_TRUE(actual_self_rrect_3.IsEmpty()); + + bounds_in_target_space = kRoundedCornerLayer3Bound; + bounds_in_target_space.Scale(kDeviceScale); + const gfx::RRectF actual_render_target_rrect_3 = + rounded_corner_layer_impl_2->render_target()->rounded_corner_bounds(); + EXPECT_EQ(actual_render_target_rrect_3.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_render_target_rrect_3.GetSimpleRadius(), + kRoundedCorner3Radius * kDeviceScale); + + // Rounded corner layer 4 + // The render target for this layer is |rounded_corner_layer_2|. + // The offset from the origin of the render target is [0, 5] and the device + // scale factor is 1.6 thus giving the target space origin of [0, 8]. The + // corner radius is also scaled by a factor of 1.6. + const gfx::RRectF actual_self_rrect_4 = + rounded_corner_layer_impl_3->draw_properties().rounded_corner_bounds; + bounds_in_target_space = kRoundedCornerLayer4Bound; + bounds_in_target_space.Scale(kDeviceScale); + EXPECT_EQ(actual_self_rrect_4.rect(), bounds_in_target_space); + EXPECT_FLOAT_EQ(actual_self_rrect_4.GetSimpleRadius(), + kRoundedCorner4Radius * kDeviceScale); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index e6b65ce1144..f9e0cb0c095 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -60,6 +60,7 @@ #include "cc/resources/memory_history.h" #include "cc/resources/resource_pool.h" #include "cc/resources/ui_resource_bitmap.h" +#include "cc/scheduler/compositor_frame_reporting_controller.h" #include "cc/tiles/eviction_tile_priority_queue.h" #include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/tiles/gpu_image_decode_cache.h" @@ -123,6 +124,13 @@ namespace { // V1 saw errors of ~0.065 between computed window and content widths. const float kMobileViewportWidthEpsilon = 0.15f; +// In BuildHitTestData we iterate all layers to find all layers that overlap +// OOPIFs, but when the number of layers is greater than +// |kAssumeOverlapThreshold|, it can be inefficient to accumulate layer bounds +// for overlap checking. As a result, we are conservative and make OOPIFs +// kHitTestAsk after the threshold is reached. +const size_t kAssumeOverlapThreshold = 100; + bool HasFixedPageScale(LayerTreeImpl* active_tree) { return active_tree->min_page_scale_factor() == active_tree->max_page_scale_factor(); @@ -295,6 +303,8 @@ LayerTreeHostImpl::LayerTreeHostImpl( : client_(client), task_runner_provider_(task_runner_provider), current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), + compositor_frame_reporting_controller_( + std::make_unique<CompositorFrameReportingController>()), settings_(settings), is_synchronous_single_threaded_(!task_runner_provider->HasImplThread() && !settings_.single_thread_proxy_scheduler), @@ -319,7 +329,6 @@ LayerTreeHostImpl::LayerTreeHostImpl( task_graph_runner_(task_graph_runner), id_(id), consecutive_frame_with_damage_count_(settings.damaged_frame_limit), - scroll_animating_latched_element_id_(kInvalidElementId), // It is safe to use base::Unretained here since we will outlive the // ImageAnimationController. image_animation_controller_(GetTaskRunner(), @@ -329,6 +338,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( skipped_frame_tracker_(&frame_metrics_), is_animating_for_snap_(false), paint_image_generator_client_id_(PaintImage::GetNextGeneratorClientId()), + scrollbar_controller_(std::make_unique<ScrollbarController>(this)), scroll_gesture_did_end_(false) { DCHECK(mutator_host_); mutator_host_->SetMutatorHostClient(this); @@ -759,7 +769,7 @@ LayerTreeHostImpl::EventListenerTypeForTouchStartOrMoveAt( gfx::PointF(planar_point.x(), planar_point.y()); const auto& region = layer_impl_with_touch_handler->touch_action_region(); gfx::Point point = gfx::ToRoundedPoint(hit_test_point_in_layer_space); - *out_touch_action = region.GetWhiteListedTouchAction(point); + *out_touch_action = region.GetAllowedTouchAction(point); } if (!CurrentlyScrollingNode()) @@ -906,9 +916,9 @@ static void AppendQuadsToFillScreen( viz::SharedQuadState* shared_quad_state = target_render_pass->CreateAndAppendSharedQuadState(); shared_quad_state->SetAll(gfx::Transform(), root_target_rect, - root_target_rect, root_target_rect, false, - are_contents_opaque, opacity, SkBlendMode::kSrcOver, - sorting_context_id); + root_target_rect, gfx::RRectF(), root_target_rect, + false, are_contents_opaque, opacity, + SkBlendMode::kSrcOver, sorting_context_id); for (gfx::Rect screen_space_rect : fill_region) { gfx::Rect visible_screen_space_rect = screen_space_rect; @@ -1329,8 +1339,7 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { // an animation worklet is asked to produce its output at the beginning of the // frame along side other animations but its output arrives asynchronously so // we tick worklet animations and apply that output here instead. - base::TimeTicks monotonic_time = CurrentBeginFrameArgs().frame_time; - mutator_host_->TickWorkletAnimations(monotonic_time); + mutator_host_->TickWorkletAnimations(); bool ok = active_tree_->UpdateDrawProperties(); DCHECK(ok) << "UpdateDrawProperties failed during draw"; @@ -1347,11 +1356,9 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { frame->may_contain_video = false; if (active_tree_->RootRenderSurface()) { - gfx::Rect device_viewport_damage_rect = viewport_damage_rect_; - viewport_damage_rect_ = gfx::Rect(); - active_tree_->RootRenderSurface()->damage_tracker()->AddDamageNextUpdate( - device_viewport_damage_rect); + viewport_damage_rect_); + viewport_damage_rect_ = gfx::Rect(); } DrawResult draw_result = CalculateRenderPasses(frame); @@ -2087,6 +2094,12 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( debug_state_); } + TRACE_EVENT_INSTANT2("cc", "Scroll Delta This Frame", + TRACE_EVENT_SCOPE_THREAD, "x", + scroll_accumulated_this_frame_.x(), "y", + scroll_accumulated_this_frame_.y()); + scroll_accumulated_this_frame_ = gfx::ScrollOffset(); + bool is_new_trace; TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); if (is_new_trace) { @@ -2599,6 +2612,8 @@ static void PopulateHitTestRegion(viz::HitTestRegion* hit_test_region, } base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { + TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildHitTestData"); + if (!settings_.build_hit_test_data) return {}; @@ -2612,8 +2627,19 @@ base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { float device_scale_factor = active_tree()->device_scale_factor(); Region overlapping_region; + size_t num_iterated_layers = 0; + // If the layer tree contains more than 100 layers, we stop accumulating + // layers in |overlapping_region| to save compositor frame submitting time, as + // a result we do async hit test on any surface layers that + bool assume_overlap = false; for (const auto* layer : base::Reversed(*active_tree())) { - if (!layer->ShouldHitTest()) + // Viz hit test needs to collect information for pointer-events: none OOPIFs + // as well. Now Layer::HitTestable ignores pointer-events property, but this + // early out will not work correctly if we integrate has_pointer_events_none + // into Layer::HitTestable, so we make sure we don't skip surface layers + // that draws content but has pointer-events: none property. + if (!(layer->HitTestable() || + (layer->is_surface_layer() && layer->DrawsContent()))) continue; if (layer->is_surface_layer()) { @@ -2621,11 +2647,11 @@ base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { // If a surface layer is created not by child frame compositor or the // frame owner has pointer-events: none property, the surface layer // becomes not hit testable. We should not generate data for it. - if (!surface_layer->ShouldGenerateSurfaceHitTestData()) { - // If a surface layer is created due to video or offscreen canvas, it - // can still block overlapped surface layers from getting events, we - // need to account for all layers that don't have pointer-events: none. - if (!surface_layer->has_pointer_events_none()) { + if (!surface_layer->surface_hit_testable() || + !surface_layer->range().IsValid()) { + // We collect any overlapped regions that does not have pointer-events: + // none. + if (!surface_layer->has_pointer_events_none() && !assume_overlap) { overlapping_region.Union(MathUtil::MapEnclosingClippedRect( layer->ScreenSpaceTransform(), gfx::Rect(surface_layer->bounds()))); @@ -2643,15 +2669,18 @@ base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { auto flag = GetFlagsForSurfaceLayer(surface_layer); uint32_t async_hit_test_reasons = viz::AsyncHitTestReasons::kNotAsyncHitTest; - if (overlapping_region.Intersects(layer_screen_space_rect)) { + if (surface_layer->has_pointer_events_none()) + flag |= viz::HitTestRegionFlags::kHitTestIgnore; + if (assume_overlap || + overlapping_region.Intersects(layer_screen_space_rect)) { flag |= viz::HitTestRegionFlags::kHitTestAsk; async_hit_test_reasons |= viz::AsyncHitTestReasons::kOverlappedRegion; } bool layer_hit_test_region_is_masked = active_tree() ->property_trees() - ->effect_tree.Node(surface_layer->effect_tree_index()) - ->is_masked; + ->effect_tree.HitTestMayBeAffectedByMask( + surface_layer->effect_tree_index()); if (surface_layer->is_clipped() || layer_hit_test_region_is_masked) { bool layer_hit_test_region_is_rectangle = !layer_hit_test_region_is_masked && @@ -2677,8 +2706,13 @@ base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { } // TODO(sunxd): Submit all overlapping layer bounds as hit test regions. // Also investigate if we can use visible layer rect as overlapping regions. - overlapping_region.Union(MathUtil::MapEnclosingClippedRect( - layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds()))); + num_iterated_layers++; + if (num_iterated_layers > kAssumeOverlapThreshold) + assume_overlap = true; + if (!assume_overlap) { + overlapping_region.Union(MathUtil::MapEnclosingClippedRect( + layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds()))); + } } return hit_test_region_list; @@ -3441,13 +3475,20 @@ InputHandler::ScrollStatus LayerTreeHostImpl::TryScroll( LayerImpl* layer = active_tree_->ScrollableLayerByElementId(scroll_node->element_id); - // We may not find an associated layer for the root or secondary root node - - // that's fine, they're not associated with any elements on the page. We also - // won't find a layer for the inner viewport (in CompositeAfterPaint) since it - // doesn't require hit testing. - DCHECK(layer || scroll_node->id == ScrollTree::kRootNodeId || - scroll_node->id == ScrollTree::kSecondaryRootNodeId || - scroll_node->scrolls_inner_viewport); + // If an associated scrolling layer is not found, the scroll node must not + // support impl-scrolling. The root, secondary root, and inner viewports are + // all exceptions to this and may not have a layer because it is not required + // for hit testing. + if (!layer && scroll_node->id != ScrollTree::kRootNodeId && + scroll_node->id != ScrollTree::kSecondaryRootNodeId && + !scroll_node->scrolls_inner_viewport) { + TRACE_EVENT0("cc", + "LayerImpl::tryScroll: Failed due to no scrolling layer"); + scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD; + scroll_status.main_thread_scrolling_reasons = + MainThreadScrollingReason::kNonFastScrollableRegion; + return scroll_status; + } if (layer && !layer->non_fast_scrollable_region().IsEmpty()) { bool clipped = false; @@ -3526,7 +3567,19 @@ ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint( ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* impl_scroll_node = nullptr; if (layer_impl) { - ScrollNode* scroll_node = scroll_tree.Node(layer_impl->scroll_tree_index()); + // If this is a scrollbar layer, we can't directly use the associated + // scroll_node (because the scroll_node associated with this layer will be + // the owning scroller's parent). Instead, we first retrieve the scrollable + // layer corresponding to the scrollbars owner and then use its + // scroll_tree_index instead. + int scroll_tree_index = layer_impl->scroll_tree_index(); + if (layer_impl->ToScrollbarLayer()) { + LayerImpl* owner_scroll_layer = active_tree_->ScrollableLayerByElementId( + layer_impl->ToScrollbarLayer()->scroll_element_id()); + scroll_tree_index = owner_scroll_layer->scroll_tree_index(); + } + + ScrollNode* scroll_node = scroll_tree.Node(scroll_tree_index); for (; scroll_tree.parent(scroll_node); scroll_node = scroll_tree.parent(scroll_node)) { // The content layer can also block attempts to scroll outside the main @@ -3744,19 +3797,43 @@ bool LayerTreeHostImpl::IsTouchDraggingScrollbar( } // Initial scroll hit testing can be unreliable in the presence of squashed -// layers. In this case, we fall back to main thread scrolling. +// layers. In this case, we fall back to main thread scrolling. This function +// compares |layer_impl| returned from a regular hit test to the layer +// returned from a hit test performed only on scrollers and scrollbars. If the +// closest scrolling ancestor of |layer_impl| is not the other layer, then the +// layer_impl must be a squasing layer overtop of some other scroller and we +// must rely on the main thread. +// +// Note, position: fixed layers use the inner viewport as their ScrollNode +// (since they don't scroll with the outer viewport), however, scrolls from the +// fixed layer still chain to the outer viewport. It's also possible for a node +// to have the inner viewport as its ancestor without going through the outer +// viewport; however, it will still scroll using the viewport(). Hence, this +// method needs to use the same scroll chaining logic we use in ApplyScroll by +// looking at Viewport::ShouldScroll. bool LayerTreeHostImpl::IsInitialScrollHitTestReliable( LayerImpl* layer_impl, LayerImpl* first_scrolling_layer_or_scrollbar) { if (!first_scrolling_layer_or_scrollbar) return true; + + // Hit tests directly on a composited scrollbar are always reliable. + if (layer_impl->ToScrollbarLayer()) { + DCHECK(layer_impl == first_scrolling_layer_or_scrollbar); + return true; + } + ScrollNode* closest_scroll_node = nullptr; auto& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.Node(layer_impl->scroll_tree_index()); for (; scroll_tree.parent(scroll_node); scroll_node = scroll_tree.parent(scroll_node)) { if (scroll_node->scrollable) { - closest_scroll_node = scroll_node; + // Ensure we use scroll chaining behavior for the inner viewport node. + if (viewport()->ShouldScroll(*scroll_node)) + closest_scroll_node = viewport()->MainScrollNode(); + else + closest_scroll_node = scroll_node; break; } } @@ -3772,9 +3849,8 @@ bool LayerTreeHostImpl::IsInitialScrollHitTestReliable( first_scrolling_layer_or_scrollbar->scroll_tree_index(); } - // If |first_scrolling_layer_or_scrollbar| is not scrollable, it must - // be a drawn scrollbar. It may hit the squashing layer at the same time. - // These hit tests require falling back to main-thread scrolling. + // If |first_scrolling_layer_or_scrollbar| is not scrollable, it must be a + // scrollbar. It may hit the squashing layer at the same time. DCHECK(first_scrolling_layer_or_scrollbar->is_scrollbar()); return false; } @@ -3785,6 +3861,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; + deferred_scroll_end_state_.reset(); ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); if (scroll_node) { @@ -3809,6 +3886,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimatedBegin( scroll_status = ScrollBegin(scroll_state, WHEEL); if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { scroll_animating_latched_element_id_ = ElementId(); + scroll_animating_overscroll_target_element_id_ = ElementId(); ScrollStateData scroll_state_end_data; scroll_state_end_data.is_ending = true; ScrollState scroll_state_end(scroll_state_end_data); @@ -3893,6 +3971,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); + scroll_accumulated_this_frame_ += gfx::ScrollOffset(scroll_delta); + if (scroll_node) { // Flash the overlay scrollbar even if the scroll dalta is 0. if (settings_.scrollbar_flash_after_any_scroll_update) { @@ -4012,7 +4092,30 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated( break; } } + // Set overscroll event target since neither an ongoing scroll animation has + // been updated nor a new scroll animation has been created for the current + // GSU. + if (!scroll_animating_latched_element_id_) { + // When no scroll animation has been created during the current scroll + // sequence (i.e. scroll_animating_latched_element_id_ == ElementId()) we + // need to set last_scroller_element_id_ here since scrollEnd won't get + // called. + last_scroller_element_id_ = scroll_node->element_id; + // We will send the overscroll events to viewport or the last element in + // the cut chain when no scroll animation has been created during the + // current scroll sequence. + scroll_animating_overscroll_target_element_id_ = scroll_node->element_id; + } else { + // When a scroll animation has been created during the current scroll + // sequence, the overscroll events target should be the element that + // scrolling is latched to. + scroll_animating_overscroll_target_element_id_ = + scroll_animating_latched_element_id_; + } + overscroll_delta_for_main_thread_ += pending_delta; + client_->SetNeedsCommitOnImplThread(); } + scroll_state.set_is_ending(true); ScrollEndImpl(&scroll_state); if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { @@ -4180,21 +4283,17 @@ void LayerTreeHostImpl::ApplyScroll(ScrollNode* scroll_node, // details. const float kEpsilon = 0.1f; - bool scrolls_main_viewport_scroll_layer = - viewport()->MainScrollLayer() && - viewport()->MainScrollLayer()->scroll_tree_index() == scroll_node->id; - - // This is needed if the scroll chains up to the viewport without going - // through the outer viewport scroll node. This can happen if we scroll an - // element that's not a descendant of the document.rootScroller. In that case - // we want to scroll the inner viewport -- to allow panning while zoomed -- - // but also move browser controls if needed. - bool scrolls_inner_viewport = scroll_node->scrolls_inner_viewport; - - if (scrolls_main_viewport_scroll_layer || scrolls_inner_viewport) { + if (viewport()->ShouldScroll(*scroll_node)) { + // This will be false if the scroll chains up to the viewport without going + // through the outer viewport scroll node. This can happen if we scroll an + // element that's not a descendant of the document.rootScroller. In that + // case we want to scroll *only* the inner viewport -- to allow panning + // while zoomed -- but still use Viewport::ScrollBy to also move browser + // controls if needed. + bool scroll_outer_viewport = scroll_node->scrolls_outer_viewport; Viewport::ScrollResult result = viewport()->ScrollBy( delta, viewport_point, scroll_state->is_direct_manipulation(), - !wheel_scrolling_, scrolls_main_viewport_scroll_layer); + !wheel_scrolling_, scroll_outer_viewport); applied_delta = result.consumed_delta; delta_applied_to_content = result.content_scrolled_delta; @@ -4212,12 +4311,12 @@ void LayerTreeHostImpl::ApplyScroll(ScrollNode* scroll_node, // TODO(bokan): This preserves existing behavior by not allowing tiny // scrolls to produce overscroll but is inconsistent in how delta gets // chained up. We need to clean this up. - if (scrolls_main_viewport_scroll_layer) + if (scroll_node->scrolls_outer_viewport) scroll_state->ConsumeDelta(applied_delta.x(), applied_delta.y()); return; } - if (!scrolls_main_viewport_scroll_layer && !scrolls_inner_viewport) { + if (!viewport()->ShouldScroll(*scroll_node)) { // If the applied delta is within 45 degrees of the input // delta, bail out to make it easier to scroll just one layer // in one direction without affecting any of its parents. @@ -4353,6 +4452,9 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); auto& scroll_tree = active_tree_->property_trees()->scroll_tree; + scroll_accumulated_this_frame_ += + gfx::ScrollOffset(scroll_state->delta_x(), scroll_state->delta_y()); + ElementId provided_element = scroll_state->data()->current_native_scrolling_element(); const auto* provided_scroll_node = @@ -4493,7 +4595,15 @@ void LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset( TRACE_EVENT2("cc", "LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset", "offset_x", root_offset.x(), "offset_y", root_offset.y()); - bool changed = active_tree_->DistributeRootScrollOffset(root_offset); + + gfx::Vector2dF delta = root_offset.DeltaFrom(viewport()->TotalScrollOffset()); + bool changed = !viewport() + ->ScrollBy(delta, + /*viewport_point=*/gfx::Point(), + /*is_wheel_scroll=*/false, + /*affect_browser_controls=*/false, + /*scroll_outer_viewport=*/true) + .consumed_delta.IsZero(); if (!changed) return; @@ -4605,25 +4715,34 @@ void LayerTreeHostImpl::ScrollEndImpl(ScrollState* scroll_state) { DCHECK(scroll_state); DCHECK(scroll_state->delta_x() == 0 && scroll_state->delta_y() == 0); + // In smooth-scrolling path when the GSE arrives after scroll animation + // completion, CurrentlyScrollingNode() is already cleared due to + // ScrollEndImpl call inside ScrollOffsetAnimationFinished. In this case + // last_scroller_element_id_ is already set in the same ScrollEndImpl call and + // we should not reset it here. + if (!last_scroller_element_id_ && CurrentlyScrollingNode()) + last_scroller_element_id_ = CurrentlyScrollingNode()->element_id; + DistributeScrollDelta(scroll_state); browser_controls_offset_manager_->ScrollEnd(); ClearCurrentlyScrollingNode(); } void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) { - scroll_gesture_did_end_ = true; - last_scroller_element_id_ = CurrentlyScrollingNode() - ? CurrentlyScrollingNode()->element_id - : ElementId(); - client_->SetNeedsCommitOnImplThread(); - - if (should_snap && SnapAtScrollEnd()) + if ((should_snap && SnapAtScrollEnd()) || + mutator_host_->IsImplOnlyScrollAnimating()) { + DCHECK(!deferred_scroll_end_state_.has_value()); + deferred_scroll_end_state_ = *scroll_state; return; - + } ScrollEndImpl(scroll_state); + deferred_scroll_end_state_.reset(); + scroll_gesture_did_end_ = true; + client_->SetNeedsCommitOnImplThread(); } -void LayerTreeHostImpl::MouseDown() { +InputHandlerPointerResult LayerTreeHostImpl::MouseDown( + const gfx::PointF& viewport_point) { ScrollbarAnimationController* animation_controller = ScrollbarAnimationControllerForElementId( scroll_element_id_mouse_currently_over_); @@ -4632,9 +4751,16 @@ void LayerTreeHostImpl::MouseDown() { scroll_element_id_mouse_currently_captured_ = scroll_element_id_mouse_currently_over_; } + + InputHandlerPointerResult result; + if (settings().compositor_threaded_scrollbar_scrolling) + result = scrollbar_controller_->HandleMouseDown(viewport_point); + + return result; } -void LayerTreeHostImpl::MouseUp() { +InputHandlerPointerResult LayerTreeHostImpl::MouseUp( + const gfx::PointF& viewport_point) { if (scroll_element_id_mouse_currently_captured_) { ScrollbarAnimationController* animation_controller = ScrollbarAnimationControllerForElementId( @@ -4645,6 +4771,12 @@ void LayerTreeHostImpl::MouseUp() { if (animation_controller) animation_controller->DidMouseUp(); } + + InputHandlerPointerResult result; + if (settings().compositor_threaded_scrollbar_scrolling) + result = scrollbar_controller_->HandleMouseUp(viewport_point); + + return result; } void LayerTreeHostImpl::MouseMoveAt(const gfx::Point& viewport_point) { @@ -4776,12 +4908,13 @@ void LayerTreeHostImpl::CollectScrollbarUpdates( } std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { - std::unique_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet()); + auto scroll_info = std::make_unique<ScrollAndScaleSet>(); CollectScrollDeltas(scroll_info.get()); CollectScrollbarUpdates(scroll_info.get()); scroll_info->page_scale_delta = active_tree_->page_scale_factor()->PullDeltaForMainThread(); + scroll_info->is_pinch_gesture_active = active_tree_->PinchGestureActive(); // We should never process non-unit page_scale_delta for an OOPIF subframe. // TODO(wjmaclean): Remove this DCHECK as a pre-condition to closing the bug. // https://crbug.com/845097 @@ -4809,11 +4942,20 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { scroll_info->scroll_latched_element_id = last_scroller_element_id_; last_scroller_element_id_ = ElementId(); } else { - // Send the element id of the currently scrolling node. - auto* node = - active_tree_->property_trees()->scroll_tree.CurrentlyScrollingNode(); + // In scroll animation path CurrentlyScrollingNode does not exist during + // overscrolling. Use the explicitly stored overscroll target instead. scroll_info->scroll_latched_element_id = - node ? node->element_id : ElementId(); + scroll_animating_overscroll_target_element_id_; + scroll_animating_overscroll_target_element_id_ = ElementId(); + + if (!scroll_info->scroll_latched_element_id) { + // In non-animating scroll path the overscroll target is always the + // CurrentlyScrollingNode. + ScrollNode* node = + active_tree_->property_trees()->scroll_tree.CurrentlyScrollingNode(); + scroll_info->scroll_latched_element_id = + node ? node->element_id : ElementId(); + } } if (browser_controls_manager()) { @@ -4862,7 +5004,7 @@ bool LayerTreeHostImpl::AnimateBrowserControls(base::TimeTicks time) { if (!browser_controls_offset_manager_->has_animation()) return false; - gfx::Vector2dF scroll = browser_controls_offset_manager_->Animate(time); + gfx::Vector2dF scroll_delta = browser_controls_offset_manager_->Animate(time); if (browser_controls_offset_manager_->has_animation()) SetNeedsOneBeginImplFrame(); @@ -4870,11 +5012,15 @@ bool LayerTreeHostImpl::AnimateBrowserControls(base::TimeTicks time) { if (active_tree_->TotalScrollOffset().y() == 0.f) return false; - if (scroll.IsZero()) + if (scroll_delta.IsZero()) return false; DCHECK(viewport()); - viewport()->ScrollBy(scroll, gfx::Point(), false, false, true); + viewport()->ScrollBy(scroll_delta, + /*viewport_point=*/gfx::Point(), + /*is_wheel_scroll=*/false, + /*affect_browser_controls=*/false, + /*scroll_outer_viewport=*/true); client_->SetNeedsCommitOnImplThread(); client_->RenewTreePriority(); return true; @@ -5509,10 +5655,12 @@ bool LayerTreeHostImpl::ScrollAnimationUpdateTarget( bool LayerTreeHostImpl::IsElementInList(ElementId element_id, ElementListType list_type) const { if (list_type == ElementListType::ACTIVE) - return active_tree() && active_tree()->IsElementInLayerList(element_id); + return active_tree() && active_tree()->IsElementInPropertyTree(element_id); - return (pending_tree() && pending_tree()->IsElementInLayerList(element_id)) || - (recycle_tree() && recycle_tree()->IsElementInLayerList(element_id)); + return (pending_tree() && + pending_tree()->IsElementInPropertyTree(element_id)) || + (recycle_tree() && + recycle_tree()->IsElementInPropertyTree(element_id)); } void LayerTreeHostImpl::SetMutatorsNeedCommit() {} @@ -5602,18 +5750,43 @@ void LayerTreeHostImpl::ElementIsAnimatingChanged( list_type == ElementListType::ACTIVE ? active_tree() : pending_tree(); // TODO(wkorman): Explore enabling DCHECK in ElementIsAnimatingChanged() // below. Currently enabling causes batch of unit test failures. - if (tree && - tree->property_trees()->ElementIsAnimatingChanged( - mutator_host(), element_id_map, list_type, mask, state, false)) + if (tree && tree->property_trees()->ElementIsAnimatingChanged( + element_id_map, mask, state, false)) tree->set_needs_update_draw_properties(); } +void LayerTreeHostImpl::AnimationScalesChanged(ElementId element_id, + ElementListType list_type, + float maximum_scale, + float starting_scale) { + if (LayerTreeImpl* tree = list_type == ElementListType::ACTIVE + ? active_tree() + : pending_tree()) { + tree->property_trees()->AnimationScalesChanged(element_id, maximum_scale, + starting_scale); + } +} + void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollOffsetAnimationFinished"); + // ScrollOffsetAnimationFinished is called in two cases: 1- smooth scrolling + // animation is over (is_animating_for_snap_ == false). 2- snap scroll + // animation is over (is_animating_for_snap_ == true). When smooth scroll + // animation is over we should check and run snap scroll animation if needed. + if (!is_animating_for_snap_ && SnapAtScrollEnd()) + return; + + // Call scrollEnd with the deferred scroll end state when the scroll animation + // completes after GSE arrival. + if (deferred_scroll_end_state_.has_value()) { + ScrollEnd(&deferred_scroll_end_state_.value(), false); + return; + } + // TODO(majidvp): We should pass in the original starting scroll position here ScrollStateData scroll_state_data; ScrollState scroll_state(scroll_state_data); - ScrollEnd(&scroll_state, !is_animating_for_snap_); + ScrollEndImpl(&scroll_state); } void LayerTreeHostImpl::NotifyAnimationWorkletStateChange( diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index 6f07f2514cd..18ccfb6763d 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -17,7 +17,6 @@ #include "base/callback.h" #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" -#include "base/macros.h" #include "base/memory/memory_pressure_listener.h" #include "base/sequenced_task_runner.h" #include "base/time/time.h" @@ -27,6 +26,7 @@ #include "cc/input/browser_controls_offset_manager_client.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar_animation_controller.h" +#include "cc/input/scrollbar_controller.h" #include "cc/layers/layer_collections.h" #include "cc/resources/ui_resource_client.h" #include "cc/scheduler/begin_frame_tracker.h" @@ -66,7 +66,9 @@ class CompositorFrameMetadata; } namespace cc { + class BrowserControlsOffsetManager; +class CompositorFrameReportingController; class DebugRectHistory; class EvictionTilePriorityQueue; class FrameRateCounter; @@ -184,7 +186,10 @@ class CC_EXPORT LayerTreeHostImpl // or become part of the CompositorFrameMetadata. struct CC_EXPORT FrameData { FrameData(); + FrameData(const FrameData&) = delete; ~FrameData(); + + FrameData& operator=(const FrameData&) = delete; void AsValueInto(base::trace_event::TracedValue* value) const; std::vector<viz::SurfaceId> activation_dependencies; @@ -196,17 +201,17 @@ class CC_EXPORT LayerTreeHostImpl bool has_no_damage = false; bool may_contain_video = false; viz::BeginFrameAck begin_frame_ack; - - private: - DISALLOW_COPY_AND_ASSIGN(FrameData); }; // A struct of data for a single UIResource, including the backing // pixels, and metadata about it. struct CC_EXPORT UIResourceData { UIResourceData(); - ~UIResourceData(); + UIResourceData(const UIResourceData&) = delete; UIResourceData(UIResourceData&&) noexcept; + ~UIResourceData(); + + UIResourceData& operator=(const UIResourceData&) = delete; UIResourceData& operator=(UIResourceData&&); bool opaque; @@ -221,9 +226,6 @@ class CC_EXPORT LayerTreeHostImpl // The name with which to refer to the resource in frames submitted to the // display compositor. viz::ResourceId resource_id_for_export; - - private: - DISALLOW_COPY_AND_ASSIGN(UIResourceData); }; static std::unique_ptr<LayerTreeHostImpl> Create( @@ -235,8 +237,11 @@ class CC_EXPORT LayerTreeHostImpl std::unique_ptr<MutatorHost> mutator_host, int id, scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner); + LayerTreeHostImpl(const LayerTreeHostImpl&) = delete; ~LayerTreeHostImpl() override; + LayerTreeHostImpl& operator=(const LayerTreeHostImpl&) = delete; + // InputHandler implementation void BindToClient(InputHandlerClient* client) override; InputHandler::ScrollStatus ScrollBegin( @@ -257,8 +262,9 @@ class CC_EXPORT LayerTreeHostImpl const gfx::ScrollOffset& root_offset) override; void ScrollEnd(ScrollState* scroll_state, bool should_snap = false) override; - void MouseDown() override; - void MouseUp() override; + InputHandlerPointerResult MouseDown( + const gfx::PointF& viewport_point) override; + InputHandlerPointerResult MouseUp(const gfx::PointF& viewport_point) override; void MouseMoveAt(const gfx::Point& viewport_point) override; void MouseLeave() override; @@ -368,6 +374,10 @@ class CC_EXPORT LayerTreeHostImpl ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) override; + void AnimationScalesChanged(ElementId element_id, + ElementListType list_type, + float maximum_scale, + float starting_scale) override; void ScrollOffsetAnimationFinished() override; gfx::ScrollOffset GetScrollOffsetForAnimation( @@ -584,7 +594,20 @@ class CC_EXPORT LayerTreeHostImpl return accumulated_root_overscroll_; } - bool pinch_gesture_active() const { return pinch_gesture_active_; } + bool pinch_gesture_active() const { + return pinch_gesture_active_ || external_pinch_gesture_active_; + } + // Used to set the pinch gesture active state when the pinch gesture is + // handled on another layer tree. In a page with OOPIFs, only the main + // frame's layer tree directly handles pinch events. But layer trees for + // sub-frames need to know when pinch gestures are active so they can + // throttle the re-rastering. This function allows setting this flag on + // OOPIF layer trees using information sent (initially) from the main-frame. + void set_external_pinch_gesture_active(bool external_pinch_gesture_active) { + external_pinch_gesture_active_ = external_pinch_gesture_active; + // Only one of the flags should ever be true at any given time. + DCHECK(!pinch_gesture_active_ || !external_pinch_gesture_active_); + } void SetTreePriority(TreePriority priority); TreePriority GetTreePriority() const; @@ -731,6 +754,11 @@ class CC_EXPORT LayerTreeHostImpl // See SyncSurfaceIdAllocator for details. uint32_t GenerateChildSurfaceSequenceNumberSync(); + CompositorFrameReportingController* compositor_frame_reporting_controller() + const { + return compositor_frame_reporting_controller_.get(); + } + protected: LayerTreeHostImpl( const LayerTreeSettings& settings, @@ -758,6 +786,9 @@ class CC_EXPORT LayerTreeHostImpl BeginFrameTracker current_begin_frame_tracker_; + std::unique_ptr<CompositorFrameReportingController> + compositor_frame_reporting_controller_; + private: const gfx::ColorSpace& GetRasterColorSpaceAndId(int* id) const; @@ -969,6 +1000,11 @@ class CC_EXPORT LayerTreeHostImpl ElementId scroll_element_id_mouse_currently_over_; ElementId scroll_element_id_mouse_currently_captured_; + // Tracks, for debugging purposes, the amount of scroll received (not + // necessarily applied) in this compositor frame. This will be reset each + // time a CompositorFrame is generated. + gfx::ScrollOffset scroll_accumulated_this_frame_; + std::vector<std::unique_ptr<SwapPromise>> swap_promises_for_main_thread_scroll_update_; @@ -995,7 +1031,17 @@ class CC_EXPORT LayerTreeHostImpl bool did_scroll_x_for_scroll_gesture_; bool did_scroll_y_for_scroll_gesture_; + // This value is used to allow the compositor to throttle re-rastering during + // pinch gestures, when the page scale factor may be changing frequently. It + // is set in one of two ways: + // i) In a layer tree serving the root of the frame/compositor tree, it is + // directly set during processing of GesturePinch events on the impl thread + // (only the root layer tree has access to these). + // ii) In a layer tree serving a sub-frame in the frame/compositor tree, it + // is set from the main thread during the commit process, using information + // sent from the root layer tree via IPC messaging. bool pinch_gesture_active_ = false; + bool external_pinch_gesture_active_ = false; bool pinch_gesture_end_should_clear_scrolling_node_ = false; std::unique_ptr<BrowserControlsOffsetManager> @@ -1074,6 +1120,19 @@ class CC_EXPORT LayerTreeHostImpl // in SetPropertyTrees. ElementId scroll_animating_latched_element_id_; + // In scroll animation path CurrentlyScrollingNode does not exist when there + // is no ongoing scroll animation (e.g. during overscrolling). In this case we + // need to explicitly store the element id of the overscroll event target. The + // overscroll event target is either the element that scroll animation is + // latched to (scroll_animating_latched_element_id_) when any scrolling has + // happened during the current scroll sequence or the last element in the + // scroll chain when no scrolling has happened during the current scroll + // sequence. TODO(input-dev): Decouple CurrentlyScrollingNode life cycle from + // scroll animation life cycle to use CurrentlyScrollingNode instead of both + // scroll_animating_latched_element_id_ and + // scroll_animating_overscroll_target_element_id_. https://crbug.com/940508 + ElementId scroll_animating_overscroll_target_element_id_; + // These completion states to be transfered to the main thread when we // begin main frame. The pair represents a request id and the completion (ie // success) state. @@ -1114,9 +1173,13 @@ class CC_EXPORT LayerTreeHostImpl uint32_t token, base::TimeTicks cc_frame_time, std::vector<LayerTreeHost::PresentationTimeCallback> callbacks); + FrameTokenInfo(const FrameTokenInfo&) = delete; FrameTokenInfo(FrameTokenInfo&&); ~FrameTokenInfo(); + FrameTokenInfo& operator=(const FrameTokenInfo&) = delete; + FrameTokenInfo& operator=(FrameTokenInfo&&) = default; + uint32_t token; // The compositor frame time used to produce the frame. @@ -1124,8 +1187,6 @@ class CC_EXPORT LayerTreeHostImpl // The callbacks to send back to the main thread. std::vector<LayerTreeHost::PresentationTimeCallback> callbacks; - - DISALLOW_COPY_AND_ASSIGN(FrameTokenInfo); }; base::circular_deque<FrameTokenInfo> frame_token_infos_; @@ -1136,7 +1197,11 @@ class CC_EXPORT LayerTreeHostImpl const PaintImage::GeneratorClientId paint_image_generator_client_id_; + // Manages composited scrollbar hit testing. + std::unique_ptr<ScrollbarController> scrollbar_controller_; + // Set to true when a scroll gesture being handled on the compositor has + // ended. i.e. When a GSE has arrived and any ongoing scroll animation has // ended. bool scroll_gesture_did_end_; @@ -1144,7 +1209,11 @@ class CC_EXPORT LayerTreeHostImpl // used to send the scrollend DOM event when scrolling has happened on CC. ElementId last_scroller_element_id_; - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); + // Scroll animation can finish either before or after GSE arrival. + // deferred_scroll_end_state_ is set when the GSE has arrvied before scroll + // animation completion. ScrollEnd will get called with this deferred state + // once the animation is over. + base::Optional<ScrollState> deferred_scroll_end_state_; }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index 8288c54dde8..470a819eefb 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -394,6 +394,7 @@ class LayerTreeHostImplTest : public testing::Test, LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollable(viewport_scroll_bounds); + inner_scroll->SetHitTestable(true); inner_scroll->SetElementId( LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(content_size); @@ -408,6 +409,7 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollable(content_size); + outer_scroll->SetHitTestable(true); outer_scroll->SetElementId( LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() @@ -465,6 +467,7 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -484,15 +487,17 @@ class LayerTreeHostImplTest : public testing::Test, squash1->test_properties()->opacity = 0.0f; // The transparent layer should still participate in hit testing even // through it does not draw content. - squash1->SetHitTestableWithoutDrawsContent(true); + squash1->SetHitTestable(true); } else { squash1->SetDrawsContent(true); + squash1->SetHitTestable(true); } std::unique_ptr<LayerImpl> squash2 = LayerImpl::Create(layer_tree_impl, 6); squash2->SetBounds(gfx::Size(140, 300)); squash2->test_properties()->position = gfx::PointF(220, 300); squash2->SetDrawsContent(true); + squash2->SetHitTestable(true); scroll->test_properties()->AddChild(std::move(squash2)); root->test_properties()->AddChild(std::move(scroll)); @@ -540,6 +545,7 @@ class LayerTreeHostImplTest : public testing::Test, content_layer->SetBounds(content_size); host_impl_->OuterViewportScrollLayer()->SetBounds(content_size); host_impl_->OuterViewportScrollLayer()->SetScrollable(viewport_size); + host_impl_->OuterViewportScrollLayer()->SetHitTestable(true); LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->test_properties()->parent; @@ -552,6 +558,7 @@ class LayerTreeHostImplTest : public testing::Test, inner_clip_layer->SetBounds(viewport_size); host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size); host_impl_->InnerViewportScrollLayer()->SetScrollable(viewport_size); + host_impl_->InnerViewportScrollLayer()->SetHitTestable(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -571,6 +578,7 @@ class LayerTreeHostImplTest : public testing::Test, gfx::Size scroll_container_bounds = gfx::Size(size.width() / 2, size.height() / 2); layer->SetScrollable(scroll_container_bounds); + layer->SetHitTestable(true); return layer; } @@ -710,6 +718,7 @@ class LayerTreeHostImplTest : public testing::Test, LayerImpl* overflow = scroll_layer->test_properties()->children[0]; overflow->SetBounds(overflow_size); overflow->SetScrollable(gfx::Size(100, 100)); + overflow->SetHitTestable(true); overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() @@ -876,6 +885,30 @@ class TestInputHandlerClient : public InputHandlerClient { float max_page_scale_factor_; }; +TEST_F(LayerTreeHostImplTest, LocalAndExternalPinchState) { + // PinchGestureBegin/End update pinch_gesture_active() properly. + EXPECT_FALSE(host_impl_->pinch_gesture_active()); + host_impl_->PinchGestureBegin(); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->PinchGestureEnd(gfx::Point(), false /* snap_to_min */); + EXPECT_FALSE(host_impl_->pinch_gesture_active()); + + // set_external_pinch_gesture_active updates pinch_gesture_active() properly. + host_impl_->set_external_pinch_gesture_active(true); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->set_external_pinch_gesture_active(false); + EXPECT_FALSE(host_impl_->pinch_gesture_active()); + + // Clearing external_pinch_gesture_active doesn't affect + // pinch_gesture_active() if it was set by PinchGestureBegin(). + host_impl_->PinchGestureBegin(); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->set_external_pinch_gesture_active(false); + EXPECT_TRUE(host_impl_->pinch_gesture_active()); + host_impl_->PinchGestureEnd(gfx::Point(), false /* snap_to_min */); + EXPECT_FALSE(host_impl_->pinch_gesture_active()); +} + TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) { // Note: It is not possible to disable the renderer once it has been set, // so we do not need to test that disabling the renderer notifies us @@ -1035,6 +1068,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) { root->SetBounds(gfx::Size(110, 110)); root->SetScrollable(gfx::Size(10, 10)); + root->SetHitTestable(true); root->SetElementId(LayerIdToElementIdForTesting(root->id())); root->layer_tree_impl() ->property_trees() @@ -1334,8 +1368,10 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); + scroll->SetHitTestable(true); std::unique_ptr<SolidColorScrollbarLayerImpl> drawn_scrollbar = SolidColorScrollbarLayerImpl::Create(layer_tree_impl, 4, VERTICAL, 10, 0, @@ -1344,12 +1380,14 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { drawn_scrollbar->test_properties()->position = gfx::PointF(345, 0); drawn_scrollbar->SetScrollElementId(scroll->element_id()); drawn_scrollbar->SetDrawsContent(true); + drawn_scrollbar->SetHitTestable(true); drawn_scrollbar->test_properties()->opacity = 1.f; std::unique_ptr<LayerImpl> squash = LayerImpl::Create(layer_tree_impl, 5); squash->SetBounds(gfx::Size(140, 300)); squash->test_properties()->position = gfx::PointF(220, 0); squash->SetDrawsContent(true); + squash->SetHitTestable(true); scroll->test_properties()->AddChild(std::move(drawn_scrollbar)); scroll->test_properties()->AddChild(std::move(squash)); @@ -1367,12 +1405,12 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest, status.main_thread_scrolling_reasons); - // The point hits the drawn scrollbar layer completely and should not scroll - // on the impl thread. + // The point hits the drawn scrollbar layer completely and should scroll on + // the impl thread. status = host_impl_->ScrollBegin(BeginState(gfx::Point(350, 500)).get(), InputHandler::WHEEL); - EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest, + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); } @@ -1775,6 +1813,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) { LayerImpl* overflow = scroll_layer->test_properties()->children[0]; overflow->SetBounds(overflow_size); overflow->SetScrollable(gfx::Size(100, 100)); + overflow->SetHitTestable(true); overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() @@ -1944,6 +1983,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { LayerImpl* overflow = scroll_layer->test_properties()->children[0]; overflow->SetBounds(overflow_size); overflow->SetScrollable(gfx::Size(100, 100)); + overflow->SetHitTestable(true); overflow->SetElementId(LayerIdToElementIdForTesting(overflow->id())); overflow->layer_tree_impl() ->property_trees() @@ -2005,6 +2045,26 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset()); } +TEST_F(LayerTreeHostImplTest, ForceMainThreadScrollWithoutScrollLayer) { + SetupScrollAndContentsLayers(gfx::Size(200, 200)); + host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(100, 100)); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + ScrollNode* scroll_node = + host_impl_->active_tree()->property_trees()->scroll_tree.Node( + host_impl_->OuterViewportScrollLayer()->scroll_tree_index()); + // Change the scroll node so that it no longer has an associated layer. + scroll_node->element_id = ElementId(42); + + DrawFrame(); + + InputHandler::ScrollStatus status = host_impl_->ScrollBegin( + BeginState(gfx::Point(25, 25)).get(), InputHandler::WHEEL); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + status.main_thread_scrolling_reasons); +} + TEST_F(CommitToPendingTreeLayerTreeHostImplTest, AnimationSchedulingPendingTree) { EXPECT_FALSE(host_impl_->CommitToActiveTree()); @@ -2366,6 +2426,7 @@ TEST_F(LayerTreeHostImplTest, ViewportScrollbarGeometry) { // frame (outer viewport) such that it matches the width of the content, // preventing horizontal scrolling. Replicate that behavior here. host_impl_->OuterViewportScrollLayer()->SetScrollable(outer_viewport_size); + host_impl_->OuterViewportScrollLayer()->SetHitTestable(true); LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->test_properties()->parent; outer_clip->SetBounds(outer_viewport_size); @@ -2813,6 +2874,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) { TEST_F(LayerTreeHostImplTest, PinchGesture) { SetupScrollAndContentsLayers(gfx::Size(100, 100)); host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); @@ -2987,6 +3049,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { TEST_F(LayerTreeHostImplTest, SyncSubpixelScrollDelta) { SetupScrollAndContentsLayers(gfx::Size(100, 100)); host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer(); @@ -3968,6 +4031,7 @@ class LayerTreeHostImplTestMultiScrollable : public LayerTreeHostImplTest { scrollbar_1_ = scrollbar_1.get(); scrollbar_1->SetScrollElementId(root_scroll->element_id()); scrollbar_1->SetDrawsContent(true); + scrollbar_1->SetHitTestable(true); scrollbar_1->SetBounds(scrollbar_size_1); TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionNone, gfx::Rect(scrollbar_size_1)); @@ -3990,12 +4054,15 @@ class LayerTreeHostImplTestMultiScrollable : public LayerTreeHostImplTest { child->test_properties()->position = gfx::PointF(50, 50); child->SetBounds(child_layer_size); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetScrollable(gfx::Size(100, 100)); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); ElementId child_element_id = child->element_id(); scrollbar_2->SetScrollElementId(child_element_id); scrollbar_2->SetDrawsContent(true); + scrollbar_2->SetHitTestable(true); scrollbar_2->SetBounds(scrollbar_size_2); scrollbar_2->SetCurrentPos(0); scrollbar_2->test_properties()->position = gfx::PointF(0, 0); @@ -4112,12 +4179,12 @@ TEST_F(LayerTreeHostImplTestMultiScrollable, ScrollHitTestOnScrollbar) { status.main_thread_scrolling_reasons); } - // Wheel scroll on scrollbar should fallback to main thread. + // Wheel scroll on scrollbar should process on impl thread. { InputHandler::ScrollStatus status = host_impl_->ScrollBegin( BeginState(gfx::Point(51, 51)).get(), InputHandler::WHEEL); - EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest, + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); } @@ -4316,6 +4383,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { // Check scrollbar registration on a sublayer. child->SetScrollable(viewport_size); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); ElementId child_scroll_element_id = child->element_id(); root_scroll->test_properties()->AddChild(std::move(child)); @@ -5898,6 +5966,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, LayerImpl::Create(host_impl_->active_tree(), id + 2); child->SetScrollable(sub_content_layer_size); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); child->SetBounds(sub_content_size); child->test_properties()->position = gfx::PointF(); @@ -6452,6 +6521,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { std::unique_ptr<LayerImpl> scroll_layer = LayerImpl::Create(host_impl_->active_tree(), 12); scroll_layer->SetScrollable(surface_size); + scroll_layer->SetHitTestable(true); scroll_layer->SetElementId(LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(contents_size); scroll_layer->test_properties()->position = gfx::PointF(); @@ -7092,44 +7162,87 @@ TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) { gfx::ScrollOffset(0, 4))); } } + +// Ensure that layers who's scroll parent is the InnerViewportScrollNode are +// still able to scroll on thte compositor. +TEST_F(LayerTreeHostImplTest, ChildrenOfInnerScrollNodeCanScrollOnThread) { + gfx::Size viewport_size(10, 10); + gfx::Size content_size(20, 20); + LayerImpl* content_layer = + CreateBasicVirtualViewportLayers(viewport_size, content_size); + + constexpr int kFixedLayerId = 300; + + // Simulate adding a "fixed" layer to the tree. + { + std::unique_ptr<LayerImpl> fixed_layer = + LayerImpl::Create(host_impl_->active_tree(), kFixedLayerId); + fixed_layer->SetBounds(viewport_size); + fixed_layer->SetDrawsContent(true); + content_layer->test_properties()->AddChild(std::move(fixed_layer)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + // This is very hackish but we want to simulate the kind of property tree + // that BGPT would create where a fixed layer's ScrollNode is parented to + // the inner viewport, rather than the outer. + host_impl_->active_tree() + ->LayerById(kFixedLayerId) + ->SetScrollTreeIndex( + host_impl_->active_tree()->InnerViewportScrollNode()->id); + } + + host_impl_->active_tree()->DidBecomeActive(); + DrawFrame(); + { + gfx::ScrollOffset scroll_delta(0, 4); + // Scrolling should be able to happen on the compositor thread here. + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, + host_impl_ + ->ScrollBegin(BeginState(gfx::Point(5, 5)).get(), + InputHandler::WHEEL) + .thread); + host_impl_->ScrollBy( + UpdateState(gfx::Point(), gfx::ScrollOffsetToVector2dF(scroll_delta)) + .get()); + host_impl_->ScrollEnd(EndState().get()); + + std::unique_ptr<ScrollAndScaleSet> scroll_info = + host_impl_->ProcessScrollDeltas(); + + // The outer viewport should have scrolled. + ASSERT_EQ(scroll_info->scrolls.size(), 1u); + EXPECT_TRUE(ScrollInfoContains( + *scroll_info.get(), + host_impl_->active_tree()->OuterViewportScrollNode()->element_id, + scroll_delta)); + } +} + TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) { // When we try to scroll a non-scrollable child layer, the scroll delta // should be applied to one of its ancestors if possible. - gfx::Size surface_size(10, 10); + gfx::Size viewport_size(10, 10); gfx::Size content_size(20, 20); - const int kPageScaleLayerId = 4; - const int kViewportClipLayerId = 1; - const int kViewportScrollLayerId = 2; - std::unique_ptr<LayerImpl> root_ptr = - LayerImpl::Create(host_impl_->active_tree(), kPageScaleLayerId); - std::unique_ptr<LayerImpl> root_clip = - LayerImpl::Create(host_impl_->active_tree(), 3); - root_clip->test_properties()->force_render_surface = true; - std::unique_ptr<LayerImpl> root_scroll = - CreateScrollableLayer(kViewportClipLayerId, content_size); - // Make 'root' the clip layer for child: since they have the same sizes the - // child will have zero max_scroll_offset and scrolls will bubble. - std::unique_ptr<LayerImpl> child = - CreateScrollableLayer(kViewportScrollLayerId, content_size); - child->test_properties()->is_container_for_fixed_position_layers = true; - root_scroll->SetBounds(content_size); - child->SetScrollable(content_size); + LayerImpl* content_layer = + CreateBasicVirtualViewportLayers(viewport_size, content_size); - ElementId root_scroll_id = root_scroll->element_id(); - root_scroll->test_properties()->AddChild(std::move(child)); - root_clip->test_properties()->AddChild(std::move(root_scroll)); - root_ptr->test_properties()->AddChild(std::move(root_clip)); + constexpr int kScrollChildClipId = 300; + constexpr int kScrollChildScrollId = 301; + + // Add a scroller whose scroll bounds and scroll container bounds are equal. + // Since the max_scroll_offset is 0, scrolls will bubble. + std::unique_ptr<LayerImpl> scroll_child_clip = + LayerImpl::Create(host_impl_->active_tree(), kScrollChildClipId); + std::unique_ptr<LayerImpl> scroll_child = + CreateScrollableLayer(kScrollChildScrollId, gfx::Size(10, 10)); + scroll_child->test_properties()->is_container_for_fixed_position_layers = + true; + scroll_child->SetScrollable(gfx::Size(10, 10)); + + scroll_child_clip->test_properties()->AddChild(std::move(scroll_child)); + content_layer->test_properties()->AddChild(std::move(scroll_child_clip)); - host_impl_->active_tree()->SetRootLayerForTesting(std::move(root_ptr)); - LayerTreeImpl::ViewportLayerIds viewport_ids; - viewport_ids.page_scale = kPageScaleLayerId; - viewport_ids.inner_viewport_container = kViewportClipLayerId; - viewport_ids.inner_viewport_scroll = kViewportScrollLayerId; - host_impl_->active_tree()->SetViewportLayersFromIds(viewport_ids); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->DidBecomeActive(); - - host_impl_->active_tree()->SetDeviceViewportSize(surface_size); DrawFrame(); { gfx::ScrollOffset scroll_delta(0, 4); @@ -7148,8 +7261,10 @@ TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) { // Only the root scroll should have scrolled. ASSERT_EQ(scroll_info->scrolls.size(), 1u); - EXPECT_TRUE( - ScrollInfoContains(*scroll_info.get(), root_scroll_id, scroll_delta)); + EXPECT_TRUE(ScrollInfoContains( + *scroll_info.get(), + host_impl_->active_tree()->OuterViewportScrollNode()->element_id, + scroll_delta)); } } @@ -7315,6 +7430,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) { gfx::Size(child->bounds().width(), child->bounds().height() / 2); clip_layer->SetBounds(scroll_container_bounds); child->SetScrollable(scroll_container_bounds); + child->SetHitTestable(true); // The rotation depends on the layer's transform origin, and the child layer // is a different size than the clip, so make sure the clip layer's origin // lines up over the child. @@ -7548,6 +7664,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { scroll_layer->test_properties()->parent->test_properties()->parent; clip_layer->SetBounds(gfx::Size(10, 20)); scroll_layer->SetScrollable(gfx::Size(10, 20)); + scroll_layer->SetHitTestable(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->BindToClient(&scroll_watcher); @@ -7661,6 +7778,7 @@ TEST_F(LayerTreeHostImplTest, scroll_layer->test_properties()->parent->test_properties()->parent; clip_layer->SetBounds(gfx::Size(10, 20)); scroll_layer->SetScrollable(gfx::Size(10, 20)); + scroll_layer->SetHitTestable(true); scroll_layer->SetDrawsContent(true); // Draw first frame to clear any pending draws and check scroll. @@ -7683,42 +7801,133 @@ TEST_F(LayerTreeHostImplTest, gfx::ScrollOffsetToVector2dF(scroll_offset)); } -TEST_F(LayerTreeHostImplTest, - ExternalRootLayerScrollOffsetPreventedByUserNotScrollable) { - host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 20)); - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); - LayerImpl* clip_layer = - scroll_layer->test_properties()->parent->test_properties()->parent; - clip_layer->SetBounds(gfx::Size(10, 20)); - scroll_layer->SetScrollable(gfx::Size(10, 20)); - scroll_layer->SetDrawsContent(true); - host_impl_->active_tree() - ->InnerViewportScrollLayer() - ->test_properties() - ->user_scrollable_vertical = false; - host_impl_->active_tree() - ->InnerViewportScrollLayer() - ->test_properties() - ->user_scrollable_horizontal = false; - host_impl_->active_tree()->BuildPropertyTreesForTesting(); +// Ensure that the SetSynchronousInputHandlerRootScrollOffset method used by +// the WebView API correctly respects the user_scrollable bits on both of the +// inner and outer viewport scroll nodes. +TEST_F(LayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { + gfx::Size viewport_size(100, 100); + gfx::Size content_size(200, 200); + CreateBasicVirtualViewportLayers(viewport_size, content_size); - // Draw first frame to clear any pending draws and check scroll. - DrawFrame(); - CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f)); - EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties()); + auto* outer_scroll = host_impl_->active_tree()->OuterViewportScrollLayer(); + auto* inner_scroll = host_impl_->active_tree()->InnerViewportScrollLayer(); + + ScrollTree& scroll_tree = + host_impl_->active_tree()->property_trees()->scroll_tree; + ElementId inner_element_id = inner_scroll->element_id(); + ElementId outer_element_id = outer_scroll->element_id(); - // Set external scroll delta on delegate and notify LayerTreeHost. - gfx::ScrollOffset scroll_offset(10.f, 10.f); - host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); host_impl_->active_tree()->BuildPropertyTreesForTesting(); + DrawFrame(); - TestFrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame); - host_impl_->DidDrawAllLayers(frame); - EXPECT_TRUE(frame.has_no_damage); - CheckLayerScrollDelta(scroll_layer, - gfx::ScrollOffsetToVector2dF(gfx::ScrollOffset())); + float page_scale_factor = 2.f; + host_impl_->active_tree()->PushPageScaleFromMainThread( + page_scale_factor, page_scale_factor, page_scale_factor); + + // Disable scrolling the inner viewport. Only the outer should scroll. + { + ASSERT_FALSE(did_request_redraw_); + inner_scroll->test_properties()->user_scrollable_vertical = false; + inner_scroll->test_properties()->user_scrollable_horizontal = false; + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(25.f, 30.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(inner_element_id)); + scroll_offset.Scale(1.f / page_scale_factor); + EXPECT_VECTOR_EQ(scroll_offset, + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_TRUE(did_request_redraw_); + + // Reset + did_request_redraw_ = false; + inner_scroll->test_properties()->user_scrollable_vertical = true; + inner_scroll->test_properties()->user_scrollable_horizontal = true; + outer_scroll->SetCurrentScrollOffset(gfx::ScrollOffset(0, 0)); + } + + // Disable scrolling the outer viewport. The inner should scroll to its + // extent but there should be no bubbling over to the outer viewport. + { + ASSERT_FALSE(did_request_redraw_); + outer_scroll->test_properties()->user_scrollable_vertical = false; + outer_scroll->test_properties()->user_scrollable_horizontal = false; + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(120.f, 140.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(50.f, 50.f), + scroll_tree.current_scroll_offset(inner_element_id)); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_TRUE(did_request_redraw_); + + // Reset + did_request_redraw_ = false; + inner_scroll->test_properties()->user_scrollable_vertical = true; + inner_scroll->test_properties()->user_scrollable_horizontal = true; + inner_scroll->SetCurrentScrollOffset(gfx::ScrollOffset(0, 0)); + } + + // Disable both viewports. No scrolling should take place, no redraw should + // be requested. + { + ASSERT_FALSE(did_request_redraw_); + outer_scroll->test_properties()->user_scrollable_vertical = false; + outer_scroll->test_properties()->user_scrollable_horizontal = false; + inner_scroll->test_properties()->user_scrollable_vertical = false; + inner_scroll->test_properties()->user_scrollable_horizontal = false; + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(60.f, 70.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(inner_element_id)); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_FALSE(did_request_redraw_); + + // Reset + inner_scroll->test_properties()->user_scrollable_vertical = true; + inner_scroll->test_properties()->user_scrollable_horizontal = true; + outer_scroll->test_properties()->user_scrollable_vertical = true; + outer_scroll->test_properties()->user_scrollable_horizontal = true; + } + + // If the inner is at its extent but the outer cannot scroll, we shouldn't + // request a redraw. + { + ASSERT_FALSE(did_request_redraw_); + outer_scroll->test_properties()->user_scrollable_vertical = false; + outer_scroll->test_properties()->user_scrollable_horizontal = false; + inner_scroll->SetCurrentScrollOffset(gfx::ScrollOffset(50.f, 50.f)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(60.f, 70.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(50.f, 50.f), + scroll_tree.current_scroll_offset(inner_element_id)); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_FALSE(did_request_redraw_); + + // Reset + outer_scroll->test_properties()->user_scrollable_vertical = true; + outer_scroll->test_properties()->user_scrollable_horizontal = true; + } +} + +// The SetSynchronousInputHandlerRootScrollOffset API can be called while there +// is no inner viewport set. This test passes if we don't crash. +TEST_F(LayerTreeHostImplTest, SetRootScrollOffsetNoViewportCrash) { + host_impl_->active_tree()->ClearViewportLayers(); + host_impl_->active_tree()->DidBecomeActive(); + + auto* inner_scroll = host_impl_->active_tree()->InnerViewportScrollLayer(); + ASSERT_FALSE(inner_scroll); + gfx::ScrollOffset scroll_offset(25.f, 30.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); } TEST_F(LayerTreeHostImplTest, OverscrollRoot) { @@ -8002,6 +8211,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollAlways) { clip_layer->SetBounds(gfx::Size(50, 50)); scroll_layer->SetScrollable(gfx::Size(50, 50)); + scroll_layer->SetHitTestable(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50)); @@ -8110,6 +8320,7 @@ TEST_F(LayerTreeHostImplTest, NoOverscrollOnNonViewportLayers) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -8231,6 +8442,7 @@ TEST_F(LayerTreeHostImplTest, ScrollFromOuterViewportSibling) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollable(viewport_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -8319,12 +8531,14 @@ TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(400, 400)); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 13); scroll2->SetBounds(gfx::Size(500, 500)); scroll2->SetScrollable(gfx::Size(300, 300)); + scroll2->SetHitTestable(true); scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); @@ -8442,6 +8656,7 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) { std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(gfx::Size(1200, 1200)); scroll->SetScrollable(content_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -8453,6 +8668,7 @@ TEST_F(LayerTreeHostImplTest, RootScrollerScrollNonDescendant) { std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 15); scroll2->SetBounds(gfx::Size(1200, 1200)); scroll2->SetScrollable(gfx::Size(600, 600)); + scroll2->SetHitTestable(true); scroll2->SetElementId(LayerIdToElementIdForTesting(scroll2->id())); scroll2->SetDrawsContent(true); @@ -9696,6 +9912,7 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) { gfx::ScrollOffset scroll_offset(100000, 0); scrolling_layer->SetScrollable(content_layer_bounds); + scrolling_layer->SetHitTestable(true); scrolling_layer->SetElementId( LayerIdToElementIdForTesting(scrolling_layer->id())); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); @@ -10170,19 +10387,20 @@ TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) { host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); - // The CopyOutputResult has a ref on the viz::ContextProvider and a texture - // in a texture mailbox. + auto* sii = context_provider->SharedImageInterface(); + // The CopyOutputResult has a ref on the viz::ContextProvider and a shared + // image allocated. ASSERT_TRUE(helper.unprocessed_result); EXPECT_FALSE(context_provider->HasOneRef()); - EXPECT_EQ(1u, context_provider->TestContextGL()->NumTextures()); + EXPECT_EQ(1u, sii->shared_image_count()); host_impl_->ReleaseLayerTreeFrameSink(); host_impl_ = nullptr; // The texture release callback that was given to the CopyOutputResult has - // been canceled, and the texture deleted. + // been canceled, and the shared image deleted. EXPECT_TRUE(context_provider->HasOneRef()); - EXPECT_EQ(0u, context_provider->TestContextGL()->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); // When resetting the CopyOutputResult, it will run its texture release // callback. This should not cause a crash, etc. @@ -10199,6 +10417,7 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) { LayerImpl* scroll_layer = host_impl_->active_tree()->LayerById(scroll_layer_id); scroll_layer->SetDrawsContent(true); + scroll_layer->SetHitTestable(true); int page_scale_layer_id = 5; LayerImpl* page_scale_layer = @@ -10208,6 +10427,7 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) { std::unique_ptr<LayerImpl> occluder_layer = LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); occluder_layer->SetDrawsContent(true); + occluder_layer->SetHitTestable(true); occluder_layer->SetBounds(content_size); occluder_layer->test_properties()->position = gfx::PointF(); @@ -10235,11 +10455,13 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) { LayerImpl* scroll_layer = host_impl_->active_tree()->LayerById(scroll_layer_id); scroll_layer->SetDrawsContent(true); + scroll_layer->SetHitTestable(true); int occluder_layer_id = 6; std::unique_ptr<LayerImpl> occluder_layer = LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); occluder_layer->SetDrawsContent(true); + occluder_layer->SetHitTestable(true); occluder_layer->SetBounds(content_size); occluder_layer->test_properties()->position = gfx::PointF(-10.f, -10.f); @@ -11108,6 +11330,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(scroll_content_size); scroll->SetScrollable(root_layer_size); + scroll->SetHitTestable(true); scroll->SetElementId(LayerIdToElementIdForTesting(scroll->id())); scroll->SetDrawsContent(true); @@ -11176,6 +11399,7 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { LayerImpl::Create(layer_tree_impl, kPageScaleLayerId); inner_scroll->SetScrollable(inner_viewport); + inner_scroll->SetHitTestable(true); inner_scroll->SetElementId( LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(outer_viewport); @@ -11190,6 +11414,7 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { std::unique_ptr<LayerImpl> outer_scroll = LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId); outer_scroll->SetScrollable(outer_viewport); + outer_scroll->SetHitTestable(true); outer_scroll->SetElementId( LayerIdToElementIdForTesting(outer_scroll->id())); outer_scroll->layer_tree_impl() @@ -11225,7 +11450,7 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { } }; -TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) { +TEST_F(LayerTreeHostImplVirtualViewportTest, RootScrollBothInnerAndOuterLayer) { gfx::Size content_size = gfx::Size(100, 160); gfx::Size outer_viewport = gfx::Size(50, 80); gfx::Size inner_viewport = gfx::Size(25, 40); @@ -11248,11 +11473,11 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) { EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset()); EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset()); - // Outer viewport scrolls first. Then the rest is applied to the inner + // Inner viewport scrolls first. Then the rest is applied to the outer // viewport. - EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f), + EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->CurrentScrollOffset()); - EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), + EXPECT_EQ(gfx::ScrollOffset(45.f, 60.f), outer_scroll->CurrentScrollOffset()); } } @@ -13420,6 +13645,7 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( child->SetBounds(child_layer_size); child->SetDrawsContent(true); child->SetScrollable(gfx::Size(100, 100)); + child->SetHitTestable(true); child->SetElementId(LayerIdToElementIdForTesting(child->id())); ElementId child_element_id = child->element_id(); @@ -13504,9 +13730,10 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( scrollbar_1_animation_controller->DidScrollUpdate(); animation_task_.Reset(); - host_impl_->MouseDown(); + // Only the MouseMove's location will affect the overlay scrollbar. + host_impl_->MouseDown(gfx::PointF(60, 50)); host_impl_->MouseMoveAt(gfx::Point(60, 50)); - host_impl_->MouseUp(); + host_impl_->MouseUp(gfx::PointF(60, 50)); EXPECT_FALSE(animation_task_.is_null()); @@ -13515,16 +13742,16 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( host_impl_->MouseMoveAt(gfx::Point(40, 150)); animation_task_.Reset(); - host_impl_->MouseDown(); - host_impl_->MouseUp(); + host_impl_->MouseDown(gfx::PointF(40, 150)); + host_impl_->MouseUp(gfx::PointF(40, 150)); EXPECT_TRUE(animation_task_.is_null()); // Near scrollbar_1, then mouse down and unregister // scrollbar_2_animation_controller, then mouse up should not cause crash. host_impl_->MouseMoveAt(gfx::Point(40, 150)); - host_impl_->MouseDown(); + host_impl_->MouseDown(gfx::PointF(40, 150)); host_impl_->UnregisterScrollbarAnimationController(root_scroll->element_id()); - host_impl_->MouseUp(); + host_impl_->MouseUp(gfx::PointF(40, 150)); } TEST_F(LayerTreeHostImplTest, @@ -13859,8 +14086,13 @@ class TestRenderFrameMetadataObserver : public RenderFrameMetadataObserver { public: explicit TestRenderFrameMetadataObserver(bool increment_counter) : increment_counter_(increment_counter) {} + TestRenderFrameMetadataObserver(const TestRenderFrameMetadataObserver&) = + delete; ~TestRenderFrameMetadataObserver() override {} + TestRenderFrameMetadataObserver& operator=( + const TestRenderFrameMetadataObserver&) = delete; + void BindToCurrentThread() override {} void OnRenderFrameSubmission( const RenderFrameMetadata& render_frame_metadata, @@ -13878,8 +14110,6 @@ class TestRenderFrameMetadataObserver : public RenderFrameMetadataObserver { private: bool increment_counter_; base::Optional<RenderFrameMetadata> last_metadata_; - - DISALLOW_COPY_AND_ASSIGN(TestRenderFrameMetadataObserver); }; TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToRenderFrameMetadata) { @@ -14071,16 +14301,19 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { rotate.Rotate(45); surface_child1->test_properties()->transform = rotate; surface_child1->SetDrawsContent(true); + surface_child1->SetHitTestable(true); surface_child1->SetSurfaceHitTestable(true); surface_child2->test_properties()->position = gfx::PointF(450, 300); surface_child2->SetBounds(gfx::Size(100, 100)); surface_child2->SetDrawsContent(true); + surface_child2->SetHitTestable(true); surface_child2->SetSurfaceHitTestable(true); overlapping_layer->test_properties()->position = gfx::PointF(500, 350); overlapping_layer->SetBounds(gfx::Size(200, 200)); overlapping_layer->SetDrawsContent(true); + overlapping_layer->SetHitTestable(true); viz::LocalSurfaceId child_local_surface_id(2, base::UnguessableToken::Create()); @@ -14109,6 +14342,8 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { ->AddChild(std::move(overlapping_layer)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); + draw_property_utils::ComputeEffects( + &host_impl_->active_tree()->property_trees()->effect_tree); constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); @@ -14155,6 +14390,259 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { hit_test_region_list->regions[0].rect.ToString()); } +TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, PointerEvents) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + + // The structure of the layer tree: + // +-Root (1024x768) + // +---surface_child1 (0, 0), 100x100 + // +---overlapping_surface_child2 (50, 50), 100x100, pointer-events: none, + // does not generate hit test region + std::unique_ptr<SurfaceLayerImpl> surface_child1 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 2); + std::unique_ptr<SurfaceLayerImpl> surface_child2 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + + host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768)); + + surface_child1->test_properties()->position = gfx::PointF(0, 0); + surface_child1->SetBounds(gfx::Size(100, 100)); + surface_child1->SetDrawsContent(true); + surface_child1->SetHitTestable(true); + surface_child1->SetSurfaceHitTestable(true); + surface_child1->SetHasPointerEventsNone(false); + + surface_child2->test_properties()->position = gfx::PointF(50, 50); + surface_child2->SetBounds(gfx::Size(100, 100)); + surface_child2->SetDrawsContent(true); + surface_child2->SetHitTestable(true); + surface_child2->SetSurfaceHitTestable(false); + surface_child2->SetHasPointerEventsNone(true); + + viz::LocalSurfaceId child_local_surface_id(2, + base::UnguessableToken::Create()); + viz::FrameSinkId frame_sink_id(2, 0); + viz::SurfaceId child_surface_id(frame_sink_id, child_local_surface_id); + surface_child1->SetRange(viz::SurfaceRange(base::nullopt, child_surface_id), + base::nullopt); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child1)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child2)); + + constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->UpdateDrawProperties(); + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + // Generating HitTestRegionList should have been enabled for this test. + ASSERT_TRUE(hit_test_region_list); + + uint32_t expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestMine; + EXPECT_EQ(expected_flags, hit_test_region_list->flags); + EXPECT_EQ(kFrameRect, hit_test_region_list->bounds); + // Since |surface_child2| is not |surface_hit_testable|, it does not + // contribute to a hit test region. Although it overlaps |surface_child1|, it + // does not make |surface_child1| kHitTestAsk because it has pointer-events + // none property. + EXPECT_EQ(1u, hit_test_region_list->regions.size()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[0].frame_sink_id); + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[0].flags); + 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()); +} + +TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, ComplexPage) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + + // The structure of the layer tree: + // +-Root (1024x768) + // +---surface_child (0, 0), 100x100 + // +---100x non overlapping layers (110, 110), 1x1 + std::unique_ptr<SurfaceLayerImpl> surface_child = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 2); + + host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768)); + + surface_child->test_properties()->position = gfx::PointF(0, 0); + surface_child->SetBounds(gfx::Size(100, 100)); + surface_child->SetDrawsContent(true); + surface_child->SetHitTestable(true); + surface_child->SetSurfaceHitTestable(true); + surface_child->SetHasPointerEventsNone(false); + + viz::LocalSurfaceId child_local_surface_id(2, + base::UnguessableToken::Create()); + viz::FrameSinkId frame_sink_id(2, 0); + viz::SurfaceId child_surface_id(frame_sink_id, child_local_surface_id); + surface_child->SetRange(viz::SurfaceRange(base::nullopt, child_surface_id), + base::nullopt); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child)); + + // Create 101 non overlapping layers. + for (size_t i = 0; i <= 100; ++i) { + std::unique_ptr<LayerImpl> layer = + LayerImpl::Create(host_impl_->active_tree(), i + 3); + layer->test_properties()->position = gfx::PointF(110, 110); + layer->SetBounds(gfx::Size(1, 1)); + layer->SetDrawsContent(true); + layer->SetHitTestable(true); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(layer)); + } + + constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->UpdateDrawProperties(); + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + // Generating HitTestRegionList should have been enabled for this test. + ASSERT_TRUE(hit_test_region_list); + + uint32_t expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestMine; + EXPECT_EQ(expected_flags, hit_test_region_list->flags); + EXPECT_EQ(kFrameRect, hit_test_region_list->bounds); + EXPECT_EQ(1u, hit_test_region_list->regions.size()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[0].frame_sink_id); + // Since the layer count is greater than 100, in order to save time, we do not + // check whether each layer overlaps the surface layer, instead, we are being + // conservative and make the surface layer slow hit testing. + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface | + viz::HitTestRegionFlags::kHitTestAsk; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[0].flags); + 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()); +} + +TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, InvalidFrameSinkId) { + // Setup surface layers in LayerTreeHostImpl. + host_impl_->CreatePendingTree(); + host_impl_->ActivateSyncTree(); + + // The structure of the layer tree: + // +-Root (1024x768) + // +---surface_child1 (0, 0), 100x100 + // +---surface_child2 (0, 0), 50x50, frame_sink_id = (0, 0) + std::unique_ptr<SurfaceLayerImpl> surface_child1 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 2); + + host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768)); + + surface_child1->test_properties()->position = gfx::PointF(0, 0); + surface_child1->SetBounds(gfx::Size(100, 100)); + surface_child1->SetDrawsContent(true); + surface_child1->SetHitTestable(true); + surface_child1->SetSurfaceHitTestable(true); + surface_child1->SetHasPointerEventsNone(false); + + viz::LocalSurfaceId child_local_surface_id(2, + base::UnguessableToken::Create()); + viz::FrameSinkId frame_sink_id(2, 0); + viz::SurfaceId child_surface_id(frame_sink_id, child_local_surface_id); + surface_child1->SetRange(viz::SurfaceRange(base::nullopt, child_surface_id), + base::nullopt); + + std::unique_ptr<SurfaceLayerImpl> surface_child2 = + SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); + + surface_child2->test_properties()->position = gfx::PointF(0, 0); + surface_child2->SetBounds(gfx::Size(50, 50)); + surface_child2->SetDrawsContent(true); + surface_child2->SetHitTestable(true); + surface_child2->SetSurfaceHitTestable(true); + surface_child2->SetHasPointerEventsNone(false); + + surface_child2->SetRange(viz::SurfaceRange(base::nullopt, viz::SurfaceId()), + base::nullopt); + + std::unique_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + host_impl_->active_tree()->SetRootLayerForTesting(std::move(root)); + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child1)); + + host_impl_->active_tree() + ->root_layer_for_testing() + ->test_properties() + ->AddChild(std::move(surface_child2)); + + constexpr gfx::Rect kFrameRect(0, 0, 1024, 768); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + host_impl_->active_tree()->UpdateDrawProperties(); + base::Optional<viz::HitTestRegionList> hit_test_region_list = + host_impl_->BuildHitTestData(); + // Generating HitTestRegionList should have been enabled for this test. + ASSERT_TRUE(hit_test_region_list); + + uint32_t expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestMine; + EXPECT_EQ(expected_flags, hit_test_region_list->flags); + EXPECT_EQ(kFrameRect, hit_test_region_list->bounds); + EXPECT_EQ(1u, hit_test_region_list->regions.size()); + + EXPECT_EQ(child_surface_id.frame_sink_id(), + hit_test_region_list->regions[0].frame_sink_id); + // We do not populate hit test region for a surface layer with invalid frame + // sink id to avoid deserialization failure. Instead we make the overlapping + // hit test region kHitTestAsk. + expected_flags = viz::HitTestRegionFlags::kHitTestMouse | + viz::HitTestRegionFlags::kHitTestTouch | + viz::HitTestRegionFlags::kHitTestChildSurface | + viz::HitTestRegionFlags::kHitTestAsk; + EXPECT_EQ(expected_flags, hit_test_region_list->regions[0].flags); + 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()); +} + TEST_F(LayerTreeHostImplTest, ImplThreadPhaseUponImplSideInvalidation) { LayerTreeSettings settings = DefaultSettings(); CreateHostImpl(settings, CreateLayerTreeFrameSink()); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc index 41c663d73fb..4819bbe2825 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc @@ -216,7 +216,7 @@ class LayerTreeHostBlendingPixelTest if (test_type_ != PIXEL_TEST_GL && flags & kForceShaders) return; - SCOPED_TRACE(test_type_ == PIXEL_TEST_GL ? "GL" : "Software"); + SCOPED_TRACE(TestTypeToString(test_type_)); SCOPED_TRACE(SkBlendMode_Name(current_blend_mode())); scoped_refptr<SolidColorLayer> root = CreateSolidColorLayer( diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc index 7843440be5e..32c04b5e286 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -17,9 +17,80 @@ namespace cc { namespace { -class LayerTreeHostFiltersPixelTest : public LayerTreePixelTest {}; +class LayerTreeHostFiltersPixelTest + : public LayerTreePixelTest, + public ::testing::WithParamInterface<LayerTreePixelTest::PixelTestType> { + protected: + void InitializeSettings(LayerTreeSettings* settings) override { + LayerTreePixelTest::InitializeSettings(settings); + // Required so that device scale is inherited by content scale. True for + // most tests, but can be overwritten before RunPixelTest() is called. + settings->layer_transforms_should_scale_layer_contents = + layer_transforms_should_scale_layer_contents_; + } + + LayerTreePixelTest::PixelTestType GetPixelTestType() { return GetParam(); } + + // Text string for graphics backend of the RendererType. Suitable for + // generating separate base line file paths. + const char* GetRendererSuffix() { + switch (GetPixelTestType()) { + case LayerTreePixelTest::PIXEL_TEST_GL: + return "gl"; + case LayerTreePixelTest::PIXEL_TEST_SKIA_GL: + return "skia"; + case LayerTreePixelTest::PIXEL_TEST_SOFTWARE: + return "sw"; + } + } + + scoped_refptr<SolidColorLayer> BuildFilterWithGiantCropRect( + bool masks_to_bounds) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(50, 50, 100, 100), SK_ColorRED); + + // This matrix swaps the red and green channels, and has a slight + // translation in the alpha component, so that it affects transparent + // pixels. + SkScalar matrix[20] = { + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 20.0f, + }; -TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRect) { + FilterOperations filters; + SkImageFilter::CropRect cropRect( + SkRect::MakeXYWH(-40000, -40000, 80000, 80000)); + filters.Append(FilterOperation::CreateReferenceFilter( + sk_make_sp<ColorFilterPaintFilter>( + SkColorFilters::MatrixRowMajor255(matrix), nullptr, &cropRect))); + filter_layer->SetFilters(filters); + background->SetMasksToBounds(masks_to_bounds); + background->AddChild(filter_layer); + + return background; + } + + bool layer_transforms_should_scale_layer_contents_ = true; +}; + +// TODO(crbug.com/948128): Enable these tests for Skia. +INSTANTIATE_TEST_SUITE_P( + , + LayerTreeHostFiltersPixelTest, + ::testing::Values(LayerTreePixelTest::PIXEL_TEST_GL, + LayerTreePixelTest::PIXEL_TEST_SOFTWARE)); + +class LayerTreeHostFiltersPixelTestGPU : public LayerTreeHostFiltersPixelTest { +}; + +// TODO(crbug.com/948128): Enable these tests for Skia. +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostFiltersPixelTestGPU, + ::testing::Values(LayerTreePixelTest::PIXEL_TEST_GL)); + +TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRect) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( gfx::Rect(200, 200), SK_ColorWHITE); @@ -55,11 +126,11 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRect) { small_error_allowed)); #endif - RunPixelTest(PIXEL_TEST_GL, background, + RunPixelTest(GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur.png"))); } -TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRounded) { +TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRounded) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); @@ -95,11 +166,11 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRounded) { #endif RunPixelTest( - PIXEL_TEST_GL, background, + GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_rounded.png"))); } -TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOutsets) { +TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurOutsets) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( gfx::Rect(200, 200), SK_ColorWHITE); @@ -144,11 +215,11 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOutsets) { #endif RunPixelTest( - PIXEL_TEST_GL, background, + GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_outsets.png"))); } -TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOffAxis) { +TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurOffAxis) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT); @@ -212,26 +283,19 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOffAxis) { #endif RunPixelTest( - PIXEL_TEST_GL, background, + GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_off_axis.png"))); } class LayerTreeHostFiltersScaledPixelTest : public LayerTreeHostFiltersPixelTest { - void InitializeSettings(LayerTreeSettings* settings) override { - // Required so that device scale is inherited by content scale. - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { SetInitialDeviceScaleFactor(device_scale_factor_); LayerTreePixelTest::SetupTree(); } protected: - void RunPixelTestType(int content_size, - float device_scale_factor, - PixelTestType test_type) { + void RunPixelTestType(int content_size, float device_scale_factor) { int half_content = content_size / 2; scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( @@ -254,861 +318,641 @@ class LayerTreeHostFiltersScaledPixelTest device_scale_factor_ = device_scale_factor; RunPixelTest( - test_type, - background, + GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png"))); } float device_scale_factor_; }; -TEST_F(LayerTreeHostFiltersScaledPixelTest, StandardDpi_GL) { - RunPixelTestType(100, 1.f, PIXEL_TEST_GL); -} - -TEST_F(LayerTreeHostFiltersScaledPixelTest, StandardDpi_Software) { - RunPixelTestType(100, 1.f, PIXEL_TEST_SOFTWARE); -} +// TODO(crbug.com/948128): Enable these tests for Skia. +INSTANTIATE_TEST_SUITE_P( + , + LayerTreeHostFiltersScaledPixelTest, + ::testing::Values(LayerTreePixelTest::PIXEL_TEST_GL, + LayerTreePixelTest::PIXEL_TEST_SOFTWARE)); -TEST_F(LayerTreeHostFiltersScaledPixelTest, HiDpi_GL) { - RunPixelTestType(50, 2.f, PIXEL_TEST_GL); +TEST_P(LayerTreeHostFiltersScaledPixelTest, StandardDpi) { + RunPixelTestType(100, 1.f); } -TEST_F(LayerTreeHostFiltersScaledPixelTest, HiDpi_Software) { - RunPixelTestType(50, 2.f, PIXEL_TEST_SOFTWARE); +TEST_P(LayerTreeHostFiltersScaledPixelTest, HiDpi) { + RunPixelTestType(50, 2.f); } -class LayerTreeHostNullFilterPixelTest : public LayerTreeHostFiltersPixelTest { - void InitializeSettings(LayerTreeSettings* settings) override {} - - protected: - void RunPixelTestType(PixelTestType test_type) { - scoped_refptr<SolidColorLayer> foreground = - CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorGREEN); - - FilterOperations filters; - filters.Append(FilterOperation::CreateReferenceFilter(nullptr)); - foreground->SetFilters(filters); +TEST_P(LayerTreeHostFiltersPixelTest, NullFilter) { + layer_transforms_should_scale_layer_contents_ = false; - RunPixelTest(test_type, foreground, - base::FilePath(FILE_PATH_LITERAL("green.png"))); - } -}; + scoped_refptr<SolidColorLayer> foreground = + CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorGREEN); -TEST_F(LayerTreeHostNullFilterPixelTest, GL) { - RunPixelTestType(PIXEL_TEST_GL); -} + FilterOperations filters; + filters.Append(FilterOperation::CreateReferenceFilter(nullptr)); + foreground->SetFilters(filters); -TEST_F(LayerTreeHostNullFilterPixelTest, Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE); + RunPixelTest(GetPixelTestType(), foreground, + base::FilePath(FILE_PATH_LITERAL("green.png"))); } -class LayerTreeHostCroppedFilterPixelTest - : public LayerTreeHostFiltersPixelTest { - void InitializeSettings(LayerTreeSettings* settings) override {} - - protected: - void RunPixelTestType(PixelTestType test_type) { - scoped_refptr<SolidColorLayer> foreground = - CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorGREEN); - - // Check that a filter with a zero-height crop rect crops out its - // result completely. - FilterOperations filters; - SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 0)); - sk_sp<PaintFilter> offset( - sk_make_sp<OffsetPaintFilter>(0, 0, nullptr, &cropRect)); - filters.Append(FilterOperation::CreateReferenceFilter(offset)); - foreground->SetFilters(filters); +TEST_P(LayerTreeHostFiltersPixelTest, CroppedFilter) { + layer_transforms_should_scale_layer_contents_ = false; - RunPixelTest(test_type, foreground, - base::FilePath(FILE_PATH_LITERAL("white.png"))); - } -}; + scoped_refptr<SolidColorLayer> foreground = + CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorGREEN); -TEST_F(LayerTreeHostCroppedFilterPixelTest, GL) { - RunPixelTestType(PIXEL_TEST_GL); -} + // Check that a filter with a zero-height crop rect crops out its + // result completely. + FilterOperations filters; + SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 0)); + sk_sp<PaintFilter> offset( + sk_make_sp<OffsetPaintFilter>(0, 0, nullptr, &cropRect)); + filters.Append(FilterOperation::CreateReferenceFilter(offset)); + foreground->SetFilters(filters); -TEST_F(LayerTreeHostCroppedFilterPixelTest, Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE); + RunPixelTest(GetPixelTestType(), foreground, + base::FilePath(FILE_PATH_LITERAL("white.png"))); } -class ImageFilterClippedPixelTest : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW); - - scoped_refptr<SolidColorLayer> foreground = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED); - background->AddChild(foreground); - - SkScalar matrix[20]; - memset(matrix, 0, 20 * sizeof(matrix[0])); - // This filter does a red-blue swap, so the foreground becomes blue. - matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1; - // We filter only the bottom 200x100 pixels of the foreground. - SkImageFilter::CropRect crop_rect(SkRect::MakeXYWH(0, 100, 200, 100)); - FilterOperations filters; - filters.Append(FilterOperation::CreateReferenceFilter( - sk_make_sp<ColorFilterPaintFilter>( - SkColorFilter::MakeMatrixFilterRowMajor255(matrix), nullptr, - &crop_rect))); - - // Make the foreground layer's render surface be clipped by the background - // layer. - background->SetMasksToBounds(true); - foreground->SetFilters(filters); - - // Then we translate the foreground up by 100 pixels in Y, so the cropped - // region is moved to to the top. This ensures that the crop rect is being - // correctly transformed in skia by the amount of clipping that the - // compositor performs. - gfx::Transform transform; - transform.Translate(0.0, -100.0); - foreground->SetTransform(transform); +TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterClipped) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW); + + scoped_refptr<SolidColorLayer> foreground = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED); + background->AddChild(foreground); + + SkScalar matrix[20]; + memset(matrix, 0, 20 * sizeof(matrix[0])); + // This filter does a red-blue swap, so the foreground becomes blue. + matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1; + // We filter only the bottom 200x100 pixels of the foreground. + SkImageFilter::CropRect crop_rect(SkRect::MakeXYWH(0, 100, 200, 100)); + FilterOperations filters; + filters.Append( + FilterOperation::CreateReferenceFilter(sk_make_sp<ColorFilterPaintFilter>( + SkColorFilters::MatrixRowMajor255(matrix), nullptr, &crop_rect))); - RunPixelTest(test_type, - background, - base::FilePath(FILE_PATH_LITERAL("blue_yellow.png"))); - } -}; + // Make the foreground layer's render surface be clipped by the background + // layer. + background->SetMasksToBounds(true); + foreground->SetFilters(filters); -TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_GL) { - RunPixelTestType(PIXEL_TEST_GL); -} + // Then we translate the foreground up by 100 pixels in Y, so the cropped + // region is moved to to the top. This ensures that the crop rect is being + // correctly transformed in skia by the amount of clipping that the + // compositor performs. + gfx::Transform transform; + transform.Translate(0.0, -100.0); + foreground->SetTransform(transform); -TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE); + RunPixelTest(GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("blue_yellow.png"))); } -class ImageFilterNonZeroOriginPixelTest : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW); - - scoped_refptr<SolidColorLayer> foreground = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED); - background->AddChild(foreground); - - SkScalar matrix[20]; - memset(matrix, 0, 20 * sizeof(matrix[0])); - // This filter does a red-blue swap, so the foreground becomes blue. - matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1; - // Set up a crop rec to filter the bottom 200x100 pixels of the foreground. - SkImageFilter::CropRect crop_rect(SkRect::MakeXYWH(0, 100, 200, 100)); - FilterOperations filters; - filters.Append(FilterOperation::CreateReferenceFilter( - sk_make_sp<ColorFilterPaintFilter>( - SkColorFilter::MakeMatrixFilterRowMajor255(matrix), nullptr, - &crop_rect))); +TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterNonZeroOrigin) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW); + + scoped_refptr<SolidColorLayer> foreground = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED); + background->AddChild(foreground); + + SkScalar matrix[20]; + memset(matrix, 0, 20 * sizeof(matrix[0])); + // This filter does a red-blue swap, so the foreground becomes blue. + matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1; + // Set up a crop rec to filter the bottom 200x100 pixels of the foreground. + SkImageFilter::CropRect crop_rect(SkRect::MakeXYWH(0, 100, 200, 100)); + FilterOperations filters; + filters.Append( + FilterOperation::CreateReferenceFilter(sk_make_sp<ColorFilterPaintFilter>( + SkColorFilters::MatrixRowMajor255(matrix), nullptr, &crop_rect))); - // Make the foreground layer's render surface be clipped by the background - // layer. - background->SetMasksToBounds(true); - foreground->SetFilters(filters); + // Make the foreground layer's render surface be clipped by the background + // layer. + background->SetMasksToBounds(true); + foreground->SetFilters(filters); - // Now move the filters origin up by 100 pixels, so the crop rect is - // applied only to the top 100 pixels, not the bottom. - foreground->SetFiltersOrigin(gfx::PointF(0.0f, -100.0f)); + // Now move the filters origin up by 100 pixels, so the crop rect is + // applied only to the top 100 pixels, not the bottom. + foreground->SetFiltersOrigin(gfx::PointF(0.0f, -100.0f)); - RunPixelTest(test_type, background, - base::FilePath(FILE_PATH_LITERAL("blue_yellow.png"))); - } -}; - -TEST_F(ImageFilterNonZeroOriginPixelTest, ImageFilterNonZeroOrigin_GL) { - RunPixelTestType(PIXEL_TEST_GL); -} - -TEST_F(ImageFilterNonZeroOriginPixelTest, ImageFilterNonZeroOrigin_Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE); + RunPixelTest(GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("blue_yellow.png"))); } -class ImageScaledBackdropFilter : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); +TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterScaled) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); - gfx::Rect rect(50, 50, 100, 100); + gfx::Rect rect(50, 50, 100, 100); - const int kInset = 3; - for (int i = 0; !rect.IsEmpty(); ++i) { - scoped_refptr<SolidColorLayer> layer = - CreateSolidColorLayer(rect, (i & 1) ? SK_ColorWHITE : SK_ColorRED); + const int kInset = 3; + for (int i = 0; !rect.IsEmpty(); ++i) { + scoped_refptr<SolidColorLayer> layer = + CreateSolidColorLayer(rect, (i & 1) ? SK_ColorWHITE : SK_ColorRED); - gfx::Transform transform; - transform.Translate(rect.width() / 2.0, rect.height() / 2.0); - transform.RotateAboutZAxis(30.0); - transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); - layer->SetTransform(transform); + gfx::Transform transform; + transform.Translate(rect.width() / 2.0, rect.height() / 2.0); + transform.RotateAboutZAxis(30.0); + transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); + layer->SetTransform(transform); - background->AddChild(layer); + background->AddChild(layer); - rect.Inset(kInset, kInset); - } + rect.Inset(kInset, kInset); + } - scoped_refptr<SolidColorLayer> filter = - CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorTRANSPARENT); + scoped_refptr<SolidColorLayer> filter = + CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorTRANSPARENT); - background->AddChild(filter); + background->AddChild(filter); - // Apply a scale to |background| so that we can see any scaling artifacts - // that may appear. - gfx::Transform background_transform; - static float scale = 1.1f; - background_transform.Scale(scale, scale); - background->SetTransform(background_transform); + // Apply a scale to |background| so that we can see any scaling artifacts + // that may appear. + gfx::Transform background_transform; + static float scale = 1.1f; + background_transform.Scale(scale, scale); + background->SetTransform(background_transform); - FilterOperations filters; - filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); - filter->SetBackdropFilters(filters); - filter->SetBackdropFilterBounds(gfx::RRectF()); + FilterOperations filters; + filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); + filter->SetBackdropFilters(filters); + filter->SetBackdropFilterBounds(gfx::RRectF()); #if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) - // Windows has 153 pixels off by at most 2: crbug.com/225027 - float percentage_pixels_large_error = 0.3825f; // 153px / (200*200) - int large_error_allowed = 2; + // Windows has 153 pixels off by at most 2: crbug.com/225027 + float percentage_pixels_large_error = 0.3825f; // 153px / (200*200) + int large_error_allowed = 2; #elif defined(_MIPS_ARCH_LOONGSON) - // Loongson has 2 pixels off by at most 2: crbug.com/819075 - float percentage_pixels_large_error = 0.005f; // 2px / (200*200) - int large_error_allowed = 2; + // Loongson has 2 pixels off by at most 2: crbug.com/819075 + float percentage_pixels_large_error = 0.005f; // 2px / (200*200) + int large_error_allowed = 2; #else - float percentage_pixels_large_error = 0.0325f; // 13px / (200*200) - int large_error_allowed = 1; + float percentage_pixels_large_error = 0.0325f; // 13px / (200*200) + int large_error_allowed = 1; #endif - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 1.f; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 1.f; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); #endif - RunPixelTest(test_type, background, image_name); - } -}; - -TEST_F(ImageScaledBackdropFilter, ImageFilterScaled_GL) { - RunPixelTestType(PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL( - "backdrop_filter_on_scaled_layer_gl.png"))); + RunPixelTest( + GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("backdrop_filter_on_scaled_layer_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -TEST_F(ImageScaledBackdropFilter, ImageFilterScaled_Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL( - "backdrop_filter_on_scaled_layer_sw.png"))); -} +TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterRotated) { + // Add a white background with a rotated red rect in the center. + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); -class ImageBackdropFilter : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - // Add a white background with a rotated red rect in the center. - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); + gfx::Rect rect(50, 50, 100, 100); - gfx::Rect rect(50, 50, 100, 100); + scoped_refptr<SolidColorLayer> layer = + CreateSolidColorLayer(rect, SK_ColorRED); - scoped_refptr<SolidColorLayer> layer = - CreateSolidColorLayer(rect, SK_ColorRED); + gfx::Transform transform; + transform.Translate(rect.width() / 2.0, rect.height() / 2.0); + transform.RotateAboutZAxis(30.0); + transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); + layer->SetTransform(transform); - gfx::Transform transform; - transform.Translate(rect.width() / 2.0, rect.height() / 2.0); - transform.RotateAboutZAxis(30.0); - transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); - layer->SetTransform(transform); - - background->AddChild(layer); - - // Add a slightly transparent blue layer. - SkColor transparent_blue = SkColorSetARGB(0x23, 0x00, 0x00, 0xFF); - scoped_refptr<SolidColorLayer> filter_layer = - CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), transparent_blue); - - // Add some rotation so that we can see that it blurs only under the layer. - gfx::Transform transform_filter; - transform_filter.RotateAboutZAxis(10.0); - filter_layer->SetTransform(transform_filter); + background->AddChild(layer); - // Add a blur filter to the blue layer. - FilterOperations filters; - filters.Append(FilterOperation::CreateBlurFilter( - 5.0f, SkBlurImageFilter::kClamp_TileMode)); - filter_layer->SetBackdropFilters(filters); - // TODO(916311): Adding filter bounds here should work, but it clips - // the corner of the red box. - // gfx::RectF backdrop_filter_bounds(gfx::SizeF(filter_layer->bounds())); - gfx::RRectF backdrop_filter_bounds; - filter_layer->SetBackdropFilterBounds(backdrop_filter_bounds); + // Add a slightly transparent blue layer. + SkColor transparent_blue = SkColorSetARGB(0x23, 0x00, 0x00, 0xFF); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), transparent_blue); - background->AddChild(filter_layer); + // Add some rotation so that we can see that it blurs only under the layer. + gfx::Transform transform_filter; + transform_filter.RotateAboutZAxis(10.0); + filter_layer->SetTransform(transform_filter); - // Allow some fuzziness so that this doesn't fail when Skia makes minor - // changes to blur or rectangle rendering. - float percentage_pixels_large_error = 4.f; - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 2.f; - int large_error_allowed = 2; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); - - RunPixelTest(test_type, background, image_name); - } -}; + // Add a blur filter to the blue layer. + FilterOperations filters; + filters.Append(FilterOperation::CreateBlurFilter( + 5.0f, SkBlurImageFilter::kClamp_TileMode)); + filter_layer->SetBackdropFilters(filters); + // TODO(916311): Adding filter bounds here should work, but it clips + // the corner of the red box. + // gfx::RectF backdrop_filter_bounds(gfx::SizeF(filter_layer->bounds())); + gfx::RRectF backdrop_filter_bounds; + filter_layer->SetBackdropFilterBounds(backdrop_filter_bounds); + + background->AddChild(filter_layer); + + // Allow some fuzziness so that this doesn't fail when Skia makes minor + // changes to blur or rectangle rendering. + float percentage_pixels_large_error = 4.f; + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 2.f; + int large_error_allowed = 2; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); -TEST_F(ImageBackdropFilter, BackdropFilterRotated_GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("backdrop_filter_rotated_gl.png"))); + RunPixelTest(GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("backdrop_filter_rotated_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -TEST_F(ImageBackdropFilter, BackdropFilterRotated_Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("backdrop_filter_rotated_sw.png"))); -} +TEST_P(LayerTreeHostFiltersPixelTest, ImageRenderSurfaceScaled) { + // A filter will cause a render surface to be used. Here we force the + // render surface on, and scale the result to make sure that we rasterize at + // the correct resolution. + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorBLUE); -class ImageScaledRenderSurface : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - // A filter will cause a render surface to be used. Here we force the - // render surface on, and scale the result to make sure that we rasterize at - // the correct resolution. - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorBLUE); + scoped_refptr<SolidColorLayer> render_surface_layer = + CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE); - scoped_refptr<SolidColorLayer> render_surface_layer = - CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE); + gfx::Rect rect(50, 50, 100, 100); - gfx::Rect rect(50, 50, 100, 100); + scoped_refptr<SolidColorLayer> child = + CreateSolidColorLayer(rect, SK_ColorRED); - scoped_refptr<SolidColorLayer> child = - CreateSolidColorLayer(rect, SK_ColorRED); + gfx::Transform transform; + transform.Translate(rect.width() / 2.0, rect.height() / 2.0); + transform.RotateAboutZAxis(30.0); + transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); + child->SetTransform(transform); - gfx::Transform transform; - transform.Translate(rect.width() / 2.0, rect.height() / 2.0); - transform.RotateAboutZAxis(30.0); - transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); - child->SetTransform(transform); - - render_surface_layer->AddChild(child); - - gfx::Transform render_surface_transform; - render_surface_transform.Scale(1.5f, 1.5f); - render_surface_layer->SetTransform(render_surface_transform); - render_surface_layer->SetForceRenderSurfaceForTesting(true); - - background->AddChild(render_surface_layer); - - // Software has some huge differences in the AA'd pixels on the different - // trybots. See crbug.com/452198. - float percentage_pixels_large_error = 0.686f; - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 16.f; - int large_error_allowed = 17; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); - - RunPixelTest(test_type, background, image_name); - } -}; + render_surface_layer->AddChild(child); -TEST_F(ImageScaledRenderSurface, ImageRenderSurfaceScaled_GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_gl.png"))); -} + gfx::Transform render_surface_transform; + render_surface_transform.Scale(1.5f, 1.5f); + render_surface_layer->SetTransform(render_surface_transform); + render_surface_layer->SetForceRenderSurfaceForTesting(true); -TEST_F(ImageScaledRenderSurface, ImageRenderSurfaceScaled_Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_sw.png"))); -} + background->AddChild(render_surface_layer); -class ZoomFilterTest : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> root = - CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); - - // Create the pattern. Two blue/yellow side by side blocks with a horizontal - // green strip. - scoped_refptr<SolidColorLayer> left = - CreateSolidColorLayer(gfx::Rect(0, 0, 100, 150), SK_ColorBLUE); - root->AddChild(left); - scoped_refptr<SolidColorLayer> right = - CreateSolidColorLayer(gfx::Rect(100, 0, 200, 150), SK_ColorYELLOW); - root->AddChild(right); - scoped_refptr<SolidColorLayer> horizontal_strip = - CreateSolidColorLayer(gfx::Rect(0, 10, 300, 10), SK_ColorGREEN); - root->AddChild(horizontal_strip); - - // Test a zoom that extends past the edge of the screen. - scoped_refptr<SolidColorLayer> border_edge_zoom = - CreateSolidColorLayer(gfx::Rect(-10, -10, 50, 50), SK_ColorTRANSPARENT); - FilterOperations border_filters; - border_filters.Append( - FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); - border_edge_zoom->SetBackdropFilters(border_filters); - gfx::RectF border_filter_bounds(gfx::SizeF(border_edge_zoom->bounds())); - border_edge_zoom->SetBackdropFilterBounds( - gfx::RRectF(border_filter_bounds, 0)); - root->AddChild(border_edge_zoom); - - // Test a zoom that extends past the edge of the screen. - scoped_refptr<SolidColorLayer> top_edge_zoom = - CreateSolidColorLayer(gfx::Rect(70, -10, 50, 50), SK_ColorTRANSPARENT); - FilterOperations top_filters; - top_filters.Append( - FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); - top_edge_zoom->SetBackdropFilters(top_filters); - gfx::RectF top_filter_bounds(gfx::SizeF(top_edge_zoom->bounds())); - top_edge_zoom->SetBackdropFilterBounds(gfx::RRectF(top_filter_bounds, 0)); - root->AddChild(top_edge_zoom); - - // Test a zoom that is fully within the screen. - scoped_refptr<SolidColorLayer> contained_zoom = - CreateSolidColorLayer(gfx::Rect(150, 5, 50, 50), SK_ColorTRANSPARENT); - FilterOperations mid_filters; - mid_filters.Append( - FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); - contained_zoom->SetBackdropFilters(mid_filters); - gfx::RectF mid_filter_bounds(gfx::SizeF(contained_zoom->bounds())); - contained_zoom->SetBackdropFilterBounds(gfx::RRectF(mid_filter_bounds, 0)); - root->AddChild(contained_zoom); + // Software has some huge differences in the AA'd pixels on the different + // trybots. See crbug.com/452198. + float percentage_pixels_large_error = 0.686f; + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 16.f; + int large_error_allowed = 17; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); + + RunPixelTest( + GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); +} + +TEST_P(LayerTreeHostFiltersPixelTest, ZoomFilter) { + scoped_refptr<SolidColorLayer> root = + CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); + + // Create the pattern. Two blue/yellow side by side blocks with a horizontal + // green strip. + scoped_refptr<SolidColorLayer> left = + CreateSolidColorLayer(gfx::Rect(0, 0, 100, 150), SK_ColorBLUE); + root->AddChild(left); + scoped_refptr<SolidColorLayer> right = + CreateSolidColorLayer(gfx::Rect(100, 0, 200, 150), SK_ColorYELLOW); + root->AddChild(right); + scoped_refptr<SolidColorLayer> horizontal_strip = + CreateSolidColorLayer(gfx::Rect(0, 10, 300, 10), SK_ColorGREEN); + root->AddChild(horizontal_strip); + + // Test a zoom that extends past the edge of the screen. + scoped_refptr<SolidColorLayer> border_edge_zoom = + CreateSolidColorLayer(gfx::Rect(-10, -10, 50, 50), SK_ColorTRANSPARENT); + FilterOperations border_filters; + border_filters.Append( + FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); + border_edge_zoom->SetBackdropFilters(border_filters); + gfx::RectF border_filter_bounds(gfx::SizeF(border_edge_zoom->bounds())); + border_edge_zoom->SetBackdropFilterBounds( + gfx::RRectF(border_filter_bounds, 0)); + root->AddChild(border_edge_zoom); + + // Test a zoom that extends past the edge of the screen. + scoped_refptr<SolidColorLayer> top_edge_zoom = + CreateSolidColorLayer(gfx::Rect(70, -10, 50, 50), SK_ColorTRANSPARENT); + FilterOperations top_filters; + top_filters.Append( + FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); + top_edge_zoom->SetBackdropFilters(top_filters); + gfx::RectF top_filter_bounds(gfx::SizeF(top_edge_zoom->bounds())); + top_edge_zoom->SetBackdropFilterBounds(gfx::RRectF(top_filter_bounds, 0)); + root->AddChild(top_edge_zoom); + + // Test a zoom that is fully within the screen. + scoped_refptr<SolidColorLayer> contained_zoom = + CreateSolidColorLayer(gfx::Rect(150, 5, 50, 50), SK_ColorTRANSPARENT); + FilterOperations mid_filters; + mid_filters.Append( + FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); + contained_zoom->SetBackdropFilters(mid_filters); + gfx::RectF mid_filter_bounds(gfx::SizeF(contained_zoom->bounds())); + contained_zoom->SetBackdropFilterBounds(gfx::RRectF(mid_filter_bounds, 0)); + root->AddChild(contained_zoom); #if defined(OS_WIN) - // Windows has 1 pixel off by 1: crbug.com/259915 - float percentage_pixels_large_error = 0.00111112f; // 1px / (300*300) - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 1; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + // Windows has 1 pixel off by 1: crbug.com/259915 + float percentage_pixels_large_error = 0.00111112f; // 1px / (300*300) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 1.f; + int large_error_allowed = 1; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); #endif - RunPixelTest(test_type, std::move(root), image_name); - } -}; - -TEST_F(ZoomFilterTest, ZoomFilterTest_GL) { - RunPixelTestType(PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("zoom_filter_gl.png"))); -} - -TEST_F(ZoomFilterTest, ZoomFilterTest_Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("zoom_filter_sw.png"))); + RunPixelTest(GetPixelTestType(), std::move(root), + base::FilePath(FILE_PATH_LITERAL("zoom_filter_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -class RotatedFilterTest : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); +TEST_P(LayerTreeHostFiltersPixelTest, RotatedFilter) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); - gfx::Rect rect(50, 50, 100, 100); + gfx::Rect rect(50, 50, 100, 100); - scoped_refptr<SolidColorLayer> child = - CreateSolidColorLayer(rect, SK_ColorBLUE); + scoped_refptr<SolidColorLayer> child = + CreateSolidColorLayer(rect, SK_ColorBLUE); - gfx::Transform transform; - transform.Translate(50.0f, 50.0f); - transform.RotateAboutZAxis(1.0); - transform.Translate(-50.0f, -50.0f); - child->SetTransform(transform); - FilterOperations filters; - // We need a clamping brightness filter here to force the Skia filter path. - filters.Append(FilterOperation::CreateBrightnessFilter(1.1f)); - filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); - child->SetFilters(filters); + gfx::Transform transform; + transform.Translate(50.0f, 50.0f); + transform.RotateAboutZAxis(1.0); + transform.Translate(-50.0f, -50.0f); + child->SetTransform(transform); + FilterOperations filters; + // We need a clamping brightness filter here to force the Skia filter path. + filters.Append(FilterOperation::CreateBrightnessFilter(1.1f)); + filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); + child->SetFilters(filters); - background->AddChild(child); + background->AddChild(child); #if defined(OS_WIN) - // Windows has 1 pixel off by 1: crbug.com/259915 - float percentage_pixels_large_error = 0.00111112f; // 1px / (300*300) - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 1; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + // Windows has 1 pixel off by 1: crbug.com/259915 + float percentage_pixels_large_error = 0.00111112f; // 1px / (300*300) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 1.f; + int large_error_allowed = 1; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); #endif - RunPixelTest(test_type, background, image_name); - } -}; - -TEST_F(RotatedFilterTest, RotatedFilterTest_GL) { - RunPixelTestType(PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("rotated_filter_gl.png"))); + RunPixelTest(GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("rotated_filter_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -TEST_F(RotatedFilterTest, RotatedFilterTest_Software) { - RunPixelTestType(PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("rotated_filter_sw.png"))); -} - -class RotatedDropShadowFilterTest : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); - - gfx::Rect rect(50, 50, 100, 100); - - // Use a border to defeat solid color detection to force a tile quad. - // This is intended to test render pass removal optimizations. - SolidColorContentLayerClient blue_client(SK_ColorBLUE, rect.size(), 1, - SK_ColorBLACK); - scoped_refptr<PictureLayer> child = PictureLayer::Create(&blue_client); - child->SetBounds(rect.size()); - child->SetPosition(gfx::PointF(rect.origin())); - child->SetIsDrawable(true); - - gfx::Transform transform; - transform.Translate(50.0f, 50.0f); - transform.RotateAboutZAxis(1.0); - transform.Translate(-50.0f, -50.0f); - child->SetTransform(transform); - FilterOperations filters; - filters.Append(FilterOperation::CreateDropShadowFilter( - gfx::Point(10.0f, 10.0f), 0.0f, SK_ColorBLACK)); - child->SetFilters(filters); +TEST_P(LayerTreeHostFiltersPixelTest, RotatedDropShadowFilter) { + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); + + gfx::Rect rect(50, 50, 100, 100); + + // Use a border to defeat solid color detection to force a tile quad. + // This is intended to test render pass removal optimizations. + SolidColorContentLayerClient blue_client(SK_ColorBLUE, rect.size(), 1, + SK_ColorBLACK); + scoped_refptr<PictureLayer> child = PictureLayer::Create(&blue_client); + child->SetBounds(rect.size()); + child->SetPosition(gfx::PointF(rect.origin())); + child->SetIsDrawable(true); + + gfx::Transform transform; + transform.Translate(50.0f, 50.0f); + transform.RotateAboutZAxis(1.0); + transform.Translate(-50.0f, -50.0f); + child->SetTransform(transform); + FilterOperations filters; + filters.Append(FilterOperation::CreateDropShadowFilter( + gfx::Point(10.0f, 10.0f), 0.0f, SK_ColorBLACK)); + child->SetFilters(filters); - background->AddChild(child); + background->AddChild(child); #if defined(OS_WIN) || defined(ARCH_CPU_ARM64) - // Windows and ARM64 have 3 pixels off by 1: crbug.com/259915 - float percentage_pixels_large_error = 0.00333334f; // 3px / (300*300) - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 1; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + // Windows and ARM64 have 3 pixels off by 1: crbug.com/259915 + float percentage_pixels_large_error = 0.00333334f; // 3px / (300*300) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 1.f; + int large_error_allowed = 1; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); #endif - RunPixelTest(test_type, background, image_name); - } -}; - -TEST_F(RotatedDropShadowFilterTest, RotatedDropShadowFilterTest_GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("rotated_drop_shadow_filter_gl.png"))); -} - -TEST_F(RotatedDropShadowFilterTest, RotatedDropShadowFilterTest_Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("rotated_drop_shadow_filter_sw.png"))); -} - -class TranslatedFilterTest : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<Layer> clip = Layer::Create(); - clip->SetBounds(gfx::Size(300, 300)); - clip->SetMasksToBounds(true); - - scoped_refptr<Layer> parent = Layer::Create(); - parent->SetPosition(gfx::PointF(30.f, 30.f)); - - gfx::Rect child_rect(100, 100); - // Use two colors to bypass solid color detection, so we get a tile quad. - // This is intended to test render pass removal optimizations. - FakeContentLayerClient client; - client.set_bounds(child_rect.size()); - PaintFlags flags; - flags.setColor(SK_ColorGREEN); - client.add_draw_rect(child_rect, flags); - flags.setColor(SK_ColorBLUE); - client.add_draw_rect(gfx::Rect(100, 50), flags); - scoped_refptr<PictureLayer> child = PictureLayer::Create(&client); - child->SetBounds(child_rect.size()); - child->SetIsDrawable(true); - FilterOperations filters; - filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); - child->SetFilters(filters); - - // This layer will be clipped by |clip|, so the RenderPass created for - // |child| will only have one visible quad. - scoped_refptr<SolidColorLayer> grand_child = - CreateSolidColorLayer(gfx::Rect(-300, -300, 100, 100), SK_ColorRED); - - child->AddChild(grand_child); - parent->AddChild(child); - clip->AddChild(parent); + RunPixelTest( + GetPixelTestType(), background, + base::FilePath(FILE_PATH_LITERAL("rotated_drop_shadow_filter_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); +} + +TEST_P(LayerTreeHostFiltersPixelTest, TranslatedFilter) { + scoped_refptr<Layer> clip = Layer::Create(); + clip->SetBounds(gfx::Size(300, 300)); + clip->SetMasksToBounds(true); + + scoped_refptr<Layer> parent = Layer::Create(); + parent->SetPosition(gfx::PointF(30.f, 30.f)); + + gfx::Rect child_rect(100, 100); + // Use two colors to bypass solid color detection, so we get a tile quad. + // This is intended to test render pass removal optimizations. + FakeContentLayerClient client; + client.set_bounds(child_rect.size()); + PaintFlags flags; + flags.setColor(SK_ColorGREEN); + client.add_draw_rect(child_rect, flags); + flags.setColor(SK_ColorBLUE); + client.add_draw_rect(gfx::Rect(100, 50), flags); + scoped_refptr<PictureLayer> child = PictureLayer::Create(&client); + child->SetBounds(child_rect.size()); + child->SetIsDrawable(true); + FilterOperations filters; + filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); + child->SetFilters(filters); - RunPixelTest(test_type, clip, image_name); - } -}; + // This layer will be clipped by |clip|, so the RenderPass created for + // |child| will only have one visible quad. + scoped_refptr<SolidColorLayer> grand_child = + CreateSolidColorLayer(gfx::Rect(-300, -300, 100, 100), SK_ColorRED); -TEST_F(TranslatedFilterTest, GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("translated_blue_green_alpha_gl.png"))); -} + child->AddChild(grand_child); + parent->AddChild(child); + clip->AddChild(parent); -TEST_F(TranslatedFilterTest, Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("translated_blue_green_alpha_sw.png"))); + RunPixelTest( + GetPixelTestType(), clip, + base::FilePath(FILE_PATH_LITERAL("translated_blue_green_alpha_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -class EnlargedTextureWithAlphaThresholdFilter - : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - // Rectangles choosen so that if flipped, the test will fail. - gfx::Rect rect1(10, 10, 10, 15); - gfx::Rect rect2(20, 25, 70, 65); - - scoped_refptr<SolidColorLayer> child1 = - CreateSolidColorLayer(rect1, SK_ColorRED); - scoped_refptr<SolidColorLayer> child2 = - CreateSolidColorLayer(rect2, SK_ColorGREEN); - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); - scoped_refptr<SolidColorLayer> filter_layer = - CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); - - // Make sure a transformation does not cause misregistration of the filter - // and source texture. - gfx::Transform filter_transform; - filter_transform.Scale(2.f, 2.f); - filter_layer->SetTransform(filter_transform); - filter_layer->AddChild(child1); - filter_layer->AddChild(child2); - - rect1.Inset(-5, -5); - rect2.Inset(-5, -5); - FilterOperation::ShapeRects alpha_shape = {rect1, rect2}; - FilterOperations filters; - filters.Append( - FilterOperation::CreateAlphaThresholdFilter(alpha_shape, 0.f, 0.f)); - filter_layer->SetFilters(filters); +TEST_P(LayerTreeHostFiltersPixelTest, EnlargedTextureWithAlphaThresholdFilter) { + // Rectangles chosen so that if flipped, the test will fail. + gfx::Rect rect1(10, 10, 10, 15); + gfx::Rect rect2(20, 25, 70, 65); - background->AddChild(filter_layer); + scoped_refptr<SolidColorLayer> child1 = + CreateSolidColorLayer(rect1, SK_ColorRED); + scoped_refptr<SolidColorLayer> child2 = + CreateSolidColorLayer(rect2, SK_ColorGREEN); + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); + + // Make sure a transformation does not cause misregistration of the filter + // and source texture. + gfx::Transform filter_transform; + filter_transform.Scale(2.f, 2.f); + filter_layer->SetTransform(filter_transform); + filter_layer->AddChild(child1); + filter_layer->AddChild(child2); + + rect1.Inset(-5, -5); + rect2.Inset(-5, -5); + FilterOperation::ShapeRects alpha_shape = {rect1, rect2}; + FilterOperations filters; + filters.Append( + FilterOperation::CreateAlphaThresholdFilter(alpha_shape, 0.f, 0.f)); + filter_layer->SetFilters(filters); - // Force the allocation a larger textures. - set_enlarge_texture_amount(gfx::Size(50, 50)); + background->AddChild(filter_layer); - RunPixelTest(test_type, background, image_name); - } -}; + // Force the allocation a larger textures. + set_enlarge_texture_amount(gfx::Size(50, 50)); -TEST_F(EnlargedTextureWithAlphaThresholdFilter, GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png"))); -} - -TEST_F(EnlargedTextureWithAlphaThresholdFilter, Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, + RunPixelTest( + GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png"))); } -class EnlargedTextureWithCropOffsetFilter - : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - // Rectangles choosen so that if flipped, the test will fail. - gfx::Rect rect1(10, 10, 10, 15); - gfx::Rect rect2(20, 25, 70, 65); - - scoped_refptr<SolidColorLayer> child1 = - CreateSolidColorLayer(rect1, SK_ColorRED); - scoped_refptr<SolidColorLayer> child2 = - CreateSolidColorLayer(rect2, SK_ColorGREEN); - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); - scoped_refptr<SolidColorLayer> filter_layer = - CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); - - // Make sure a transformation does not cause misregistration of the filter - // and source texture. - gfx::Transform filter_transform; - filter_transform.Scale(2.f, 2.f); - filter_layer->SetTransform(filter_transform); - filter_layer->AddChild(child1); - filter_layer->AddChild(child2); - - FilterOperations filters; - SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(10, 10, 80, 80)); - filters.Append(FilterOperation::CreateReferenceFilter( - sk_make_sp<OffsetPaintFilter>(0, 0, nullptr, &cropRect))); - filter_layer->SetFilters(filters); +TEST_P(LayerTreeHostFiltersPixelTest, EnlargedTextureWithCropOffsetFilter) { + // Rectangles chosen so that if flipped, the test will fail. + gfx::Rect rect1(10, 10, 10, 15); + gfx::Rect rect2(20, 25, 70, 65); - background->AddChild(filter_layer); + scoped_refptr<SolidColorLayer> child1 = + CreateSolidColorLayer(rect1, SK_ColorRED); + scoped_refptr<SolidColorLayer> child2 = + CreateSolidColorLayer(rect2, SK_ColorGREEN); + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); + + // Make sure a transformation does not cause misregistration of the filter + // and source texture. + gfx::Transform filter_transform; + filter_transform.Scale(2.f, 2.f); + filter_layer->SetTransform(filter_transform); + filter_layer->AddChild(child1); + filter_layer->AddChild(child2); - // Force the allocation a larger textures. - set_enlarge_texture_amount(gfx::Size(50, 50)); + FilterOperations filters; + SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(10, 10, 80, 80)); + filters.Append(FilterOperation::CreateReferenceFilter( + sk_make_sp<OffsetPaintFilter>(0, 0, nullptr, &cropRect))); + filter_layer->SetFilters(filters); - RunPixelTest(test_type, background, image_name); - } -}; + background->AddChild(filter_layer); -TEST_F(EnlargedTextureWithCropOffsetFilter, GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_crop_offset.png"))); -} + // Force the allocation a larger textures. + set_enlarge_texture_amount(gfx::Size(50, 50)); -TEST_F(EnlargedTextureWithCropOffsetFilter, Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, + RunPixelTest( + GetPixelTestType(), background, base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_crop_offset.png"))); } -class BlurFilterWithClip : public LayerTreeHostFiltersPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> child1 = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); - scoped_refptr<SolidColorLayer> child2 = - CreateSolidColorLayer(gfx::Rect(20, 20, 160, 160), SK_ColorWHITE); - scoped_refptr<SolidColorLayer> child3 = - CreateSolidColorLayer(gfx::Rect(40, 40, 20, 30), SK_ColorRED); - scoped_refptr<SolidColorLayer> child4 = - CreateSolidColorLayer(gfx::Rect(60, 70, 100, 90), SK_ColorGREEN); - scoped_refptr<SolidColorLayer> filter_layer = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); +TEST_P(LayerTreeHostFiltersPixelTest, BlurFilterWithClip) { + scoped_refptr<SolidColorLayer> child1 = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); + scoped_refptr<SolidColorLayer> child2 = + CreateSolidColorLayer(gfx::Rect(20, 20, 160, 160), SK_ColorWHITE); + scoped_refptr<SolidColorLayer> child3 = + CreateSolidColorLayer(gfx::Rect(40, 40, 20, 30), SK_ColorRED); + scoped_refptr<SolidColorLayer> child4 = + CreateSolidColorLayer(gfx::Rect(60, 70, 100, 90), SK_ColorGREEN); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); - filter_layer->AddChild(child1); - filter_layer->AddChild(child2); - filter_layer->AddChild(child3); - filter_layer->AddChild(child4); + filter_layer->AddChild(child1); + filter_layer->AddChild(child2); + filter_layer->AddChild(child3); + filter_layer->AddChild(child4); - FilterOperations filters; - filters.Append(FilterOperation::CreateBlurFilter( - 2.f, SkBlurImageFilter::kClamp_TileMode)); - filter_layer->SetFilters(filters); + FilterOperations filters; + filters.Append(FilterOperation::CreateBlurFilter( + 2.f, SkBlurImageFilter::kClamp_TileMode)); + filter_layer->SetFilters(filters); - // Force the allocation a larger textures. - set_enlarge_texture_amount(gfx::Size(50, 50)); + // Force the allocation a larger textures. + set_enlarge_texture_amount(gfx::Size(50, 50)); #if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) - // Windows has 1880 pixels off by 1: crbug.com/259915 - float percentage_pixels_large_error = 4.7f; // 1880px / (200*200) + // Windows has 1880 pixels off by 1: crbug.com/259915 + float percentage_pixels_large_error = 4.7f; // 1880px / (200*200) #else - // Differences in floating point calculation on ARM means a small percentage - // of pixels will have small differences. - float percentage_pixels_large_error = 2.76f; // 1104px / (200*200) + // Differences in floating point calculation on ARM means a small percentage + // of pixels will have small differences. + float percentage_pixels_large_error = 2.76f; // 1104px / (200*200) #endif - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 1.f; - int large_error_allowed = 2; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 1.f; + int large_error_allowed = 2; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); #endif - RunPixelTest(test_type, filter_layer, image_name); - } -}; - -TEST_F(BlurFilterWithClip, GL) { - RunPixelTestType( - PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("blur_filter_with_clip_gl.png"))); + RunPixelTest(GetPixelTestType(), filter_layer, + base::FilePath(FILE_PATH_LITERAL("blur_filter_with_clip_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -TEST_F(BlurFilterWithClip, Software) { - RunPixelTestType( - PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("blur_filter_with_clip_sw.png"))); -} - -class FilterWithGiantCropRectPixelTest : public LayerTreeHostFiltersPixelTest { - protected: - scoped_refptr<SolidColorLayer> BuildFilterWithGiantCropRect( - bool masks_to_bounds) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); - scoped_refptr<SolidColorLayer> filter_layer = - CreateSolidColorLayer(gfx::Rect(50, 50, 100, 100), SK_ColorRED); - - // This matrix swaps the red and green channels, and has a slight - // translation in the alpha component, so that it affects transparent - // pixels. - SkScalar matrix[20] = { - 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 20.0f, - }; - - FilterOperations filters; - SkImageFilter::CropRect cropRect( - SkRect::MakeXYWH(-40000, -40000, 80000, 80000)); - filters.Append(FilterOperation::CreateReferenceFilter( - sk_make_sp<ColorFilterPaintFilter>( - SkColorFilter::MakeMatrixFilterRowMajor255(matrix), nullptr, - &cropRect))); - filter_layer->SetFilters(filters); - background->SetMasksToBounds(masks_to_bounds); - background->AddChild(filter_layer); - - return background; - } -}; - -class FilterWithGiantCropRect : public FilterWithGiantCropRectPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> tree = BuildFilterWithGiantCropRect(true); - RunPixelTest(test_type, tree, image_name); - } -}; - -TEST_F(FilterWithGiantCropRect, GL) { - RunPixelTestType( - PIXEL_TEST_GL, +TEST_P(LayerTreeHostFiltersPixelTestGPU, FilterWithGiantCropRect) { + scoped_refptr<SolidColorLayer> tree = BuildFilterWithGiantCropRect(true); + RunPixelTest( + GetPixelTestType(), tree, base::FilePath(FILE_PATH_LITERAL("filter_with_giant_crop_rect.png"))); } -class FilterWithGiantCropRectNoClip : public FilterWithGiantCropRectPixelTest { - protected: - void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { - scoped_refptr<SolidColorLayer> tree = BuildFilterWithGiantCropRect(false); - RunPixelTest(test_type, tree, image_name); - } -}; - -TEST_F(FilterWithGiantCropRectNoClip, GL) { - RunPixelTestType( - PIXEL_TEST_GL, +TEST_P(LayerTreeHostFiltersPixelTestGPU, FilterWithGiantCropRectNoClip) { + scoped_refptr<SolidColorLayer> tree = BuildFilterWithGiantCropRect(false); + RunPixelTest( + GetPixelTestType(), tree, base::FilePath(FILE_PATH_LITERAL("filter_with_giant_crop_rect.png"))); } @@ -1116,7 +960,6 @@ class BackdropFilterWithDeviceScaleFactorTest : public LayerTreeHostFiltersPixelTest { protected: void RunPixelTestType(float device_scale_factor, - PixelTestType test_type, const base::FilePath& expected_result) { device_scale_factor_ = device_scale_factor; @@ -1139,18 +982,11 @@ class BackdropFilterWithDeviceScaleFactorTest // This should appear as a grid of 4 100x100 squares which are: // BLACK WHITE // DARK GREEN LIGHT GREEN - RunPixelTest(test_type, std::move(root), expected_result); + RunPixelTest(GetPixelTestType(), std::move(root), expected_result); } private: // LayerTreePixelTest overrides - - void InitializeSettings(LayerTreeSettings* settings) override { - LayerTreeHostFiltersPixelTest::InitializeSettings(settings); - // Required so that device scale is inherited by content scale. - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { SetInitialDeviceScaleFactor(device_scale_factor_); LayerTreeHostFiltersPixelTest::SetupTree(); @@ -1159,28 +995,21 @@ class BackdropFilterWithDeviceScaleFactorTest float device_scale_factor_ = 1; }; -TEST_F(BackdropFilterWithDeviceScaleFactorTest, StandardDpi_GL) { - RunPixelTestType( - 1.f, PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png"))); -} - -TEST_F(BackdropFilterWithDeviceScaleFactorTest, StandardDpi_Software) { - RunPixelTestType( - 1.f, PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png"))); -} +// TODO(crbug.com/948128): Enable these tests for Skia. +INSTANTIATE_TEST_SUITE_P( + , + BackdropFilterWithDeviceScaleFactorTest, + ::testing::Values(LayerTreePixelTest::PIXEL_TEST_GL, + LayerTreePixelTest::PIXEL_TEST_SOFTWARE)); -TEST_F(BackdropFilterWithDeviceScaleFactorTest, HiDpi_GL) { +TEST_P(BackdropFilterWithDeviceScaleFactorTest, StandardDpi) { RunPixelTestType( - 2.f, PIXEL_TEST_GL, - base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png"))); + 1.f, base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png"))); } -TEST_F(BackdropFilterWithDeviceScaleFactorTest, HiDpi_Software) { +TEST_P(BackdropFilterWithDeviceScaleFactorTest, HiDpi) { RunPixelTestType( - 2.f, PIXEL_TEST_SOFTWARE, - base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png"))); + 2.f, base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png"))); } } // namespace diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc index 6d363e65e0f..1c94cf36b3e 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc @@ -49,6 +49,8 @@ class PaintedScrollbar : public Scrollbar { int ThumbThickness() const override { return rect_.width(); } int ThumbLength() const override { return rect_.height(); } gfx::Rect TrackRect() const override { return rect_; } + gfx::Rect BackButtonRect() const override { return rect_; } + gfx::Rect ForwardButtonRect() const override { return rect_; } float ThumbOpacity() const override { return 1.f; } bool NeedsPaintPart(ScrollbarPart part) const override { return true; } bool HasTickmarks() const override { return false; } diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 3890622f2f4..1698efbc9fa 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -147,8 +147,8 @@ class LayerTreeHostTestFrameOrdering : public LayerTreeHostTest { enum MainOrder : int { MAIN_START = 1, MAIN_LAYOUT, - MAIN_DID_BEGIN_FRAME, MAIN_COMMIT_COMPLETE, + MAIN_DID_BEGIN_FRAME, MAIN_END, }; @@ -1174,6 +1174,9 @@ class LayerTreeHostTestLayerListSurfaceDamage : public LayerTreeHostTest { child_c_->SetForceRenderSurfaceForTesting(true); child_c_->SetIsDrawable(true); + // TODO(pdr): Do not use the property tree builder for testing in layer list + // mode. This will require rewriting this test to manually build property + // trees. layer_tree_host()->BuildPropertyTreesForTesting(); LayerTreeHostTest::SetupTree(); @@ -8401,6 +8404,9 @@ class LayerTreeHostTestHudLayerWithLayerLists : public LayerTreeHostTest { LayerTreeHostTest::SetupTree(); // Build the property trees for the root layer. + // TODO(pdr): Do not use the property tree builder for testing in layer list + // mode. This will require rewriting this test to manually build property + // trees. layer_tree_host()->BuildPropertyTreesForTesting(); // The HUD layer should not have been setup by the property tree building. @@ -8596,9 +8602,8 @@ class LayerTreeHostTestImageAnimationDrawImageShader : public LayerTreeHostTestImageAnimation { void AddImageOp(const PaintImage& image) override { PaintFlags flags; - flags.setShader( - PaintShader::MakeImage(image, SkShader::TileMode::kRepeat_TileMode, - SkShader::TileMode::kRepeat_TileMode, nullptr)); + flags.setShader(PaintShader::MakeImage(image, SkTileMode::kRepeat, + SkTileMode::kRepeat, nullptr)); content_layer_client_.add_draw_rect(gfx::Rect(500, 500), flags); } }; @@ -8612,8 +8617,8 @@ class LayerTreeHostTestImageAnimationDrawRecordShader record->push<DrawImageOp>(image, 0.f, 0.f, nullptr); PaintFlags flags; flags.setShader(PaintShader::MakePaintRecord( - record, SkRect::MakeWH(500, 500), SkShader::TileMode::kClamp_TileMode, - SkShader::TileMode::kClamp_TileMode, nullptr)); + record, SkRect::MakeWH(500, 500), SkTileMode::kClamp, + SkTileMode::kClamp, nullptr)); content_layer_client_.add_draw_rect(gfx::Rect(500, 500), flags); } }; diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index e38693e10a2..cad1e7288bd 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -793,7 +793,7 @@ class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestAsyncTwoReadbacksWithoutDraw); -class LayerTreeHostCopyRequestTestDeleteTexture +class LayerTreeHostCopyRequestTestDeleteSharedImage : public LayerTreeHostCopyRequestTest { protected: std::unique_ptr<viz::OutputSurface> CreateDisplayOutputSurfaceOnThread( @@ -837,27 +837,30 @@ class LayerTreeHostCopyRequestTestDeleteTexture void InsertCopyRequest() { copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>( viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE, - base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: + base::BindOnce(&LayerTreeHostCopyRequestTestDeleteSharedImage:: ReceiveCopyRequestOutputAndCommit, base::Unretained(this)))); } - void DestroyCopyResultAndCheckNumTextures() { + void DestroyCopyResultAndCheckNumSharedImages() { EXPECT_TRUE(result_); result_ = nullptr; ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: - CheckNumTexturesAfterReadbackDestroyed, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&LayerTreeHostCopyRequestTestDeleteSharedImage:: + CheckNumSharedImagesAfterReadbackDestroyed, + base::Unretained(this))); } - void CheckNumTexturesAfterReadbackDestroyed() { - // After the copy we had |num_textures_after_readback_| many textures, but - // releasing the copy output request should cause the texture in the request - // to be destroyed by the compositor, so we should have 1 less by now. - EXPECT_EQ(num_textures_after_readback_ - 1, - display_context_provider_->TestContextGL()->NumTextures()); + void CheckNumSharedImagesAfterReadbackDestroyed() { + // After the copy we had |num_shared_images_after_readback_| many shared + // images, but releasing the copy output request should cause the shared + // image in the request to be destroyed by the compositor, so we should have + // 1 less by now. + EXPECT_EQ(num_shared_images_after_readback_ - 1, + display_context_provider_->SharedImageInterface() + ->shared_image_count()); // Drop the reference to the context provider on the compositor thread. display_context_provider_ = nullptr; @@ -865,20 +868,20 @@ class LayerTreeHostCopyRequestTestDeleteTexture } void DisplayDidDrawAndSwapOnThread() override { + auto* sii = display_context_provider_->SharedImageInterface(); switch (num_swaps_++) { case 0: // The layers have been drawn, so any textures required for drawing have // been allocated. EXPECT_FALSE(result_); - num_textures_without_readback_ = - display_context_provider_->TestContextGL()->NumTextures(); + num_shared_images_without_readback_ = sii->shared_image_count(); // Request a copy of the layer. This will use another texture. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::BindOnce( - &LayerTreeHostCopyRequestTestDeleteTexture::InsertCopyRequest, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostCopyRequestTestDeleteSharedImage:: + InsertCopyRequest, + base::Unretained(this))); break; case 1: // Copy requests cause a followup commit and draw without the separate @@ -887,17 +890,17 @@ class LayerTreeHostCopyRequestTestDeleteTexture break; case 2: // We did a readback, so there will be a readback texture around now. - num_textures_after_readback_ = - display_context_provider_->TestContextGL()->NumTextures(); - EXPECT_LT(num_textures_without_readback_, num_textures_after_readback_); + num_shared_images_after_readback_ = sii->shared_image_count(); + EXPECT_LT(num_shared_images_without_readback_, + num_shared_images_after_readback_); // Now destroy the CopyOutputResult, releasing the texture inside back // to the compositor. Then check the resulting number of allocated // textures. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture:: - DestroyCopyResultAndCheckNumTextures, + base::BindOnce(&LayerTreeHostCopyRequestTestDeleteSharedImage:: + DestroyCopyResultAndCheckNumSharedImages, base::Unretained(this))); break; } @@ -907,25 +910,22 @@ class LayerTreeHostCopyRequestTestDeleteTexture scoped_refptr<viz::TestContextProvider> display_context_provider_; int num_swaps_ = 0; - size_t num_textures_without_readback_ = 0; - size_t num_textures_after_readback_ = 0; + size_t num_shared_images_without_readback_ = 0; + size_t num_shared_images_after_readback_ = 0; FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> root_; scoped_refptr<FakePictureLayer> copy_layer_; std::unique_ptr<viz::CopyOutputResult> result_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestDeleteTexture); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestDeleteSharedImage); -class LayerTreeHostCopyRequestTestCountTextures +class LayerTreeHostCopyRequestTestCountSharedImages : public LayerTreeHostCopyRequestTest { protected: std::unique_ptr<viz::OutputSurface> CreateDisplayOutputSurfaceOnThread( scoped_refptr<viz::ContextProvider> compositor_context_provider) override { - // These tests expect the LayerTreeHostImpl to share a context with - // the Display so that sync points are not needed and the texture counts - // are visible together. // Since this test does not override CreateLayerTreeFrameSink, the // |compositor_context_provider| will be a viz::TestContextProvider. display_context_provider_ = static_cast<viz::TestContextProvider*>( @@ -961,7 +961,6 @@ class LayerTreeHostCopyRequestTestCountTextures } void BeginTest() override { - waited_sync_token_after_readback_.Clear(); PostSetNeedsCommitToMainThread(); } @@ -978,27 +977,23 @@ class LayerTreeHostCopyRequestTestCountTextures } void DisplayDidDrawAndSwapOnThread() override { + auto* sii = display_context_provider_->SharedImageInterface(); switch (num_swaps_++) { case 0: - // The first frame has been drawn, so textures for drawing have been - // allocated. - num_textures_without_readback_ = - display_context_provider_->TestContextGL()->NumTextures(); + // The first frame has been drawn without readback, so result shared + // images not have been allocated. + num_shared_images_without_readback_ = sii->shared_image_count(); break; case 1: - // We did a readback, so there will be a readback texture around now. - num_textures_with_readback_ = - display_context_provider_->TestContextGL()->NumTextures(); - waited_sync_token_after_readback_ = - display_context_provider_->TestContextGL() - ->last_waited_sync_token(); + // We did a readback, so there will be a result shared image around now. + num_shared_images_with_readback_ = sii->shared_image_count(); // End the test after main thread has a chance to hear about the // readback. MainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce( - &LayerTreeHostCopyRequestTestCountTextures::DoEndTest, + &LayerTreeHostCopyRequestTestCountSharedImages::DoEndTest, base::Unretained(this))); break; } @@ -1008,24 +1003,23 @@ class LayerTreeHostCopyRequestTestCountTextures scoped_refptr<viz::TestContextProvider> display_context_provider_; int num_swaps_ = 0; - size_t num_textures_without_readback_ = 0; - size_t num_textures_with_readback_ = 0; - gpu::SyncToken waited_sync_token_after_readback_; + size_t num_shared_images_without_readback_ = 0; + size_t num_shared_images_with_readback_ = 0; FakeContentLayerClient root_client_; FakeContentLayerClient copy_client_; scoped_refptr<FakePictureLayer> root_; scoped_refptr<FakePictureLayer> copy_layer_; }; -class LayerTreeHostCopyRequestTestCreatesTexture - : public LayerTreeHostCopyRequestTestCountTextures { +class LayerTreeHostCopyRequestTestCreatesSharedImage + : public LayerTreeHostCopyRequestTestCountSharedImages { protected: void RequestCopy(Layer* layer) override { - // Request a normal texture copy. This should create a new texture. + // Request a normal texture copy. This should create a new shared image. copy_layer_->RequestCopyOfOutput(std::make_unique<viz::CopyOutputRequest>( viz::CopyOutputRequest::ResultFormat::RGBA_TEXTURE, base::BindOnce( - &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback, + &LayerTreeHostCopyRequestTestCreatesSharedImage::CopyOutputCallback, base::Unretained(this)))); } @@ -1040,16 +1034,15 @@ class LayerTreeHostCopyRequestTestCreatesTexture void AfterTest() override { release_->Run(gpu::SyncToken(), false); - // No sync point was needed. - EXPECT_FALSE(waited_sync_token_after_readback_.HasData()); - // Except the copy to have made another texture. - EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_); + // Except the copy to have made a new shared image. + EXPECT_EQ(num_shared_images_without_readback_ + 1, + num_shared_images_with_readback_); } std::unique_ptr<viz::SingleReleaseCallback> release_; }; -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestCreatesTexture); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestCreatesSharedImage); class LayerTreeHostCopyRequestTestDestroyBeforeCopy : public LayerTreeHostCopyRequestTest { diff --git a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc index 1443be72b3f..399b68f06be 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc @@ -4,7 +4,6 @@ #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/macros.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" @@ -39,8 +38,13 @@ class LayerTreeHostProxyTest : public LayerTreeTest { class LayerTreeHostProxyTestSetNeedsCommit : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestSetNeedsCommit() = default; + LayerTreeHostProxyTestSetNeedsCommit( + const LayerTreeHostProxyTestSetNeedsCommit&) = delete; ~LayerTreeHostProxyTestSetNeedsCommit() override = default; + LayerTreeHostProxyTestSetNeedsCommit& operator=( + const LayerTreeHostProxyTestSetNeedsCommit&) = delete; + void BeginTest() override { EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE, GetProxyMain()->max_requested_pipeline_stage()); @@ -66,9 +70,6 @@ class LayerTreeHostProxyTestSetNeedsCommit : public LayerTreeHostProxyTest { } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsCommit); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsCommit); @@ -76,8 +77,13 @@ MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsCommit); class LayerTreeHostProxyTestSetNeedsAnimate : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestSetNeedsAnimate() = default; + LayerTreeHostProxyTestSetNeedsAnimate( + const LayerTreeHostProxyTestSetNeedsAnimate&) = delete; ~LayerTreeHostProxyTestSetNeedsAnimate() override = default; + LayerTreeHostProxyTestSetNeedsAnimate& operator=( + const LayerTreeHostProxyTestSetNeedsAnimate&) = delete; + void BeginTest() override { EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE, GetProxyMain()->max_requested_pipeline_stage()); @@ -101,9 +107,6 @@ class LayerTreeHostProxyTestSetNeedsAnimate : public LayerTreeHostProxyTest { } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsAnimate); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsAnimate); @@ -112,8 +115,13 @@ class LayerTreeHostProxyTestSetNeedsUpdateLayers : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestSetNeedsUpdateLayers() = default; + LayerTreeHostProxyTestSetNeedsUpdateLayers( + const LayerTreeHostProxyTestSetNeedsUpdateLayers&) = delete; ~LayerTreeHostProxyTestSetNeedsUpdateLayers() override = default; + LayerTreeHostProxyTestSetNeedsUpdateLayers& operator=( + const LayerTreeHostProxyTestSetNeedsUpdateLayers&) = delete; + void BeginTest() override { EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE, GetProxyMain()->max_requested_pipeline_stage()); @@ -137,9 +145,6 @@ class LayerTreeHostProxyTestSetNeedsUpdateLayers } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsUpdateLayers); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsUpdateLayers); @@ -148,9 +153,14 @@ class LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() = default; + LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating( + const LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating&) = delete; ~LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating() override = default; + LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating& operator=( + const LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating&) = delete; + void BeginTest() override { proxy()->SetNeedsAnimate(); } void WillBeginMainFrame() override { @@ -182,10 +192,6 @@ class LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN( - LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsUpdateLayersWhileAnimating); @@ -194,8 +200,13 @@ class LayerTreeHostProxyTestSetNeedsCommitWhileAnimating : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() = default; + LayerTreeHostProxyTestSetNeedsCommitWhileAnimating( + const LayerTreeHostProxyTestSetNeedsCommitWhileAnimating&) = delete; ~LayerTreeHostProxyTestSetNeedsCommitWhileAnimating() override = default; + LayerTreeHostProxyTestSetNeedsCommitWhileAnimating& operator=( + const LayerTreeHostProxyTestSetNeedsCommitWhileAnimating&) = delete; + void BeginTest() override { proxy()->SetNeedsAnimate(); } void WillBeginMainFrame() override { @@ -227,9 +238,6 @@ class LayerTreeHostProxyTestSetNeedsCommitWhileAnimating } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestSetNeedsCommitWhileAnimating); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestSetNeedsCommitWhileAnimating); @@ -238,6 +246,11 @@ class LayerTreeHostProxyTestCommitWaitsForActivation : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestCommitWaitsForActivation() = default; + LayerTreeHostProxyTestCommitWaitsForActivation( + const LayerTreeHostProxyTestCommitWaitsForActivation&) = delete; + + LayerTreeHostProxyTestCommitWaitsForActivation& operator=( + const LayerTreeHostProxyTestCommitWaitsForActivation&) = delete; void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -314,8 +327,6 @@ class LayerTreeHostProxyTestCommitWaitsForActivation private: base::Lock activate_blocked_lock_; bool activate_blocked_ = false; - - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestCommitWaitsForActivation); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestCommitWaitsForActivation); @@ -328,6 +339,11 @@ class LayerTreeHostProxyTestCommitWaitsForActivationMFBA : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestCommitWaitsForActivationMFBA() = default; + LayerTreeHostProxyTestCommitWaitsForActivationMFBA( + const LayerTreeHostProxyTestCommitWaitsForActivationMFBA&) = delete; + + LayerTreeHostProxyTestCommitWaitsForActivationMFBA& operator=( + const LayerTreeHostProxyTestCommitWaitsForActivationMFBA&) = delete; void InitializeSettings(LayerTreeSettings* settings) override { settings->main_frame_before_activation_enabled = true; @@ -419,8 +435,6 @@ class LayerTreeHostProxyTestCommitWaitsForActivationMFBA private: base::Lock activate_blocked_lock_; bool activate_blocked_ = false; - - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestCommitWaitsForActivationMFBA); }; MULTI_THREAD_TEST_F(LayerTreeHostProxyTestCommitWaitsForActivationMFBA); @@ -431,6 +445,10 @@ class LayerTreeHostProxyTestImplFrameCausesAnimatePending : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestImplFrameCausesAnimatePending() = default; + LayerTreeHostProxyTestImplFrameCausesAnimatePending( + const LayerTreeHostProxyTestImplFrameCausesAnimatePending&) = delete; + LayerTreeHostProxyTestImplFrameCausesAnimatePending& operator=( + const LayerTreeHostProxyTestImplFrameCausesAnimatePending&) = delete; void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -453,9 +471,6 @@ class LayerTreeHostProxyTestImplFrameCausesAnimatePending } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestImplFrameCausesAnimatePending); }; SINGLE_THREAD_TEST_F(LayerTreeHostProxyTestImplFrameCausesAnimatePending); @@ -466,6 +481,10 @@ class LayerTreeHostProxyTestNeedsCommitFromImpl : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestNeedsCommitFromImpl() = default; + LayerTreeHostProxyTestNeedsCommitFromImpl( + const LayerTreeHostProxyTestNeedsCommitFromImpl&) = delete; + LayerTreeHostProxyTestNeedsCommitFromImpl& operator=( + const LayerTreeHostProxyTestNeedsCommitFromImpl&) = delete; void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -500,9 +519,6 @@ class LayerTreeHostProxyTestNeedsCommitFromImpl } void AfterTest() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestNeedsCommitFromImpl); }; SINGLE_THREAD_TEST_F(LayerTreeHostProxyTestNeedsCommitFromImpl); @@ -514,8 +530,13 @@ class LayerTreeHostProxyTestDelayedCommitDueToVisibility : public LayerTreeHostProxyTest { protected: LayerTreeHostProxyTestDelayedCommitDueToVisibility() = default; + LayerTreeHostProxyTestDelayedCommitDueToVisibility( + const LayerTreeHostProxyTestDelayedCommitDueToVisibility&) = delete; ~LayerTreeHostProxyTestDelayedCommitDueToVisibility() override = default; + LayerTreeHostProxyTestDelayedCommitDueToVisibility& operator=( + const LayerTreeHostProxyTestDelayedCommitDueToVisibility&) = delete; + void BeginTest() override { PostSetNeedsCommitToMainThread(); } void WillSendBeginMainFrameOnThread(LayerTreeHostImpl*) override { @@ -537,8 +558,6 @@ class LayerTreeHostProxyTestDelayedCommitDueToVisibility private: bool set_invisible_once_ = false; - - DISALLOW_COPY_AND_ASSIGN(LayerTreeHostProxyTestDelayedCommitDueToVisibility); }; SINGLE_AND_MULTI_THREAD_TEST_F( diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index 6a6f99be3e3..667f67d8909 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -599,6 +599,7 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { child_layer_->SetIsDrawable(true); child_layer_->SetScrollable(root_layer->bounds()); + child_layer_->SetHitTestable(true); child_layer_->SetElementId( LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(root_scroll_layer_->bounds()); @@ -1130,6 +1131,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset switch (layer_tree_host()->SourceFrameNumber()) { case 0: scroll_layer->SetScrollable(root->bounds()); + scroll_layer->SetHitTestable(true); // Set max_scroll_offset = (100, 100). scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100)); @@ -1410,6 +1412,7 @@ class LayerTreeHostScrollTestLayerStructureChange scroll_layer->SetPosition(gfx::PointF()); scroll_layer->SetIsDrawable(true); scroll_layer->SetScrollable(parent->bounds()); + scroll_layer->SetHitTestable(true); scroll_layer->SetElementId( LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(gfx::Size(parent->bounds().width() + 100, diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index 2731ba97d52..8202fa00798 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -618,7 +618,7 @@ LayerImplList::reverse_iterator LayerTreeImpl::rend() { return layer_list_.rend(); } -bool LayerTreeImpl::IsElementInLayerList(ElementId element_id) const { +bool LayerTreeImpl::IsElementInPropertyTree(ElementId element_id) const { return elements_in_property_trees_.count(element_id); } @@ -626,15 +626,7 @@ ElementListType LayerTreeImpl::GetElementTypeForAnimation() const { return IsActiveTree() ? ElementListType::ACTIVE : ElementListType::PENDING; } -void LayerTreeImpl::AddToElementLayerList(ElementId element_id, - LayerImpl* layer) { - if (!element_id) - return; - - TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("layer-element"), - "LayerTreeImpl::AddToElementLayerList", "element", - element_id.AsValue().release()); - +void LayerTreeImpl::AddToElementPropertyTreeList(ElementId element_id) { #if DCHECK_IS_ON() bool element_id_collision_detected = elements_in_property_trees_.count(element_id); @@ -644,10 +636,34 @@ void LayerTreeImpl::AddToElementLayerList(ElementId element_id, elements_in_property_trees_.insert(element_id); + DCHECK(settings().use_layer_lists); host_impl_->mutator_host()->RegisterElement(element_id, GetElementTypeForAnimation()); +} + +void LayerTreeImpl::RemoveFromElementPropertyTreeList(ElementId element_id) { + DCHECK(settings().use_layer_lists); + host_impl_->mutator_host()->UnregisterElement(element_id, + GetElementTypeForAnimation()); + elements_in_property_trees_.erase(element_id); +} + +void LayerTreeImpl::AddToElementLayerList(ElementId element_id, + LayerImpl* layer) { + if (!element_id) + return; + + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("layer-element"), + "LayerTreeImpl::AddToElementLayerList", "element", + element_id.AsValue().release()); - if (layer && layer->scrollable()) + if (!settings().use_layer_lists) { + elements_in_property_trees_.insert(element_id); + host_impl_->mutator_host()->RegisterElement(element_id, + GetElementTypeForAnimation()); + } + + if (layer->scrollable()) AddScrollableLayer(layer); } @@ -659,10 +675,12 @@ void LayerTreeImpl::RemoveFromElementLayerList(ElementId element_id) { "LayerTreeImpl::RemoveFromElementLayerList", "element", element_id.AsValue().release()); - host_impl_->mutator_host()->UnregisterElement(element_id, - GetElementTypeForAnimation()); + if (!settings().use_layer_lists) { + elements_in_property_trees_.erase(element_id); + host_impl_->mutator_host()->UnregisterElement(element_id, + GetElementTypeForAnimation()); + } - elements_in_property_trees_.erase(element_id); element_id_to_scrollable_layer_.erase(element_id); } @@ -843,8 +861,10 @@ void LayerTreeImpl::UpdateTransformAnimation(ElementId element_id, list_type); if (node->has_potential_animation != has_potential_animation) { node->has_potential_animation = has_potential_animation; - node->has_only_translation_animations = - mutator_host()->HasOnlyTranslationTransforms(element_id, list_type); + node->maximum_animation_scale = + mutator_host()->MaximumTargetScale(element_id, list_type); + node->starting_animation_scale = + mutator_host()->AnimationStartScale(element_id, list_type); transform_tree.set_needs_update(true); set_needs_update_draw_properties(); } @@ -1720,49 +1740,6 @@ void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->EndArray(); } -bool LayerTreeImpl::DistributeRootScrollOffset( - const gfx::ScrollOffset& desired_root_offset) { - if (!InnerViewportScrollNode() || !OuterViewportScrollLayer()) - return false; - - gfx::ScrollOffset root_offset = desired_root_offset; - ScrollTree& scroll_tree = property_trees()->scroll_tree; - - // If we get here, we have both inner/outer viewports, and need to distribute - // the scroll offset between them. - gfx::ScrollOffset inner_viewport_offset = - scroll_tree.current_scroll_offset(InnerViewportScrollNode()->element_id); - gfx::ScrollOffset outer_viewport_offset = - OuterViewportScrollLayer()->CurrentScrollOffset(); - DCHECK(inner_viewport_offset + outer_viewport_offset == TotalScrollOffset()); - - // Setting the root scroll offset is driven by user actions so prevent - // it if it is not user scrollable in certain directions. - if (!InnerViewportScrollNode()->user_scrollable_horizontal) - root_offset.set_x(inner_viewport_offset.x() + outer_viewport_offset.x()); - - if (!InnerViewportScrollNode()->user_scrollable_vertical) - root_offset.set_y(inner_viewport_offset.y() + outer_viewport_offset.y()); - - // It may be nothing has changed. - if (inner_viewport_offset + outer_viewport_offset == root_offset) - return false; - - gfx::ScrollOffset max_outer_viewport_scroll_offset = - OuterViewportScrollLayer()->MaxScrollOffset(); - - outer_viewport_offset = root_offset - inner_viewport_offset; - outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset); - outer_viewport_offset.SetToMax(gfx::ScrollOffset()); - - OuterViewportScrollLayer()->SetCurrentScrollOffset(outer_viewport_offset); - inner_viewport_offset = root_offset - outer_viewport_offset; - if (scroll_tree.SetScrollOffset(InnerViewportScrollNode()->element_id, - inner_viewport_offset)) - DidUpdateScrollOffset(InnerViewportScrollNode()->element_id); - return true; -} - void LayerTreeImpl::QueueSwapPromise( std::unique_ptr<SwapPromise> swap_promise) { DCHECK(swap_promise); @@ -2156,10 +2133,7 @@ LayerImpl* LayerTreeImpl::FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( } struct HitTestVisibleScrollableOrTouchableFunctor { - bool operator()(LayerImpl* layer) const { - return layer->scrollable() || layer->ShouldHitTest() || - !layer->touch_action_region().region().IsEmpty(); - } + bool operator()(LayerImpl* layer) const { return layer->HitTestable(); } }; LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint( diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index a42e2153e06..88d798bce13 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -12,7 +12,6 @@ #include <vector> #include "base/containers/flat_set.h" -#include "base/macros.h" #include "base/time/time.h" #include "base/values.h" #include "cc/base/synced_property.h" @@ -99,8 +98,11 @@ class CC_EXPORT LayerTreeImpl { scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor, scoped_refptr<SyncedBrowserControls> top_controls_shown_ratio, scoped_refptr<SyncedElasticOverscroll> elastic_overscroll); + LayerTreeImpl(const LayerTreeImpl&) = delete; virtual ~LayerTreeImpl(); + LayerTreeImpl& operator=(const LayerTreeImpl&) = delete; + void Shutdown(); void ReleaseResources(); void OnPurgeMemory(); @@ -455,7 +457,10 @@ class CC_EXPORT LayerTreeImpl { LayerImpl* LayerById(int id) const; LayerImpl* ScrollableLayerByElementId(ElementId element_id) const; - bool IsElementInLayerList(ElementId element_id) const; + bool IsElementInPropertyTree(ElementId element_id) const; + void AddToElementPropertyTreeList(ElementId element_id); + void RemoveFromElementPropertyTreeList(ElementId element_id); + void AddToElementLayerList(ElementId element_id, LayerImpl* layer); void RemoveFromElementLayerList(ElementId element_id); @@ -486,10 +491,6 @@ class CC_EXPORT LayerTreeImpl { // Used for accessing the task runner and debug assertions. TaskRunnerProvider* task_runner_provider() const; - // Distribute the root scroll between outer and inner viewport scroll layer. - // The outer viewport scroll layer scrolls first. - bool DistributeRootScrollOffset(const gfx::ScrollOffset& root_offset); - void ApplyScroll(ScrollNode* scroll_node, ScrollState* scroll_state) { host_impl_->ApplyScroll(scroll_node, scroll_state); } @@ -803,8 +804,6 @@ class CC_EXPORT LayerTreeImpl { LayerTreeLifecycle lifecycle_; std::vector<LayerTreeHost::PresentationTimeCallback> presentation_callbacks_; - - DISALLOW_COPY_AND_ASSIGN(LayerTreeImpl); }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 5c8054c72d7..e703093d5b4 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -4,7 +4,6 @@ #include "cc/trees/layer_tree_impl.h" -#include "base/macros.h" #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" @@ -78,6 +77,7 @@ class LayerTreeImplTest : public testing::Test { root->test_properties()->sorting_context_id = root_sorting_context; root->SetBounds(bounds); root->SetDrawsContent(true); + root->SetHitTestable(true); } { gfx::Transform translate_z; @@ -87,6 +87,7 @@ class LayerTreeImplTest : public testing::Test { left_child_sorting_context; left_child->SetBounds(bounds); left_child->SetDrawsContent(true); + left_child->SetHitTestable(true); left_child->test_properties()->should_flatten_transform = false; } { @@ -97,6 +98,7 @@ class LayerTreeImplTest : public testing::Test { right_child_sorting_context; right_child->SetBounds(bounds); right_child->SetDrawsContent(true); + right_child->SetHitTestable(true); } root->test_properties()->AddChild(std::move(left_child)); @@ -125,6 +127,7 @@ TEST_F(LayerTreeImplTest, HitTestingForSingleLayer) { LayerImpl* root = root_layer(); root->SetBounds(bounds); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -164,6 +167,7 @@ TEST_F(LayerTreeImplTest, UpdateViewportAndHitTest) { LayerImpl* root = root_layer(); root->SetBounds(bounds); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -186,12 +190,14 @@ TEST_F(LayerTreeImplTest, HitTestingForSingleLayerAndHud) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); // Create hud and add it as a child of root. std::unique_ptr<HeadsUpDisplayLayerImpl> hud = HeadsUpDisplayLayerImpl::Create(host_impl().active_tree(), 11111); hud->SetBounds(gfx::Size(200, 200)); hud->SetDrawsContent(true); + hud->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(hud->bounds()); host_impl().active_tree()->set_hud_layer(hud.get()); @@ -240,6 +246,7 @@ TEST_F(LayerTreeImplTest, HitTestingForUninvertibleTransform) { root->test_properties()->transform = uninvertible_transform; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -296,6 +303,7 @@ TEST_F(LayerTreeImplTest, HitTestingForSinglePositionedLayer) { test_layer->test_properties()->position = gfx::PointF(50.f, 50.f); test_layer->SetBounds(gfx::Size(100, 100)); test_layer->SetDrawsContent(true); + test_layer->SetHitTestable(true); root_layer()->test_properties()->AddChild(std::move(test_layer)); } @@ -344,6 +352,7 @@ TEST_F(LayerTreeImplTest, HitTestingForSingleRotatedLayer) { root->test_properties()->transform = rotation45_degrees_about_center; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -415,6 +424,7 @@ TEST_F(LayerTreeImplTest, HitTestingClipNodeDifferentTransformAndTargetIds) { LayerImpl::Create(host_impl().active_tree(), 5); test->SetBounds(gfx::Size(100, 100)); test->SetDrawsContent(true); + test->SetHitTestable(true); clip->test_properties()->AddChild(std::move(test)); scale->test_properties()->AddChild(std::move(clip)); @@ -446,12 +456,14 @@ TEST_F(LayerTreeImplTest, HitTestingSiblings) { child1->SetBounds(gfx::Size(25, 25)); child1->SetMasksToBounds(true); child1->SetDrawsContent(true); + child1->SetHitTestable(true); std::unique_ptr<LayerImpl> child2 = LayerImpl::Create(host_impl().active_tree(), 3); child2->SetBounds(gfx::Size(75, 75)); child2->SetMasksToBounds(true); child2->SetDrawsContent(true); + child2->SetHitTestable(true); root->test_properties()->AddChild(std::move(child1)); root->test_properties()->AddChild(std::move(child2)); @@ -481,6 +493,7 @@ TEST_F(LayerTreeImplTest, HitTestingForSinglePerspectiveLayer) { (perspective_projection_about_center * translation_by_z); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -536,6 +549,7 @@ TEST_F(LayerTreeImplTest, HitTestingForSimpleClippedLayer) { child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); + child->SetHitTestable(true); clipping_layer->test_properties()->AddChild(std::move(child)); root->test_properties()->AddChild(std::move(clipping_layer)); } @@ -630,6 +644,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) { rotated_leaf->SetBounds(gfx::Size(100, 100)); rotated_leaf->test_properties()->transform = rotated_leaf_transform; rotated_leaf->SetDrawsContent(true); + rotated_leaf->SetHitTestable(true); grand_child->test_properties()->AddChild(std::move(rotated_leaf)); child->test_properties()->AddChild(std::move(grand_child)); @@ -713,6 +728,7 @@ TEST_F(LayerTreeImplTest, HitTestingForNonClippingIntermediateLayer) { gfx::PointF(60.f, 60.f); // 70, 70 in screen spae child->SetBounds(gfx::Size(20, 20)); child->SetDrawsContent(true); + child->SetHitTestable(true); intermediate_layer->test_properties()->AddChild(std::move(child)); root->test_properties()->AddChild(std::move(intermediate_layer)); } @@ -755,6 +771,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { // child 1 and child2 are initialized to overlap between x=50 and x=60. // grand_child is set to overlap both child1 and child2 between y=50 and @@ -772,10 +789,12 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) { child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); + child1->SetHitTestable(true); child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); + child2->SetHitTestable(true); // Remember that grand_child is positioned with respect to its parent (i.e. // child1). In screen space, the intended position is (10, 50), with size @@ -783,6 +802,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) { grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); + grand_child1->SetHitTestable(true); child1->test_properties()->AddChild(std::move(grand_child1)); root->test_properties()->AddChild(std::move(child1)); @@ -899,6 +919,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); root->test_properties()->should_flatten_transform = false; root->test_properties()->sorting_context_id = 1; { @@ -918,6 +939,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) { child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); + child1->SetHitTestable(true); child1->test_properties()->should_flatten_transform = false; child1->test_properties()->sorting_context_id = 1; @@ -927,6 +949,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) { translate_z.Translate3d(0, 0, 10.f); child2->test_properties()->transform = translate_z; child2->SetDrawsContent(true); + child2->SetHitTestable(true); child2->test_properties()->should_flatten_transform = false; child2->test_properties()->sorting_context_id = 1; @@ -936,6 +959,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) { grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); + grand_child1->SetHitTestable(true); grand_child1->test_properties()->should_flatten_transform = false; child1->test_properties()->AddChild(std::move(grand_child1)); @@ -1009,6 +1033,7 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsClipParents) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 2); @@ -1018,11 +1043,13 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsClipParents) { child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetMasksToBounds(true); grand_child->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child->SetBounds(gfx::Size(100, 50)); grand_child->SetDrawsContent(true); + grand_child->SetHitTestable(true); grand_child->test_properties()->force_render_surface = true; // This should let |grand_child| "escape" |child|'s clip. @@ -1050,6 +1077,7 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsScrollParents) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 2); @@ -1061,10 +1089,12 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsScrollParents) { child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetMasksToBounds(true); scroll_child->SetBounds(gfx::Size(200, 200)); scroll_child->SetDrawsContent(true); + scroll_child->SetHitTestable(true); // This should cause scroll child and its descendants to be affected by // |child|'s clip. @@ -1072,6 +1102,7 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsScrollParents) { grand_child->SetBounds(gfx::Size(200, 200)); grand_child->SetDrawsContent(true); + grand_child->SetHitTestable(true); grand_child->test_properties()->force_render_surface = true; scroll_child->test_properties()->AddChild(std::move(grand_child)); @@ -1098,6 +1129,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { // child 1 and child2 are initialized to overlap between x=50 and x=60. // grand_child is set to overlap both child1 and child2 between y=50 and @@ -1115,11 +1147,13 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) { child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); + child1->SetHitTestable(true); child1->test_properties()->force_render_surface = true; child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); + child2->SetHitTestable(true); child2->test_properties()->force_render_surface = true; // Remember that grand_child is positioned with respect to its parent (i.e. @@ -1128,6 +1162,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) { grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); + grand_child1->SetHitTestable(true); grand_child1->test_properties()->force_render_surface = true; child1->test_properties()->AddChild(std::move(grand_child1)); @@ -1219,6 +1254,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSingleLayer) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); @@ -1296,6 +1332,7 @@ TEST_F(LayerTreeImplTest, root->test_properties()->transform = uninvertible_transform; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); root->SetTouchActionRegion(touch_action_region); host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); @@ -1366,6 +1403,7 @@ TEST_F(LayerTreeImplTest, test_layer->test_properties()->position = gfx::PointF(50.f, 50.f); test_layer->SetBounds(gfx::Size(100, 100)); test_layer->SetDrawsContent(true); + test_layer->SetHitTestable(true); test_layer->SetTouchActionRegion(touch_action_region); root_layer()->test_properties()->AddChild(std::move(test_layer)); } @@ -1435,6 +1473,7 @@ TEST_F(LayerTreeImplTest, test_layer->test_properties()->position = gfx::PointF(25.f, 25.f); test_layer->SetBounds(gfx::Size(50, 50)); test_layer->SetDrawsContent(true); + test_layer->SetHitTestable(true); test_layer->SetTouchActionRegion(touch_action_region); root->test_properties()->AddChild(std::move(test_layer)); } @@ -1580,6 +1619,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSimpleClippedLayer) { child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetTouchActionRegion(touch_action_region); clipping_layer->test_properties()->AddChild(std::move(child)); root->test_properties()->AddChild(std::move(clipping_layer)); @@ -1664,6 +1704,7 @@ TEST_F(LayerTreeImplTest, child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); + child->SetHitTestable(true); child->SetTouchActionRegion(touch_action_region); clipping_layer->test_properties()->AddChild(std::move(child)); surface->test_properties()->AddChild(std::move(clipping_layer)); @@ -1724,6 +1765,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) { // layer is located. touch_layer->SetBounds(gfx::Size(50, 50)); touch_layer->SetDrawsContent(true); + touch_layer->SetHitTestable(true); TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionNone, gfx::Rect(0, 0, 50, 50)); touch_layer->SetTouchActionRegion(touch_action_region); @@ -1738,6 +1780,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) { notouch_layer->test_properties()->position = gfx::PointF(0, 25); notouch_layer->SetBounds(gfx::Size(50, 50)); notouch_layer->SetDrawsContent(true); + notouch_layer->SetHitTestable(true); root->test_properties()->AddChild(std::move(notouch_layer)); } @@ -1790,6 +1833,7 @@ TEST_F(LayerTreeImplTest, HitTestingTouchHandlerRegionsForLayerThatIsNotDrawn) { LayerImpl* root = root_layer(); root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); { TouchActionRegion touch_action_region; touch_action_region.Union(kTouchActionNone, gfx::Rect(10, 10, 30, 30)); @@ -1797,6 +1841,7 @@ TEST_F(LayerTreeImplTest, HitTestingTouchHandlerRegionsForLayerThatIsNotDrawn) { LayerImpl::Create(host_impl().active_tree(), 12345); test_layer->SetBounds(gfx::Size(50, 50)); test_layer->SetDrawsContent(false); + test_layer->SetHitTestable(false); test_layer->SetTouchActionRegion(touch_action_region); root->test_properties()->AddChild(std::move(test_layer)); } @@ -2260,6 +2305,7 @@ TEST_F(LayerTreeImplTest, HitTestingCorrectLayerWheelListener) { root->test_properties()->transform = translate_z; root->SetBounds(gfx::Size(100, 100)); root->SetDrawsContent(true); + root->SetHitTestable(true); } { gfx::Transform translate_z; @@ -2267,6 +2313,7 @@ TEST_F(LayerTreeImplTest, HitTestingCorrectLayerWheelListener) { left_child->test_properties()->transform = translate_z; left_child->SetBounds(gfx::Size(100, 100)); left_child->SetDrawsContent(true); + left_child->SetHitTestable(true); } { gfx::Transform translate_z; diff --git a/chromium/cc/trees/layer_tree_mutator.h b/chromium/cc/trees/layer_tree_mutator.h index a25f40cd1b6..fd5956c21fa 100644 --- a/chromium/cc/trees/layer_tree_mutator.h +++ b/chromium/cc/trees/layer_tree_mutator.h @@ -18,10 +18,20 @@ namespace cc { +// TOOD(kevers): Remove kDrop once confirmed that it is no longer needed under +// any circumstances. enum class MutateQueuingStrategy { - kDrop, // Discard request if busy. - kQueueAndReplace // Queue request if busy replacing previously queued - // request. + kDrop, // Discard request if busy. + kQueueHighPriority, // Queues request if busy. This request is + // is next to run in the queue. Only one + // high priority request can be in-flight + // at any point in time. + kQueueAndReplaceNormalPriority, // Queues request if busy. This request + // replaces an existing normal priority + // request. In the case of mutations cycles + // that cannot keep up with the frame rate, + // replaced mutation requests are dropped + // from the queue. }; enum class MutateStatus { @@ -79,20 +89,25 @@ struct CC_EXPORT AnimationWorkletInput { std::vector<WorkletAnimationId> peeked_animations; AnimationWorkletInput(); + AnimationWorkletInput(const AnimationWorkletInput&) = delete; ~AnimationWorkletInput(); + AnimationWorkletInput& operator=(const AnimationWorkletInput&) = delete; + #if DCHECK_IS_ON() // Verifies all animation states have the expected worklet id. bool ValidateId(int worklet_id) const; #endif - DISALLOW_COPY_AND_ASSIGN(AnimationWorkletInput); }; class CC_EXPORT MutatorInputState { public: MutatorInputState(); + MutatorInputState(const MutatorInputState&) = delete; ~MutatorInputState(); + MutatorInputState& operator=(const MutatorInputState&) = delete; + bool IsEmpty() const; void Add(AnimationWorkletInput::AddAndUpdateState&& state); void Update(AnimationWorkletInput::UpdateState&& state); @@ -119,8 +134,6 @@ class CC_EXPORT MutatorInputState { // Returns iterator pointing to the entry in |inputs_| map whose key is id. It // inserts a new entry if none exists. AnimationWorkletInput& EnsureWorkletEntry(int id); - - DISALLOW_COPY_AND_ASSIGN(MutatorInputState); }; struct CC_EXPORT AnimationWorkletOutput { diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index 3f3000b41bf..047b36948e7 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -35,6 +35,8 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const { wait_for_all_pipeline_stages_before_draw; scheduler_settings.enable_surface_synchronization = enable_surface_synchronization; + scheduler_settings.compositor_threaded_scrollbar_scrolling = + compositor_threaded_scrollbar_scrolling; return scheduler_settings; } diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 04e48714a6f..644305bc425 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -132,6 +132,10 @@ class CC_EXPORT LayerTreeSettings { // deadlines. bool wait_for_all_pipeline_stages_before_draw = false; + // Determines whether mouse interactions on composited scrollbars are handled + // on the compositor thread. + bool compositor_threaded_scrollbar_scrolling = false; + // Whether layer tree commits should be made directly to the active // tree on the impl thread. If |false| LayerTreeHostImpl creates a // pending layer tree and produces that as the 'sync tree' with diff --git a/chromium/cc/trees/mutator_host.h b/chromium/cc/trees/mutator_host.h index 03aa3fd52a4..377579edb91 100644 --- a/chromium/cc/trees/mutator_host.h +++ b/chromium/cc/trees/mutator_host.h @@ -26,6 +26,11 @@ class MutatorHostClient; class LayerTreeMutator; class ScrollTree; +// Used as the return value of MaximumTargetScale() and AnimationStartScale() to +// indicate that there is no active scale animation or the scale cannot be +// computed. +const float kNotScaled = 0; + // A MutatorHost owns all the animation and mutation effects. // There is just one MutatorHost for LayerTreeHost on main renderer thread // and just one MutatorHost for LayerTreeHostImpl on the impl thread. @@ -42,6 +47,8 @@ class MutatorHost { virtual void ClearMutators() = 0; + virtual void InitClientAnimationState() = 0; + virtual void RegisterElement(ElementId element_id, ElementListType list_type) = 0; virtual void UnregisterElement(ElementId element_id, @@ -68,7 +75,7 @@ class MutatorHost { // Tick animations that depends on scroll offset. virtual void TickScrollAnimations(base::TimeTicks monotonic_time, const ScrollTree& scroll_tree) = 0; - virtual void TickWorkletAnimations(base::TimeTicks monotonic_time) = 0; + virtual void TickWorkletAnimations() = 0; virtual bool UpdateAnimationState(bool start_ready_animations, MutatorEvents* events) = 0; virtual void PromoteScrollTimelinesPendingToActive() = 0; @@ -106,12 +113,17 @@ class MutatorHost { ElementListType list_type) const = 0; virtual bool AnimationsPreserveAxisAlignment(ElementId element_id) const = 0; - virtual bool MaximumTargetScale(ElementId element_id, - ElementListType list_type, - float* max_scale) const = 0; - virtual bool AnimationStartScale(ElementId element_id, - ElementListType list_type, - float* start_scale) const = 0; + // Returns the maximum scale along any dimension at any destination in active + // scale animations, or kNotScaled if there is no active scale animation or + // the maximum scale cannot be computed. + virtual float MaximumTargetScale(ElementId element_id, + ElementListType list_type) const = 0; + + // Returns the maximum of starting animation scale along any dimension at any + // destination in active scale animations, or kNotScaled if there is no active + // scale animation or the starting scale cannot be computed. + virtual float AnimationStartScale(ElementId element_id, + ElementListType list_type) const = 0; virtual bool IsElementAnimating(ElementId element_id) const = 0; virtual bool HasTickingKeyframeModelForTesting( @@ -132,6 +144,9 @@ class MutatorHost { virtual void ScrollAnimationAbort() = 0; + // True when there is an ongoing scroll animation on Impl. + virtual bool IsImplOnlyScrollAnimating() const = 0; + virtual size_t CompositedAnimationsCount() const = 0; virtual size_t MainThreadAnimationsCount() const = 0; virtual bool CurrentFrameHadRAF() const = 0; diff --git a/chromium/cc/trees/mutator_host_client.h b/chromium/cc/trees/mutator_host_client.h index 40d6b7ef30d..44bad2c372b 100644 --- a/chromium/cc/trees/mutator_host_client.h +++ b/chromium/cc/trees/mutator_host_client.h @@ -56,6 +56,11 @@ class MutatorHostClient { const PropertyAnimationState& mask, const PropertyAnimationState& state) = 0; + virtual void AnimationScalesChanged(ElementId element_id, + ElementListType list_type, + float maximum_scale, + float starting_scale) = 0; + virtual void ScrollOffsetAnimationFinished() = 0; virtual gfx::ScrollOffset GetScrollOffsetForAnimation( ElementId element_id) const = 0; diff --git a/chromium/cc/trees/occlusion_tracker.h b/chromium/cc/trees/occlusion_tracker.h index 0f360f39313..09c7aec6f5e 100644 --- a/chromium/cc/trees/occlusion_tracker.h +++ b/chromium/cc/trees/occlusion_tracker.h @@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "cc/base/simple_enclosed_region.h" #include "cc/cc_export.h" #include "cc/layers/effect_tree_layer_list_iterator.h" @@ -31,8 +30,11 @@ class RenderSurfaceImpl; class CC_EXPORT OcclusionTracker { public: explicit OcclusionTracker(const gfx::Rect& screen_space_clip_rect); + OcclusionTracker(const OcclusionTracker&) = delete; ~OcclusionTracker(); + OcclusionTracker& operator=(const OcclusionTracker&) = delete; + // Return an occlusion that retains the current state of the tracker // and can be used outside of a layer walk to check occlusion. Occlusion GetCurrentOcclusionForLayer( @@ -102,8 +104,6 @@ class CC_EXPORT OcclusionTracker { gfx::Rect screen_space_clip_rect_; gfx::Size minimum_tracking_size_; - - DISALLOW_COPY_AND_ASSIGN(OcclusionTracker); }; } // namespace cc diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index 456f2a61d32..9801773b479 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -17,7 +17,6 @@ #include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" -#include "cc/trees/mutator_host.h" #include "cc/trees/property_tree.h" #include "cc/trees/scroll_node.h" #include "cc/trees/transform_node.h" @@ -831,13 +830,10 @@ void EffectTree::UpdateHasMaskingChild(EffectNode* node, // Reset to false when a node is first met. We'll set the bit later // when we actually encounter a masking child. node->has_masking_child = false; - if (node->blend_mode == SkBlendMode::kDstIn) + if (node->blend_mode == SkBlendMode::kDstIn) { + DCHECK(parent_node->has_render_surface); parent_node->has_masking_child = true; -} - -void EffectTree::UpdateIsMasked(EffectNode* node, EffectNode* parent_node) { - node->is_masked = (parent_node && parent_node->is_masked) || - node->mask_layer_id != Layer::INVALID_ID; + } } void EffectTree::UpdateSurfaceContentsScale(EffectNode* effect_node) { @@ -916,7 +912,6 @@ void EffectTree::UpdateEffects(int id) { UpdateEffectChanged(node, parent_node); UpdateBackfaceVisibility(node, parent_node); UpdateHasMaskingChild(node, parent_node); - UpdateIsMasked(node, parent_node); UpdateSurfaceContentsScale(node); } @@ -1195,6 +1190,16 @@ bool EffectTree::ClippedHitTestRegionIsRectangle(int effect_id) const { return true; } +bool EffectTree::HitTestMayBeAffectedByMask(int effect_id) const { + const EffectNode* effect_node = Node(effect_id); + for (; effect_node->id != kContentsRootNodeId; + effect_node = Node(effect_node->target_id)) { + if (effect_node->has_masking_child || effect_node->is_masked) + return true; + } + return false; +} + void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations( TransformNode* node, TransformNode* parent_node) { @@ -1847,9 +1852,7 @@ void PropertyTrees::SetOuterViewportContainerBoundsDelta( } bool PropertyTrees::ElementIsAnimatingChanged( - const MutatorHost* mutator_host, const PropertyToElementIdMap& element_id_map, - ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state, bool check_node_existence) { @@ -1883,9 +1886,6 @@ bool PropertyTrees::ElementIsAnimatingChanged( if (mask.potentially_animating[property]) { transform_node->has_potential_animation = state.potentially_animating[property]; - transform_node->has_only_translation_animations = - mutator_host->HasOnlyTranslationTransforms(element_id, - list_type); transform_tree.set_needs_update(true); // We track transform updates specifically, whereas we // don't do so for opacity/filter, because whether a @@ -1941,6 +1941,17 @@ bool PropertyTrees::ElementIsAnimatingChanged( return updated_transform; } +void PropertyTrees::AnimationScalesChanged(ElementId element_id, + float maximum_scale, + float starting_scale) { + if (TransformNode* transform_node = + transform_tree.FindNodeFromElementId(element_id)) { + transform_node->maximum_animation_scale = maximum_scale; + transform_node->starting_animation_scale = starting_scale; + UpdateTransformTreeUpdateNumber(); + } +} + void PropertyTrees::SetInnerViewportScrollBoundsDelta( gfx::Vector2dF bounds_delta) { inner_viewport_scroll_bounds_delta_ = bounds_delta; @@ -2030,28 +2041,26 @@ std::string PropertyTrees::ToString() const { CombinedAnimationScale PropertyTrees::GetAnimationScales( int transform_node_id, LayerTreeImpl* layer_tree_impl) { - if (cached_data_.animation_scales[transform_node_id].update_number != + AnimationScaleData* animation_scales = + &cached_data_.animation_scales[transform_node_id]; + if (animation_scales->update_number != cached_data_.transform_tree_update_number) { if (!layer_tree_impl->settings() .layer_transforms_should_scale_layer_contents) { - cached_data_.animation_scales[transform_node_id].update_number = + animation_scales->update_number = cached_data_.transform_tree_update_number; - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale = 0.f; - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale = 0.f; + animation_scales->combined_maximum_animation_target_scale = kNotScaled; + animation_scales->combined_starting_animation_scale = kNotScaled; return CombinedAnimationScale( - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale, - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale); + animation_scales->combined_maximum_animation_target_scale, + animation_scales->combined_starting_animation_scale); } TransformNode* node = transform_tree.Node(transform_node_id); TransformNode* parent_node = transform_tree.parent(node); bool ancestor_is_animating_scale = false; - float ancestor_maximum_target_scale = 0.f; - float ancestor_starting_animation_scale = 0.f; + float ancestor_maximum_target_scale = kNotScaled; + float ancestor_starting_animation_scale = kNotScaled; if (parent_node) { CombinedAnimationScale combined_animation_scale = GetAnimationScales(parent_node->id, layer_tree_impl); @@ -2064,14 +2073,17 @@ CombinedAnimationScale PropertyTrees::GetAnimationScales( .to_screen_has_scale_animation; } - cached_data_.animation_scales[transform_node_id] - .to_screen_has_scale_animation = - !node->has_only_translation_animations || ancestor_is_animating_scale; + bool node_is_animating_scale = + node->maximum_animation_scale != kNotScaled && + node->starting_animation_scale != kNotScaled; + + animation_scales->to_screen_has_scale_animation = + node_is_animating_scale || ancestor_is_animating_scale; // Once we've failed to compute a maximum animated scale at an ancestor, we // continue to fail. - bool failed_at_ancestor = - ancestor_is_animating_scale && ancestor_maximum_target_scale == 0.f; + bool failed_at_ancestor = ancestor_is_animating_scale && + ancestor_maximum_target_scale == kNotScaled; // Computing maximum animated scale in the presence of non-scale/translation // transforms isn't supported. @@ -2084,90 +2096,46 @@ CombinedAnimationScale PropertyTrees::GetAnimationScales( // as another node is decreasing scale from 10 to 1. Naively combining these // scales would produce a scale of 100. bool failed_for_multiple_scale_animations = - ancestor_is_animating_scale && !node->has_only_translation_animations; + ancestor_is_animating_scale && node_is_animating_scale; if (failed_at_ancestor || failed_for_non_scale_or_translation || failed_for_multiple_scale_animations) { // This ensures that descendants know we've failed to compute a maximum // animated scale. - cached_data_.animation_scales[transform_node_id] - .to_screen_has_scale_animation = true; - - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale = 0.f; - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale = 0.f; - } else if (!cached_data_.animation_scales[transform_node_id] - .to_screen_has_scale_animation) { - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale = 0.f; - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale = 0.f; - } else if (node->has_only_translation_animations) { + animation_scales->to_screen_has_scale_animation = true; + animation_scales->combined_maximum_animation_target_scale = kNotScaled; + animation_scales->combined_starting_animation_scale = kNotScaled; + } else if (!animation_scales->to_screen_has_scale_animation) { + animation_scales->combined_maximum_animation_target_scale = kNotScaled; + animation_scales->combined_starting_animation_scale = kNotScaled; + } else if (!node_is_animating_scale) { // An ancestor is animating scale. gfx::Vector2dF local_scales = - MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f); + MathUtil::ComputeTransform2dScaleComponents(node->local, kNotScaled); float max_local_scale = std::max(local_scales.x(), local_scales.y()); - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale = + animation_scales->combined_maximum_animation_target_scale = max_local_scale * ancestor_maximum_target_scale; - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale = + animation_scales->combined_starting_animation_scale = max_local_scale * ancestor_starting_animation_scale; } else { - ElementListType list_type = layer_tree_impl->IsActiveTree() - ? ElementListType::ACTIVE - : ElementListType::PENDING; - - layer_tree_impl->mutator_host()->MaximumTargetScale( - node->element_id, list_type, - &cached_data_.animation_scales[transform_node_id] - .local_maximum_animation_target_scale); - layer_tree_impl->mutator_host()->AnimationStartScale( - node->element_id, list_type, - &cached_data_.animation_scales[transform_node_id] - .local_starting_animation_scale); - gfx::Vector2dF local_scales = - MathUtil::ComputeTransform2dScaleComponents(node->local, 0.f); - float max_local_scale = std::max(local_scales.x(), local_scales.y()); - - if (cached_data_.animation_scales[transform_node_id] - .local_starting_animation_scale == 0.f || - cached_data_.animation_scales[transform_node_id] - .local_maximum_animation_target_scale == 0.f) { - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale = - max_local_scale * ancestor_maximum_target_scale; - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale = - max_local_scale * ancestor_starting_animation_scale; - } else { - gfx::Vector2dF ancestor_scales = - parent_node ? MathUtil::ComputeTransform2dScaleComponents( - transform_tree.ToScreen(parent_node->id), 0.f) - : gfx::Vector2dF(1.f, 1.f); - - float max_ancestor_scale = - std::max(ancestor_scales.x(), ancestor_scales.y()); - cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale = - max_ancestor_scale * - cached_data_.animation_scales[transform_node_id] - .local_maximum_animation_target_scale; - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale = - max_ancestor_scale * - cached_data_.animation_scales[transform_node_id] - .local_starting_animation_scale; - } + gfx::Vector2dF ancestor_scales = + parent_node + ? MathUtil::ComputeTransform2dScaleComponents( + transform_tree.ToScreen(parent_node->id), kNotScaled) + : gfx::Vector2dF(1.f, 1.f); + + float max_ancestor_scale = + std::max(ancestor_scales.x(), ancestor_scales.y()); + animation_scales->combined_maximum_animation_target_scale = + max_ancestor_scale * node->maximum_animation_scale; + animation_scales->combined_starting_animation_scale = + max_ancestor_scale * node->starting_animation_scale; } - cached_data_.animation_scales[transform_node_id].update_number = - cached_data_.transform_tree_update_number; + animation_scales->update_number = cached_data_.transform_tree_update_number; } - return CombinedAnimationScale(cached_data_.animation_scales[transform_node_id] - .combined_maximum_animation_target_scale, - cached_data_.animation_scales[transform_node_id] - .combined_starting_animation_scale); + return CombinedAnimationScale( + animation_scales->combined_maximum_animation_target_scale, + animation_scales->combined_starting_animation_scale); } void PropertyTrees::SetAnimationScalesForTesting( @@ -2318,10 +2286,18 @@ DrawTransforms& PropertyTrees::GetDrawTransforms(int transform_id, void PropertyTrees::ResetCachedData() { cached_data_.transform_tree_update_number = 0; - cached_data_.animation_scales = std::vector<AnimationScaleData>( - transform_tree.nodes().size(), AnimationScaleData()); - cached_data_.draw_transforms = std::vector<std::vector<DrawTransformData>>( - transform_tree.nodes().size(), std::vector<DrawTransformData>(1)); + const auto transform_count = transform_tree.nodes().size(); + cached_data_.animation_scales.resize(transform_count); + for (auto& animation_scale : cached_data_.animation_scales) + animation_scale.update_number = -1; + + cached_data_.draw_transforms.resize(transform_count, + std::vector<DrawTransformData>(1)); + for (auto& draw_transforms_for_id : cached_data_.draw_transforms) { + draw_transforms_for_id.resize(1); + draw_transforms_for_id[0].update_number = -1; + draw_transforms_for_id[0].target_id = EffectTree::kInvalidNodeId; + } } void PropertyTrees::UpdateTransformTreeUpdateNumber() { diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index 779a94a12cd..3296420fe6f 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -35,7 +35,6 @@ class CopyOutputRequest; namespace cc { class LayerTreeImpl; -class MutatorHost; class RenderSurfaceImpl; class ScrollState; struct ClipNode; @@ -372,13 +371,16 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { // 2) There are no mask layers. bool ClippedHitTestRegionIsRectangle(int effect_node_id) const; + // This function checks if the associated layer can use its layer bounds to + // correctly hit test. It returns true if the layer bounds cannot be trusted. + bool HitTestMayBeAffectedByMask(int effect_node_id) const; + private: void UpdateOpacities(EffectNode* node, EffectNode* parent_node); void UpdateSubtreeHidden(EffectNode* node, EffectNode* parent_node); void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node); void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node); void UpdateHasMaskingChild(EffectNode* node, EffectNode* parent_node); - void UpdateIsMasked(EffectNode* node, EffectNode* parent_node); // Stores copy requests, keyed by node id. std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>> @@ -512,14 +514,6 @@ struct AnimationScaleData { // updates. int update_number; - // Current animations, considering only scales at keyframes not including the - // starting keyframe of each animation. - float local_maximum_animation_target_scale; - - // The maximum scale that this node's |local| transform will have during - // current animatons, considering only the starting scale of each animation. - float local_starting_animation_scale; - // The maximum scale that this node's |to_target| transform will have during // current animations, considering only scales at keyframes not incuding the // starting keyframe of each animation. @@ -533,8 +527,6 @@ struct AnimationScaleData { AnimationScaleData() { update_number = -1; - local_maximum_animation_target_scale = 0.f; - local_starting_animation_scale = 0.f; combined_maximum_animation_target_scale = 0.f; combined_starting_animation_scale = 0.f; to_screen_has_scale_animation = false; @@ -658,12 +650,13 @@ class CC_EXPORT PropertyTrees final { // Applies an animation state change for a particular element in // this property tree. Returns whether a draw property update is // needed. - bool ElementIsAnimatingChanged(const MutatorHost* mutator_host, - const PropertyToElementIdMap& element_id_map, - ElementListType list_type, + bool ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map, const PropertyAnimationState& mask, const PropertyAnimationState& state, bool check_node_existence); + void AnimationScalesChanged(ElementId element_id, + float maximum_scale, + float starting_scale); void SetInnerViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); void SetOuterViewportContainerBoundsDelta(gfx::Vector2dF bounds_delta); void SetInnerViewportScrollBoundsDelta(gfx::Vector2dF bounds_delta); diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index 3b0833daff0..0e5434ee2b5 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -9,6 +9,7 @@ #include <map> #include <set> +#include "base/auto_reset.h" #include "cc/base/math_util.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" @@ -47,6 +48,7 @@ struct DataForRecursion { bool animation_axis_aligned_since_render_target; bool not_axis_aligned_since_last_clip; gfx::Transform compound_transform_since_render_target; + bool* subtree_has_rounded_corner; }; template <typename LayerType> @@ -112,6 +114,12 @@ class PropertyTreeBuilderContext { LayerType* layer, DataForRecursion<LayerType>* data_for_children) const; + bool UpdateRenderSurfaceIfNeeded( + int parent_effect_tree_id, + DataForRecursion<LayerType>* data_for_children, + bool subtree_has_rounded_corner, + bool created_transform_node) const; + LayerType* root_layer_; const LayerType* page_scale_layer_; const LayerType* inner_viewport_scroll_layer_; @@ -186,6 +194,33 @@ static inline const FilterOperations& Filters(LayerImpl* layer) { return layer->test_properties()->filters; } +static bool IsFastRoundedCorner(Layer* layer) { + return layer->is_fast_rounded_corner(); +} + +static bool IsFastRoundedCorner(LayerImpl* layer) { + return false; +} + +static bool HasRoundedCorner(Layer* layer) { + return layer->HasRoundedCorner(); +} + +static bool HasRoundedCorner(LayerImpl* layer) { + return false; +} + +static gfx::RRectF RoundedCornerBounds(Layer* layer) { + const std::array<uint32_t, 4> radii = layer->corner_radii(); + return gfx::RRectF(gfx::RectF(gfx::Rect(layer->bounds())), radii[0], radii[0], + radii[1], radii[1], radii[2], radii[2], radii[3], + radii[3]); +} + +static gfx::RRectF RoundedCornerBounds(LayerImpl* layer) { + return gfx::RRectF(); +} + static PictureLayer* MaskLayer(Layer* layer) { return layer->mask_layer(); } @@ -257,6 +292,18 @@ bool HasOnlyTranslationTransforms(const MutatorHost& host, LayerType* layer) { } template <typename LayerType> +float MaximumAnimationScale(const MutatorHost& host, LayerType* layer) { + return host.MaximumTargetScale(layer->element_id(), + layer->GetElementTypeForAnimation()); +} + +template <typename LayerType> +float StartingAnimationScale(const MutatorHost& host, LayerType* layer) { + return host.AnimationStartScale(layer->element_id(), + layer->GetElementTypeForAnimation()); +} + +template <typename LayerType> bool AnimationsPreserveAxisAlignment(const MutatorHost& host, LayerType* layer) { return host.AnimationsPreserveAxisAlignment(layer->element_id()); @@ -281,7 +328,8 @@ static int GetTransformParent(const DataForRecursion<LayerType>& data, template <typename LayerType> static bool LayerClipsSubtree(LayerType* layer) { - return layer->masks_to_bounds() || MaskLayer(layer); + return layer->masks_to_bounds() || MaskLayer(layer) || + HasRoundedCorner(layer); } template <typename LayerType> @@ -437,7 +485,8 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded( bool requires_node = is_root || is_snapped || has_significant_transform || has_any_transform_animation || has_surface || is_fixed || is_page_scale_layer || is_overscroll_elasticity_layer || - is_sticky || is_at_boundary_of_3d_rendering_context; + is_sticky || is_at_boundary_of_3d_rendering_context || + HasRoundedCorner(layer); int parent_index = TransformTree::kRootNodeId; int source_index = TransformTree::kRootNodeId; @@ -527,10 +576,8 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded( node->has_potential_animation = has_potentially_animated_transform; node->is_currently_animating = TransformIsAnimating(mutator_host_, layer); - if (has_potentially_animated_transform) { - node->has_only_translation_animations = - HasOnlyTranslationTransforms(mutator_host_, layer); - } + node->maximum_animation_scale = MaximumAnimationScale(mutator_host_, layer); + node->starting_animation_scale = StartingAnimationScale(mutator_host_, layer); float post_local_scale_factor = 1.0f; @@ -847,6 +894,11 @@ bool ShouldCreateRenderSurface(const MutatorHost& mutator_host, return true; } + if (!IsFastRoundedCorner(layer) && HasRoundedCorner(layer) && + num_descendants_that_draw_content > 1) { + return true; + } + // If the layer has blending. // TODO(rosca): this is temporary, until blending is implemented for other // types of quads than viz::RenderPassDrawQuad. Layers having descendants that @@ -994,7 +1046,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( bool requires_node = is_root || has_transparency || has_potential_opacity_animation || has_potential_filter_animation || has_non_axis_aligned_clip || - should_create_render_surface; + should_create_render_surface || HasRoundedCorner(layer); int parent_id = data_from_ancestor.effect_tree_parent; @@ -1041,13 +1093,21 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( if (MaskLayer(layer)) { node->mask_layer_id = MaskLayer(layer)->id(); effect_tree_.AddMaskLayerId(node->mask_layer_id); + node->is_masked = true; + } + + if (HasRoundedCorner(layer)) { + // This is currently in the local space of the layer and hence in an invalid + // space. Once we have the associated transform node for this effect node, + // we will update this to the transform node's coordinate space. + node->rounded_corner_bounds = RoundedCornerBounds(layer); + node->is_fast_rounded_corner = IsFastRoundedCorner(layer); } if (!is_root) { - // The effect node's transform id is used only when we create a render - // surface. So, we can leave the default value when we don't create a render - // surface. - if (should_create_render_surface) { + // Having a rounded corner or a render surface, both trigger the creation + // of a transform node. + if (should_create_render_surface || HasRoundedCorner(layer)) { // In this case, we will create a transform node, so it's safe to use the // next available id from the transform tree as this effect node's // transform id. @@ -1094,6 +1154,48 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( return should_create_render_surface; } +template <typename LayerType> +bool PropertyTreeBuilderContext<LayerType>::UpdateRenderSurfaceIfNeeded( + int parent_effect_tree_id, + DataForRecursion<LayerType>* data_for_children, + bool subtree_has_rounded_corner, + bool created_transform_node) const { + // No effect node was generated for this layer. + if (parent_effect_tree_id == data_for_children->effect_tree_parent) { + *data_for_children->subtree_has_rounded_corner = subtree_has_rounded_corner; + return false; + } + + EffectNode* effect_node = + effect_tree_.Node(data_for_children->effect_tree_parent); + const bool has_rounded_corner = !effect_node->rounded_corner_bounds.IsEmpty(); + + // Having a rounded corner should trigger a transform node. + if (has_rounded_corner) + DCHECK(created_transform_node); + + // If the subtree has a rounded corner and this node also has a rounded + // corner, then this node needs to have a render surface to prevent any + // intersections between the rrects. Since GL renderer can only handle a + // single rrect per quad at draw time, it would be unable to handle + // intersections thus resulting in artifacts. + if (subtree_has_rounded_corner && has_rounded_corner) + effect_node->has_render_surface = true; + + // Inform the parent that its subtree has rounded corners if one of the two + // scenario is true: + // - The subtree rooted at this node has a rounded corner and this node + // does not have a render surface. + // - This node has a rounded corner. + // The parent may have a rounded corner and would want to create a render + // surface of its own to prevent blending artifacts due to intersecting + // rounded corners. + *data_for_children->subtree_has_rounded_corner = + (subtree_has_rounded_corner && !effect_node->has_render_surface) || + has_rounded_corner; + return effect_node->has_render_surface; +} + static inline bool UserScrollableHorizontal(Layer* layer) { return layer->GetUserScrollableHorizontal(); } @@ -1265,6 +1367,7 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTreesInternal( layer->set_property_tree_sequence_number(property_trees_.sequence_number); DataForRecursion<LayerType> data_for_children(data_from_parent); + *data_for_children.subtree_has_rounded_corner = false; bool created_render_surface = AddEffectNodeIfNeeded(data_from_parent, layer, &data_for_children); @@ -1290,11 +1393,14 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTreesInternal( data_for_children.not_axis_aligned_since_last_clip = !has_non_axis_aligned_clip; + bool subtree_has_rounded_corner = false; for (size_t i = 0; i < LayerChildren(layer).size(); ++i) { LayerType* current_child = LayerChildAt(layer, i); SetLayerPropertyChangedForChild(layer, current_child); if (!ScrollParent(current_child)) { BuildPropertyTreesInternal(current_child, data_for_children); + subtree_has_rounded_corner |= + *data_for_children.subtree_has_rounded_corner; } } @@ -1304,11 +1410,16 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTreesInternal( LayerType* scroll_child = it->second; DCHECK_EQ(ScrollParent(scroll_child), layer); DCHECK(LayerParent(scroll_child)); - data_for_children.effect_tree_parent = - LayerParent(scroll_child)->effect_tree_index(); + base::AutoReset<int> auto_reset_effect_tree_parent( + &data_for_children.effect_tree_parent, + LayerParent(scroll_child)->effect_tree_index()); BuildPropertyTreesInternal(scroll_child, data_for_children); } + created_render_surface = UpdateRenderSurfaceIfNeeded( + data_from_parent.effect_tree_parent, &data_for_children, + subtree_has_rounded_corner, created_transform_node); + if (MaskLayer(layer)) { MaskLayer(layer)->set_property_tree_sequence_number( property_trees_.sequence_number); @@ -1419,6 +1530,9 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTrees( data_for_recursion.clip_tree_parent = clip_tree_.Insert(root_clip, ClipTree::kRootNodeId); + bool subtree_has_rounded_corner; + data_for_recursion.subtree_has_rounded_corner = &subtree_has_rounded_corner; + BuildPropertyTreesInternal(root_layer_, data_for_recursion); property_trees_.needs_rebuild = false; diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index 305d3c6df56..b275bc84635 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -60,8 +60,6 @@ class CC_EXPORT Proxy { // completed yet. virtual bool RequestedAnimatePending() = 0; - virtual void NotifyInputThrottledUntilCommit() = 0; - // Defers LayerTreeHost::BeginMainFrameUpdate and commits until it is // reset. It is only supported when using a scheduler. virtual void SetDeferMainFrameUpdate(bool defer_main_frame_update) = 0; diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index 672f1c38db2..9d5f067d3d0 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -46,11 +46,13 @@ unsigned int nextBeginFrameId = 0; class ScopedCompletionEvent { public: explicit ScopedCompletionEvent(CompletionEvent* event) : event_(event) {} + ScopedCompletionEvent(const ScopedCompletionEvent&) = delete; ~ScopedCompletionEvent() { event_->Signal(); } + ScopedCompletionEvent& operator=(const ScopedCompletionEvent&) = delete; + private: CompletionEvent* const event_; - DISALLOW_COPY_AND_ASSIGN(ScopedCompletionEvent); }; ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, @@ -60,7 +62,6 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, commit_completion_waits_for_activation_(false), next_frame_is_newly_committed_frame_(false), inside_draw_(false), - input_throttled_until_commit_(false), task_runner_provider_(task_runner_provider), smoothness_priority_expiration_notifier_( task_runner_provider->ImplThreadTaskRunner(), @@ -68,8 +69,6 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, base::Unretained(this)), base::TimeDelta::FromSecondsD( kSmoothnessTakesPriorityExpirationDelay)), - rendering_stats_instrumentation_( - layer_tree_host->rendering_stats_instrumentation()), proxy_main_weak_ptr_(proxy_main_weak_ptr) { TRACE_EVENT0("cc", "ProxyImpl::ProxyImpl"); DCHECK(IsImplThread()); @@ -89,7 +88,8 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, new CompositorTimingHistory( scheduler_settings.using_synchronous_renderer_compositor, CompositorTimingHistory::RENDERER_UMA, - rendering_stats_instrumentation_)); + layer_tree_host->rendering_stats_instrumentation(), + host_impl_->compositor_frame_reporting_controller())); scheduler_.reset(new Scheduler(this, scheduler_settings, layer_tree_host_id_, task_runner_provider_->ImplThreadTaskRunner(), std::move(compositor_timing_history))); @@ -165,14 +165,6 @@ void ProxyImpl::InitializeLayerTreeFrameSinkOnImpl( scheduler_->DidCreateAndInitializeLayerTreeFrameSink(); } -void ProxyImpl::SetInputThrottledUntilCommitOnImpl(bool is_throttled) { - DCHECK(IsImplThread()); - if (is_throttled == input_throttled_until_commit_) - return; - input_throttled_until_commit_ = is_throttled; - RenewTreePriority(); -} - void ProxyImpl::SetDeferBeginMainFrameOnImpl( bool defer_begin_main_frame) const { DCHECK(IsImplThread()); @@ -199,9 +191,6 @@ void ProxyImpl::BeginMainFrameAbortedOnImpl( DCHECK(IsImplThread()); DCHECK(scheduler_->CommitPending()); - if (CommitEarlyOutHandledCommit(reason)) { - SetInputThrottledUntilCommitOnImpl(false); - } host_impl_->BeginMainFrameAborted(reason, std::move(swap_promises)); scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time); scheduler_->BeginMainFrameAborted(reason); @@ -424,7 +413,7 @@ void ProxyImpl::RenewTreePriority() { // New content always takes priority when ui resources have been evicted. if (host_impl_->active_tree()->GetDeviceViewport().size().IsEmpty() || - host_impl_->EvictedUIResourcesExist() || input_throttled_until_commit_) { + host_impl_->EvictedUIResourcesExist()) { // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active // tree might be freed. We need to set RequiresHighResToDraw to ensure that // high res tiles will be required to activate pending tree. @@ -630,8 +619,6 @@ void ProxyImpl::ScheduledActionCommit() { // often a good bit of work to update the tree and prepare the new frame. host_impl_->CommitComplete(); - SetInputThrottledUntilCommitOnImpl(false); - next_frame_is_newly_committed_frame_ = true; } diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index 21090c96962..4916e5a09a6 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "cc/base/completion_event.h" #include "cc/base/delayed_unique_notifier.h" @@ -31,8 +30,11 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, LayerTreeHost* layer_tree_host, TaskRunnerProvider* task_runner_provider); + ProxyImpl(const ProxyImpl&) = delete; ~ProxyImpl() override; + ProxyImpl& operator=(const ProxyImpl&) = delete; + void UpdateBrowserControlsStateOnImpl(BrowserControlsState constraints, BrowserControlsState current, bool animate); @@ -42,7 +44,6 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, void InitializeMutatorOnImpl(std::unique_ptr<LayerTreeMutator> mutator); void InitializePaintWorkletLayerPainterOnImpl( std::unique_ptr<PaintWorkletLayerPainter> painter); - void SetInputThrottledUntilCommitOnImpl(bool is_throttled); void SetDeferBeginMainFrameOnImpl(bool defer_begin_main_frame) const; void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect); void SetNeedsCommitOnImpl(); @@ -162,7 +163,6 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, bool next_frame_is_newly_committed_frame_; bool inside_draw_; - bool input_throttled_until_commit_; bool send_compositor_frame_ack_; @@ -170,8 +170,6 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, DelayedUniqueNotifier smoothness_priority_expiration_notifier_; - RenderingStatsInstrumentation* rendering_stats_instrumentation_; - std::unique_ptr<LayerTreeHostImpl> host_impl_; // Use accessors instead of this variable directly. @@ -184,8 +182,6 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, // A weak pointer to ProxyMain that is invalidated when LayerTreeFrameSink is // released. base::WeakPtr<ProxyMain> proxy_main_frame_sink_bound_weak_ptr_; - - DISALLOW_COPY_AND_ASSIGN(ProxyImpl); }; } // namespace cc diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index c859f043ba4..3c4b947f371 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -292,7 +292,6 @@ void ProxyMain::BeginMainFrame( current_pipeline_stage_ = NO_PIPELINE_STAGE; layer_tree_host_->DidBeginMainFrame(); TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD); - layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); std::vector<std::unique_ptr<SwapPromise>> swap_promises = layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises(); ImplThreadTaskRunner()->PostTask( @@ -306,6 +305,7 @@ void ProxyMain::BeginMainFrame( // 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_->CommitComplete(); + layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); return; } @@ -320,7 +320,6 @@ void ProxyMain::BeginMainFrame( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); current_pipeline_stage_ = NO_PIPELINE_STAGE; - layer_tree_host_->DidBeginMainFrame(); // Notify the impl thread that the main thread is ready to commit. This will // begin the commit process, which is blocking from the main thread's @@ -328,7 +327,6 @@ void ProxyMain::BeginMainFrame( // coordinated by the Scheduler. { TRACE_EVENT0("cc", "ProxyMain::BeginMainFrame::commit"); - layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_); @@ -343,8 +341,15 @@ void ProxyMain::BeginMainFrame( hold_commit_for_activation)); completion.Wait(); } - layer_tree_host_->CommitComplete(); + + // For Blink implementations, this updates frame throttling and + // delivers IntersectionObserver events for Chromium-internal customers + // but *not* script-created IntersectionObserver. See + // blink::LocalFrameView::RunPostLifecycleSteps. + layer_tree_host_->DidBeginMainFrame(); + + layer_tree_host_->RecordEndOfFrameMetrics(begin_main_frame_start_time); } void ProxyMain::DidPresentCompositorFrame( @@ -443,13 +448,6 @@ bool ProxyMain::RequestedAnimatePending() { return max_requested_pipeline_stage_ >= ANIMATE_PIPELINE_STAGE; } -void ProxyMain::NotifyInputThrottledUntilCommit() { - DCHECK(IsMainThread()); - ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&ProxyImpl::SetInputThrottledUntilCommitOnImpl, - base::Unretained(proxy_impl_.get()), true)); -} - void ProxyMain::SetDeferMainFrameUpdate(bool defer_main_frame_update) { DCHECK(IsMainThread()); if (defer_main_frame_update_ == defer_main_frame_update) diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h index 468bad8fb32..a9e5fb4c06f 100644 --- a/chromium/cc/trees/proxy_main.h +++ b/chromium/cc/trees/proxy_main.h @@ -5,7 +5,6 @@ #ifndef CC_TREES_PROXY_MAIN_H_ #define CC_TREES_PROXY_MAIN_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/input/browser_controls_state.h" #include "cc/trees/proxy.h" @@ -33,9 +32,11 @@ class CC_EXPORT ProxyMain : public Proxy { public: ProxyMain(LayerTreeHost* layer_tree_host, TaskRunnerProvider* task_runner_provider); - + ProxyMain(const ProxyMain&) = delete; ~ProxyMain() override; + ProxyMain& operator=(const ProxyMain&) = delete; + // Commits between the main and impl threads are processed through a pipeline // with the following stages. For efficiency we can early out at any stage if // we decide that no further processing is necessary. @@ -87,7 +88,6 @@ class CC_EXPORT ProxyMain : public Proxy { void SetNeedsRedraw(const gfx::Rect& damage_rect) override; void SetNextCommitWaitsForActivation() override; bool RequestedAnimatePending() override; - void NotifyInputThrottledUntilCommit() override; void SetDeferMainFrameUpdate(bool defer_main_frame_update) override; void StartDeferringCommits(base::TimeDelta timeout) override; void StopDeferringCommits() override; @@ -166,8 +166,6 @@ class CC_EXPORT ProxyMain : public Proxy { base::WeakPtrFactory<ProxyMain> frame_sink_bound_weak_factory_; base::WeakPtrFactory<ProxyMain> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ProxyMain); }; } // namespace cc diff --git a/chromium/cc/trees/render_frame_metadata_observer.h b/chromium/cc/trees/render_frame_metadata_observer.h index 13b0263c5c4..4b30e52edaf 100644 --- a/chromium/cc/trees/render_frame_metadata_observer.h +++ b/chromium/cc/trees/render_frame_metadata_observer.h @@ -5,7 +5,6 @@ #ifndef CC_TREES_RENDER_FRAME_METADATA_OBSERVER_H_ #define CC_TREES_RENDER_FRAME_METADATA_OBSERVER_H_ -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/trees/render_frame_metadata.h" @@ -22,8 +21,12 @@ namespace cc { class CC_EXPORT RenderFrameMetadataObserver { public: RenderFrameMetadataObserver() = default; + RenderFrameMetadataObserver(const RenderFrameMetadataObserver&) = delete; virtual ~RenderFrameMetadataObserver() = default; + RenderFrameMetadataObserver& operator=(const RenderFrameMetadataObserver&) = + delete; + // Binds on the current thread. This should only be called from the compositor // thread. virtual void BindToCurrentThread() = 0; @@ -34,9 +37,6 @@ class CC_EXPORT RenderFrameMetadataObserver { const RenderFrameMetadata& render_frame_metadata, viz::CompositorFrameMetadata* compositor_frame_metadata, bool force_send) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderFrameMetadataObserver); }; } // namespace cc diff --git a/chromium/cc/trees/scoped_abort_remaining_swap_promises.h b/chromium/cc/trees/scoped_abort_remaining_swap_promises.h index b6c119705f0..af9cd7905ad 100644 --- a/chromium/cc/trees/scoped_abort_remaining_swap_promises.h +++ b/chromium/cc/trees/scoped_abort_remaining_swap_promises.h @@ -5,7 +5,6 @@ #ifndef CC_TREES_SCOPED_ABORT_REMAINING_SWAP_PROMISES_H_ #define CC_TREES_SCOPED_ABORT_REMAINING_SWAP_PROMISES_H_ -#include "base/macros.h" #include "cc/trees/swap_promise.h" #include "cc/trees/swap_promise_manager.h" @@ -16,15 +15,18 @@ class ScopedAbortRemainingSwapPromises { explicit ScopedAbortRemainingSwapPromises( SwapPromiseManager* swap_promise_manager) : swap_promise_manager_(swap_promise_manager) {} + ScopedAbortRemainingSwapPromises(const ScopedAbortRemainingSwapPromises&) = + delete; ~ScopedAbortRemainingSwapPromises() { swap_promise_manager_->BreakSwapPromises(SwapPromise::COMMIT_FAILS); } + ScopedAbortRemainingSwapPromises& operator=( + const ScopedAbortRemainingSwapPromises&) = delete; + private: SwapPromiseManager* swap_promise_manager_; - - DISALLOW_COPY_AND_ASSIGN(ScopedAbortRemainingSwapPromises); }; } // namespace cc diff --git a/chromium/cc/trees/scroll_node.cc b/chromium/cc/trees/scroll_node.cc index 069c731ae98..69b7b3318f5 100644 --- a/chromium/cc/trees/scroll_node.cc +++ b/chromium/cc/trees/scroll_node.cc @@ -63,6 +63,9 @@ void ScrollNode::AsValueInto(base::trace_event::TracedValue* value) const { value->SetBoolean("user_scrollable_horizontal", user_scrollable_horizontal); value->SetBoolean("user_scrollable_vertical", user_scrollable_vertical); + value->SetBoolean("scrolls_inner_viewport", scrolls_inner_viewport); + value->SetBoolean("scrolls_outer_viewport", scrolls_outer_viewport); + element_id.AddToTracedValue(value); value->SetInteger("transform_id", transform_id); value->SetInteger("overscroll_behavior_x", overscroll_behavior.x); diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 84f7627a162..8a5393d776d 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -72,6 +72,7 @@ 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); if (settings.single_thread_proxy_scheduler && !scheduler_on_impl_thread_) { SchedulerSettings scheduler_settings(settings.ToSchedulerSettings()); scheduler_settings.commit_to_active_tree = CommitToActiveTree(); @@ -80,14 +81,13 @@ void SingleThreadProxy::Start() { new CompositorTimingHistory( scheduler_settings.using_synchronous_renderer_compositor, CompositorTimingHistory::BROWSER_UMA, - layer_tree_host_->rendering_stats_instrumentation())); + layer_tree_host_->rendering_stats_instrumentation(), + host_impl_->compositor_frame_reporting_controller())); scheduler_on_impl_thread_.reset( new Scheduler(this, scheduler_settings, layer_tree_host_->GetId(), task_runner_provider_->MainThreadTaskRunner(), std::move(compositor_timing_history))); } - - host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); } SingleThreadProxy::~SingleThreadProxy() { @@ -231,8 +231,8 @@ void SingleThreadProxy::CommitComplete() { << "Activation is expected to have synchronously occurred by now."; DebugScopedSetMainThread main(task_runner_provider_); - layer_tree_host_->DidBeginMainFrame(); layer_tree_host_->CommitComplete(); + layer_tree_host_->DidBeginMainFrame(); next_frame_is_newly_committed_frame_ = true; } diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 107f91b2e07..24f95bfb7ad 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -8,7 +8,6 @@ #include <limits> #include "base/cancelable_callback.h" -#include "base/macros.h" #include "base/time/time.h" #include "cc/scheduler/scheduler.h" #include "cc/trees/layer_tree_host_impl.h" @@ -35,8 +34,11 @@ class CC_EXPORT SingleThreadProxy : public Proxy, LayerTreeHost* layer_tree_host, LayerTreeHostSingleThreadClient* client, TaskRunnerProvider* task_runner_provider); + SingleThreadProxy(const SingleThreadProxy&) = delete; ~SingleThreadProxy() override; + SingleThreadProxy& operator=(const SingleThreadProxy&) = delete; + // Proxy implementation bool IsStarted() const override; bool CommitToActiveTree() const override; @@ -50,7 +52,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void SetNeedsRedraw(const gfx::Rect& damage_rect) override; void SetNextCommitWaitsForActivation() override; bool RequestedAnimatePending() override; - void NotifyInputThrottledUntilCommit() override {} void SetDeferMainFrameUpdate(bool defer_main_frame_update) override; void StartDeferringCommits(base::TimeDelta timeout) override; void StopDeferringCommits() override; @@ -211,8 +212,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, base::WeakPtrFactory<SingleThreadProxy> frame_sink_bound_weak_factory_; base::WeakPtrFactory<SingleThreadProxy> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SingleThreadProxy); }; // For use in the single-threaded case. In debug builds, it pretends that the @@ -229,19 +228,22 @@ class DebugScopedSetImplThread { explicit DebugScopedSetImplThread(TaskRunnerProvider* task_runner_provider) {} #endif + DebugScopedSetImplThread(const DebugScopedSetImplThread&) = delete; + ~DebugScopedSetImplThread() { #if DCHECK_IS_ON() task_runner_provider_->SetCurrentThreadIsImplThread(previous_value_); #endif } - private: + DebugScopedSetImplThread& operator=(const DebugScopedSetImplThread&) = delete; + #if DCHECK_IS_ON() + + private: bool previous_value_; TaskRunnerProvider* task_runner_provider_; #endif - - DISALLOW_COPY_AND_ASSIGN(DebugScopedSetImplThread); }; // For use in the single-threaded case. In debug builds, it pretends that the @@ -258,19 +260,22 @@ class DebugScopedSetMainThread { explicit DebugScopedSetMainThread(TaskRunnerProvider* task_runner_provider) {} #endif + DebugScopedSetMainThread(const DebugScopedSetMainThread&) = delete; + ~DebugScopedSetMainThread() { #if DCHECK_IS_ON() task_runner_provider_->SetCurrentThreadIsImplThread(previous_value_); #endif } - private: + DebugScopedSetMainThread& operator=(const DebugScopedSetMainThread&) = delete; + #if DCHECK_IS_ON() + + private: bool previous_value_; TaskRunnerProvider* task_runner_provider_; #endif - - DISALLOW_COPY_AND_ASSIGN(DebugScopedSetMainThread); }; // For use in the single-threaded case. In debug builds, it pretends that the @@ -282,12 +287,14 @@ class DebugScopedSetImplThreadAndMainThreadBlocked { TaskRunnerProvider* task_runner_provider) : impl_thread_(task_runner_provider), main_thread_blocked_(task_runner_provider) {} + DebugScopedSetImplThreadAndMainThreadBlocked( + const DebugScopedSetImplThreadAndMainThreadBlocked&) = delete; + DebugScopedSetImplThreadAndMainThreadBlocked& operator=( + const DebugScopedSetImplThreadAndMainThreadBlocked&) = delete; private: DebugScopedSetImplThread impl_thread_; DebugScopedSetMainThreadBlocked main_thread_blocked_; - - DISALLOW_COPY_AND_ASSIGN(DebugScopedSetImplThreadAndMainThreadBlocked); }; } // namespace cc diff --git a/chromium/cc/trees/swap_promise_manager.h b/chromium/cc/trees/swap_promise_manager.h index da72a8ac0aa..f2dc6e4069c 100644 --- a/chromium/cc/trees/swap_promise_manager.h +++ b/chromium/cc/trees/swap_promise_manager.h @@ -8,7 +8,6 @@ #include <set> #include <vector> -#include "base/macros.h" #include "cc/cc_export.h" #include "cc/trees/swap_promise.h" @@ -19,8 +18,11 @@ class SwapPromiseMonitor; class CC_EXPORT SwapPromiseManager { public: SwapPromiseManager(); + SwapPromiseManager(const SwapPromiseManager&) = delete; ~SwapPromiseManager(); + SwapPromiseManager& operator=(const SwapPromiseManager&) = delete; + // Call this function when you expect there to be a swap buffer. // See swap_promise.h for how to use SwapPromise. void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise); @@ -49,8 +51,6 @@ class CC_EXPORT SwapPromiseManager { private: std::vector<std::unique_ptr<SwapPromise>> swap_promise_list_; std::set<SwapPromiseMonitor*> swap_promise_monitors_; - - DISALLOW_COPY_AND_ASSIGN(SwapPromiseManager); }; } // namespace cc diff --git a/chromium/cc/trees/task_runner_provider.h b/chromium/cc/trees/task_runner_provider.h index 42b0ed80a31..0bc19d31f38 100644 --- a/chromium/cc/trees/task_runner_provider.h +++ b/chromium/cc/trees/task_runner_provider.h @@ -9,7 +9,6 @@ #include <string> #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" @@ -35,6 +34,9 @@ class CC_EXPORT TaskRunnerProvider { new TaskRunnerProvider(main_task_runner, impl_task_runner)); } + TaskRunnerProvider(const TaskRunnerProvider&) = delete; + TaskRunnerProvider& operator=(const TaskRunnerProvider&) = delete; + // TODO(vmpstr): Should these return scoped_refptr to task runners? Many // places turn them into scoped_refptrs. How many of them need to? base::SingleThreadTaskRunner* MainThreadTaskRunner() const; @@ -70,8 +72,6 @@ class CC_EXPORT TaskRunnerProvider { bool impl_thread_is_overridden_; bool is_main_thread_blocked_; #endif - - DISALLOW_COPY_AND_ASSIGN(TaskRunnerProvider); }; #if DCHECK_IS_ON() @@ -83,24 +83,30 @@ class DebugScopedSetMainThreadBlocked { DCHECK(!task_runner_provider_->IsMainThreadBlocked()); task_runner_provider_->SetMainThreadBlocked(true); } + DebugScopedSetMainThreadBlocked(const DebugScopedSetMainThreadBlocked&) = + delete; ~DebugScopedSetMainThreadBlocked() { DCHECK(task_runner_provider_->IsMainThreadBlocked()); task_runner_provider_->SetMainThreadBlocked(false); } + DebugScopedSetMainThreadBlocked& operator=( + const DebugScopedSetMainThreadBlocked&) = delete; + private: TaskRunnerProvider* task_runner_provider_; - DISALLOW_COPY_AND_ASSIGN(DebugScopedSetMainThreadBlocked); }; #else class DebugScopedSetMainThreadBlocked { public: explicit DebugScopedSetMainThreadBlocked( TaskRunnerProvider* task_runner_provider) {} + DebugScopedSetMainThreadBlocked(const DebugScopedSetMainThreadBlocked&) = + delete; ~DebugScopedSetMainThreadBlocked() {} - private: - DISALLOW_COPY_AND_ASSIGN(DebugScopedSetMainThreadBlocked); + DebugScopedSetMainThreadBlocked& operator=( + const DebugScopedSetMainThreadBlocked&) = delete; }; #endif diff --git a/chromium/cc/trees/transform_node.cc b/chromium/cc/trees/transform_node.cc index 9964f16880b..bf8f4262a19 100644 --- a/chromium/cc/trees/transform_node.cc +++ b/chromium/cc/trees/transform_node.cc @@ -6,6 +6,7 @@ #include "base/trace_event/traced_value.h" #include "cc/base/math_util.h" #include "cc/layers/layer.h" +#include "cc/trees/mutator_host.h" #include "cc/trees/property_tree.h" #include "ui/gfx/geometry/point3_f.h" @@ -24,7 +25,6 @@ TransformNode::TransformNode() has_potential_animation(false), is_currently_animating(false), to_screen_is_potentially_animated(false), - has_only_translation_animations(true), flattens_inherited_transform(false), node_and_ancestors_are_flat(true), node_and_ancestors_have_only_integer_translation(true), @@ -36,7 +36,9 @@ TransformNode::TransformNode() moved_by_outer_viewport_bounds_delta_y(false), in_subtree_of_page_scale_layer(false), transform_changed(false), - post_local_scale_factor(1.0f) {} + post_local_scale_factor(1.0f), + maximum_animation_scale(kNotScaled), + starting_animation_scale(kNotScaled) {} TransformNode::TransformNode(const TransformNode&) = default; @@ -56,8 +58,6 @@ bool TransformNode::operator==(const TransformNode& other) const { is_currently_animating == other.is_currently_animating && to_screen_is_potentially_animated == other.to_screen_is_potentially_animated && - has_only_translation_animations == - other.has_only_translation_animations && flattens_inherited_transform == other.flattens_inherited_transform && node_and_ancestors_are_flat == other.node_and_ancestors_are_flat && node_and_ancestors_have_only_integer_translation == @@ -79,7 +79,9 @@ bool TransformNode::operator==(const TransformNode& other) const { scroll_offset == other.scroll_offset && snap_amount == other.snap_amount && source_offset == other.source_offset && - source_to_parent == other.source_to_parent; + source_to_parent == other.source_to_parent && + maximum_animation_scale == other.maximum_animation_scale && + starting_animation_scale == other.starting_animation_scale; } void TransformNode::update_pre_local_transform( diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h index c8f8ebf8505..ba14b1469b7 100644 --- a/chromium/cc/trees/transform_node.h +++ b/chromium/cc/trees/transform_node.h @@ -89,9 +89,6 @@ struct CC_EXPORT TransformNode { // (i.e., irrespective of exact timeline) transform // animation. bool to_screen_is_potentially_animated : 1; - // Whether all animations on this transform node are simple - // translations. - bool has_only_translation_animations : 1; // Flattening, when needed, is only applied to a node's inherited transform, // never to its local transform. @@ -112,6 +109,13 @@ struct CC_EXPORT TransformNode { // outer viewport. bool moved_by_inner_viewport_bounds_delta_x : 1; bool moved_by_inner_viewport_bounds_delta_y : 1; + + // These are used by the compositor to determine which layers need to be + // repositioned by the compositor as a result of browser controls + // expanding/contracting the outer viewport size before Blink repositions the + // fixed layers. + // TODO(bokan): Note: we never change bounds_delta in the x direction so we + // can remove this variable. bool moved_by_outer_viewport_bounds_delta_x : 1; bool moved_by_outer_viewport_bounds_delta_y : 1; @@ -139,6 +143,11 @@ struct CC_EXPORT TransformNode { gfx::Vector2dF source_offset; gfx::Vector2dF source_to_parent; + // See ElementAnimations::MaximumTargetScale() and AnimationStartScale() for + // their meanings. Updated by PropertyTrees::AnimationScalesChanged(). + float maximum_animation_scale; + float starting_animation_scale; + bool operator==(const TransformNode& other) const; void set_to_parent(const gfx::Transform& transform) { diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index 867593c7345..34839495a62 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -95,14 +95,14 @@ void PushElementsInPropertyTreesTo(LayerTreeType* host, id_iter != tree_impl->elements_in_property_trees().end();) { const auto& id = *(id_iter++); if (!host->elements_in_property_trees().count(id)) - tree_impl->RemoveFromElementLayerList(id); + tree_impl->RemoveFromElementPropertyTreeList(id); } for (const auto& id : host->elements_in_property_trees()) { - if (!tree_impl->IsElementInLayerList(id)) { + if (!tree_impl->IsElementInPropertyTree(id)) { // TODO(flackr): We should expose adding element ids without a // layer pointer. - tree_impl->AddToElementLayerList(id, nullptr); + tree_impl->AddToElementPropertyTreeList(id); } } } diff --git a/chromium/cc/trees/tree_synchronizer.h b/chromium/cc/trees/tree_synchronizer.h index 1f0a1a1c8cf..81f1986cc0b 100644 --- a/chromium/cc/trees/tree_synchronizer.h +++ b/chromium/cc/trees/tree_synchronizer.h @@ -7,7 +7,6 @@ #include <memory> -#include "base/macros.h" #include "cc/cc_export.h" namespace cc { @@ -19,6 +18,9 @@ class Layer; class CC_EXPORT TreeSynchronizer { public: + // Not instantiable. + TreeSynchronizer() = delete; + // 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. @@ -30,11 +32,6 @@ class CC_EXPORT TreeSynchronizer { LayerTreeImpl* active_tree); static void PushLayerProperties(LayerTreeHost* host_tree, LayerTreeImpl* impl_tree); - - private: - TreeSynchronizer(); // Not instantiable. - - DISALLOW_COPY_AND_ASSIGN(TreeSynchronizer); }; } // namespace cc diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc index 99b8819cb7c..b7a3dc02eee 100644 --- a/chromium/cc/trees/tree_synchronizer_unittest.cc +++ b/chromium/cc/trees/tree_synchronizer_unittest.cc @@ -766,7 +766,7 @@ TEST_F(TreeSynchronizerTest, RefreshPropertyTreesCachedData) { host_->CommitAndCreatePendingTree(); host_impl->ActivateSyncTree(); EXPECT_EQ( - CombinedAnimationScale(0.f, 0.f), + CombinedAnimationScale(kNotScaled, kNotScaled), host_impl->active_tree()->property_trees()->GetAnimationScales( transform_layer->transform_tree_index(), host_impl->active_tree())); } |