diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 10:22:43 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:36:28 +0000 |
commit | 271a6c3487a14599023a9106329505597638d793 (patch) | |
tree | e040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/cc/trees | |
parent | 7b2ffa587235a47d4094787d72f38102089f402a (diff) |
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/cc/trees')
69 files changed, 3189 insertions, 1446 deletions
diff --git a/chromium/cc/trees/damage_tracker.cc b/chromium/cc/trees/damage_tracker.cc index f3ddee21062..743b681dc6a 100644 --- a/chromium/cc/trees/damage_tracker.cc +++ b/chromium/cc/trees/damage_tracker.cc @@ -386,7 +386,7 @@ void DamageTracker::AccumulateDamageFromLayer(LayerImpl* layer) { // If the layer properties haven't changed, then the the target surface is // only affected by the layer's damaged area, which could be empty. gfx::Rect damage_rect = - gfx::UnionRects(layer->update_rect(), layer->damage_rect()); + gfx::UnionRects(layer->update_rect(), layer->GetDamageRect()); damage_rect.Intersect(gfx::Rect(layer->bounds())); if (!damage_rect.IsEmpty()) { @@ -416,7 +416,7 @@ void DamageTracker::AccumulateDamageFromLayer(LayerImpl* layer) { if (layer_is_new || !layer->update_rect().IsEmpty() || layer->LayerPropertyChangedNotFromPropertyTrees() || - !layer->damage_rect().IsEmpty() || property_change_on_non_target_node) { + !layer->GetDamageRect().IsEmpty() || property_change_on_non_target_node) { has_damage_from_contributing_content_ |= !damage_for_this_update_.IsEmpty(); } } diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index fcd75ca4f75..b9046c6644b 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -26,6 +26,36 @@ namespace cc { namespace { +class TestLayerImpl : public LayerImpl { + public: + TestLayerImpl(LayerTreeImpl* tree_impl, int id); + + void AddDamageRect(const gfx::Rect& damage_rect); + + // LayerImpl overrides. + gfx::Rect GetDamageRect() const override; + void ResetChangeTracking() override; + + private: + gfx::Rect damage_rect_; +}; + +TestLayerImpl::TestLayerImpl(LayerTreeImpl* tree_impl, int id) + : LayerImpl(tree_impl, id) {} + +void TestLayerImpl::AddDamageRect(const gfx::Rect& damage_rect) { + damage_rect_.Union(damage_rect); +} + +gfx::Rect TestLayerImpl::GetDamageRect() const { + return damage_rect_; +} + +void TestLayerImpl::ResetChangeTracking() { + LayerImpl::ResetChangeTracking(); + damage_rect_.SetRect(0, 0, 0, 0); +} + void ExecuteCalculateDrawProperties(LayerImpl* root, float device_scale_factor, RenderSurfaceList* render_surface_list) { @@ -71,16 +101,15 @@ class DamageTrackerTest : public testing::Test { LayerImpl* CreateTestTreeWithOneSurface(int number_of_children) { host_impl_.active_tree()->DetachLayers(); - std::unique_ptr<LayerImpl> root = - LayerImpl::Create(host_impl_.active_tree(), 1); + auto root = std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 1); root->SetBounds(gfx::Size(500, 500)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; for (int i = 0; i < number_of_children; ++i) { - std::unique_ptr<LayerImpl> child = - LayerImpl::Create(host_impl_.active_tree(), 2 + i); + auto child = + std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 2 + i); child->test_properties()->position = gfx::PointF(100.f, 100.f); child->SetBounds(gfx::Size(30, 30)); child->SetDrawsContent(true); @@ -98,16 +127,13 @@ class DamageTrackerTest : public testing::Test { // two children of its own. host_impl_.active_tree()->DetachLayers(); - std::unique_ptr<LayerImpl> root = - LayerImpl::Create(host_impl_.active_tree(), 1); - std::unique_ptr<LayerImpl> child1 = - LayerImpl::Create(host_impl_.active_tree(), 2); - std::unique_ptr<LayerImpl> child2 = - LayerImpl::Create(host_impl_.active_tree(), 3); - std::unique_ptr<LayerImpl> grand_child1 = - LayerImpl::Create(host_impl_.active_tree(), 4); - std::unique_ptr<LayerImpl> grand_child2 = - LayerImpl::Create(host_impl_.active_tree(), 5); + auto root = std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 1); + auto child1 = std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 2); + auto child2 = std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 3); + auto grand_child1 = + std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 4); + auto grand_child2 = + std::make_unique<TestLayerImpl>(host_impl_.active_tree(), 5); root->SetBounds(gfx::Size(500, 500)); root->SetDrawsContent(true); @@ -276,7 +302,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForUpdateRects) { TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) { LayerImpl* root = CreateAndSetUpTestTreeWithOneSurface(); - LayerImpl* child = root->test_properties()->children[0]; + auto* child = + static_cast<TestLayerImpl*>(root->test_properties()->children[0]); // CASE 1: Adding the layer damage rect should cause the corresponding damage // to the surface. @@ -336,7 +363,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForLayerDamageRects) { TEST_F(DamageTrackerTest, VerifyDamageForLayerUpdateAndDamageRects) { LayerImpl* root = CreateAndSetUpTestTreeWithOneSurface(); - LayerImpl* child = root->test_properties()->children[0]; + auto* child = + static_cast<TestLayerImpl*>(root->test_properties()->children[0]); // CASE 1: Adding the layer damage rect and update rect should cause the // corresponding damage to the surface. @@ -547,9 +575,12 @@ TEST_F(DamageTrackerTest, TransformPropertyChangeNoSurface) { TEST_F(DamageTrackerTest, VerifyDamageForUpdateAndDamageRectsFromContributingContents) { LayerImpl* root = CreateAndSetUpTestTreeWithTwoSurfaces(); - LayerImpl* child1 = root->test_properties()->children[0]; - LayerImpl* child2 = root->test_properties()->children[1]; - LayerImpl* grandchild1 = child1->test_properties()->children[0]; + auto* child1 = + static_cast<TestLayerImpl*>(root->test_properties()->children[0]); + auto* child2 = + static_cast<TestLayerImpl*>(root->test_properties()->children[1]); + auto* grandchild1 = + static_cast<TestLayerImpl*>(child1->test_properties()->children[0]); // CASE 1: Adding the layer1's damage rect and update rect should cause the // corresponding damage to the surface. @@ -1912,8 +1943,10 @@ TEST_F(DamageTrackerTest, DamageRectTooBigWithFilter) { TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { LayerImpl* root = CreateAndSetUpTestTreeWithTwoSurfaces(); LayerImpl* child1 = root->test_properties()->children[0]; - LayerImpl* grandchild1 = child1->test_properties()->children[0]; - LayerImpl* grandchild2 = child1->test_properties()->children[1]; + auto* grandchild1 = + static_cast<TestLayerImpl*>(child1->test_properties()->children[0]); + auto* grandchild2 = + static_cast<TestLayerImpl*>(child1->test_properties()->children[1]); // Really far left. grandchild1->test_properties()->position = @@ -2002,8 +2035,10 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { LayerImpl* root = CreateAndSetUpTestTreeWithTwoSurfaces(); LayerImpl* child1 = root->test_properties()->children[0]; - LayerImpl* grandchild1 = child1->test_properties()->children[0]; - LayerImpl* grandchild2 = child1->test_properties()->children[1]; + auto* grandchild1 = + static_cast<TestLayerImpl*>(child1->test_properties()->children[0]); + auto* grandchild2 = + static_cast<TestLayerImpl*>(child1->test_properties()->children[1]); // Set up a moving pixels filter on the child. FilterOperations filters; diff --git a/chromium/cc/trees/draw_property_utils.cc b/chromium/cc/trees/draw_property_utils.cc index 9c1bec65c92..cf566cb9b6e 100644 --- a/chromium/cc/trees/draw_property_utils.cc +++ b/chromium/cc/trees/draw_property_utils.cc @@ -838,8 +838,17 @@ void FindLayersThatNeedUpdates(LayerTreeImpl* layer_tree_impl, } void ComputeTransforms(TransformTree* transform_tree) { - if (!transform_tree->needs_update()) + if (!transform_tree->needs_update()) { +#if DCHECK_IS_ON() + // If the transform tree does not need an update, no TransformNode should + // need a local transform update. + for (int i = TransformTree::kContentsRootNodeId; + i < static_cast<int>(transform_tree->size()); ++i) { + DCHECK(!transform_tree->Node(i)->needs_local_transform_update); + } +#endif return; + } for (int i = TransformTree::kContentsRootNodeId; i < static_cast<int>(transform_tree->size()); ++i) transform_tree->UpdateTransforms(i); @@ -872,22 +881,11 @@ void UpdatePropertyTrees(LayerTreeHost* layer_tree_host, } void UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, - PropertyTrees* property_trees, - bool can_adjust_raster_scales) { - bool render_surfaces_need_update = false; - if (property_trees->can_adjust_raster_scales != can_adjust_raster_scales) { - property_trees->can_adjust_raster_scales = can_adjust_raster_scales; - property_trees->transform_tree.set_needs_update(true); - render_surfaces_need_update = true; - } + PropertyTrees* property_trees) { if (property_trees->transform_tree.needs_update()) { property_trees->clip_tree.set_needs_update(true); property_trees->effect_tree.set_needs_update(true); } - if (render_surfaces_need_update) { - property_trees->effect_tree.UpdateRenderSurfaces( - root_layer->layer_tree_impl()); - } UpdateRenderTarget(&property_trees->effect_tree); ComputeTransforms(&property_trees->transform_tree); diff --git a/chromium/cc/trees/draw_property_utils.h b/chromium/cc/trees/draw_property_utils.h index c37eaa0c066..6ca984986bd 100644 --- a/chromium/cc/trees/draw_property_utils.h +++ b/chromium/cc/trees/draw_property_utils.h @@ -44,8 +44,7 @@ void CC_EXPORT UpdatePropertyTrees(LayerTreeHost* layer_tree_host, void CC_EXPORT UpdatePropertyTreesAndRenderSurfaces(LayerImpl* root_layer, - PropertyTrees* property_trees, - bool can_adjust_raster_scales); + PropertyTrees* property_trees); void CC_EXPORT FindLayersThatNeedUpdates(LayerTreeHost* layer_tree_host, const PropertyTrees* property_trees, diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc index 8c7a016eee4..847432950b3 100644 --- a/chromium/cc/trees/effect_node.cc +++ b/chromium/cc/trees/effect_node.cc @@ -57,6 +57,7 @@ bool EffectNode::operator==(const EffectNode& other) const { filters == other.filters && backdrop_filters == other.backdrop_filters && backdrop_filter_bounds == other.backdrop_filter_bounds && + backdrop_mask_element_id == other.backdrop_mask_element_id && filters_origin == other.filters_origin && rounded_corner_bounds == other.rounded_corner_bounds && is_fast_rounded_corner == other.is_fast_rounded_corner && @@ -142,10 +143,15 @@ const char* RenderSurfaceReasonToString(RenderSurfaceReason reason) { } void EffectNode::AsValueInto(base::trace_event::TracedValue* value) const { + value->SetInteger("backdrop_mask_element_id", + backdrop_mask_element_id.GetInternalValue()); value->SetInteger("id", id); value->SetInteger("parent_id", parent_id); value->SetInteger("stable_id", stable_id); value->SetDouble("opacity", opacity); + if (!backdrop_filters.IsEmpty()) { + value->SetString("backdrop_filters", backdrop_filters.ToString()); + } value->SetDouble("backdrop_filter_quality", backdrop_filter_quality); value->SetBoolean("is_fast_rounded_corner", is_fast_rounded_corner); if (!rounded_corner_bounds.IsEmpty()) { diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index 340305e9355..eaddb83fb4e 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -6,6 +6,7 @@ #define CC_TREES_EFFECT_NODE_H_ #include "cc/cc_export.h" +#include "cc/paint/element_id.h" #include "cc/paint/filter_operations.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point_f.h" @@ -40,6 +41,7 @@ enum class RenderSurfaceReason : uint8_t { kTrilinearFiltering, kCache, kCopyRequest, + kMirrored, // This must be the last value because it's used in tracing code to know the // number of reasons. kTest, @@ -73,6 +75,11 @@ struct CC_EXPORT EffectNode { float backdrop_filter_quality; gfx::PointF filters_origin; + // The element id corresponding to the mask to apply to the filtered backdrop + // image. Note that this is separate from mask_layer_id, which is a layer id, + // and is used for masking the "normal" (non-backdrop-filter) content. + ElementId backdrop_mask_element_id; + // Bounds of rounded corner rrect in the space of the transform node // associated with this effect node. gfx::RRectF rounded_corner_bounds; diff --git a/chromium/cc/trees/element_id.cc b/chromium/cc/trees/element_id.cc deleted file mode 100644 index 6690378fc16..00000000000 --- a/chromium/cc/trees/element_id.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "cc/trees/element_id.h" - -#include <inttypes.h> -#include <limits> -#include <ostream> - -#include "base/strings/stringprintf.h" -#include "base/trace_event/traced_value.h" -#include "base/values.h" - -namespace cc { - -const ElementIdType ElementId::kInvalidElementId = 0; - -ElementId LayerIdToElementIdForTesting(int layer_id) { - return ElementId(std::numeric_limits<int>::max() - layer_id); -} - -void ElementId::AddToTracedValue(base::trace_event::TracedValue* res) const { - res->BeginDictionary("element_id"); - res->SetInteger("id_", id_); - res->EndDictionary(); -} - -ElementIdType ElementId::GetInternalValue() const { - return id_; -} - -std::string ElementId::ToString() const { - return base::StringPrintf("(%" PRIu64 ")", id_); -} - -std::unique_ptr<base::Value> ElementId::AsValue() const { - std::unique_ptr<base::DictionaryValue> res(new base::DictionaryValue()); - res->SetInteger("id_", id_); - return std::move(res); -} - -size_t ElementIdHash::operator()(ElementId key) const { - return std::hash<int>()(key.id_); -} - -std::ostream& operator<<(std::ostream& out, const ElementId& id) { - return out << id.ToString(); -} - -} // namespace cc diff --git a/chromium/cc/trees/element_id.h b/chromium/cc/trees/element_id.h deleted file mode 100644 index e8275c521cc..00000000000 --- a/chromium/cc/trees/element_id.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_TREES_ELEMENT_ID_H_ -#define CC_TREES_ELEMENT_ID_H_ - -#include <stddef.h> - -#include <cstdint> -#include <functional> -#include <iosfwd> -#include <memory> - -#include "base/hash/hash.h" -#include "cc/cc_export.h" - -namespace base { -class Value; -namespace trace_event { -class TracedValue; -} // namespace trace_event -} // namespace base - -namespace cc { - -using ElementIdType = uint64_t; - -// Element ids are chosen by cc's clients and can be used as a stable identifier -// across updates. -// -// Historically, the layer tree stored all compositing data but this has been -// refactored over time into auxilliary structures such as property trees. -// -// In composited scrolling, Layers directly reference scroll tree nodes -// (Layer::scroll_tree_index) but scroll tree nodes are being refactored to -// reference stable element ids instead of layers. Scroll property nodes have -// unique element ids that blink creates from scrollable areas (though this is -// opaque to the compositor). This refactoring of scroll nodes keeping a -// scrolling element id instead of a scrolling layer id allows for more general -// compositing where, for example, multiple layers scroll with one scroll node. -// -// The animation system (see ElementAnimations) is another auxilliary structure -// to the layer tree and uses element ids as a stable identifier for animation -// 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) { - 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_; } - - // 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; - std::unique_ptr<base::Value> AsValue() const; - - ElementIdType GetInternalValue() const; - - std::string ToString() const; - - 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 - // layers and may set this value to match the client's layer id. - ElementIdType id_; -}; - -ElementId CC_EXPORT LayerIdToElementIdForTesting(int layer_id); - -struct CC_EXPORT ElementIdHash { - size_t operator()(ElementId key) const; -}; - -// Stream operator so ElementId can be used in assertion statements. -CC_EXPORT std::ostream& operator<<(std::ostream& out, const ElementId& id); - -} // namespace cc - -#endif // CC_TREES_ELEMENT_ID_H_ diff --git a/chromium/cc/trees/frame_sequence_tracker.cc b/chromium/cc/trees/frame_sequence_tracker.cc new file mode 100644 index 00000000000..a4020409e7a --- /dev/null +++ b/chromium/cc/trees/frame_sequence_tracker.cc @@ -0,0 +1,390 @@ +// 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/trees/frame_sequence_tracker.h" + +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" +#include "base/strings/strcat.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/traced_value.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" +#include "components/viz/common/quads/compositor_frame_metadata.h" +#include "ui/gfx/presentation_feedback.h" + +namespace cc { + +namespace { + +enum class ThreadType { + kMain, + kCompositor, +}; + +constexpr const char* const kBuiltinSequences[] = { + [FrameSequenceTrackerType::kCompositorAnimation] = "CompositorAnimation", + [FrameSequenceTrackerType::kMainThreadAnimation] = "MainThreadAnimation", + [FrameSequenceTrackerType::kPinchZoom] = "PinchZoom", + [FrameSequenceTrackerType::kRAF] = "RAF", + [FrameSequenceTrackerType::kTouchScroll] = "TouchScroll", + [FrameSequenceTrackerType::kWheelScroll] = "WheelScroll", +}; + +constexpr int kBuiltinSequenceNum = base::size(kBuiltinSequences); +constexpr int kMaximumHistogramIndex = 2 * kBuiltinSequenceNum; + +int GetIndexForMetric(ThreadType thread_type, FrameSequenceTrackerType type) { + return thread_type == ThreadType::kMain + ? static_cast<int>(type) + : static_cast<int>(type + kBuiltinSequenceNum); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// FrameSequenceTrackerCollection + +FrameSequenceTrackerCollection::FrameSequenceTrackerCollection() {} +FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() { + removal_trackers_.clear(); + DCHECK(frame_trackers_.empty()); +} + +std::unique_ptr<FrameSequenceTracker> +FrameSequenceTrackerCollection::CreateTracker(FrameSequenceTrackerType type) { + // The collection always outlives the trackers. So using Unretained() here is + // safe. + auto tracker = base::WrapUnique(new FrameSequenceTracker( + type, base::BindOnce(&FrameSequenceTrackerCollection::RemoveFrameTracker, + base::Unretained(this)))); + AddFrameTracker(tracker.get()); + return tracker; +} + +void FrameSequenceTrackerCollection::ScheduleRemoval( + std::unique_ptr<FrameSequenceTracker> tracker) { + if (!tracker) + return; + tracker->ScheduleTerminate(); + removal_trackers_.push_back(std::move(tracker)); +} + +void FrameSequenceTrackerCollection::ClearAll() { + removal_trackers_.clear(); + DCHECK(frame_trackers_.empty()); +} + +void FrameSequenceTrackerCollection::NotifyBeginImplFrame( + const viz::BeginFrameArgs& args) { + for (auto* tracker : frame_trackers_) { + tracker->ReportBeginImplFrame(args); + } +} + +void FrameSequenceTrackerCollection::NotifyBeginMainFrame( + const viz::BeginFrameArgs& args) { + for (auto* tracker : frame_trackers_) { + tracker->ReportBeginMainFrame(args); + } +} + +void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage( + const viz::BeginFrameAck& ack) { + for (auto* tracker : frame_trackers_) { + tracker->ReportImplFrameCausedNoDamage(ack); + } +} + +void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage( + const viz::BeginFrameArgs& args) { + for (auto* tracker : frame_trackers_) { + tracker->ReportMainFrameCausedNoDamage(args); + } +} + +void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() { + for (auto* tracker : frame_trackers_) + tracker->PauseFrameProduction(); +} + +void FrameSequenceTrackerCollection::NotifySubmitFrame( + uint32_t frame_token, + const viz::BeginFrameAck& ack, + const viz::BeginFrameArgs& origin_args) { + for (auto* tracker : frame_trackers_) { + tracker->ReportSubmitFrame(frame_token, ack, origin_args); + } +} + +void FrameSequenceTrackerCollection::NotifyFramePresented( + uint32_t frame_token, + const gfx::PresentationFeedback& feedback) { + for (auto* tracker : frame_trackers_) + tracker->ReportFramePresented(frame_token, feedback); + + // Destroy the trackers that are ready to be terminated. + base::EraseIf( + removal_trackers_, + [](const std::unique_ptr<FrameSequenceTracker>& tracker) { + return tracker->termination_status() == + FrameSequenceTracker::TerminationStatus::kReadyForTermination; + }); +} + +void FrameSequenceTrackerCollection::AddFrameTracker( + FrameSequenceTracker* tracker) { + frame_trackers_.push_back(tracker); +} + +void FrameSequenceTrackerCollection::RemoveFrameTracker( + FrameSequenceTracker* tracker) { + base::Erase(frame_trackers_, tracker); +} + +//////////////////////////////////////////////////////////////////////////////// +// FrameSequenceTracker + +FrameSequenceTracker::FrameSequenceTracker( + FrameSequenceTrackerType type, + base::OnceCallback<void(FrameSequenceTracker*)> destroy_callback) + : type_(type), destroy_callback_(std::move(destroy_callback)) { + DCHECK_LT(type_, FrameSequenceTrackerType::kMaxType); + TRACE_EVENT_ASYNC_BEGIN1("cc,benchmark", "FrameSequenceTracker", this, "name", + TRACE_STR_COPY(kBuiltinSequences[type_])); +} + +FrameSequenceTracker::~FrameSequenceTracker() { + DCHECK_LE(impl_throughput_.frames_produced, impl_throughput_.frames_expected); + DCHECK_LE(main_throughput_.frames_produced, main_throughput_.frames_expected); + DCHECK_LE(main_throughput_.frames_produced, impl_throughput_.frames_produced); + TRACE_EVENT_ASYNC_END1( + "cc,benchmark", "FrameSequenceTracker", this, "args", + ThroughputData::ToTracedValue(impl_throughput_, main_throughput_)); + ThroughputData::ReportHistogram( + type_, "CompositorThread", + GetIndexForMetric(ThreadType::kCompositor, type_), impl_throughput_); + ThroughputData::ReportHistogram(type_, "MainThread", + GetIndexForMetric(ThreadType::kMain, type_), + main_throughput_); + std::move(destroy_callback_).Run(this); +} + +void FrameSequenceTracker::ReportBeginImplFrame( + const viz::BeginFrameArgs& args) { + if (termination_status_ != TerminationStatus::kActive) + return; + + if (ShouldIgnoreBeginFrameSource(args.source_id)) + return; + + UpdateTrackedFrameData(&begin_impl_frame_data_, args.source_id, + args.sequence_number); + impl_throughput_.frames_expected += + begin_impl_frame_data_.previous_sequence_delta; +} + +void FrameSequenceTracker::ReportBeginMainFrame( + const viz::BeginFrameArgs& args) { + if (termination_status_ != TerminationStatus::kActive) + return; + + if (ShouldIgnoreBeginFrameSource(args.source_id)) + return; + + UpdateTrackedFrameData(&begin_main_frame_data_, args.source_id, + args.sequence_number); + if (first_received_main_sequence_ == 0) + first_received_main_sequence_ = args.sequence_number; + main_throughput_.frames_expected += + begin_main_frame_data_.previous_sequence_delta; +} + +void FrameSequenceTracker::ReportSubmitFrame( + uint32_t frame_token, + const viz::BeginFrameAck& ack, + const viz::BeginFrameArgs& origin_args) { + if (termination_status_ != TerminationStatus::kActive) + return; + + if (ShouldIgnoreBeginFrameSource(ack.source_id)) + return; + + if (begin_impl_frame_data_.previous_sequence == 0 || + ack.sequence_number < begin_impl_frame_data_.previous_sequence) { + return; + } + + if (first_submitted_frame_ == 0) + first_submitted_frame_ = frame_token; + last_submitted_frame_ = frame_token; + + if (!ShouldIgnoreBeginFrameSource(origin_args.source_id) && + first_received_main_sequence_ && + origin_args.sequence_number >= first_received_main_sequence_) { + if (last_submitted_main_sequence_ == 0 || + origin_args.sequence_number > last_submitted_main_sequence_) { + last_submitted_main_sequence_ = origin_args.sequence_number; + main_frames_.push_back(frame_token); + DCHECK_GE(main_throughput_.frames_expected, main_frames_.size()); + } + } +} + +void FrameSequenceTracker::ReportFramePresented( + uint32_t frame_token, + const gfx::PresentationFeedback& feedback) { + const bool frame_token_acks_last_frame = + frame_token == last_submitted_frame_ || + viz::FrameTokenGT(frame_token, last_submitted_frame_); + + // Update termination status if this is scheduled for termination, and it is + // not waiting for any frames, or it has received the presentation-feedback + // for the latest frame it is tracking. + if (termination_status_ == TerminationStatus::kScheduledForTermination && + (last_submitted_frame_ == 0 || frame_token_acks_last_frame)) { + termination_status_ = TerminationStatus::kReadyForTermination; + } + + if (first_submitted_frame_ == 0 || + viz::FrameTokenGT(first_submitted_frame_, frame_token)) { + // We are getting presentation feedback for frames that were submitted + // before this sequence started. So ignore these. + return; + } + + const bool was_presented = !feedback.timestamp.is_null(); + if (was_presented && last_submitted_frame_) { + DCHECK_LT(impl_throughput_.frames_produced, + impl_throughput_.frames_expected); + ++impl_throughput_.frames_produced; + + if (frame_token_acks_last_frame) + last_submitted_frame_ = 0; + } + + while (!main_frames_.empty() && + !viz::FrameTokenGT(main_frames_.front(), frame_token)) { + if (was_presented && main_frames_.front() == frame_token) { + DCHECK_LT(main_throughput_.frames_produced, + main_throughput_.frames_expected); + ++main_throughput_.frames_produced; + } + main_frames_.pop_front(); + } +} + +void FrameSequenceTracker::ReportImplFrameCausedNoDamage( + const viz::BeginFrameAck& ack) { + if (termination_status_ != TerminationStatus::kActive) + return; + + if (ShouldIgnoreBeginFrameSource(ack.source_id)) + return; + + // It is possible that this is called before a begin-impl-frame has been + // dispatched for this frame-sequence. In such cases, ignore this call. + if (begin_impl_frame_data_.previous_sequence == 0 || + ack.sequence_number < begin_impl_frame_data_.previous_sequence) { + return; + } + DCHECK_GT(impl_throughput_.frames_expected, 0u); + DCHECK_GT(impl_throughput_.frames_expected, impl_throughput_.frames_produced); + --impl_throughput_.frames_expected; + + if (begin_impl_frame_data_.previous_sequence == ack.sequence_number) + begin_impl_frame_data_.previous_sequence = 0; +} + +void FrameSequenceTracker::ReportMainFrameCausedNoDamage( + const viz::BeginFrameArgs& args) { + if (termination_status_ != TerminationStatus::kActive) + return; + + if (ShouldIgnoreBeginFrameSource(args.source_id)) + return; + + // It is possible that this is called before a begin-main-frame has been + // dispatched for this frame-sequence. In such cases, ignore this call. + if (begin_main_frame_data_.previous_sequence == 0 || + args.sequence_number < begin_main_frame_data_.previous_sequence) { + return; + } + + DCHECK_GT(main_throughput_.frames_expected, 0u); + DCHECK_GT(main_throughput_.frames_expected, main_throughput_.frames_produced); + --main_throughput_.frames_expected; + DCHECK_GE(main_throughput_.frames_expected, main_frames_.size()); + + if (begin_main_frame_data_.previous_sequence == args.sequence_number) + begin_main_frame_data_.previous_sequence = 0; +} + +void FrameSequenceTracker::PauseFrameProduction() { + // Reset the states, so that the tracker ignores the vsyncs until the next + // received begin-frame. + begin_impl_frame_data_ = {0, 0, 0}; + begin_main_frame_data_ = {0, 0, 0}; +} + +void FrameSequenceTracker::UpdateTrackedFrameData(TrackedFrameData* frame_data, + uint64_t source_id, + uint64_t sequence_number) { + if (frame_data->previous_sequence && + frame_data->previous_source == source_id) { + uint8_t current_latency = sequence_number - frame_data->previous_sequence; + frame_data->previous_sequence_delta = current_latency; + } else { + frame_data->previous_sequence_delta = 1; + } + frame_data->previous_source = source_id; + frame_data->previous_sequence = sequence_number; +} + +bool FrameSequenceTracker::ShouldIgnoreBeginFrameSource( + uint64_t source_id) const { + if (begin_impl_frame_data_.previous_source == 0) + return false; + return source_id != begin_impl_frame_data_.previous_source; +} + +std::unique_ptr<base::trace_event::TracedValue> +FrameSequenceTracker::ThroughputData::ToTracedValue( + const ThroughputData& impl, + const ThroughputData& main) { + auto dict = std::make_unique<base::trace_event::TracedValue>(); + dict->SetInteger("impl-frames-produced", impl.frames_produced); + dict->SetInteger("impl-frames-expected", impl.frames_expected); + dict->SetInteger("main-frames-produced", main.frames_produced); + dict->SetInteger("main-frames-expected", main.frames_expected); + return dict; +} + +void FrameSequenceTracker::ThroughputData::ReportHistogram( + FrameSequenceTrackerType sequence_type, + const char* thread_name, + int metric_index, + const ThroughputData& data) { + DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType); + + UMA_HISTOGRAM_COUNTS_1000("Graphics.Smoothness.FrameSequenceLength", + data.frames_expected); + + // Avoid reporting any throughput metric for sequences that had a small amount + // of frames. + constexpr int kMinFramesForThroughputMetric = 4; + if (data.frames_expected < kMinFramesForThroughputMetric) + return; + + const std::string name = + base::StrCat({"Graphics.Smoothness.Throughput.", thread_name, ".", + kBuiltinSequences[sequence_type]}); + const int percent = + static_cast<int>(100 * data.frames_produced / data.frames_expected); + STATIC_HISTOGRAM_POINTER_GROUP( + name, metric_index, kMaximumHistogramIndex, Add(percent), + base::LinearHistogram::FactoryGet( + name, 1, 100, 101, base::HistogramBase::kUmaTargetedHistogramFlag)); +} + +} // namespace cc diff --git a/chromium/cc/trees/frame_sequence_tracker.h b/chromium/cc/trees/frame_sequence_tracker.h new file mode 100644 index 00000000000..57b370eb316 --- /dev/null +++ b/chromium/cc/trees/frame_sequence_tracker.h @@ -0,0 +1,238 @@ +// 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_TREES_FRAME_SEQUENCE_TRACKER_H_ +#define CC_TREES_FRAME_SEQUENCE_TRACKER_H_ + +#include <stdint.h> +#include <memory> +#include <set> +#include <utility> +#include <vector> + +#include "base/callback_helpers.h" +#include "base/containers/circular_deque.h" +#include "base/macros.h" +#include "base/trace_event/traced_value.h" +#include "cc/cc_export.h" + +namespace gfx { +struct PresentationFeedback; +} + +namespace viz { +struct BeginFrameAck; +struct BeginFrameArgs; +} // namespace viz + +namespace cc { +class FrameSequenceTracker; + +enum FrameSequenceTrackerType { + kCompositorAnimation, + kMainThreadAnimation, + kPinchZoom, + kRAF, + kTouchScroll, + kWheelScroll, + kMaxType +}; + +// Used for notifying attached FrameSequenceTracker's of begin-frames and +// submitted frames. +class CC_EXPORT FrameSequenceTrackerCollection { + public: + FrameSequenceTrackerCollection(); + ~FrameSequenceTrackerCollection(); + + FrameSequenceTrackerCollection(const FrameSequenceTrackerCollection&) = + delete; + FrameSequenceTrackerCollection& operator=( + const FrameSequenceTrackerCollection&) = delete; + + // Creates a tracker for the specified sequence-type. + std::unique_ptr<FrameSequenceTracker> CreateTracker( + FrameSequenceTrackerType type); + + // Schedules |tracker| for destruction. This is preferred instead of outright + // desrtruction of the tracker, since this ensures that the actual tracker + // instance is destroyed *after* the presentation-feedbacks have been received + // for all submitted frames. + void ScheduleRemoval(std::unique_ptr<FrameSequenceTracker> tracker); + + // Removes all trackers. This also immediately destroys all trackers that had + // been scheduled for destruction, even if there are pending + // presentation-feedbacks. This is typically used if the client no longer + // expects to receive presentation-feedbacks for the previously submitted + // frames (e.g. when the gpu process dies). + void ClearAll(); + + // Notifies all trackers of various events. + void NotifyBeginImplFrame(const viz::BeginFrameArgs& args); + void NotifyBeginMainFrame(const viz::BeginFrameArgs& args); + void NotifyImplFrameCausedNoDamage(const viz::BeginFrameAck& ack); + void NotifyMainFrameCausedNoDamage(const viz::BeginFrameArgs& args); + void NotifyPauseFrameProduction(); + void NotifySubmitFrame(uint32_t frame_token, + const viz::BeginFrameAck& ack, + const viz::BeginFrameArgs& origin_args); + + // Note that this notifies the trackers of the presentation-feedbacks, and + // destroys any tracker that had been scheduled for destruction (using + // |ScheduleRemoval()|) if it has no more pending frames. + void NotifyFramePresented(uint32_t frame_token, + const gfx::PresentationFeedback& feedback); + + private: + void AddFrameTracker(FrameSequenceTracker* tracker); + void RemoveFrameTracker(FrameSequenceTracker* tracker); + + std::vector<FrameSequenceTracker*> frame_trackers_; + std::vector<std::unique_ptr<FrameSequenceTracker>> removal_trackers_; +}; + +// Tracks a sequence of frames to determine the throughput. It tracks this by +// tracking the vsync sequence-numbers (from |BeginFrameArgs::sequence_number|), +// and the presentation-timestamps (from |gfx::PresentationFeedback|). It also +// tracks which frames were expected to include update from the main-thread, and +// which presented frames did include updates from the main-thread. +// This object should be created through +// FrameSequenceTrackerCollection::CreateTracker() API. +class CC_EXPORT FrameSequenceTracker { + public: + enum class TerminationStatus { + kActive, + kScheduledForTermination, + kReadyForTermination, + }; + + ~FrameSequenceTracker(); + + FrameSequenceTracker(const FrameSequenceTracker&) = delete; + FrameSequenceTracker& operator=(const FrameSequenceTracker&) = delete; + + // Notifies the tracker when the compositor thread starts to process a + // BeginFrameArgs. + void ReportBeginImplFrame(const viz::BeginFrameArgs& args); + + // Notifies the tracker when a BeginFrameArgs is dispatched to the main + // thread. + void ReportBeginMainFrame(const viz::BeginFrameArgs& args); + + // Notifies the tracker when the compositor submits a CompositorFrame. + // |origin_args| represents the BeginFrameArgs that triggered the update from + // the main-thread. + void ReportSubmitFrame(uint32_t frame_token, + const viz::BeginFrameAck& ack, + const viz::BeginFrameArgs& origin_args); + + // Notifies the tracker of the presentation-feedback of a previously submitted + // CompositorFrame with |frame_token|. + void ReportFramePresented(uint32_t frame_token, + const gfx::PresentationFeedback& feedback); + + // Notifies the tracker that a CompositorFrame is not going to be submitted + // for a particular BeginFrameArgs because it did not cause any damage (visual + // change). Note that if a begin-main-frame was dispatched, then a separate + // call to |ReportMainFrameCausedNoDamage()| is made to notify that the + // main-thread did not cause any damage/updates. + void ReportImplFrameCausedNoDamage(const viz::BeginFrameAck& ack); + + // Notifies the tracker that a |BeginFrameArgs| either was not dispatched to + // the main-thread (because it did not ask for it), or that a |BeginFrameArgs| + // that was dispatched to the main-thread did not cause any updates/damage. + void ReportMainFrameCausedNoDamage(const viz::BeginFrameArgs& args); + + // Notifies that frame production has currently paused. This is typically used + // for interactive frame-sequences, e.g. during touch-scroll. + void PauseFrameProduction(); + + TerminationStatus termination_status() const { return termination_status_; } + + private: + friend class FrameSequenceTrackerCollection; + + FrameSequenceTracker( + FrameSequenceTrackerType type, + base::OnceCallback<void(FrameSequenceTracker*)> destroy_callback); + + void ScheduleTerminate() { + termination_status_ = TerminationStatus::kScheduledForTermination; + } + + struct TrackedFrameData { + // Represents the |BeginFrameArgs::source_id| and + // |BeginFrameArgs::sequence_number| fields of the last processed + // BeginFrameArgs. + uint64_t previous_source = 0; + uint64_t previous_sequence = 0; + + // The difference in |BeginFrameArgs::sequence_number| fields of the last + // two processed BeginFrameArgs. + uint8_t previous_sequence_delta = 0; + }; + + struct ThroughputData { + static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue( + const ThroughputData& impl, + const ThroughputData& main); + static void ReportHistogram(FrameSequenceTrackerType sequence_type, + const char* thread_name, + int metric_index, + const ThroughputData& data); + // Tracks the number of frames that were expected to be shown during this + // frame-sequence. + uint32_t frames_expected = 0; + + // Tracks the number of frames that were actually presented to the user + // during this frame-sequence. + uint32_t frames_produced = 0; + }; + + void UpdateTrackedFrameData(TrackedFrameData* frame_data, + uint64_t source_id, + uint64_t sequence_number); + + bool ShouldIgnoreBeginFrameSource(uint64_t source_id) const; + + const FrameSequenceTrackerType type_; + base::OnceCallback<void(FrameSequenceTracker*)> destroy_callback_; + + TerminationStatus termination_status_ = TerminationStatus::kActive; + + TrackedFrameData begin_impl_frame_data_; + TrackedFrameData begin_main_frame_data_; + + ThroughputData impl_throughput_; + ThroughputData main_throughput_; + + // Tracks the list of frame-tokens for compositor-frames that included new + // updates from the main-thread, whose presentation-feedback have not been + // received yet. When the presentation-feedback for a frame is received, the + // corresponding frame-token is removed from this collection. + base::circular_deque<uint32_t> main_frames_; + + // Keeps track of the sequence-number of the first received begin-main-frame. + // This is used to ignore submitted frames that include updates from earlier + // begin-main-frames. + uint64_t first_received_main_sequence_ = 0; + + // Keeps track of the first submitted compositor-frame. This is used to ignore + // reports from frames that were submitted before this tracker had been + // created. + uint32_t first_submitted_frame_ = 0; + + // Keeps track of the latest submitted compositor-frame, so that it can + // determine when it has received presentation-feedback for submitted frames. + // This is used to decide when to terminate this FrameSequenceTracker object. + uint32_t last_submitted_frame_ = 0; + + // Keeps track of the last sequence-number that produced a frame from the + // main-thread. + uint64_t last_submitted_main_sequence_ = 0; +}; + +} // namespace cc + +#endif // CC_TREES_FRAME_SEQUENCE_TRACKER_H_ diff --git a/chromium/cc/trees/frame_sequence_tracker_unittest.cc b/chromium/cc/trees/frame_sequence_tracker_unittest.cc new file mode 100644 index 00000000000..1de4c9c38a9 --- /dev/null +++ b/chromium/cc/trees/frame_sequence_tracker_unittest.cc @@ -0,0 +1,109 @@ +// 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/trees/frame_sequence_tracker.h" + +#include "base/macros.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class FrameSequenceTrackerTest; + +class FrameSequenceTrackerTest : public testing::Test { + public: + const uint32_t kImplDamage = 0x1; + const uint32_t kMainDamage = 0x2; + + FrameSequenceTrackerTest() + : tracker_( + collection_.CreateTracker(FrameSequenceTrackerType::kTouchScroll)) { + } + ~FrameSequenceTrackerTest() override = default; + + std::unique_ptr<FrameSequenceTracker> CreateNewTracker() { + return collection_.CreateTracker(FrameSequenceTrackerType::kTouchScroll); + } + + viz::BeginFrameArgs CreateBeginFrameArgs(uint64_t source_id, + uint64_t sequence_number) { + auto now = base::TimeTicks::Now(); + auto interval = base::TimeDelta::FromMilliseconds(16); + auto deadline = now + interval; + return viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, source_id, + sequence_number, now, deadline, interval, + viz::BeginFrameArgs::NORMAL); + } + + void StartImplAndMainFrames(const viz::BeginFrameArgs& args) { + collection_.NotifyBeginImplFrame(args); + collection_.NotifyBeginMainFrame(args); + } + + uint32_t DispatchCompleteFrame(const viz::BeginFrameArgs& args, + uint32_t damage_type) { + StartImplAndMainFrames(args); + + if (damage_type & kImplDamage) { + if (!(damage_type & kMainDamage)) { + collection_.NotifyMainFrameCausedNoDamage(args); + } + uint32_t frame_token = NextFrameToken(); + collection_.NotifySubmitFrame(frame_token, viz::BeginFrameAck(args, true), + args); + return frame_token; + } else { + collection_.NotifyImplFrameCausedNoDamage( + viz::BeginFrameAck(args, false)); + collection_.NotifyMainFrameCausedNoDamage(args); + } + return 0; + } + + uint32_t NextFrameToken() { + static uint32_t frame_token = 0; + return ++frame_token; + } + + protected: + FrameSequenceTrackerCollection collection_; + + std::unique_ptr<FrameSequenceTracker> tracker_; +}; + +// Tests that the tracker works correctly when the source-id for the +// begin-frames change. +TEST_F(FrameSequenceTrackerTest, SourceIdChangeDuringSequence) { + const uint64_t source_1 = 1; + uint64_t sequence_1 = 0; + + // Dispatch some frames, both causing damage to impl/main, and both impl and + // main providing damage to the frame. + auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1); + DispatchCompleteFrame(args_1, kImplDamage | kMainDamage); + args_1 = CreateBeginFrameArgs(source_1, ++sequence_1); + DispatchCompleteFrame(args_1, kImplDamage | kMainDamage); + + // Start a new tracker. + auto tracker = CreateNewTracker(); + + // Change the source-id, and start an impl frame. This time, the main-frame + // does not provide any damage. + const uint64_t source_2 = 2; + uint64_t sequence_2 = 0; + auto args_2 = CreateBeginFrameArgs(source_2, ++sequence_2); + collection_.NotifyBeginImplFrame(args_2); + collection_.NotifyBeginMainFrame(args_2); + collection_.NotifyMainFrameCausedNoDamage(args_2); + // Since the main-frame did not have any new damage from the latest + // BeginFrameArgs, the submit-frame will carry the previous BeginFrameArgs + // (from source_1); + collection_.NotifySubmitFrame(NextFrameToken(), + viz::BeginFrameAck(args_2, true), args_1); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/trees/image_animation_controller.cc b/chromium/cc/trees/image_animation_controller.cc index eb92e3b4f5f..a7e1ebf6de6 100644 --- a/chromium/cc/trees/image_animation_controller.cc +++ b/chromium/cc/trees/image_animation_controller.cc @@ -454,7 +454,7 @@ size_t ImageAnimationController::AnimationState::NextFrameIndex() const { ImageAnimationController::InvalidationScheduler::InvalidationScheduler( base::SingleThreadTaskRunner* task_runner, Client* client) - : task_runner_(task_runner), client_(client), weak_factory_(this) { + : task_runner_(task_runner), client_(client) { DCHECK(task_runner_->BelongsToCurrentThread()); } diff --git a/chromium/cc/trees/image_animation_controller.h b/chromium/cc/trees/image_animation_controller.h index a95ec12448e..1f118704810 100644 --- a/chromium/cc/trees/image_animation_controller.h +++ b/chromium/cc/trees/image_animation_controller.h @@ -267,7 +267,7 @@ class CC_EXPORT ImageAnimationController { // The time at which the next animation is expected to run. base::TimeTicks next_animation_time_; - base::WeakPtrFactory<InvalidationScheduler> weak_factory_; + base::WeakPtrFactory<InvalidationScheduler> weak_factory_{this}; }; // The AnimationState for images is persisted until they are cleared on diff --git a/chromium/cc/trees/layer_tree_frame_sink.cc b/chromium/cc/trees/layer_tree_frame_sink.cc index 71ed2774860..34ac5b7dfa5 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.cc +++ b/chromium/cc/trees/layer_tree_frame_sink.cc @@ -48,8 +48,7 @@ LayerTreeFrameSink::LayerTreeFrameSink( : context_provider_(std::move(context_provider)), worker_context_provider_(std::move(worker_context_provider)), compositor_task_runner_(std::move(compositor_task_runner)), - gpu_memory_buffer_manager_(gpu_memory_buffer_manager), - weak_ptr_factory_(this) { + gpu_memory_buffer_manager_(gpu_memory_buffer_manager) { DETACH_FROM_THREAD(thread_checker_); } diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h index 76634a79771..68b9734737a 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.h +++ b/chromium/cc/trees/layer_tree_frame_sink.h @@ -8,6 +8,7 @@ #include <deque> #include <memory> +#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -127,7 +128,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, virtual void DidNotProduceFrame(const viz::BeginFrameAck& ack) = 0; // viz::SharedBitmapReporter implementation. - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override = 0; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override = 0; @@ -154,7 +155,7 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, private: THREAD_CHECKER(thread_checker_); - base::WeakPtrFactory<LayerTreeFrameSink> weak_ptr_factory_; + base::WeakPtrFactory<LayerTreeFrameSink> weak_ptr_factory_{this}; }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_frame_sink_client.h b/chromium/cc/trees/layer_tree_frame_sink_client.h index fc298c8fef5..50848593309 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_client.h +++ b/chromium/cc/trees/layer_tree_frame_sink_client.h @@ -68,9 +68,6 @@ class CC_EXPORT LayerTreeFrameSinkClient { // viz::ContextProviders) must be recreated. virtual void DidLoseLayerTreeFrameSink() = 0; - // Notification that the client does not need a new BeginFrame. - virtual void DidNotNeedBeginFrame() = 0; - // For SynchronousCompositor (WebView) to ask the layer compositor to submit // a new CompositorFrame synchronously. virtual void OnDraw(const gfx::Transform& transform, diff --git a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc index 58334b8322f..5eabeb0a5dc 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc @@ -4,6 +4,7 @@ #include "cc/trees/layer_tree_frame_sink.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/single_thread_task_runner.h" #include "base/test/test_simple_task_runner.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" @@ -34,7 +35,7 @@ class StubLayerTreeFrameSink : public LayerTreeFrameSink { client_->DidReceiveCompositorFrameAck(); } void DidNotProduceFrame(const viz::BeginFrameAck& ack) override {} - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region, const viz::SharedBitmapId& id) override {} void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override {} }; diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 4e9a9393289..5270f43d422 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -131,10 +131,8 @@ LayerTreeHost::LayerTreeHost(InitParams params, CompositorMode mode) debug_state_(settings_.initial_debug_state), id_(s_layer_tree_host_sequence_number.GetNext() + 1), task_graph_runner_(params.task_graph_runner), - content_source_id_(0), event_listener_properties_(), - mutator_host_(params.mutator_host), - defer_main_frame_update_weak_ptr_factory_(this) { + mutator_host_(params.mutator_host) { DCHECK(task_graph_runner_); DCHECK(!settings_.enable_checker_imaging || image_worker_task_runner_); @@ -392,7 +390,11 @@ void LayerTreeHost::FinishCommitOnImplThread( // Dump property trees and layers if run with: // --vmodule=layer_tree_host=3 if (VLOG_IS_ON(3)) { - VLOG(3) << "After finishing commit on impl, the sync tree:" + const char* client_name = GetClientNameForMetrics(); + if (!client_name) + client_name = "<unknown client>"; + VLOG(3) << "After finishing (" << client_name + << ") commit on impl, the sync tree:" << "\nproperty_trees:\n" << sync_tree->property_trees()->ToString() << "\n" << "cc::LayerImpls:\n" @@ -769,7 +771,7 @@ std::string LayerTreeHost::LayersAsString() const { return layers; } -bool LayerTreeHost::CaptureContent(std::vector<NodeHolder>* content) { +bool LayerTreeHost::CaptureContent(std::vector<NodeId>* content) { if (viewport_visible_rect_.IsEmpty()) return false; @@ -914,15 +916,9 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) { SetNeedsUpdateLayers(); } -void LayerTreeHost::RecordWheelAndTouchScrollingCount( - const ScrollAndScaleSet& info) { - bool has_scrolled_by_wheel = info.has_scrolled_by_wheel; - bool has_scrolled_by_touch = info.has_scrolled_by_touch; - - if (has_scrolled_by_wheel || has_scrolled_by_touch) { - client_->RecordWheelAndTouchScrollingCount(has_scrolled_by_wheel, - has_scrolled_by_touch); - } +void LayerTreeHost::RecordManipulationTypeCounts( + const ScrollAndScaleSet& scroll_info) { + client_->RecordManipulationTypeCounts(scroll_info.manipulation_info); } void LayerTreeHost::SendOverscrollAndScrollEndEventsFromImplSide( @@ -972,7 +968,7 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { // on the main thread. ApplyViewportChanges(*info); - RecordWheelAndTouchScrollingCount(*info); + RecordManipulationTypeCounts(*info); } void LayerTreeHost::RecordStartOfFrameMetrics() { @@ -1343,10 +1339,6 @@ void LayerTreeHost::SetExternalPageScaleFactor( SetNeedsCommit(); } -void LayerTreeHost::SetContentSourceId(uint32_t id) { - content_source_id_ = id; -} - void LayerTreeHost::ClearCachesOnNextCommit() { clear_caches_on_next_commit_ = true; } @@ -1606,8 +1598,6 @@ void LayerTreeHost::PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl) { tree_impl->SetRasterColorSpace(raster_color_space_id_, raster_color_space_); tree_impl->SetExternalPageScaleFactor(external_page_scale_factor_); - tree_impl->set_content_source_id(content_source_id_); - tree_impl->set_painted_device_scale_factor(painted_device_scale_factor_); tree_impl->SetDeviceScaleFactor(device_scale_factor_); tree_impl->SetDeviceViewportSize(device_viewport_size_); diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index b7cf9d9af7d..54000cfece0 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -33,7 +33,7 @@ #include "cc/input/scrollbar.h" #include "cc/layers/layer_collections.h" #include "cc/layers/layer_list_iterator.h" -#include "cc/paint/node_holder.h" +#include "cc/paint/node_id.h" #include "cc/trees/compositor_mode.h" #include "cc/trees/layer_tree_frame_sink.h" #include "cc/trees/layer_tree_host_client.h" @@ -432,9 +432,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { return painted_device_scale_factor_; } - void SetContentSourceId(uint32_t); - uint32_t content_source_id() const { return content_source_id_; } - // Clears image caches and resets the scheduling history for the content // produced by this host so far. void ClearCachesOnNextCommit(); @@ -678,8 +675,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { std::string LayersAsString() const; // Captures the on-screen text content, if success, fills the associated - // NodeHolder in |content| and return true, otherwise return false. - bool CaptureContent(std::vector<NodeHolder>* content); + // NodeId in |content| and return true, otherwise return false. + bool CaptureContent(std::vector<NodeId>* content); protected: LayerTreeHost(InitParams params, CompositorMode mode); @@ -722,7 +719,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { enum { kNumFramesToConsiderBeforeRemovingSlowPathFlag = 60 }; void ApplyViewportChanges(const ScrollAndScaleSet& info); - void RecordWheelAndTouchScrollingCount(const ScrollAndScaleSet& info); + void RecordManipulationTypeCounts(const ScrollAndScaleSet& scroll_info); void SendOverscrollAndScrollEndEventsFromImplSide( const ScrollAndScaleSet& info); void ApplyPageScaleDeltaFromImplSide(float page_scale_delta); @@ -807,7 +804,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { gfx::ColorSpace raster_color_space_; bool clear_caches_on_next_commit_ = false; - uint32_t content_source_id_; viz::LocalSurfaceIdAllocation local_surface_id_allocation_from_parent_; // Used to detect surface invariant violations. bool has_pushed_local_surface_id_from_parent_ = false; @@ -882,7 +878,8 @@ 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_; + base::WeakPtrFactory<LayerTreeHost> defer_main_frame_update_weak_ptr_factory_{ + this}; }; } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index 5ddc975a950..f48af6c6d1e 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -53,6 +53,14 @@ struct ApplyViewportChangesArgs { bool scroll_gesture_did_end; }; +using ManipulationInfo = uint32_t; +constexpr ManipulationInfo kManipulationInfoNone = 0; +constexpr ManipulationInfo kManipulationInfoHasScrolledByWheel = 1 << 0; +constexpr ManipulationInfo kManipulationInfoHasScrolledByTouch = 1 << 1; +constexpr ManipulationInfo kManipulationInfoHasScrolledByPrecisionTouchPad = + 1 << 2; +constexpr ManipulationInfo kManipulationInfoHasPinchZoomed = 1 << 3; + // A LayerTreeHost is bound to a LayerTreeHostClient. The main rendering // loop (in ProxyMain or SingleThreadProxy) calls methods on the // LayerTreeHost, which then handles them and also calls into the equivalent @@ -104,9 +112,9 @@ class LayerTreeHostClient { // related to pinch-zoom, browser controls (aka URL bar), overscroll, etc. virtual void ApplyViewportChanges(const ApplyViewportChangesArgs& args) = 0; - virtual void RecordWheelAndTouchScrollingCount( - bool has_scrolled_by_wheel, - bool has_scrolled_by_touch) = 0; + // Record use counts of different methods of scrolling (e.g. wheel, touch, + // precision touchpad, etc.). + virtual void RecordManipulationTypeCounts(ManipulationInfo info) = 0; // Notifies the client when an overscroll has happened. virtual void SendOverscrollEventFromImplSide( diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc index 6eb7ec07102..7ea7995ee11 100644 --- a/chromium/cc/trees/layer_tree_host_common.cc +++ b/chromium/cc/trees/layer_tree_host_common.cc @@ -81,7 +81,6 @@ LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs( const gfx::Vector2dF& elastic_overscroll, const ElementId elastic_overscroll_element_id, int max_texture_size, - bool can_adjust_raster_scales, RenderSurfaceList* render_surface_list, PropertyTrees* property_trees, TransformNode* page_scale_transform_node) @@ -96,7 +95,6 @@ LayerTreeHostCommon::CalcDrawPropsImplInputs::CalcDrawPropsImplInputs( elastic_overscroll(elastic_overscroll), elastic_overscroll_element_id(elastic_overscroll_element_id), max_texture_size(max_texture_size), - can_adjust_raster_scales(can_adjust_raster_scales), render_surface_list(render_surface_list), property_trees(property_trees), page_scale_transform_node(page_scale_transform_node) {} @@ -118,7 +116,6 @@ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting:: gfx::Vector2dF(), ElementId(), std::numeric_limits<int>::max() / 2, - false, render_surface_list, GetPropertyTrees(root_layer), nullptr) { @@ -181,9 +178,8 @@ ScrollAndScaleSet::ScrollAndScaleSet() top_controls_delta(0.f), browser_controls_constraint(BrowserControlsState::kBoth), browser_controls_constraint_changed(false), - has_scrolled_by_wheel(false), - has_scrolled_by_touch(false), - scroll_gesture_did_end(false) {} + scroll_gesture_did_end(false), + manipulation_info(kManipulationInfoNone) {} ScrollAndScaleSet::~ScrollAndScaleSet() = default; @@ -541,8 +537,7 @@ void CalculateDrawPropertiesInternal( gfx::Rect(inputs->device_viewport_size), inputs->device_transform, inputs->property_trees); draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( - inputs->root_layer, inputs->property_trees, - inputs->can_adjust_raster_scales); + inputs->root_layer, inputs->property_trees); // Property trees are normally constructed on the main thread and // passed to compositor thread. Source to parent updates on them are not @@ -609,8 +604,7 @@ void CalculateDrawPropertiesInternal( inputs->device_scale_factor, page_scale_factor_for_root, inputs->device_transform); draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( - inputs->root_layer, inputs->property_trees, - inputs->can_adjust_raster_scales); + inputs->root_layer, inputs->property_trees); break; } } diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h index c27157a9939..07c0bc586c2 100644 --- a/chromium/cc/trees/layer_tree_host_common.h +++ b/chromium/cc/trees/layer_tree_host_common.h @@ -74,7 +74,6 @@ class CC_EXPORT LayerTreeHostCommon { const gfx::Vector2dF& elastic_overscroll, const ElementId elastic_overscroll_element_id, int max_texture_size, - bool can_adjust_raster_scales, RenderSurfaceList* render_surface_list, PropertyTrees* property_trees, TransformNode* page_scale_transform_node); @@ -90,7 +89,6 @@ class CC_EXPORT LayerTreeHostCommon { gfx::Vector2dF elastic_overscroll; const ElementId elastic_overscroll_element_id; int max_texture_size; - bool can_adjust_raster_scales; RenderSurfaceList* render_surface_list; PropertyTrees* property_trees; TransformNode* page_scale_transform_node; @@ -189,12 +187,14 @@ struct CC_EXPORT ScrollAndScaleSet { std::vector<std::unique_ptr<SwapPromise>> swap_promises; BrowserControlsState browser_controls_constraint; bool browser_controls_constraint_changed; - bool has_scrolled_by_wheel; - bool has_scrolled_by_touch; // Set to true when a scroll gesture being handled on the compositor has // ended. bool scroll_gesture_did_end; + + // Tracks different methods of scrolling (e.g. wheel, touch, precision + // touchpad, etc.). + ManipulationInfo manipulation_info; }; template <typename Function> diff --git a/chromium/cc/trees/layer_tree_host_common_perftest.cc b/chromium/cc/trees/layer_tree_host_common_perftest.cc index 2c1c4ab1d82..4cb8bc9e760 100644 --- a/chromium/cc/trees/layer_tree_host_common_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_common_perftest.cc @@ -107,7 +107,6 @@ class CalcDrawPropsTest : public LayerTreeHostCommonPerfTest { active_tree->OuterViewportScrollLayer(), active_tree->elastic_overscroll()->Current(active_tree->IsActiveTree()), active_tree->OverscrollElasticityElementId(), max_texture_size, - host_impl->settings().layer_transforms_should_scale_layer_contents, &update_list, active_tree->property_trees(), active_tree->property_trees()->transform_tree.Node( active_tree->InnerViewportContainerLayer() diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc index 93750755adb..12652e57e9f 100644 --- a/chromium/cc/trees/layer_tree_host_common_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc @@ -168,7 +168,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { inputs.page_scale_layer = page_scale_layer; inputs.inner_viewport_scroll_layer = inner_viewport_scroll_layer; inputs.outer_viewport_scroll_layer = outer_viewport_scroll_layer; - inputs.can_adjust_raster_scales = true; if (page_scale_layer) { PropertyTrees* property_trees = root_layer->layer_tree_impl()->property_trees(); @@ -236,7 +235,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { void ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList( LayerImpl* root_layer) { DCHECK(root_layer->layer_tree_impl()); - bool can_adjust_raster_scales = true; const LayerImpl* page_scale_layer = nullptr; LayerImpl* inner_viewport_scroll_layer = @@ -262,8 +260,8 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { outer_viewport_scroll_layer, overscroll_elasticity_element_id, elastic_overscroll, page_scale_factor, device_scale_factor, gfx::Rect(device_viewport_size), gfx::Transform(), property_trees); - draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( - root_layer, property_trees, can_adjust_raster_scales); + draw_property_utils::UpdatePropertyTreesAndRenderSurfaces(root_layer, + property_trees); draw_property_utils::FindLayersThatNeedUpdates( root_layer->layer_tree_impl(), property_trees, update_layer_impl_list_.get()); @@ -280,7 +278,6 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { DCHECK(!root_layer->bounds().IsEmpty()); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, device_viewport_size, render_surface_list_impl_.get()); - inputs.can_adjust_raster_scales = false; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -311,7 +308,7 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { bool VerifyLayerInList(scoped_refptr<Layer> layer, const LayerList* layer_list) { - return base::ContainsValue(*layer_list, layer); + return base::Contains(*layer_list, layer); } private: @@ -323,18 +320,11 @@ class LayerTreeHostCommonTestBase : public LayerTestCommon::LayerImplTest { class LayerTreeHostCommonTest : public LayerTreeHostCommonTestBase, public testing::Test {}; -class LayerTreeSettingsScaleContent : public VerifyTreeCalcsLayerTreeSettings { - public: - LayerTreeSettingsScaleContent() { - layer_transforms_should_scale_layer_contents = true; - } -}; - class LayerTreeHostCommonScalingTest : public LayerTreeHostCommonTestBase, public testing::Test { public: LayerTreeHostCommonScalingTest() - : LayerTreeHostCommonTestBase(LayerTreeSettingsScaleContent()) {} + : LayerTreeHostCommonTestBase(VerifyTreeCalcsLayerTreeSettings()) {} }; class LayerTreeHostCommonDrawRectsTest : public LayerTreeHostCommonTest { @@ -1401,7 +1391,6 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTransparentChild) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); // Since the layer is transparent, render_surface1->GetRenderSurface() should @@ -1437,7 +1426,6 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); EXPECT_EQ(2U, render_surface_list.size()); } @@ -1461,7 +1449,6 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -1496,7 +1483,6 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForFilter) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); ASSERT_TRUE(GetRenderSurface(parent)); @@ -4436,7 +4422,6 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); // We should have one render surface and two layers. The child @@ -4451,7 +4436,6 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { RenderSurfaceList render_surface_list2; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs2( root_layer, root_layer->bounds(), &render_surface_list2); - inputs2.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs2); LayerImpl* child_ptr = root_layer->layer_tree_impl()->LayerById(2); @@ -4468,7 +4452,6 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) { RenderSurfaceList render_surface_list3; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs3( root_layer, root_layer->bounds(), &render_surface_list3); - inputs3.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs3); child_ptr = root_layer->layer_tree_impl()->LayerById(2); @@ -4754,7 +4737,6 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_SingleLayerImpl) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); // We should have one render surface and two layers. The grand child has @@ -4798,7 +4780,6 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHidden_TwoLayersImpl) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); // We should have one render surface and one layer. The child has @@ -4894,7 +4875,6 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); auto& effect_tree = @@ -5002,7 +4982,6 @@ TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) { root_layer->layer_tree_impl()->SetRootLayerForTesting(std::move(root)); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); // We should have two render surface, as the others are clipped out. @@ -6442,7 +6421,7 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionSubpixelScroll) { sticky_position.is_sticky = true; sticky_position.is_anchored_bottom = true; sticky_position.bottom_offset = 10.0f; - sticky_position.constraint_box_rect = gfx::RectF(0, 0, 100, 100); + sticky_position.constraint_box_rect = gfx::Rect(0, 0, 100, 100); sticky_position.scroll_container_relative_sticky_box_rect = gfx::Rect(0, 200, 10, 10); sticky_position.scroll_container_relative_containing_block_rect = @@ -6489,7 +6468,7 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionBottom) { sticky_position.is_sticky = true; sticky_position.is_anchored_bottom = true; sticky_position.bottom_offset = 10.0f; - sticky_position.constraint_box_rect = gfx::RectF(0, 0, 100, 100); + sticky_position.constraint_box_rect = gfx::Rect(0, 0, 100, 100); sticky_position.scroll_container_relative_sticky_box_rect = gfx::Rect(0, 150, 10, 10); sticky_position.scroll_container_relative_containing_block_rect = @@ -6571,7 +6550,7 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionBottomOuterViewportDelta) { sticky_position.is_sticky = true; sticky_position.is_anchored_bottom = true; sticky_position.bottom_offset = 10.0f; - sticky_position.constraint_box_rect = gfx::RectF(0, 0, 100, 100); + sticky_position.constraint_box_rect = gfx::Rect(0, 0, 100, 100); sticky_position.scroll_container_relative_sticky_box_rect = gfx::Rect(0, 70, 10, 10); sticky_position.scroll_container_relative_containing_block_rect = @@ -6650,7 +6629,7 @@ TEST_F(LayerTreeHostCommonTest, StickyPositionLeftRight) { sticky_position.is_anchored_right = true; sticky_position.left_offset = 10.f; sticky_position.right_offset = 10.f; - sticky_position.constraint_box_rect = gfx::RectF(0, 0, 100, 100); + sticky_position.constraint_box_rect = gfx::Rect(0, 0, 100, 100); sticky_position.scroll_container_relative_sticky_box_rect = gfx::Rect(145, 0, 10, 10); sticky_position.scroll_container_relative_containing_block_rect = @@ -7303,7 +7282,6 @@ TEST_F(LayerTreeHostCommonTest, MaximumAnimationScaleFactor) { FakeImplTaskRunnerProvider task_runner_provider; TestTaskGraphRunner task_graph_runner; LayerTreeSettings settings = host()->GetSettings(); - settings.layer_transforms_should_scale_layer_contents = true; FakeLayerTreeHostImpl host_impl(settings, &task_runner_provider, &task_graph_runner); std::unique_ptr<AnimationScaleFactorTrackingLayerImpl> grand_parent = @@ -7790,7 +7768,6 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { FakeImplTaskRunnerProvider task_runner_provider; TestTaskGraphRunner task_graph_runner; LayerTreeSettings settings = host()->GetSettings(); - settings.layer_transforms_should_scale_layer_contents = true; FakeLayerTreeHostImpl host_impl(settings, &task_runner_provider, &task_graph_runner); @@ -7864,7 +7841,6 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { root_layer, device_viewport_size, &render_surface_list); inputs.page_scale_factor = page_scale_factor; - inputs.can_adjust_raster_scales = true; inputs.page_scale_layer = root_layer; inputs.page_scale_transform_node = inputs.property_trees->transform_tree.Node( inputs.page_scale_layer->transform_tree_index()); @@ -7886,7 +7862,6 @@ TEST_F(LayerTreeHostCommonTest, DrawPropertyScales) { device_scale_factor = 4.0f; inputs.device_scale_factor = device_scale_factor; - inputs.can_adjust_raster_scales = true; root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); @@ -7906,7 +7881,6 @@ TEST_F(LayerTreeHostCommonTest, AnimationScales) { FakeImplTaskRunnerProvider task_runner_provider; TestTaskGraphRunner task_graph_runner; LayerTreeSettings settings = host()->GetSettings(); - settings.layer_transforms_should_scale_layer_contents = true; FakeLayerTreeHostImpl host_impl(settings, &task_runner_provider, &task_graph_runner); @@ -7974,56 +7948,6 @@ TEST_F(LayerTreeHostCommonTest, AnimationScales) { EXPECT_FLOAT_EQ(100.f, GetStartingAnimationScale(child2_layer)); } -TEST_F(LayerTreeHostCommonTest, - AnimationScaleWhenLayerTransformShouldNotScaleLayerBounds) { - // Returns empty scale if layer_transforms_should_scale_layer_contents is - // false. - FakeImplTaskRunnerProvider task_runner_provider; - TestTaskGraphRunner task_graph_runner; - LayerTreeSettings settings = host()->GetSettings(); - settings.layer_transforms_should_scale_layer_contents = false; - FakeLayerTreeHostImpl host_impl(settings, &task_runner_provider, - &task_graph_runner); - - std::unique_ptr<LayerImpl> root = - LayerImpl::Create(host_impl.active_tree(), 1); - LayerImpl* root_layer = root.get(); - std::unique_ptr<LayerImpl> child = - LayerImpl::Create(host_impl.active_tree(), 2); - LayerImpl* child_layer = child.get(); - - root->test_properties()->AddChild(std::move(child)); - host_impl.active_tree()->SetRootLayerForTesting(std::move(root)); - - host_impl.active_tree()->SetElementIdsForTesting(); - - gfx::Transform scale_transform_child; - scale_transform_child.Scale(4, 5); - - root_layer->SetBounds(gfx::Size(1, 1)); - child_layer->test_properties()->transform = scale_transform_child; - child_layer->SetBounds(gfx::Size(1, 1)); - - TransformOperations scale; - scale.AppendScale(5.f, 8.f, 3.f); - - scoped_refptr<AnimationTimeline> timeline = - AnimationTimeline::Create(AnimationIdProvider::NextTimelineId()); - host_impl.animation_host()->AddAnimationTimeline(timeline); - - AddAnimatedTransformToElementWithAnimation( - child_layer->element_id(), timeline, 1.0, TransformOperations(), scale); - - root_layer->layer_tree_impl()->property_trees()->needs_rebuild = true; - ExecuteCalculateDrawProperties(root_layer); - - EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(kNotScaled, GetMaximumAnimationScale(child_layer)); - - EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(root_layer)); - EXPECT_FLOAT_EQ(kNotScaled, GetStartingAnimationScale(child_layer)); -} - TEST_F(LayerTreeHostCommonTest, VisibleContentRectInChildRenderSurface) { LayerImpl* root = root_layer_for_testing(); LayerImpl* clip = AddChild<LayerImpl>(root); @@ -9789,7 +9713,7 @@ TEST_F(LayerTreeHostCommonTest, LargeTransformTest) { // The root layer should be in the RenderSurfaceList. const auto* rsl = render_surface_list_impl(); - EXPECT_TRUE(base::ContainsValue(*rsl, GetRenderSurface(root))); + EXPECT_TRUE(base::Contains(*rsl, GetRenderSurface(root))); } TEST_F(LayerTreeHostCommonTest, PropertyTreesRebuildWithOpacityChanges) { @@ -10143,40 +10067,7 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { EXPECT_EQ(scroll_root1.id, grand_child12->scroll_tree_index()); } -TEST_F(LayerTreeHostCommonTest, CanAdjustRasterScaleTest) { - LayerImpl* root = root_layer_for_testing(); - LayerImpl* render_surface = AddChild<LayerImpl>(root); - LayerImpl* child = AddChild<LayerImpl>(render_surface); - - root->SetBounds(gfx::Size(50, 50)); - - render_surface->SetBounds(gfx::Size(10, 10)); - render_surface->test_properties()->force_render_surface = true; - gfx::Transform transform; - transform.Scale(5.f, 5.f); - render_surface->test_properties()->transform = transform; - - child->SetDrawsContent(true); - child->SetMasksToBounds(true); - child->SetBounds(gfx::Size(10, 10)); - - ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales(root); - - // Check surface draw properties. - EXPECT_EQ(gfx::Rect(10, 10), - GetRenderSurface(render_surface)->content_rect()); - EXPECT_EQ(transform, GetRenderSurface(render_surface)->draw_transform()); - EXPECT_EQ(gfx::RectF(50.0f, 50.0f), - GetRenderSurface(render_surface)->DrawableContentRect()); - - // Check child layer draw properties. - EXPECT_EQ(gfx::Rect(10, 10), child->visible_layer_rect()); - EXPECT_EQ(gfx::Transform(), child->DrawTransform()); - EXPECT_EQ(gfx::Rect(10, 10), child->clip_rect()); - EXPECT_EQ(gfx::Rect(10, 10), child->drawable_content_rect()); -} - -TEST_F(LayerTreeHostCommonTest, SurfaceContentsScaleChangeWithCopyRequestTest) { +TEST_F(LayerTreeHostCommonTest, CopyRequestScalingTest) { LayerImpl* root = root_layer_for_testing(); LayerImpl* scale_layer = AddChild<LayerImpl>(root); LayerImpl* copy_layer = AddChild<LayerImpl>(scale_layer); @@ -10203,7 +10094,7 @@ TEST_F(LayerTreeHostCommonTest, SurfaceContentsScaleChangeWithCopyRequestTest) { test_layer->SetMasksToBounds(true); test_layer->SetBounds(gfx::Size(20, 20)); - ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales(root); + ExecuteCalculateDrawProperties(root); // Check surface with copy request draw properties. EXPECT_EQ(gfx::Rect(50, 50), GetRenderSurface(copy_layer)->content_rect()); @@ -10219,19 +10110,7 @@ TEST_F(LayerTreeHostCommonTest, SurfaceContentsScaleChangeWithCopyRequestTest) { // Clear the copy request and call UpdateSurfaceContentsScale. host_impl()->active_tree()->property_trees()->effect_tree.ClearCopyRequests(); - ExecuteCalculateDrawPropertiesWithoutAdjustingRasterScales(root); - - // Check surface draw properties without copy request. - EXPECT_EQ(gfx::Rect(10, 10), GetRenderSurface(copy_layer)->content_rect()); - EXPECT_EQ(transform, GetRenderSurface(copy_layer)->draw_transform()); - EXPECT_EQ(gfx::RectF(50.0f, 50.0f), - GetRenderSurface(copy_layer)->DrawableContentRect()); - - // Check test layer draw properties without copy request. - EXPECT_EQ(gfx::Rect(10, 10), test_layer->visible_layer_rect()); - EXPECT_EQ(gfx::Transform(), test_layer->DrawTransform()); - EXPECT_EQ(gfx::Rect(10, 10), test_layer->clip_rect()); - EXPECT_EQ(gfx::Rect(10, 10), test_layer->drawable_content_rect()); + ExecuteCalculateDrawProperties(root); } TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCacheRenderSurface) { @@ -10316,7 +10195,6 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCacheRenderSurface) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); // We should have four render surfaces, one for the root, one for the grand @@ -10541,7 +10419,6 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTrilinearFiltering) { RenderSurfaceList render_surface_list; LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_list); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); ASSERT_TRUE(GetRenderSurface(parent)); @@ -11677,5 +11554,229 @@ TEST_F(LayerTreeHostCommonTest, kRoundedCorner4Radius * kDeviceScale); } +TEST_F(LayerTreeHostCommonTest, CustomLayerClipBounds) { + // The custom clip API should have the same effect as if an intermediate + // clip layer has been added to the layer tree. To check this the test creates + // 2 subtree for a root layer. One of the subtree uses the clip API to clip + // its subtree while the other uses an intermediate layer. The resulting clip + // in draw properties are expected to be the same. + // -Root + // - Parent [Clip set to |kClipBounds| using API] + // - Child + // - Clip Layer [Masks to bounds = true] [Layer bounds set to |kClipBounds|] + // - Expected Parent + // - Expected Child + constexpr float kDeviceScale = 1.f; + + const gfx::Rect kRootLayerBounds(0, 0, 100, 100); + const gfx::Rect kParentLayerBounds(0, 0, 50, 100); + const gfx::Rect kChildLayerBounds(20, 20, 30, 60); + + constexpr gfx::Rect kClipBounds(10, 10, 50, 50); + + // The position of |Expected Parent| on screen should be same as |Parent|. + const gfx::Rect kExpectedParentLayerBounds( + gfx::Point(0, 0) - kClipBounds.OffsetFromOrigin(), gfx::Size(50, 100)); + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(); + + scoped_refptr<Layer> clip_layer = Layer::Create(); + scoped_refptr<Layer> expected_parent = Layer::Create(); + scoped_refptr<Layer> expected_child = Layer::Create(); + + root->AddChild(parent); + parent->AddChild(child); + + root->AddChild(clip_layer); + clip_layer->AddChild(expected_parent); + expected_parent->AddChild(expected_child); + + host()->SetRootLayer(root); + + root->SetIsDrawable(true); + parent->SetIsDrawable(true); + child->SetIsDrawable(true); + expected_parent->SetIsDrawable(true); + expected_child->SetIsDrawable(true); + + // Set layer positions. + root->SetPosition(gfx::PointF(kRootLayerBounds.origin())); + parent->SetPosition(gfx::PointF(kParentLayerBounds.origin())); + child->SetPosition(gfx::PointF(kChildLayerBounds.origin())); + + clip_layer->SetPosition(gfx::PointF(kClipBounds.origin())); + expected_parent->SetPosition( + gfx::PointF(kExpectedParentLayerBounds.origin())); + expected_child->SetPosition(gfx::PointF(kChildLayerBounds.origin())); + + root->SetBounds(kRootLayerBounds.size()); + parent->SetBounds(kParentLayerBounds.size()); + child->SetBounds(kChildLayerBounds.size()); + + clip_layer->SetBounds(kClipBounds.size()); + expected_parent->SetBounds(kExpectedParentLayerBounds.size()); + expected_child->SetBounds(kChildLayerBounds.size()); + + parent->SetClipRect(kClipBounds); + clip_layer->SetMasksToBounds(true); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const ClipTree& clip_tree = + root->layer_tree_host()->property_trees()->clip_tree; + + const ClipNode* parent_clip_node = clip_tree.Node(parent->clip_tree_index()); + EXPECT_EQ(parent_clip_node->clip, gfx::RectF(kClipBounds)); + EXPECT_TRUE(!parent->clip_rect().IsEmpty()); + + const ClipNode* child_clip_node = clip_tree.Node(child->clip_tree_index()); + EXPECT_EQ(child_clip_node->clip, gfx::RectF(kClipBounds)); + + 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* parent_impl = layer_tree_impl->LayerById(parent->id()); + LayerImpl* child_impl = layer_tree_impl->LayerById(child->id()); + LayerImpl* expected_parent_impl = + layer_tree_impl->LayerById(expected_parent->id()); + LayerImpl* expected_child_impl = + layer_tree_impl->LayerById(expected_child->id()); + + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + EXPECT_TRUE(parent_impl->is_clipped()); + EXPECT_TRUE(child_impl->is_clipped()); + ASSERT_TRUE(expected_parent_impl->is_clipped()); + ASSERT_TRUE(expected_child_impl->is_clipped()); + + EXPECT_EQ(parent_impl->clip_rect(), expected_parent_impl->clip_rect()); + EXPECT_EQ(child_impl->clip_rect(), expected_child_impl->clip_rect()); +} + +TEST_F(LayerTreeHostCommonTest, CustomLayerClipBoundsWithMaskToBounds) { + // The custom clip API should have the same effect as if an intermediate + // clip layer has been added to the layer tree. To check this the test creates + // 2 subtree for a root layer. One of the subtree uses the clip API to clip + // its subtree while the other uses an intermediate layer. The resulting clip + // in draw properties are expected to be the same. In this test, the subtree + // roots also have their masks to bounds property set. + // -Root + // - Parent [Clip set to |kClipBounds| using API] + // - Child + // - Clip Layer [Masks to bounds = true] [Layer bounds set to |kClipBounds|] + // - Expected Parent [Masks to bounds = true] + // - Expected Child + constexpr float kDeviceScale = 1.f; + + const gfx::Rect kRootLayerBounds(0, 0, 100, 100); + const gfx::Rect kParentLayerBounds(0, 0, 50, 100); + const gfx::Rect kChildLayerBounds(20, 20, 30, 60); + + constexpr gfx::Rect kClipBounds(10, 10, 50, 50); + + // The position of |Expected Parent| on screen should be same as |Parent|. + const gfx::Rect kExpectedParentLayerBounds( + gfx::Point(0, 0) - kClipBounds.OffsetFromOrigin(), gfx::Size(50, 100)); + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<Layer> child = Layer::Create(); + + scoped_refptr<Layer> clip_layer = Layer::Create(); + scoped_refptr<Layer> expected_parent = Layer::Create(); + scoped_refptr<Layer> expected_child = Layer::Create(); + + root->AddChild(parent); + parent->AddChild(child); + + root->AddChild(clip_layer); + clip_layer->AddChild(expected_parent); + expected_parent->AddChild(expected_child); + + host()->SetRootLayer(root); + + root->SetIsDrawable(true); + parent->SetIsDrawable(true); + child->SetIsDrawable(true); + expected_parent->SetIsDrawable(true); + expected_child->SetIsDrawable(true); + + // Set layer positions. + root->SetPosition(gfx::PointF(kRootLayerBounds.origin())); + parent->SetPosition(gfx::PointF(kParentLayerBounds.origin())); + child->SetPosition(gfx::PointF(kChildLayerBounds.origin())); + + clip_layer->SetPosition(gfx::PointF(kClipBounds.origin())); + expected_parent->SetPosition( + gfx::PointF(kExpectedParentLayerBounds.origin())); + expected_child->SetPosition(gfx::PointF(kChildLayerBounds.origin())); + + root->SetBounds(kRootLayerBounds.size()); + parent->SetBounds(kParentLayerBounds.size()); + child->SetBounds(kChildLayerBounds.size()); + + clip_layer->SetBounds(kClipBounds.size()); + expected_parent->SetBounds(kExpectedParentLayerBounds.size()); + expected_child->SetBounds(kChildLayerBounds.size()); + + parent->SetClipRect(kClipBounds); + parent->SetMasksToBounds(true); + + clip_layer->SetMasksToBounds(true); + expected_parent->SetMasksToBounds(true); + + ExecuteCalculateDrawProperties(root.get(), kDeviceScale); + + const ClipTree& clip_tree = + root->layer_tree_host()->property_trees()->clip_tree; + + const ClipNode* parent_clip_node = clip_tree.Node(parent->clip_tree_index()); + const gfx::RectF expected_clip_bounds = gfx::IntersectRects( + gfx::RectF(kClipBounds), gfx::RectF(kParentLayerBounds)); + EXPECT_EQ(parent_clip_node->clip, expected_clip_bounds); + EXPECT_TRUE(!parent->clip_rect().IsEmpty()); + + const ClipNode* child_clip_node = clip_tree.Node(child->clip_tree_index()); + EXPECT_EQ(child_clip_node->clip, expected_clip_bounds); + + 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* parent_impl = layer_tree_impl->LayerById(parent->id()); + LayerImpl* child_impl = layer_tree_impl->LayerById(child->id()); + LayerImpl* expected_parent_impl = + layer_tree_impl->LayerById(expected_parent->id()); + LayerImpl* expected_child_impl = + layer_tree_impl->LayerById(expected_child->id()); + + ExecuteCalculateDrawProperties(root_impl, kDeviceScale); + + EXPECT_TRUE(parent_impl->is_clipped()); + EXPECT_TRUE(child_impl->is_clipped()); + ASSERT_TRUE(expected_parent_impl->is_clipped()); + ASSERT_TRUE(expected_child_impl->is_clipped()); + + EXPECT_EQ(parent_impl->clip_rect(), expected_parent_impl->clip_rect()); + EXPECT_EQ(child_impl->clip_rect(), expected_child_impl->clip_rect()); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index e2921219d25..0585a41551c 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -38,6 +38,7 @@ #include "cc/input/page_scale_animation.h" #include "cc/input/scroll_elasticity_helper.h" #include "cc/input/scroll_state.h" +#include "cc/input/scrollbar.h" #include "cc/input/scrollbar_animation_controller.h" #include "cc/input/scroller_size_metrics.h" #include "cc/input/snap_selection_strategy.h" @@ -323,7 +324,8 @@ LayerTreeHostImpl::LayerTreeHostImpl( task_runner_provider_(task_runner_provider), current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), compositor_frame_reporting_controller_( - std::make_unique<CompositorFrameReportingController>()), + std::make_unique<CompositorFrameReportingController>( + settings.single_thread_proxy_scheduler)), settings_(settings), is_synchronous_single_threaded_(!task_runner_provider->HasImplThread() && !settings_.single_thread_proxy_scheduler), @@ -358,8 +360,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( is_animating_for_snap_(false), paint_image_generator_client_id_(PaintImage::GetNextGeneratorClientId()), scrollbar_controller_(std::make_unique<ScrollbarController>(this)), - scroll_gesture_did_end_(false), - weak_factory_(this) { + scroll_gesture_did_end_(false) { DCHECK(mutator_host_); mutator_host_->SetMutatorHostClient(this); @@ -427,9 +428,21 @@ LayerTreeHostImpl::~LayerTreeHostImpl() { mutator_host_->SetMutatorHostClient(nullptr); } +void LayerTreeHostImpl::DidSendBeginMainFrame(const viz::BeginFrameArgs& args) { + if (impl_thread_phase_ == ImplThreadPhase::INSIDE_IMPL_FRAME) + begin_main_frame_sent_during_impl_ = true; + frame_trackers_.NotifyBeginMainFrame(args); +} + void LayerTreeHostImpl::BeginMainFrameAborted( CommitEarlyOutReason reason, - std::vector<std::unique_ptr<SwapPromise>> swap_promises) { + std::vector<std::unique_ptr<SwapPromise>> swap_promises, + const viz::BeginFrameArgs& args) { + if (reason == CommitEarlyOutReason::ABORTED_NOT_VISIBLE || + reason == CommitEarlyOutReason::FINISHED_NO_UPDATES) { + frame_trackers_.NotifyMainFrameCausedNoDamage(args); + } + // If the begin frame data was handled, then scroll and scale set was applied // by the main thread, so the active tree needs to be updated as if these sent // values were applied and committed. @@ -457,7 +470,7 @@ void LayerTreeHostImpl::CommitComplete() { // In high latency mode commit cannot finish within the same frame. We need to // flush input here to make sure they got picked up by |PrepareTiles()|. if (input_handler_client_ && impl_thread_phase_ == ImplThreadPhase::IDLE) - input_handler_client_->DeliverInputForBeginFrame(); + input_handler_client_->DeliverInputForHighLatencyMode(); if (CommitToActiveTree()) { active_tree_->HandleScrollbarShowRequestsFromMain(); @@ -483,6 +496,18 @@ void LayerTreeHostImpl::CommitComplete() { UpdateSyncTreeAfterCommitOrImplSideInvalidation(); micro_benchmark_controller_.DidCompleteCommit(); + + if (mutator_host_->CurrentFrameHadRAF() && + !request_animation_frame_tracker_) { + request_animation_frame_tracker_ = + frame_trackers_.CreateTracker(FrameSequenceTrackerType::kRAF); + } + + if (mutator_host_->MainThreadAnimationsCount() > 0 && + !main_thread_animation_frame_tracker_) { + main_thread_animation_frame_tracker_ = frame_trackers_.CreateTracker( + FrameSequenceTrackerType::kMainThreadAnimation); + } } void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() { @@ -529,6 +554,97 @@ void LayerTreeHostImpl::UpdateSyncTreeAfterCommitOrImplSideInvalidation() { if (CommitToActiveTree()) ActivateStateForImages(); + if (!paint_worklet_painter_) { + // Blink should not send us any PaintWorklet inputs until we have a painter + // registered. + DCHECK(sync_tree()->picture_layers_with_paint_worklets().empty()); + pending_tree_fully_painted_ = true; + NotifyPendingTreeFullyPainted(); + return; + } + + PaintWorkletJobMap dirty_paint_worklets = GatherDirtyPaintWorklets(); + if (!dirty_paint_worklets.size()) { + pending_tree_fully_painted_ = true; + NotifyPendingTreeFullyPainted(); + return; + } + + client_->NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState::PROCESSING); + auto done_callback = base::BindOnce( + &LayerTreeHostImpl::OnPaintWorkletResultsReady, base::Unretained(this)); + paint_worklet_painter_->DispatchWorklets(std::move(dirty_paint_worklets), + std::move(done_callback)); +} + +PaintWorkletJobMap LayerTreeHostImpl::GatherDirtyPaintWorklets() const { + PaintWorkletJobMap dirty_paint_worklets; + for (PictureLayerImpl* layer : + sync_tree()->picture_layers_with_paint_worklets()) { + for (const auto& entry : layer->GetPaintWorkletRecordMap()) { + // If we already have a record we can reuse it and so the + // PaintWorkletInput isn't dirty. + if (entry.second) + continue; + + int id = entry.first->WorkletId(); + auto result = dirty_paint_worklets.insert( + std::make_pair(id, scoped_refptr<PaintWorkletJobVector>{})); + scoped_refptr<PaintWorkletJobVector>& job_vector = result.first->second; + if (!job_vector) + job_vector = base::WrapRefCounted(new PaintWorkletJobVector); + job_vector->data.emplace_back(layer->id(), entry.first); + } + } + return dirty_paint_worklets; +} + +void LayerTreeHostImpl::OnPaintWorkletResultsReady(PaintWorkletJobMap results) { + // Nothing else should have painted the PaintWorklets while we were waiting, + // and the results should have painted every PaintWorklet, so these should be + // the same. + DCHECK_EQ(results.size(), GatherDirtyPaintWorklets().size()); + + for (const auto& entry : results) { + for (const PaintWorkletJob& job : entry.second->data) { + LayerImpl* layer_impl = + pending_tree_->FindPendingTreeLayerById(job.layer_id()); + // Painting the pending tree occurs asynchronously but stalls the pending + // tree pipeline, so nothing should have changed while we were doing that. + DCHECK(layer_impl); + static_cast<PictureLayerImpl*>(layer_impl) + ->SetPaintWorkletRecord(job.input(), job.output()); + } + } + + // While the pending tree is being painted by PaintWorklets, we restrict the + // tiles the TileManager is able to see. This may cause the TileManager to + // believe that it has finished rastering all the necessary tiles. When we + // finish painting the tree and release all the tiles, we need to mark the + // tile priorities as dirty so that the TileManager logic properly re-runs. + tile_priorities_dirty_ = true; + + // Set the painted state before calling the scheduler, to ensure any callback + // running as a result sees the correct painted state. + pending_tree_fully_painted_ = true; + client_->NotifyPaintWorkletStateChange(Scheduler::PaintWorkletState::IDLE); + + // The pending tree may have been force activated from the signal to the + // scheduler above, in which case there is no longer a tree to paint. + if (pending_tree_) + NotifyPendingTreeFullyPainted(); +} + +void LayerTreeHostImpl::NotifyPendingTreeFullyPainted() { + // The pending tree must be fully painted at this point. + DCHECK(pending_tree_fully_painted_); + + // Nobody should claim the pending tree is fully painted if there is an + // ongoing dispatch. + DCHECK(!paint_worklet_painter_ || + !paint_worklet_painter_->HasOngoingDispatch()); + // Start working on newly created tiles immediately if needed. // TODO(vmpstr): Investigate always having PrepareTiles issue // NotifyReadyToActivate, instead of handling it here. @@ -714,8 +830,7 @@ bool LayerTreeHostImpl::IsCurrentlyScrollingViewport() const { } bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt( - const gfx::Point& viewport_point, - InputHandler::ScrollInputType type) const { + const gfx::Point& viewport_point) const { auto* scrolling_node = CurrentlyScrollingNode(); if (!scrolling_node) return false; @@ -729,7 +844,7 @@ bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt( bool scroll_on_main_thread = false; uint32_t main_thread_scrolling_reasons; auto* test_scroll_node = FindScrollNodeForDeviceViewportPoint( - device_viewport_point, type, layer_impl, &scroll_on_main_thread, + device_viewport_point, layer_impl, &scroll_on_main_thread, &main_thread_scrolling_reasons); if (scroll_on_main_thread) @@ -1183,6 +1298,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { } frame->use_default_lower_bound_deadline |= append_quads_data.use_default_lower_bound_deadline; + frame->mirror_rect.Union(append_quads_data.mirror_rect); } // If CommitToActiveTree() is true, then we wait to draw until @@ -1338,10 +1454,19 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { if (client_name) { size_t total_memory_in_bytes = 0; size_t total_gpu_memory_for_tilings_in_bytes = 0; + int layers_with_text_count = 0; + int layers_with_text_no_lcd_text_count = 0; for (const PictureLayerImpl* layer : active_tree()->picture_layers()) { total_memory_in_bytes += layer->GetRasterSource()->GetMemoryUsage(); total_gpu_memory_for_tilings_in_bytes += layer->GPUMemoryUsageInBytes(); + if (layer->GetRasterSource()->HasText()) { + layers_with_text_count++; + if (!layer->can_use_lcd_text()) { + layers_with_text_no_lcd_text_count++; + } + } } + if (total_memory_in_bytes != 0) { UMA_HISTOGRAM_COUNTS_1M( base::StringPrintf("Compositing.%s.PictureMemoryUsageKb", @@ -1359,6 +1484,34 @@ DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) { base::saturated_cast<int>(active_tree_->picture_layers().size()), 1, 400, 20); + if (layers_with_text_count > 0) { + int percent = + 100.0 * layers_with_text_no_lcd_text_count / layers_with_text_count; + + if (layers_with_text_count < 10) { + UMA_HISTOGRAM_PERCENTAGE( + base::StringPrintf( + "Compositing.%s.PercentPictureLayersWithTextButLCDTextDisabled." + "LessThan10", + client_name), + percent); + } else if (layers_with_text_count <= 30) { + UMA_HISTOGRAM_PERCENTAGE( + base::StringPrintf( + "Compositing.%s.PercentPictureLayersWithTextButLCDTextDisabled." + "10To30", + client_name), + percent); + } else { + UMA_HISTOGRAM_PERCENTAGE( + base::StringPrintf( + "Compositing.%s." + "PercentPictureLayersWithTextButLCDTextDisabled.MoreThan30", + client_name), + percent); + } + } + // TODO(yigu): Maybe we should use the same check above. Need to figure out // why exactly we skip 0. if (!active_tree()->picture_layers().empty()) { @@ -1588,11 +1741,12 @@ std::unique_ptr<RasterTilePriorityQueue> LayerTreeHostImpl::BuildRasterQueue( TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "LayerTreeHostImpl::BuildRasterQueue"); - return RasterTilePriorityQueue::Create(active_tree_->picture_layers(), - pending_tree_ - ? pending_tree_->picture_layers() - : std::vector<PictureLayerImpl*>(), - tree_priority, type); + return RasterTilePriorityQueue::Create( + active_tree_->picture_layers(), + pending_tree_ && pending_tree_fully_painted_ + ? pending_tree_->picture_layers() + : std::vector<PictureLayerImpl*>(), + tree_priority, type); } std::unique_ptr<EvictionTilePriorityQueue> @@ -1666,6 +1820,13 @@ size_t LayerTreeHostImpl::GetFrameIndexForImage(const PaintImage& paint_image, } void LayerTreeHostImpl::NotifyReadyToActivate() { + // The TileManager may call this method while the pending tree is still being + // painted, as it isn't aware of the ongoing paint. We shouldn't tell the + // scheduler we are ready to activate in that case, as if we do it will + // immediately activate once we call NotifyPaintWorkletStateChange, rather + // than wait for the TileManager to actually raster the content! + if (!pending_tree_fully_painted_) + return; pending_tree_raster_duration_timer_.reset(); client_->NotifyReadyToActivate(); } @@ -1800,6 +1961,7 @@ void LayerTreeHostImpl::DidReceiveCompositorFrameAck() { void LayerTreeHostImpl::DidPresentCompositorFrame( uint32_t frame_token, const gfx::PresentationFeedback& feedback) { + frame_trackers_.NotifyFramePresented(frame_token, feedback); PresentationTimeCallbackBuffer::PendingCallbacks activated = presentation_time_callbacks_.PopPendingCallbacks(frame_token); @@ -1817,6 +1979,7 @@ void LayerTreeHostImpl::DidPresentCompositorFrame( void LayerTreeHostImpl::DidNotNeedBeginFrame() { skipped_frame_tracker_.WillNotProduceFrame(); + frame_trackers_.NotifyPauseFrameProduction(); } void LayerTreeHostImpl::ReclaimResources( @@ -1909,7 +2072,6 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { metadata.page_scale_factor = active_tree_->current_page_scale_factor(); metadata.scrollable_viewport_size = active_tree_->ScrollableViewportSize(); metadata.root_background_color = active_tree_->background_color(); - metadata.content_source_id = active_tree_->content_source_id(); if (active_tree_->has_presentation_callbacks()) { presentation_time_callbacks_.RegisterMainThreadPresentationCallbacks( @@ -2061,6 +2223,7 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { if (frame->has_no_damage) { DCHECK(!resourceless_software_draw_); + frame_trackers_.NotifyImplFrameCausedNoDamage(frame->begin_frame_ack); TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoDamage", TRACE_EVENT_SCOPE_THREAD); active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS); return false; @@ -2070,10 +2233,26 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { active_tree_->source_frame_number()); auto compositor_frame = GenerateCompositorFrame(frame); + frame->frame_token = compositor_frame.metadata.frame_token; layer_tree_frame_sink_->SubmitCompositorFrame( std::move(compositor_frame), /*hit_test_data_changed=*/false, debug_state_.show_hit_test_borders); + frame_trackers_.NotifySubmitFrame(compositor_frame.metadata.frame_token, + frame->begin_frame_ack, + frame->origin_begin_main_frame_args); + if (request_animation_frame_tracker_ && + !mutator_host_->NextFrameHasPendingRAF()) { + frame_trackers_.ScheduleRemoval( + std::move(request_animation_frame_tracker_)); + } + + if (main_thread_animation_frame_tracker_ && + mutator_host_->MainThreadAnimationsCount() == 0) { + frame_trackers_.ScheduleRemoval( + std::move(main_thread_animation_frame_tracker_)); + } + // Clears the list of swap promises after calling DidSwap on each of them to // signal that the swap is over. active_tree()->ClearSwapPromises(); @@ -2097,7 +2276,6 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( FrameData* frame) { - TRACE_EVENT0("cc,benchmark", "LayerTreeHostImpl::GenerateCompositorFrame"); TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline", TRACE_ID_GLOBAL(CurrentBeginFrameArgs().trace_id), TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, @@ -2177,15 +2355,15 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( ui::LatencyInfo& new_latency_info = metadata.latency_info.back(); if (CommitToActiveTree()) { new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, frame_time, 1); + ui::LATENCY_BEGIN_FRAME_UI_COMPOSITOR_COMPONENT, frame_time); } else { new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, frame_time, 1); + ui::LATENCY_BEGIN_FRAME_RENDERER_COMPOSITOR_COMPONENT, frame_time); base::TimeTicks draw_time = base::TimeTicks::Now(); for (auto& latency : metadata.latency_info) { latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, draw_time, 1); + ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, draw_time); } } ui::LatencyInfo::TraceIntermediateFlowEvents(metadata.latency_info, @@ -2204,6 +2382,8 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( frame->begin_frame_ack.sequence_number); metadata.begin_frame_ack = frame->begin_frame_ack; + metadata.mirror_rect = frame->mirror_rect; + viz::CompositorFrame compositor_frame; compositor_frame.metadata = std::move(metadata); resource_provider_.PrepareSendToParent( @@ -2226,15 +2406,6 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( } last_draw_local_surface_id_allocation_ = child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); - if (const char* client_name = GetClientNameForMetrics()) { - size_t total_quad_count = 0; - for (const auto& pass : compositor_frame.render_pass_list) - total_quad_count += pass->quad_list.size(); - UMA_HISTOGRAM_COUNTS_1000( - base::StringPrintf("Compositing.%s.CompositorFrame.Quads", client_name), - total_quad_count); - } - return compositor_frame; } @@ -2305,13 +2476,16 @@ void LayerTreeHostImpl::GetGpuRasterizationCapabilities( if (!*gpu_rasterization_enabled && !settings_.gpu_rasterization_forced) return; + bool use_msaa = !caps.msaa_is_slow && !caps.avoid_stencil_buffers; + if (use_oop_rasterization_) { *gpu_rasterization_supported = true; *supports_disable_msaa = caps.multisample_compatibility; // For OOP raster, the gpu service side will disable msaa if the // requested samples are not enough. GPU raster does this same // logic below client side. - *max_msaa_samples = RequestedMSAASampleCount(); + if (use_msaa) + *max_msaa_samples = RequestedMSAASampleCount(); return; } @@ -2326,7 +2500,7 @@ void LayerTreeHostImpl::GetGpuRasterizationCapabilities( return; *supports_disable_msaa = caps.multisample_compatibility; - if (!caps.msaa_is_slow && !caps.avoid_stencil_buffers) { + if (use_msaa) { // Skia may blacklist MSAA independently of Chrome. Query Skia for its max // supported sample count. Assume gpu compositing + gpu raster for this, as // that is what we are hoping to use. @@ -2432,6 +2606,10 @@ void LayerTreeHostImpl::UpdateTreeResourcesForGpuRasterizationIfNeeded() { bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { impl_thread_phase_ = ImplThreadPhase::INSIDE_IMPL_FRAME; current_begin_frame_tracker_.Start(args); + frame_trackers_.NotifyBeginImplFrame(args); + + begin_main_frame_expected_during_impl_ = client_->IsBeginMainFrameExpected(); + begin_main_frame_sent_during_impl_ = false; if (is_likely_to_require_a_draw_) { // Optimistically schedule a draw. This will let us expect the tile manager @@ -2440,8 +2618,10 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { SetNeedsRedraw(); } - if (input_handler_client_) - input_handler_client_->DeliverInputForBeginFrame(); + if (input_handler_client_) { + scrollbar_controller_->WillBeginImplFrame(); + input_handler_client_->DeliverInputForBeginFrame(args); + } Animate(); @@ -2475,6 +2655,18 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { } void LayerTreeHostImpl::DidFinishImplFrame() { + if (!begin_main_frame_sent_during_impl_ && + !begin_main_frame_expected_during_impl_) { + // A begin-main-frame was never dispatched for this BeginFrameArgs, and one + // was not expected to be dispatched either. So notify the trackers of the + // begin-main-frame, and not to expect any updates from it. This is + // necessary to make sure the trackers can correctly know which frames were + // not expected to produce any updates. + frame_trackers_.NotifyBeginMainFrame( + current_begin_frame_tracker_.Current()); + frame_trackers_.NotifyMainFrameCausedNoDamage( + current_begin_frame_tracker_.Current()); + } skipped_frame_tracker_.FinishFrame(); impl_thread_phase_ = ImplThreadPhase::IDLE; current_begin_frame_tracker_.Finish(); @@ -2812,6 +3004,7 @@ void LayerTreeHostImpl::CreatePendingTree() { active_tree()->top_controls_shown_ratio(), active_tree()->elastic_overscroll()); } + pending_tree_fully_painted_ = false; client_->OnCanDrawStateChanged(CanDraw()); TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree:waiting", pending_tree_.get()); @@ -2967,7 +3160,11 @@ void LayerTreeHostImpl::ActivateSyncTree() { // Dump property trees and layers if run with: // --vmodule=layer_tree_host_impl=3 if (VLOG_IS_ON(3)) { - VLOG(3) << "After activating sync tree, the active tree:" + const char* client_name = GetClientNameForMetrics(); + if (!client_name) + client_name = "<unknown client>"; + VLOG(3) << "After activating (" << client_name + << ") sync tree, the active tree:" << "\nproperty_trees:\n" << active_tree_->property_trees()->ToString() << "\n" << "cc::LayerImpls:\n" @@ -3204,7 +3401,7 @@ void LayerTreeHostImpl::SetLayerTreeMutator( void LayerTreeHostImpl::SetPaintWorkletLayerPainter( std::unique_ptr<PaintWorkletLayerPainter> painter) { - tile_manager_.SetPaintWorkletLayerPainter(std::move(painter)); + paint_worklet_painter_ = std::move(painter); } LayerImpl* LayerTreeHostImpl::ViewportMainScrollLayer() { @@ -3320,6 +3517,14 @@ void LayerTreeHostImpl::ReleaseLayerTreeFrameSink() { bool all_resources_are_lost = layer_tree_frame_sink_->context_provider(); + // Destroy the submit-frame trackers before destroying the frame sink. + pinch_frame_tracker_ = nullptr; + scroll_frame_tracker_ = nullptr; + compositor_animation_frame_tracker_ = nullptr; + request_animation_frame_tracker_ = nullptr; + main_thread_animation_frame_tracker_ = nullptr; + frame_trackers_.ClearAll(); + // Detach from the old LayerTreeFrameSink and reset |layer_tree_frame_sink_| // pointer as this surface is going to be destroyed independent of if binding // the new LayerTreeFrameSink succeeds or not. @@ -3329,15 +3534,24 @@ void LayerTreeHostImpl::ReleaseLayerTreeFrameSink() { // If gpu compositing, then any resources created with the gpu context in the // LayerTreeFrameSink were exported to the display compositor may be modified // by it, and thus we would be unable to determine what state they are in, in - // order to reuse them, so they must be lost. In software compositing, the - // resources are not modified by the display compositor (there is no stateful - // metadata for shared memory), so we do not need to consider them lost. + // order to reuse them, so they must be lost. Note that this includes + // resources created using the gpu context associated with + // |layer_tree_frame_sink_| internally by the compositor and any resources + // received from an external source (for instance, TextureLayers). This is + // because the API contract for releasing these external resources requires + // that the compositor return them with a valid sync token and no + // modifications to their GL state. Since that can not be guaranteed, these + // must also be marked lost. + // + // In software compositing, the resources are not modified by the display + // compositor (there is no stateful metadata for shared memory), so we do not + // need to consider them lost. // // In both cases, the resources that are exported to the display compositor // will have no means of being returned to this client without the - // LayerTreeFrameSink, so they should no longer be considered as exported. - // Do this *after* any interactions with the |layer_tree_frame_sink_| in case - // it tries to return resources during destruction. + // LayerTreeFrameSink, so they should no longer be considered as exported. Do + // this *after* any interactions with the |layer_tree_frame_sink_| in case it + // tries to return resources during destruction. // // The assumption being made here is that the display compositor WILL NOT use // any resources previously exported when the CompositorFrameSink is closed. @@ -3472,7 +3686,6 @@ void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) { InputHandler::ScrollStatus LayerTreeHostImpl::TryScroll( const gfx::PointF& screen_space_point, - InputHandler::ScrollInputType type, const ScrollTree& scroll_tree, ScrollNode* scroll_node) const { InputHandler::ScrollStatus scroll_status; @@ -3516,29 +3729,6 @@ InputHandler::ScrollStatus LayerTreeHostImpl::TryScroll( return scroll_status; } - if (layer && !layer->non_fast_scrollable_region().IsEmpty()) { - bool clipped = false; - gfx::Transform inverse_screen_space_transform( - gfx::Transform::kSkipInitialization); - if (!screen_space_transform.GetInverse(&inverse_screen_space_transform)) { - // TODO(shawnsingh): We shouldn't be applying a projection if screen space - // transform is uninvertible here. Perhaps we should be returning - // SCROLL_ON_MAIN_THREAD in this case? - } - - gfx::PointF hit_test_point_in_layer_space = MathUtil::ProjectPoint( - inverse_screen_space_transform, screen_space_point, &clipped); - if (!clipped && layer->non_fast_scrollable_region().Contains( - gfx::ToRoundedPoint(hit_test_point_in_layer_space))) { - TRACE_EVENT0("cc", - "LayerImpl::tryScroll: Failed NonFastScrollableRegion"); - scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD; - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNonFastScrollableRegion; - return scroll_status; - } - } - if (!scroll_node->scrollable) { TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable"); scroll_status.thread = InputHandler::SCROLL_IGNORED; @@ -3578,9 +3768,21 @@ static bool IsMainThreadScrolling(const InputHandler::ScrollStatus& status, return false; } +base::flat_set<int> LayerTreeHostImpl::NonFastScrollableNodes( + const gfx::PointF& device_viewport_point) const { + base::flat_set<int> non_fast_scrollable_nodes; + + const auto& non_fast_layers = + active_tree_->FindLayersHitByPointInNonFastScrollableRegion( + device_viewport_point); + for (const auto* layer : non_fast_layers) + non_fast_scrollable_nodes.insert(layer->scroll_tree_index()); + + return non_fast_scrollable_nodes; +} + ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint( const gfx::PointF& device_viewport_point, - InputHandler::ScrollInputType type, LayerImpl* layer_impl, bool* scroll_on_main_thread, uint32_t* main_thread_scrolling_reasons) const { @@ -3589,6 +3791,9 @@ ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint( *main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; + const auto& non_fast_scrollable_nodes = + NonFastScrollableNodes(device_viewport_point); + // Walk up the hierarchy and look for a scrollable layer. ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* impl_scroll_node = nullptr; @@ -3611,13 +3816,20 @@ ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint( // The content layer can also block attempts to scroll outside the main // thread. ScrollStatus status = - TryScroll(device_viewport_point, type, scroll_tree, scroll_node); + TryScroll(device_viewport_point, scroll_tree, scroll_node); if (IsMainThreadScrolling(status, scroll_node)) { *scroll_on_main_thread = true; *main_thread_scrolling_reasons = status.main_thread_scrolling_reasons; return scroll_node; } + if (non_fast_scrollable_nodes.contains(scroll_node->id)) { + *scroll_on_main_thread = true; + *main_thread_scrolling_reasons = + MainThreadScrollingReason::kNonFastScrollableRegion; + return scroll_node; + } + if (status.thread == InputHandler::SCROLL_ON_IMPL_THREAD && !impl_scroll_node) { impl_scroll_node = scroll_node; @@ -3638,10 +3850,14 @@ ScrollNode* LayerTreeHostImpl::FindScrollNodeForDeviceViewportPoint( if (impl_scroll_node) { // Ensure that final layer scrolls on impl thread (crbug.com/625100) ScrollStatus status = - TryScroll(device_viewport_point, type, scroll_tree, impl_scroll_node); + TryScroll(device_viewport_point, scroll_tree, impl_scroll_node); if (IsMainThreadScrolling(status, impl_scroll_node)) { *scroll_on_main_thread = true; *main_thread_scrolling_reasons = status.main_thread_scrolling_reasons; + } else if (non_fast_scrollable_nodes.contains(impl_scroll_node->id)) { + *scroll_on_main_thread = true; + *main_thread_scrolling_reasons = + MainThreadScrollingReason::kNonFastScrollableRegion; } } @@ -3710,10 +3926,13 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBeginImpl( scroll_status.bubble = true; } + scroll_frame_tracker_ = frame_trackers_.CreateTracker( + wheel_scrolling_ ? FrameSequenceTrackerType::kWheelScroll + : FrameSequenceTrackerType::kTouchScroll); client_->RenewTreePriority(); RecordCompositorSlowScrollMetric(type, CC_THREAD); - UpdateScrollSourceInfo(type); + UpdateScrollSourceInfo(type, scroll_state); return scroll_status; } @@ -3796,7 +4015,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin( } scrolling_node = FindScrollNodeForDeviceViewportPoint( - device_viewport_point, type, layer_impl, &scroll_on_main_thread, + device_viewport_point, layer_impl, &scroll_on_main_thread, &scroll_status.main_thread_scrolling_reasons); } @@ -3943,14 +4162,31 @@ gfx::Vector2dF LayerTreeHostImpl::ComputeScrollDelta( return gfx::Vector2dF(scrolled.x(), scrolled.y()); } +bool LayerTreeHostImpl::AutoScrollAnimationCreate(ScrollNode* scroll_node, + const gfx::Vector2dF& delta, + float autoscroll_velocity) { + return ScrollAnimationCreateInternal(scroll_node, delta, base::TimeDelta(), + autoscroll_velocity); +} + bool LayerTreeHostImpl::ScrollAnimationCreate(ScrollNode* scroll_node, const gfx::Vector2dF& delta, base::TimeDelta delayed_by) { + return ScrollAnimationCreateInternal(scroll_node, delta, delayed_by, + base::nullopt); +} + +bool LayerTreeHostImpl::ScrollAnimationCreateInternal( + ScrollNode* scroll_node, + const gfx::Vector2dF& delta, + base::TimeDelta delayed_by, + base::Optional<float> autoscroll_velocity) { ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; const float kEpsilon = 0.1f; bool scroll_animated = - (std::abs(delta.x()) > kEpsilon || std::abs(delta.y()) > kEpsilon); + (std::abs(delta.x()) > kEpsilon || std::abs(delta.y()) > kEpsilon) || + autoscroll_velocity; if (!scroll_animated) { scroll_tree.ScrollBy(scroll_node, delta, active_tree()); TRACE_EVENT_INSTANT0("cc", "no scroll animation due to small delta", @@ -3970,9 +4206,15 @@ bool LayerTreeHostImpl::ScrollAnimationCreate(ScrollNode* scroll_node, // input latency tracking architecture from working. base::TimeDelta animation_start_offset = CurrentBeginFrameArgs().interval; - mutator_host_->ImplOnlyScrollAnimationCreate( - scroll_node->element_id, target_offset, current_offset, delayed_by, - animation_start_offset); + if (autoscroll_velocity) { + mutator_host_->ImplOnlyAutoScrollAnimationCreate( + scroll_node->element_id, gfx::ScrollOffset(delta), current_offset, + autoscroll_velocity.value(), animation_start_offset); + } else { + mutator_host_->ImplOnlyScrollAnimationCreate( + scroll_node->element_id, target_offset, current_offset, delayed_by, + animation_start_offset); + } SetNeedsOneBeginImplFrame(); @@ -4762,6 +5004,7 @@ void LayerTreeHostImpl::ScrollEndImpl(ScrollState* scroll_state) { DistributeScrollDelta(scroll_state); browser_controls_offset_manager_->ScrollEnd(); ClearCurrentlyScrollingNode(); + frame_trackers_.ScheduleRemoval(std::move(scroll_frame_tracker_)); } void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) { @@ -4843,8 +5086,8 @@ InputHandlerPointerResult LayerTreeHostImpl::MouseMoveAt( bool scroll_on_main_thread = false; uint32_t main_thread_scrolling_reasons; auto* scroll_node = FindScrollNodeForDeviceViewportPoint( - device_viewport_point, InputHandler::TOUCHSCREEN, layer_impl, - &scroll_on_main_thread, &main_thread_scrolling_reasons); + device_viewport_point, layer_impl, &scroll_on_main_thread, + &main_thread_scrolling_reasons); if (scroll_node) scroll_element_id = scroll_node->element_id; @@ -4895,6 +5138,8 @@ void LayerTreeHostImpl::PinchGestureBegin() { OuterViewportScrollNode() ? false : true); active_tree_->SetCurrentlyScrollingNode(OuterViewportScrollNode()); browser_controls_offset_manager_->PinchBegin(); + pinch_frame_tracker_ = + frame_trackers_.CreateTracker(FrameSequenceTrackerType::kPinchZoom); } void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, @@ -4902,6 +5147,7 @@ void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate"); if (!InnerViewportScrollNode()) return; + has_pinch_zoomed_ = true; viewport()->PinchUpdate(magnify_delta, anchor); client_->SetNeedsCommitOnImplThread(); SetNeedsRedraw(); @@ -4926,6 +5172,7 @@ void LayerTreeHostImpl::PinchGestureEnd(const gfx::Point& anchor, // scales that we want when we're not inside a pinch. active_tree_->set_needs_update_draw_properties(); SetNeedsRedraw(); + frame_trackers_.ScheduleRemoval(std::move(pinch_frame_tracker_)); } void LayerTreeHostImpl::CollectScrollDeltas( @@ -4971,10 +5218,23 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { scroll_info->swap_promises.swap(swap_promises_for_main_thread_scroll_update_); // Record and reset scroll source flags. - scroll_info->has_scrolled_by_wheel = has_scrolled_by_wheel_; - scroll_info->has_scrolled_by_touch = has_scrolled_by_touch_; + if (has_scrolled_by_wheel_) { + scroll_info->manipulation_info |= kManipulationInfoHasScrolledByWheel; + } + if (has_scrolled_by_touch_) { + scroll_info->manipulation_info |= kManipulationInfoHasScrolledByTouch; + } + if (has_scrolled_by_precisiontouchpad_) { + scroll_info->manipulation_info |= + kManipulationInfoHasScrolledByPrecisionTouchPad; + } + if (has_pinch_zoomed_) { + scroll_info->manipulation_info |= kManipulationInfoHasPinchZoomed; + } + + has_scrolled_by_wheel_ = has_scrolled_by_touch_ = + has_scrolled_by_precisiontouchpad_ = has_pinch_zoomed_ = false; scroll_info->scroll_gesture_did_end = scroll_gesture_did_end_; - has_scrolled_by_wheel_ = has_scrolled_by_touch_ = false; // Record and reset overscroll delta. scroll_info->overscroll_delta = overscroll_delta_for_main_thread_; @@ -5091,8 +5351,17 @@ bool LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time, // TODO(crbug.com/551138): We currently have a single signal from the // animation_host, so on the last frame of an animation we will // still request an extra SetNeedsAnimate here. - if (animated) + if (animated) { SetNeedsOneBeginImplFrame(); + if (!compositor_animation_frame_tracker_) { + compositor_animation_frame_tracker_ = frame_trackers_.CreateTracker( + FrameSequenceTrackerType::kCompositorAnimation); + } + } else { + frame_trackers_.ScheduleRemoval( + std::move(compositor_animation_frame_tracker_)); + } + // TODO(crbug.com/551138): We could return true only if the animaitons are on // the active tree. There's no need to cause a draw to take place from // animations starting/ticking on the pending tree. @@ -5371,7 +5640,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, GLenum texture_target = GL_TEXTURE_2D; // For software compositing, shared memory will be allocated and the // UIResource will be copied into it. - base::MappedReadOnlyRegion mapped_region; + base::MappedReadOnlyRegion shm; viz::SharedBitmapId shared_bitmap_id; bool overlay_candidate = false; @@ -5389,8 +5658,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, BufferFormat(format), caps); } } else { - mapped_region = - viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format); + shm = viz::bitmap_allocation::AllocateSharedBitmap(upload_size, format); shared_bitmap_id = viz::SharedBitmap::GenerateId(); } @@ -5415,7 +5683,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( - dst_info, mapped_region.mapping.memory(), dst_info.minRowBytes()); + dst_info, shm.mapping.memory(), dst_info.minRowBytes()); surface->getCanvas()->writePixels( src_info, const_cast<uint8_t*>(bitmap.GetPixels()), src_info.minRowBytes(), 0, 0); @@ -5451,7 +5719,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, SkImageInfo dst_info = SkImageInfo::MakeN32Premul(gfx::SizeToSkISize(upload_size)); scaled_surface = SkSurface::MakeRasterDirect( - dst_info, mapped_region.mapping.memory(), dst_info.minRowBytes()); + dst_info, shm.mapping.memory(), dst_info.minRowBytes()); } SkCanvas* scaled_canvas = scaled_surface->getCanvas(); scaled_canvas->scale(canvas_scale_x, canvas_scale_y); @@ -5494,9 +5762,8 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, overlay_candidate); transferable.format = format; } else { - layer_tree_frame_sink_->DidAllocateSharedBitmap( - viz::bitmap_allocation::ToMojoHandle(std::move(mapped_region.region)), - shared_bitmap_id); + layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(shm.region), + shared_bitmap_id); transferable = viz::TransferableResource::MakeSoftware(shared_bitmap_id, upload_size, format); } @@ -5514,7 +5781,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, data.opaque = bitmap.GetOpaque(); data.format = format; data.shared_bitmap_id = shared_bitmap_id; - data.shared_mapping = std::move(mapped_region.mapping); + data.shared_mapping = std::move(shm.mapping); data.mailbox = mailbox; data.resource_id_for_export = id; ui_resource_map_[uid] = std::move(data); @@ -5916,11 +6183,18 @@ void LayerTreeHostImpl::SetContextVisibility(bool is_visible) { } void LayerTreeHostImpl::UpdateScrollSourceInfo( - InputHandler::ScrollInputType type) { - if (type == InputHandler::WHEEL) + InputHandler::ScrollInputType type, + ScrollState* scroll_state) { + if (type == InputHandler::WHEEL && + scroll_state->delta_granularity() == + static_cast<double>( + ui::input_types::ScrollGranularity::kScrollByPrecisePixel)) { + has_scrolled_by_precisiontouchpad_ = true; + } else if (type == InputHandler::WHEEL) { has_scrolled_by_wheel_ = true; - else if (type == InputHandler::TOUCHSCREEN) + } else if (type == InputHandler::TOUCHSCREEN) { has_scrolled_by_touch_ = true; + } } void LayerTreeHostImpl::ShowScrollbarsForImplScroll(ElementId element_id) { diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index bb89bc998a4..ca403dbfd97 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -27,14 +27,17 @@ #include "cc/input/scrollbar_animation_controller.h" #include "cc/input/scrollbar_controller.h" #include "cc/layers/layer_collections.h" +#include "cc/paint/paint_worklet_job.h" #include "cc/resources/ui_resource_client.h" #include "cc/scheduler/begin_frame_tracker.h" #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/draw_result.h" +#include "cc/scheduler/scheduler.h" #include "cc/scheduler/video_frame_controller.h" #include "cc/tiles/decoded_image_tracker.h" #include "cc/tiles/image_decode_cache.h" #include "cc/tiles/tile_manager.h" +#include "cc/trees/frame_sequence_tracker.h" #include "cc/trees/layer_tree_frame_sink_client.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_mutator.h" @@ -156,10 +159,16 @@ class LayerTreeHostImplClient { std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback) = 0; + // Returns whether the main-thread is expected to receive a BeginMainFrame. + virtual bool IsBeginMainFrameExpected() = 0; + virtual void NotifyAnimationWorkletStateChange( AnimationWorkletMutationState state, ElementListType tree_type) = 0; + virtual void NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) = 0; + protected: virtual ~LayerTreeHostImplClient() {} }; @@ -187,6 +196,9 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, FrameData& operator=(const FrameData&) = delete; void AsValueInto(base::trace_event::TracedValue* value) const; + uint32_t frame_token = 0; + // frame_token is populated by the LayerTreeHostImpl when submitted. + std::vector<viz::SurfaceId> activation_dependencies; base::Optional<uint32_t> deadline_in_frames; bool use_default_lower_bound_deadline = false; @@ -196,6 +208,13 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, bool has_no_damage = false; bool may_contain_video = false; viz::BeginFrameAck begin_frame_ack; + // The original BeginFrameArgs that triggered the latest update from the + // main thread. + viz::BeginFrameArgs origin_begin_main_frame_args; + + // Union of visible rects of MirrorLayers in the frame, used to force damage + // on the surface. + gfx::Rect mirror_rect; }; // A struct of data for a single UIResource, including the backing @@ -275,8 +294,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, void SetNeedsAnimateInput() override; bool IsCurrentlyScrollingViewport() const override; bool IsCurrentlyScrollingLayerAt( - const gfx::Point& viewport_point, - InputHandler::ScrollInputType type) const override; + const gfx::Point& viewport_point) const override; EventListenerProperties GetEventListenerProperties( EventListenerClass event_class) const override; InputHandler::TouchStartOrMoveEventListenerType @@ -320,10 +338,11 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, } virtual void WillSendBeginMainFrame() {} - virtual void DidSendBeginMainFrame() {} + virtual void DidSendBeginMainFrame(const viz::BeginFrameArgs& args); virtual void BeginMainFrameAborted( CommitEarlyOutReason reason, - std::vector<std::unique_ptr<SwapPromise>> swap_promises); + std::vector<std::unique_ptr<SwapPromise>> swap_promises, + const viz::BeginFrameArgs& args); virtual void ReadyToCommit() {} // For tests. virtual void BeginCommit(); virtual void CommitComplete(); @@ -432,6 +451,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, DrawMode GetDrawMode() const; + void DidNotNeedBeginFrame(); + // TileManagerClient implementation. void NotifyReadyToActivate() override; void NotifyReadyToDraw() override; @@ -471,7 +492,6 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, void DidPresentCompositorFrame( uint32_t frame_token, const gfx::PresentationFeedback& feedback) override; - void DidNotNeedBeginFrame() override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override; @@ -506,6 +526,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, int* max_msaa_samples, bool* supports_disable_msaa); bool use_gpu_rasterization() const { return use_gpu_rasterization_; } + bool use_oop_rasterization() const { return use_oop_rasterization_; } bool use_msaa() const { return use_msaa_; } GpuRasterizationStatus gpu_rasterization_status() const { @@ -710,19 +731,30 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, } InputHandler::ScrollStatus TryScroll(const gfx::PointF& screen_space_point, - InputHandler::ScrollInputType type, const ScrollTree& scroll_tree, ScrollNode* scroll_node) const; + // Return all ScrollNode indices that have an associated layer with a non-fast + // region that intersects the point. + base::flat_set<int> NonFastScrollableNodes( + const gfx::PointF& device_viewport_point) const; + // Returns true if a scroll offset animation is created and false if we scroll // by the desired amount without an animation. bool ScrollAnimationCreate(ScrollNode* scroll_node, const gfx::Vector2dF& scroll_amount, base::TimeDelta delayed_by); + bool AutoScrollAnimationCreate(ScrollNode* scroll_node, + const gfx::Vector2dF& scroll_amount, + float autoscroll_velocity); void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator); + void SetPaintWorkletLayerPainter( std::unique_ptr<PaintWorkletLayerPainter> painter); + PaintWorkletLayerPainter* GetPaintWorkletLayerPainterForTesting() const { + return paint_worklet_painter_.get(); + } // The viewport has two scroll nodes, corresponding to the visual and layout // viewports. However, when we compute the scroll chain we include only one @@ -759,6 +791,10 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, return compositor_frame_reporting_controller_.get(); } + void set_pending_tree_fully_painted_for_testing(bool painted) { + pending_tree_fully_painted_ = painted; + } + protected: LayerTreeHostImpl( const LayerTreeSettings& settings, @@ -810,6 +846,10 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, const gfx::PointF& viewport_point, const gfx::Vector2dF& viewport_delta, ScrollTree* scroll_tree); + bool ScrollAnimationCreateInternal(ScrollNode* scroll_node, + const gfx::Vector2dF& delta, + base::TimeDelta delayed_by, + base::Optional<float> autoscroll_velocity); void CleanUpTileManagerResources(); void CreateTileManagerResources(); @@ -824,6 +864,18 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, // impl thread. void UpdateSyncTreeAfterCommitOrImplSideInvalidation(); + // Returns a job map for all 'dirty' PaintWorklets, e.g. PaintWorkletInputs + // that do not map to a PaintRecord. + PaintWorkletJobMap GatherDirtyPaintWorklets() const; + + // Called when all PaintWorklet results are ready (i.e. have been painted) for + // the current pending tree. + void OnPaintWorkletResultsReady(PaintWorkletJobMap results); + + // Called when the pending tree has been fully painted, i.e. all required data + // is available to raster the tree. + void NotifyPendingTreeFullyPainted(); + // Returns true if status changed. bool UpdateGpuRasterizationStatus(); void UpdateTreeResourcesForGpuRasterizationIfNeeded(); @@ -862,7 +914,6 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, ScrollNode* FindScrollNodeForDeviceViewportPoint( const gfx::PointF& device_viewport_point, - InputHandler::ScrollInputType type, LayerImpl* layer_hit_by_point, bool* scroll_on_main_thread, uint32_t* main_thread_scrolling_reason) const; @@ -910,7 +961,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, // thread side to keep track of the frequency of scrolling with different // sources per page load. TODO(crbug.com/691886): Use GRC API to plumb the // scroll source info for Use Counters. - void UpdateScrollSourceInfo(InputHandler::ScrollInputType type); + void UpdateScrollSourceInfo(InputHandler::ScrollInputType type, + ScrollState* scroll_state); bool IsScrolledBy(LayerImpl* child, ScrollNode* ancestor); void ShowScrollbarsForImplScroll(ElementId element_id); @@ -931,6 +983,13 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, void AllocateLocalSurfaceId(); const LayerTreeSettings settings_; + + // This is set to true only if: + // . The compositor is running single-threaded (i.e. there is no separate + // compositor/impl thread). + // . There is no scheduler (which means layer-update, composite, etc. steps + // happen explicitly via. synchronous calls to appropriate functions). + // This is usually turned on only in some tests (e.g. web-tests). const bool is_synchronous_single_threaded_; const int default_color_space_id_ = gfx::ColorSpace::GetNextId(); @@ -1138,13 +1197,21 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, // success) state. std::vector<std::pair<int, bool>> completed_image_decode_requests_; - // These are used to transfer usage of touch and wheel scrolls to the main - // thread. + // These are used to transfer usage of different types of scrolling to the + // main thread. bool has_scrolled_by_wheel_ = false; bool has_scrolled_by_touch_ = false; + bool has_scrolled_by_precisiontouchpad_ = false; + bool has_pinch_zoomed_ = false; ImplThreadPhase impl_thread_phase_ = ImplThreadPhase::IDLE; + // Tracks whether a BeginMainFrame is expected to be dispatched during an + // 'impl frame' (i.e. between WillBeginImplFrame() and DidFinishImplFrame()), + // and whether it was actually dispatched during the impl frame. + bool begin_main_frame_expected_during_impl_ = false; + bool begin_main_frame_sent_during_impl_ = false; + ImageAnimationController image_animation_controller_; std::unique_ptr<UkmManager> ukm_manager_; @@ -1172,6 +1239,13 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, // Manages composited scrollbar hit testing. std::unique_ptr<ScrollbarController> scrollbar_controller_; + FrameSequenceTrackerCollection frame_trackers_; + std::unique_ptr<FrameSequenceTracker> pinch_frame_tracker_; + std::unique_ptr<FrameSequenceTracker> scroll_frame_tracker_; + std::unique_ptr<FrameSequenceTracker> compositor_animation_frame_tracker_; + std::unique_ptr<FrameSequenceTracker> request_animation_frame_tracker_; + std::unique_ptr<FrameSequenceTracker> main_thread_animation_frame_tracker_; + // 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. @@ -1187,9 +1261,18 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler, // once the animation is over. base::Optional<ScrollState> deferred_scroll_end_state_; + // PaintWorklet painting is controlled from the LayerTreeHostImpl, dispatched + // to the worklet thread via |paint_worklet_painter_|. + std::unique_ptr<PaintWorkletLayerPainter> paint_worklet_painter_; + + // While PaintWorklet painting is ongoing the PendingTree is not yet fully + // painted and cannot be rastered or activated. This boolean tracks whether or + // not we are in that state. + bool pending_tree_fully_painted_ = false; + // Must be the last member to ensure this is destroyed first in the // destruction order and invalidates all weak pointers. - base::WeakPtrFactory<LayerTreeHostImpl> weak_factory_; + base::WeakPtrFactory<LayerTreeHostImpl> weak_factory_{this}; }; } // 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 80d1f14a001..24ceca1c40c 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -55,6 +55,8 @@ #include "cc/test/layer_test_common.h" #include "cc/test/layer_tree_test.h" #include "cc/test/skia_common.h" +#include "cc/test/test_layer_tree_frame_sink.h" +#include "cc/test/test_paint_worklet_layer_painter.h" #include "cc/test/test_task_graph_runner.h" #include "cc/trees/clip_node.h" #include "cc/trees/draw_property_utils.h" @@ -81,7 +83,6 @@ #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" #include "components/viz/test/fake_skia_output_surface.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #include "gpu/GLES2/gl2extchromium.h" #include "media/base/media.h" #include "testing/gmock/include/gmock/gmock.h" @@ -135,6 +136,7 @@ class LayerTreeHostImplTest : public testing::Test, did_request_redraw_(false), did_request_next_frame_(false), did_request_prepare_tiles_(false), + did_prepare_tiles_(false), did_complete_page_scale_animation_(false), reduce_memory_result_(true), did_request_impl_side_invalidation_(false) { @@ -159,6 +161,13 @@ class LayerTreeHostImplTest : public testing::Test, host_impl_->active_tree()->GetDeviceViewport().size()); pending_tree->SetDeviceScaleFactor( host_impl_->active_tree()->device_scale_factor()); + // Normally a pending tree will not be fully painted until the commit has + // happened and any PaintWorklets have been resolved. However many of the + // unittests never actually commit the pending trees that they create, so to + // enable them to still treat the tree as painted we forcibly override the + // state here. Note that this marks a distinct departure from reality in the + // name of easier testing. + host_impl_->set_pending_tree_fully_painted_for_testing(true); } void TearDown() override { @@ -189,6 +198,7 @@ class LayerTreeHostImplTest : public testing::Test, void PostAnimationEventsToMainThreadOnImplThread( std::unique_ptr<MutatorEvents> events) override {} bool IsInsideDraw() override { return false; } + bool IsBeginMainFrameExpected() override { return true; } void RenewTreePriority() override {} void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) override { @@ -203,7 +213,7 @@ class LayerTreeHostImplTest : public testing::Test, base::TimeTicks::Now())); } void WillPrepareTiles() override {} - void DidPrepareTiles() override {} + void DidPrepareTiles() override { did_prepare_tiles_ = true; } void DidCompletePageScaleAnimationOnImplThread() override { did_complete_page_scale_animation_ = true; } @@ -229,6 +239,8 @@ class LayerTreeHostImplTest : public testing::Test, const gfx::PresentationFeedback& feedback) override {} void NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state, ElementListType tree_type) override {} + void NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) override {} void set_reduce_memory_result(bool reduce_memory_result) { reduce_memory_result_ = reduce_memory_result; @@ -796,6 +808,7 @@ class LayerTreeHostImplTest : public testing::Test, bool did_request_redraw_; bool did_request_next_frame_; bool did_request_prepare_tiles_; + bool did_prepare_tiles_; bool did_complete_page_scale_animation_; bool reduce_memory_result_; bool did_request_impl_side_invalidation_; @@ -852,7 +865,8 @@ class TestInputHandlerClient : public InputHandlerClient { min_page_scale_factor_ = min_page_scale_factor; max_page_scale_factor_ = max_page_scale_factor; } - void DeliverInputForBeginFrame() override {} + void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override {} + void DeliverInputForHighLatencyMode() override {} gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } @@ -1095,14 +1109,11 @@ TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) { EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(), - InputHandler::WHEEL)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get()); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10), - InputHandler::WHEEL)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10))); host_impl_->ScrollEnd(EndState().get()); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(), - InputHandler::WHEEL)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); EXPECT_TRUE(did_request_redraw_); EXPECT_TRUE(did_request_commit_); } @@ -1374,16 +1385,14 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) { EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, status.main_thread_scrolling_reasons); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25), - InputHandler::WHEEL)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25))); status = host_impl_->ScrollBegin(BeginState(gfx::Point(25, 25)).get(), InputHandler::TOUCHSCREEN); EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, status.main_thread_scrolling_reasons); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(25, 25), InputHandler::TOUCHSCREEN)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25))); // All scroll types outside this region should succeed. status = host_impl_->ScrollBegin(BeginState(gfx::Point(75, 75)).get(), @@ -1392,26 +1401,21 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) { EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(75, 75), InputHandler::TOUCHSCREEN)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75))); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get()); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(25, 25), InputHandler::TOUCHSCREEN)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25))); host_impl_->ScrollEnd(EndState().get()); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(75, 75), InputHandler::TOUCHSCREEN)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75))); status = host_impl_->ScrollBegin(BeginState(gfx::Point(75, 75)).get(), InputHandler::TOUCHSCREEN); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(75, 75), InputHandler::TOUCHSCREEN)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75))); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get()); host_impl_->ScrollEnd(EndState().get()); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(75, 75), InputHandler::TOUCHSCREEN)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75))); } TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) { @@ -1434,8 +1438,7 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) { EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10), - InputHandler::WHEEL)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10))); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 1)).get()); host_impl_->ScrollEnd(EndState().get()); @@ -10410,7 +10413,88 @@ TEST_F(LayerTreeHostImplTest, EXPECT_FALSE(host_impl_->EvictedUIResourcesExist()); } -class FrameSinkClient : public viz::TestLayerTreeFrameSinkClient { +TEST_F(LayerTreeHostImplTest, ObeyMSAACaps) { + LayerTreeSettings msaaSettings = DefaultSettings(); + msaaSettings.gpu_rasterization_msaa_sample_count = 4; + + // gpu raster, msaa on + { + bool msaa_is_slow = false; + EXPECT_TRUE(CreateHostImpl( + msaaSettings, + FakeLayerTreeFrameSink::Create3dForGpuRasterization( + msaaSettings.gpu_rasterization_msaa_sample_count, msaa_is_slow))); + + host_impl_->SetHasGpuRasterizationTrigger(true); + host_impl_->SetContentHasSlowPaths(true); + host_impl_->CommitComplete(); + + EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT, + host_impl_->gpu_rasterization_status()); + EXPECT_TRUE(host_impl_->use_gpu_rasterization()); + EXPECT_FALSE(host_impl_->use_oop_rasterization()); + EXPECT_TRUE(host_impl_->use_msaa()); + } + + // gpu raster, msaa off + { + bool msaa_is_slow = true; + EXPECT_TRUE(CreateHostImpl( + msaaSettings, + FakeLayerTreeFrameSink::Create3dForGpuRasterization( + msaaSettings.gpu_rasterization_msaa_sample_count, msaa_is_slow))); + + host_impl_->SetHasGpuRasterizationTrigger(true); + host_impl_->SetContentHasSlowPaths(true); + host_impl_->CommitComplete(); + + EXPECT_EQ(GpuRasterizationStatus::ON, + host_impl_->gpu_rasterization_status()); + EXPECT_TRUE(host_impl_->use_gpu_rasterization()); + EXPECT_FALSE(host_impl_->use_oop_rasterization()); + EXPECT_FALSE(host_impl_->use_msaa()); + } + + // oop raster, msaa on + { + bool msaa_is_slow = false; + EXPECT_TRUE(CreateHostImpl( + msaaSettings, + FakeLayerTreeFrameSink::Create3dForOopRasterization( + msaaSettings.gpu_rasterization_msaa_sample_count, msaa_is_slow))); + + host_impl_->SetHasGpuRasterizationTrigger(true); + host_impl_->SetContentHasSlowPaths(true); + host_impl_->CommitComplete(); + + EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT, + host_impl_->gpu_rasterization_status()); + EXPECT_TRUE(host_impl_->use_gpu_rasterization()); + EXPECT_TRUE(host_impl_->use_oop_rasterization()); + EXPECT_TRUE(host_impl_->use_msaa()); + } + + // oop raster, msaa off + { + bool msaa_is_slow = true; + EXPECT_TRUE(CreateHostImpl( + msaaSettings, + FakeLayerTreeFrameSink::Create3dForOopRasterization( + msaaSettings.gpu_rasterization_msaa_sample_count, msaa_is_slow))); + + host_impl_->SetHasGpuRasterizationTrigger(true); + host_impl_->SetContentHasSlowPaths(true); + host_impl_->CommitComplete(); + + EXPECT_EQ(GpuRasterizationStatus::ON, + host_impl_->gpu_rasterization_status()); + EXPECT_TRUE(host_impl_->use_gpu_rasterization()); + EXPECT_TRUE(host_impl_->use_oop_rasterization()); + EXPECT_FALSE(host_impl_->use_msaa()); + } +} + +class FrameSinkClient : public TestLayerTreeFrameSinkClient { public: explicit FrameSinkClient( scoped_refptr<viz::ContextProvider> display_context_provider) @@ -10464,7 +10548,7 @@ TEST_P(LayerTreeHostImplTestWithRenderer, ShutdownReleasesContext) { constexpr double refresh_rate = 60.0; viz::RendererSettings renderer_settings = viz::RendererSettings(); renderer_settings.use_skia_renderer = renderer_type() == RENDERER_SKIA; - auto layer_tree_frame_sink = std::make_unique<viz::TestLayerTreeFrameSink>( + auto layer_tree_frame_sink = std::make_unique<TestLayerTreeFrameSink>( context_provider, viz::TestContextProvider::CreateWorker(), nullptr, renderer_settings, base::ThreadTaskRunnerHandle::Get().get(), synchronous_composite, disable_display_vsync, refresh_rate); @@ -11611,16 +11695,14 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, ->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::TOUCHSCREEN) .thread); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(), InputHandler::TOUCHSCREEN)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); // Scroll near the edge of the outer viewport. gfx::Vector2d scroll_delta(inner_viewport.width() / 2.f, inner_viewport.height() / 2.f); host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get()); inner_expected += scroll_delta; - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(), InputHandler::TOUCHSCREEN)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); @@ -11630,13 +11712,11 @@ TEST_F(LayerTreeHostImplVirtualViewportTest, // and outer viewport layers is perfect. host_impl_->ScrollBy( UpdateState(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2)).get()); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(), InputHandler::TOUCHSCREEN)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); outer_expected += scroll_delta; inner_expected += scroll_delta; host_impl_->ScrollEnd(EndState().get()); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt( - gfx::Point(), InputHandler::TOUCHSCREEN)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset()); EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset()); @@ -12452,16 +12532,13 @@ TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimatedAborted) { host_impl_ ->ScrollBegin(BeginState(gfx::Point(0, y)).get(), InputHandler::WHEEL) .thread); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y), - InputHandler::WHEEL)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y))); host_impl_->ScrollBy( UpdateState(gfx::Point(0, y), gfx::Vector2d(0, 50)).get()); - EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y + 50), - InputHandler::WHEEL)); + EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, y + 50))); std::unique_ptr<ScrollState> scroll_state_end = EndState(); host_impl_->ScrollEnd(scroll_state_end.get()); - EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(), - InputHandler::WHEEL)); + EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point())); // The instant scroll should have marked the smooth scroll animation as // aborted. @@ -12851,7 +12928,7 @@ TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) { layer->SetDrawsContent(true); layer->tilings()->AddTiling(gfx::AxisTransform2d(), raster_source_with_tiles); layer->UpdateRasterSource(raster_source_with_tiles, &empty_invalidation, - nullptr); + nullptr, nullptr); layer->tilings()->tiling_at(0)->set_resolution( TileResolution::HIGH_RESOLUTION); layer->tilings()->tiling_at(0)->CreateAllTilesForTesting(); @@ -13447,9 +13524,7 @@ TEST_F(LayerTreeHostImplTest, UpdatePageScaleFactorOnActiveTree) { CreateScrollAndContentsLayers(host_impl_->pending_tree(), gfx::Size(100, 100)); host_impl_->pending_tree()->BuildPropertyTreesForTesting(); - LOG(ERROR) << "ACTIVATE SYNC TREE"; host_impl_->ActivateSyncTree(); - LOG(ERROR) << "DONE ACTIVATE SYNC TREE"; DrawFrame(); CreatePendingTree(); @@ -13475,9 +13550,7 @@ TEST_F(LayerTreeHostImplTest, UpdatePageScaleFactorOnActiveTree) { page_scale_layer->transform_tree_index()); EXPECT_EQ(pending_tree_node->post_local_scale_factor, 2.f); - LOG(ERROR) << "2 ACTIVATE SYNC TREE"; host_impl_->ActivateSyncTree(); - LOG(ERROR) << "DONE 2 ACTIVATE SYNC TREE"; host_impl_->active_tree()->UpdateDrawProperties(); active_tree_node = host_impl_->active_tree()->property_trees()->transform_tree.Node( @@ -14839,5 +14912,194 @@ TEST_F(LayerTreeHostImplTest, TouchScrollOnAndroidScrollbar) { EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); } +TEST_F(CommitToPendingTreeLayerTreeHostImplTest, + CommitWithNoPaintWorkletLayerPainter) { + ASSERT_FALSE(host_impl_->GetPaintWorkletLayerPainterForTesting()); + host_impl_->CreatePendingTree(); + + // When there is no PaintWorkletLayerPainter registered, commits should finish + // immediately and move onto preparing tiles. + ASSERT_FALSE(did_prepare_tiles_); + host_impl_->CommitComplete(); + EXPECT_TRUE(did_prepare_tiles_); +} + +TEST_F(CommitToPendingTreeLayerTreeHostImplTest, CommitWithNoPaintWorklets) { + host_impl_->SetPaintWorkletLayerPainter( + std::make_unique<TestPaintWorkletLayerPainter>()); + host_impl_->CreatePendingTree(); + + // When there are no PaintWorklets in the committed display lists, commits + // should finish immediately and move onto preparing tiles. + ASSERT_FALSE(did_prepare_tiles_); + host_impl_->CommitComplete(); + EXPECT_TRUE(did_prepare_tiles_); +} + +TEST_F(CommitToPendingTreeLayerTreeHostImplTest, CommitWithDirtyPaintWorklets) { + auto painter_owned = std::make_unique<TestPaintWorkletLayerPainter>(); + TestPaintWorkletLayerPainter* painter = painter_owned.get(); + host_impl_->SetPaintWorkletLayerPainter(std::move(painter_owned)); + + // Setup the pending tree with a PictureLayerImpl that will contain + // PaintWorklets. + host_impl_->CreatePendingTree(); + std::unique_ptr<PictureLayerImpl> root_owned = PictureLayerImpl::Create( + host_impl_->pending_tree(), 1, Layer::LayerMaskType::NOT_MASK); + PictureLayerImpl* root = root_owned.get(); + host_impl_->pending_tree()->SetRootLayerForTesting(std::move(root_owned)); + + root->SetBounds(gfx::Size(100, 100)); + root->test_properties()->force_render_surface = true; + root->SetNeedsPushProperties(); + + // Add a PaintWorkletInput to the PictureLayerImpl. + scoped_refptr<RasterSource> raster_source_with_pws( + FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds())); + Region empty_invalidation; + root->UpdateRasterSource(raster_source_with_pws, &empty_invalidation, nullptr, + nullptr); + + host_impl_->pending_tree()->SetElementIdsForTesting(); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + + // Since we have dirty PaintWorklets, committing will not cause tile + // preparation to happen. Instead, it will be delayed until the callback + // passed to the PaintWorkletLayerPainter is called. + did_prepare_tiles_ = false; + host_impl_->CommitComplete(); + EXPECT_FALSE(did_prepare_tiles_); + + // Set up a result to have been 'painted'. + ASSERT_EQ(root->GetPaintWorkletRecordMap().size(), 1u); + scoped_refptr<PaintWorkletInput> input = + root->GetPaintWorkletRecordMap().begin()->first; + int worklet_id = input->WorkletId(); + + PaintWorkletJob painted_job(worklet_id, input); + sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>(); + painted_job.SetOutput(record); + + auto painted_job_vector = base::MakeRefCounted<PaintWorkletJobVector>(); + painted_job_vector->data.push_back(std::move(painted_job)); + PaintWorkletJobMap painted_job_map; + painted_job_map[worklet_id] = std::move(painted_job_vector); + + // Finally, 'paint' the content. This should unlock tile preparation and + // update the PictureLayerImpl's map. + std::move(painter->TakeDoneCallback()).Run(std::move(painted_job_map)); + EXPECT_EQ(root->GetPaintWorkletRecordMap().find(input)->second, record); + EXPECT_TRUE(did_prepare_tiles_); +} + +TEST_F(CommitToPendingTreeLayerTreeHostImplTest, + CommitWithNoDirtyPaintWorklets) { + host_impl_->SetPaintWorkletLayerPainter( + std::make_unique<TestPaintWorkletLayerPainter>()); + + host_impl_->CreatePendingTree(); + std::unique_ptr<PictureLayerImpl> root_owned = PictureLayerImpl::Create( + host_impl_->pending_tree(), 1, Layer::LayerMaskType::NOT_MASK); + PictureLayerImpl* root = root_owned.get(); + host_impl_->pending_tree()->SetRootLayerForTesting(std::move(root_owned)); + + root->SetBounds(gfx::Size(100, 100)); + root->test_properties()->force_render_surface = true; + root->SetNeedsPushProperties(); + + // Add some PaintWorklets. + scoped_refptr<RasterSource> raster_source_with_pws( + FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds())); + Region empty_invalidation; + root->UpdateRasterSource(raster_source_with_pws, &empty_invalidation, nullptr, + nullptr); + + host_impl_->pending_tree()->SetElementIdsForTesting(); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + + // Pretend that our worklets were already painted. + ASSERT_EQ(root->GetPaintWorkletRecordMap().size(), 1u); + root->SetPaintWorkletRecord(root->GetPaintWorkletRecordMap().begin()->first, + sk_make_sp<PaintRecord>()); + + // Since there are no dirty PaintWorklets, the commit should immediately + // prepare tiles. + ASSERT_FALSE(did_prepare_tiles_); + host_impl_->CommitComplete(); + EXPECT_TRUE(did_prepare_tiles_); +} + +class ForceActivateAfterPaintWorkletPaintLayerTreeHostImplTest + : public CommitToPendingTreeLayerTreeHostImplTest { + public: + void NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) override { + if (state == Scheduler::PaintWorkletState::IDLE) { + // Pretend a force activation happened. + host_impl_->ActivateSyncTree(); + ASSERT_FALSE(host_impl_->pending_tree()); + } + } +}; + +TEST_F(ForceActivateAfterPaintWorkletPaintLayerTreeHostImplTest, + ForceActivationAfterPaintWorkletsFinishPainting) { + auto painter_owned = std::make_unique<TestPaintWorkletLayerPainter>(); + TestPaintWorkletLayerPainter* painter = painter_owned.get(); + host_impl_->SetPaintWorkletLayerPainter(std::move(painter_owned)); + + // Setup the pending tree with a PictureLayerImpl that will contain + // PaintWorklets. + host_impl_->CreatePendingTree(); + std::unique_ptr<PictureLayerImpl> root_owned = PictureLayerImpl::Create( + host_impl_->pending_tree(), 1, Layer::LayerMaskType::NOT_MASK); + PictureLayerImpl* root = root_owned.get(); + host_impl_->pending_tree()->SetRootLayerForTesting(std::move(root_owned)); + + root->SetBounds(gfx::Size(100, 100)); + root->test_properties()->force_render_surface = true; + root->SetNeedsPushProperties(); + + // Add a PaintWorkletInput to the PictureLayerImpl. + scoped_refptr<RasterSource> raster_source_with_pws( + FakeRasterSource::CreateFilledWithPaintWorklet(root->bounds())); + Region empty_invalidation; + root->UpdateRasterSource(raster_source_with_pws, &empty_invalidation, nullptr, + nullptr); + + host_impl_->pending_tree()->SetElementIdsForTesting(); + host_impl_->pending_tree()->BuildPropertyTreesForTesting(); + + // Since we have dirty PaintWorklets, committing will not cause tile + // preparation to happen. Instead, it will be delayed until the callback + // passed to the PaintWorkletLayerPainter is called. + did_prepare_tiles_ = false; + host_impl_->CommitComplete(); + EXPECT_FALSE(did_prepare_tiles_); + + // Set up a result to have been 'painted'. + ASSERT_EQ(root->GetPaintWorkletRecordMap().size(), 1u); + scoped_refptr<PaintWorkletInput> input = + root->GetPaintWorkletRecordMap().begin()->first; + int worklet_id = input->WorkletId(); + + PaintWorkletJob painted_job(worklet_id, input); + sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>(); + painted_job.SetOutput(record); + + auto painted_job_vector = base::MakeRefCounted<PaintWorkletJobVector>(); + painted_job_vector->data.push_back(std::move(painted_job)); + PaintWorkletJobMap painted_job_map; + painted_job_map[worklet_id] = std::move(painted_job_vector); + + // Finally, 'paint' the content. The test class causes a forced activation + // during NotifyPaintWorkletStateChange. The PictureLayerImpl should still be + // updated, but since the tree was force activated there should be no tile + // preparation. + std::move(painter->TakeDoneCallback()).Run(std::move(painted_job_map)); + EXPECT_EQ(root->GetPaintWorkletRecordMap().find(input)->second, record); + EXPECT_FALSE(did_prepare_tiles_); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 92fd3570952..c6036f13f59 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -21,10 +21,10 @@ #include "cc/test/fake_content_layer_client.h" #include "cc/test/layer_tree_json_parser.h" #include "cc/test/layer_tree_test.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "cc/trees/layer_tree_impl.h" #include "components/viz/common/resources/single_release_callback.h" #include "components/viz/test/paths.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/sync_token.h" #include "testing/perf/perf_test.h" @@ -48,7 +48,7 @@ class LayerTreeHostPerfTest : public LayerTreeTest { measure_commit_cost_(false) { } - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -58,7 +58,7 @@ class LayerTreeHostPerfTest : public LayerTreeTest { bool synchronous_composite = !HasImplThread() && !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; - return std::make_unique<viz::TestLayerTreeFrameSink>( + return std::make_unique<TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, refresh_rate); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc index 3f0c28b4311..7d5ea2a2d08 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc @@ -14,7 +14,7 @@ #include "cc/paint/skia_paint_canvas.h" #include "cc/test/layer_tree_pixel_resource_test.h" #include "cc/test/pixel_comparator.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkSurface.h" @@ -71,7 +71,7 @@ class LayerTreeHostBlendingPixelTest public: LayerTreeHostBlendingPixelTest() : force_antialiasing_(false), force_blending_with_shaders_(false) { - pixel_comparator_.reset(new FuzzyPixelOffByOneComparator(true)); + pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true); } PixelResourceTestCase resource_type() const { @@ -82,7 +82,7 @@ class LayerTreeHostBlendingPixelTest } protected: - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -132,7 +132,7 @@ class LayerTreeHostBlendingPixelTest gfx::Size bounds = layer->bounds(); scoped_refptr<PictureImageLayer> mask = PictureImageLayer::Create(); mask->SetIsDrawable(true); - mask->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); mask->SetBounds(bounds); sk_sp<SkSurface> surface = @@ -213,10 +213,10 @@ class LayerTreeHostBlendingPixelTest InitializeFromTestCase(resource_type()); // Force shaders only applies to gl renderer. - if (renderer_type_ != RENDERER_GL && flags & kForceShaders) + if (renderer_type() != RENDERER_GL && flags & kForceShaders) return; - SCOPED_TRACE(TestTypeToString(renderer_type_)); + SCOPED_TRACE(TestTypeToString(renderer_type())); SCOPED_TRACE(SkBlendMode_Name(current_blend_mode())); scoped_refptr<SolidColorLayer> root = CreateSolidColorLayer( @@ -229,28 +229,23 @@ class LayerTreeHostBlendingPixelTest CreateBlendingColorLayers(kRootWidth, kRootHeight, background.get(), flags); - this->force_antialiasing_ = (flags & kUseAntialiasing); - this->force_blending_with_shaders_ = (flags & kForceShaders); + force_antialiasing_ = (flags & kUseAntialiasing); + force_blending_with_shaders_ = (flags & kForceShaders); - if ((flags & kUseAntialiasing) && (renderer_type_ == RENDERER_GL)) { + if ((renderer_type() == RENDERER_GL && force_antialiasing_) || + renderer_type() == RENDERER_SKIA_VK) { // Blending results might differ with one pixel. - // Don't allow large errors here, only off by ones. - // However, large error still has to be specified to satisfy - // the pixel comparator so set it equivalent to small errors. + float percentage_pixels_error = 35.f; + float percentage_pixels_small_error = 0.f; + float average_error_allowed_in_bad_pixels = 1.f; int large_error_allowed = 1; - int small_error_allowed = 1; - float percentage_pixels_small_error = 35.0f; - float percentage_pixels_error = 35.0f; - // The average error is still close to 1. - float average_error_allowed_in_bad_pixels = 1.4f; - - pixel_comparator_.reset( - new FuzzyPixelComparator(false, // discard_alpha - percentage_pixels_error, - percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, - large_error_allowed, - small_error_allowed)); + int small_error_allowed = 0; + + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( + false, // discard_alpha + percentage_pixels_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed); } RunPixelResourceTest(root, CreateBlendingWithRenderPassExpected( @@ -262,19 +257,18 @@ class LayerTreeHostBlendingPixelTest SkColor misc_opaque_color_ = 0xffc86464; }; -INSTANTIATE_TEST_SUITE_P( - B, - LayerTreeHostBlendingPixelTest, - ::testing::Combine(::testing::Values(SOFTWARE, ZERO_COPY, SKIA_GL), - ::testing::ValuesIn(kBlendModes))); - -using LayerTreeHostBlendingPixelTestNonSkia = LayerTreeHostBlendingPixelTest; +std::vector<PixelResourceTestCase> const kTestCases = { + {LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE}, + {LayerTreeTest::RENDERER_GL, ZERO_COPY}, + {LayerTreeTest::RENDERER_SKIA_GL, GPU}, +#if defined(ENABLE_CC_VULKAN_TESTS) + {LayerTreeTest::RENDERER_SKIA_VK, GPU}, +#endif +}; -// TODO(crbug.com/948128): Enable these tests for Skia. INSTANTIATE_TEST_SUITE_P(B, - LayerTreeHostBlendingPixelTestNonSkia, - ::testing::Combine(::testing::Values(SOFTWARE, - ZERO_COPY), + LayerTreeHostBlendingPixelTest, + ::testing::Combine(::testing::ValuesIn(kTestCases), ::testing::ValuesIn(kBlendModes))); TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithRoot) { @@ -304,7 +298,7 @@ TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithRoot) { RunPixelResourceTest(background, expected); } -TEST_P(LayerTreeHostBlendingPixelTestNonSkia, BlendingWithBackdropFilter) { +TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithBackdropFilter) { const int kRootWidth = 2; const int kRootHeight = 2; InitializeFromTestCase(resource_type()); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc index 165f1d8879c..3ac848ed527 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -4,6 +4,7 @@ #include <stddef.h> +#include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "cc/layers/picture_layer.h" #include "cc/layers/solid_color_layer.h" @@ -21,14 +22,6 @@ class LayerTreeHostFiltersPixelTest : public LayerTreePixelTest, public ::testing::WithParamInterface<LayerTreeTest::RendererType> { 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_; - } - RendererType renderer_type() { return GetParam(); } // Text string for graphics backend of the RendererType. Suitable for @@ -38,7 +31,9 @@ class LayerTreeHostFiltersPixelTest case RENDERER_GL: return "gl"; case RENDERER_SKIA_GL: - return "skia"; + return "skia_gl"; + case RENDERER_SKIA_VK: + return "skia_vk"; case RENDERER_SOFTWARE: return "sw"; } @@ -71,23 +66,20 @@ class LayerTreeHostFiltersPixelTest return background; } +}; - bool layer_transforms_should_scale_layer_contents_ = true; +LayerTreeTest::RendererType const kRendererTypes[] = { + LayerTreeTest::RENDERER_GL, + LayerTreeTest::RENDERER_SKIA_GL, + LayerTreeTest::RENDERER_SOFTWARE, +#if defined(ENABLE_CC_VULKAN_TESTS) + LayerTreeTest::RENDERER_SKIA_VK, +#endif }; INSTANTIATE_TEST_SUITE_P(, LayerTreeHostFiltersPixelTest, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL, - LayerTreeTest::RENDERER_SOFTWARE)); - -using LayerTreeHostFiltersPixelTestNonSkia = LayerTreeHostFiltersPixelTest; - -// TODO(crbug.com/948128): Enable these tests for Skia. -INSTANTIATE_TEST_SUITE_P(, - LayerTreeHostFiltersPixelTestNonSkia, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SOFTWARE)); + ::testing::ValuesIn(kRendererTypes)); using LayerTreeHostFiltersPixelTestGL = LayerTreeHostFiltersPixelTest; @@ -98,12 +90,19 @@ INSTANTIATE_TEST_SUITE_P(, using LayerTreeHostFiltersPixelTestGPU = LayerTreeHostFiltersPixelTest; +LayerTreeTest::RendererType const kRendererTypesGpu[] = { + LayerTreeTest::RENDERER_GL, + LayerTreeTest::RENDERER_SKIA_GL, +#if defined(ENABLE_CC_VULKAN_TESTS) + LayerTreeTest::RENDERER_SKIA_VK, +#endif +}; + INSTANTIATE_TEST_SUITE_P(, LayerTreeHostFiltersPixelTestGPU, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL)); + ::testing::ValuesIn(kRendererTypesGpu)); -TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRect) { +TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRect) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( gfx::Rect(200, 200), SK_ColorWHITE); @@ -139,11 +138,56 @@ TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRect) { small_error_allowed)); #endif - RunPixelTest(renderer_type(), background, - base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur.png"))); + RunPixelTest( + renderer_type(), background, + (renderer_type() == RENDERER_SOFTWARE) + ? base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_sw.png")) + : base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur.png"))); +} + +TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRadius) { + if (renderer_type() == RENDERER_SOFTWARE) { + // TODO(989238): Software renderer does not support/implement + // kClamp_TileMode. + return; + } + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(400, 400), SK_ColorRED); + scoped_refptr<SolidColorLayer> green = + CreateSolidColorLayer(gfx::Rect(200, 200, 200, 200), kCSSLime); + gfx::Rect blur_rect(100, 100, 200, 200); + scoped_refptr<SolidColorLayer> blur = + CreateSolidColorLayer(blur_rect, SkColorSetARGB(40, 10, 20, 200)); + background->AddChild(green); + background->AddChild(blur); + + FilterOperations filters; + filters.Append(FilterOperation::CreateBlurFilter( + 30.f, SkBlurImageFilter::kClamp_TileMode)); + blur->SetBackdropFilters(filters); + gfx::RRectF backdrop_filter_bounds(gfx::RectF(gfx::SizeF(blur->bounds())), 0); + blur->SetBackdropFilterBounds(backdrop_filter_bounds); + +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) + // Windows and ARM64 have 436 pixels off by 1: crbug.com/259915 + float percentage_pixels_large_error = 1.09f; // 436px / (200*200) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 1.f; + int large_error_allowed = 1; + int 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( + renderer_type(), background, + base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_radius_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix())); } -TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRounded) { +TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurRounded) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); @@ -180,17 +224,17 @@ TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRounded) { pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(false); #endif - RunPixelTest( - renderer_type(), background, - base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_rounded.png"))); + RunPixelTest(renderer_type(), background, + (renderer_type() == RENDERER_SOFTWARE) + ? base::FilePath(FILE_PATH_LITERAL( + "backdrop_filter_blur_rounded_sw.png")) + : base::FilePath(FILE_PATH_LITERAL( + "backdrop_filter_blur_rounded.png"))); } -TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurOutsets) { - if (renderer_type() == RENDERER_SKIA_GL -#if defined(ENABLE_CC_VULKAN_TESTS) - || renderer_type() == RENDERER_SKIA_VK -#endif - ) { +TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOutsets) { + if (renderer_type() == RENDERER_SKIA_GL || + renderer_type() == RENDERER_SKIA_VK) { // TODO(973696): Implement bounds clipping in skia_renderer. return; } @@ -233,6 +277,9 @@ TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurOutsets) { average_error_allowed_in_bad_pixels, large_error_allowed, small_error_allowed)); +#else + if (renderer_type() == RENDERER_SKIA_VK) + pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true); #endif RunPixelTest( @@ -380,9 +427,7 @@ class LayerTreeHostFiltersScaledPixelTest INSTANTIATE_TEST_SUITE_P(, LayerTreeHostFiltersScaledPixelTest, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL, - LayerTreeTest::RENDERER_SOFTWARE)); + ::testing::ValuesIn(kRendererTypes)); TEST_P(LayerTreeHostFiltersScaledPixelTest, StandardDpi) { RunPixelTestType(100, 1.f); @@ -393,8 +438,6 @@ TEST_P(LayerTreeHostFiltersScaledPixelTest, HiDpi) { } TEST_P(LayerTreeHostFiltersPixelTest, NullFilter) { - layer_transforms_should_scale_layer_contents_ = false; - scoped_refptr<SolidColorLayer> foreground = CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorGREEN); @@ -407,8 +450,6 @@ TEST_P(LayerTreeHostFiltersPixelTest, NullFilter) { } TEST_P(LayerTreeHostFiltersPixelTest, CroppedFilter) { - layer_transforms_should_scale_layer_contents_ = false; - scoped_refptr<SolidColorLayer> foreground = CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorGREEN); @@ -668,7 +709,7 @@ TEST_P(LayerTreeHostFiltersPixelTest, ImageRenderSurfaceScaled) { .InsertBeforeExtensionASCII(GetRendererSuffix())); } -TEST_P(LayerTreeHostFiltersPixelTestNonSkia, ZoomFilter) { +TEST_P(LayerTreeHostFiltersPixelTest, ZoomFilter) { scoped_refptr<SolidColorLayer> root = CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE); @@ -945,8 +986,7 @@ TEST_P(LayerTreeHostFiltersPixelTest, EnlargedTextureWithCropOffsetFilter) { base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_crop_offset.png"))); } -// TODO(crbug.com/948128): Enable this test for SkiaRenderer. -TEST_P(LayerTreeHostFiltersPixelTestNonSkia, BlurFilterWithClip) { +TEST_P(LayerTreeHostFiltersPixelTest, BlurFilterWithClip) { scoped_refptr<SolidColorLayer> child1 = CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE); scoped_refptr<SolidColorLayer> child2 = @@ -1010,32 +1050,96 @@ TEST_P(LayerTreeHostFiltersPixelTestGPU, FilterWithGiantCropRectNoClip) { base::FilePath(FILE_PATH_LITERAL("filter_with_giant_crop_rect.png"))); } -class BackdropFilterWithDeviceScaleFactorTest - : public LayerTreeHostFiltersPixelTest { +class BackdropFilterOffsetTest : public LayerTreeHostFiltersPixelTest { protected: - void RunPixelTestType(float device_scale_factor, - const base::FilePath& expected_result) { - device_scale_factor_ = device_scale_factor; - + void RunPixelTestType(int device_scale_factor) { scoped_refptr<Layer> root = CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE); - scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(100, 120), SK_ColorBLACK); root->AddChild(background); - scoped_refptr<SolidColorLayer> filtered = CreateSolidColorLayer( gfx::Rect(0, 100, 200, 100), SkColorSetA(SK_ColorGREEN, 127)); FilterOperations filters; + // TODO(989329): This test actually also tests how the OffsetPaintFilter + // handles the edge condition. Because the OffsetPaintFilter is pulling + // content from outside the filter region (just the bottom 200x100 square), + // it must create content for all but the bottom 20px of the filter rect. + // The GPU implementation of OffsetPaintFilter effectively clamps to the + // edge pixels and copies them into the top 80px of the image. The CPU + // implementation, on the other hand, pulls in transparent pixels for those + // 80px. The behavior is basically unspecified, though for blur filters the + // explicitly specified behavior is edgemode:duplicate, as seen in [1]. And + // the default for svg filters, including feOffset, is also duplicate. + // [1] https://drafts.fxtf.org/filter-effects-2/#backdrop-filter-operation + // [2] https://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElementEdgeModeAttribute filters.Append(FilterOperation::CreateReferenceFilter( sk_make_sp<OffsetPaintFilter>(0, 80, nullptr))); filtered->SetBackdropFilters(filters); filtered->ClearBackdropFilterBounds(); root->AddChild(filtered); - // This should appear as a grid of 4 100x100 squares which are: // BLACK WHITE - // DARK GREEN LIGHT GREEN + // DARK GREEN* LIGHT GREEN + // + // *except for software (see crbug.com/989329) which will be a + // dark-light-dark horizontal sandwich. + device_scale_factor_ = device_scale_factor; + + base::FilePath expected_result = + base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_.png")); + expected_result = expected_result.InsertBeforeExtensionASCII( + base::NumberToString(device_scale_factor) + "x"); + if (renderer_type() == RENDERER_SOFTWARE) { + expected_result = expected_result.InsertBeforeExtensionASCII("_sw"); + } + RunPixelTest(renderer_type(), std::move(root), expected_result); + } + + private: + // LayerTreePixelTest overrides + void SetupTree() override { + SetInitialDeviceScaleFactor(device_scale_factor_); + LayerTreeHostFiltersPixelTest::SetupTree(); + } + + float device_scale_factor_ = 1; +}; + +INSTANTIATE_TEST_SUITE_P(, + BackdropFilterOffsetTest, + ::testing::ValuesIn(kRendererTypes)); + +TEST_P(BackdropFilterOffsetTest, StandardDpi) { + RunPixelTestType(1.f); +} + +TEST_P(BackdropFilterOffsetTest, HiDpi) { + RunPixelTestType(2.f); +} + +class BackdropFilterInvertTest : public LayerTreeHostFiltersPixelTest { + protected: + void RunPixelTestType(int device_scale_factor) { + scoped_refptr<Layer> root = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN); + scoped_refptr<SolidColorLayer> filtered = + CreateSolidColorLayer(gfx::Rect(50, 50, 100, 100), SK_ColorTRANSPARENT); + FilterOperations filters; + filters.Append(FilterOperation::CreateInvertFilter(1.0)); + filtered->SetBackdropFilters(filters); + gfx::RRectF backdrop_filter_bounds( + gfx::RectF(gfx::SizeF(filtered->bounds())), 20); + filtered->SetBackdropFilterBounds(backdrop_filter_bounds); + root->AddChild(filtered); + device_scale_factor_ = device_scale_factor; + base::FilePath expected_result = + base::FilePath(FILE_PATH_LITERAL("invert_backdrop_filter_.png")); + expected_result = expected_result.InsertBeforeExtensionASCII( + base::NumberToString(device_scale_factor) + "x"); + if (renderer_type() == RENDERER_SOFTWARE) { + expected_result = expected_result.InsertBeforeExtensionASCII("_sw"); + } RunPixelTest(renderer_type(), std::move(root), expected_result); } @@ -1049,21 +1153,16 @@ class BackdropFilterWithDeviceScaleFactorTest float device_scale_factor_ = 1; }; -// TODO(973699): This test is broken in software_renderer. Re-enable this test -// when fixed. INSTANTIATE_TEST_SUITE_P(, - BackdropFilterWithDeviceScaleFactorTest, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL)); + BackdropFilterInvertTest, + ::testing::ValuesIn(kRendererTypes)); -TEST_P(BackdropFilterWithDeviceScaleFactorTest, StandardDpi) { - RunPixelTestType( - 1.f, base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png"))); +TEST_P(BackdropFilterInvertTest, StandardDpi) { + RunPixelTestType(1.f); } -TEST_P(BackdropFilterWithDeviceScaleFactorTest, HiDpi) { - RunPixelTestType( - 2.f, base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png"))); +TEST_P(BackdropFilterInvertTest, HiDpi) { + RunPixelTestType(2.f); } } // namespace diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index 9e125057e0d..1dcc664c201 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -18,7 +18,7 @@ #include "cc/test/layer_tree_pixel_resource_test.h" #include "cc/test/pixel_comparator.h" #include "cc/test/solid_color_content_layer_client.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "third_party/skia/include/core/SkImage.h" #if !defined(OS_ANDROID) @@ -26,9 +26,33 @@ namespace cc { namespace { +auto CombineWithLayerMaskTypes( + const std::vector<PixelResourceTestCase>& test_cases) { + return ::testing::Combine( + ::testing::ValuesIn(test_cases), + ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK)); +} + +// TODO(penghuang): Fix vulkan with one copy or zero copy +// https://crbug.com/979703 +std::vector<PixelResourceTestCase> const kTestCases = { + {LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE}, + {LayerTreeTest::RENDERER_GL, GPU}, + {LayerTreeTest::RENDERER_GL, ONE_COPY}, + {LayerTreeTest::RENDERER_GL, ZERO_COPY}, + {LayerTreeTest::RENDERER_SKIA_GL, GPU}, + {LayerTreeTest::RENDERER_SKIA_GL, ONE_COPY}, + {LayerTreeTest::RENDERER_SKIA_GL, ZERO_COPY}, +#if defined(ENABLE_CC_VULKAN_TESTS) + {LayerTreeTest::RENDERER_SKIA_VK, GPU}, +#endif +}; + using LayerTreeHostMasksPixelTest = ParameterizedPixelResourceTest; -INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P(LayerTreeHostMasksPixelTest); +INSTANTIATE_TEST_SUITE_P(PixelResourceTest, + LayerTreeHostMasksPixelTest, + CombineWithLayerMaskTypes(kTestCases)); class MaskContentLayerClient : public ContentLayerClient { public: @@ -89,17 +113,23 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) { mask->SetLayerMaskType(mask_type_); green->SetMaskLayer(mask.get()); + pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true); + RunPixelResourceTest(background, base::FilePath(FILE_PATH_LITERAL("mask_of_layer.png"))); } class LayerTreeHostLayerListPixelTest : public ParameterizedPixelResourceTest { + protected: void InitializeSettings(LayerTreeSettings* settings) override { settings->use_layer_lists = true; + settings->gpu_rasterization_forced = use_vulkan(); } }; -INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P(LayerTreeHostLayerListPixelTest); +INSTANTIATE_TEST_SUITE_P(PixelResourceTest, + LayerTreeHostLayerListPixelTest, + CombineWithLayerMaskTypes(kTestCases)); TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffect) { PropertyTrees property_trees; @@ -153,6 +183,9 @@ TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffect) { mask->SetTransformTreeIndex(1); root_layer->AddChild(mask); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); + RunPixelResourceTestWithLayerList( root_layer, base::FilePath(FILE_PATH_LITERAL("mask_with_effect.png")), &property_trees); @@ -418,18 +451,7 @@ TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffectNoContentToMask) { &property_trees); } -using LayerTreeHostLayerListPixelTestNonSkia = LayerTreeHostLayerListPixelTest; - -// TODO(crbug.com/948128): Enable this test for Skia. -INSTANTIATE_TEST_SUITE_P( - PixelResourceTest, - LayerTreeHostLayerListPixelTestNonSkia, - ::testing::Combine( - ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY), - ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK, - Layer::LayerMaskType::MULTI_TEXTURE_MASK))); - -TEST_P(LayerTreeHostLayerListPixelTestNonSkia, ScaledMaskWithEffect) { +TEST_P(LayerTreeHostLayerListPixelTest, ScaledMaskWithEffect) { PropertyTrees property_trees; scoped_refptr<Layer> root_layer; InitializeForLayerListMode(&root_layer, &property_trees); @@ -450,10 +472,12 @@ TEST_P(LayerTreeHostLayerListPixelTestNonSkia, ScaledMaskWithEffect) { // Scale the mask with a non-integral transform. This will trigger the // AA path in the renderer. - TransformNode transform; - transform.local = gfx::Transform(); - transform.local.Scale(1.5, 1.5); - property_trees.transform_tree.Insert(transform, 1); + TransformTree& transform_tree = property_trees.transform_tree; + auto& transform_node = + *transform_tree.Node(transform_tree.Insert(TransformNode(), 1)); + transform_node.source_node_id = transform_node.parent_id; + transform_node.local = gfx::Transform(); + transform_node.local.Scale(1.5, 1.5); scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); @@ -488,20 +512,13 @@ TEST_P(LayerTreeHostLayerListPixelTestNonSkia, ScaledMaskWithEffect) { mask->SetTransformTreeIndex(2); root_layer->AddChild(mask); - float percentage_pixels_large_error = 2.5f; // 2.5%, ~250px / (100*100) - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 100.0f; - int large_error_allowed = 256; - int small_error_allowed = 0; - pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); RunPixelResourceTestWithLayerList( root_layer, - base::FilePath(FILE_PATH_LITERAL("scaled_mask_with_effect.png")), + base::FilePath(FILE_PATH_LITERAL("scaled_mask_with_effect_.png")) + .InsertBeforeExtensionASCII(GetRendererSuffix()), &property_trees); } @@ -557,6 +574,9 @@ TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffectDifferentSize) { mask->SetTransformTreeIndex(1); root_layer->AddChild(mask); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); + // The mask is half the size of thing it's masking. In layer-list mode, // the mask is not automatically scaled to match the other layer. RunPixelResourceTestWithLayerList( @@ -631,6 +651,9 @@ TEST_P(LayerTreeHostLayerListPixelTest, ImageMaskWithEffect) { SkMatrix::I(), false); root_layer->AddChild(mask); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); + // The mask is half the size of thing it's masking. In layer-list mode, // the mask is not automatically scaled to match the other layer. RunPixelResourceTestWithLayerList( @@ -670,6 +693,9 @@ TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) { green->SetMaskLayer(mask.get()); background->AddChild(green); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); + RunPixelResourceTest( background, base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png"))); } @@ -697,6 +723,9 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfClippedLayer) { mask->SetLayerMaskType(mask_type_); green->SetMaskLayer(mask.get()); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); + RunPixelResourceTest( background, base::FilePath(FILE_PATH_LITERAL("mask_of_clipped_layer.png"))); @@ -719,6 +748,9 @@ TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayerNonExactTextureSize) { mask->set_fixed_tile_size(gfx::Size(173, 135)); green->SetMaskLayer(mask.get()); + pixel_comparator_ = + std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */); + RunPixelResourceTest(background, base::FilePath(FILE_PATH_LITERAL( "mask_with_non_exact_texture_size.png"))); @@ -817,20 +849,9 @@ class CircleContentLayerClient : public ContentLayerClient { using LayerTreeHostMasksForBackdropFiltersPixelTest = ParameterizedPixelResourceTest; -INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P( - LayerTreeHostMasksForBackdropFiltersPixelTest); - -using LayerTreeHostMasksForBackdropFiltersPixelTestNonSkia = - ParameterizedPixelResourceTest; - -// TODO(crbug.com/948128): Enable these tests for Skia. -INSTANTIATE_TEST_SUITE_P( - PixelResourceTest, - LayerTreeHostMasksForBackdropFiltersPixelTestNonSkia, - ::testing::Combine( - ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY), - ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK, - Layer::LayerMaskType::MULTI_TEXTURE_MASK))); +INSTANTIATE_TEST_SUITE_P(PixelResourceTest, + LayerTreeHostMasksForBackdropFiltersPixelTest, + CombineWithLayerMaskTypes(kTestCases)); TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest, MaskOfLayerWithBackdropFilter) { @@ -863,9 +884,24 @@ TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest, CHECK_EQ(Layer::LayerMaskType::SINGLE_TEXTURE_MASK, mask->mask_type()); base::FilePath image_name = - (test_case_ == GPU || test_case_ == SKIA_GL) + (raster_type() == GPU) ? base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter_gpu.png")) : base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter.png")); + + if (renderer_type() == RENDERER_SKIA_VK && raster_type() == GPU) { + // Vulkan with GPU raster has 4 pixels errors (the circle mask shape is + // slight different). + float percentage_pixels_large_error = 0.04f; // 4px / (100*100) + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 182.f; + int large_error_allowed = 182; + int small_error_allowed = 0; + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( + true /* discard_alpha */, percentage_pixels_large_error, + percentage_pixels_small_error, average_error_allowed_in_bad_pixels, + large_error_allowed, small_error_allowed); + } + RunPixelResourceTest(background, image_name); } @@ -962,22 +998,16 @@ class LayerTreeHostMaskAsBlendingPixelTest Layer::LayerMaskType::SINGLE_TEXTURE_MASK), use_antialiasing_(GetParam().flags & kUseAntialiasing), force_shaders_(GetParam().flags & kForceShaders) { - float percentage_pixels_small_error = 0.f; float percentage_pixels_error = 0.f; + float percentage_pixels_small_error = 0.f; float average_error_allowed_in_bad_pixels = 0.f; int large_error_allowed = 0; int small_error_allowed = 0; - if (use_antialiasing_) { - percentage_pixels_small_error = 0.9f; - percentage_pixels_error = 6.7f; - average_error_allowed_in_bad_pixels = 3.5f; - large_error_allowed = 15; - small_error_allowed = 1; - } else if (test_case_ != SOFTWARE) { - percentage_pixels_small_error = 0.9f; - percentage_pixels_error = 6.5f; - average_error_allowed_in_bad_pixels = 3.5f; - large_error_allowed = 15; + if (renderer_type() != RENDERER_SOFTWARE) { + percentage_pixels_error = 6.0f; + percentage_pixels_small_error = 2.f; + average_error_allowed_in_bad_pixels = 2.1f; + large_error_allowed = 11; small_error_allowed = 1; } else { #if defined(ARCH_CPU_ARM64) @@ -1061,7 +1091,7 @@ class LayerTreeHostMaskAsBlendingPixelTest } protected: - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -1080,13 +1110,21 @@ class LayerTreeHostMaskAsBlendingPixelTest bool force_shaders_; }; -// TODO(crbug.com/948128): Enable these tests for Skia. MaskTestConfig const kTestConfigs[] = { - MaskTestConfig{SOFTWARE, 0}, - MaskTestConfig{ZERO_COPY, 0}, - MaskTestConfig{ZERO_COPY, kUseAntialiasing}, - MaskTestConfig{ZERO_COPY, kForceShaders}, - MaskTestConfig{ZERO_COPY, kUseAntialiasing | kForceShaders}, + MaskTestConfig{{LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE}, 0}, + MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, 0}, + MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, kUseAntialiasing}, + MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, kForceShaders}, + MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, + kUseAntialiasing | kForceShaders}, + MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_GL, ZERO_COPY}, 0}, + MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_GL, ZERO_COPY}, + kUseAntialiasing}, +#if defined(ENABLE_CC_VULKAN_TESTS) + MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_VK, ZERO_COPY}, 0}, + MaskTestConfig{{LayerTreeTest::RENDERER_SKIA_VK, ZERO_COPY}, + kUseAntialiasing}, +#endif }; INSTANTIATE_TEST_SUITE_P(All, @@ -1229,7 +1267,7 @@ TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircle) { mask_isolation->AddChild(mask_layer); base::FilePath image_name = - (test_case_ == SOFTWARE) + (raster_type() == SOFTWARE) ? base::FilePath( FILE_PATH_LITERAL("mask_as_blending_rotated_circle.png")) : base::FilePath( @@ -1276,7 +1314,7 @@ TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircleUnderflow) { mask_isolation->AddChild(mask_layer); base::FilePath image_name = - (test_case_ == SOFTWARE) + (raster_type() == SOFTWARE) ? base::FilePath(FILE_PATH_LITERAL( "mask_as_blending_rotated_circle_underflow.png")) : base::FilePath(FILE_PATH_LITERAL( @@ -1284,7 +1322,7 @@ TEST_P(LayerTreeHostMaskAsBlendingPixelTest, RotatedClippedCircleUnderflow) { RunPixelResourceTest(root, image_name); } -TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTestNonSkia, +TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest, MaskOfLayerWithBackdropFilterAndBlend) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(128, 128), SK_ColorWHITE); @@ -1322,20 +1360,14 @@ TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTestNonSkia, mask->SetLayerMaskType(mask_type_); picture_horizontal->SetMaskLayer(mask.get()); - float percentage_pixels_large_error = 0.062f; // 0.062%, ~10px / (128*128) - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 200.0f; - int large_error_allowed = 256; - int small_error_allowed = 0; - pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed); - - RunPixelResourceTest(background, - base::FilePath(FILE_PATH_LITERAL( - "mask_of_backdrop_filter_and_blend.png"))); + base::FilePath result_path( + FILE_PATH_LITERAL("mask_of_backdrop_filter_and_blend_.png")); + if (raster_type() != GPU) { + result_path = result_path.InsertBeforeExtensionASCII("sw"); + } else { + result_path = result_path.InsertBeforeExtensionASCII(GetRendererSuffix()); + } + RunPixelResourceTest(background, result_path); } } // namespace diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc b/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc new file mode 100644 index 00000000000..ed011f43887 --- /dev/null +++ b/chromium/cc/trees/layer_tree_host_pixeltest_mirror.cc @@ -0,0 +1,83 @@ +// 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 "build/build_config.h" +#include "cc/layers/mirror_layer.h" +#include "cc/layers/solid_color_layer.h" +#include "cc/test/layer_tree_pixel_test.h" +#include "cc/test/pixel_comparator.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/transform_util.h" + +#if !defined(OS_ANDROID) + +namespace cc { +namespace { + +class LayerTreeHostMirrorPixelTest + : public LayerTreePixelTest, + public ::testing::WithParamInterface<LayerTreeTest::RendererType> { + protected: + RendererType renderer_type() { return GetParam(); } +}; + +const LayerTreeTest::RendererType kRendererTypes[] = { + LayerTreeTest::RENDERER_GL, + LayerTreeTest::RENDERER_SKIA_GL, + LayerTreeTest::RENDERER_SOFTWARE, +#if defined(ENABLE_CC_VULKAN_TESTS) + LayerTreeTest::RENDERER_SKIA_VK, +#endif +}; + +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostMirrorPixelTest, + ::testing::ValuesIn(kRendererTypes)); + +// Verifies that a mirror layer with a scale mirrors another layer correctly. +TEST_P(LayerTreeHostMirrorPixelTest, MirrorLayer) { + const float scale = 2.f; + gfx::Rect background_bounds(120, 180); + gfx::Rect mirrored_bounds(10, 10, 50, 50); + gfx::Rect mirror_bounds(10, 70, 100, 100); + + auto background = CreateSolidColorLayer(background_bounds, SK_ColorWHITE); + + auto mirrored_layer = CreateSolidColorLayerWithBorder( + mirrored_bounds, SK_ColorGREEN, 5, SK_ColorBLUE); + + auto mirror_layer = MirrorLayer::Create(mirrored_layer); + mirror_layer->SetIsDrawable(true); + mirror_layer->SetBounds(mirror_bounds.size()); + mirror_layer->SetPosition(gfx::PointF(mirror_bounds.origin())); + mirror_layer->SetTransform(gfx::GetScaleTransform(gfx::Point(), scale)); + background->AddChild(mirrored_layer); + background->AddChild(mirror_layer); + + if (renderer_type() == RENDERER_SOFTWARE) { + const bool discard_alpha = true; + const float error_pixels_percentage_limit = 3.f; + const float small_error_pixels_percentage_limit = 0.f; + const float avg_abs_error_limit = 65.f; + const int max_abs_error_limit = 120; + const int small_error_threshold = 0; + pixel_comparator_ = std::make_unique<FuzzyPixelComparator>( + discard_alpha, error_pixels_percentage_limit, + small_error_pixels_percentage_limit, avg_abs_error_limit, + max_abs_error_limit, small_error_threshold); + } + +#if defined(ENABLE_CC_VULKAN_TESTS) && defined(OS_LINUX) + if (renderer_type() == RENDERER_SKIA_VK) + pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true); +#endif + + RunPixelTest(renderer_type(), background, + base::FilePath(FILE_PATH_LITERAL("mirror_layer.png"))); +} + +} // namespace +} // namespace cc + +#endif // !defined(OS_ANDROID) diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc index 41660e1fb34..52317bb5fa2 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc @@ -10,11 +10,11 @@ #include "cc/test/fake_picture_layer_impl.h" #include "cc/test/layer_tree_pixel_test.h" #include "cc/test/solid_color_content_layer_client.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "cc/trees/layer_tree_impl.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_result.h" #include "components/viz/test/paths.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #if !defined(OS_ANDROID) @@ -29,9 +29,6 @@ enum ReadbackType { }; struct ReadbackTestConfig { - ReadbackTestConfig(LayerTreeTest::RendererType renderer_type_, - ReadbackType readback_type_) - : renderer_type(renderer_type_), readback_type(readback_type_) {} LayerTreeTest::RendererType renderer_type; ReadbackType readback_type; }; @@ -191,7 +188,11 @@ TEST_P(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayerWithChild) { base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png"))); } -TEST_P(LayerTreeHostReadbackPixelTest, ReadbackSubtreeSurroundsTargetLayer) { +using LayerTreeHostReadbackPixelTestMaybeVulkan = + LayerTreeHostReadbackPixelTest; + +TEST_P(LayerTreeHostReadbackPixelTestMaybeVulkan, + ReadbackSubtreeSurroundsTargetLayer) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE); @@ -379,7 +380,7 @@ TEST_P(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerOutsideViewport) { base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png"))); } -TEST_P(LayerTreeHostReadbackPixelTest, ReadbackNonRootOrFirstLayer) { +TEST_P(LayerTreeHostReadbackPixelTestMaybeVulkan, ReadbackNonRootOrFirstLayer) { // This test has 3 render passes with the copy request on the render pass in // the middle. This test caught an issue where copy requests on non-root // non-first render passes were being treated differently from the first @@ -415,15 +416,40 @@ TEST_P(LayerTreeHostReadbackPixelTest, MultipleReadbacksOnLayer) { base::FilePath(FILE_PATH_LITERAL("green.png"))); } -INSTANTIATE_TEST_SUITE_P( - , - LayerTreeHostReadbackPixelTest, - ::testing::Values( - ReadbackTestConfig(LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_GL, READBACK_TEXTURE), - ReadbackTestConfig(LayerTreeTest::RENDERER_GL, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE))); +// TODO(crbug.com/963446): Enable these tests for Skia Vulkan using texture +// readback. +ReadbackTestConfig const kTestConfigs[] = { + ReadbackTestConfig{LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP}, + ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_TEXTURE}, + ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_BITMAP}, + ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE}, + ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP}, +#if defined(ENABLE_CC_VULKAN_TESTS) + ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_VK, READBACK_BITMAP}, +#endif +}; + +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostReadbackPixelTest, + ::testing::ValuesIn(kTestConfigs)); + +// TODO(crbug.com/974283): These tests are crashing with vulkan when TSan or +// MSan are used. +ReadbackTestConfig const kMaybeVulkanTestConfigs[] = { + ReadbackTestConfig{LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP}, + ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_TEXTURE}, + ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_BITMAP}, + ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE}, + ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP}, +#if defined(ENABLE_CC_VULKAN_TESTS) && !defined(THREAD_SANITIZER) && \ + !defined(MEMORY_SANITIZER) + ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_VK, READBACK_BITMAP}, +#endif +}; + +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostReadbackPixelTestMaybeVulkan, + ::testing::ValuesIn(kMaybeVulkanTestConfigs)); class LayerTreeHostReadbackDeviceScalePixelTest : public LayerTreeHostReadbackPixelTest { @@ -434,11 +460,6 @@ class LayerTreeHostReadbackDeviceScalePixelTest green_client_(SK_ColorGREEN, gfx::Size(200, 200)), blue_client_(SK_ColorBLUE, gfx::Size(200, 200)) {} - void InitializeSettings(LayerTreeSettings* settings) override { - // Cause the device scale factor to be inherited by contents scales. - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { SetInitialDeviceScaleFactor(device_scale_factor_); LayerTreePixelTest::SetupTree(); @@ -510,15 +531,9 @@ TEST_P(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackNonRootLayerSubrect) { base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png"))); } -INSTANTIATE_TEST_SUITE_P( - , - LayerTreeHostReadbackDeviceScalePixelTest, - ::testing::Values( - ReadbackTestConfig(LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_GL, READBACK_TEXTURE), - ReadbackTestConfig(LayerTreeTest::RENDERER_GL, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE))); +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostReadbackDeviceScalePixelTest, + ::testing::ValuesIn(kTestConfigs)); class LayerTreeHostReadbackColorSpacePixelTest : public LayerTreeHostReadbackPixelTest { @@ -528,17 +543,17 @@ class LayerTreeHostReadbackColorSpacePixelTest output_color_space_ = gfx::ColorSpace::CreateDisplayP3D65(); } - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider) override { - std::unique_ptr<viz::TestLayerTreeFrameSink> frame_sink = + std::unique_ptr<TestLayerTreeFrameSink> frame_sink = LayerTreePixelTest::CreateLayerTreeFrameSink( renderer_settings, refresh_rate, compositor_context_provider, worker_context_provider); - frame_sink->SetDisplayColorSpace(output_color_space_, output_color_space_); + frame_sink->SetDisplayColorSpace(output_color_space_); return frame_sink; } @@ -556,15 +571,9 @@ TEST_P(LayerTreeHostReadbackColorSpacePixelTest, Readback) { base::FilePath(FILE_PATH_LITERAL("srgb_green_in_p3.png"))); } -INSTANTIATE_TEST_SUITE_P( - , - LayerTreeHostReadbackColorSpacePixelTest, - ::testing::Values( - ReadbackTestConfig(LayerTreeTest::RENDERER_SOFTWARE, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_GL, READBACK_TEXTURE), - ReadbackTestConfig(LayerTreeTest::RENDERER_GL, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP), - ReadbackTestConfig(LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE))); +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostReadbackColorSpacePixelTest, + ::testing::ValuesIn(kTestConfigs)); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc index 8955987ba23..b271f513c0c 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_scrollbars.cc @@ -13,8 +13,8 @@ #include "cc/paint/paint_flags.h" #include "cc/test/layer_tree_pixel_test.h" #include "cc/test/pixel_comparator.h" -#include "cc/test/test_in_process_context_provider.h" #include "cc/trees/layer_tree_impl.h" +#include "components/viz/test/test_in_process_context_provider.h" #include "gpu/command_buffer/client/gles2_interface.h" #if !defined(OS_ANDROID) @@ -30,10 +30,6 @@ class LayerTreeHostScrollbarsPixelTest RendererType renderer_type() { return GetParam(); } - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { SetInitialDeviceScaleFactor(device_scale_factor_); LayerTreePixelTest::SetupTree(); @@ -89,10 +85,17 @@ class PaintedScrollbar : public Scrollbar { gfx::Rect rect_; }; +LayerTreeTest::RendererType const kRendererTypes[] = { + LayerTreeTest::RENDERER_GL, + LayerTreeTest::RENDERER_SKIA_GL, +#if defined(ENABLE_CC_VULKAN_TESTS) + LayerTreeTest::RENDERER_SKIA_VK, +#endif +}; + INSTANTIATE_TEST_SUITE_P(, LayerTreeHostScrollbarsPixelTest, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL)); + ::testing::ValuesIn(kRendererTypes)); TEST_P(LayerTreeHostScrollbarsPixelTest, NoScale) { scoped_refptr<SolidColorLayer> background = @@ -167,9 +170,9 @@ TEST_P(LayerTreeHostScrollbarsPixelTest, MAYBE_HugeTransformScale) { layer->SetBounds(gfx::Size(10, 400)); background->AddChild(layer); - scoped_refptr<TestInProcessContextProvider> context( - new TestInProcessContextProvider(/*enable_oop_rasterization=*/false, - /*support_locking=*/false)); + auto context = base::MakeRefCounted<viz::TestInProcessContextProvider>( + /*enable_oop_rasterization=*/false, + /*support_locking=*/false); gpu::ContextResult result = context->BindToCurrentThread(); DCHECK_EQ(result, gpu::ContextResult::kSuccess); int max_texture_size = 0; @@ -189,7 +192,8 @@ TEST_P(LayerTreeHostScrollbarsPixelTest, MAYBE_HugeTransformScale) { scale_transform.Scale(scale, scale); layer->SetTransform(scale_transform); - if (renderer_type() == RENDERER_SKIA_GL) + if (renderer_type() == RENDERER_SKIA_GL || + renderer_type() == RENDERER_SKIA_VK) pixel_comparator_ = std::make_unique<FuzzyPixelOffByOneComparator>(true); RunPixelTest(renderer_type(), background, @@ -256,8 +260,7 @@ class PaintedOverlayScrollbar : public PaintedScrollbar { INSTANTIATE_TEST_SUITE_P(, LayerTreeHostOverlayScrollbarsPixelTest, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL)); + ::testing::ValuesIn(kRendererTypes)); // Simulate increasing the thickness of a painted overlay scrollbar. Ensure that // the scrollbar border remains crisp. diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc index fac28b34708..708eefad33a 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_synchronous.cc @@ -54,10 +54,17 @@ class LayerTreeHostSynchronousPixelTest bool use_zero_copy_ = false; }; +LayerTreeTest::RendererType const kRendererTypesGpu[] = { + LayerTreeTest::RENDERER_GL, + LayerTreeTest::RENDERER_SKIA_GL, +#if defined(ENABLE_CC_VULKAN_TESTS) + LayerTreeTest::RENDERER_SKIA_VK, +#endif +}; + INSTANTIATE_TEST_SUITE_P(, LayerTreeHostSynchronousPixelTest, - ::testing::Values(LayerTreeTest::RENDERER_GL, - LayerTreeTest::RENDERER_SKIA_GL)); + ::testing::ValuesIn(kRendererTypesGpu)); TEST_P(LayerTreeHostSynchronousPixelTest, OneContentLayerZeroCopy) { use_zero_copy_ = true; diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc index ad22f279d6a..0da4873f16f 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -11,8 +11,8 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/paint_op_buffer.h" #include "cc/test/layer_tree_pixel_test.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "components/viz/common/frame_sinks/copy_output_request.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #include "gpu/command_buffer/client/raster_interface.h" #if !defined(OS_ANDROID) @@ -172,15 +172,21 @@ class LayerTreeHostTilesTestPartialInvalidation scoped_refptr<PictureLayer> picture_layer_; }; -INSTANTIATE_TEST_SUITE_P( - , - LayerTreeHostTilesTestPartialInvalidation, - ::testing::Values(TilesTestConfig{LayerTreeTest::RENDERER_SOFTWARE, BITMAP}, - TilesTestConfig{LayerTreeTest::RENDERER_GL, ONE_COPY}, - TilesTestConfig{LayerTreeTest::RENDERER_GL, GPU}, - TilesTestConfig{LayerTreeTest::RENDERER_SKIA_GL, - ONE_COPY}, - TilesTestConfig{LayerTreeTest::RENDERER_SKIA_GL, GPU})); +std::vector<TilesTestConfig> const kTestCases = { + {LayerTreeTest::RENDERER_SOFTWARE, BITMAP}, + {LayerTreeTest::RENDERER_GL, ONE_COPY}, + {LayerTreeTest::RENDERER_GL, GPU}, + {LayerTreeTest::RENDERER_SKIA_GL, ONE_COPY}, + {LayerTreeTest::RENDERER_SKIA_GL, GPU}, +#if defined(ENABLE_CC_VULKAN_TESTS) + {LayerTreeTest::RENDERER_SKIA_VK, ONE_COPY}, + {LayerTreeTest::RENDERER_SKIA_VK, GPU}, +#endif +}; + +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostTilesTestPartialInvalidation, + ::testing::ValuesIn(kTestCases)); TEST_P(LayerTreeHostTilesTestPartialInvalidation, PartialRaster) { use_partial_raster_ = true; @@ -195,15 +201,20 @@ TEST_P(LayerTreeHostTilesTestPartialInvalidation, FullRaster) { base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png"))); } +std::vector<TilesTestConfig> const kTestCasesMultiThread = { + {LayerTreeTest::RENDERER_GL, ONE_COPY}, + {LayerTreeTest::RENDERER_SKIA_GL, ONE_COPY}, +#if defined(ENABLE_CC_VULKAN_TESTS) + {LayerTreeTest::RENDERER_SKIA_VK, ONE_COPY}, +#endif +}; + using LayerTreeHostTilesTestPartialInvalidationMultiThread = LayerTreeHostTilesTestPartialInvalidation; -INSTANTIATE_TEST_SUITE_P( - , - LayerTreeHostTilesTestPartialInvalidationMultiThread, - ::testing::Values(TilesTestConfig{LayerTreeTest::RENDERER_GL, ONE_COPY}, - TilesTestConfig{LayerTreeTest::RENDERER_SKIA_GL, - ONE_COPY})); +INSTANTIATE_TEST_SUITE_P(, + LayerTreeHostTilesTestPartialInvalidationMultiThread, + ::testing::ValuesIn(kTestCasesMultiThread)); // Flaky on Linux TSAN. https://crbug.com/707711 #if defined(OS_LINUX) && defined(THREAD_SANITIZER) @@ -227,6 +238,7 @@ TEST_P(LayerTreeHostTilesTestPartialInvalidationMultiThread, FullRaster) { using LayerTreeHostTilesTestPartialInvalidationLowBitDepth = LayerTreeHostTilesTestPartialInvalidation; +// TODO(crbug.com/963446): Enable these tests for Vulkan. INSTANTIATE_TEST_SUITE_P( , LayerTreeHostTilesTestPartialInvalidationLowBitDepth, diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index f10dada2a20..023517fc874 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -47,6 +47,7 @@ #include "cc/test/push_properties_counting_layer_impl.h" #include "cc/test/render_pass_test_utils.h" #include "cc/test/skia_common.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "cc/trees/clip_node.h" #include "cc/trees/effect_node.h" #include "cc/trees/frame_rate_counter.h" @@ -69,7 +70,6 @@ #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_output_surface.h" #include "components/viz/test/test_gles2_interface.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/khronos/GLES2/gl2.h" @@ -501,7 +501,7 @@ SINGLE_THREAD_TEST_F(LayerTreeHostTestReadyToDrawVisibility); class LayerTreeHostContextCacheTest : public LayerTreeHostTest { public: - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -2468,10 +2468,6 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterDeviceSizeChanged); class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest { public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { root_layer_ = Layer::Create(); root_layer_->SetBounds(gfx::Size(10, 20)); @@ -2519,10 +2515,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestNoExtraCommitFromInvalidate); class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate : public LayerTreeHostTest { public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { root_layer_ = Layer::Create(); root_layer_->SetBounds(gfx::Size(10, 20)); @@ -2578,10 +2570,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F( class LayerTreeHostTestDeviceScaleFactorChange : public LayerTreeHostTest { public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { root_layer_ = Layer::Create(); root_layer_->SetBounds(gfx::Size(10, 20)); @@ -4006,25 +3994,25 @@ class LayerTreeHostTestLCDChange : public LayerTreeHostTest { // The first draw. EXPECT_EQ(1, num_tiles_rastered_); EXPECT_TRUE(can_use_lcd_text); - EXPECT_TRUE(root_layer->RasterSourceUsesLCDTextForTesting()); + EXPECT_TRUE(root_layer->can_use_lcd_text()); break; case 1: // Nothing changed on the layer. EXPECT_EQ(1, num_tiles_rastered_); EXPECT_TRUE(can_use_lcd_text); - EXPECT_TRUE(root_layer->RasterSourceUsesLCDTextForTesting()); + EXPECT_TRUE(root_layer->can_use_lcd_text()); break; case 2: // LCD text was disabled; it should be re-rastered with LCD text off. EXPECT_EQ(2, num_tiles_rastered_); EXPECT_FALSE(can_use_lcd_text); - EXPECT_FALSE(root_layer->RasterSourceUsesLCDTextForTesting()); + EXPECT_FALSE(root_layer->can_use_lcd_text()); break; case 3: // LCD text was enabled, but it's sticky and stays off. EXPECT_EQ(2, num_tiles_rastered_); EXPECT_TRUE(can_use_lcd_text); - EXPECT_FALSE(root_layer->RasterSourceUsesLCDTextForTesting()); + EXPECT_FALSE(root_layer->can_use_lcd_text()); break; } } @@ -4106,7 +4094,7 @@ class LayerTreeHostTestAbortedCommitDoesntStall : public LayerTreeHostTest { int commit_complete_count_; }; -class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { +class OnDrawLayerTreeFrameSink : public TestLayerTreeFrameSink { public: OnDrawLayerTreeFrameSink( scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -4148,7 +4136,7 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor settings->using_synchronous_renderer_compositor = true; } - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -4406,37 +4394,36 @@ class LayerTreeHostTestLayersPushProperties : public LayerTreeHostTest { // The scrollbar layer always needs to be pushed. if (root_->layer_tree_host()) { - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( root_->layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); } if (child2_->layer_tree_host()) { - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( child2_->layer_tree_host()->LayersThatShouldPushProperties(), child2_.get())); } if (leaf_always_pushing_layer_->layer_tree_host()) { leaf_always_pushing_layer_->SetNeedsPushProperties(); - EXPECT_TRUE( - base::ContainsKey(leaf_always_pushing_layer_->layer_tree_host() - ->LayersThatShouldPushProperties(), - leaf_always_pushing_layer_.get())); + EXPECT_TRUE(base::Contains(leaf_always_pushing_layer_->layer_tree_host() + ->LayersThatShouldPushProperties(), + leaf_always_pushing_layer_.get())); } // child_ and grandchild_ don't persist their need to push properties. if (child_->layer_tree_host()) { - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( child_->layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); } if (grandchild_->layer_tree_host()) { - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( grandchild_->layer_tree_host()->LayersThatShouldPushProperties(), grandchild_.get())); } if (other_root_->layer_tree_host()) { - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( other_root_->layer_tree_host()->LayersThatShouldPushProperties(), other_root_.get())); } @@ -4789,9 +4776,9 @@ class LayerTreeHostTestPropertyChangesDuringUpdateArePushed scrollbar_layer_->SetBounds(gfx::Size(30, 30)); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - scrollbar_layer_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + scrollbar_layer_.get())); layer_tree_host()->SetNeedsCommit(); scrollbar_layer_->reset_push_properties_count(); @@ -4835,9 +4822,9 @@ class LayerTreeHostTestSetDrawableCausesCommit : public LayerTreeHostTest { // avoid causing a second commit to be scheduled. If a property change // is made during this, however, it needs to be pushed in the upcoming // commit. - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EXPECT_EQ(0, root_->NumDescendantsThatDrawContent()); root_->reset_push_properties_count(); @@ -4846,18 +4833,18 @@ class LayerTreeHostTestSetDrawableCausesCommit : public LayerTreeHostTest { EXPECT_EQ(1, root_->NumDescendantsThatDrawContent()); EXPECT_EQ(0u, root_->push_properties_count()); EXPECT_EQ(0u, child_->push_properties_count()); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); break; } case 2: EXPECT_EQ(1u, root_->push_properties_count()); EXPECT_EQ(1u, child_->push_properties_count()); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EndTest(); break; @@ -4925,19 +4912,19 @@ class LayerTreeHostTestPushPropertiesAddingToTreeRequiresPush case 0: // All layers will need push properties as we set their layer tree host layer_tree_host()->SetRootLayer(root_); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); break; case 1: EndTest(); @@ -4958,81 +4945,81 @@ class LayerTreeHostTestPushPropertiesRemovingChildStopsRecursion layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); grandchild1_->RemoveFromParent(); grandchild1_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); child_->AddChild(grandchild1_); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); // grandchild2_ will still need a push properties. grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); // grandchild3_ does not need a push properties, so recursing should // no longer be needed. grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EndTest(); break; @@ -5057,35 +5044,35 @@ class LayerTreeHostTestPushPropertiesRemovingChildStopsRecursionWithPersistence layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); // grandchild2_ will still need a push properties. grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); // grandchild3_ does not need a push properties, so recursing should // no longer be needed. grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EndTest(); break; @@ -5106,19 +5093,19 @@ class LayerTreeHostTestPushPropertiesSetPropertiesWhileOutsideTree layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); // Change grandchildren while their parent is not in the tree. child_->RemoveFromParent(); @@ -5126,39 +5113,39 @@ class LayerTreeHostTestPushPropertiesSetPropertiesWhileOutsideTree grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); root_->AddChild(child_); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); grandchild3_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); EndTest(); @@ -5180,55 +5167,55 @@ class LayerTreeHostTestPushPropertiesSetPropertyInParentThenChild layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); child_->SetPosition(gfx::PointF(1.f, 1.f)); grandchild1_->SetPosition(gfx::PointF(1.f, 1.f)); grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); child_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); EndTest(); @@ -5250,55 +5237,55 @@ class LayerTreeHostTestPushPropertiesSetPropertyInChildThenParent layer_tree_host()->SetRootLayer(root_); break; case 1: - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); grandchild1_->SetPosition(gfx::PointF(1.f, 1.f)); grandchild2_->SetPosition(gfx::PointF(1.f, 1.f)); child_->SetPosition(gfx::PointF(1.f, 1.f)); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild1_.get())); - EXPECT_TRUE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild2_.get())); - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - grandchild3_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild1_.get())); + EXPECT_TRUE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild2_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + grandchild3_.get())); grandchild1_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); grandchild2_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), child_.get())); child_->RemoveFromParent(); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( layer_tree_host()->LayersThatShouldPushProperties(), root_.get())); EndTest(); @@ -5460,9 +5447,9 @@ class LayerTreeHostTestPushHiddenLayer : public LayerTreeHostTest { switch (layer_tree_host()->SourceFrameNumber()) { case 1: // The layer type used does not need to push properties every frame. - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - child_layer_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + child_layer_.get())); // Change the bounds of the child layer, but make it skipped // by CalculateDrawProperties. @@ -5471,9 +5458,9 @@ class LayerTreeHostTestPushHiddenLayer : public LayerTreeHostTest { break; case 2: // The bounds of the child layer were pushed to the impl side. - EXPECT_FALSE(base::ContainsKey( - layer_tree_host()->LayersThatShouldPushProperties(), - child_layer_.get())); + EXPECT_FALSE( + base::Contains(layer_tree_host()->LayersThatShouldPushProperties(), + child_layer_.get())); EndTest(); break; @@ -6410,7 +6397,7 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestEmptyLayerGpuRasterization); class LayerTreeHostWithGpuRasterizationTest : public LayerTreeHostTest { protected: - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> ignored_compositor_context_provider, @@ -6939,7 +6926,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise settings->use_zero_copy = true; } - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -6949,7 +6936,7 @@ class LayerTreeHostTestSynchronousCompositeSwapPromise bool synchronous_composite = !HasImplThread() && !layer_tree_host()->GetSettings().single_thread_proxy_scheduler; - return std::make_unique<viz::TestLayerTreeFrameSink>( + return std::make_unique<TestLayerTreeFrameSink>( compositor_context_provider, std::move(worker_context_provider), gpu_memory_buffer_manager(), renderer_settings, ImplThreadTaskRunner(), synchronous_composite, disable_display_vsync, refresh_rate); @@ -7807,7 +7794,7 @@ class LayerTreeTestPageScaleFlags : public LayerTreeTest { layer->IsAffectedByPageScale() ? this->affected_by_page_scale_ : this->not_affected_by_page_scale_; - EXPECT_TRUE(base::ContainsValue(list, layer->id())); + EXPECT_TRUE(base::Contains(list, layer->id())); }); EndTest(); @@ -8179,7 +8166,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSubmitFrameMetadata); class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { protected: - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -8248,33 +8235,6 @@ class LayerTreeHostTestSubmitFrameResources : public LayerTreeHostTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSubmitFrameResources); -// Ensure that content_source_id is propagated to the frame's metadata. -class LayerTreeHostTestContentSourceId : public LayerTreeHostTest { - protected: - void BeginTest() override { - layer_tree_host()->SetContentSourceId(5); - PostSetNeedsCommitToMainThread(); - } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame_data, - DrawResult draw_result) override { - EXPECT_EQ(DRAW_SUCCESS, draw_result); - EXPECT_EQ(5U, host_impl->active_tree()->content_source_id()); - return draw_result; - } - - void DisplayReceivedCompositorFrameOnThread( - const viz::CompositorFrame& frame) override { - EXPECT_EQ(5U, frame.metadata.content_source_id); - EndTest(); - } - - void AfterTest() override {} -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContentSourceId); - class LayerTreeHostTestBeginFrameAcks : public LayerTreeHostTest { protected: void BeginTest() override { PostSetNeedsCommitToMainThread(); } diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc index 47a27fd67c8..d5a0aa983c0 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc @@ -369,6 +369,15 @@ class LayerTreeHostAnimationTestAddKeyframeModelWithTimingFunction if (host_impl->active_tree()->source_frame_number() != 0) return; + // The impl thread may start a second frame before the test finishes. This + // can lead to a race as if the main thread has committed a new sync tree + // the impl thread can now delete the KeyframeModel as the animation only + // lasts a single frame and no longer affects either tree. Only test the + // first frame the animation shows up for. + if (!first_animation_frame_) + return; + first_animation_frame_ = false; + scoped_refptr<AnimationTimeline> timeline_impl = GetImplAnimationHost(host_impl)->GetTimelineById(timeline_id_); scoped_refptr<SingleKeyframeEffectAnimation> animation_child_impl = @@ -397,6 +406,7 @@ class LayerTreeHostAnimationTestAddKeyframeModelWithTimingFunction FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> picture_; + bool first_animation_frame_ = true; }; SINGLE_AND_MULTI_THREAD_TEST_F( @@ -712,13 +722,6 @@ class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations animation_child_->set_animation_delegate(this); } - void InitializeSettings(LayerTreeSettings* settings) override { - // Make sure that drawing many times doesn't cause a checkerboarded - // animation to start so we avoid flake in this test. - settings->timeout_and_draw_when_animation_checkerboards = false; - LayerTreeHostAnimationTest::InitializeSettings(settings); - } - void BeginTest() override { prevented_draw_ = 0; started_times_ = 0; diff --git a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc index 75f69a3cbef..1b6d70d9527 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_capture_content.cc @@ -12,44 +12,42 @@ namespace cc { namespace { -class FakeTextHolder : public TextHolder { +class FakeTextHolder { public: - FakeTextHolder(const std::string& text, const gfx::Rect& rect) - : text_(text), rect_(rect) {} + FakeTextHolder(const std::string& text, const gfx::Rect& rect, NodeId node_id) + : text_(text), rect_(rect), node_id_(node_id) {} std::string text() const { return text_; } gfx::Rect rect() const { return rect_; } - - protected: - ~FakeTextHolder() override = default; + NodeId node_id() const { return node_id_; } private: std::string text_; gfx::Rect rect_; + NodeId node_id_; }; class FakeCaptureContentLayerClient : public FakeContentLayerClient { public: - void addTextHolder(scoped_refptr<FakeTextHolder> holder) { + void addTextHolder(const FakeTextHolder& holder) { holders_.push_back(holder); } scoped_refptr<DisplayItemList> PaintContentsToDisplayList( PaintingControlSetting painting_control) override { auto display_list = base::MakeRefCounted<DisplayItemList>(); - for (auto holder : holders_) { + for (auto& holder : holders_) { display_list->StartPaint(); display_list->push<DrawTextBlobOp>( - SkTextBlob::MakeFromString(holder->text().data(), SkFont()), - holder->rect().x(), holder->rect().y(), PaintFlags(), - NodeHolder(holder)); - display_list->EndPaintOfUnpaired(holder->rect()); + SkTextBlob::MakeFromString(holder.text().data(), SkFont()), + holder.rect().x(), holder.rect().y(), holder.node_id(), PaintFlags()); + display_list->EndPaintOfUnpaired(holder.rect()); } display_list->Finalize(); return display_list; } private: - std::vector<scoped_refptr<FakeTextHolder>> holders_; + std::vector<const FakeTextHolder> holders_; }; // These tests are for LayerTreeHost::CaptureContent(). @@ -58,8 +56,7 @@ class LayerTreeHostCaptureContentTest : public LayerTreeTest { ~LayerTreeHostCaptureContentTest() override = default; protected: - LayerTreeHostCaptureContentTest() - : device_bounds_(10, 10), weak_factory_(this) {} + LayerTreeHostCaptureContentTest() : device_bounds_(10, 10) {} void BeginTest() override { PostSetNeedsCommitToMainThread(); } @@ -78,17 +75,13 @@ class LayerTreeHostCaptureContentTest : public LayerTreeTest { layer_tree_host()->SetViewportVisibleRect(gfx::Rect(device_bounds_)); } - void VerifyCapturedContent( - std::vector<scoped_refptr<FakeTextHolder>>* expected_result) { + void VerifyCapturedContent(std::vector<FakeTextHolder>* expected_result) { EXPECT_EQ(expected_result->size(), captured_content_.size()); size_t expected_left_result = expected_result->size(); - for (auto c : captured_content_) { - EXPECT_EQ(c.type, NodeHolder::Type::kTextHolder); + for (auto& c : captured_content_) { for (auto it = expected_result->begin(); it != expected_result->end(); ++it) { - if (it->get() == c.text_holder.get()) { - EXPECT_EQ(static_cast<FakeTextHolder*>(c.text_holder.get())->text(), - it->get()->text()); + if (it->node_id() == c) { expected_result->erase(it); break; } @@ -114,23 +107,23 @@ class LayerTreeHostCaptureContentTest : public LayerTreeTest { } scoped_refptr<FakePictureLayer> root_picture_layer_; - std::vector<NodeHolder> captured_content_; + std::vector<NodeId> captured_content_; const gfx::Size device_bounds_; - base::WeakPtrFactory<LayerTreeHostCaptureContentTest> weak_factory_; + base::WeakPtrFactory<LayerTreeHostCaptureContentTest> weak_factory_{this}; }; class LayerTreeHostCaptureContentTestBasic : public LayerTreeHostCaptureContentTest { protected: void SetupTextHolders(const gfx::Rect& rect1, const gfx::Rect& rect2) { - text_holder_1_ = base::MakeRefCounted<FakeTextHolder>("Text1", rect1); - client_.addTextHolder(text_holder_1_); - text_holder_2_ = base::MakeRefCounted<FakeTextHolder>("Text2", rect2); - client_.addTextHolder(text_holder_2_); + text_holder_1_ = std::make_unique<FakeTextHolder>("Text1", rect1, 1); + client_.addTextHolder(*text_holder_1_); + text_holder_2_ = std::make_unique<FakeTextHolder>("Text2", rect2, 2); + client_.addTextHolder(*text_holder_2_); } - scoped_refptr<FakeTextHolder> text_holder_1_; - scoped_refptr<FakeTextHolder> text_holder_2_; + std::unique_ptr<FakeTextHolder> text_holder_1_; + std::unique_ptr<FakeTextHolder> text_holder_2_; }; // Test that one DrawTextBlobOp is on-screen, another isn't. @@ -144,8 +137,8 @@ class LayerTreeHostCaptureContentTestOneVisible } void AfterTest() override { - std::vector<scoped_refptr<FakeTextHolder>> expected_result; - expected_result.push_back(text_holder_1_); + std::vector<FakeTextHolder> expected_result; + expected_result.push_back(*text_holder_1_); VerifyCapturedContent(&expected_result); } }; @@ -163,9 +156,9 @@ class LayerTreeHostCaptureContentTestTwoVisible } void AfterTest() override { - std::vector<scoped_refptr<FakeTextHolder>> expected_result; - expected_result.push_back(text_holder_1_); - expected_result.push_back(text_holder_2_); + std::vector<FakeTextHolder> expected_result; + expected_result.push_back(*text_holder_1_); + expected_result.push_back(*text_holder_2_); VerifyCapturedContent(&expected_result); } }; @@ -208,11 +201,11 @@ class LayerTreeHostCaptureContentTestTwoLayers void SetupSecondaryPictureLayer(const gfx::Size& size) { // Add text to layer. text_holder_21_ = - base::MakeRefCounted<FakeTextHolder>("Text21", gfx::Rect(0, 0, 10, 5)); - client2_.addTextHolder(text_holder_21_); + std::make_unique<FakeTextHolder>("Text21", gfx::Rect(0, 0, 10, 5), 21); + client2_.addTextHolder(*text_holder_21_); text_holder_22_ = - base::MakeRefCounted<FakeTextHolder>("Text22", gfx::Rect(0, 5, 10, 5)); - client2_.addTextHolder(text_holder_22_); + std::make_unique<FakeTextHolder>("Text22", gfx::Rect(0, 5, 10, 5), 22); + client2_.addTextHolder(*text_holder_22_); client2_.set_bounds(size); // Create layer. @@ -223,8 +216,8 @@ class LayerTreeHostCaptureContentTestTwoLayers } scoped_refptr<FakePictureLayer> picture_layer; - scoped_refptr<FakeTextHolder> text_holder_21_; - scoped_refptr<FakeTextHolder> text_holder_22_; + std::unique_ptr<FakeTextHolder> text_holder_21_; + std::unique_ptr<FakeTextHolder> text_holder_22_; FakeCaptureContentLayerClient client2_; }; @@ -237,9 +230,9 @@ class LayerTreeHostCaptureContentTestOneLayerVisible } void AfterTest() override { - std::vector<scoped_refptr<FakeTextHolder>> expected_result; - expected_result.push_back(text_holder_1_); - expected_result.push_back(text_holder_2_); + std::vector<FakeTextHolder> expected_result; + expected_result.push_back(*text_holder_1_); + expected_result.push_back(*text_holder_2_); VerifyCapturedContent(&expected_result); } }; @@ -256,10 +249,10 @@ class LayerTreeHostCaptureContentTestTwoLayersVisible } void AfterTest() override { - std::vector<scoped_refptr<FakeTextHolder>> expected_result; - expected_result.push_back(text_holder_1_); - expected_result.push_back(text_holder_2_); - expected_result.push_back(text_holder_21_); + std::vector<FakeTextHolder> expected_result; + expected_result.push_back(*text_holder_1_); + expected_result.push_back(*text_holder_2_); + expected_result.push_back(*text_holder_21_); VerifyCapturedContent(&expected_result); } }; @@ -274,10 +267,10 @@ class LayerTreeHostCaptureContentTestTwoLayersVisibleAndTransparent void AfterTest() override { // All 3 TextHolders are returned. - std::vector<scoped_refptr<FakeTextHolder>> expected_result; - expected_result.push_back(text_holder_1_); - expected_result.push_back(text_holder_2_); - expected_result.push_back(text_holder_21_); + std::vector<FakeTextHolder> expected_result; + expected_result.push_back(*text_holder_1_); + expected_result.push_back(*text_holder_2_); + expected_result.push_back(*text_holder_21_); VerifyCapturedContent(&expected_result); } }; @@ -295,11 +288,11 @@ class LayerTreeHostCaptureContentTestUpperLayerPartialOverlay } void AfterTest() override { - std::vector<scoped_refptr<FakeTextHolder>> expected_result; - expected_result.push_back(text_holder_1_); - expected_result.push_back(text_holder_2_); - expected_result.push_back(text_holder_21_); - expected_result.push_back(text_holder_22_); + std::vector<FakeTextHolder> expected_result; + expected_result.push_back(*text_holder_1_); + expected_result.push_back(*text_holder_2_); + expected_result.push_back(*text_holder_21_); + expected_result.push_back(*text_holder_22_); VerifyCapturedContent(&expected_result); } }; diff --git a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc index 5ad5e2a6977..dfdecdb3ef6 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_checkerimaging.cc @@ -7,11 +7,11 @@ #include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" #include "cc/test/skia_common.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "cc/trees/layer_tree_impl.h" #include "components/ukm/test_ukm_recorder.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/fake_external_begin_frame_source.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" namespace cc { namespace { diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index a06f23dc57f..b658d15f6fe 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -29,6 +29,7 @@ #include "cc/test/fake_video_frame_provider.h" #include "cc/test/layer_tree_test.h" #include "cc/test/render_pass_test_utils.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" @@ -38,7 +39,6 @@ #include "components/viz/test/fake_output_surface.h" #include "components/viz/test/test_context_provider.h" #include "components/viz/test/test_gles2_interface.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #include "components/viz/test/test_shared_bitmap_manager.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/raster_interface.h" @@ -85,7 +85,7 @@ class LayerTreeHostContextTest : public LayerTreeTest { gl_ = nullptr; } - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -1682,7 +1682,7 @@ SINGLE_AND_MULTI_THREAD_TEST_F(TileResourceFreedIfLostWhileExported); class SoftwareTileResourceFreedIfLostWhileExported : public LayerTreeTest { protected: - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, diff --git a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc index 5bac6e88f25..3f335e7d9d5 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_copyrequest.cc @@ -13,6 +13,7 @@ #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_picture_layer.h" #include "cc/test/layer_tree_test.h" +#include "cc/test/test_layer_tree_frame_sink.h" #include "cc/trees/layer_tree_impl.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_result.h" @@ -20,7 +21,6 @@ #include "components/viz/test/fake_output_surface.h" #include "components/viz/test/fake_skia_output_surface.h" #include "components/viz/test/test_gles2_interface.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" #include "gpu/GLES2/gl2extchromium.h" namespace cc { @@ -514,7 +514,7 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest client_.set_bounds(root_->bounds()); } - std::unique_ptr<viz::TestLayerTreeFrameSink> CreateLayerTreeFrameSink( + std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink( const viz::RendererSettings& renderer_settings, double refresh_rate, scoped_refptr<viz::ContextProvider> compositor_context_provider, @@ -589,7 +589,7 @@ class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest viz::RenderPassId parent_render_pass_id = 0; viz::RenderPassId copy_layer_render_pass_id = 0; - viz::TestLayerTreeFrameSink* frame_sink_ = nullptr; + TestLayerTreeFrameSink* frame_sink_ = nullptr; bool did_swap_ = false; FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> root_; @@ -671,10 +671,6 @@ TEST_P(LayerTreeHostCopyRequestTestClippedOut, Test) { class LayerTreeHostCopyRequestTestScaledLayer : public LayerTreeHostCopyRequestTest { protected: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void SetupTree() override { root_ = Layer::Create(); root_->SetBounds(gfx::Size(20, 20)); diff --git a/chromium/cc/trees/layer_tree_host_unittest_masks.cc b/chromium/cc/trees/layer_tree_host_unittest_masks.cc index b0a8b0c9ac2..3870aba8671 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_masks.cc @@ -50,7 +50,7 @@ class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin gfx::Size mask_size(100, 100); mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); mask_layer_id_ = mask_layer->id(); layer_tree_host()->SetRootLayer(root); @@ -89,21 +89,9 @@ class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin render_pass_quad->rect); EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), rect_in_target_space.ToString()); - if (host_impl->settings().enable_mask_tiling) { - PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( - host_impl->active_tree()->LayerById(mask_layer_id_)); - gfx::SizeF texture_size( - mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); - EXPECT_EQ( - gfx::RectF(50.f / texture_size.width(), 50.f / texture_size.height(), - 50.f / texture_size.width(), 50.f / texture_size.height()) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(50.f, 50.f, 50.f, 50.f), 1.f / 100.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(50.f, 50.f, 50.f, 50.f), 1.f / 100.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); EndTest(); return draw_result; } @@ -114,27 +102,8 @@ class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin FakeContentLayerClient client_; }; -class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Untiled - : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Untiled); - -class LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Tiled - : public LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin_Tiled); + LayerTreeTestMaskLayerForSurfaceWithContentRectNotAtOrigin); class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { protected: @@ -191,7 +160,7 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { gfx::Size mask_size(50, 50); mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); mask_layer_id_ = mask_layer->id(); layer_tree_host()->SetRootLayer(root); @@ -226,21 +195,9 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { // coords in the mask are scaled by 10/50 and 20/50. // The surface is clipped to (20,10) so the mask texture coords are offset // by 20/50 and 10/50 - if (host_impl->settings().enable_mask_tiling) { - PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( - host_impl->active_tree()->LayerById(mask_layer_id_)); - gfx::SizeF texture_size( - mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); - EXPECT_EQ( - gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), - 10.f / texture_size.width(), 20.f / texture_size.height()) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); EndTest(); return draw_result; } @@ -251,27 +208,8 @@ class LayerTreeTestMaskLayerForSurfaceWithClippedLayer : public LayerTreeTest { FakeContentLayerClient client_; }; -class LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Untiled - : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Untiled); - -class LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Tiled - : public LayerTreeTestMaskLayerForSurfaceWithClippedLayer { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskLayerForSurfaceWithClippedLayer_Tiled); + LayerTreeTestMaskLayerForSurfaceWithClippedLayer); class LayerTreeTestMaskLayerForSurfaceWithDifferentScale : public LayerTreeTest { @@ -333,7 +271,7 @@ class LayerTreeTestMaskLayerForSurfaceWithDifferentScale gfx::Size mask_size(50, 50); mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); // Setting will change transform on mask layer will make it not adjust // raster scale, which will remain 1. This means the mask_layer and render // surface will have a scale of 2 during draw time. @@ -378,21 +316,9 @@ class LayerTreeTestMaskLayerForSurfaceWithDifferentScale // coords in the mask are scaled by 10/50 and 20/50. // The surface is clipped to (20,10) so the mask texture coords are offset // by 20/50 and 10/50 - if (host_impl->settings().enable_mask_tiling) { - PictureLayerImpl* mask_layer_impl = static_cast<PictureLayerImpl*>( - host_impl->active_tree()->LayerById(mask_layer_id_)); - gfx::SizeF texture_size( - mask_layer_impl->CalculateTileSize(mask_layer_impl->bounds())); - EXPECT_EQ( - gfx::RectF(20.f / texture_size.width(), 10.f / texture_size.height(), - 10.f / texture_size.width(), 20.f / texture_size.height()) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) - .ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } + EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f), 1.f / 50.f) + .ToString(), + render_pass_quad->mask_uv_rect.ToString()); EndTest(); return draw_result; } @@ -403,27 +329,8 @@ class LayerTreeTestMaskLayerForSurfaceWithDifferentScale FakeContentLayerClient client_; }; -class LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Untiled - : public LayerTreeTestMaskLayerForSurfaceWithDifferentScale { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Untiled); - -class LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Tiled - : public LayerTreeTestMaskLayerForSurfaceWithDifferentScale { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskLayerForSurfaceWithDifferentScale_Tiled); + LayerTreeTestMaskLayerForSurfaceWithDifferentScale); class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { protected: @@ -471,7 +378,7 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { content_layer->SetBounds(scaling_layer_size); mask_layer->SetBounds(scaling_layer_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); + mask_layer->SetLayerMaskType(Layer::LayerMaskType::SINGLE_TEXTURE_MASK); layer_tree_host()->SetRootLayer(root); LayerTreeTest::SetupTree(); @@ -495,34 +402,25 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { root_pass->quad_list.front()->material); const viz::RenderPassDrawQuad* render_pass_quad = viz::RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); + gfx::Rect rect_in_target_space = MathUtil::MapEnclosingClippedRect( + render_pass_quad->shared_quad_state->quad_to_target_transform, + render_pass_quad->rect); switch (host_impl->active_tree()->source_frame_number()) { case 0: // Check that the tree scaling is correctly taken into account for the // mask, that should fully map onto the quad. EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - EXPECT_EQ( - gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } + rect_in_target_space.ToString()); + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); break; case 1: // Applying a DSF should change the render surface size, but won't // affect which part of the mask is used. EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - EXPECT_EQ( - gfx::RectF(0.f, 0.f, 100.f / 128.f, 100.f / 128.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } + rect_in_target_space.ToString()); + EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), + render_pass_quad->mask_uv_rect.ToString()); EndTest(); break; } @@ -544,27 +442,7 @@ class LayerTreeTestMaskLayerWithScaling : public LayerTreeTest { FakeContentLayerClient client_; }; -class LayerTreeTestMaskLayerWithScaling_Untiled - : public LayerTreeTestMaskLayerWithScaling { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - settings->layer_transforms_should_scale_layer_contents = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling_Untiled); - -class LayerTreeTestMaskLayerWithScaling_Tiled - : public LayerTreeTestMaskLayerWithScaling { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - settings->layer_transforms_should_scale_layer_contents = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling_Tiled); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskLayerWithScaling); class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { protected: @@ -642,26 +520,7 @@ class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { FakeContentLayerClient client_; }; -class LayerTreeTestMaskWithNonExactTextureSize_Untiled - : public LayerTreeTestMaskWithNonExactTextureSize { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMaskWithNonExactTextureSize_Untiled); - -class LayerTreeTestMaskWithNonExactTextureSize_Tiled - : public LayerTreeTestMaskWithNonExactTextureSize { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskWithNonExactTextureSize_Tiled); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMaskWithNonExactTextureSize); } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_unittest_picture.cc b/chromium/cc/trees/layer_tree_host_unittest_picture.cc index feea9ffa2cb..8c103dfc473 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_picture.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_picture.cc @@ -439,10 +439,6 @@ class LayerTreeHostPictureTestRSLLMembershipWithScale client_.set_bounds(picture_->bounds()); } - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void BeginTest() override { frame_ = 0; draws_in_frame_ = 0; @@ -607,10 +603,6 @@ class LayerTreeHostPictureTestForceRecalculateScales client_.set_bounds(size); } - void InitializeSettings(LayerTreeSettings* settings) override { - settings->layer_transforms_should_scale_layer_contents = true; - } - void BeginTest() override { PostSetNeedsCommitToMainThread(); } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index 667f67d8909..8ebf210f056 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -25,6 +25,8 @@ #include "cc/test/layer_tree_test.h" #include "cc/test/test_task_graph_runner.h" #include "cc/test/test_ukm_recorder_factory.h" +#include "cc/trees/clip_node.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/scroll_node.h" @@ -977,7 +979,7 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { Layer* scroll_layer = layer_tree_host()->outer_viewport_scroll_layer(); switch (layer_tree_host()->SourceFrameNumber()) { case 0: - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(), scroll_layer)); break; @@ -985,7 +987,7 @@ class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest { // Even if this layer doesn't need push properties, it should // still pick up scrolls that happen on the active layer during // commit. - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(), scroll_layer)); break; @@ -1155,8 +1157,7 @@ class LayerTreeHostScrollTestScrollZeroMaxScrollOffset ScrollNode* scroll_node = scroll_tree.Node(scroll_layer->scroll_tree_index()); InputHandler::ScrollStatus status = - impl->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::TOUCHSCREEN, - scroll_tree, scroll_node); + impl->TryScroll(gfx::PointF(0.0f, 1.0f), scroll_tree, scroll_node); switch (impl->active_tree()->source_frame_number()) { case 0: EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); @@ -1206,26 +1207,17 @@ class LayerTreeHostScrollTestScrollNonDrawnLayer } void DrawLayersOnThread(LayerTreeHostImpl* impl) override { - LayerImpl* scroll_layer = impl->OuterViewportScrollLayer(); - - ScrollTree& scroll_tree = - impl->active_tree()->property_trees()->scroll_tree; - ScrollNode* scroll_node = - scroll_tree.Node(scroll_layer->scroll_tree_index()); - // Verify that the scroll layer's scroll offset is taken into account when // checking whether the screen space point is inside the non-fast // scrollable region. - - InputHandler::ScrollStatus status = - impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, - scroll_tree, scroll_node); + InputHandler::ScrollStatus status = impl->ScrollBegin( + BeginState(gfx::Point(0, 0)).get(), InputHandler::TOUCHSCREEN); EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, status.main_thread_scrolling_reasons); - status = impl->TryScroll(gfx::PointF(21.f, 21.f), InputHandler::TOUCHSCREEN, - scroll_tree, scroll_node); + status = impl->ScrollBegin(BeginState(gfx::Point(21, 21)).get(), + InputHandler::TOUCHSCREEN); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); @@ -1265,14 +1257,13 @@ class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent scroll_tree.Node(outer_scroll_layer->scroll_tree_index()); InputHandler::ScrollStatus status = - impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, - scroll_tree, inner_scroll_node); + impl->TryScroll(gfx::PointF(1.f, 1.f), scroll_tree, inner_scroll_node); EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, status.main_thread_scrolling_reasons); - status = impl->TryScroll(gfx::PointF(1.f, 1.f), InputHandler::TOUCHSCREEN, - scroll_tree, outer_scroll_node); + status = + impl->TryScroll(gfx::PointF(1.f, 1.f), scroll_tree, outer_scroll_node); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); @@ -1321,12 +1312,18 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient { } } - void DeliverInputForBeginFrame() override { + void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override { if (!task_runner_->BelongsToCurrentThread()) { ADD_FAILURE() << "DeliverInputForBeginFrame called on wrong thread"; } } + void DeliverInputForHighLatencyMode() override { + if (!task_runner_->BelongsToCurrentThread()) { + ADD_FAILURE() << "DeliverInputForHighLatencyMode called on wrong thread"; + } + } + private: base::SingleThreadTaskRunner* task_runner_; bool* received_stop_flinging_; @@ -1825,7 +1822,8 @@ class MockInputHandlerClient : public InputHandlerClient { float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor) override {} - void DeliverInputForBeginFrame() override {} + void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override {} + void DeliverInputForHighLatencyMode() override {} }; // This is a regression test, see crbug.com/639046. @@ -2233,5 +2231,189 @@ class LayerTreeHostScrollTestImplSideInvalidation MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplSideInvalidation); +// Version of LayerTreeHostScrollTest that uses layer lists which means the +// property trees and layer list are explicitly specified instead of running +// the cc property tree builder. +class LayerListLayerTreeHostScrollTest : public LayerTreeHostScrollTest { + public: + // The id of the root property tree nodes. + static constexpr int kRootNodeId = 1; + + LayerListLayerTreeHostScrollTest() { SetUseLayerList(); } + + void SetupTree() override { + // Setup the root transform, effect, clip, and scroll property tree nodes. + auto& transform_tree = layer_tree_host()->property_trees()->transform_tree; + auto& root_transform_node = *transform_tree.Node( + transform_tree.Insert(TransformNode(), kRealRootNodeId)); + DCHECK_EQ(root_transform_node.id, kRootNodeId); + root_transform_node.source_node_id = root_transform_node.parent_id; + transform_tree.set_needs_update(true); + + auto& effect_tree = layer_tree_host()->property_trees()->effect_tree; + auto& root_effect_node = + *effect_tree.Node(effect_tree.Insert(EffectNode(), kRealRootNodeId)); + DCHECK_EQ(root_effect_node.id, kRootNodeId); + root_effect_node.stable_id = 1; + root_effect_node.transform_id = kRealRootNodeId; + root_effect_node.clip_id = kRealRootNodeId; + root_effect_node.render_surface_reason = RenderSurfaceReason::kRoot; + effect_tree.set_needs_update(true); + + auto& clip_tree = layer_tree_host()->property_trees()->clip_tree; + auto& root_clip_node = + *clip_tree.Node(clip_tree.Insert(ClipNode(), kRealRootNodeId)); + DCHECK_EQ(root_clip_node.id, kRootNodeId); + root_clip_node.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP; + root_clip_node.clip = gfx::RectF(gfx::SizeF(800, 600)); + root_clip_node.transform_id = kRealRootNodeId; + clip_tree.set_needs_update(true); + + auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; + auto& root_scroll_node = + *scroll_tree.Node(scroll_tree.Insert(ScrollNode(), kRealRootNodeId)); + DCHECK_EQ(root_scroll_node.id, kRootNodeId); + root_scroll_node.transform_id = kRealRootNodeId; + scroll_tree.set_needs_update(true); + + // Setup the root Layer which should be used to attach the layer list. + root_ = Layer::Create(); + root_->SetBounds(gfx::Size(800, 600)); + root_->SetIsDrawable(true); + root_->SetHitTestable(true); + root_->SetTransformTreeIndex(root_transform_node.id); + root_->SetEffectTreeIndex(root_effect_node.id); + root_->SetScrollTreeIndex(root_scroll_node.id); + root_->SetClipTreeIndex(root_clip_node.id); + layer_tree_host()->SetRootLayer(root_); + + layer_tree_host()->SetViewportSizeAndScale(gfx::Size(800, 600), 1.f, + viz::LocalSurfaceIdAllocation()); + + layer_tree_host()->property_trees()->sequence_number = + root_->property_tree_sequence_number(); + + root_->SetNeedsCommit(); + } + + Layer* root() const { return root_.get(); } + + private: + // The compositor is hard-coded to use 0 for the root nodes (always non-null). + static constexpr int kRealRootNodeId = 0; + + scoped_refptr<Layer> root_; +}; + +class NonScrollingNonFastScrollableRegion + : public LayerListLayerTreeHostScrollTest { + public: + // Setup 3 Layers: + // 1) bottom_ which has a non-fast region in the bottom-right. + // 2) middle_scrollable_ which is scrollable. + // 3) top_ which has a non-fast region in the top-left and is offset by + // |middle_scrollable_|'s scroll offset. + void SetupTree() override { + LayerListLayerTreeHostScrollTest::SetupTree(); + + fake_content_layer_client_.set_bounds(root()->bounds()); + + std::vector<scoped_refptr<Layer>> layer_list; + + bottom_ = FakePictureLayer::Create(&fake_content_layer_client_); + bottom_->SetElementId(LayerIdToElementIdForTesting(bottom_->id())); + bottom_->SetBounds(gfx::Size(100, 100)); + bottom_->SetNonFastScrollableRegion(Region(gfx::Rect(50, 50, 50, 50))); + bottom_->SetHitTestable(true); + bottom_->SetTransformTreeIndex(kRootNodeId); + bottom_->SetEffectTreeIndex(kRootNodeId); + bottom_->SetScrollTreeIndex(kRootNodeId); + bottom_->SetClipTreeIndex(kRootNodeId); + bottom_->set_property_tree_sequence_number( + root()->property_tree_sequence_number()); + layer_list.push_back(bottom_); + + auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; + auto& scroll_node = + *scroll_tree.Node(scroll_tree.Insert(ScrollNode(), kRootNodeId)); + scroll_node.transform_id = kRootNodeId; + middle_scrollable_ = FakePictureLayer::Create(&fake_content_layer_client_); + middle_scrollable_->SetElementId( + LayerIdToElementIdForTesting(middle_scrollable_->id())); + scroll_node.element_id = middle_scrollable_->element_id(); + scroll_node.scrollable = true; + scroll_node.bounds = gfx::Size(100, 200); + scroll_node.container_bounds = gfx::Size(100, 100); + middle_scrollable_->SetBounds(gfx::Size(100, 100)); + middle_scrollable_->SetIsDrawable(true); + middle_scrollable_->SetScrollable(gfx::Size(100, 200)); + middle_scrollable_->SetHitTestable(true); + middle_scrollable_->SetTransformTreeIndex(kRootNodeId); + middle_scrollable_->SetEffectTreeIndex(kRootNodeId); + middle_scrollable_->SetScrollTreeIndex(scroll_node.id); + middle_scrollable_->SetClipTreeIndex(kRootNodeId); + middle_scrollable_->set_property_tree_sequence_number( + root()->property_tree_sequence_number()); + layer_list.push_back(middle_scrollable_); + + top_ = FakePictureLayer::Create(&fake_content_layer_client_); + top_->SetElementId(LayerIdToElementIdForTesting(top_->id())); + top_->SetBounds(gfx::Size(100, 100)); + top_->SetNonFastScrollableRegion(Region(gfx::Rect(0, 0, 50, 50))); + top_->SetHitTestable(true); + top_->SetTransformTreeIndex(kRootNodeId); + top_->SetEffectTreeIndex(kRootNodeId); + top_->SetScrollTreeIndex(scroll_node.id); + top_->SetClipTreeIndex(kRootNodeId); + top_->set_property_tree_sequence_number( + root()->property_tree_sequence_number()); + + layer_list.push_back(top_); + root()->SetChildLayerList(std::move(layer_list)); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void CommitCompleteOnThread(LayerTreeHostImpl* impl) override { + // The top-left hit should immediately hit the top layer's non-fast region + // which forces main-thread scrolling. + auto top_left_status = impl->ScrollBegin( + BeginState(gfx::Point(20, 20)).get(), InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, top_left_status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + top_left_status.main_thread_scrolling_reasons); + + // The top-right hit should hit the top layer but not the non-fast region so + // the scroll should continue to scroll on the impl. + InputHandler::ScrollStatus top_right_status = impl->ScrollBegin( + BeginState(gfx::Point(80, 20)).get(), InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, top_right_status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, + top_right_status.main_thread_scrolling_reasons); + + // The bottom-right should hit the bottom layer's non-fast region. Though + // the middle layer is a composited scroller and is hit first, we cannot do + // a fast scroll because an ancestor on the scroll chain has hit a non-fast + // region. + InputHandler::ScrollStatus bottom_right_status = impl->ScrollBegin( + BeginState(gfx::Point(80, 80)).get(), InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, bottom_right_status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion, + bottom_right_status.main_thread_scrolling_reasons); + + EndTest(); + } + + void AfterTest() override {} + + private: + FakeContentLayerClient fake_content_layer_client_; + scoped_refptr<Layer> bottom_; + scoped_refptr<Layer> middle_scrollable_; + scoped_refptr<Layer> top_; +}; + +SINGLE_THREAD_TEST_F(NonScrollingNonFastScrollableRegion); + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index fbd783c9798..fe75edcd991 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -89,7 +89,6 @@ LayerTreeImpl::LayerTreeImpl( external_page_scale_factor_(1.f), device_scale_factor_(1.f), painted_device_scale_factor_(1.f), - content_source_id_(0), elastic_overscroll_(elastic_overscroll), layers_(new OwnedLayerImplList), needs_update_draw_properties_(true), @@ -484,8 +483,6 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->SetRasterColorSpace(raster_color_space_id_, raster_color_space_); target_tree->elastic_overscroll()->PushPendingToActive(); - target_tree->set_content_source_id(content_source_id()); - target_tree->set_painted_device_scale_factor(painted_device_scale_factor()); target_tree->SetDeviceScaleFactor(device_scale_factor()); target_tree->SetDeviceViewportSize(device_viewport_size_); @@ -1290,7 +1287,6 @@ bool LayerTreeImpl::UpdateDrawProperties( InnerViewportScrollLayer(), OuterViewportScrollLayer(), elastic_overscroll()->Current(IsActiveTree()), OverscrollElasticityElementId(), max_texture_size(), - settings().layer_transforms_should_scale_layer_contents, &render_surface_list_, &property_trees_, PageScaleTransformNode()); LayerTreeHostCommon::CalculateDrawProperties(&inputs); if (const char* client_name = GetClientNameForMetrics()) { @@ -1456,6 +1452,18 @@ LayerImpl* LayerTreeImpl::LayerById(int id) const { return iter != layer_id_map_.end() ? iter->second : nullptr; } +// TODO(masonfreed): If this shows up on profiles, this could use +// a layer_element_map_ approach similar to LayerById(). +LayerImpl* LayerTreeImpl::LayerByElementId(ElementId element_id) const { + auto it = std::find_if(layer_list_.rbegin(), layer_list_.rend(), + [&element_id](LayerImpl* layer_impl) { + return layer_impl->element_id() == element_id; + }); + if (it == layer_list_.rend()) + return nullptr; + return *it; +} + LayerImpl* LayerTreeImpl::ScrollableLayerByElementId( ElementId element_id) const { auto iter = element_id_to_scrollable_layer_.find(element_id); @@ -1482,7 +1490,7 @@ void LayerTreeImpl::AddLayerShouldPushProperties(LayerImpl* layer) { DCHECK(!IsActiveTree()) << "The active tree does not push layer properties"; // TODO(crbug.com/303943): PictureLayerImpls always push properties so should // not go into this set or we'd push them twice. - DCHECK(!base::ContainsValue(picture_layers_, layer)); + DCHECK(!base::Contains(picture_layers_, layer)); layers_that_should_push_properties_.insert(layer); } @@ -1503,7 +1511,7 @@ void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) { // These manage ownership of the LayerImpl. void LayerTreeImpl::AddLayer(std::unique_ptr<LayerImpl> layer) { - DCHECK(!base::ContainsValue(*layers_, layer)); + DCHECK(!base::Contains(*layers_, layer)); DCHECK(layer); layers_->push_back(std::move(layer)); set_needs_update_draw_properties(); @@ -1862,7 +1870,7 @@ void LayerTreeImpl::ProcessUIResourceRequestQueue() { } void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) { - DCHECK(!base::ContainsValue(picture_layers_, layer)); + DCHECK(!base::Contains(picture_layers_, layer)); picture_layers_.push_back(layer); } @@ -1870,6 +1878,23 @@ void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) { auto it = std::find(picture_layers_.begin(), picture_layers_.end(), layer); DCHECK(it != picture_layers_.end()); picture_layers_.erase(it); + + // Make sure that |picture_layers_with_paint_worklets_| doesn't get left with + // dead layers. They should already have been removed (via calling + // NotifyLayerHasPaintWorkletsChanged) before the layer was unregistered. + DCHECK(!picture_layers_with_paint_worklets_.contains(layer)); +} + +void LayerTreeImpl::NotifyLayerHasPaintWorkletsChanged(PictureLayerImpl* layer, + bool has_worklets) { + if (has_worklets) { + auto insert_pair = picture_layers_with_paint_worklets_.insert(layer); + DCHECK(insert_pair.second); + } else { + auto it = picture_layers_with_paint_worklets_.find(layer); + DCHECK(it != picture_layers_with_paint_worklets_.end()); + picture_layers_with_paint_worklets_.erase(it); + } } void LayerTreeImpl::RegisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer) { @@ -2179,8 +2204,10 @@ LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint( struct FindTouchEventLayerFunctor { bool operator()(LayerImpl* layer) const { + if (!layer->has_touch_action_regions()) + return false; return PointHitsRegion(screen_space_point, layer->ScreenSpaceTransform(), - layer->touch_action_region().region(), layer); + layer->GetAllTouchActionRegions(), layer); } const gfx::PointF screen_space_point; }; @@ -2220,6 +2247,28 @@ LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInWheelEventHandlerRegion( func); } +std::vector<const LayerImpl*> +LayerTreeImpl::FindLayersHitByPointInNonFastScrollableRegion( + const gfx::PointF& screen_space_point) { + std::vector<const LayerImpl*> layers; + if (layer_list_.empty()) + return layers; + if (!UpdateDrawProperties()) + return layers; + for (const auto* layer : *this) { + if (layer->non_fast_scrollable_region().IsEmpty()) + continue; + if (!PointHitsLayer(layer, screen_space_point, nullptr)) + continue; + if (PointHitsRegion(screen_space_point, layer->ScreenSpaceTransform(), + layer->non_fast_scrollable_region(), layer)) { + layers.push_back(layer); + } + } + + return layers; +} + void LayerTreeImpl::RegisterSelection(const LayerSelection& selection) { if (selection_ == selection) return; diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index 21f3f87674a..5efd40a6f8f 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -343,9 +343,6 @@ class CC_EXPORT LayerTreeImpl { return painted_device_scale_factor_; } - void set_content_source_id(uint32_t id) { content_source_id_ = id; } - uint32_t content_source_id() { return content_source_id_; } - void SetLocalSurfaceIdAllocationFromParent( const viz::LocalSurfaceIdAllocation& local_surface_id_allocation_from_parent); @@ -460,6 +457,7 @@ class CC_EXPORT LayerTreeImpl { gfx::Rect RootScrollLayerDeviceViewportBounds() const; LayerImpl* LayerById(int id) const; + LayerImpl* LayerByElementId(ElementId element_id) const; LayerImpl* ScrollableLayerByElementId(ElementId element_id) const; bool IsElementInPropertyTree(ElementId element_id) const; @@ -545,6 +543,13 @@ class CC_EXPORT LayerTreeImpl { return picture_layers_; } + void NotifyLayerHasPaintWorkletsChanged(PictureLayerImpl* layer, + bool has_worklets); + const base::flat_set<PictureLayerImpl*>& picture_layers_with_paint_worklets() + const { + return picture_layers_with_paint_worklets_; + } + void RegisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer); void UnregisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer); ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const; @@ -560,6 +565,10 @@ class CC_EXPORT LayerTreeImpl { LayerImpl* FindLayerThatIsHitByPointInWheelEventHandlerRegion( const gfx::PointF& screen_space_point); + // Return all layers with a hit non-fast scrollable region. + std::vector<const LayerImpl*> FindLayersHitByPointInNonFastScrollableRegion( + const gfx::PointF& screen_space_point); + void RegisterSelection(const LayerSelection& selection); bool HandleVisibilityChanged() const { return handle_visibility_changed_; } @@ -704,7 +713,6 @@ class CC_EXPORT LayerTreeImpl { int raster_color_space_id_ = -1; gfx::ColorSpace raster_color_space_; - uint32_t content_source_id_; viz::LocalSurfaceIdAllocation local_surface_id_allocation_from_parent_; bool new_local_surface_id_request_ = false; gfx::Size device_viewport_size_; @@ -745,6 +753,11 @@ class CC_EXPORT LayerTreeImpl { std::vector<PictureLayerImpl*> picture_layers_; + // After commit (or impl-side invalidation), the LayerTreeHostImpl must walk + // all PictureLayerImpls that have PaintWorklets to ensure they are painted. + // To avoid unnecessary walking, we track that set here. + base::flat_set<PictureLayerImpl*> picture_layers_with_paint_worklets_; + base::flat_set<viz::SurfaceRange> surface_layer_ranges_; // List of render surfaces for the most recently prepared frame. diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 4dc46346a58..11d6bbc38d7 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -6,6 +6,7 @@ #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/test/fake_raster_source.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" #include "cc/trees/clip_node.h" @@ -18,17 +19,10 @@ namespace cc { namespace { -class LayerTreeImplTestSettings : public LayerTreeSettings { - public: - LayerTreeImplTestSettings() { - layer_transforms_should_scale_layer_contents = true; - } -}; - class LayerTreeImplTest : public testing::Test { public: - LayerTreeImplTest( - const LayerTreeSettings& settings = LayerTreeImplTestSettings()) + explicit LayerTreeImplTest( + const LayerTreeSettings& settings = LayerTreeSettings()) : impl_test_(settings) {} FakeLayerTreeHostImpl& host_impl() const { return *impl_test_.host_impl(); } @@ -47,7 +41,6 @@ class LayerTreeImplTest : public testing::Test { render_surface_list_impl_.clear(); LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root_layer, root_layer->bounds(), &render_surface_list_impl_); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); } @@ -2468,6 +2461,61 @@ TEST_F(LayerTreeImplTest, NotPersistentSwapPromisesAreDroppedWhenSwapFails) { } } +TEST_F(LayerTreeImplTest, TrackPictureLayersWithPaintWorklets) { + host_impl().CreatePendingTree(); + LayerTreeImpl* pending_tree = host_impl().pending_tree(); + + // Initially there are no layers in the set. + EXPECT_EQ(pending_tree->picture_layers_with_paint_worklets().size(), 0u); + + // Add three layers; two with PaintWorklets and one without. + std::unique_ptr<PictureLayerImpl> child1_owned = + PictureLayerImpl::Create(pending_tree, 2, Layer::LayerMaskType::NOT_MASK); + child1_owned->SetBounds(gfx::Size(100, 100)); + std::unique_ptr<PictureLayerImpl> child2_owned = + PictureLayerImpl::Create(pending_tree, 3, Layer::LayerMaskType::NOT_MASK); + child2_owned->SetBounds(gfx::Size(100, 100)); + std::unique_ptr<PictureLayerImpl> child3_owned = + PictureLayerImpl::Create(pending_tree, 4, Layer::LayerMaskType::NOT_MASK); + child3_owned->SetBounds(gfx::Size(100, 100)); + + PictureLayerImpl* child1 = child1_owned.get(); + PictureLayerImpl* child3 = child3_owned.get(); + + root_layer()->test_properties()->AddChild(std::move(child1_owned)); + root_layer()->test_properties()->AddChild(std::move(child2_owned)); + root_layer()->test_properties()->AddChild(std::move(child3_owned)); + + Region empty_invalidation; + scoped_refptr<RasterSource> raster_source1( + FakeRasterSource::CreateFilledWithPaintWorklet(child1->bounds())); + child1->UpdateRasterSource(raster_source1, &empty_invalidation, nullptr, + nullptr); + scoped_refptr<RasterSource> raster_source3( + FakeRasterSource::CreateFilledWithPaintWorklet(child3->bounds())); + child3->UpdateRasterSource(raster_source3, &empty_invalidation, nullptr, + nullptr); + + // The set should correctly track which layers are in it. + const base::flat_set<PictureLayerImpl*>& layers = + pending_tree->picture_layers_with_paint_worklets(); + EXPECT_EQ(layers.size(), 2u); + EXPECT_TRUE(layers.contains(child1)); + EXPECT_TRUE(layers.contains(child3)); + + // Test explicitly removing a layer from the set. + scoped_refptr<RasterSource> empty_raster_source( + FakeRasterSource::CreateFilled(child1->bounds())); + child1->UpdateRasterSource(empty_raster_source, &empty_invalidation, nullptr, + nullptr); + EXPECT_EQ(layers.size(), 1u); + EXPECT_FALSE(layers.contains(child1)); + + // Deleting a layer should also cause it to be removed from the set. + root_layer()->test_properties()->RemoveChild(child3); + EXPECT_EQ(layers.size(), 0u); +} + namespace { class CommitToPendingTreeLayerTreeImplTestSettings : public LayerTreeSettings { public: diff --git a/chromium/cc/trees/layer_tree_settings.cc b/chromium/cc/trees/layer_tree_settings.cc index 047b36948e7..ce4ba0308eb 100644 --- a/chromium/cc/trees/layer_tree_settings.cc +++ b/chromium/cc/trees/layer_tree_settings.cc @@ -24,19 +24,11 @@ SchedulerSettings LayerTreeSettings::ToSchedulerSettings() const { SchedulerSettings scheduler_settings; scheduler_settings.main_frame_before_activation_enabled = main_frame_before_activation_enabled; - scheduler_settings.timeout_and_draw_when_animation_checkerboards = - timeout_and_draw_when_animation_checkerboards; scheduler_settings.using_synchronous_renderer_compositor = using_synchronous_renderer_compositor; scheduler_settings.enable_latency_recovery = enable_latency_recovery; - scheduler_settings.background_frame_interval = - base::TimeDelta::FromSecondsD(1.0 / background_animation_rate); scheduler_settings.wait_for_all_pipeline_stages_before_draw = 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 092fb1b7ea3..d62c52b5326 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -62,13 +62,11 @@ class CC_EXPORT LayerTreeSettings { SkColor solid_color_scrollbar_color = SK_ColorWHITE; base::TimeDelta scroll_animation_duration_for_testing; bool timeout_and_draw_when_animation_checkerboards = true; - bool layer_transforms_should_scale_layer_contents = false; bool layers_always_allowed_lcd_text = false; float minimum_contents_scale = 0.0625f; float low_res_contents_scale_factor = 0.25f; float top_controls_show_threshold = 0.5f; float top_controls_hide_threshold = 0.5f; - double background_animation_rate = 1.0; gfx::Size default_tile_size; gfx::Size max_untiled_layer_size; // If set, indicates the largest tile size we will use for GPU Raster. If not @@ -97,8 +95,6 @@ class CC_EXPORT LayerTreeSettings { bool use_rgba_4444 = false; bool unpremultiply_and_dither_low_bit_depth_tiles = false; - bool enable_mask_tiling = true; - // If set to true, the compositor may selectively defer image decodes to the // Image Decode Service and raster tiles without images until the decode is // ready. diff --git a/chromium/cc/trees/mutator_host.h b/chromium/cc/trees/mutator_host.h index 03e3ce4d4a0..c52ce403301 100644 --- a/chromium/cc/trees/mutator_host.h +++ b/chromium/cc/trees/mutator_host.h @@ -9,7 +9,7 @@ #include "base/callback_forward.h" #include "base/time/time.h" -#include "cc/trees/element_id.h" +#include "cc/paint/element_id.h" #include "cc/trees/layer_tree_mutator.h" #include "cc/trees/mutator_host_client.h" #include "ui/gfx/geometry/box_f.h" @@ -131,6 +131,13 @@ class MutatorHost { virtual bool HasTickingKeyframeModelForTesting( ElementId element_id) const = 0; + virtual void ImplOnlyAutoScrollAnimationCreate( + ElementId element_id, + const gfx::ScrollOffset& target_offset, + const gfx::ScrollOffset& current_offset, + float autoscroll_velocity, + base::TimeDelta animation_start_offset) = 0; + virtual void ImplOnlyScrollAnimationCreate( ElementId element_id, const gfx::ScrollOffset& target_offset, diff --git a/chromium/cc/trees/mutator_host_client.h b/chromium/cc/trees/mutator_host_client.h index 5d221f3051c..406b10abfc5 100644 --- a/chromium/cc/trees/mutator_host_client.h +++ b/chromium/cc/trees/mutator_host_client.h @@ -5,7 +5,7 @@ #ifndef CC_TREES_MUTATOR_HOST_CLIENT_H_ #define CC_TREES_MUTATOR_HOST_CLIENT_H_ -#include "cc/trees/element_id.h" +#include "cc/paint/element_id.h" #include "cc/trees/property_animation_state.h" #include "cc/trees/target_property.h" diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index 04827454e5e..638a253ceb6 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -203,7 +203,6 @@ class OcclusionTrackerTest : public testing::Test { LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( root, root->bounds(), &render_surface_list_impl_); - inputs.can_adjust_raster_scales = true; LayerTreeHostCommon::CalculateDrawPropertiesForTesting(&inputs); layer_iterator_ = std::make_unique<EffectTreeLayerListIterator>( diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index 5d6b0b82fa1..f91deac77f3 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -233,6 +233,8 @@ void TransformTree::UpdateTransforms(int id) { UpdateNodeAndAncestorsHaveIntegerTranslations(node, parent_node); UpdateTransformChanged(node, parent_node, source_node); UpdateNodeAndAncestorsAreAnimatedOrInvertible(node, parent_node); + + DCHECK(!node->needs_local_transform_update); } bool TransformTree::IsDescendant(int desc_id, int source_id) const { @@ -374,7 +376,7 @@ gfx::Vector2dF StickyPositionOffset(TransformTree* tree, TransformNode* node) { scroll_position -= transform_node->snap_amount; } - gfx::RectF clip = constraint.constraint_box_rect; + gfx::Rect clip = constraint.constraint_box_rect; clip.Offset(scroll_position.x(), scroll_position.y()); // The clip region may need to be offset by the outer viewport bounds, e.g. if @@ -831,7 +833,6 @@ void EffectTree::UpdateHasMaskingChild(EffectNode* node, // when we actually encounter a masking child. node->has_masking_child = false; if (node->blend_mode == SkBlendMode::kDstIn) { - DCHECK(parent_node->HasRenderSurface()); parent_node->has_masking_child = true; } } @@ -850,16 +851,10 @@ void EffectTree::UpdateSurfaceContentsScale(EffectNode* effect_node) { if (transform_node->in_subtree_of_page_scale_layer) layer_scale_factor *= transform_tree.page_scale_factor(); - // Note: Copy requests currently expect transform to effect output size. - bool use_transform_for_contents_scale = - property_trees()->can_adjust_raster_scales || - effect_node->has_copy_request; const gfx::Vector2dF old_scale = effect_node->surface_contents_scale; effect_node->surface_contents_scale = - use_transform_for_contents_scale - ? MathUtil::ComputeTransform2dScaleComponents( - transform_tree.ToScreen(transform_node->id), layer_scale_factor) - : gfx::Vector2dF(layer_scale_factor, layer_scale_factor); + MathUtil::ComputeTransform2dScaleComponents( + transform_tree.ToScreen(transform_node->id), layer_scale_factor); // If surface contents scale changes, draw transforms are no longer valid. // Invalidates the draw transform cache and updates the clip for the surface. @@ -1757,7 +1752,6 @@ PropertyTreesCachedData::~PropertyTreesCachedData() = default; PropertyTrees::PropertyTrees() : needs_rebuild(true), - can_adjust_raster_scales(true), changed(false), full_tree_damaged(false), sequence_number(0), @@ -1785,7 +1779,6 @@ bool PropertyTrees::operator==(const PropertyTrees& other) const { full_tree_damaged == other.full_tree_damaged && is_main_thread == other.is_main_thread && is_active == other.is_active && - can_adjust_raster_scales == other.can_adjust_raster_scales && sequence_number == other.sequence_number; } @@ -1800,7 +1793,6 @@ PropertyTrees& PropertyTrees::operator=(const PropertyTrees& from) { needs_rebuild = from.needs_rebuild; changed = from.changed; full_tree_damaged = from.full_tree_damaged; - can_adjust_raster_scales = from.can_adjust_raster_scales; sequence_number = from.sequence_number; is_main_thread = from.is_main_thread; is_active = from.is_active; @@ -1830,7 +1822,6 @@ void PropertyTrees::clear() { needs_rebuild = true; full_tree_damaged = false; changed = false; - can_adjust_raster_scales = true; sequence_number++; #if DCHECK_IS_ON() @@ -2077,17 +2068,6 @@ CombinedAnimationScale PropertyTrees::GetAnimationScales( &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) { - animation_scales->update_number = - cached_data_.transform_tree_update_number; - animation_scales->combined_maximum_animation_target_scale = kNotScaled; - animation_scales->combined_starting_animation_scale = kNotScaled; - return CombinedAnimationScale( - 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; diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index f61d2c26a84..75b972dd86c 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -15,8 +15,8 @@ #include "cc/base/synced_property.h" #include "cc/cc_export.h" #include "cc/layers/layer_sticky_position_constraint.h" +#include "cc/paint/element_id.h" #include "cc/paint/filter_operations.h" -#include "cc/trees/element_id.h" #include "cc/trees/mutator_host_client.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/scroll_offset.h" @@ -631,7 +631,6 @@ class CC_EXPORT PropertyTrees final { ClipTree clip_tree; ScrollTree scroll_tree; bool needs_rebuild; - bool can_adjust_raster_scales; // Change tracking done on property trees needs to be preserved across commits // (when they are not rebuild). We cache a global bool which stores whether // we did any change tracking so that we can skip copying the change status diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index bd5882ee4f9..44a2033de9a 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -180,6 +180,14 @@ static LayerImpl* ClipParent(LayerImpl* layer) { return layer->test_properties()->clip_parent; } +static bool HasClipRect(Layer* layer) { + return !layer->clip_rect().IsEmpty(); +} + +static bool HasClipRect(LayerImpl* layer) { + return false; +} + static inline const FilterOperations& Filters(Layer* layer) { return layer->filters(); } @@ -204,15 +212,6 @@ static bool HasRoundedCorner(LayerImpl* layer) { return !layer->test_properties()->rounded_corner_bounds.IsEmpty(); } -static gfx::RRectF RoundedCornerBounds(Layer* layer) { - return gfx::RRectF(gfx::RectF(gfx::Rect(layer->bounds())), - layer->corner_radii()); -} - -static gfx::RRectF RoundedCornerBounds(LayerImpl* layer) { - return layer->test_properties()->rounded_corner_bounds; -} - static PictureLayer* MaskLayer(Layer* layer) { return layer->mask_layer(); } @@ -310,9 +309,30 @@ static int GetTransformParent(const DataForRecursion& data, LayerType* layer) { } template <typename LayerType> +static bool LayerClipsSubtreeToItsBounds(LayerType* layer) { + return layer->masks_to_bounds() || MaskLayer(layer); +} + +template <typename LayerType> static bool LayerClipsSubtree(LayerType* layer) { - return layer->masks_to_bounds() || MaskLayer(layer) || - HasRoundedCorner(layer); + return LayerClipsSubtreeToItsBounds(layer) || HasRoundedCorner(layer) || + HasClipRect(layer); +} + +gfx::RectF EffectiveClipRect(Layer* layer) { + return layer->EffectiveClipRect(); +} + +gfx::RectF EffectiveClipRect(LayerImpl* layer) { + return gfx::RectF(gfx::PointF(), gfx::SizeF(layer->bounds())); +} + +static gfx::RRectF RoundedCornerBounds(Layer* layer) { + return gfx::RRectF(EffectiveClipRect(layer), layer->corner_radii()); +} + +static gfx::RRectF RoundedCornerBounds(LayerImpl* layer) { + return layer->test_properties()->rounded_corner_bounds; } template <typename LayerType> @@ -355,6 +375,12 @@ static inline bool HasLatestSequenceNumber(const LayerImpl*, int) { return true; } +static inline void SetHasClipNode(Layer* layer, bool val) { + layer->SetHasClipNode(val); +} + +static inline void SetHasClipNode(LayerImpl* layer, bool val) {} + template <typename LayerType> void PropertyTreeBuilderContext<LayerType>::AddClipNodeIfNeeded( const DataForRecursion& data_from_ancestor, @@ -376,8 +402,11 @@ void PropertyTreeBuilderContext<LayerType>::AddClipNodeIfNeeded( data_for_children->clip_tree_parent = parent_id; } else { ClipNode node; - node.clip = gfx::RectF(gfx::PointF() + layer->offset_to_transform_parent(), - gfx::SizeF(layer->bounds())); + node.clip = EffectiveClipRect(layer); + + // Move the clip bounds so that it is relative to the transform parent. + node.clip += layer->offset_to_transform_parent(); + node.transform_id = created_transform_node ? data_for_children->transform_tree_parent : GetTransformParent(data_from_ancestor, layer); @@ -391,6 +420,7 @@ void PropertyTreeBuilderContext<LayerType>::AddClipNodeIfNeeded( data_for_children->clip_tree_parent = clip_tree_.Insert(node, parent_id); } + SetHasClipNode(layer, requires_node); layer->SetClipTreeIndex(data_for_children->clip_tree_parent); } @@ -797,6 +827,14 @@ static inline const base::Optional<gfx::RRectF>& BackdropFilterBounds( return layer->test_properties()->backdrop_filter_bounds; } +static inline ElementId BackdropMaskElementId(Layer* layer) { + return layer->backdrop_mask_element_id(); +} + +static inline ElementId BackdropMaskElementId(LayerImpl* layer) { + return layer->test_properties()->backdrop_mask_element_id; +} + static inline float BackdropFilterQuality(Layer* layer) { return layer->backdrop_filter_quality(); } @@ -821,6 +859,14 @@ static inline bool HasCopyRequest(LayerImpl* layer) { return !layer->test_properties()->copy_requests.empty(); } +static inline int MirrorCount(Layer* layer) { + return layer->mirror_count(); +} + +static inline int MirrorCount(LayerImpl* layer) { + return 0; +} + static inline bool PropertyChanged(Layer* layer) { return layer->subtree_property_changed(); } @@ -933,6 +979,10 @@ RenderSurfaceReason ComputeRenderSurfaceReason(const MutatorHost& mutator_host, if (HasCopyRequest(layer)) return RenderSurfaceReason::kCopyRequest; + // If the layer is mirrored. + if (MirrorCount(layer)) + return RenderSurfaceReason::kMirrored; + return RenderSurfaceReason::kNone; } @@ -1040,6 +1090,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( node->backdrop_filters = BackdropFilters(layer); node->backdrop_filter_bounds = BackdropFilterBounds(layer); node->backdrop_filter_quality = BackdropFilterQuality(layer); + node->backdrop_mask_element_id = BackdropMaskElementId(layer); node->filters_origin = FiltersOrigin(layer); node->trilinear_filtering = TrilinearFiltering(layer); node->has_potential_opacity_animation = has_potential_opacity_animation; diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index 10a58a32998..0fe7a90fe3f 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -39,10 +39,6 @@ class CC_EXPORT Proxy { virtual bool IsStarted() const = 0; - // This function retruns true if the commits go directly to active tree by - // skipping commit to pending tree. - virtual bool CommitToActiveTree() const = 0; - virtual void SetLayerTreeFrameSink( LayerTreeFrameSink* layer_tree_frame_sink) = 0; virtual void ReleaseLayerTreeFrameSink() = 0; diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index cdfd8d3a135..2e69eddc64e 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -191,7 +191,9 @@ void ProxyImpl::BeginMainFrameAbortedOnImpl( DCHECK(IsImplThread()); DCHECK(scheduler_->CommitPending()); - host_impl_->BeginMainFrameAborted(reason, std::move(swap_promises)); + host_impl_->BeginMainFrameAborted( + reason, std::move(swap_promises), + scheduler_->last_dispatched_begin_main_frame_args()); scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time); scheduler_->BeginMainFrameAborted(reason); } @@ -365,7 +367,7 @@ void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread( DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ProxyMain::SetAnimationEvents, - proxy_main_weak_ptr_, base::Passed(&events))); + proxy_main_weak_ptr_, std::move(events))); } size_t ProxyImpl::CompositedAnimationsCount() const { @@ -388,6 +390,14 @@ bool ProxyImpl::IsInsideDraw() { return inside_draw_; } +bool ProxyImpl::IsBeginMainFrameExpected() { + // Check whether the main-thread has requested for updates. If main-thread has + // not responded to a previously dispatched BeginMainFrame, then assume that + // main-thread would want to produce an update for the current frame too. + return scheduler_->needs_begin_main_frame() || + scheduler_->IsBeginMainFrameSent(); +} + void ProxyImpl::RenewTreePriority() { DCHECK(IsImplThread()); const bool user_interaction_in_progress = @@ -495,6 +505,8 @@ void ProxyImpl::DidPresentCompositorFrameOnImplThread( FROM_HERE, base::BindOnce(&ProxyMain::DidPresentCompositorFrame, proxy_main_weak_ptr_, frame_token, std::move(callbacks), feedback)); + if (scheduler_) + scheduler_->DidPresentCompositorFrame(frame_token, feedback.timestamp); } void ProxyImpl::NotifyAnimationWorkletStateChange( @@ -512,6 +524,12 @@ void ProxyImpl::NotifyAnimationWorkletStateChange( tree_type); } +void ProxyImpl::NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) { + DCHECK(IsImplThread()); + scheduler_->NotifyPaintWorkletStateChange(state); +} + bool ProxyImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { DCHECK(IsImplThread()); return host_impl_->WillBeginImplFrame(args); @@ -551,8 +569,8 @@ void ProxyImpl::ScheduledActionSendBeginMainFrame( MainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_, - base::Passed(&begin_main_frame_state))); - host_impl_->DidSendBeginMainFrame(); + std::move(begin_main_frame_state))); + host_impl_->DidSendBeginMainFrame(args); devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_); } @@ -685,6 +703,8 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { LayerTreeHostImpl::FrameData frame; frame.begin_frame_ack = scheduler_->CurrentBeginFrameAckForActiveTree(); + frame.origin_begin_main_frame_args = + scheduler_->last_activate_origin_frame_args(); bool draw_frame = false; DrawResult result; @@ -696,9 +716,11 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { } if (draw_frame) { - if (host_impl_->DrawLayers(&frame)) + if (host_impl_->DrawLayers(&frame)) { + DCHECK_NE(frame.frame_token, 0u); // Drawing implies we submitted a frame to the LayerTreeFrameSink. - scheduler_->DidSubmitCompositorFrame(); + scheduler_->DidSubmitCompositorFrame(frame.frame_token); + } result = DRAW_SUCCESS; } else { DCHECK_NE(DRAW_SUCCESS, result); @@ -709,7 +731,7 @@ DrawResult ProxyImpl::DrawInternal(bool forced_draw) { bool start_ready_animations = draw_frame; host_impl_->UpdateAnimationState(start_ready_animations); - // Tell the main thread that the the newly-commited frame was drawn. + // Tell the main thread that the newly-commited frame was drawn. if (next_frame_is_newly_committed_frame_) { next_frame_is_newly_committed_frame_ = false; MainThreadTaskRunner()->PostTask( diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index 62636b88386..d8222df2013 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -94,6 +94,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, void PostAnimationEventsToMainThreadOnImplThread( std::unique_ptr<MutatorEvents> events) override; bool IsInsideDraw() override; + bool IsBeginMainFrameExpected() override; void RenewTreePriority() override; void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) override; @@ -112,6 +113,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, void NotifyAnimationWorkletStateChange( AnimationWorkletMutationState state, ElementListType element_list_type) override; + void NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) override; // SchedulerClient implementation bool WillBeginImplFrame(const viz::BeginFrameArgs& args) override; diff --git a/chromium/cc/trees/proxy_main.cc b/chromium/cc/trees/proxy_main.cc index 20299713e6a..dc7b697ae2b 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -39,9 +39,7 @@ ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host, commit_waits_for_activation_(false), started_(false), defer_main_frame_update_(false), - defer_commits_(true), - frame_sink_bound_weak_factory_(this), - weak_factory_(this) { + defer_commits_(true) { TRACE_EVENT0("cc", "ProxyMain::ProxyMain"); DCHECK(task_runner_provider_); DCHECK(IsMainThread()); @@ -157,7 +155,7 @@ void ProxyMain::BeginMainFrame( base::Unretained(proxy_impl_.get()), CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + std::move(empty_swap_promises))); return; } @@ -188,7 +186,7 @@ void ProxyMain::BeginMainFrame( base::Unretained(proxy_impl_.get()), CommitEarlyOutReason::ABORTED_DEFERRED_MAIN_FRAME_UPDATE, begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + std::move(empty_swap_promises))); // When we stop deferring main frame updates, we should resume any // previously requested pipeline stages. deferred_final_pipeline_stage_ = @@ -202,11 +200,22 @@ void ProxyMain::BeginMainFrame( current_pipeline_stage_ = ANIMATE_PIPELINE_STAGE; - // Synchronizes scroll offsets and page scale deltas (for pinch zoom) from the - // compositor thread thread to the main thread for both cc and and its - // client (e.g. Blink). - layer_tree_host_->ApplyScrollAndScale( - begin_main_frame_state->scroll_info.get()); + // Check now if we should stop deferring commits due to a timeout. We + // may also stop deferring in BeginMainFrame, but maintain the status + // from this point to keep scroll in sync. + if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_) { + StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout); + } + skip_commit |= defer_commits_; + + if (!skip_commit) { + // Synchronizes scroll offsets and page scale deltas (for pinch zoom) from + // the compositor thread to the main thread for both cc and and its client + // (e.g. Blink). Do not do this if we explicitly plan to not commit the + // layer tree, to prevent scroll offsets getting out of sync. + layer_tree_host_->ApplyScrollAndScale( + begin_main_frame_state->scroll_info.get()); + } layer_tree_host_->WillBeginMainFrame(); layer_tree_host_->RecordStartOfFrameMetrics(); @@ -230,14 +239,10 @@ void ProxyMain::BeginMainFrame( // what this does. layer_tree_host_->RequestMainFrameUpdate(); - // Check now if we should stop deferring commits - if (defer_commits_ && base::TimeTicks::Now() > commits_restart_time_) { - StopDeferringCommits(PaintHoldingCommitTrigger::kTimeout); - } - - // At this point the main frame may have deferred commits to avoid committing - // right now, or we may be deferring commits but not deferring main - // frame updates. + // At this point the main frame may have deferred main frame updates to + // avoid committing right now, or we may be deferring commits but not + // deferring main frame updates. Either may have changed the status + // of the defer... flags, so re-evaluate skip_commit. skip_commit |= defer_main_frame_update_ || defer_commits_; if (skip_commit) { @@ -252,7 +257,7 @@ void ProxyMain::BeginMainFrame( base::Unretained(proxy_impl_.get()), CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT, begin_main_frame_start_time, - base::Passed(&empty_swap_promises))); + std::move(empty_swap_promises))); // We intentionally don't report CommitComplete() here since it was aborted // prematurely and we're waiting to do another commit in the future. // When we stop deferring commits, we should resume any previously requested @@ -295,11 +300,11 @@ void ProxyMain::BeginMainFrame( std::vector<std::unique_ptr<SwapPromise>> swap_promises = layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises(); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, - base::Unretained(proxy_impl_.get()), - CommitEarlyOutReason::FINISHED_NO_UPDATES, - begin_main_frame_start_time, - base::Passed(&swap_promises))); + FROM_HERE, + base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl, + base::Unretained(proxy_impl_.get()), + CommitEarlyOutReason::FINISHED_NO_UPDATES, + begin_main_frame_start_time, std::move(swap_promises))); // Although the commit is internally aborted, this is because it has been // detected to be a no-op. From the perspective of an embedder, this commit @@ -315,7 +320,7 @@ void ProxyMain::BeginMainFrame( ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME); new_latency_info.AddLatencyNumberWithTimestamp( ui::LATENCY_BEGIN_FRAME_RENDERER_MAIN_COMPONENT, - begin_main_frame_state->begin_frame_args.frame_time, 1); + begin_main_frame_state->begin_frame_args.frame_time); layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); @@ -365,12 +370,6 @@ bool ProxyMain::IsStarted() const { return started_; } -bool ProxyMain::CommitToActiveTree() const { - // With ProxyMain, we use a pending tree and activate it once it's ready to - // draw to allow input to modify the active tree and draw during raster. - return false; -} - void ProxyMain::SetLayerTreeFrameSink( LayerTreeFrameSink* layer_tree_frame_sink) { ImplThreadTaskRunner()->PostTask( diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h index 7b110c08a7d..515f1e10de9 100644 --- a/chromium/cc/trees/proxy_main.h +++ b/chromium/cc/trees/proxy_main.h @@ -72,7 +72,6 @@ class CC_EXPORT ProxyMain : public Proxy { private: // Proxy implementation. bool IsStarted() const override; - bool CommitToActiveTree() const override; void SetLayerTreeFrameSink( LayerTreeFrameSink* layer_tree_frame_sink) override; void SetVisible(bool visible) override; @@ -156,9 +155,9 @@ class CC_EXPORT ProxyMain : public Proxy { // WeakPtrs generated by this factory will be invalidated when // LayerTreeFrameSink is released. - base::WeakPtrFactory<ProxyMain> frame_sink_bound_weak_factory_; + base::WeakPtrFactory<ProxyMain> frame_sink_bound_weak_factory_{this}; - base::WeakPtrFactory<ProxyMain> weak_factory_; + base::WeakPtrFactory<ProxyMain> weak_factory_{this}; }; } // namespace cc diff --git a/chromium/cc/trees/scroll_node.cc b/chromium/cc/trees/scroll_node.cc index 69b7b3318f5..50227da93d4 100644 --- a/chromium/cc/trees/scroll_node.cc +++ b/chromium/cc/trees/scroll_node.cc @@ -7,7 +7,7 @@ #include "cc/base/math_util.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/layers/layer.h" -#include "cc/trees/element_id.h" +#include "cc/paint/element_id.h" #include "cc/trees/property_tree.h" #include "base/trace_event/traced_value.h" diff --git a/chromium/cc/trees/scroll_node.h b/chromium/cc/trees/scroll_node.h index de9f9343c8d..1d2e6fa789e 100644 --- a/chromium/cc/trees/scroll_node.h +++ b/chromium/cc/trees/scroll_node.h @@ -9,8 +9,8 @@ #include "cc/cc_export.h" #include "cc/input/overscroll_behavior.h" #include "cc/input/scroll_snap_data.h" +#include "cc/paint/element_id.h" #include "cc/paint/filter_operations.h" -#include "cc/trees/element_id.h" #include "ui/gfx/geometry/size.h" namespace base { diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index d74fe26e408..0bc215ea7c4 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -27,6 +27,7 @@ #include "cc/trees/scoped_abort_remaining_swap_promises.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" #include "components/viz/common/gpu/context_provider.h" +#include "ui/gfx/presentation_feedback.h" namespace cc { @@ -56,9 +57,7 @@ SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host, inside_synchronous_composite_(false), needs_impl_frame_(false), layer_tree_frame_sink_creation_requested_(false), - layer_tree_frame_sink_lost_(true), - frame_sink_bound_weak_factory_(this), - weak_factory_(this) { + layer_tree_frame_sink_lost_(true) { TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy"); DCHECK(task_runner_provider_); DCHECK(task_runner_provider_->IsMainThread()); @@ -75,7 +74,7 @@ void SingleThreadProxy::Start() { 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(); + scheduler_settings.commit_to_active_tree = true; std::unique_ptr<CompositorTimingHistory> compositor_timing_history( new CompositorTimingHistory( @@ -102,12 +101,6 @@ bool SingleThreadProxy::IsStarted() const { return !!host_impl_; } -bool SingleThreadProxy::CommitToActiveTree() const { - // With SingleThreadProxy we skip the pending tree and commit directly to the - // active tree. - return true; -} - void SingleThreadProxy::SetVisible(bool visible) { TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible); DebugScopedSetImplThread impl(task_runner_provider_); @@ -436,6 +429,10 @@ bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; } +bool SingleThreadProxy::IsBeginMainFrameExpected() { + return true; +} + void SingleThreadProxy::DidActivateSyncTree() { CommitComplete(); } @@ -525,6 +522,11 @@ void SingleThreadProxy::DidPresentCompositorFrameOnImplThread( const gfx::PresentationFeedback& feedback) { layer_tree_host_->DidPresentCompositorFrame(frame_token, std::move(callbacks), feedback); + + if (scheduler_on_impl_thread_) { + scheduler_on_impl_thread_->DidPresentCompositorFrame(frame_token, + feedback.timestamp); + } } void SingleThreadProxy::NotifyAnimationWorkletStateChange( @@ -533,6 +535,12 @@ void SingleThreadProxy::NotifyAnimationWorkletStateChange( layer_tree_host_->NotifyAnimationWorkletStateChange(state, element_list_type); } +void SingleThreadProxy::NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) { + // Off-Thread PaintWorklet is only supported on the threaded compositor. + NOTREACHED(); +} + void SingleThreadProxy::RequestBeginMainFrameNotExpected(bool new_state) { if (scheduler_on_impl_thread_) { scheduler_on_impl_thread_->SetMainThreadWantsBeginMainFrameNotExpected( @@ -605,6 +613,7 @@ void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time, if (raster) { LayerTreeHostImpl::FrameData frame; frame.begin_frame_ack = viz::BeginFrameAck(begin_frame_args, true); + frame.origin_begin_main_frame_args = begin_frame_args; DoComposite(&frame); } @@ -666,9 +675,11 @@ DrawResult SingleThreadProxy::DoComposite(LayerTreeHostImpl::FrameData* frame) { draw_frame = draw_result == DRAW_SUCCESS; if (draw_frame) { if (host_impl_->DrawLayers(frame)) { - if (scheduler_on_impl_thread_) + if (scheduler_on_impl_thread_) { // Drawing implies we submitted a frame to the LayerTreeFrameSink. - scheduler_on_impl_thread_->DidSubmitCompositorFrame(); + scheduler_on_impl_thread_->DidSubmitCompositorFrame( + frame->frame_token); + } single_thread_client_->DidSubmitCompositorFrame(); } } @@ -744,7 +755,7 @@ void SingleThreadProxy::ScheduledActionSendBeginMainFrame( task_runner_provider_->MainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&SingleThreadProxy::BeginMainFrame, weak_factory_.GetWeakPtr(), begin_frame_args)); - host_impl_->DidSendBeginMainFrame(); + host_impl_->DidSendBeginMainFrame(begin_frame_args); } void SingleThreadProxy::FrameIntervalUpdated(base::TimeDelta interval) { @@ -823,8 +834,7 @@ void SingleThreadProxy::BeginMainFrame( // know we will commit since QueueSwapPromise itself requests a commit. ui::LatencyInfo new_latency_info(ui::SourceEventType::FRAME); new_latency_info.AddLatencyNumberWithTimestamp( - ui::LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT, begin_frame_args.frame_time, - 1); + ui::LATENCY_BEGIN_FRAME_UI_MAIN_COMPONENT, begin_frame_args.frame_time); layer_tree_host_->QueueSwapPromise( std::make_unique<LatencyInfoSwapPromise>(new_latency_info)); @@ -863,7 +873,9 @@ void SingleThreadProxy::BeginMainFrameAbortedOnImplThread( DCHECK(!host_impl_->pending_tree()); std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises; - host_impl_->BeginMainFrameAborted(reason, std::move(empty_swap_promises)); + host_impl_->BeginMainFrameAborted( + reason, std::move(empty_swap_promises), + scheduler_on_impl_thread_->last_dispatched_begin_main_frame_args()); scheduler_on_impl_thread_->BeginMainFrameAborted(reason); } @@ -872,6 +884,8 @@ DrawResult SingleThreadProxy::ScheduledActionDrawIfPossible() { LayerTreeHostImpl::FrameData frame; frame.begin_frame_ack = scheduler_on_impl_thread_->CurrentBeginFrameAckForActiveTree(); + frame.origin_begin_main_frame_args = + scheduler_on_impl_thread_->last_activate_origin_frame_args(); return DoComposite(&frame); } diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index 97a449b3442..320688ea79b 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -41,7 +41,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, // Proxy implementation bool IsStarted() const override; - bool CommitToActiveTree() const override; void SetLayerTreeFrameSink( LayerTreeFrameSink* layer_tree_frame_sink) override; void ReleaseLayerTreeFrameSink() override; @@ -115,6 +114,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void PostAnimationEventsToMainThreadOnImplThread( std::unique_ptr<MutatorEvents> events) override; bool IsInsideDraw() override; + bool IsBeginMainFrameExpected() override; void RenewTreePriority() override {} void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) override {} @@ -134,6 +134,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void NotifyAnimationWorkletStateChange( AnimationWorkletMutationState state, ElementListType element_list_type) override; + void NotifyPaintWorkletStateChange( + Scheduler::PaintWorkletState state) override; void RequestNewLayerTreeFrameSink(); @@ -206,9 +208,9 @@ class CC_EXPORT SingleThreadProxy : public Proxy, // WeakPtrs generated by this factory will be invalidated when // LayerTreeFrameSink is released. - base::WeakPtrFactory<SingleThreadProxy> frame_sink_bound_weak_factory_; + base::WeakPtrFactory<SingleThreadProxy> frame_sink_bound_weak_factory_{this}; - base::WeakPtrFactory<SingleThreadProxy> weak_factory_; + base::WeakPtrFactory<SingleThreadProxy> weak_factory_{this}; }; // For use in the single-threaded case. In debug builds, it pretends that the diff --git a/chromium/cc/trees/transform_node.h b/chromium/cc/trees/transform_node.h index 5a19ccec9e0..4f123a6390f 100644 --- a/chromium/cc/trees/transform_node.h +++ b/chromium/cc/trees/transform_node.h @@ -6,7 +6,7 @@ #define CC_TREES_TRANSFORM_NODE_H_ #include "cc/cc_export.h" -#include "cc/trees/element_id.h" +#include "cc/paint/element_id.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/transform.h" @@ -67,7 +67,8 @@ struct CC_EXPORT TransformNode { // context. int sorting_context_id; - // TODO(vollick): will be moved when accelerated effects are implemented. + // True if |TransformTree::UpdateLocalTransform| needs to be called which + // will update |to_parent| and |source_to_parent| (if possible). bool needs_local_transform_update : 1; // Whether this node or any ancestor has a potentially running diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index 9e329f02eaa..393e45b1167 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -41,14 +41,14 @@ static bool LayerHasValidPropertyTreeIndices(LayerImpl* layer) { } static bool LayerWillPushProperties(LayerTreeHost* host, Layer* layer) { - return base::ContainsKey(host->LayersThatShouldPushProperties(), layer); + return base::Contains(host->LayersThatShouldPushProperties(), layer); } static bool LayerWillPushProperties(LayerTreeImpl* tree, LayerImpl* layer) { - return base::ContainsKey(tree->LayersThatShouldPushProperties(), layer) || + return base::Contains(tree->LayersThatShouldPushProperties(), layer) || // TODO(crbug.com/303943): Stop always pushing PictureLayerImpl // properties. - base::ContainsValue(tree->picture_layers(), layer); + base::Contains(tree->picture_layers(), layer); } #endif diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc index b7a3dc02eee..6d0d4e5688e 100644 --- a/chromium/cc/trees/tree_synchronizer_unittest.cc +++ b/chromium/cc/trees/tree_synchronizer_unittest.cc @@ -200,7 +200,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeFromEmpty) { host_->pending_tree()); LayerImpl* root = host_->pending_tree()->root_layer_for_testing(); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( host_->pending_tree()->LayersThatShouldPushProperties(), root)); ExpectTreesAreIdentical(layer_tree_root.get(), @@ -226,7 +226,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndPushPropertiesFromEmpty) { // layers are created on pending tree and they all need to push properties to // active tree. LayerImpl* root = host_->pending_tree()->root_layer_for_testing(); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( host_->pending_tree()->LayersThatShouldPushProperties(), root)); ExpectTreesAreIdentical(layer_tree_root.get(), @@ -242,20 +242,20 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndPushPropertiesFromEmpty) { host_->active_tree()); TreeSynchronizer::PushLayerProperties(host_->pending_tree(), host_->active_tree()); - EXPECT_FALSE(base::ContainsKey( + EXPECT_FALSE(base::Contains( host_->pending_tree()->LayersThatShouldPushProperties(), root)); // Set the main thread root layer needs push properties. layer_tree_root->SetNeedsPushProperties(); - EXPECT_TRUE(base::ContainsKey(host_->LayersThatShouldPushProperties(), - layer_tree_root.get())); + EXPECT_TRUE(base::Contains(host_->LayersThatShouldPushProperties(), + layer_tree_root.get())); // When sync from main thread, the needs push properties status is carried // over to pending tree. TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(), host_->pending_tree()); TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree()); - EXPECT_TRUE(base::ContainsKey( + EXPECT_TRUE(base::Contains( host_->pending_tree()->LayersThatShouldPushProperties(), root)); } @@ -278,8 +278,8 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeReusingLayers) { LayerImpl* layer_impl_tree_root = host_->pending_tree()->root_layer_for_testing(); EXPECT_TRUE( - base::ContainsKey(host_->pending_tree()->LayersThatShouldPushProperties(), - layer_impl_tree_root)); + base::Contains(host_->pending_tree()->LayersThatShouldPushProperties(), + layer_impl_tree_root)); ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root, host_->pending_tree()); @@ -522,12 +522,12 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeThenDestroy) { ASSERT_EQ(3u, layer_impl_destruction_list.size()); - EXPECT_TRUE(base::ContainsValue(layer_impl_destruction_list, - old_tree_root_layer_id)); - EXPECT_TRUE(base::ContainsValue(layer_impl_destruction_list, - old_tree_first_child_layer_id)); - EXPECT_TRUE(base::ContainsValue(layer_impl_destruction_list, - old_tree_second_child_layer_id)); + EXPECT_TRUE( + base::Contains(layer_impl_destruction_list, old_tree_root_layer_id)); + EXPECT_TRUE(base::Contains(layer_impl_destruction_list, + old_tree_first_child_layer_id)); + EXPECT_TRUE(base::Contains(layer_impl_destruction_list, + old_tree_second_child_layer_id)); } // Constructs+syncs a tree with mask layer. diff --git a/chromium/cc/trees/viewport_layers.h b/chromium/cc/trees/viewport_layers.h index 7cdb88bd27e..b92d1190bc1 100644 --- a/chromium/cc/trees/viewport_layers.h +++ b/chromium/cc/trees/viewport_layers.h @@ -6,7 +6,8 @@ #define CC_TREES_VIEWPORT_LAYERS_H_ #include "base/memory/ref_counted.h" -#include "cc/trees/element_id.h" +#include "cc/cc_export.h" +#include "cc/paint/element_id.h" namespace cc { class Layer; |