diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-13 16:23:34 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-14 10:37:21 +0000 |
commit | 38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch) | |
tree | c4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/cc | |
parent | e684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff) | |
download | qtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz |
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/cc')
211 files changed, 4100 insertions, 2186 deletions
diff --git a/chromium/cc/BUILD.gn b/chromium/cc/BUILD.gn index 1c7b04e7a28..a03bd1fa818 100644 --- a/chromium/cc/BUILD.gn +++ b/chromium/cc/BUILD.gn @@ -150,6 +150,8 @@ cc_component("cc") { "raster/gpu_raster_buffer_provider.h", "raster/one_copy_raster_buffer_provider.cc", "raster/one_copy_raster_buffer_provider.h", + "raster/paint_worklet_image_provider.cc", + "raster/paint_worklet_image_provider.h", "raster/playback_image_provider.cc", "raster/playback_image_provider.h", "raster/raster_buffer.cc", @@ -225,6 +227,8 @@ cc_component("cc") { "tiles/image_decode_cache_utils.h", "tiles/mipmap_util.cc", "tiles/mipmap_util.h", + "tiles/paint_worklet_image_cache.cc", + "tiles/paint_worklet_image_cache.h", "tiles/picture_layer_tiling.cc", "tiles/picture_layer_tiling.h", "tiles/picture_layer_tiling_set.cc", @@ -297,7 +301,6 @@ cc_component("cc") { "trees/layer_tree_impl.h", "trees/layer_tree_mutator.cc", "trees/layer_tree_mutator.h", - "trees/layer_tree_painter.h", "trees/layer_tree_settings.cc", "trees/layer_tree_settings.h", "trees/managed_memory_policy.cc", @@ -346,9 +349,6 @@ cc_component("cc") { "trees/ukm_manager.h", ] - # TODO(khushalsagar): Remove once crbug.com/683263 is fixed. - configs = [ "//build/config/compiler:no_size_t_to_int_warning" ] - public_deps = [ "//cc/base", "//cc/paint", @@ -496,6 +496,10 @@ cc_test_static_library("test_support") { "test/test_occlusion_tracker.h", "test/test_options_provider.cc", "test/test_options_provider.h", + "test/test_paint_worklet_input.cc", + "test/test_paint_worklet_input.h", + "test/test_paint_worklet_layer_painter.cc", + "test/test_paint_worklet_layer_painter.h", "test/test_skcanvas.cc", "test/test_skcanvas.h", "test/test_task_graph_runner.cc", @@ -641,6 +645,7 @@ cc_test("cc_unittests") { "tiles/gpu_image_decode_cache_unittest.cc", "tiles/image_controller_unittest.cc", "tiles/mipmap_util_unittest.cc", + "tiles/paint_worklet_image_cache_unittest.cc", "tiles/picture_layer_tiling_set_unittest.cc", "tiles/picture_layer_tiling_unittest.cc", "tiles/software_image_decode_cache_unittest.cc", @@ -711,9 +716,6 @@ cc_test("cc_unittests") { cflags = [ "/wd4250" ] } - # TODO(khushalsagar): Remove once crbug.com/683263 is fixed. - configs = [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":cc", ":test_support", diff --git a/chromium/cc/OWNERS b/chromium/cc/OWNERS index 10a074fa7f1..e12309d4c86 100644 --- a/chromium/cc/OWNERS +++ b/chromium/cc/OWNERS @@ -1,52 +1,37 @@ # For patches touching specific topics, try the topic-specific OWNERS at the # bottom of the file. For patches that touch multiple areas or if you aren't -# sure, try the more general OWNERS at the top. +# sure, try the more general OWNERS at the bottom. # # Folks listed as unofficial can't do OWNERS approvals but are good people to # ask for informal reviews. +# layers enne@chromium.org danakj@chromium.org -vmpstr@chromium.org - -# layers / quads / passes -enne@chromium.org -danakj@chromium.org - -# ubercompositor -piman@chromium.org -danakj@chromium.org +pdr@chromium.org # mac-specific ccameron@chromium.org # scheduling / begin frames -brianderson@chromium.org -skyostil@chromium.org sunnyps@chromium.org -# texture uploading -brianderson@chromium.org -reveman@chromium.org -skyostil@chromium.org - # tiles, tile management, and raster work -reveman@chromium.org vmpstr@chromium.org ericrk@chromium.org +# texture uploading +sunnyps@chromium.org + # math / geometry flackr@chromium.org -vollick@chromium.org # property trees -ajuma@chromium.org chrishtr@chromium.org -vollick@chromium.org weiliangc@chromium.org +pdr@chromium.org # animation -ajuma@chromium.org flackr@chromium.org smcgruer@chromium.org @@ -56,17 +41,18 @@ khushalsagar@chromium.org vmpstr@chromium.org # surfaces -fsamuel@chromium.org +enne@chromium.org kylechar@chromium.org samans@chromium.org # input, scrolling bokan@chromium.org -# we miss you -# jamesr@chromium.org -# nduca@chromium.org -# mithro@mithis.com / tansell@chromium.org +# general +enne@chromium.org +danakj@chromium.org +vmpstr@chromium.org +piman@chromium.org # TEAM: graphics-dev@chromium.org # COMPONENT: Internals>Compositing diff --git a/chromium/cc/README.md b/chromium/cc/README.md index d1b5218d69b..5b3669d1b8e 100644 --- a/chromium/cc/README.md +++ b/chromium/cc/README.md @@ -42,6 +42,10 @@ composited browser contents into a backbuffer or a bitmap, respectively. Design documents for the graphics stack can be found at [chromium-graphics](https://www.chromium.org/developers/design-documents/chromium-graphics). +## Other Docs + +* [How cc Works](https://docs.google.com/document/d/1yjzOWrPfFGviEd1nru3yzqxSHETC-zsEBSt9C8SvV-Q/edit) + ## Glossaries ### Active CompositorFrame diff --git a/chromium/cc/animation/animation_host.cc b/chromium/cc/animation/animation_host.cc index b78c578afd6..f5d610983c9 100644 --- a/chromium/cc/animation/animation_host.cc +++ b/chromium/cc/animation/animation_host.cc @@ -158,10 +158,17 @@ void AnimationHost::UnregisterKeyframeEffectForElement( scoped_refptr<ElementAnimations> element_animations = GetElementAnimationsForElementId(element_id); DCHECK(element_animations); + + // |ClearAffectedElementTypes| requires an ElementId map in order to update + // the property trees. Generating that map requires walking the keyframe + // effects, so we have to do it before removing this one. + PropertyToElementIdMap element_id_map = + element_animations->GetPropertyToElementIdMap(); + element_animations->RemoveKeyframeEffect(keyframe_effect); if (element_animations->IsEmpty()) { - element_animations->ClearAffectedElementTypes(); + element_animations->ClearAffectedElementTypes(element_id_map); element_to_animations_map_.erase(element_animations->element_id()); element_animations->SetAnimationHost(nullptr); } diff --git a/chromium/cc/animation/element_animations.cc b/chromium/cc/animation/element_animations.cc index f5d216cd5ab..dda8db90061 100644 --- a/chromium/cc/animation/element_animations.cc +++ b/chromium/cc/animation/element_animations.cc @@ -31,7 +31,7 @@ namespace { // tracking is done on the KeyframeModel - https://crbug.com/900241 ElementId CalculateTargetElementId(const ElementAnimations* element_animations, const KeyframeModel* keyframe_model) { - if (keyframe_model->element_id()) + if (LIKELY(keyframe_model->element_id())) return keyframe_model->element_id(); return element_animations->element_id(); } @@ -84,7 +84,8 @@ TargetProperties ElementAnimations::GetPropertiesMaskForAnimationState() { return properties; } -void ElementAnimations::ClearAffectedElementTypes() { +void ElementAnimations::ClearAffectedElementTypes( + const PropertyToElementIdMap& element_id_map) { DCHECK(animation_host_); TargetProperties disable_properties = GetPropertiesMaskForAnimationState(); @@ -96,7 +97,7 @@ void ElementAnimations::ClearAffectedElementTypes() { // mutator_host_client() to be null. if (has_element_in_active_list() && animation_host()->mutator_host_client()) { animation_host()->mutator_host_client()->ElementIsAnimatingChanged( - element_id(), ElementListType::ACTIVE, disabled_state_mask, + element_id_map, ElementListType::ACTIVE, disabled_state_mask, disabled_state); } set_has_element_in_active_list(false); @@ -104,7 +105,7 @@ void ElementAnimations::ClearAffectedElementTypes() { if (has_element_in_pending_list() && animation_host()->mutator_host_client()) { animation_host()->mutator_host_client()->ElementIsAnimatingChanged( - element_id(), ElementListType::PENDING, disabled_state_mask, + element_id_map, ElementListType::PENDING, disabled_state_mask, disabled_state); } set_has_element_in_pending_list(false); @@ -349,15 +350,17 @@ void ElementAnimations::UpdateClientAnimationState() { DCHECK(pending_state_.IsValid()); DCHECK(active_state_.IsValid()); + PropertyToElementIdMap element_id_map = GetPropertyToElementIdMap(); + if (has_element_in_active_list() && prev_active != active_state_) { PropertyAnimationState diff_active = prev_active ^ active_state_; animation_host()->mutator_host_client()->ElementIsAnimatingChanged( - element_id(), ElementListType::ACTIVE, diff_active, active_state_); + element_id_map, ElementListType::ACTIVE, diff_active, active_state_); } if (has_element_in_pending_list() && prev_pending != pending_state_) { PropertyAnimationState diff_pending = prev_pending ^ pending_state_; animation_host()->mutator_host_client()->ElementIsAnimatingChanged( - element_id(), ElementListType::PENDING, diff_pending, pending_state_); + element_id_map, ElementListType::PENDING, diff_pending, pending_state_); } } @@ -467,6 +470,60 @@ gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const { return gfx::ScrollOffset(); } +PropertyToElementIdMap ElementAnimations::GetPropertyToElementIdMap() const { + // As noted in the header documentation, this method assumes that each + // property type maps to at most one ElementId. This is not conceptually true + // for cc/animations, but it is true for the current clients: + // + // * ui/ does not set per-keyframe-model ElementIds, so this map will be + // each property type mapping to the same ElementId (i.e. element_id()). + // + // * blink guarantees that any two keyframe models that it creates which + // target the same property on the same target will have the same ElementId. + // + // In order to make this as little of a footgun as possible for future-us, + // this method DCHECKs that the assumption holds. + + std::vector<PropertyToElementIdMap::value_type> entries; + for (int property_index = TargetProperty::FIRST_TARGET_PROPERTY; + property_index <= TargetProperty::LAST_TARGET_PROPERTY; + ++property_index) { + TargetProperty::Type property = + static_cast<TargetProperty::Type>(property_index); + ElementId element_id_for_property; + for (auto& keyframe_effect : keyframe_effects_list_) { + KeyframeModel* model = keyframe_effect.GetKeyframeModel(property); + if (model) { + // We deliberately use two branches here so that the DCHECK can + // differentiate between models with different element ids, and the case + // where some models don't have an element id. + // TODO(crbug.com/900241): All KeyframeModels should have an ElementId. + if (model->element_id()) { + DCHECK(!element_id_for_property || + element_id_for_property == model->element_id()) + << "Different KeyframeModels for the same target must have the " + << "same ElementId"; + element_id_for_property = model->element_id(); + } else { + // This DCHECK isn't perfect; you could have a case where one model + // has an ElementId and the other doesn't, but model->element_id() == + // this->element_id() and so the DCHECK passes. That is unlikely + // enough that we don't bother guarding against it specifically. + DCHECK(!element_id_for_property || + element_id_for_property == element_id()) + << "Either all models should have an ElementId or none should"; + element_id_for_property = element_id(); + } + } + } + + if (element_id_for_property) + entries.emplace_back(property, element_id_for_property); + } + + return PropertyToElementIdMap(std::move(entries)); +} + bool ElementAnimations::KeyframeModelAffectsActiveElements( KeyframeModel* keyframe_model) const { // When we force a keyframe_model update due to a notification, we do not have diff --git a/chromium/cc/animation/element_animations.h b/chromium/cc/animation/element_animations.h index 7c51dc7900f..629379a3d2f 100644 --- a/chromium/cc/animation/element_animations.h +++ b/chromium/cc/animation/element_animations.h @@ -55,7 +55,7 @@ class CC_ANIMATION_EXPORT ElementAnimations void SetAnimationHost(AnimationHost* host); void InitAffectedElementTypes(); - void ClearAffectedElementTypes(); + void ClearAffectedElementTypes(const PropertyToElementIdMap& element_id_map); void ElementRegistered(ElementId element_id, ElementListType list_type); void ElementUnregistered(ElementId element_id, ElementListType list_type); @@ -164,6 +164,15 @@ class CC_ANIMATION_EXPORT ElementAnimations gfx::ScrollOffset ScrollOffsetForAnimation() const; + // Returns a map of target property to the ElementId for that property, for + // KeyframeEffects associated with this ElementAnimations. + // + // This method makes the assumption that a given target property doesn't map + // to more than one ElementId. While conceptually this isn't true for + // cc/animations, it is true for the two current clients (ui/ and blink) and + // this is required to let BGPT ship (see http://crbug.com/912574). + PropertyToElementIdMap GetPropertyToElementIdMap() const; + private: friend class base::RefCounted<ElementAnimations>; diff --git a/chromium/cc/animation/keyframe_model.cc b/chromium/cc/animation/keyframe_model.cc index 13b2f100cd1..d4b89dda44b 100644 --- a/chromium/cc/animation/keyframe_model.cc +++ b/chromium/cc/animation/keyframe_model.cc @@ -7,6 +7,7 @@ #include <cmath> #include "base/memory/ptr_util.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" @@ -25,7 +26,7 @@ static const char* const s_runStateNames[] = {"WAITING_FOR_TARGET_AVAILABILITY", "ABORTED_BUT_NEEDS_COMPLETION"}; static_assert(static_cast<int>(cc::KeyframeModel::LAST_RUN_STATE) + 1 == - arraysize(s_runStateNames), + base::size(s_runStateNames), "RunStateEnumSize should equal the number of elements in " "s_runStateNames"); @@ -33,7 +34,7 @@ static const char* const s_curveTypeNames[] = { "COLOR", "FLOAT", "TRANSFORM", "FILTER", "SCROLL_OFFSET", "SIZE"}; static_assert(static_cast<int>(cc::AnimationCurve::LAST_CURVE_TYPE) + 1 == - arraysize(s_curveTypeNames), + base::size(s_curveTypeNames), "CurveType enum should equal the number of elements in " "s_runStateNames"); @@ -142,14 +143,10 @@ void KeyframeModel::SetRunState(RunState run_state, } void KeyframeModel::Pause(base::TimeDelta pause_offset) { - // Convert pause offset to monotonic time. - - // TODO(crbug.com/840364): This conversion is incorrect. pause_offset is - // actually a local time so to convert it to monotonic time we should include - // total_paused_duration_ but exclude time_offset. The current calculation is - // is incorrect for animations that have start-delay or are paused and - // unpaused multiple times. - base::TimeTicks monotonic_time = pause_offset + start_time_ + time_offset_; + // Convert pause offset which is in local time to monotonic time. + // TODO(yigu): This should be scaled by playbackrate. http://crbug.com/912407 + base::TimeTicks monotonic_time = + pause_offset + start_time_ + total_paused_duration_; SetRunState(PAUSED, monotonic_time); } @@ -168,12 +165,78 @@ bool KeyframeModel::IsFinishedAt(base::TimeTicks monotonic_time) const { (ConvertMonotonicTimeToLocalTime(monotonic_time) + time_offset_); } +KeyframeModel::Phase KeyframeModel::CalculatePhaseForTesting( + base::TimeDelta local_time) const { + return CalculatePhase(local_time); +} + +KeyframeModel::Phase KeyframeModel::CalculatePhase( + base::TimeDelta local_time) const { + base::TimeDelta opposite_time_offset = time_offset_ == base::TimeDelta::Min() + ? base::TimeDelta::Max() + : -time_offset_; + base::TimeDelta before_active_boundary_time = + std::max(opposite_time_offset, base::TimeDelta()); + if (local_time < before_active_boundary_time || + (local_time == before_active_boundary_time && playback_rate_ < 0)) { + return KeyframeModel::Phase::BEFORE; + } + // Scaling the duration is against spec but needed to comply with the cc + // implementation. By spec (in blink) the playback rate is an Animation level + // concept but in cc it's per KeyframeModel. We grab the active time + // calculated here and later scale it with the playback rate in order to get a + // proper progress. Therefore we need to un-scale it here. This can be fixed + // once we scale the local time by playback rate. See + // https://crbug.com/912407. + base::TimeDelta active_duration = + curve_->Duration() * iterations_ / std::abs(playback_rate_); + // TODO(crbug.com/909794): By spec end time = max(start delay + duration + + // end delay, 0). The logic should be updated once "end delay" is supported. + base::TimeDelta active_after_boundary_time = + // Negative iterations_ represents "infinite iterations". + iterations_ >= 0 + ? std::max(opposite_time_offset + active_duration, base::TimeDelta()) + : base::TimeDelta::Max(); + if (local_time > active_after_boundary_time || + (local_time == active_after_boundary_time && playback_rate_ > 0)) { + return KeyframeModel::Phase::AFTER; + } + return KeyframeModel::Phase::ACTIVE; +} + +base::Optional<base::TimeDelta> KeyframeModel::CalculateActiveTime( + base::TimeTicks monotonic_time) const { + base::TimeDelta local_time = ConvertMonotonicTimeToLocalTime(monotonic_time); + KeyframeModel::Phase phase = CalculatePhase(local_time); + DCHECK(playback_rate_); + switch (phase) { + case KeyframeModel::Phase::BEFORE: + if (fill_mode_ == FillMode::BACKWARDS || fill_mode_ == FillMode::BOTH) + return std::max(local_time + time_offset_, base::TimeDelta()); + return base::nullopt; + case KeyframeModel::Phase::ACTIVE: + return local_time + time_offset_; + case KeyframeModel::Phase::AFTER: + if (fill_mode_ == FillMode::FORWARDS || fill_mode_ == FillMode::BOTH) { + DCHECK_GE(iterations_, 0); + base::TimeDelta active_duration = + curve_->Duration() * iterations_ / std::abs(playback_rate_); + return std::max(std::min(local_time + time_offset_, active_duration), + base::TimeDelta()); + } + return base::nullopt; + default: + NOTREACHED(); + return base::nullopt; + } +} + bool KeyframeModel::InEffect(base::TimeTicks monotonic_time) const { - return ConvertMonotonicTimeToLocalTime(monotonic_time) + time_offset_ >= - base::TimeDelta() || - (fill_mode_ == FillMode::BOTH || fill_mode_ == FillMode::BACKWARDS); + return CalculateActiveTime(monotonic_time).has_value(); } +// TODO(yigu): Local time should be scaled by playback rate by spec. +// https://crbug.com/912407. base::TimeDelta KeyframeModel::ConvertMonotonicTimeToLocalTime( base::TimeTicks monotonic_time) const { // When waiting on receiving a start time, then our global clock is 'stuck' at @@ -183,24 +246,17 @@ base::TimeDelta KeyframeModel::ConvertMonotonicTimeToLocalTime( return base::TimeDelta(); // If we're paused, time is 'stuck' at the pause time. - base::TimeTicks time = - (run_state_ == PAUSED) ? pause_time_ - time_offset_ : monotonic_time; + base::TimeTicks time = (run_state_ == PAUSED) ? pause_time_ : monotonic_time; return time - start_time_ - total_paused_duration_; } base::TimeDelta KeyframeModel::TrimTimeToCurrentIteration( base::TimeTicks monotonic_time) const { - base::TimeDelta local_time = ConvertMonotonicTimeToLocalTime(monotonic_time); - return TrimLocalTimeToCurrentIteration(local_time); -} - -base::TimeDelta KeyframeModel::TrimLocalTimeToCurrentIteration( - base::TimeDelta local_time) const { - // Check for valid parameters DCHECK(playback_rate_); DCHECK_GE(iteration_start_, 0); - base::TimeDelta active_time = local_time + time_offset_; + DCHECK(InEffect(monotonic_time)); + base::TimeDelta active_time = CalculateActiveTime(monotonic_time).value(); base::TimeDelta start_offset = curve_->Duration() * iteration_start_; // Return start offset if we are before the start of the keyframe model @@ -218,10 +274,6 @@ base::TimeDelta KeyframeModel::TrimLocalTimeToCurrentIteration( base::TimeDelta active_duration = repeated_duration / std::abs(playback_rate_); - // Check if we are past active duration - if (iterations_ > 0 && active_time >= active_duration) - active_time = active_duration; - // Calculate the scaled active time base::TimeDelta scaled_active_time; if (playback_rate_ < 0) { diff --git a/chromium/cc/animation/keyframe_model.h b/chromium/cc/animation/keyframe_model.h index 39557caa3e4..cdbb2d5c236 100644 --- a/chromium/cc/animation/keyframe_model.h +++ b/chromium/cc/animation/keyframe_model.h @@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/optional.h" #include "base/time/time.h" #include "cc/animation/animation_export.h" #include "cc/trees/element_id.h" @@ -55,6 +56,8 @@ class CC_ANIMATION_EXPORT KeyframeModel { enum class FillMode { NONE, FORWARDS, BACKWARDS, BOTH, AUTO }; + enum class Phase { BEFORE, ACTIVE, AFTER }; + static std::unique_ptr<KeyframeModel> Create( std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, @@ -169,6 +172,9 @@ class CC_ANIMATION_EXPORT KeyframeModel { } bool affects_pending_elements() const { return affects_pending_elements_; } + KeyframeModel::Phase CalculatePhaseForTesting( + base::TimeDelta local_time) const; + private: KeyframeModel(std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, @@ -202,8 +208,9 @@ class CC_ANIMATION_EXPORT KeyframeModel { base::TimeDelta ConvertMonotonicTimeToLocalTime( base::TimeTicks monotonic_time) const; - base::TimeDelta TrimLocalTimeToCurrentIteration( - base::TimeDelta local_time) const; + KeyframeModel::Phase CalculatePhase(base::TimeDelta local_time) const; + base::Optional<base::TimeDelta> CalculateActiveTime( + base::TimeTicks monotonic_time) const; std::unique_ptr<AnimationCurve> curve_; diff --git a/chromium/cc/animation/keyframe_model_unittest.cc b/chromium/cc/animation/keyframe_model_unittest.cc index 3757df9ee9f..5c853eb1246 100644 --- a/chromium/cc/animation/keyframe_model_unittest.cc +++ b/chromium/cc/animation/keyframe_model_unittest.cc @@ -350,7 +350,7 @@ TEST(KeyframeModelTest, TrimTimeStartTimeReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); keyframe_model->set_start_time(TicksFromSecondsF(4)); keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); - EXPECT_EQ(0, + EXPECT_EQ(1.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) .InSecondsF()); EXPECT_EQ(1.0, @@ -399,9 +399,6 @@ TEST(KeyframeModelTest, TrimTimeTimeOffsetReverse) { EXPECT_EQ(0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1.0)) .InSecondsF()); - EXPECT_EQ(0, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1.0)) - .InSecondsF()); } TEST(KeyframeModelTest, TrimTimeNegativeTimeOffset) { @@ -427,7 +424,7 @@ TEST(KeyframeModelTest, TrimTimeNegativeTimeOffsetReverse) { keyframe_model->set_time_offset(TimeDelta::FromMilliseconds(-4000)); keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); - EXPECT_EQ(0, + EXPECT_EQ(1.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) .InSecondsF()); EXPECT_EQ(1.0, @@ -441,16 +438,67 @@ TEST(KeyframeModelTest, TrimTimeNegativeTimeOffsetReverse) { .InSecondsF()); } +TEST(KeyframeModelTest, TrimTimePauseBasic) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + // When paused, the time returned is always the pause time + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1)) + .InSecondsF()); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.2)) + .InSecondsF()); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(2)) + .InSecondsF()); +} + +TEST(KeyframeModelTest, TrimTimePauseAffectedByDelay) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // Pause time is in local time so delay should apply on top of it. + keyframe_model->set_time_offset(TimeDelta::FromSecondsD(-0.2)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.3, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); + + keyframe_model->set_time_offset(TimeDelta::FromSecondsD(0.2)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.7, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); +} + +TEST(KeyframeModelTest, TrimTimePauseNotAffectedByStartTime) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // Pause time is in local time so start time should not affect it. + keyframe_model->set_start_time(TicksFromSecondsF(0.2)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); + + keyframe_model->set_start_time(TicksFromSecondsF(0.4)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); +} + TEST(KeyframeModelTest, TrimTimePauseResume) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); EXPECT_EQ(0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) .InSecondsF()); - EXPECT_EQ(0.5, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) + EXPECT_EQ(0.4, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.4)) .InSecondsF()); - keyframe_model->SetRunState(KeyframeModel::PAUSED, TicksFromSecondsF(0.5)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); EXPECT_EQ( 0.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) .InSecondsF()); @@ -462,6 +510,15 @@ TEST(KeyframeModelTest, TrimTimePauseResume) { EXPECT_EQ( 1, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.5)) .InSecondsF()); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.6)); + EXPECT_EQ( + 0.6, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(2000.0)) + .InSecondsF()); + keyframe_model->SetRunState(KeyframeModel::RUNNING, + TicksFromSecondsF(2000.0)); + EXPECT_EQ( + 0.7, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(2000.1)) + .InSecondsF()); } TEST(KeyframeModelTest, TrimTimePauseResumeReverse) { @@ -474,7 +531,7 @@ TEST(KeyframeModelTest, TrimTimePauseResumeReverse) { EXPECT_EQ(0.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) .InSecondsF()); - keyframe_model->SetRunState(KeyframeModel::PAUSED, TicksFromSecondsF(0.25)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.25)); EXPECT_EQ(0.75, keyframe_model ->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) .InSecondsF()); @@ -739,11 +796,12 @@ TEST(KeyframeModelTest, TrimTimePlaybackFast) { TEST(KeyframeModelTest, TrimTimePlaybackNormalReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 2, -1)); - EXPECT_EQ(0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); - EXPECT_EQ(2, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) - .InSecondsF()); + EXPECT_EQ(2.0, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) + .InSecondsF()); EXPECT_EQ(1.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) .InSecondsF()); @@ -764,11 +822,12 @@ TEST(KeyframeModelTest, TrimTimePlaybackNormalReverse) { TEST(KeyframeModelTest, TrimTimePlaybackSlowReverse) { std::unique_ptr<KeyframeModel> keyframe_model( CreateKeyframeModel(1, 2, -0.5)); - EXPECT_EQ(0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); - EXPECT_EQ(2, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) - .InSecondsF()); + EXPECT_EQ(2.0, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) + .InSecondsF()); EXPECT_EQ(1.75, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) .InSecondsF()); @@ -799,11 +858,12 @@ TEST(KeyframeModelTest, TrimTimePlaybackSlowReverse) { TEST(KeyframeModelTest, TrimTimePlaybackFastReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 2, -2)); - EXPECT_EQ(0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); - EXPECT_EQ(2, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) - .InSecondsF()); + EXPECT_EQ(2.0, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) + .InSecondsF()); EXPECT_EQ(1.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.25)) .InSecondsF()); @@ -927,7 +987,7 @@ TEST(KeyframeModelTest, TrimTimeAlternateTwoIterationsPlaybackFast) { TEST(KeyframeModelTest, TrimTimeAlternateTwoIterationsPlaybackFastReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(2, 2, 2)); keyframe_model->set_direction(KeyframeModel::Direction::ALTERNATE_REVERSE); - EXPECT_EQ(0.0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); EXPECT_EQ(2.0, @@ -1193,9 +1253,12 @@ TEST(KeyframeModelTest, TEST(KeyframeModelTest, InEffectFillMode) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // Effect before start is not InEffect EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + // Effect at start is InEffect EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); - EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + // Effect at end is not InEffect + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); @@ -1205,7 +1268,7 @@ TEST(KeyframeModelTest, InEffectFillMode) { keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); - EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); @@ -1213,27 +1276,101 @@ TEST(KeyframeModelTest, InEffectFillMode) { EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); } -TEST(KeyframeModelTest, InEffectFillModePlayback) { +TEST(KeyframeModelTest, InEffectFillModeNoneWithNegativePlaybackRate) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 1, -1)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); - EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); +} + +TEST(KeyframeModelTest, InEffectFillModeWithIterations) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(2, 1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); +} + +TEST(KeyframeModelTest, InEffectFillModeWithInfiniteIterations) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(-1, 1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); +} + +TEST(KeyframeModelTest, InEffectReverseWithIterations) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(2, 1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // KeyframeModel::direction_ doesn't affect InEffect. + keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); +} + +// CalculatePhase uses -time_offset_ which may cause integer overflow when +// time_offset_ is set to min(). This test makes sure that the code handles it +// correctly. See https://crbug.com/921454. +TEST(KeyframeModelTest, CalculatePhaseWithMinTimeOffset) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_time_offset( + TimeDelta::FromMilliseconds(std::numeric_limits<int64_t>::min())); + + // Setting the time_offset_ to min implies that the effect has a max start + // delay and any local time will fall into the BEFORE phase. + EXPECT_EQ( + keyframe_model->CalculatePhaseForTesting(TimeDelta::FromSecondsD(1.0)), + KeyframeModel::Phase::BEFORE); } TEST(KeyframeModelTest, ToString) { diff --git a/chromium/cc/animation/scroll_offset_animation_curve.cc b/chromium/cc/animation/scroll_offset_animation_curve.cc index 39d75dc22ce..fe61dc63e15 100644 --- a/chromium/cc/animation/scroll_offset_animation_curve.cc +++ b/chromium/cc/animation/scroll_offset_animation_curve.cc @@ -18,6 +18,9 @@ using DurationBehavior = cc::ScrollOffsetAnimationCurve::DurationBehavior; const double kConstantDuration = 9.0; const double kDurationDivisor = 60.0; +// 3 seconds limit for long-distance programmatic scrolls +const double kDeltaBasedMaxDuration = 180.0; + const double kInverseDeltaRampStartPx = 120.0; const double kInverseDeltaRampEndPx = 480.0; const double kInverseDeltaMinDuration = 6.0; @@ -83,7 +86,8 @@ base::TimeDelta ScrollOffsetAnimationCurve::SegmentDuration( duration = kConstantDuration; break; case DurationBehavior::DELTA_BASED: - duration = std::sqrt(std::abs(MaximumDimension(delta))); + duration = std::min(double(std::sqrt(std::abs(MaximumDimension(delta)))), + kDeltaBasedMaxDuration); break; case DurationBehavior::INVERSE_DELTA: duration = std::min( diff --git a/chromium/cc/animation/scroll_timeline.h b/chromium/cc/animation/scroll_timeline.h index c1a1dc34d76..0563ab97e6a 100644 --- a/chromium/cc/animation/scroll_timeline.h +++ b/chromium/cc/animation/scroll_timeline.h @@ -53,6 +53,17 @@ class CC_ANIMATION_EXPORT ScrollTimeline { void PromoteScrollTimelinePendingToActive(); + base::Optional<ElementId> GetActiveIdForTest() const { return active_id_; } + base::Optional<ElementId> GetPendingIdForTest() const { return pending_id_; } + ScrollDirection GetDirectionForTest() const { return direction_; } + base::Optional<double> GetStartScrollOffsetForTest() const { + return start_scroll_offset_; + } + base::Optional<double> GetEndScrollOffsetForTest() const { + return end_scroll_offset_; + } + double GetTimeRangeForTest() const { return time_range_; } + private: // The scroller which this ScrollTimeline is based on. The same underlying // scroll source may have different ids in the pending and active tree (see diff --git a/chromium/cc/animation/transform_operations.cc b/chromium/cc/animation/transform_operations.cc index 9b456185030..56061923ea2 100644 --- a/chromium/cc/animation/transform_operations.cc +++ b/chromium/cc/animation/transform_operations.cc @@ -17,17 +17,10 @@ namespace cc { -TransformOperations::TransformOperations() - : decomposed_transform_dirty_(true) { -} +TransformOperations::TransformOperations() {} TransformOperations::TransformOperations(const TransformOperations& other) { operations_ = other.operations_; - decomposed_transform_dirty_ = other.decomposed_transform_dirty_; - if (!decomposed_transform_dirty_) { - decomposed_transform_.reset( - new gfx::DecomposedTransform(*other.decomposed_transform_.get())); - } } TransformOperations::~TransformOperations() = default; @@ -35,21 +28,23 @@ TransformOperations::~TransformOperations() = default; TransformOperations& TransformOperations::operator=( const TransformOperations& other) { operations_ = other.operations_; - decomposed_transform_dirty_ = other.decomposed_transform_dirty_; - if (!decomposed_transform_dirty_) { - decomposed_transform_.reset( - new gfx::DecomposedTransform(*other.decomposed_transform_.get())); - } return *this; } gfx::Transform TransformOperations::Apply() const { + return ApplyRemaining(0); +} + +gfx::Transform TransformOperations::ApplyRemaining(size_t start) const { gfx::Transform to_return; - for (auto& operation : operations_) - to_return.PreconcatTransform(operation.matrix); + for (size_t i = start; i < operations_.size(); i++) { + to_return.PreconcatTransform(operations_[i].matrix); + } return to_return; } +// TODO(crbug.com/914397): Consolidate blink and cc implementations of transform +// interpolation. TransformOperations TransformOperations::Blend(const TransformOperations& from, SkMScalar progress) const { TransformOperations to_return; @@ -197,6 +192,23 @@ bool TransformOperations::MatchesTypes(const TransformOperations& other) const { return true; } +size_t TransformOperations::MatchingPrefixLength( + const TransformOperations& other) const { + size_t num_operations = + std::min(operations_.size(), other.operations_.size()); + for (size_t i = 0; i < num_operations; ++i) { + if (operations_[i].type != other.operations_[i].type) { + // Remaining operations in each operations list require matrix/matrix3d + // interpolation. + return i; + } + } + // If the operations match to the length of the shorter list, then pad its + // length with the matching identity operations. + // https://drafts.csswg.org/css-transforms/#transform-function-lists + return std::max(operations_.size(), other.operations_.size()); +} + bool TransformOperations::CanBlendWith( const TransformOperations& other) const { TransformOperations dummy; @@ -213,7 +225,7 @@ void TransformOperations::AppendTranslate(SkMScalar x, to_add.translate.y = y; to_add.translate.z = z; operations_.push_back(to_add); - decomposed_transform_dirty_ = true; + decomposed_transforms_.clear(); } void TransformOperations::AppendRotate(SkMScalar x, @@ -228,7 +240,7 @@ void TransformOperations::AppendRotate(SkMScalar x, to_add.rotate.angle = degrees; to_add.Bake(); operations_.push_back(to_add); - decomposed_transform_dirty_ = true; + decomposed_transforms_.clear(); } void TransformOperations::AppendScale(SkMScalar x, SkMScalar y, SkMScalar z) { @@ -239,7 +251,7 @@ void TransformOperations::AppendScale(SkMScalar x, SkMScalar y, SkMScalar z) { to_add.scale.z = z; to_add.Bake(); operations_.push_back(to_add); - decomposed_transform_dirty_ = true; + decomposed_transforms_.clear(); } void TransformOperations::AppendSkew(SkMScalar x, SkMScalar y) { @@ -249,7 +261,7 @@ void TransformOperations::AppendSkew(SkMScalar x, SkMScalar y) { to_add.skew.y = y; to_add.Bake(); operations_.push_back(to_add); - decomposed_transform_dirty_ = true; + decomposed_transforms_.clear(); } void TransformOperations::AppendPerspective(SkMScalar depth) { @@ -258,7 +270,7 @@ void TransformOperations::AppendPerspective(SkMScalar depth) { to_add.perspective_depth = depth; to_add.Bake(); operations_.push_back(to_add); - decomposed_transform_dirty_ = true; + decomposed_transforms_.clear(); } void TransformOperations::AppendMatrix(const gfx::Transform& matrix) { @@ -266,7 +278,7 @@ void TransformOperations::AppendMatrix(const gfx::Transform& matrix) { to_add.matrix = matrix; to_add.type = TransformOperation::TRANSFORM_OPERATION_MATRIX; operations_.push_back(to_add); - decomposed_transform_dirty_ = true; + decomposed_transforms_.clear(); } void TransformOperations::AppendIdentity() { @@ -275,6 +287,7 @@ void TransformOperations::AppendIdentity() { void TransformOperations::Append(const TransformOperation& operation) { operations_.push_back(operation); + decomposed_transforms_.clear(); } bool TransformOperations::IsIdentity() const { @@ -304,42 +317,44 @@ bool TransformOperations::BlendInternal(const TransformOperations& from, if (from_identity && to_identity) return true; - if (MatchesTypes(from)) { - size_t num_operations = - std::max(from_identity ? 0 : from.operations_.size(), - to_identity ? 0 : operations_.size()); - for (size_t i = 0; i < num_operations; ++i) { - TransformOperation blended; - if (!TransformOperation::BlendTransformOperations( - from_identity ? nullptr : &from.operations_[i], - to_identity ? nullptr : &operations_[i], progress, &blended)) { - return false; - } - result->Append(blended); + size_t matching_prefix_length = MatchingPrefixLength(from); + size_t from_size = from_identity ? 0 : from.operations_.size(); + size_t to_size = to_identity ? 0 : operations_.size(); + size_t num_operations = std::max(from_size, to_size); + + for (size_t i = 0; i < matching_prefix_length; ++i) { + TransformOperation blended; + if (!TransformOperation::BlendTransformOperations( + i >= from_size ? nullptr : &from.operations_[i], + i >= to_size ? nullptr : &operations_[i], progress, &blended)) { + return false; } - return true; + result->Append(blended); } - if (!ComputeDecomposedTransform() || !from.ComputeDecomposedTransform()) - return false; - - gfx::DecomposedTransform to_return; - to_return = gfx::BlendDecomposedTransforms(*decomposed_transform_.get(), - *from.decomposed_transform_.get(), - progress); - - result->AppendMatrix(ComposeTransform(to_return)); + if (matching_prefix_length < num_operations) { + if (!ComputeDecomposedTransform(matching_prefix_length) || + !from.ComputeDecomposedTransform(matching_prefix_length)) { + return false; + } + gfx::DecomposedTransform matrix_transform = gfx::BlendDecomposedTransforms( + *decomposed_transforms_[matching_prefix_length].get(), + *from.decomposed_transforms_[matching_prefix_length].get(), progress); + result->AppendMatrix(ComposeTransform(matrix_transform)); + } return true; } -bool TransformOperations::ComputeDecomposedTransform() const { - if (decomposed_transform_dirty_) { - if (!decomposed_transform_) - decomposed_transform_.reset(new gfx::DecomposedTransform()); - gfx::Transform transform = Apply(); - if (!gfx::DecomposeTransform(decomposed_transform_.get(), transform)) +bool TransformOperations::ComputeDecomposedTransform( + size_t start_offset) const { + auto it = decomposed_transforms_.find(start_offset); + if (it == decomposed_transforms_.end()) { + std::unique_ptr<gfx::DecomposedTransform> decomposed_transform = + std::make_unique<gfx::DecomposedTransform>(); + gfx::Transform transform = ApplyRemaining(start_offset); + if (!gfx::DecomposeTransform(decomposed_transform.get(), transform)) return false; - decomposed_transform_dirty_ = false; + decomposed_transforms_[start_offset] = std::move(decomposed_transform); } return true; } diff --git a/chromium/cc/animation/transform_operations.h b/chromium/cc/animation/transform_operations.h index 081da5932c9..4a6706d75d6 100644 --- a/chromium/cc/animation/transform_operations.h +++ b/chromium/cc/animation/transform_operations.h @@ -6,8 +6,10 @@ #define CC_ANIMATION_TRANSFORM_OPERATIONS_H_ #include <memory> +#include <unordered_map> #include <vector> +#include "base/gtest_prod_util.h" #include "base/logging.h" #include "base/macros.h" #include "cc/animation/animation_export.h" @@ -41,6 +43,10 @@ class CC_ANIMATION_EXPORT TransformOperations { // Returns a transformation matrix representing these transform operations. gfx::Transform Apply() const; + // Returns a transformation matrix representing the set of transform + // operations from index |start| to the end of the list. + gfx::Transform ApplyRemaining(size_t start) const; + // Given another set of transform operations and a progress in the range // [0, 1], returns a transformation matrix representing the intermediate // value. If this->MatchesTypes(from), then each of the operations are @@ -74,6 +80,12 @@ class CC_ANIMATION_EXPORT TransformOperations { // as other and its descendants. bool MatchesTypes(const TransformOperations& other) const; + // Returns the number of matching transform operations at the start of the + // transform lists. If one list is shorter but pairwise compatible, it will be + // extended with matching identity operators per spec + // (https://drafts.csswg.org/css-transforms/#interpolation-of-transforms). + size_t MatchingPrefixLength(const TransformOperations& other) const; + // Returns true if these operations can be blended. It will only return // false if we must resort to matrix interpolation, and matrix interpolation // fails (this can happen if either matrix cannot be decomposed). @@ -109,17 +121,19 @@ class CC_ANIMATION_EXPORT TransformOperations { SkMScalar tolerance) const; private: + FRIEND_TEST_ALL_PREFIXES(TransformOperationsTest, TestDecompositionCache); + bool BlendInternal(const TransformOperations& from, SkMScalar progress, TransformOperations* result) const; std::vector<TransformOperation> operations_; - bool ComputeDecomposedTransform() const; + bool ComputeDecomposedTransform(size_t start_offset) const; - // For efficiency, we cache the decomposed transform. - mutable std::unique_ptr<gfx::DecomposedTransform> decomposed_transform_; - mutable bool decomposed_transform_dirty_; + // For efficiency, we cache the decomposed transforms. + mutable std::unordered_map<size_t, std::unique_ptr<gfx::DecomposedTransform>> + decomposed_transforms_; }; } // namespace cc diff --git a/chromium/cc/animation/transform_operations_unittest.cc b/chromium/cc/animation/transform_operations_unittest.cc index ac7e5289d9f..91a6d6c1931 100644 --- a/chromium/cc/animation/transform_operations_unittest.cc +++ b/chromium/cc/animation/transform_operations_unittest.cc @@ -9,6 +9,7 @@ #include <limits> #include <vector> +#include "base/stl_util.h" #include "cc/test/geometry_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/animation/tween.h" @@ -85,7 +86,7 @@ TEST(TransformOperationTest, TransformTypesAreUnique) { } } -TEST(TransformOperationTest, MatchTypesSameLength) { +TEST(TransformOperationTest, MatchingPrefixSameLength) { TransformOperations translates; translates.AppendTranslate(1, 0, 0); translates.AppendTranslate(1, 0, 0); @@ -101,14 +102,20 @@ TEST(TransformOperationTest, MatchTypesSameLength) { translates2.AppendTranslate(0, 2, 0); translates2.AppendTranslate(0, 2, 0); + TransformOperations mixed; + mixed.AppendTranslate(0, 2, 0); + mixed.AppendScale(2, 1, 1); + mixed.AppendSkew(0, 2); + TransformOperations translates3 = translates2; - EXPECT_FALSE(translates.MatchesTypes(skews)); - EXPECT_TRUE(translates.MatchesTypes(translates2)); - EXPECT_TRUE(translates.MatchesTypes(translates3)); + EXPECT_EQ(0UL, translates.MatchingPrefixLength(skews)); + EXPECT_EQ(3UL, translates.MatchingPrefixLength(translates2)); + EXPECT_EQ(3UL, translates.MatchingPrefixLength(translates3)); + EXPECT_EQ(1UL, translates.MatchingPrefixLength(mixed)); } -TEST(TransformOperationTest, MatchTypesDifferentLength) { +TEST(TransformOperationTest, MatchingPrefixDifferentLength) { TransformOperations translates; translates.AppendTranslate(1, 0, 0); translates.AppendTranslate(1, 0, 0); @@ -122,8 +129,14 @@ TEST(TransformOperationTest, MatchTypesDifferentLength) { translates2.AppendTranslate(0, 2, 0); translates2.AppendTranslate(0, 2, 0); - EXPECT_FALSE(translates.MatchesTypes(skews)); - EXPECT_FALSE(translates.MatchesTypes(translates2)); + TransformOperations none; + + EXPECT_EQ(0UL, translates.MatchingPrefixLength(skews)); + // Pad the length of the shorter list provided all previous operation- + // pairs match per spec + // (https://drafts.csswg.org/css-transforms/#interpolation-of-transforms). + EXPECT_EQ(3UL, translates.MatchingPrefixLength(translates2)); + EXPECT_EQ(3UL, translates.MatchingPrefixLength(none)); } std::vector<std::unique_ptr<TransformOperations>> GetIdentityOperations() { @@ -180,7 +193,7 @@ std::vector<std::unique_ptr<TransformOperations>> GetIdentityOperations() { return operations; } -TEST(TransformOperationTest, MatchTypesOrder) { +TEST(TransformOperationTest, MatchingPrefixLengthOrder) { TransformOperations mix_order_identity; mix_order_identity.AppendTranslate(0, 0, 0); mix_order_identity.AppendScale(1, 1, 1); @@ -196,9 +209,9 @@ TEST(TransformOperationTest, MatchTypesOrder) { mix_order_two.AppendTranslate(1, 0, 0); mix_order_two.AppendScale(2, 1, 3); - EXPECT_TRUE(mix_order_identity.MatchesTypes(mix_order_one)); - EXPECT_FALSE(mix_order_identity.MatchesTypes(mix_order_two)); - EXPECT_FALSE(mix_order_one.MatchesTypes(mix_order_two)); + EXPECT_EQ(3UL, mix_order_identity.MatchingPrefixLength(mix_order_one)); + EXPECT_EQ(1UL, mix_order_identity.MatchingPrefixLength(mix_order_two)); + EXPECT_EQ(1UL, mix_order_one.MatchingPrefixLength(mix_order_two)); } TEST(TransformOperationTest, NoneAlwaysMatches) { @@ -207,7 +220,8 @@ TEST(TransformOperationTest, NoneAlwaysMatches) { TransformOperations none_operation; for (size_t i = 0; i < operations.size(); ++i) - EXPECT_TRUE(operations[i]->MatchesTypes(none_operation)); + EXPECT_EQ(operations[i]->size(), + operations[i]->MatchingPrefixLength(none_operation)); } TEST(TransformOperationTest, ApplyTranslate) { @@ -316,6 +330,10 @@ TEST(TransformOperationTest, BlendOrder) { SkMScalar dy2 = 20; SkMScalar dz2 = 30; + SkMScalar sx3 = 2; + SkMScalar sy3 = 1; + SkMScalar sz3 = 1; + TransformOperations operations_from; operations_from.AppendScale(sx1, sy1, sz1); operations_from.AppendTranslate(dx1, dy1, dz1); @@ -368,16 +386,54 @@ TEST(TransformOperationTest, BlendOrder) { ExpectTransformOperationEqual(expected_op, blended_op); } - // Create a mismatch, forcing matrix interpolation. - operations_to.AppendMatrix(gfx::Transform()); + TransformOperations base_operations_expected = operations_expected; + + // Create a mismatch in number of operations. Pairwise interpolation is still + // used when the operations match up to the length of the shorter list. + operations_to.AppendScale(sx3, sy3, sz3); + + gfx::Transform appended_scale; + appended_scale.Scale3d(sx3, sy3, sz3); + + gfx::Transform blended_append_scale = appended_scale; + blended_append_scale.Blend(gfx::Transform(), progress); + expected.PreconcatTransform(blended_append_scale); + + operations_expected.AppendScale( + gfx::Tween::FloatValueBetween(progress, 1, sx3), + gfx::Tween::FloatValueBetween(progress, 1, sy3), + gfx::Tween::FloatValueBetween(progress, 1, sz3)); + + blended = operations_to.Blend(operations_from, progress); + + EXPECT_TRANSFORMATION_MATRIX_EQ(expected, blended.Apply()); + EXPECT_TRANSFORMATION_MATRIX_EQ(operations_expected.Apply(), blended.Apply()); + EXPECT_EQ(operations_expected.size(), blended.size()); + for (size_t i = 0; i < operations_expected.size(); ++i) { + TransformOperation expected_op = operations_expected.at(i); + TransformOperation blended_op = blended.at(i); + SCOPED_TRACE(i); + ExpectTransformOperationEqual(expected_op, blended_op); + } + + // Create a mismatch, forcing matrix interpolation for the last operator pair. + operations_from.AppendRotate(0, 0, 1, 90); blended = operations_to.Blend(operations_from, progress); - expected = operations_to.Apply(); - expected.Blend(operations_from.Apply(), progress); + gfx::Transform transform_from; + transform_from.RotateAboutZAxis(90); + gfx::Transform transform_to; + transform_to.Scale3d(sx3, sy3, sz3); + gfx::Transform blended_matrix = transform_to; + blended_matrix.Blend(transform_from, progress); + + expected = blended_scale; + expected.PreconcatTransform(blended_translate); + expected.PreconcatTransform(blended_matrix); - operations_expected = TransformOperations(); - operations_expected.AppendMatrix(expected); + operations_expected = base_operations_expected; + operations_expected.AppendMatrix(blended_matrix); EXPECT_TRANSFORMATION_MATRIX_EQ(expected, blended.Apply()); EXPECT_TRANSFORMATION_MATRIX_EQ(operations_expected.Apply(), blended.Apply()); @@ -1028,7 +1084,7 @@ TEST(TransformOperationTest, BlendedBoundsForRotationTrivial) { // Since we're rotating 360 degrees, any box with dimensions between 0 and // 2 * sqrt(2) should give the same result. float sizes[] = { 0.f, 0.1f, sqrt_2, 2.f * sqrt_2 }; - for (size_t i = 0; i < arraysize(sizes); ++i) { + for (size_t i = 0; i < base::size(sizes); ++i) { box.set_size(sizes[i], sizes[i], 0.f); SkMScalar min_progress = 0.f; SkMScalar max_progress = 1.f; @@ -1123,7 +1179,7 @@ TEST(TransformOperationTest, BlendedBoundsForRotationProblematicAxes) { {0.f, 1.f, 1.f, gfx::BoxF(-1.f, dim1, dim1, 2.f, dim2, dim2)}, {1.f, 0.f, 1.f, gfx::BoxF(dim1, -1.f, dim1, dim2, 2.f, dim2)}}; - for (size_t i = 0; i < arraysize(tests); ++i) { + for (size_t i = 0; i < base::size(tests); ++i) { float x = tests[i].x; float y = tests[i].y; float z = tests[i].z; @@ -1262,9 +1318,9 @@ TEST(TransformOperationTest, BlendedBoundsForRotationEmpiricalTests) { {0.f, 1.f}, {-.25f, 1.25f}, }; - for (size_t i = 0; i < arraysize(axes); ++i) { - for (size_t j = 0; j < arraysize(angles); ++j) { - for (size_t k = 0; k < arraysize(progress); ++k) { + for (size_t i = 0; i < base::size(axes); ++i) { + for (size_t j = 0; j < base::size(angles); ++j) { + for (size_t k = 0; k < base::size(progress); ++k) { float x = axes[i].x; float y = axes[i].y; float z = axes[i].z; @@ -1325,8 +1381,8 @@ TEST(TransformOperationTest, BlendedBoundsForPerspective) { {0.f, 1.f}, {-0.1f, 1.1f}, }; - for (size_t i = 0; i < arraysize(perspective_depths); ++i) { - for (size_t j = 0; j < arraysize(progress); ++j) { + for (size_t i = 0; i < base::size(perspective_depths); ++i) { + for (size_t j = 0; j < base::size(progress); ++j) { TransformOperations operations_from; operations_from.AppendPerspective(perspective_depths[i].from_depth); TransformOperations operations_to; @@ -1356,8 +1412,8 @@ TEST(TransformOperationTest, BlendedBoundsForSkew) { {0.f, 1.f}, {-0.1f, 1.1f}, }; - for (size_t i = 0; i < arraysize(skews); ++i) { - for (size_t j = 0; j < arraysize(progress); ++j) { + for (size_t i = 0; i < base::size(skews); ++i) { + for (size_t j = 0; j < base::size(progress); ++j) { TransformOperations operations_from; operations_from.AppendSkew(skews[i].from_x, skews[i].from_y); TransformOperations operations_to; @@ -1681,4 +1737,60 @@ TEST(TransformOperationsTest, ApproximateEquality) { } } // namespace + +// This test is intentionally outside the anonymous namespace for visibility as +// it needs to be friend of TransformOperations. +TEST(TransformOperationsTest, TestDecompositionCache) { + TransformOperations transforms; + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a scale transform. + transforms.AppendScale(2.f, 2.f, 2.f); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(1)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(1)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(2UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a rotation transform. + transforms.AppendRotate(1, 0, 0, 45); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a translation transform. + transforms.AppendTranslate(1, 1, 1); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a skew transform. + transforms.AppendSkew(1, 0); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a perspective transform. + transforms.AppendPerspective(800); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a matrix transform. + transforms.AppendMatrix(gfx::Transform()); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); + + // Reset cache when appending a generic transform operation. + transforms.Append(TransformOperation()); + EXPECT_EQ(0UL, transforms.decomposed_transforms_.size()); + EXPECT_TRUE(transforms.ComputeDecomposedTransform(0)); + EXPECT_EQ(1UL, transforms.decomposed_transforms_.size()); +} + } // namespace cc diff --git a/chromium/cc/animation/worklet_animation_unittest.cc b/chromium/cc/animation/worklet_animation_unittest.cc index c8d009f4adf..68600f49314 100644 --- a/chromium/cc/animation/worklet_animation_unittest.cc +++ b/chromium/cc/animation/worklet_animation_unittest.cc @@ -118,12 +118,12 @@ TEST_F(WorkletAnimationTest, CurrentTimeCorrectlyUsesScrollTimeline) { worklet_animation->UpdateInputState(state.get(), base::TimeTicks::Now(), scroll_tree, true); std::unique_ptr<AnimationWorkletInput> input = - state->TakeWorkletState(worklet_animation_id_.scope_id); + state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(1234, input->added_and_updated_animations[0].current_time); } TEST_F(WorkletAnimationTest, - CurrentTimeFromDocumentTimelineIsOffsetByStartTime) { + CurrentTimeFromRegularTimelineIsOffsetByStartTime) { scoped_refptr<WorkletAnimation> worklet_animation = WorkletAnimation::Create( worklet_animation_id_, "test_name", nullptr, nullptr); @@ -141,18 +141,18 @@ TEST_F(WorkletAnimationTest, true); // First state request sets the start time and thus current time should be 0. std::unique_ptr<AnimationWorkletInput> input = - state->TakeWorkletState(worklet_animation_id_.scope_id); + state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(0, input->added_and_updated_animations[0].current_time); state.reset(new MutatorInputState); worklet_animation->UpdateInputState(state.get(), second_ticks, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(123.4, input->updated_animations[0].current_time); // Should always offset from start time. state.reset(new MutatorInputState()); worklet_animation->UpdateInputState(state.get(), third_ticks, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(246.8, input->updated_animations[0].current_time); } @@ -178,7 +178,7 @@ TEST_F(WorkletAnimationTest, UpdateInputStateProducesCorrectState) { base::TimeTicks time; worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); std::unique_ptr<AnimationWorkletInput> input = - state->TakeWorkletState(worklet_animation_id_.scope_id); + state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->added_and_updated_animations.size(), 1u); EXPECT_EQ("test_name", input->added_and_updated_animations[0].name); EXPECT_EQ(input->updated_animations.size(), 0u); @@ -189,7 +189,7 @@ TEST_F(WorkletAnimationTest, UpdateInputStateProducesCorrectState) { state.reset(new MutatorInputState()); time += base::TimeDelta::FromSecondsD(0.1); worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->added_and_updated_animations.size(), 0u); EXPECT_EQ(input->updated_animations.size(), 1u); EXPECT_EQ(input->removed_animations.size(), 0u); @@ -200,7 +200,7 @@ TEST_F(WorkletAnimationTest, UpdateInputStateProducesCorrectState) { state.reset(new MutatorInputState()); time += base::TimeDelta::FromSecondsD(0.1); worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->added_and_updated_animations.size(), 0u); EXPECT_EQ(input->updated_animations.size(), 1u); EXPECT_EQ(input->removed_animations.size(), 0u); @@ -211,7 +211,7 @@ TEST_F(WorkletAnimationTest, UpdateInputStateProducesCorrectState) { worklet_animation_->UpdateState(true, nullptr); state.reset(new MutatorInputState()); worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->added_and_updated_animations.size(), 0u); EXPECT_EQ(input->updated_animations.size(), 0u); EXPECT_EQ(input->removed_animations.size(), 1u); @@ -236,21 +236,21 @@ TEST_F(WorkletAnimationTest, SkipUnchangedAnimations) { base::TimeTicks time; worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); std::unique_ptr<AnimationWorkletInput> input = - state->TakeWorkletState(worklet_animation_id_.scope_id); + state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->added_and_updated_animations.size(), 1u); EXPECT_EQ(input->updated_animations.size(), 0u); state.reset(new MutatorInputState()); // No update on the input state if input time stays the same. worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_FALSE(input); state.reset(new MutatorInputState()); // Different input time causes the input state to be updated. time += base::TimeDelta::FromSecondsD(0.1); worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->updated_animations.size(), 1u); state.reset(new MutatorInputState()); @@ -258,7 +258,7 @@ TEST_F(WorkletAnimationTest, SkipUnchangedAnimations) { // the input time doesn't change. worklet_animation_->RemoveKeyframeModel(keyframe_model_id); worklet_animation_->UpdateInputState(state.get(), time, scroll_tree, true); - input = state->TakeWorkletState(worklet_animation_id_.scope_id); + input = state->TakeWorkletState(worklet_animation_id_.worklet_id); EXPECT_EQ(input->updated_animations.size(), 0u); EXPECT_EQ(input->removed_animations.size(), 1u); } diff --git a/chromium/cc/base/delayed_unique_notifier.cc b/chromium/cc/base/delayed_unique_notifier.cc index fa8da7ab467..741bc83c71f 100644 --- a/chromium/cc/base/delayed_unique_notifier.cc +++ b/chromium/cc/base/delayed_unique_notifier.cc @@ -13,14 +13,13 @@ namespace cc { DelayedUniqueNotifier::DelayedUniqueNotifier( base::SequencedTaskRunner* task_runner, - const base::Closure& closure, + base::RepeatingClosure closure, const base::TimeDelta& delay) : task_runner_(task_runner), - closure_(closure), + closure_(std::move(closure)), delay_(delay), notification_pending_(false), - weak_ptr_factory_(this) { -} + weak_ptr_factory_(this) {} DelayedUniqueNotifier::~DelayedUniqueNotifier() = default; diff --git a/chromium/cc/base/delayed_unique_notifier.h b/chromium/cc/base/delayed_unique_notifier.h index 86d2e37e1b8..4a7486e099a 100644 --- a/chromium/cc/base/delayed_unique_notifier.h +++ b/chromium/cc/base/delayed_unique_notifier.h @@ -21,7 +21,7 @@ class CC_BASE_EXPORT DelayedUniqueNotifier { // Configure this notifier to issue the |closure| notification in |delay| time // from Schedule() call. DelayedUniqueNotifier(base::SequencedTaskRunner* task_runner, - const base::Closure& closure, + base::RepeatingClosure closure, const base::TimeDelta& delay); // Destroying the notifier will ensure that no further notifications will @@ -56,7 +56,7 @@ class CC_BASE_EXPORT DelayedUniqueNotifier { void NotifyIfTime(); base::SequencedTaskRunner* const task_runner_; - const base::Closure closure_; + const base::RepeatingClosure closure_; const base::TimeDelta delay_; // Lock should be held before modifying |next_notification_time_| or diff --git a/chromium/cc/base/delayed_unique_notifier_unittest.cc b/chromium/cc/base/delayed_unique_notifier_unittest.cc index 8731cb0ba73..16ee60687a8 100644 --- a/chromium/cc/base/delayed_unique_notifier_unittest.cc +++ b/chromium/cc/base/delayed_unique_notifier_unittest.cc @@ -16,9 +16,9 @@ namespace { class TestNotifier : public DelayedUniqueNotifier { public: TestNotifier(base::SequencedTaskRunner* task_runner, - const base::Closure& closure, + base::RepeatingClosure closure, const base::TimeDelta& delay) - : DelayedUniqueNotifier(task_runner, closure, delay) {} + : DelayedUniqueNotifier(task_runner, std::move(closure), delay) {} ~TestNotifier() override = default; // Overridden from DelayedUniqueNotifier: @@ -54,10 +54,10 @@ class DelayedUniqueNotifierTest : public testing::Test { TEST_F(DelayedUniqueNotifierTest, ZeroDelay) { base::TimeDelta delay; // Zero delay. - TestNotifier notifier( - task_runner_.get(), - base::Bind(&DelayedUniqueNotifierTest::Notify, base::Unretained(this)), - delay); + TestNotifier notifier(task_runner_.get(), + base::BindRepeating(&DelayedUniqueNotifierTest::Notify, + base::Unretained(this)), + delay); EXPECT_EQ(0, NotificationCount()); @@ -89,10 +89,10 @@ TEST_F(DelayedUniqueNotifierTest, ZeroDelay) { TEST_F(DelayedUniqueNotifierTest, SmallDelay) { base::TimeDelta delay = base::TimeDelta::FromMicroseconds(20); - TestNotifier notifier( - task_runner_.get(), - base::Bind(&DelayedUniqueNotifierTest::Notify, base::Unretained(this)), - delay); + TestNotifier notifier(task_runner_.get(), + base::BindRepeating(&DelayedUniqueNotifierTest::Notify, + base::Unretained(this)), + delay); EXPECT_EQ(0, NotificationCount()); @@ -149,10 +149,10 @@ TEST_F(DelayedUniqueNotifierTest, SmallDelay) { TEST_F(DelayedUniqueNotifierTest, RescheduleDelay) { base::TimeDelta delay = base::TimeDelta::FromMicroseconds(20); - TestNotifier notifier( - task_runner_.get(), - base::Bind(&DelayedUniqueNotifierTest::Notify, base::Unretained(this)), - delay); + TestNotifier notifier(task_runner_.get(), + base::BindRepeating(&DelayedUniqueNotifierTest::Notify, + base::Unretained(this)), + delay); base::TimeTicks schedule_time; // Move time 19 units forward and reschedule, expecting that we still need to @@ -191,10 +191,10 @@ TEST_F(DelayedUniqueNotifierTest, RescheduleDelay) { TEST_F(DelayedUniqueNotifierTest, CancelAndHasPendingNotification) { base::TimeDelta delay = base::TimeDelta::FromMicroseconds(20); - TestNotifier notifier( - task_runner_.get(), - base::Bind(&DelayedUniqueNotifierTest::Notify, base::Unretained(this)), - delay); + TestNotifier notifier(task_runner_.get(), + base::BindRepeating(&DelayedUniqueNotifierTest::Notify, + base::Unretained(this)), + delay); EXPECT_EQ(0, NotificationCount()); @@ -261,10 +261,10 @@ TEST_F(DelayedUniqueNotifierTest, CancelAndHasPendingNotification) { TEST_F(DelayedUniqueNotifierTest, ShutdownWithScheduledTask) { base::TimeDelta delay = base::TimeDelta::FromMicroseconds(20); - TestNotifier notifier( - task_runner_.get(), - base::Bind(&DelayedUniqueNotifierTest::Notify, base::Unretained(this)), - delay); + TestNotifier notifier(task_runner_.get(), + base::BindRepeating(&DelayedUniqueNotifierTest::Notify, + base::Unretained(this)), + delay); EXPECT_EQ(0, NotificationCount()); @@ -302,10 +302,10 @@ TEST_F(DelayedUniqueNotifierTest, ShutdownWithScheduledTask) { TEST_F(DelayedUniqueNotifierTest, ShutdownPreventsSchedule) { base::TimeDelta delay = base::TimeDelta::FromMicroseconds(20); - TestNotifier notifier( - task_runner_.get(), - base::Bind(&DelayedUniqueNotifierTest::Notify, base::Unretained(this)), - delay); + TestNotifier notifier(task_runner_.get(), + base::BindRepeating(&DelayedUniqueNotifierTest::Notify, + base::Unretained(this)), + delay); EXPECT_EQ(0, NotificationCount()); diff --git a/chromium/cc/base/index_rect_unittest.cc b/chromium/cc/base/index_rect_unittest.cc index aff41ee9759..1580a3947e7 100644 --- a/chromium/cc/base/index_rect_unittest.cc +++ b/chromium/cc/base/index_rect_unittest.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/macros.h" #include "cc/base/index_rect.h" +#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -22,7 +22,7 @@ TEST(IndexRectTest, NumIndices) { {0, 0, 0, 0, 1, 1}, {10, 10, 10, 10, 1, 1}}; - for (size_t i = 0; i < arraysize(num_indices_cases); ++i) { + for (size_t i = 0; i < base::size(num_indices_cases); ++i) { const NumIndicesCase& value = num_indices_cases[i]; IndexRect rect(value.left, value.right, value.top, value.bottom); EXPECT_EQ(value.num_indices_x, rect.num_indices_x()); @@ -49,7 +49,7 @@ TEST(IndexRectTest, ClampTo) { {{-10, 5, -10, 5}, {0, 10, 0, 10}, {0, 5, 0, 5}, true}, {{0, 5, 0, 5}, {10, 20, 10, 20}, {0, 0, 0, 0}, false}}; - for (size_t i = 0; i < arraysize(clamp_to_cases); ++i) { + for (size_t i = 0; i < base::size(clamp_to_cases); ++i) { const ClampToCase& value = clamp_to_cases[i]; IndexRect first(value.first.left, value.first.right, value.first.top, value.first.bottom); @@ -82,7 +82,7 @@ TEST(IndexRectTest, Contains) { {-10, 10, -10, 10, 20, 20, false}, {-10, 10, -10, 10, 20, 5, false}, {-10, 10, -10, 10, 5, 20, false}}; - for (size_t i = 0; i < arraysize(contains_cases); ++i) { + for (size_t i = 0; i < base::size(contains_cases); ++i) { const ContainsCase& value = contains_cases[i]; IndexRect rect(value.left, value.right, value.top, value.bottom); EXPECT_EQ(value.contained, rect.Contains(value.index_x, value.index_y)); diff --git a/chromium/cc/base/switches.cc b/chromium/cc/base/switches.cc index d363fe84b1d..22db5dd0254 100644 --- a/chromium/cc/base/switches.cc +++ b/chromium/cc/base/switches.cc @@ -48,10 +48,6 @@ const char kCheckDamageEarly[] = "check-damage-early"; // Enables the GPU benchmarking extension const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking"; -// Always asks the display compositor to send back presentation times. -const char kAlwaysRequestPresentationTime[] = - "always-request-presentation-time"; - // Renders a border around compositor layers to help debug and study // layer compositing. const char kShowCompositedLayerBorders[] = "show-composited-layer-borders"; diff --git a/chromium/cc/base/switches.h b/chromium/cc/base/switches.h index fe8de281021..cde4700a15d 100644 --- a/chromium/cc/base/switches.h +++ b/chromium/cc/base/switches.h @@ -29,7 +29,6 @@ CC_BASE_EXPORT extern const char kCheckDamageEarly[]; // Switches for both the renderer and ui compositors. CC_BASE_EXPORT extern const char kEnableGpuBenchmarking[]; -CC_BASE_EXPORT extern const char kAlwaysRequestPresentationTime[]; // Debug visualizations. CC_BASE_EXPORT extern const char kShowCompositedLayerBorders[]; diff --git a/chromium/cc/base/unique_notifier.cc b/chromium/cc/base/unique_notifier.cc index 2ad6a291c73..52e7a498de3 100644 --- a/chromium/cc/base/unique_notifier.cc +++ b/chromium/cc/base/unique_notifier.cc @@ -12,12 +12,11 @@ namespace cc { UniqueNotifier::UniqueNotifier(base::SequencedTaskRunner* task_runner, - const base::Closure& closure) + base::RepeatingClosure closure) : task_runner_(task_runner), - closure_(closure), + closure_(std::move(closure)), notification_pending_(false), - weak_ptr_factory_(this) { -} + weak_ptr_factory_(this) {} UniqueNotifier::~UniqueNotifier() = default; diff --git a/chromium/cc/base/unique_notifier.h b/chromium/cc/base/unique_notifier.h index d753e1f352a..ff129c8b525 100644 --- a/chromium/cc/base/unique_notifier.h +++ b/chromium/cc/base/unique_notifier.h @@ -22,7 +22,7 @@ class CC_BASE_EXPORT UniqueNotifier { public: // Configure this notifier to issue the |closure| notification when scheduled. UniqueNotifier(base::SequencedTaskRunner* task_runner, - const base::Closure& closure); + base::RepeatingClosure closure); // Destroying the notifier will ensure that no further notifications will // happen from this class. @@ -40,7 +40,7 @@ class CC_BASE_EXPORT UniqueNotifier { // TODO(dcheng): How come this doesn't need to hold a ref to the task runner? base::SequencedTaskRunner* const task_runner_; - const base::Closure closure_; + const base::RepeatingClosure closure_; // Lock should be held before modifying |notification_pending_|. base::Lock lock_; diff --git a/chromium/cc/base/unique_notifier_unittest.cc b/chromium/cc/base/unique_notifier_unittest.cc index cfac61efaef..a7995e29d10 100644 --- a/chromium/cc/base/unique_notifier_unittest.cc +++ b/chromium/cc/base/unique_notifier_unittest.cc @@ -49,9 +49,9 @@ class UniqueNotifierTest : public testing::Test { // 50000 can be any number bigger than 1. The bigger the easier to more runs. TEST_F(UniqueNotifierTest, Schedule) { { - UniqueNotifier notifier( - base::ThreadTaskRunnerHandle::Get().get(), - base::Bind(&UniqueNotifierTest::Notify, base::Unretained(this))); + UniqueNotifier notifier(base::ThreadTaskRunnerHandle::Get().get(), + base::BindRepeating(&UniqueNotifierTest::Notify, + base::Unretained(this))); EXPECT_EQ(0, NotificationCount()); diff --git a/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc b/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc index 355447a6d00..171351e1c9b 100644 --- a/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc +++ b/chromium/cc/benchmarks/micro_benchmark_controller_unittest.cc @@ -76,7 +76,7 @@ TEST_F(MicroBenchmarkControllerTest, BenchmarkRan) { int run_count = 0; int id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", nullptr, - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); layer_tree_host_->UpdateLayers(); @@ -88,11 +88,11 @@ TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) { int run_count = 0; int id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", nullptr, - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", nullptr, - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); layer_tree_host_->UpdateLayers(); @@ -101,11 +101,11 @@ TEST_F(MicroBenchmarkControllerTest, MultipleBenchmarkRan) { id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", nullptr, - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", nullptr, - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); layer_tree_host_->UpdateLayers(); @@ -123,7 +123,7 @@ TEST_F(MicroBenchmarkControllerTest, BenchmarkImplRan) { // Schedule a main thread benchmark. int id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", std::move(settings), - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); // Schedule impl benchmarks. In production code, this is run in commit. @@ -151,7 +151,7 @@ TEST_F(MicroBenchmarkControllerTest, SendMessage) { int run_count = 0; int id = layer_tree_host_->ScheduleMicroBenchmark( "unittest_only_benchmark", nullptr, - base::Bind(&IncrementCallCount, base::Unretained(&run_count))); + base::BindOnce(&IncrementCallCount, base::Unretained(&run_count))); EXPECT_GT(id, 0); // Send valid message to valid benchmark diff --git a/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc b/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc index 5d1afd1357b..a8c606ac470 100644 --- a/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc +++ b/chromium/cc/benchmarks/rasterize_and_record_benchmark.cc @@ -131,8 +131,8 @@ RasterizeAndRecordBenchmark::CreateBenchmarkImpl( scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner) { return base::WrapUnique(new RasterizeAndRecordBenchmarkImpl( origin_task_runner, settings_.get(), - base::Bind(&RasterizeAndRecordBenchmark::RecordRasterResults, - weak_ptr_factory_.GetWeakPtr()))); + base::BindOnce(&RasterizeAndRecordBenchmark::RecordRasterResults, + weak_ptr_factory_.GetWeakPtr()))); } void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) { diff --git a/chromium/cc/benchmarks/unittest_only_benchmark.cc b/chromium/cc/benchmarks/unittest_only_benchmark.cc index 10724d47f98..4e32942140a 100644 --- a/chromium/cc/benchmarks/unittest_only_benchmark.cc +++ b/chromium/cc/benchmarks/unittest_only_benchmark.cc @@ -61,8 +61,8 @@ std::unique_ptr<MicroBenchmarkImpl> UnittestOnlyBenchmark::CreateBenchmarkImpl( return base::WrapUnique(new UnittestOnlyBenchmarkImpl( origin_task_runner, nullptr, - base::Bind(&UnittestOnlyBenchmark::RecordImplResults, - weak_ptr_factory_.GetWeakPtr()))); + base::BindOnce(&UnittestOnlyBenchmark::RecordImplResults, + weak_ptr_factory_.GetWeakPtr()))); } } // namespace cc diff --git a/chromium/cc/input/layer_selection_bound.cc b/chromium/cc/input/layer_selection_bound.cc index 521cd653f59..55f2e3a5fb4 100644 --- a/chromium/cc/input/layer_selection_bound.cc +++ b/chromium/cc/input/layer_selection_bound.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/logging.h" +#include "base/strings/stringprintf.h" #include "cc/input/layer_selection_bound.h" namespace cc { @@ -22,4 +23,10 @@ bool LayerSelectionBound::operator!=(const LayerSelectionBound& other) const { return !(*this == other); } +std::string LayerSelectionBound::ToString() const { + return base::StringPrintf("LayerSelectionBound(%s, %s, %d)", + edge_top.ToString().c_str(), + edge_bottom.ToString().c_str(), hidden); +} + } // namespace cc diff --git a/chromium/cc/input/layer_selection_bound.h b/chromium/cc/input/layer_selection_bound.h index 5174341909b..a2a2583c143 100644 --- a/chromium/cc/input/layer_selection_bound.h +++ b/chromium/cc/input/layer_selection_bound.h @@ -26,6 +26,8 @@ struct CC_EXPORT LayerSelectionBound { // content of the layer (as opposed to being outside of the layer's bounds). bool hidden; + std::string ToString() const; + bool operator==(const LayerSelectionBound& other) const; bool operator!=(const LayerSelectionBound& other) const; }; diff --git a/chromium/cc/input/main_thread_scrolling_reason.cc b/chromium/cc/input/main_thread_scrolling_reason.cc index 728708ce776..5d1a6b9c5a9 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.cc +++ b/chromium/cc/input/main_thread_scrolling_reason.cc @@ -35,8 +35,8 @@ void MainThreadScrollingReason::AddToTracedValue( traced_value.AppendString("Threaded scrolling is disabled"); if (reasons & kScrollbarScrolling) traced_value.AppendString("Scrollbar scrolling"); - if (reasons & kPageOverlay) - traced_value.AppendString("Page overlay"); + if (reasons & kFrameOverlay) + traced_value.AppendString("Frame overlay"); if (reasons & kHandlingScrollFromMainThread) traced_value.AppendString("Handling scroll from main thread"); if (reasons & kCustomScrollbarScrolling) diff --git a/chromium/cc/input/main_thread_scrolling_reason.h b/chromium/cc/input/main_thread_scrolling_reason.h index 732c3fa904b..6878928bfe7 100644 --- a/chromium/cc/input/main_thread_scrolling_reason.h +++ b/chromium/cc/input/main_thread_scrolling_reason.h @@ -28,7 +28,7 @@ struct CC_EXPORT MainThreadScrollingReason { kHasNonLayerViewportConstrainedObjects = 1 << 1, kThreadedScrollingDisabled = 1 << 2, kScrollbarScrolling = 1 << 3, - kPageOverlay = 1 << 4, + kFrameOverlay = 1 << 4, // This bit is set when any of the other main thread scrolling reasons cause // an input event to be handled on the main thread, and the main thread @@ -80,7 +80,7 @@ struct CC_EXPORT MainThreadScrollingReason { uint32_t reasons_set_by_main_thread = kNotScrollingOnMain | kHasBackgroundAttachmentFixedObjects | kHasNonLayerViewportConstrainedObjects | kThreadedScrollingDisabled | - kScrollbarScrolling | kPageOverlay | kHandlingScrollFromMainThread | + kScrollbarScrolling | kFrameOverlay | kHandlingScrollFromMainThread | kCustomScrollbarScrolling; return (reasons & reasons_set_by_main_thread) == reasons; } diff --git a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc index 7560dda71d9..c6ab9e4a61f 100644 --- a/chromium/cc/input/main_thread_scrolling_reason_unittest.cc +++ b/chromium/cc/input/main_thread_scrolling_reason_unittest.cc @@ -17,7 +17,7 @@ TEST_F(MainThreadScrollingReasonTest, AsText) { "Has non-layer viewport-constrained objects," "Threaded scrolling is disabled," "Scrollbar scrolling," - "Page overlay," + "Frame overlay," "Handling scroll from main thread," "Custom scrollbar scrolling," "Has opacity and LCD text," diff --git a/chromium/cc/input/scroll_snap_data.cc b/chromium/cc/input/scroll_snap_data.cc index 3fc17474fc7..3d4ad87e1ba 100644 --- a/chromium/cc/input/scroll_snap_data.cc +++ b/chromium/cc/input/scroll_snap_data.cc @@ -153,24 +153,42 @@ base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea( SearchAxis axis, const SnapSelectionStrategy& strategy, const SnapSearchResult& cros_axis_snap_result) const { + base::Optional<SnapSearchResult> result = + FindClosestValidAreaInternal(axis, strategy, cros_axis_snap_result); + // Our current direction based strategies are too strict ignoring the other + // directions even when we have no candidate in the given direction. This is + // particularly problematic with mandatory snap points and for fling + // gestures. To counteract this, if the direction based strategy finds no + // candidates, we do a second search ignoring the direction (this is + // implemented by using an equivalent EndPosition strategy). + if (result.has_value() || + scroll_snap_type_.strictness == SnapStrictness::kProximity || + !strategy.HasIntendedDirection()) + return result; + + std::unique_ptr<SnapSelectionStrategy> relaxed_strategy = + SnapSelectionStrategy::CreateForEndPosition(strategy.current_position(), + strategy.ShouldSnapOnX(), + strategy.ShouldSnapOnY()); + return FindClosestValidAreaInternal(axis, *relaxed_strategy, + cros_axis_snap_result); +} + +base::Optional<SnapSearchResult> +SnapContainerData::FindClosestValidAreaInternal( + SearchAxis axis, + const SnapSelectionStrategy& strategy, + const SnapSearchResult& cros_axis_snap_result) const { // The search result from the snap area that's closest to the search origin. base::Optional<SnapSearchResult> closest; // The search result with the intended position if it makes a snap area cover // the snapport. base::Optional<SnapSearchResult> covering; - // The search result with the current position as a backup in case no other - // valid snap position exists. - base::Optional<SnapSearchResult> current; // The valid snap positions immediately before and after the current position. float prev = std::numeric_limits<float>::lowest(); float next = std::numeric_limits<float>::max(); - // The current position before the scroll or snap happens. If no other snap - // position exists, this would become a backup option. - float current_position = axis == SearchAxis::kX - ? strategy.current_position().x() - : strategy.current_position().y(); // The intended position of the scroll operation if there's no snap. This // scroll position becomes the covering candidate if there is a snap area that // fully covers the snapport if this position is scrolled to. @@ -203,24 +221,22 @@ base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea( } if (!IsMutualVisible(candidate, cros_axis_snap_result)) continue; - if (!strategy.IsValidSnapPosition(axis, candidate.snap_offset())) { - if (candidate.snap_offset() == current_position && - scroll_snap_type_.strictness == SnapStrictness::kMandatory) { - SetOrUpdateResult(candidate, ¤t); - } - continue; - } + float distance = std::abs(candidate.snap_offset() - base_position); - if (distance < smallest_distance) { - smallest_distance = distance; - closest = candidate; + if (strategy.IsValidSnapPosition(axis, candidate.snap_offset())) { + if (distance < smallest_distance) { + smallest_distance = distance; + closest = candidate; + } } if (candidate.snap_offset() < intended_position && - candidate.snap_offset() > prev) + candidate.snap_offset() > prev) { prev = candidate.snap_offset(); + } if (candidate.snap_offset() > intended_position && - candidate.snap_offset() < next) + candidate.snap_offset() < next) { next = candidate.snap_offset(); + } } // According to the spec [1], if the snap area is covering the snapport, the // scroll position is a valid snap position only if the distance between the @@ -235,7 +251,7 @@ base::Optional<SnapSearchResult> SnapContainerData::FindClosestValidArea( const base::Optional<SnapSearchResult>& picked = strategy.PickBestResult(closest, covering); - return picked.has_value() ? picked : current; + return picked; } SnapSearchResult SnapContainerData::GetSnapSearchResult( diff --git a/chromium/cc/input/scroll_snap_data.h b/chromium/cc/input/scroll_snap_data.h index 3057acf339e..3a8da213404 100644 --- a/chromium/cc/input/scroll_snap_data.h +++ b/chromium/cc/input/scroll_snap_data.h @@ -218,6 +218,15 @@ class CC_EXPORT SnapContainerData { // or the original scroll offset if this is the first iteration of search. // Returns the candidate as SnapSearchResult that includes the area's // |snap_offset| and its visible range on the cross axis. + base::Optional<SnapSearchResult> FindClosestValidAreaInternal( + SearchAxis axis, + const SnapSelectionStrategy& strategy, + const SnapSearchResult& cross_axis_snap_result) const; + + // A wrapper of FindClosestValidAreaInternal(). If + // FindClosestValidAreaInternal() doesn't return a valid result when the snap + // type is mandatory and the strategy has an intended direction, we relax the + // strategy to ignore the direction and find again. base::Optional<SnapSearchResult> FindClosestValidArea( SearchAxis axis, const SnapSelectionStrategy& strategy, diff --git a/chromium/cc/input/scroll_snap_data_unittest.cc b/chromium/cc/input/scroll_snap_data_unittest.cc index 6f994d543a0..3d95014f51f 100644 --- a/chromium/cc/input/scroll_snap_data_unittest.cc +++ b/chromium/cc/input/scroll_snap_data_unittest.cc @@ -229,4 +229,82 @@ TEST_F(ScrollSnapDataTest, DoesNotSnapToPositionsOutsideProximityRange) { EXPECT_EQ(100, snap_position.y()); } +TEST_F(ScrollSnapDataTest, MandatoryReturnsToCurrentIfNoValidAreaForward) { + SnapContainerData container( + ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), + gfx::RectF(0, 0, 200, 200), gfx::ScrollOffset(2000, 2000)); + SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), + gfx::RectF(600, 0, 100, 100), false); + container.AddSnapAreaData(area); + gfx::ScrollOffset snap_position; + + std::unique_ptr<SnapSelectionStrategy> direction_strategy = + SnapSelectionStrategy::CreateForDirection(gfx::ScrollOffset(600, 0), + gfx::ScrollOffset(5, 0)); + EXPECT_TRUE(container.FindSnapPosition(*direction_strategy, &snap_position)); + // The snap direction is right. However, there is no valid snap position on + // that direction. So we have to stay at the current snap position of 600 as + // the snap type is mandatory. + EXPECT_EQ(600, snap_position.x()); + EXPECT_EQ(0, snap_position.y()); + + std::unique_ptr<SnapSelectionStrategy> end_direction_strategy = + SnapSelectionStrategy::CreateForEndAndDirection( + gfx::ScrollOffset(600, 0), gfx::ScrollOffset(15, 15)); + EXPECT_TRUE( + container.FindSnapPosition(*end_direction_strategy, &snap_position)); + // The snap direction is down and right. However, there is no valid snap + // position on that direction. So we have to stay at the current snap position + // of (600, 0) as the snap type is mandatory. + EXPECT_EQ(600, snap_position.x()); + EXPECT_EQ(0, snap_position.y()); + + // If the scroll-snap-type is proximity, we wouldn't consider the current + // snap area valid even if there is no snap area forward. + container.set_scroll_snap_type( + ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kProximity)); + EXPECT_FALSE(container.FindSnapPosition(*direction_strategy, &snap_position)); + EXPECT_FALSE( + container.FindSnapPosition(*end_direction_strategy, &snap_position)); +} + +TEST_F(ScrollSnapDataTest, MandatorySnapsBackwardIfNoValidAreaForward) { + SnapContainerData container( + ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), + gfx::RectF(0, 0, 200, 200), gfx::ScrollOffset(2000, 2000)); + SnapAreaData area(ScrollSnapAlign(SnapAlignment::kStart), + gfx::RectF(600, 0, 100, 100), false); + container.AddSnapAreaData(area); + gfx::ScrollOffset snap_position; + + std::unique_ptr<SnapSelectionStrategy> direction_strategy = + SnapSelectionStrategy::CreateForDirection(gfx::ScrollOffset(650, 0), + gfx::ScrollOffset(5, 0)); + EXPECT_TRUE(container.FindSnapPosition(*direction_strategy, &snap_position)); + // The snap direction is right. However, there is no valid snap position on + // that direction. So we have to scroll back to the snap position of 600 as + // the snap type is mandatory. + EXPECT_EQ(600, snap_position.x()); + EXPECT_EQ(0, snap_position.y()); + + std::unique_ptr<SnapSelectionStrategy> end_direction_strategy = + SnapSelectionStrategy::CreateForEndAndDirection( + gfx::ScrollOffset(650, 10), gfx::ScrollOffset(15, 15)); + EXPECT_TRUE( + container.FindSnapPosition(*end_direction_strategy, &snap_position)); + // The snap direction is down and right. However, there is no valid snap + // position on that direction. So we have to scroll back to the snap position + // of (600, 0) as the snap type is mandatory. + EXPECT_EQ(600, snap_position.x()); + EXPECT_EQ(0, snap_position.y()); + + // If the scroll-snap-type is proximity, we wouldn't consider the backward + // snap area valid even if there is no snap area forward. + container.set_scroll_snap_type( + ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kProximity)); + EXPECT_FALSE(container.FindSnapPosition(*direction_strategy, &snap_position)); + EXPECT_FALSE( + container.FindSnapPosition(*end_direction_strategy, &snap_position)); +} + } // namespace cc diff --git a/chromium/cc/input/scrollbar_animation_controller.cc b/chromium/cc/input/scrollbar_animation_controller.cc index 55f97f09d1f..0e57be6414b 100644 --- a/chromium/cc/input/scrollbar_animation_controller.cc +++ b/chromium/cc/input/scrollbar_animation_controller.cc @@ -124,8 +124,8 @@ void ScrollbarAnimationController::PostDelayedAnimation( animation_change_ = animation_change; delayed_scrollbar_animation_.Cancel(); delayed_scrollbar_animation_.Reset( - base::Bind(&ScrollbarAnimationController::StartAnimation, - weak_factory_.GetWeakPtr())); + base::BindOnce(&ScrollbarAnimationController::StartAnimation, + weak_factory_.GetWeakPtr())); client_->PostDelayedScrollbarAnimationTask( delayed_scrollbar_animation_.callback(), fade_delay_); } diff --git a/chromium/cc/input/scrollbar_animation_controller.h b/chromium/cc/input/scrollbar_animation_controller.h index 9473b416bf8..f7a26c523f4 100644 --- a/chromium/cc/input/scrollbar_animation_controller.h +++ b/chromium/cc/input/scrollbar_animation_controller.h @@ -18,7 +18,7 @@ namespace cc { class CC_EXPORT ScrollbarAnimationControllerClient { public: - virtual void PostDelayedScrollbarAnimationTask(const base::Closure& task, + virtual void PostDelayedScrollbarAnimationTask(base::OnceClosure task, base::TimeDelta delay) = 0; virtual void SetNeedsRedrawForScrollbarAnimation() = 0; virtual void SetNeedsAnimateForScrollbarAnimation() = 0; @@ -153,7 +153,7 @@ class CC_EXPORT ScrollbarAnimationController { bool currently_scrolling_; bool show_in_fast_scroll_; - base::CancelableClosure delayed_scrollbar_animation_; + base::CancelableOnceClosure delayed_scrollbar_animation_; float opacity_; diff --git a/chromium/cc/input/scrollbar_animation_controller_unittest.cc b/chromium/cc/input/scrollbar_animation_controller_unittest.cc index e9f336ff695..0836aeb1afa 100644 --- a/chromium/cc/input/scrollbar_animation_controller_unittest.cc +++ b/chromium/cc/input/scrollbar_animation_controller_unittest.cc @@ -37,9 +37,9 @@ class MockScrollbarAnimationControllerClient : host_impl_(host_impl) {} ~MockScrollbarAnimationControllerClient() override = default; - void PostDelayedScrollbarAnimationTask(const base::Closure& start_fade, + void PostDelayedScrollbarAnimationTask(base::OnceClosure start_fade, base::TimeDelta delay) override { - start_fade_ = start_fade; + start_fade_ = std::move(start_fade); delay_ = delay; } void SetNeedsRedrawForScrollbarAnimation() override {} @@ -49,11 +49,11 @@ class MockScrollbarAnimationControllerClient } MOCK_METHOD0(DidChangeScrollbarVisibility, void()); - base::Closure& start_fade() { return start_fade_; } + base::OnceClosure& start_fade() { return start_fade_; } base::TimeDelta& delay() { return delay_; } private: - base::Closure start_fade_; + base::OnceClosure start_fade_; base::TimeDelta delay_; LayerTreeHostImpl* host_impl_; }; @@ -108,12 +108,12 @@ class ScrollbarAnimationControllerAuraOverlayTest : public testing::Test { host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); v_scrollbar_layer_->SetBounds(gfx::Size(kThumbThickness, kTrackLength)); - v_scrollbar_layer_->SetPosition(gfx::PointF(90, 0)); + v_scrollbar_layer_->test_properties()->position = gfx::PointF(90, 0); v_scrollbar_layer_->SetScrollElementId(scroll_layer_ptr->element_id()); v_scrollbar_layer_->test_properties()->opacity_can_animate = true; h_scrollbar_layer_->SetBounds(gfx::Size(kTrackLength, kThumbThickness)); - h_scrollbar_layer_->SetPosition(gfx::PointF(0, 90)); + h_scrollbar_layer_->test_properties()->position = gfx::PointF(0, 90); h_scrollbar_layer_->SetScrollElementId(scroll_layer_ptr->element_id()); h_scrollbar_layer_->test_properties()->opacity_can_animate = true; @@ -261,7 +261,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicAppearAndFadeOut) { // An fade out animation should have been enqueued. EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); - client_.start_fade().Run(); + std::move(client_.start_fade()).Run(); // Scrollbar should fade out over kFadeDuration. scrollbar_controller_->Animate(time); @@ -290,7 +290,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, // An fade out animation should have been enqueued. EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); - client_.start_fade().Run(); + std::move(client_.start_fade()).Run(); // Scrollbar should fade out over kFadeDuration. scrollbar_controller_->Animate(time); @@ -651,7 +651,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, // A fade out animation should have been enqueued. Start it. EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); - client_.start_fade().Run(); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(1); @@ -691,7 +691,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, TestCantCaptureWhenFaded) { EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); EXPECT_FALSE(client_.start_fade().IsCancelled()); - client_.start_fade().Run(); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); ExpectScrollbarsOpacity(1); @@ -736,8 +736,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, TestCantCaptureWhenFaded) { EXPECT_EQ(kFadeDelay, client_.delay()); // Play the delay animation. - client_.start_fade().Run(); - EXPECT_TRUE(client_.start_fade().IsCancelled()); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); time += kFadeDuration; @@ -831,7 +830,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, FadeAnimated) { // An fade out animation should have been enqueued. EXPECT_EQ(kFadeDelay, client_.delay()); EXPECT_FALSE(client_.start_fade().is_null()); - client_.start_fade().Run(); + std::move(client_.start_fade()).Run(); // Test that at half the fade duration time, the opacity is at half. scrollbar_controller_->Animate(time); @@ -865,7 +864,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, NotifyChangedVisibility) { // to) notify during the animation that the scrollbars are still visible. EXPECT_CALL(client_, DidChangeScrollbarVisibility()).Times(0); ASSERT_FALSE(client_.start_fade().is_null()); - client_.start_fade().Run(); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); time += kFadeDuration / 4; EXPECT_FALSE(scrollbar_controller_->ScrollbarsHidden()); @@ -1123,8 +1122,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, BasicMouseHoverFadeIn) { EXPECT_EQ(kFadeDelay, client_.delay()); // Play the delay animation. - client_.start_fade().Run(); - EXPECT_TRUE(client_.start_fade().IsCancelled()); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); time += kFadeDuration / 2; @@ -1156,13 +1154,13 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, EXPECT_FALSE(client_.start_fade().IsCancelled()); EXPECT_EQ(kFadeDelay, client_.delay()); - base::Closure& fade = client_.start_fade(); + client_.start_fade().Reset(); // Move mouse still hover the fade in region of scrollbar should not // post a new fade in. scrollbar_controller_->DidMouseMove( NearVerticalScrollbarBegin(-kMouseMoveDistanceToTriggerFadeIn + 2, 0)); - EXPECT_TRUE(fade.Equals(client_.start_fade())); + EXPECT_TRUE(client_.start_fade().is_null()); } // Scrollbars should cancel delay fade in when mouse hover hidden scrollbar then @@ -1220,8 +1218,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, EXPECT_EQ(kFadeDelay, client_.delay()); // Play the delay animation. - client_.start_fade().Run(); - EXPECT_TRUE(client_.start_fade().IsCancelled()); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); time += kFadeDuration; @@ -1269,8 +1266,7 @@ TEST_F(ScrollbarAnimationControllerAuraOverlayTest, EXPECT_EQ(kFadeDelay, client_.delay()); // Play the delay animation. - client_.start_fade().Run(); - EXPECT_TRUE(client_.start_fade().IsCancelled()); + std::move(client_.start_fade()).Run(); scrollbar_controller_->Animate(time); time += kFadeDuration; @@ -1375,9 +1371,9 @@ class ScrollbarAnimationControllerAndroidTest did_request_redraw_(false), did_request_animate_(false) {} - void PostDelayedScrollbarAnimationTask(const base::Closure& start_fade, + void PostDelayedScrollbarAnimationTask(base::OnceClosure start_fade, base::TimeDelta delay) override { - start_fade_ = start_fade; + start_fade_ = std::move(start_fade); delay_ = delay; } void SetNeedsRedrawForScrollbarAnimation() override { @@ -1438,7 +1434,7 @@ class ScrollbarAnimationControllerAndroidTest std::unique_ptr<ScrollbarAnimationController> scrollbar_controller_; SolidColorScrollbarLayerImpl* scrollbar_layer_; - base::Closure start_fade_; + base::OnceClosure start_fade_; base::TimeDelta delay_; bool did_request_redraw_; bool did_request_animate_; @@ -1467,7 +1463,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); - EXPECT_TRUE(start_fade_.Equals(base::Closure())); + EXPECT_TRUE(start_fade_.is_null()); time += base::TimeDelta::FromSeconds(100); scrollbar_controller_->Animate(time); @@ -1490,7 +1486,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, EXPECT_TRUE(scrollbar_controller_->ScrollbarsHidden()); // No fade out animation should have been enqueued. - EXPECT_TRUE(start_fade_.Equals(base::Closure())); + EXPECT_TRUE(start_fade_.is_null()); } TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { @@ -1626,7 +1622,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) { EXPECT_FALSE(did_request_animate_); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); - EXPECT_TRUE(start_fade_.Equals(base::Closure())); + EXPECT_TRUE(start_fade_.is_null()); time += base::TimeDelta::FromSeconds(100); @@ -1635,7 +1631,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) { EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); scrollbar_controller_->DidScrollEnd(); EXPECT_FALSE(did_request_animate_); - start_fade_.Run(); + std::move(start_fade_).Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; @@ -1663,7 +1659,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByScrollingGesture) { scrollbar_controller_->DidScrollUpdate(); scrollbar_controller_->DidScrollEnd(); - start_fade_.Run(); + std::move(start_fade_).Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; @@ -1697,7 +1693,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) { scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); - start_fade_.Run(); + std::move(start_fade_).Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; scrollbar_controller_->Animate(time); @@ -1713,7 +1709,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) { scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); - start_fade_.Run(); + std::move(start_fade_).Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; time += base::TimeDelta::FromSeconds(2); @@ -1736,7 +1732,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, AwakenByProgrammaticScroll) { time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollUpdate(); - start_fade_.Run(); + std::move(start_fade_).Run(); time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->Animate(time); EXPECT_TRUE(did_request_animate_); @@ -1766,7 +1762,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, base::TimeTicks time; time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollUpdate(); - start_fade_.Run(); + std::move(start_fade_).Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; scrollbar_controller_->Animate(time); @@ -1806,7 +1802,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, time += base::TimeDelta::FromSeconds(1); scrollbar_controller_->DidScrollUpdate(); EXPECT_FALSE(did_request_animate_); - start_fade_.Run(); + std::move(start_fade_).Run(); EXPECT_TRUE(did_request_animate_); did_request_animate_ = false; scrollbar_controller_->Animate(time); diff --git a/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc index 08ba96d79b5..a08e6aa8838 100644 --- a/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc +++ b/chromium/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc @@ -42,12 +42,10 @@ class MockSingleScrollbarAnimationControllerClient } MOCK_METHOD2(PostDelayedScrollbarAnimationTask, - void(const base::Closure& start_fade, base::TimeDelta delay)); + void(base::OnceClosure start_fade, base::TimeDelta delay)); MOCK_METHOD0(SetNeedsRedrawForScrollbarAnimation, void()); MOCK_METHOD0(SetNeedsAnimateForScrollbarAnimation, void()); MOCK_METHOD0(DidChangeScrollbarVisibility, void()); - MOCK_METHOD0(start_fade, base::Closure()); - MOCK_METHOD0(delay, base::TimeDelta()); private: LayerTreeHostImpl* host_impl_; @@ -90,7 +88,7 @@ class SingleScrollbarAnimationControllerThinningTest : public testing::Test { host_impl_.active_tree()->SetRootLayerForTesting(std::move(clip)); scrollbar_layer_->SetBounds(gfx::Size(kThumbThickness, kTrackLength)); - scrollbar_layer_->SetPosition(gfx::PointF(90, 0)); + scrollbar_layer_->test_properties()->position = gfx::PointF(90, 0); scrollbar_layer_->SetScrollElementId(scroll_layer_ptr->element_id()); scrollbar_layer_->test_properties()->opacity_can_animate = true; clip_layer_->SetBounds(gfx::Size(100, 100)); diff --git a/chromium/cc/input/snap_selection_strategy.cc b/chromium/cc/input/snap_selection_strategy.cc index ce0f2655ecf..8803cce22f1 100644 --- a/chromium/cc/input/snap_selection_strategy.cc +++ b/chromium/cc/input/snap_selection_strategy.cc @@ -29,6 +29,10 @@ SnapSelectionStrategy::CreateForEndAndDirection( displacement); } +bool SnapSelectionStrategy::HasIntendedDirection() const { + return true; +} + bool EndPositionStrategy::ShouldSnapOnX() const { return scrolled_x_; } @@ -52,6 +56,10 @@ bool EndPositionStrategy::IsValidSnapPosition(SearchAxis axis, (scrolled_y_ && axis == SearchAxis::kY); } +bool EndPositionStrategy::HasIntendedDirection() const { + return false; +} + const base::Optional<SnapSearchResult>& EndPositionStrategy::PickBestResult( const base::Optional<SnapSearchResult>& closest, const base::Optional<SnapSearchResult>& covering) const { diff --git a/chromium/cc/input/snap_selection_strategy.h b/chromium/cc/input/snap_selection_strategy.h index cebc63e96b5..ef6b00baa7a 100644 --- a/chromium/cc/input/snap_selection_strategy.h +++ b/chromium/cc/input/snap_selection_strategy.h @@ -48,6 +48,8 @@ class CC_EXPORT SnapSelectionStrategy { // valid for the current axis. virtual bool IsValidSnapPosition(SearchAxis axis, float position) const = 0; + virtual bool HasIntendedDirection() const; + // Returns the best result according to snap selection strategy. This method // is called at the end of selection process to make the final decision. // @@ -91,6 +93,7 @@ class EndPositionStrategy : public SnapSelectionStrategy { gfx::ScrollOffset base_position() const override; bool IsValidSnapPosition(SearchAxis axis, float position) const override; + bool HasIntendedDirection() const override; const base::Optional<SnapSearchResult>& PickBestResult( const base::Optional<SnapSearchResult>& closest, diff --git a/chromium/cc/layers/append_quads_data.h b/chromium/cc/layers/append_quads_data.h index d207cf28626..a681a97b489 100644 --- a/chromium/cc/layers/append_quads_data.h +++ b/chromium/cc/layers/append_quads_data.h @@ -25,12 +25,6 @@ class CC_EXPORT AppendQuadsData { int64_t visible_layer_area = 0; int64_t approximated_visible_content_area = 0; - // TODO(enne): These are temporary to evaluate mask layer optimizations. - int num_mask_layers = 0; - int num_rounded_corner_mask_layers = 0; - int64_t visible_mask_layer_area = 0; - int64_t visible_rounded_corner_mask_layer_area = 0; - // This is total of the following two areas. int64_t checkerboarded_visible_content_area = 0; // This is the area outside interest rect. diff --git a/chromium/cc/layers/effect_tree_layer_list_iterator_unittest.cc b/chromium/cc/layers/effect_tree_layer_list_iterator_unittest.cc index 7f79eb9b574..26bd15d973f 100644 --- a/chromium/cc/layers/effect_tree_layer_list_iterator_unittest.cc +++ b/chromium/cc/layers/effect_tree_layer_list_iterator_unittest.cc @@ -32,7 +32,6 @@ class TestLayerImpl : public LayerImpl { explicit TestLayerImpl(LayerTreeImpl* tree, int id) : LayerImpl(tree, id), count_(-1) { SetBounds(gfx::Size(100, 100)); - SetPosition(gfx::PointF()); SetDrawsContent(true); } }; diff --git a/chromium/cc/layers/heads_up_display_layer.cc b/chromium/cc/layers/heads_up_display_layer.cc index 1837ed16487..6d7044e2703 100644 --- a/chromium/cc/layers/heads_up_display_layer.cc +++ b/chromium/cc/layers/heads_up_display_layer.cc @@ -46,8 +46,10 @@ void HeadsUpDisplayLayer::UpdateLocationAndSize( // FPS meter), use a fixed size. constexpr int kDefaultHUDSize = 256; bounds.SetSize(kDefaultHUDSize, kDefaultHUDSize); - matrix.Translate(device_viewport_in_layout_pixels.width() - kDefaultHUDSize, - 0.0); + // Put the HUD on the top-left side instead of the top-right side because + // the HUD sometimes can be drawn on out of the screen when it works on + // embedded devices. + matrix.Translate(0.0, 0.0); } SetBounds(bounds); diff --git a/chromium/cc/layers/heads_up_display_layer_impl.cc b/chromium/cc/layers/heads_up_display_layer_impl.cc index cb7ee65c26e..5c1e31565d9 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.cc +++ b/chromium/cc/layers/heads_up_display_layer_impl.cc @@ -32,7 +32,6 @@ #include "cc/trees/layer_tree_impl.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/gpu/context_provider.h" -#include "components/viz/common/gpu/texture_allocation.h" #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/resources/bitmap_allocation.h" @@ -358,11 +357,9 @@ void HeadsUpDisplayLayerImpl::UpdateHudTexture( constexpr GLuint background_color = SkColorSetARGB(0, 0, 0, 0); constexpr GLuint msaa_sample_count = -1; constexpr bool can_use_lcd_text = true; - const auto pixel_config = viz::ResourceFormatToClosestSkColorType( - true /* gpu_compositing */, pool_resource.format()); ri->BeginRasterCHROMIUM(background_color, msaa_sample_count, - can_use_lcd_text, pixel_config, - raster_color_space_, backing->mailbox.name); + can_use_lcd_text, raster_color_space_, + backing->mailbox.name); gfx::Vector2dF post_translate(0.f, 0.f); DummyImageProvider image_provider; ri->RasterCHROMIUM(display_item_list.get(), &image_provider, size, @@ -582,33 +579,32 @@ void HeadsUpDisplayLayerImpl::DrawHudContents(PaintCanvas* canvas) { } void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas, - PaintFlags* flags, + const PaintFlags& flags, const std::string& text, TextAlign align, int size, int x, int y) const { DCHECK(typeface_.get()); - flags->setAntiAlias(true); - flags->setTextSize(size); - flags->setTypeface(typeface_); + SkFont font(typeface_, size); + font.setEdging(SkFont::Edging::kAntiAlias); + if (align == TextAlign::kCenter) { - auto width = flags->ToSkPaint().measureText(text.c_str(), text.length()); + auto width = + font.measureText(text.c_str(), text.length(), kUTF8_SkTextEncoding); x -= width * 0.5f; } else if (align == TextAlign::kRight) { - auto width = flags->ToSkPaint().measureText(text.c_str(), text.length()); + auto width = + font.measureText(text.c_str(), text.length(), kUTF8_SkTextEncoding); x -= width; } - auto sk_paint = flags->ToSkPaint(); - auto text_blob = SkTextBlob::MakeFromText( - text.c_str(), text.length(), - SkFont(sk_paint.refTypeface(), sk_paint.getTextSize())); - canvas->drawTextBlob(std::move(text_blob), x, y, *flags); + canvas->drawTextBlob( + SkTextBlob::MakeFromText(text.c_str(), text.length(), font), x, y, flags); } void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas, - PaintFlags* flags, + const PaintFlags& flags, const std::string& text, TextAlign align, int size, @@ -665,7 +661,7 @@ SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay( int width = kGraphWidth + kHistogramWidth + 4 * kPadding; int height = kTitleFontHeight + kFontHeight + kGraphHeight + 6 * kPadding + 2; - int left = bounds().width() - width - right; + int left = 0; SkRect area = SkRect::MakeXYWH(left, top, width, height); PaintFlags flags; @@ -693,13 +689,13 @@ SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay( VLOG(1) << value_text; flags.setColor(DebugColors::HUDTitleColor()); - DrawText(canvas, &flags, title, TextAlign::kLeft, kTitleFontHeight, + DrawText(canvas, flags, title, TextAlign::kLeft, kTitleFontHeight, title_bounds.left(), title_bounds.bottom()); flags.setColor(DebugColors::FPSDisplayTextAndGraphColor()); - DrawText(canvas, &flags, value_text, TextAlign::kLeft, kFontHeight, + DrawText(canvas, flags, value_text, TextAlign::kLeft, kFontHeight, text_bounds.left(), text_bounds.bottom()); - DrawText(canvas, &flags, min_max_text, TextAlign::kRight, kFontHeight, + DrawText(canvas, flags, min_max_text, TextAlign::kRight, kFontHeight, text_bounds.right(), text_bounds.bottom()); DrawGraphLines(canvas, &flags, graph_bounds, fps_graph_); @@ -786,7 +782,7 @@ SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(PaintCanvas* canvas, const int kFontHeight = 12; const int height = kTitleFontHeight + 2 * kFontHeight + 5 * kPadding; - const int left = bounds().width() - width - right; + const int left = 0; const SkRect area = SkRect::MakeXYWH(left, top, width, height); const double kMegabyte = 1024.0 * 1024.0; @@ -802,20 +798,20 @@ SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(PaintCanvas* canvas, top + 2 * kPadding + 3 * kFontHeight); flags.setColor(DebugColors::HUDTitleColor()); - DrawText(canvas, &flags, "GPU Memory", TextAlign::kLeft, kTitleFontHeight, + DrawText(canvas, flags, "GPU Memory", TextAlign::kLeft, kTitleFontHeight, title_pos); flags.setColor(DebugColors::MemoryDisplayTextColor()); std::string text = base::StringPrintf( "%6.1f MB used", memory_entry_.total_bytes_used / kMegabyte); - DrawText(canvas, &flags, text, TextAlign::kRight, kFontHeight, stat1_pos); + DrawText(canvas, flags, text, TextAlign::kRight, kFontHeight, stat1_pos); if (!memory_entry_.had_enough_memory) flags.setColor(SK_ColorRED); text = base::StringPrintf("%6.1f MB max ", memory_entry_.total_budget_in_bytes / kMegabyte); - DrawText(canvas, &flags, text, TextAlign::kRight, kFontHeight, stat2_pos); + DrawText(canvas, flags, text, TextAlign::kRight, kFontHeight, stat2_pos); // Draw memory graph. int length = 2 * kFontHeight + kPadding + 12; @@ -895,7 +891,7 @@ SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(PaintCanvas* canvas, const int kFontHeight = 12; const int height = kTitleFontHeight + kFontHeight + 3 * kPadding; - const int left = bounds().width() - width - right; + const int left = 0; const SkRect area = SkRect::MakeXYWH(left, top, width, height); PaintFlags flags; @@ -904,10 +900,10 @@ SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(PaintCanvas* canvas, SkPoint gpu_status_pos = SkPoint::Make(left + width - kPadding, top + 2 * kFontHeight + 2 * kPadding); flags.setColor(DebugColors::HUDTitleColor()); - DrawText(canvas, &flags, "GPU Raster", TextAlign::kLeft, kTitleFontHeight, + DrawText(canvas, flags, "GPU Raster", TextAlign::kLeft, kTitleFontHeight, left + kPadding, top + kFontHeight + kPadding); flags.setColor(color); - DrawText(canvas, &flags, status, TextAlign::kRight, kFontHeight, + DrawText(canvas, flags, status, TextAlign::kRight, kFontHeight, gpu_status_pos); return area; @@ -950,19 +946,17 @@ void HeadsUpDisplayLayerImpl::DrawDebugRect( canvas->translate(sk_clip_rect.x(), sk_clip_rect.y()); PaintFlags label_flags; - label_flags.setTextSize(kFontHeight); - label_flags.setTypeface(typeface_); label_flags.setColor(stroke_color); + SkFont label_font(typeface_, kFontHeight); - const SkScalar label_text_width = label_flags.ToSkPaint().measureText( - label_text.c_str(), label_text.length()); + const SkScalar label_text_width = label_font.measureText( + label_text.c_str(), label_text.length(), kUTF8_SkTextEncoding); canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding, kFontHeight + 2 * kPadding), label_flags); - label_flags.setAntiAlias(true); label_flags.setColor(SkColorSetARGB(255, 50, 50, 50)); - DrawText(canvas, &label_flags, label_text, TextAlign::kLeft, kFontHeight, + DrawText(canvas, label_flags, label_text, TextAlign::kLeft, kFontHeight, kPadding, kFontHeight * 0.8f + kPadding); canvas->restore(); } diff --git a/chromium/cc/layers/heads_up_display_layer_impl.h b/chromium/cc/layers/heads_up_display_layer_impl.h index 9a97daea2d4..352b71bdaf2 100644 --- a/chromium/cc/layers/heads_up_display_layer_impl.h +++ b/chromium/cc/layers/heads_up_display_layer_impl.h @@ -98,14 +98,14 @@ class CC_EXPORT HeadsUpDisplayLayerImpl : public LayerImpl { void UpdateHudContents(); void DrawHudContents(PaintCanvas* canvas); void DrawText(PaintCanvas* canvas, - PaintFlags* flags, + const PaintFlags& flags, const std::string& text, TextAlign align, int size, int x, int y) const; void DrawText(PaintCanvas* canvas, - PaintFlags* flags, + const PaintFlags& flags, const std::string& text, TextAlign align, int size, diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc index f976fa6e1aa..18dc2f32a64 100644 --- a/chromium/cc/layers/layer.cc +++ b/chromium/cc/layers/layer.cc @@ -77,6 +77,7 @@ scoped_refptr<Layer> Layer::Create() { Layer::Layer() : ignore_set_needs_commit_(false), + paint_count_(0), parent_(nullptr), layer_tree_host_(nullptr), // Layer IDs start from 1. @@ -96,9 +97,10 @@ Layer::Layer() may_contain_video_(false), needs_show_scrollbars_(false), has_transform_node_(false), - is_rounded_corner_mask_(false), subtree_has_copy_request_(false), - safe_opaque_background_color_(0) {} + safe_opaque_background_color_(0), + compositing_reasons_(0), + owner_node_id_(0) {} Layer::~Layer() { // Our parent should be holding a reference to us so there should be no @@ -124,9 +126,12 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) { bool property_tree_indices_invalid = false; if (layer_tree_host_) { + bool should_register_element = + inputs_.element_id && + (!layer_tree_host_->IsUsingLayerLists() || inputs_.scrollable); layer_tree_host_->property_trees()->needs_rebuild = true; layer_tree_host_->UnregisterLayer(this); - if (inputs_.element_id) { + if (should_register_element) { layer_tree_host_->UnregisterElement(inputs_.element_id, ElementListType::ACTIVE); } @@ -134,9 +139,12 @@ void Layer::SetLayerTreeHost(LayerTreeHost* host) { property_tree_indices_invalid = true; } if (host) { + bool should_register_element = + inputs_.element_id && + (!host->IsUsingLayerLists() || inputs_.scrollable); host->property_trees()->needs_rebuild = true; host->RegisterLayer(this); - if (inputs_.element_id) + if (should_register_element) host->RegisterElement(inputs_.element_id, ElementListType::ACTIVE, this); if (!host->IsUsingLayerLists()) property_tree_indices_invalid = true; @@ -555,6 +563,10 @@ void Layer::SetBackdropFilters(const FilterOperations& filters) { SetNeedsCommit(); } +void Layer::SetBackdropFilterBounds(const gfx::RectF& backdrop_filter_bounds) { + inputs_.backdrop_filter_bounds = backdrop_filter_bounds; +} + void Layer::SetBackdropFilterQuality(const float quality) { inputs_.backdrop_filter_quality = quality; } @@ -912,6 +924,12 @@ void Layer::SetScrollable(const gfx::Size& bounds) { if (!layer_tree_host_) return; + if (layer_tree_host_->IsUsingLayerLists() && !was_scrollable && + inputs_.element_id) { + layer_tree_host_->RegisterElement(inputs_.element_id, + ElementListType::ACTIVE, this); + } + if (!layer_tree_host_->IsUsingLayerLists()) { auto& scroll_tree = layer_tree_host_->property_trees()->scroll_tree; auto* scroll_node = scroll_tree.Node(scroll_tree_index_); @@ -955,10 +973,50 @@ void Layer::SetUserScrollable(bool horizontal, bool vertical) { SetNeedsCommit(); } +bool Layer::GetUserScrollableHorizontal() const { + // When using layer lists, horizontal scrollability is stored in scroll nodes. + if (layer_tree_host() && layer_tree_host()->IsUsingLayerLists()) { + auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; + if (auto* scroll_node = scroll_tree.Node(scroll_tree_index_)) + return scroll_node->user_scrollable_horizontal; + return false; + } + return inputs_.user_scrollable_horizontal; +} + +bool Layer::GetUserScrollableVertical() const { + // When using layer lists, vertical scrollability is stored in scroll nodes. + if (layer_tree_host() && layer_tree_host()->IsUsingLayerLists()) { + auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; + if (auto* scroll_node = scroll_tree.Node(scroll_tree_index_)) + return scroll_node->user_scrollable_vertical; + return false; + } + return inputs_.user_scrollable_vertical; +} + +uint32_t Layer::GetMainThreadScrollingReasons() const { + // When using layer lists, main thread scrolling reasons are stored in scroll + // nodes. + if (layer_tree_host() && layer_tree_host()->IsUsingLayerLists()) { + auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree; + if (auto* scroll_node = scroll_tree.Node(scroll_tree_index_)) + return scroll_node->main_thread_scrolling_reasons; + return MainThreadScrollingReason::kNotScrollingOnMain; + } + return inputs_.main_thread_scrolling_reasons; +} + void Layer::AddMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons) { DCHECK(IsPropertyChangeAllowed()); DCHECK(main_thread_scrolling_reasons); + + // When layer lists are used, the main thread scrolling reasons should be set + // on property tree nodes directly. + // TODO(pdr): Uncomment this check when https://crbug.com/919969 is fixed. + // DCHECK(!layer_tree_host() || !layer_tree_host()->IsUsingLayerLists()); + // Layer should only see non-transient scrolling reasons. Transient scrolling // reasons are computed per hit test. DCHECK(MainThreadScrollingReason::MainThreadCanSetScrollReasons( @@ -1141,6 +1199,24 @@ void Layer::SetShouldFlattenTransform(bool should_flatten) { SetSubtreePropertyChanged(); } +std::string Layer::ToString() const { + return base::StringPrintf( + "layer_id: %d\n" + " Bounds: %s\n" + " ElementId: %s\n" + " OffsetToTransformParent: %s\n" + " Position: %s\n" + " scrollable: %d\n" + " clip_tree_index: %d\n" + " effect_tree_index: %d\n" + " scroll_tree_index: %d\n" + " transform_tree_index: %d\n", + id(), bounds().ToString().c_str(), element_id().ToString().c_str(), + offset_to_transform_parent().ToString().c_str(), + position().ToString().c_str(), scrollable(), clip_tree_index(), + effect_tree_index(), scroll_tree_index(), transform_tree_index()); +} + void Layer::SetUseParentBackfaceVisibility(bool use) { DCHECK(IsPropertyChangeAllowed()); if (inputs_.use_parent_backface_visibility == use) @@ -1262,7 +1338,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { // deprecated. http://crbug.com/709137 layer->SetElementId(inputs_.element_id); layer->SetHasTransformNode(has_transform_node_); - layer->set_is_rounded_corner_mask(is_rounded_corner_mask_); layer->SetBackgroundColor(inputs_.background_color); layer->SetSafeOpaqueBackgroundColor(safe_opaque_background_color_); layer->SetBounds(inputs_.bounds); @@ -1281,8 +1356,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->NoteLayerPropertyChanged(); layer->set_may_contain_video(may_contain_video_); layer->SetMasksToBounds(inputs_.masks_to_bounds); - layer->set_main_thread_scrolling_reasons( - inputs_.main_thread_scrolling_reasons); layer->SetNonFastScrollableRegion(inputs_.non_fast_scrollable_region); layer->SetTouchActionRegion(inputs_.touch_action_region); // TODO(sunxd): Pass the correct region for wheel event handlers, see @@ -1297,7 +1370,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) { layer->SetWheelEventHandlerRegion(Region()); } layer->SetContentsOpaque(inputs_.contents_opaque); - layer->SetPosition(inputs_.position); layer->SetShouldFlattenScreenSpaceTransformFromPropertyTree( should_flatten_screen_space_transform_from_property_tree_); layer->SetUseParentBackfaceVisibility(inputs_.use_parent_backface_visibility); @@ -1509,14 +1581,17 @@ void Layer::SetElementId(ElementId id) { return; TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "Layer::SetElementId", "element", id.AsValue().release()); - if (inputs_.element_id && layer_tree_host()) { + bool should_register_element = + layer_tree_host() && + (!layer_tree_host()->IsUsingLayerLists() || inputs_.scrollable); + if (should_register_element && inputs_.element_id) { layer_tree_host_->UnregisterElement(inputs_.element_id, ElementListType::ACTIVE); } inputs_.element_id = id; - if (inputs_.element_id && layer_tree_host()) { + if (should_register_element && inputs_.element_id) { layer_tree_host_->RegisterElement(inputs_.element_id, ElementListType::ACTIVE, this); } diff --git a/chromium/cc/layers/layer.h b/chromium/cc/layers/layer.h index b90f4559bc0..286a72eec82 100644 --- a/chromium/cc/layers/layer.h +++ b/chromium/cc/layers/layer.h @@ -163,7 +163,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // specified in layer space, which excludes device scale and page scale // factors, and ignoring transforms for this layer or ancestor layers. The // root layer's position is not used as it always appears at the origin of - // the viewport. + // the viewport. When property trees are built by cc (when IsUsingLayerLists + // is false), position is used to update |offset_to_transform_parent|. void SetPosition(const gfx::PointF& position); const gfx::PointF& position() const { return inputs_.position; } @@ -276,13 +277,18 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { gfx::PointF filters_origin() const { return inputs_.filters_origin; } // Set or get the list of filters that should be applied to the content this - // layer and its subtree will be drawn into. The effect is clipped to only - // apply directly behind this layer and its subtree. + // layer and its subtree will be drawn into. The effect is clipped by + // backdrop_filter_bounds. void SetBackdropFilters(const FilterOperations& filters); const FilterOperations& backdrop_filters() const { return inputs_.backdrop_filters; } + void SetBackdropFilterBounds(const gfx::RectF& backdrop_filter_bounds); + const gfx::RectF& backdrop_filter_bounds() const { + return inputs_.backdrop_filter_bounds; + } + void SetBackdropFilterQuality(const float quality); float backdrop_filter_quality() const { return inputs_.backdrop_filter_quality; @@ -404,7 +410,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { bool is_scrollbar() const { return inputs_.is_scrollbar; } // Set or get if this layer is able to be scrolled along each axis. These are - // independant of the scrollable state, or size of the scrollable area + // independent of the scrollable state, or size of the scrollable area // specified in SetScrollable(), as these may be enabled or disabled // dynamically, while SetScrollable() defines what would be possible if these // are enabled. @@ -413,12 +419,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // the scrollbars will be shown when the scroll offset changes if these are // set to true. void SetUserScrollable(bool horizontal, bool vertical); - bool user_scrollable_horizontal() const { - return inputs_.user_scrollable_horizontal; - } - bool user_scrollable_vertical() const { - return inputs_.user_scrollable_vertical; - } + bool GetUserScrollableHorizontal() const; + bool GetUserScrollableVertical() const; // Set or get if this layer is able to be scrolled on the compositor thread. // This only applies for layers that are marked as scrollable, not for layers @@ -431,9 +433,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void AddMainThreadScrollingReasons(uint32_t main_thread_scrolling_reasons); void ClearMainThreadScrollingReasons( uint32_t main_thread_scrolling_reasons_to_clear); - uint32_t main_thread_scrolling_reasons() const { - return inputs_.main_thread_scrolling_reasons; - } + uint32_t GetMainThreadScrollingReasons() const; // Set or get an area of this layer within which initiating a scroll can not // be done from the compositor thread. Within this area, if the user attempts @@ -709,10 +709,9 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void SetEffectTreeIndex(int index); void SetScrollTreeIndex(int index); - // Internal to property tree construction. Set or get the position of this - // layer relative to the origin after transforming according to this layer's - // index into the transform tree. This translation is appended to the - // transform that comes from the transform tree for this layer. + // The position of this layer after transforming by the layer's transform + // node. When property trees are built by cc (when IsUsingLayerLists is false) + // this is set by property_tree_builder.cc. void SetOffsetToTransformParent(gfx::Vector2dF offset); gfx::Vector2dF offset_to_transform_parent() const { return offset_to_transform_parent_; @@ -764,9 +763,33 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { return should_flatten_screen_space_transform_from_property_tree_; } - void set_is_rounded_corner_mask(bool rounded) { - is_rounded_corner_mask_ = rounded; + std::string ToString() const; + + // Called when a property has been modified in a way that the layer knows + // immediately that a commit is required. This implies SetNeedsPushProperties + // to push that property. + // This is public, so that it can be called directly when needed, for example + // in PropertyTreeManager when handling scroll offsets. + void SetNeedsCommit(); + + // The following data are for profiling and debugging. They will be displayed + // e.g. in the Layers panel of DevTools. + + // The compositing reasons of the layer. The values are defined in + // third_party/blink/renderer/platform/graphics/compositing_reasons.h. + void set_compositing_reasons(uint64_t compositing_reasons) { + compositing_reasons_ = compositing_reasons; } + uint64_t compositing_reasons() const { return compositing_reasons_; } + + // The id of the DOM node that owns this layer. + void set_owner_node_id(int node_id) { owner_node_id_ = node_id; } + int owner_node_id() const { return owner_node_id_; } + + // How many times this layer has been repainted. + int paint_count() const { return paint_count_; } + + // End of data for profiling and debugging. protected: friend class LayerImpl; @@ -776,11 +799,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { virtual ~Layer(); // These SetNeeds functions are in order of severity of update: - // - // Called when a property has been modified in a way that the layer knows - // immediately that a commit is required. This implies SetNeedsPushProperties - // to push that property. - void SetNeedsCommit(); + + // See SetNeedsCommit() above - it belongs here in the order of severity. // Called when there's been a change in layer structure. Implies // SetNeedsCommit and property tree rebuld, but not SetNeedsPushProperties @@ -813,6 +833,8 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { // will be handled implicitly after the update completes. bool ignore_set_needs_commit_; + int paint_count_; + private: friend class base::RefCounted<Layer>; friend class LayerTreeHostCommon; @@ -851,9 +873,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { void UpdateScrollOffset(const gfx::ScrollOffset&); // Encapsulates all data, callbacks or interfaces received from the embedder. - // TODO(khushalsagar): This is only valid when PropertyTrees are built - // internally in cc. Update this for the SPv2 path where blink generates - // PropertyTrees. struct Inputs { explicit Inputs(int layer_id); ~Inputs(); @@ -901,6 +920,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { FilterOperations filters; FilterOperations backdrop_filters; + gfx::RectF backdrop_filter_bounds; gfx::PointF filters_origin; float backdrop_filter_quality; @@ -988,10 +1008,11 @@ class CC_EXPORT Layer : public base::RefCounted<Layer> { bool may_contain_video_ : 1; bool needs_show_scrollbars_ : 1; bool has_transform_node_ : 1; - bool is_rounded_corner_mask_ : 1; // This value is valid only when LayerTreeHost::has_copy_request() is true bool subtree_has_copy_request_ : 1; SkColor safe_opaque_background_color_; + uint64_t compositing_reasons_; + int owner_node_id_; std::unique_ptr<std::set<Layer*>> clip_children_; diff --git a/chromium/cc/layers/layer_impl.cc b/chromium/cc/layers/layer_impl.cc index 3a1f4e9aadf..7d07aa39ad5 100644 --- a/chromium/cc/layers/layer_impl.cc +++ b/chromium/cc/layers/layer_impl.cc @@ -11,6 +11,7 @@ #include <utility> #include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" @@ -20,7 +21,6 @@ #include "cc/benchmarks/micro_benchmark_impl.h" #include "cc/debug/debug_colors.h" #include "cc/debug/layer_tree_debug_state.h" -#include "cc/input/main_thread_scrolling_reason.h" #include "cc/input/scroll_state.h" #include "cc/layers/layer.h" #include "cc/trees/clip_node.h" @@ -52,8 +52,6 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, layer_tree_impl_(tree_impl), will_always_push_properties_(will_always_push_properties), test_properties_(nullptr), - main_thread_scrolling_reasons_( - MainThreadScrollingReason::kNotScrollingOnMain), scrollable_(false), should_flatten_screen_space_transform_from_property_tree_(false), layer_property_changed_not_from_property_trees_(false), @@ -82,8 +80,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, scrollbars_hidden_(false), needs_show_scrollbars_(false), raster_even_if_not_drawn_(false), - has_transform_node_(false), - is_rounded_corner_mask_(false) { + has_transform_node_(false) { DCHECK_GT(layer_id_, 0); DCHECK(layer_tree_impl_); @@ -308,9 +305,7 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->SetElementId(element_id_); layer->has_transform_node_ = has_transform_node_; - layer->is_rounded_corner_mask_ = is_rounded_corner_mask_; layer->offset_to_transform_parent_ = offset_to_transform_parent_; - layer->main_thread_scrolling_reasons_ = main_thread_scrolling_reasons_; layer->should_flatten_screen_space_transform_from_property_tree_ = should_flatten_screen_space_transform_from_property_tree_; layer->masks_to_bounds_ = masks_to_bounds_; @@ -326,7 +321,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) { layer->wheel_event_handler_region_ = wheel_event_handler_region_; layer->background_color_ = background_color_; layer->safe_opaque_background_color_ = safe_opaque_background_color_; - layer->position_ = position_; layer->transform_tree_index_ = transform_tree_index_; layer->effect_tree_index_ = effect_tree_index_; layer->clip_tree_index_ = clip_tree_index_; @@ -382,9 +376,11 @@ void LayerImpl::SetIsResizedByBrowserControls(bool resized) { is_resized_by_browser_controls_ = resized; } -std::unique_ptr<base::DictionaryValue> LayerImpl::LayerAsJson() { +std::unique_ptr<base::DictionaryValue> LayerImpl::LayerAsJson() const { std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue); result->SetInteger("LayerId", id()); + if (element_id()) + result->SetString("ElementId", element_id().ToString()); result->SetString("LayerType", LayerTypeAsString()); auto list = std::make_unique<base::ListValue>(); @@ -393,11 +389,12 @@ std::unique_ptr<base::DictionaryValue> LayerImpl::LayerAsJson() { result->Set("Bounds", std::move(list)); list = std::make_unique<base::ListValue>(); - list->AppendDouble(position_.x()); - list->AppendDouble(position_.y()); - result->Set("Position", std::move(list)); + list->AppendInteger(offset_to_transform_parent().x()); + list->AppendInteger(offset_to_transform_parent().y()); + result->Set("OffsetToTransformParent", std::move(list)); - const gfx::Transform& gfx_transform = test_properties()->transform; + const gfx::Transform& gfx_transform = + const_cast<LayerImpl*>(this)->test_properties()->transform; double transform[16]; gfx_transform.matrix().asColMajord(transform); list = std::make_unique<base::ListValue>(); @@ -409,11 +406,13 @@ std::unique_ptr<base::DictionaryValue> LayerImpl::LayerAsJson() { result->SetBoolean("HitTestableWithoutDrawsContent", hit_testable_without_draws_content_); result->SetBoolean("Is3dSorted", Is3dSorted()); - result->SetDouble("OPACITY", Opacity()); + result->SetDouble("Opacity", Opacity()); result->SetBoolean("ContentsOpaque", contents_opaque_); - result->SetString( - "mainThreadScrollingReasons", - MainThreadScrollingReason::AsText(main_thread_scrolling_reasons_)); + + result->SetInteger("transform_tree_index", transform_tree_index()); + result->SetInteger("clip_tree_index", clip_tree_index()); + result->SetInteger("effect_tree_index", effect_tree_index()); + result->SetInteger("scroll_tree_index", scroll_tree_index()); if (scrollable()) result->SetBoolean("Scrollable", true); @@ -606,6 +605,15 @@ void LayerImpl::SetHitTestableWithoutDrawsContent(bool should_hit_test) { NoteLayerPropertyChanged(); } +bool LayerImpl::ShouldHitTest() const { + bool should_hit_test = draws_content_; + if (GetEffectTree().Node(effect_tree_index())) + should_hit_test &= + !GetEffectTree().Node(effect_tree_index())->subtree_hidden; + should_hit_test |= hit_testable_without_draws_content_; + return should_hit_test; +} + void LayerImpl::SetBackgroundColor(SkColor background_color) { if (background_color_ == background_color) return; @@ -654,10 +662,6 @@ void LayerImpl::SetElementId(ElementId element_id) { layer_tree_impl_->AddToElementLayerList(element_id_, this); } -void LayerImpl::SetPosition(const gfx::PointF& position) { - position_ = position; -} - void LayerImpl::SetUpdateRect(const gfx::Rect& update_rect) { update_rect_ = update_rect; } @@ -738,7 +742,8 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetDouble("opacity", Opacity()); - MathUtil::AddToTracedValue("position", position_, state); + // For backward-compatibility of DevTools front-end. + MathUtil::AddToTracedValue("position", gfx::PointF(), state); state->SetInteger("transform_tree_index", transform_tree_index()); state->SetInteger("clip_tree_index", clip_tree_index()); @@ -785,13 +790,20 @@ void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { state->SetBoolean("has_will_change_transform_hint", has_will_change_transform_hint()); - MainThreadScrollingReason::AddToTracedValue(main_thread_scrolling_reasons_, - *state); - if (debug_info_) state->SetValue("debug_info", debug_info_); } +std::string LayerImpl::ToString() const { + std::string str; + base::JSONWriter::WriteWithOptions( + *LayerAsJson(), + base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION | + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &str); + return str; +} + size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; } void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) { diff --git a/chromium/cc/layers/layer_impl.h b/chromium/cc/layers/layer_impl.h index bdfd63a5e70..837b7e0ac47 100644 --- a/chromium/cc/layers/layer_impl.h +++ b/chromium/cc/layers/layer_impl.h @@ -167,9 +167,7 @@ class CC_EXPORT LayerImpl { // True if either the layer draws content or has been marked as hit testable // without draws_content. - bool should_hit_test() const { - return draws_content_ || hit_testable_without_draws_content_; - } + bool ShouldHitTest() const; LayerImplTestProperties* test_properties() { if (!test_properties_) @@ -196,9 +194,6 @@ class CC_EXPORT LayerImpl { void SetElementId(ElementId element_id); ElementId element_id() const { return element_id_; } - void SetPosition(const gfx::PointF& position); - gfx::PointF position() const { return position_; } - bool IsAffectedByPageScale() const; bool Is3dSorted() const { return GetSortingContextId() != 0; } @@ -309,14 +304,6 @@ class CC_EXPORT LayerImpl { gfx::Size scroll_container_bounds() const { return scroll_container_bounds_; } bool scrollable() const { return scrollable_; } - void set_main_thread_scrolling_reasons( - uint32_t main_thread_scrolling_reasons) { - main_thread_scrolling_reasons_ = main_thread_scrolling_reasons; - } - uint32_t main_thread_scrolling_reasons() const { - return main_thread_scrolling_reasons_; - } - void SetNonFastScrollableRegion(const Region& region) { non_fast_scrollable_region_ = region; } @@ -348,7 +335,7 @@ class CC_EXPORT LayerImpl { void AddDamageRect(const gfx::Rect& damage_rect); const gfx::Rect& damage_rect() const { return damage_rect_; } - virtual std::unique_ptr<base::DictionaryValue> LayerAsJson(); + virtual std::unique_ptr<base::DictionaryValue> LayerAsJson() const; // TODO(pdr): This should be removed because there is no longer a tree // of layers, only a list. std::unique_ptr<base::DictionaryValue> LayerTreeAsJson(); @@ -398,6 +385,7 @@ class CC_EXPORT LayerImpl { virtual void GetAllPrioritizedTilesForTracing( std::vector<PrioritizedTile>* prioritized_tiles) const; virtual void AsValueInto(base::trace_event::TracedValue* dict) const; + std::string ToString() const; virtual size_t GPUMemoryUsageInBytes() const; @@ -466,11 +454,6 @@ class CC_EXPORT LayerImpl { // TODO(sunxd): Remove this function and replace it with visitor pattern. virtual bool is_surface_layer() const; - void set_is_rounded_corner_mask(bool rounded) { - is_rounded_corner_mask_ = rounded; - } - bool is_rounded_corner_mask() const { return is_rounded_corner_mask_; } - protected: // When |will_always_push_properties| is true, the layer will not itself set // its SetNeedsPushProperties() state, as it expects to be always pushed to @@ -510,7 +493,6 @@ class CC_EXPORT LayerImpl { gfx::Size bounds_; gfx::Vector2dF offset_to_transform_parent_; - uint32_t main_thread_scrolling_reasons_; // Size of the scroll container that this layer scrolls in. gfx::Size scroll_container_bounds_; @@ -558,8 +540,6 @@ class CC_EXPORT LayerImpl { SkColor background_color_; SkColor safe_opaque_background_color_; - gfx::PointF position_; - int transform_tree_index_; int effect_tree_index_; int clip_tree_index_; @@ -612,7 +592,6 @@ class CC_EXPORT LayerImpl { bool raster_even_if_not_drawn_ : 1; bool has_transform_node_ : 1; - bool is_rounded_corner_mask_ : 1; DISALLOW_COPY_AND_ASSIGN(LayerImpl); }; diff --git a/chromium/cc/layers/layer_impl_test_properties.h b/chromium/cc/layers/layer_impl_test_properties.h index c931d45d95f..9f0d688a8ee 100644 --- a/chromium/cc/layers/layer_impl_test_properties.h +++ b/chromium/cc/layers/layer_impl_test_properties.h @@ -48,6 +48,7 @@ struct CC_EXPORT LayerImplTestProperties { float opacity; FilterOperations filters; FilterOperations backdrop_filters; + gfx::RectF backdrop_filter_bounds; float backdrop_filter_quality; gfx::PointF filters_origin; SkBlendMode blend_mode; @@ -55,6 +56,7 @@ struct CC_EXPORT LayerImplTestProperties { LayerStickyPositionConstraint sticky_position_constraint; gfx::Point3F transform_origin; gfx::Transform transform; + gfx::PointF position; LayerImpl* scroll_parent; LayerImpl* clip_parent; std::unique_ptr<std::set<LayerImpl*>> clip_children; @@ -62,6 +64,7 @@ struct CC_EXPORT LayerImplTestProperties { LayerImplList children; LayerImpl* mask_layer; LayerImpl* parent; + uint32_t main_thread_scrolling_reasons = 0; bool user_scrollable_horizontal = true; bool user_scrollable_vertical = true; OverscrollBehavior overscroll_behavior; diff --git a/chromium/cc/layers/layer_impl_unittest.cc b/chromium/cc/layers/layer_impl_unittest.cc index cca256cf143..9200f7a7be1 100644 --- a/chromium/cc/layers/layer_impl_unittest.cc +++ b/chromium/cc/layers/layer_impl_unittest.cc @@ -115,7 +115,6 @@ TEST(LayerImplTest, VerifyPendingLayerChangesAreTrackedProperly) { EXPECT_FALSE(child->LayerPropertyChanged()); EXPECT_FALSE(grand_child->LayerPropertyChanged()); - gfx::PointF arbitrary_point_f = gfx::PointF(0.125f, 0.25f); float arbitrary_number = 0.352f; gfx::Size arbitrary_size = gfx::Size(111, 222); gfx::Point arbitrary_point = gfx::Point(333, 444); @@ -159,8 +158,6 @@ TEST(LayerImplTest, VerifyPendingLayerChangesAreTrackedProperly) { // After setting all these properties already, setting to the exact same // values again should not cause any change. EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetMasksToBounds(true)); - EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE( - root->SetPosition(arbitrary_point_f)); EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetContentsOpaque(true)); EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetDrawsContent(true)); EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->SetBounds(root->bounds())); @@ -266,7 +263,6 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting(); DCHECK(host_impl.CanDraw()); - gfx::PointF arbitrary_point_f = gfx::PointF(0.125f, 0.25f); float arbitrary_number = 0.352f; gfx::Size arbitrary_size = gfx::Size(111, 222); gfx::Vector2d arbitrary_vector2d = gfx::Vector2d(111, 222); @@ -325,8 +321,6 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { layer->NoteLayerPropertyChanged()); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetContentsOpaque(true); layer->NoteLayerPropertyChanged()); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer2->SetPosition(arbitrary_point_f); - layer->NoteLayerPropertyChanged()); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetBackgroundColor(arbitrary_color)); VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( @@ -346,8 +340,6 @@ TEST(LayerImplTest, VerifyNeedsUpdateDrawProperties) { arbitrary_filters)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetMasksToBounds(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetContentsOpaque(true)); - VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( - layer2->SetPosition(arbitrary_point_f)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->SetDrawsContent(true)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( layer->SetBackgroundColor(arbitrary_color)); diff --git a/chromium/cc/layers/layer_unittest.cc b/chromium/cc/layers/layer_unittest.cc index 1f207f8e3bc..044c5b7dec7 100644 --- a/chromium/cc/layers/layer_unittest.cc +++ b/chromium/cc/layers/layer_unittest.cc @@ -877,22 +877,22 @@ TEST_F(LayerTest, TestSettingMainThreadScrollingReason) { EXPECT_SET_NEEDS_COMMIT(1, test_layer->AddMainThreadScrollingReasons( MainThreadScrollingReason::kScrollbarScrolling)); - EXPECT_EQ(reasons, test_layer->main_thread_scrolling_reasons()); + EXPECT_EQ(reasons, test_layer->GetMainThreadScrollingReasons()); // Check that the reasons can be selectively cleared. EXPECT_SET_NEEDS_COMMIT( 1, test_layer->ClearMainThreadScrollingReasons(reasons_to_clear)); EXPECT_EQ(reasons_after_clearing, - test_layer->main_thread_scrolling_reasons()); + test_layer->GetMainThreadScrollingReasons()); // Check that clearing non-set reasons doesn't set needs commit. reasons_to_clear = 0; reasons_to_clear |= MainThreadScrollingReason::kCustomScrollbarScrolling; - reasons_to_clear |= MainThreadScrollingReason::kPageOverlay; + reasons_to_clear |= MainThreadScrollingReason::kFrameOverlay; EXPECT_SET_NEEDS_COMMIT( 0, test_layer->ClearMainThreadScrollingReasons(reasons_to_clear)); EXPECT_EQ(reasons_after_clearing, - test_layer->main_thread_scrolling_reasons()); + test_layer->GetMainThreadScrollingReasons()); // Check that adding an existing condition doesn't set needs commit. EXPECT_SET_NEEDS_COMMIT( @@ -1346,7 +1346,7 @@ TEST_F(LayerTest, PushUpdatesShouldHitTest) { root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_TRUE(impl_layer->DrawsContent()); EXPECT_FALSE(impl_layer->hit_testable_without_draws_content()); - EXPECT_TRUE(impl_layer->should_hit_test()); + EXPECT_TRUE(impl_layer->ShouldHitTest()); // A layer that does not draw content and does not hit test without drawing // content should not be hit testable. @@ -1354,7 +1354,7 @@ TEST_F(LayerTest, PushUpdatesShouldHitTest) { root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); EXPECT_FALSE(impl_layer->hit_testable_without_draws_content()); - EXPECT_FALSE(impl_layer->should_hit_test()); + EXPECT_FALSE(impl_layer->ShouldHitTest()); // |SetHitTestableWithoutDrawsContent| should cause a layer to become hit // testable even though it does not draw content. @@ -1362,7 +1362,7 @@ TEST_F(LayerTest, PushUpdatesShouldHitTest) { root_layer->PushPropertiesTo(impl_layer.get()); EXPECT_FALSE(impl_layer->DrawsContent()); EXPECT_TRUE(impl_layer->hit_testable_without_draws_content()); - EXPECT_TRUE(impl_layer->should_hit_test()); + EXPECT_TRUE(impl_layer->ShouldHitTest()); } void ReceiveCopyOutputResult(int* result_count, @@ -1548,20 +1548,51 @@ class LayerTestWithLayerLists : public LayerTest { } }; -TEST_F(LayerTestWithLayerLists, LayerTreeHostRegistersElementId) { +TEST_F(LayerTestWithLayerLists, LayerTreeHostRegistersScrollingElementId) { + scoped_refptr<Layer> normal_layer = Layer::Create(); + scoped_refptr<Layer> scrolling_layer = Layer::Create(); + scrolling_layer->SetScrollable(gfx::Size(1000, 1000)); + ElementId normal_element_id = ElementId(2); + ElementId scrolling_element_id = ElementId(3); + normal_layer->SetElementId(normal_element_id); + scrolling_layer->SetElementId(scrolling_element_id); + + EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(normal_element_id)); + EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(scrolling_element_id)); + normal_layer->SetLayerTreeHost(layer_tree_host_.get()); + scrolling_layer->SetLayerTreeHost(layer_tree_host_.get()); + EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(normal_element_id)); + EXPECT_EQ(scrolling_layer, + layer_tree_host_->LayerByElementId(scrolling_element_id)); + + normal_layer->SetLayerTreeHost(nullptr); + scrolling_layer->SetLayerTreeHost(nullptr); + EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(scrolling_element_id)); +} + +TEST_F(LayerTestWithLayerLists, ChangingScrollableElementIdRegistersElement) { scoped_refptr<Layer> test_layer = Layer::Create(); + test_layer->SetScrollable(gfx::Size(1000, 1000)); + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); + test_layer->SetLayerTreeHost(layer_tree_host_.get()); + ElementId element_id = ElementId(2); + EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(element_id)); + + // Setting the element id should register the layer. test_layer->SetElementId(element_id); + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); + EXPECT_EQ(test_layer, layer_tree_host_->LayerByElementId(element_id)); + // Unsetting the element id should unregister the layer. + test_layer->SetElementId(ElementId()); EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(element_id)); - test_layer->SetLayerTreeHost(layer_tree_host_.get()); - EXPECT_EQ(test_layer, layer_tree_host_->LayerByElementId(element_id)); test_layer->SetLayerTreeHost(nullptr); EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(element_id)); } -TEST_F(LayerTestWithLayerLists, ChangingElementIdRegistersElement) { +TEST_F(LayerTestWithLayerLists, ChangingScrollableRegistersElement) { scoped_refptr<Layer> test_layer = Layer::Create(); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); test_layer->SetLayerTreeHost(layer_tree_host_.get()); @@ -1569,9 +1600,15 @@ TEST_F(LayerTestWithLayerLists, ChangingElementIdRegistersElement) { ElementId element_id = ElementId(2); EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(element_id)); - // Setting the element id should register the layer. + // Setting the element id commits the element id but should not register + // the layer. test_layer->SetElementId(element_id); EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); + EXPECT_EQ(nullptr, layer_tree_host_->LayerByElementId(element_id)); + + // Making the layer scrollable should register it. + test_layer->SetScrollable(gfx::Size(1000, 1000)); + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); EXPECT_EQ(test_layer, layer_tree_host_->LayerByElementId(element_id)); // Unsetting the element id should unregister the layer. diff --git a/chromium/cc/layers/nine_patch_layer_impl.cc b/chromium/cc/layers/nine_patch_layer_impl.cc index 9e6c80055f0..28a92410367 100644 --- a/chromium/cc/layers/nine_patch_layer_impl.cc +++ b/chromium/cc/layers/nine_patch_layer_impl.cc @@ -85,7 +85,7 @@ const char* NinePatchLayerImpl::LayerTypeAsString() const { return "cc::NinePatchLayerImpl"; } -std::unique_ptr<base::DictionaryValue> NinePatchLayerImpl::LayerAsJson() { +std::unique_ptr<base::DictionaryValue> NinePatchLayerImpl::LayerAsJson() const { std::unique_ptr<base::DictionaryValue> result = LayerImpl::LayerAsJson(); quad_generator_.AsJson(result.get()); return result; diff --git a/chromium/cc/layers/nine_patch_layer_impl.h b/chromium/cc/layers/nine_patch_layer_impl.h index 4841059fcaf..5e01501d4ee 100644 --- a/chromium/cc/layers/nine_patch_layer_impl.h +++ b/chromium/cc/layers/nine_patch_layer_impl.h @@ -44,7 +44,7 @@ class CC_EXPORT NinePatchLayerImpl : public UIResourceLayerImpl { void AppendQuads(viz::RenderPass* render_pass, AppendQuadsData* append_quads_data) override; - std::unique_ptr<base::DictionaryValue> LayerAsJson() override; + std::unique_ptr<base::DictionaryValue> LayerAsJson() const override; protected: NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id); diff --git a/chromium/cc/layers/painted_scrollbar_layer.cc b/chromium/cc/layers/painted_scrollbar_layer.cc index 541c024eba5..214a33ba52c 100644 --- a/chromium/cc/layers/painted_scrollbar_layer.cc +++ b/chromium/cc/layers/painted_scrollbar_layer.cc @@ -4,24 +4,12 @@ #include "cc/layers/painted_scrollbar_layer.h" -#include <algorithm> - #include "base/auto_reset.h" -#include "cc/base/math_util.h" -#include "cc/input/main_thread_scrolling_reason.h" #include "cc/layers/painted_scrollbar_layer_impl.h" -#include "cc/paint/paint_flags.h" #include "cc/paint/skia_paint_canvas.h" -#include "cc/resources/ui_resource_bitmap.h" #include "cc/trees/draw_property_utils.h" #include "cc/trees/layer_tree_host.h" -#include "cc/trees/layer_tree_impl.h" -#include "skia/ext/platform_canvas.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "third_party/skia/include/core/SkSize.h" -#include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/skia_util.h" namespace { static constexpr int kMaxScrollbarDimension = 8192; @@ -54,10 +42,6 @@ PaintedScrollbarLayer::PaintedScrollbarLayer( is_overlay_(scrollbar_->IsOverlay()), has_thumb_(scrollbar_->HasThumb()), thumb_opacity_(scrollbar_->ThumbOpacity()) { - if (!scrollbar_->IsOverlay()) { - AddMainThreadScrollingReasons( - MainThreadScrollingReason::kScrollbarScrolling); - } SetIsScrollbar(true); } diff --git a/chromium/cc/layers/picture_layer.cc b/chromium/cc/layers/picture_layer.cc index 50a0b87b9d4..fa1d6ae4c54 100644 --- a/chromium/cc/layers/picture_layer.cc +++ b/chromium/cc/layers/picture_layer.cc @@ -133,6 +133,7 @@ bool PictureLayer::Update() { layer_tree_host()->recording_scale_factor()); SetNeedsPushProperties(); + paint_count_++; } else { // If this invalidation did not affect the recording source, then it can be // cleared as an optimization. diff --git a/chromium/cc/layers/picture_layer_impl.cc b/chromium/cc/layers/picture_layer_impl.cc index 5c4c58fc5da..c3bed20247f 100644 --- a/chromium/cc/layers/picture_layer_impl.cc +++ b/chromium/cc/layers/picture_layer_impl.cc @@ -256,12 +256,6 @@ void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass, viz::SharedQuadState* shared_quad_state = render_pass->CreateAndAppendSharedQuadState(); - if (mask_type_ != Layer::LayerMaskType::NOT_MASK) { - append_quads_data->num_mask_layers++; - if (is_rounded_corner_mask()) - append_quads_data->num_rounded_corner_mask_layers++; - } - if (raster_source_->IsSolidColor()) { // TODO(sunxd): Solid color non-mask layers are forced to have contents // scale = 1. This is a workaround to temperarily fix @@ -461,13 +455,6 @@ void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass, visible_geometry_rect.height(); append_quads_data->visible_layer_area += visible_geometry_area; - if (mask_type_ != Layer::LayerMaskType::NOT_MASK) { - append_quads_data->visible_mask_layer_area += visible_geometry_area; - if (is_rounded_corner_mask()) - append_quads_data->visible_rounded_corner_mask_layer_area += - visible_geometry_area; - } - bool has_draw_quad = false; if (*iter && iter->draw_info().IsReadyToDraw()) { const TileDrawInfo& draw_info = iter->draw_info(); diff --git a/chromium/cc/layers/picture_layer_impl_unittest.cc b/chromium/cc/layers/picture_layer_impl_unittest.cc index 147364120ac..00cbffe0d5a 100644 --- a/chromium/cc/layers/picture_layer_impl_unittest.cc +++ b/chromium/cc/layers/picture_layer_impl_unittest.cc @@ -13,6 +13,7 @@ #include "base/location.h" #include "base/macros.h" +#include "base/stl_util.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" #include "cc/base/math_util.h" @@ -3242,7 +3243,7 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) { while (std::abs(tile->contents_scale_key() - expected_scales[scale_index]) > std::numeric_limits<float>::epsilon()) { ++scale_index; - ASSERT_LT(scale_index, arraysize(expected_scales)); + ASSERT_LT(scale_index, base::size(expected_scales)); } EXPECT_FLOAT_EQ(tile->contents_scale_key(), expected_scales[scale_index]); @@ -3290,7 +3291,7 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) { while (std::abs(tile->contents_scale_key() - expected_scales[scale_index]) > std::numeric_limits<float>::epsilon()) { ++scale_index; - ASSERT_LT(scale_index, arraysize(expected_scales)); + ASSERT_LT(scale_index, base::size(expected_scales)); } EXPECT_FLOAT_EQ(tile->contents_scale_key(), expected_scales[scale_index]); @@ -4051,7 +4052,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, layer1->SetBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); - layer1->SetPosition(occluding_layer_position); + layer1->test_properties()->position = occluding_layer_position; RebuildPropertyTreesOnPendingTree(); host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); @@ -4075,7 +4076,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, EXPECT_EQ(20, unoccluded_tile_count); // Full occlusion. - layer1->SetPosition(gfx::PointF()); + layer1->test_properties()->position = gfx::PointF(); layer1->NoteLayerPropertyChanged(); RebuildPropertyTreesOnPendingTree(); @@ -4146,7 +4147,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, layer1->SetBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); - layer1->SetPosition(occluding_layer_position); + layer1->test_properties()->position = occluding_layer_position; RebuildPropertyTreesOnPendingTree(); host_impl()->AdvanceToNextFrame(base::TimeDelta::FromMilliseconds(200)); @@ -4183,7 +4184,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, } // Full occlusion. - layer1->SetPosition(gfx::PointF()); + layer1->test_properties()->position = gfx::PointF(); layer1->NoteLayerPropertyChanged(); RebuildPropertyTreesOnPendingTree(); @@ -4243,7 +4244,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) { layer1->SetBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); - layer1->SetPosition(occluding_layer_position); + layer1->test_properties()->position = occluding_layer_position; pending_layer()->tilings()->RemoveAllTilings(); float low_res_factor = host_impl()->settings().low_res_contents_scale_factor; @@ -4328,7 +4329,7 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { layer1->SetBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); - layer1->SetPosition(occluding_layer_position); + layer1->test_properties()->position = occluding_layer_position; ActivateTree(); @@ -4424,7 +4425,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, active_occluding_layer->SetBounds(layer_bounds); active_occluding_layer->SetDrawsContent(true); active_occluding_layer->SetContentsOpaque(true); - active_occluding_layer->SetPosition(active_occluding_layer_position); + active_occluding_layer->test_properties()->position = + active_occluding_layer_position; ActivateTree(); // Partially invalidate the pending layer. Tiles inside the invalidation rect @@ -4440,7 +4442,8 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, pending_occluding_layer->SetBounds(layer_bounds); pending_occluding_layer->SetDrawsContent(true); pending_occluding_layer->SetContentsOpaque(true); - pending_occluding_layer->SetPosition(pending_occluding_layer_position); + pending_occluding_layer->test_properties()->position = + pending_occluding_layer_position; EXPECT_EQ(1u, pending_layer()->num_tilings()); EXPECT_EQ(2u, active_layer()->num_tilings()); diff --git a/chromium/cc/layers/render_surface_impl.cc b/chromium/cc/layers/render_surface_impl.cc index d4a0e72f590..168de7b984e 100644 --- a/chromium/cc/layers/render_surface_impl.cc +++ b/chromium/cc/layers/render_surface_impl.cc @@ -153,6 +153,10 @@ const FilterOperations& RenderSurfaceImpl::BackdropFilters() const { return OwningEffectNode()->backdrop_filters; } +const gfx::RectF& RenderSurfaceImpl::BackdropFilterBounds() const { + return OwningEffectNode()->backdrop_filter_bounds; +} + bool RenderSurfaceImpl::TrilinearFiltering() const { return OwningEffectNode()->trilinear_filtering; } @@ -375,6 +379,7 @@ std::unique_ptr<viz::RenderPass> RenderSurfaceImpl::CreateRenderPass() { draw_properties_.screen_space_transform); pass->filters = Filters(); pass->backdrop_filters = BackdropFilters(); + pass->backdrop_filter_bounds = BackdropFilterBounds(); pass->generate_mipmap = TrilinearFiltering(); pass->cache_render_pass = ShouldCacheRenderSurface(); pass->has_damage_from_contributing_content = @@ -430,17 +435,6 @@ void RenderSurfaceImpl::AppendQuads(DrawMode draw_mode, "mask_layer_gpu_memory_usage", mask_layer->GPUMemoryUsageInBytes()); - int64_t visible_geometry_area = - static_cast<int64_t>(unoccluded_content_rect.width()) * - unoccluded_content_rect.height(); - append_quads_data->num_mask_layers++; - append_quads_data->visible_mask_layer_area += visible_geometry_area; - if (mask_layer->is_rounded_corner_mask()) { - append_quads_data->num_rounded_corner_mask_layers++; - append_quads_data->visible_rounded_corner_mask_layer_area += - visible_geometry_area; - } - if (mask_layer->mask_type() == Layer::LayerMaskType::MULTI_TEXTURE_MASK) { TileMaskLayer(render_pass, shared_quad_state, unoccluded_content_rect); return; diff --git a/chromium/cc/layers/render_surface_impl.h b/chromium/cc/layers/render_surface_impl.h index 6e648a4d8ff..e3011ee3111 100644 --- a/chromium/cc/layers/render_surface_impl.h +++ b/chromium/cc/layers/render_surface_impl.h @@ -150,6 +150,7 @@ class CC_EXPORT RenderSurfaceImpl { const FilterOperations& Filters() const; const FilterOperations& BackdropFilters() const; + const gfx::RectF& BackdropFilterBounds() const; gfx::PointF FiltersOrigin() const; gfx::Transform SurfaceScale() const; diff --git a/chromium/cc/layers/scrollbar_layer_unittest.cc b/chromium/cc/layers/scrollbar_layer_unittest.cc index 4425f722798..c46e3eef674 100644 --- a/chromium/cc/layers/scrollbar_layer_unittest.cc +++ b/chromium/cc/layers/scrollbar_layer_unittest.cc @@ -252,49 +252,6 @@ TEST_F(ScrollbarLayerTest, RepaintOverlayWhenResourceDisposed) { } } -TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) { - // Create and attach a non-overlay scrollbar. - std::unique_ptr<Scrollbar> scrollbar(new FakeScrollbar); - LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), std::move(scrollbar), false, false, 0, 0); - PaintedScrollbarLayerImpl* scrollbar_layer_impl = - static_cast<PaintedScrollbarLayerImpl*>( - layer_impl_tree_root->layer_tree_impl()->LayerById( - scrollbar_layer_id_)); - ScrollTree& scroll_tree = - layer_impl_tree_root->layer_tree_impl()->property_trees()->scroll_tree; - ScrollNode* scroll_node = - scroll_tree.Node(scrollbar_layer_impl->scroll_tree_index()); - - // When the scrollbar is not an overlay scrollbar, the scroll should be - // responded to on the main thread as the compositor does not yet implement - // scrollbar scrolling. - InputHandler::ScrollStatus status = layer_tree_host_->host_impl()->TryScroll( - gfx::PointF(), InputHandler::TOUCHSCREEN, scroll_tree, scroll_node); - EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, - status.main_thread_scrolling_reasons); - - // Create and attach an overlay scrollbar. - scrollbar.reset(new FakeScrollbar(false, false, true)); - - layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar( - layer_tree_host_.get(), std::move(scrollbar), false, false, 0, 0); - scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( - layer_impl_tree_root->layer_tree_impl()->LayerById(scrollbar_layer_id_)); - scroll_tree = - layer_impl_tree_root->layer_tree_impl()->property_trees()->scroll_tree; - scroll_node = scroll_tree.Node(scrollbar_layer_impl->scroll_tree_index()); - - // The user shouldn't be able to drag an overlay scrollbar and the scroll - // may be handled in the compositor. - status = layer_tree_host_->host_impl()->TryScroll( - gfx::PointF(), InputHandler::TOUCHSCREEN, scroll_tree, scroll_node); - EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNotScrollable, - status.main_thread_scrolling_reasons); -} - class FakeNinePatchScrollbar : public FakeScrollbar { public: bool UsesNinePatchThumbResource() const override { return true; } diff --git a/chromium/cc/layers/surface_layer_impl.cc b/chromium/cc/layers/surface_layer_impl.cc index 23810a45400..3b411aa7c69 100644 --- a/chromium/cc/layers/surface_layer_impl.cc +++ b/chromium/cc/layers/surface_layer_impl.cc @@ -6,6 +6,7 @@ #include <stdint.h> +#include "base/stl_util.h" #include "base/trace_event/traced_value.h" #include "cc/debug/debug_colors.h" #include "cc/layers/append_quads_data.h" @@ -212,7 +213,7 @@ void SurfaceLayerImpl::AppendRainbowDebugBorder(viz::RenderPass* render_pass) { 0x800000ff, // Blue. 0x80ee82ee, // Violet. }; - const int kNumColors = arraysize(colors); + const int kNumColors = base::size(colors); const int kStripeWidth = 300; const int kStripeHeight = 300; diff --git a/chromium/cc/layers/texture_layer.cc b/chromium/cc/layers/texture_layer.cc index 0b2784bf04d..e97162e7b1e 100644 --- a/chromium/cc/layers/texture_layer.cc +++ b/chromium/cc/layers/texture_layer.cc @@ -339,8 +339,8 @@ TextureLayer::TransferableResourceHolder::GetCallbackForImplThread( DCHECK_GT(internal_references_, 0); InternalAddRef(); return viz::SingleReleaseCallback::Create( - base::Bind(&TransferableResourceHolder::ReturnAndReleaseOnImplThread, - this, std::move(main_thread_task_runner))); + base::BindOnce(&TransferableResourceHolder::ReturnAndReleaseOnImplThread, + this, std::move(main_thread_task_runner))); } void TextureLayer::TransferableResourceHolder::InternalAddRef() { @@ -375,7 +375,7 @@ void TextureLayer::TransferableResourceHolder::ReturnAndReleaseOnImplThread( #endif main_thread_task_runner->PostTask( FROM_HERE, - base::Bind(&TransferableResourceHolder::InternalRelease, this)); + base::BindOnce(&TransferableResourceHolder::InternalRelease, this)); } } // namespace cc diff --git a/chromium/cc/layers/texture_layer_impl_unittest.cc b/chromium/cc/layers/texture_layer_impl_unittest.cc index 7022e5757f1..93a61894e5b 100644 --- a/chromium/cc/layers/texture_layer_impl_unittest.cc +++ b/chromium/cc/layers/texture_layer_impl_unittest.cc @@ -63,7 +63,7 @@ TEST(TextureLayerImplTest, Occlusion) { texture_layer_impl->SetDrawsContent(true); texture_layer_impl->SetTransferableResource( resource, - viz::SingleReleaseCallback::Create(base::Bind(&IgnoreCallback))); + viz::SingleReleaseCallback::Create(base::BindOnce(&IgnoreCallback))); impl.CalcDrawProps(viewport_size); @@ -122,7 +122,7 @@ TEST(TextureLayerImplTest, ResourceNotFreedOnGpuRasterToggle) { texture_layer_impl->SetBounds(layer_size); texture_layer_impl->SetDrawsContent(true); texture_layer_impl->SetTransferableResource( - resource, viz::SingleReleaseCallback::Create(base::Bind( + resource, viz::SingleReleaseCallback::Create(base::BindOnce( [](bool* released, const gpu::SyncToken& sync_token, bool lost) { *released = true; }, base::Unretained(&released)))); diff --git a/chromium/cc/layers/texture_layer_unittest.cc b/chromium/cc/layers/texture_layer_unittest.cc index de62de061e6..c85b89e9247 100644 --- a/chromium/cc/layers/texture_layer_unittest.cc +++ b/chromium/cc/layers/texture_layer_unittest.cc @@ -123,11 +123,11 @@ struct CommonResourceObjects { gpu::CommandBufferId::FromUnsafeValue(0x234), 2) { release_callback1_ = - base::Bind(&MockReleaseCallback::Release, - base::Unretained(&mock_callback_), mailbox_name1_); + base::BindRepeating(&MockReleaseCallback::Release, + base::Unretained(&mock_callback_), mailbox_name1_); release_callback2_ = - base::Bind(&MockReleaseCallback::Release, - base::Unretained(&mock_callback_), mailbox_name2_); + base::BindRepeating(&MockReleaseCallback::Release, + base::Unretained(&mock_callback_), mailbox_name2_); const uint32_t arbitrary_target1 = GL_TEXTURE_2D; const uint32_t arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES; resource1_ = viz::TransferableResource::MakeGL( @@ -136,9 +136,9 @@ struct CommonResourceObjects { mailbox_name2_, GL_LINEAR, arbitrary_target2, sync_token2_); gfx::Size size(128, 128); shared_bitmap_id_ = viz::SharedBitmap::GenerateId(); - sw_release_callback_ = - base::Bind(&MockReleaseCallback::Release2, - base::Unretained(&mock_callback_), shared_bitmap_id_); + sw_release_callback_ = base::BindRepeating( + &MockReleaseCallback::Release2, base::Unretained(&mock_callback_), + shared_bitmap_id_); sw_resource_ = viz::TransferableResource::MakeSoftware( shared_bitmap_id_, size, viz::RGBA_8888); } @@ -683,7 +683,7 @@ class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { void SetMailbox(char mailbox_char) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( + viz::SingleReleaseCallback::Create(base::BindOnce( &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback, base::Unretained(this), mailbox_char)); @@ -761,7 +761,7 @@ class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { const gpu::SyncToken sync_token = SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char)); std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( + viz::SingleReleaseCallback::Create(base::BindOnce( &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback, base::Unretained(this), sync_token)); auto resource = viz::TransferableResource::MakeGL( @@ -1027,9 +1027,9 @@ class TextureLayerNoExtraCommitForMailboxTest *resource = viz::TransferableResource::MakeGL(MailboxFromChar('1'), GL_LINEAR, GL_TEXTURE_2D, SyncTokenFromUInt(0x123)); - *release_callback = viz::SingleReleaseCallback::Create( - base::Bind(&TextureLayerNoExtraCommitForMailboxTest::ResourceReleased, - base::Unretained(this))); + *release_callback = viz::SingleReleaseCallback::Create(base::BindOnce( + &TextureLayerNoExtraCommitForMailboxTest::ResourceReleased, + base::Unretained(this))); return true; } @@ -1101,9 +1101,9 @@ class TextureLayerChangeInvisibleMailboxTest if (!resource_changed_) return false; *resource = resource_; - *release_callback = viz::SingleReleaseCallback::Create( - base::Bind(&TextureLayerChangeInvisibleMailboxTest::ResourceReleased, - base::Unretained(this))); + *release_callback = viz::SingleReleaseCallback::Create(base::BindOnce( + &TextureLayerChangeInvisibleMailboxTest::ResourceReleased, + base::Unretained(this))); return true; } @@ -1220,8 +1220,8 @@ class TextureLayerReleaseResourcesBase *resource = viz::TransferableResource::MakeGL( MailboxFromChar('1'), GL_LINEAR, GL_TEXTURE_2D, SyncTokenFromUInt(1)); *release_callback = viz::SingleReleaseCallback::Create( - base::Bind(&TextureLayerReleaseResourcesBase::ResourceReleased, - base::Unretained(this))); + base::BindOnce(&TextureLayerReleaseResourcesBase::ResourceReleased, + base::Unretained(this))); return true; } @@ -1291,7 +1291,7 @@ class TextureLayerWithResourceMainThreadDeleted : public LayerTreeTest { void SetMailbox(char mailbox_char) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( + viz::SingleReleaseCallback::Create(base::BindOnce( &TextureLayerWithResourceMainThreadDeleted::ReleaseCallback, base::Unretained(this))); auto resource = viz::TransferableResource::MakeGL( @@ -1361,7 +1361,7 @@ class TextureLayerWithResourceImplThreadDeleted : public LayerTreeTest { void SetMailbox(char mailbox_char) { EXPECT_EQ(true, main_thread_.CalledOnValidThread()); std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( + viz::SingleReleaseCallback::Create(base::BindOnce( &TextureLayerWithResourceImplThreadDeleted::ReleaseCallback, base::Unretained(this))); auto resource = viz::TransferableResource::MakeGL( diff --git a/chromium/cc/layers/ui_resource_layer_impl.cc b/chromium/cc/layers/ui_resource_layer_impl.cc index c3a94fc6fbc..7eae103e9aa 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.cc +++ b/chromium/cc/layers/ui_resource_layer_impl.cc @@ -138,7 +138,8 @@ const char* UIResourceLayerImpl::LayerTypeAsString() const { return "cc::UIResourceLayerImpl"; } -std::unique_ptr<base::DictionaryValue> UIResourceLayerImpl::LayerAsJson() { +std::unique_ptr<base::DictionaryValue> UIResourceLayerImpl::LayerAsJson() + const { std::unique_ptr<base::DictionaryValue> result = LayerImpl::LayerAsJson(); result->Set("ImageBounds", MathUtil::AsValue(image_bounds_)); diff --git a/chromium/cc/layers/ui_resource_layer_impl.h b/chromium/cc/layers/ui_resource_layer_impl.h index bd94720a0e2..1283a23a9c3 100644 --- a/chromium/cc/layers/ui_resource_layer_impl.h +++ b/chromium/cc/layers/ui_resource_layer_impl.h @@ -52,7 +52,7 @@ class CC_EXPORT UIResourceLayerImpl : public LayerImpl { void AppendQuads(viz::RenderPass* render_pass, AppendQuadsData* append_quads_data) override; - std::unique_ptr<base::DictionaryValue> LayerAsJson() override; + std::unique_ptr<base::DictionaryValue> LayerAsJson() const override; protected: UIResourceLayerImpl(LayerTreeImpl* tree_impl, int id); diff --git a/chromium/cc/layers/video_layer_impl_unittest.cc b/chromium/cc/layers/video_layer_impl_unittest.cc index f70e8e22646..f7b2f20bcd6 100644 --- a/chromium/cc/layers/video_layer_impl_unittest.cc +++ b/chromium/cc/layers/video_layer_impl_unittest.cc @@ -299,8 +299,6 @@ TEST(VideoLayerImplTest, Rotated270) { EXPECT_EQ(gfx::Point3F(0, 0, 0), p2); } -void EmptyCallback(const gpu::SyncToken& sync_token) {} - TEST(VideoLayerImplTest, SoftwareVideoFrameGeneratesYUVQuad) { gfx::Size layer_size(1000, 1000); @@ -388,7 +386,7 @@ TEST(VideoLayerImplTest, NativeYUVFrameGeneratesYUVQuad) { scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::WrapNativeTextures( - media::PIXEL_FORMAT_I420, mailbox_holders, base::Bind(EmptyCallback), + media::PIXEL_FORMAT_I420, mailbox_holders, base::DoNothing(), gfx::Size(10, 10), gfx::Rect(10, 10), gfx::Size(10, 10), base::TimeDelta()); ASSERT_TRUE(video_frame); @@ -432,7 +430,7 @@ TEST(VideoLayerImplTest, NativeARGBFrameGeneratesTextureQuad) { gfx::Size resource_size = gfx::Size(10, 10); scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::WrapNativeTextures( - media::PIXEL_FORMAT_ARGB, mailbox_holders, base::Bind(EmptyCallback), + media::PIXEL_FORMAT_ARGB, mailbox_holders, base::DoNothing(), resource_size, gfx::Rect(10, 10), resource_size, base::TimeDelta()); ASSERT_TRUE(video_frame); video_frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY, diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc index 3dfd15b8666..286c3288c93 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.cc @@ -167,14 +167,15 @@ void AsyncLayerTreeFrameSink::SetLocalSurfaceId( void AsyncLayerTreeFrameSink::SubmitCompositorFrame( viz::CompositorFrame frame, + bool hit_test_data_changed, bool show_hit_test_borders) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(compositor_frame_sink_ptr_); DCHECK(frame.metadata.begin_frame_ack.has_damage); DCHECK_LE(viz::BeginFrameArgs::kStartingFrameNumber, frame.metadata.begin_frame_ack.sequence_number); - TRACE_EVENT0("cc,benchmark", - "AsyncLayerTreeFrameSink::SubmitCompositorFrame"); + TRACE_EVENT1("cc,benchmark", "AsyncLayerTreeFrameSink::SubmitCompositorFrame", + "source_frame_number_", source_frame_number_); // It's possible to request an immediate composite from cc which will bypass // BeginFrame. In that case, we cannot collect full graphics pipeline data. @@ -217,6 +218,28 @@ void AsyncLayerTreeFrameSink::SubmitCompositorFrame( if (show_hit_test_borders && hit_test_region_list) hit_test_region_list->flags |= viz::HitTestRegionFlags::kHitTestDebug; + // If |hit_test_data_changed| was set or local_surface_id has been updated, + // we always send hit-test data; otherwise we check for equality with the + // last submitted hit-test data for possible optimization. + if (!hit_test_region_list) { + last_hit_test_data_ = viz::HitTestRegionList(); + } else if (!hit_test_data_changed && + local_surface_id_ == last_submitted_local_surface_id_) { + if (viz::HitTestRegionList::IsEqual(*hit_test_region_list, + last_hit_test_data_)) { + DCHECK(!viz::HitTestRegionList::IsEqual(*hit_test_region_list, + viz::HitTestRegionList())); + hit_test_region_list = base::nullopt; + } else { + last_hit_test_data_ = *hit_test_region_list; + } + + UMA_HISTOGRAM_BOOLEAN("Event.VizHitTest.HitTestDataIsEqualAccuracy", + !hit_test_region_list); + } else { + last_hit_test_data_ = *hit_test_region_list; + } + if (last_submitted_local_surface_id_ != local_surface_id_) { last_submitted_local_surface_id_ = local_surface_id_; last_submitted_device_scale_factor_ = frame.device_scale_factor(); @@ -314,7 +337,8 @@ void AsyncLayerTreeFrameSink::OnBeginFrame( TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", "ReceiveBeginFrameDiscard"); // We had a race with SetNeedsBeginFrame(false) and still need to let the - // sink know that we didn't use this BeginFrame. + // sink know that we didn't use this BeginFrame. OnBeginFrame() can also be + // called to deliver presentation feedback. DidNotProduceFrame(viz::BeginFrameAck(args, false)); return; } diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h index f3f3be12461..0750bcf231c 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink.h @@ -118,6 +118,7 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink void DetachFromClient() override; void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id) override; void SubmitCompositorFrame(viz::CompositorFrame frame, + bool hit_test_data_changed, bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, @@ -125,6 +126,10 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; void ForceAllocateNewId() override; + const viz::HitTestRegionList& get_last_hit_test_data_for_testing() const { + return last_hit_test_data_; + } + private: // mojom::CompositorFrameSinkClient implementation: void DidReceiveCompositorFrameAck( @@ -166,6 +171,8 @@ class CC_MOJO_EMBEDDER_EXPORT AsyncLayerTreeFrameSink const bool enable_surface_synchronization_; const bool wants_animate_only_begin_frames_; + viz::HitTestRegionList last_hit_test_data_; + viz::LocalSurfaceId last_submitted_local_surface_id_; float last_submitted_device_scale_factor_ = 1.f; gfx::Size last_submitted_size_in_pixels_; diff --git a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc index b00ca4cb0ec..cc49361e62f 100644 --- a/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc @@ -10,9 +10,16 @@ #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread.h" #include "cc/test/fake_layer_tree_frame_sink_client.h" +#include "components/viz/client/hit_test_data_provider_draw_quad.h" #include "components/viz/client/local_surface_id_provider.h" +#include "components/viz/common/quads/render_pass_draw_quad.h" +#include "components/viz/common/quads/solid_color_draw_quad.h" +#include "components/viz/common/quads/surface_draw_quad.h" +#include "components/viz/common/surfaces/surface_range.h" +#include "components/viz/test/compositor_frame_helpers.h" #include "components/viz/test/test_context_provider.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -70,8 +77,6 @@ TEST(AsyncLayerTreeFrameSinkTest, init_params.gpu_memory_buffer_manager = &test_gpu_memory_buffer_manager; init_params.pipes.compositor_frame_sink_info = std::move(sink_info); init_params.pipes.client_request = std::move(client_request); - init_params.local_surface_id_provider = - std::make_unique<viz::DefaultLocalSurfaceIdProvider>(); init_params.enable_surface_synchronization = true; auto layer_tree_frame_sink = std::make_unique<AsyncLayerTreeFrameSink>( std::move(provider), nullptr, &init_params); @@ -115,5 +120,312 @@ TEST(AsyncLayerTreeFrameSinkTest, } } // namespace + +// Boilerplate code for simple AsyncLayerTreeFrameSink. Friend of +// AsyncLayerTreeFrameSink. +class AsyncLayerTreeFrameSinkSimpleTest : public testing::Test { + public: + AsyncLayerTreeFrameSinkSimpleTest() + : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>( + base::TestMockTimeTaskRunner::Type::kStandalone)), + display_rect_(1, 1) { + auto context_provider = viz::TestContextProvider::Create(); + + viz::mojom::CompositorFrameSinkPtrInfo sink_info; + viz::mojom::CompositorFrameSinkRequest sink_request = + mojo::MakeRequest(&sink_info); + viz::mojom::CompositorFrameSinkClientPtr client; + viz::mojom::CompositorFrameSinkClientRequest client_request = + mojo::MakeRequest(&client); + + init_params_.compositor_task_runner = task_runner_; + init_params_.gpu_memory_buffer_manager = &test_gpu_memory_buffer_manager_; + init_params_.pipes.compositor_frame_sink_info = std::move(sink_info); + init_params_.pipes.client_request = std::move(client_request); + init_params_.enable_surface_synchronization = true; + init_params_.hit_test_data_provider = + std::make_unique<viz::HitTestDataProviderDrawQuad>( + /*should_ask_for_child_region=*/true, /*root_accepts_events=*/true); + + layer_tree_frame_sink_ = std::make_unique<AsyncLayerTreeFrameSink>( + std::move(context_provider), nullptr, &init_params_); + + viz::LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create()); + layer_tree_frame_sink_->SetLocalSurfaceId(local_surface_id); + layer_tree_frame_sink_->BindToClient(&layer_tree_frame_sink_client_); + } + + void SendRenderPassList(viz::RenderPassList* pass_list, + bool hit_test_data_changed) { + auto frame = viz::CompositorFrameBuilder() + .SetRenderPassList(std::move(*pass_list)) + .Build(); + pass_list->clear(); + layer_tree_frame_sink_->SubmitCompositorFrame( + std::move(frame), hit_test_data_changed, + /*show_hit_test_borders=*/false); + } + + const viz::HitTestRegionList& GetHitTestData() const { + return layer_tree_frame_sink_->get_last_hit_test_data_for_testing(); + } + + AsyncLayerTreeFrameSink::InitParams init_params_; + + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; + viz::TestGpuMemoryBufferManager test_gpu_memory_buffer_manager_; + gfx::Rect display_rect_; + std::unique_ptr<AsyncLayerTreeFrameSink> layer_tree_frame_sink_; + FakeLayerTreeFrameSinkClient layer_tree_frame_sink_client_; +}; + +TEST_F(AsyncLayerTreeFrameSinkSimpleTest, HitTestRegionListDuplicate) { + viz::RenderPassList pass_list; + + // Initial submission. + auto pass1 = viz::RenderPass::Create(); + pass1->id = 1; + pass1->output_rect = display_rect_; + auto* shared_quad_state1 = pass1->CreateAndAppendSharedQuadState(); + gfx::Rect rect1(display_rect_); + shared_quad_state1->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect1, + /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad1 = + pass1->quad_list.AllocateAndConstruct<viz::SolidColorDrawQuad>(); + quad1->SetNew(shared_quad_state1, /*rect=*/rect1, + /*visible_rect=*/rect1, SK_ColorBLACK, + /*force_anti_aliasing_off=*/false); + pass_list.push_back(move(pass1)); + SendRenderPassList(&pass_list, /*hit_test_data_changed=*/false); + task_runner_->RunUntilIdle(); + const viz::HitTestRegionList hit_test_region_list = GetHitTestData(); + + // Identical submission. + auto pass2 = viz::RenderPass::Create(); + pass2->id = 2; + pass2->output_rect = display_rect_; + auto* shared_quad_state2 = pass2->CreateAndAppendSharedQuadState(); + gfx::Rect rect2(display_rect_); + shared_quad_state2->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect2, + /*visible_quad_layer_rect=*/rect2, /*clip_rect=*/rect2, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad2 = + pass2->quad_list.AllocateAndConstruct<viz::SolidColorDrawQuad>(); + quad2->SetNew(shared_quad_state2, /*rect=*/rect2, + /*visible_rect=*/rect2, SK_ColorBLACK, + /*force_anti_aliasing_off=*/false); + pass_list.push_back(move(pass2)); + SendRenderPassList(&pass_list, /*hit_test_data_changed=*/false); + task_runner_->RunUntilIdle(); + + EXPECT_TRUE( + viz::HitTestRegionList::IsEqual(hit_test_region_list, GetHitTestData())); + + // Different submission. + const viz::SurfaceId child_surface_id( + viz::FrameSinkId(1, 1), + viz::LocalSurfaceId(2, base::UnguessableToken::Create())); + auto pass3_0 = viz::RenderPass::Create(); + pass3_0->output_rect = display_rect_; + pass3_0->id = 3; + auto* shared_quad_state3_0 = pass3_0->CreateAndAppendSharedQuadState(); + gfx::Rect rect3_0(display_rect_); + gfx::Transform transform3_0; + transform3_0.Translate(-200, -100); + shared_quad_state3_0->SetAll( + transform3_0, /*quad_layer_rect=*/rect3_0, + /*visible_quad_layer_rect=*/rect3_0, /*clip_rect=*/rect3_0, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad3_0 = + pass3_0->quad_list.AllocateAndConstruct<viz::SurfaceDrawQuad>(); + quad3_0->SetNew(shared_quad_state3_0, /*rect=*/rect3_0, + /*visible_rect=*/rect3_0, + viz::SurfaceRange(base::nullopt, child_surface_id), + SK_ColorBLACK, + /*stretch_content_to_fill_bounds=*/false, + /*ignores_input_event=*/false); + pass_list.push_back(std::move(pass3_0)); + + auto pass3_1 = viz::RenderPass::Create(); + pass3_1->output_rect = display_rect_; + pass3_1->id = 4; + auto* shared_quad_state3_1 = pass3_1->CreateAndAppendSharedQuadState(); + gfx::Rect rect3_1(display_rect_); + shared_quad_state3_1->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect3_1, + /*visible_quad_layer_rect=*/rect3_1, /*clip_rect=*/rect3_1, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad3_1 = + pass3_1->quad_list.AllocateAndConstruct<viz::SolidColorDrawQuad>(); + quad3_1->SetNew(shared_quad_state3_1, /*rect=*/rect3_1, + /*visible_rect=*/rect3_1, SK_ColorBLACK, + /*force_anti_aliasing_off=*/false); + pass_list.push_back(std::move(pass3_1)); + + auto pass3_root = viz::RenderPass::Create(); + pass3_root->output_rect = display_rect_; + pass3_root->id = 5; + auto* shared_quad_state3_root = pass3_root->CreateAndAppendSharedQuadState(); + gfx::Rect rect3_root(display_rect_); + shared_quad_state3_root->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect3_root, + /*visible_quad_layer_rect=*/rect3_root, /*clip_rect=*/rect3_root, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad3_root_1 = + pass3_root->quad_list.AllocateAndConstruct<viz::RenderPassDrawQuad>(); + quad3_root_1->SetNew(shared_quad_state3_root, /*rect=*/rect3_root, + /*visible_rect=*/rect3_root, /*render_pass_id=*/3, + /*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), + gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, + 1.0f); + auto* quad3_root_2 = + pass3_root->quad_list.AllocateAndConstruct<viz::RenderPassDrawQuad>(); + quad3_root_2->SetNew(shared_quad_state3_root, /*rect=*/rect3_root, + /*visible_rect=*/rect3_root, /*render_pass_id=*/4, + /*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), + gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, + 1.0f); + pass_list.push_back(std::move(pass3_root)); + + SendRenderPassList(&pass_list, /*hit_test_data_changed=*/false); + task_runner_->RunUntilIdle(); + EXPECT_FALSE( + viz::HitTestRegionList::IsEqual(hit_test_region_list, GetHitTestData())); +} + +TEST_F(AsyncLayerTreeFrameSinkSimpleTest, + HitTestRegionListDuplicateChangedFlip) { + viz::RenderPassList pass_list; + + // Initial submission. + auto pass1 = viz::RenderPass::Create(); + pass1->id = 1; + pass1->output_rect = display_rect_; + auto* shared_quad_state1 = pass1->CreateAndAppendSharedQuadState(); + gfx::Rect rect1(display_rect_); + shared_quad_state1->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect1, + /*visible_quad_layer_rect=*/rect1, /*clip_rect=*/rect1, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad1 = + pass1->quad_list.AllocateAndConstruct<viz::SolidColorDrawQuad>(); + quad1->SetNew(shared_quad_state1, /*rect=*/rect1, + /*visible_rect=*/rect1, SK_ColorBLACK, + /*force_anti_aliasing_off=*/false); + pass_list.push_back(move(pass1)); + SendRenderPassList(&pass_list, /*hit_test_data_changed=*/false); + task_runner_->RunUntilIdle(); + viz::HitTestRegionList hit_test_region_list = GetHitTestData(); + + // Different submission with |hit_test_data_changed| set to true. + const viz::SurfaceId child_surface_id( + viz::FrameSinkId(1, 1), + viz::LocalSurfaceId(2, base::UnguessableToken::Create())); + auto pass2_0 = viz::RenderPass::Create(); + pass2_0->output_rect = display_rect_; + pass2_0->id = 2; + auto* shared_quad_state2_0 = pass2_0->CreateAndAppendSharedQuadState(); + gfx::Rect rect2_0(display_rect_); + gfx::Transform transform2_0; + transform2_0.Translate(-200, -100); + shared_quad_state2_0->SetAll( + transform2_0, /*quad_layer_rect=*/rect2_0, + /*visible_quad_layer_rect=*/rect2_0, /*clip_rect=*/rect2_0, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad2_0 = + pass2_0->quad_list.AllocateAndConstruct<viz::SurfaceDrawQuad>(); + quad2_0->SetNew(shared_quad_state2_0, /*rect=*/rect2_0, + /*visible_rect=*/rect2_0, + viz::SurfaceRange(base::nullopt, child_surface_id), + SK_ColorBLACK, + /*stretch_content_to_fill_bounds=*/false, + /*ignores_input_event=*/false); + pass_list.push_back(std::move(pass2_0)); + + auto pass2_1 = viz::RenderPass::Create(); + pass2_1->output_rect = display_rect_; + pass2_1->id = 3; + auto* shared_quad_state2_1 = pass2_1->CreateAndAppendSharedQuadState(); + gfx::Rect rect2_1(display_rect_); + shared_quad_state2_1->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect2_1, + /*visible_quad_layer_rect=*/rect2_1, /*clip_rect=*/rect2_1, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad2_1 = + pass2_1->quad_list.AllocateAndConstruct<viz::SolidColorDrawQuad>(); + quad2_1->SetNew(shared_quad_state2_1, /*rect=*/rect2_1, + /*visible_rect=*/rect2_1, SK_ColorBLACK, + /*force_anti_aliasing_off=*/false); + pass_list.push_back(std::move(pass2_1)); + + auto pass2_root = viz::RenderPass::Create(); + pass2_root->output_rect = display_rect_; + pass2_root->id = 4; + auto* shared_quad_state2_root = pass2_root->CreateAndAppendSharedQuadState(); + gfx::Rect rect2_root(display_rect_); + shared_quad_state2_root->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect2_root, + /*visible_quad_layer_rect=*/rect2_root, /*clip_rect=*/rect2_root, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad2_root_1 = + pass2_root->quad_list.AllocateAndConstruct<viz::RenderPassDrawQuad>(); + quad2_root_1->SetNew(shared_quad_state2_root, /*rect=*/rect2_root, + /*visible_rect=*/rect2_root, /*render_pass_id=*/2, + /*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), + gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, + 1.0f); + auto* quad2_root_2 = + pass2_root->quad_list.AllocateAndConstruct<viz::RenderPassDrawQuad>(); + quad2_root_2->SetNew(shared_quad_state2_root, /*rect=*/rect2_root, + /*visible_rect=*/rect2_root, /*render_pass_id=*/3, + /*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), + gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, + 1.0f); + pass_list.push_back(std::move(pass2_root)); + + SendRenderPassList(&pass_list, /*hit_test_data_changed=*/true); + task_runner_->RunUntilIdle(); + + EXPECT_FALSE( + viz::HitTestRegionList::IsEqual(hit_test_region_list, GetHitTestData())); + hit_test_region_list = GetHitTestData(); + + // Identical submission with |hit_test_data_changed| set back to false. We + // expect the hit-data to still have been sent. + auto pass3 = viz::RenderPass::Create(); + pass3->id = 4; + pass3->output_rect = display_rect_; + auto* shared_quad_state3 = pass3->CreateAndAppendSharedQuadState(); + gfx::Rect rect3(display_rect_); + shared_quad_state3->SetAll( + gfx::Transform(), /*quad_layer_rect=*/rect3, + /*visible_quad_layer_rect=*/rect3, /*clip_rect=*/rect3, + /*is_clipped=*/false, /*are_contents_opaque=*/false, + /*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0); + auto* quad3 = + pass3->quad_list.AllocateAndConstruct<viz::SolidColorDrawQuad>(); + quad3->SetNew(shared_quad_state3, /*rect=*/rect3, + /*visible_rect=*/rect3, SK_ColorBLACK, + /*force_anti_aliasing_off=*/false); + pass_list.push_back(move(pass3)); + SendRenderPassList(&pass_list, /*hit_test_data_changed=*/false); + task_runner_->RunUntilIdle(); + + EXPECT_FALSE( + viz::HitTestRegionList::IsEqual(hit_test_region_list, GetHitTestData())); +} + } // namespace mojo_embedder } // namespace cc diff --git a/chromium/cc/paint/BUILD.gn b/chromium/cc/paint/BUILD.gn index 21c6b8b7b5d..74d2b6dc4c9 100644 --- a/chromium/cc/paint/BUILD.gn +++ b/chromium/cc/paint/BUILD.gn @@ -59,6 +59,8 @@ cc_component("paint") { "paint_recorder.h", "paint_shader.cc", "paint_shader.h", + "paint_worklet_input.h", + "paint_worklet_layer_painter.h", "raw_memory_transfer_cache_entry.cc", "raw_memory_transfer_cache_entry.h", "record_paint_canvas.cc", diff --git a/chromium/cc/paint/color_space_transfer_cache_entry.cc b/chromium/cc/paint/color_space_transfer_cache_entry.cc index adde3371f4e..31f27438a45 100644 --- a/chromium/cc/paint/color_space_transfer_cache_entry.cc +++ b/chromium/cc/paint/color_space_transfer_cache_entry.cc @@ -14,6 +14,7 @@ ClientColorSpaceTransferCacheEntry::ClientColorSpaceTransferCacheEntry( DCHECK(raster_color_space.color_space.IsValid()); IPC::ParamTraits<gfx::ColorSpace>::Write(&pickle_, raster_color_space.color_space); + DCHECK_LE(pickle_.size(), UINT32_MAX); } ClientColorSpaceTransferCacheEntry::~ClientColorSpaceTransferCacheEntry() = @@ -23,8 +24,8 @@ uint32_t ClientColorSpaceTransferCacheEntry::Id() const { return id_; } -size_t ClientColorSpaceTransferCacheEntry::SerializedSize() const { - return pickle_.size(); +uint32_t ClientColorSpaceTransferCacheEntry::SerializedSize() const { + return static_cast<uint32_t>(pickle_.size()); } bool ClientColorSpaceTransferCacheEntry::Serialize( diff --git a/chromium/cc/paint/color_space_transfer_cache_entry.h b/chromium/cc/paint/color_space_transfer_cache_entry.h index baeeb4ce68d..4923c73c7fc 100644 --- a/chromium/cc/paint/color_space_transfer_cache_entry.h +++ b/chromium/cc/paint/color_space_transfer_cache_entry.h @@ -29,7 +29,7 @@ class CC_PAINT_EXPORT ClientColorSpaceTransferCacheEntry final const RasterColorSpace& raster_color_space); ~ClientColorSpaceTransferCacheEntry() override; uint32_t Id() const override; - size_t SerializedSize() const override; + uint32_t SerializedSize() const override; bool Serialize(base::span<uint8_t> data) const final; private: diff --git a/chromium/cc/paint/discardable_image_map.cc b/chromium/cc/paint/discardable_image_map.cc index c9462f1595c..eeda8585f89 100644 --- a/chromium/cc/paint/discardable_image_map.cc +++ b/chromium/cc/paint/discardable_image_map.cc @@ -195,10 +195,10 @@ class DiscardableImageGenerator { PaintOpType op_type = static_cast<PaintOpType>(op->type); if (op_type == PaintOpType::DrawImage) { auto* image_op = static_cast<DrawImageOp*>(op); - auto* sk_image = image_op->image.GetSkImage().get(); - AddImage(image_op->image, - SkRect::MakeIWH(sk_image->width(), sk_image->height()), - op_rect, ctm, image_op->flags.getFilterQuality()); + AddImage( + image_op->image, + SkRect::MakeIWH(image_op->image.width(), image_op->image.height()), + op_rect, ctm, image_op->flags.getFilterQuality()); } else if (op_type == PaintOpType::DrawImageRect) { auto* image_rect_op = static_cast<DrawImageRectOp*>(op); SkMatrix matrix = ctm; @@ -355,14 +355,16 @@ class DiscardableImageGenerator { SkIRect src_irect; src_rect.roundOut(&src_irect); - // Make a note if any image was originally specified in a non-sRGB color - // space. - SkColorSpace* source_color_space = paint_image.color_space(); - color_stats_total_pixel_count_ += image_rect.size().GetCheckedArea(); - color_stats_total_image_count_++; - if (!source_color_space || source_color_space->isSRGB()) { - color_stats_srgb_pixel_count_ += image_rect.size().GetCheckedArea(); - color_stats_srgb_image_count_++; + if (!paint_image.IsPaintWorklet()) { + // Make a note if any image was originally specified in a non-sRGB color + // space. + SkColorSpace* source_color_space = paint_image.color_space(); + color_stats_total_pixel_count_ += image_rect.size().GetCheckedArea(); + color_stats_total_image_count_++; + if (!source_color_space || source_color_space->isSRGB()) { + color_stats_srgb_pixel_count_ += image_rect.size().GetCheckedArea(); + color_stats_srgb_image_count_++; + } } auto& rects = image_id_to_rects_[paint_image.stable_id()]; diff --git a/chromium/cc/paint/discardable_image_map_unittest.cc b/chromium/cc/paint/discardable_image_map_unittest.cc index 32ec754bbe1..ba6211073ed 100644 --- a/chromium/cc/paint/discardable_image_map_unittest.cc +++ b/chromium/cc/paint/discardable_image_map_unittest.cc @@ -18,6 +18,7 @@ #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_recording_source.h" #include "cc/test/skia_common.h" +#include "cc/test/test_paint_worklet_input.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkGraphics.h" @@ -881,6 +882,19 @@ TEST_F(DiscardableImageMapTest, EmbeddedShaderWithAnimatedImages) { ImageAnalysisState::kAnimatedImages); } +TEST_F(DiscardableImageMapTest, BuildPaintWorkletImage) { + gfx::SizeF size(100, 50); + scoped_refptr<TestPaintWorkletInput> input = + base::MakeRefCounted<TestPaintWorkletInput>(size); + PaintImage paint_image = PaintImageBuilder::WithDefault() + .set_id(1) + .set_paint_worklet_input(std::move(input)) + .TakePaintImage(); + EXPECT_TRUE(paint_image.paint_worklet_input()); + EXPECT_EQ(paint_image.width(), size.width()); + EXPECT_EQ(paint_image.height(), size.height()); +} + TEST_F(DiscardableImageMapTest, DecodingModeHintsBasic) { gfx::Rect visible_rect(100, 100); PaintImage unspecified_image = diff --git a/chromium/cc/paint/display_item_list.cc b/chromium/cc/paint/display_item_list.cc index cacbe80e5a5..ea5a9768185 100644 --- a/chromium/cc/paint/display_item_list.cc +++ b/chromium/cc/paint/display_item_list.cc @@ -44,8 +44,10 @@ DisplayItemList::DisplayItemList(UsageHint usage_hint) DisplayItemList::~DisplayItemList() = default; -void DisplayItemList::Raster(SkCanvas* canvas, - ImageProvider* image_provider) const { +void DisplayItemList::Raster( + SkCanvas* canvas, + ImageProvider* image_provider, + PaintWorkletImageProvider* paint_worklet_image_provider) const { DCHECK(usage_hint_ == kTopLevelDisplayItemList); gfx::Rect canvas_playback_rect; if (!GetCanvasClipBounds(canvas, &canvas_playback_rect)) @@ -53,7 +55,9 @@ void DisplayItemList::Raster(SkCanvas* canvas, std::vector<size_t> offsets; rtree_.Search(canvas_playback_rect, &offsets); - paint_op_buffer_.Playback(canvas, PlaybackParams(image_provider), &offsets); + paint_op_buffer_.Playback( + canvas, PlaybackParams(image_provider, paint_worklet_image_provider), + &offsets); } void DisplayItemList::Finalize() { diff --git a/chromium/cc/paint/display_item_list.h b/chromium/cc/paint/display_item_list.h index feb8e5407b7..deda06057ca 100644 --- a/chromium/cc/paint/display_item_list.h +++ b/chromium/cc/paint/display_item_list.h @@ -41,6 +41,7 @@ class TracedValue; } namespace cc { +class PaintWorkletImageProvider; // DisplayItemList is a container of paint operations. One can populate the list // using StartPaint, followed by push{,_with_data,_with_array} functions @@ -59,7 +60,9 @@ class CC_PAINT_EXPORT DisplayItemList explicit DisplayItemList(UsageHint = kTopLevelDisplayItemList); - void Raster(SkCanvas* canvas, ImageProvider* image_provider = nullptr) const; + void Raster(SkCanvas* canvas, + ImageProvider* image_provider = nullptr, + PaintWorkletImageProvider* = nullptr) const; void StartPaint() { #if DCHECK_IS_ON() diff --git a/chromium/cc/paint/filter_operation.cc b/chromium/cc/paint/filter_operation.cc index 3357afb235c..267381b2bef 100644 --- a/chromium/cc/paint/filter_operation.cc +++ b/chromium/cc/paint/filter_operation.cc @@ -9,6 +9,7 @@ #include "cc/paint/filter_operation.h" #include "base/numerics/ranges.h" +#include "base/stl_util.h" #include "base/trace_event/traced_value.h" #include "base/values.h" #include "cc/base/math_util.h" @@ -300,7 +301,7 @@ void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const { break; case FilterOperation::COLOR_MATRIX: { value->BeginArray("matrix"); - for (size_t i = 0; i < arraysize(matrix_); ++i) + for (size_t i = 0; i < base::size(matrix_); ++i) value->AppendDouble(matrix_[i]); value->EndArray(); break; @@ -349,10 +350,17 @@ gfx::Rect MapRectInternal(const FilterOperation& op, switch (op.type()) { case FilterOperation::BLUR: { SkVector spread = MapStdDeviation(op.amount(), matrix); - float spread_x = std::abs(spread.x()); - float spread_y = std::abs(spread.y()); + // Mapping a blur forward requires an outset (negative inset) because a + // smaller source rectangle gets blurred to a larger destination + // rectangle. + // TODO(916583): Fix this function for reverse mapping: + // float sign = (direction == SkImageFilter::kForward_MapDirection) ? -1.0 + // : 1.0; + float sign = -1.0; + float spread_x = std::abs(spread.x()) * sign; + float spread_y = std::abs(spread.y()) * sign; gfx::RectF result(rect); - result.Inset(-spread_x, -spread_y, -spread_x, -spread_y); + result.Inset(spread_x, spread_y, spread_x, spread_y); return gfx::ToEnclosingRect(result); } case FilterOperation::DROP_SHADOW: { diff --git a/chromium/cc/paint/image_transfer_cache_entry.cc b/chromium/cc/paint/image_transfer_cache_entry.cc index dedc9add23c..3a9b9781385 100644 --- a/chromium/cc/paint/image_transfer_cache_entry.cc +++ b/chromium/cc/paint/image_transfer_cache_entry.cc @@ -69,7 +69,7 @@ ClientImageTransferCacheEntry::ClientImageTransferCacheEntry( : 0u; // Compute and cache the size of the data. - base::CheckedNumeric<size_t> safe_size; + base::CheckedNumeric<uint32_t> safe_size; safe_size += PaintOpWriter::HeaderBytes(); safe_size += sizeof(uint32_t); // color type safe_size += sizeof(uint32_t); // width @@ -90,7 +90,7 @@ ClientImageTransferCacheEntry::~ClientImageTransferCacheEntry() = default; // static base::AtomicSequenceNumber ClientImageTransferCacheEntry::s_next_id_; -size_t ClientImageTransferCacheEntry::SerializedSize() const { +uint32_t ClientImageTransferCacheEntry::SerializedSize() const { return size_; } @@ -144,7 +144,9 @@ bool ServiceImageTransferCacheEntry::Deserialize( // We don't need to populate the DeSerializeOptions here since the reader is // only used for de-serializing primitives. - PaintOp::DeserializeOptions options(nullptr, nullptr, nullptr); + std::vector<uint8_t> scratch_buffer; + PaintOp::DeserializeOptions options(nullptr, nullptr, nullptr, + &scratch_buffer); PaintOpReader reader(data.data(), data.size(), options); SkColorType color_type; reader.Read(&color_type); diff --git a/chromium/cc/paint/image_transfer_cache_entry.h b/chromium/cc/paint/image_transfer_cache_entry.h index db31ade3796..7b563c44e63 100644 --- a/chromium/cc/paint/image_transfer_cache_entry.h +++ b/chromium/cc/paint/image_transfer_cache_entry.h @@ -31,7 +31,7 @@ class CC_PAINT_EXPORT ClientImageTransferCacheEntry uint32_t Id() const final; // ClientTransferCacheEntry implementation: - size_t SerializedSize() const final; + uint32_t SerializedSize() const final; bool Serialize(base::span<uint8_t> data) const final; private: @@ -39,7 +39,7 @@ class CC_PAINT_EXPORT ClientImageTransferCacheEntry const SkPixmap* const pixmap_; const SkColorSpace* const target_color_space_; const bool needs_mips_; - size_t size_ = 0; + uint32_t size_ = 0; static base::AtomicSequenceNumber s_next_id_; }; diff --git a/chromium/cc/paint/oop_pixeltest.cc b/chromium/cc/paint/oop_pixeltest.cc index f86a674a381..11b5f62250d 100644 --- a/chromium/cc/paint/oop_pixeltest.cc +++ b/chromium/cc/paint/oop_pixeltest.cc @@ -130,7 +130,6 @@ class OopPixelTest : public testing::Test, SkColor background_color = SK_ColorBLACK; int msaa_sample_count = 0; bool use_lcd_text = false; - SkColorType color_type = kRGBA_8888_SkColorType; gfx::Size resource_size; gfx::Size content_size; gfx::Rect full_raster_rect; @@ -184,7 +183,7 @@ class OopPixelTest : public testing::Test, if (options.preclear) { raster_implementation->BeginRasterCHROMIUM( options.preclear_color, options.msaa_sample_count, - options.use_lcd_text, options.color_type, color_space, mailbox.name); + options.use_lcd_text, color_space, mailbox.name); raster_implementation->EndRasterCHROMIUM(); } @@ -192,7 +191,7 @@ class OopPixelTest : public testing::Test, raster_implementation->BeginRasterCHROMIUM( options.background_color, options.msaa_sample_count, - options.use_lcd_text, options.color_type, color_space, mailbox.name); + options.use_lcd_text, color_space, mailbox.name); raster_implementation->RasterCHROMIUM( display_item_list.get(), &image_provider, options.content_size, options.full_raster_rect, options.playback_rect, options.post_translate, @@ -1616,8 +1615,8 @@ class OopPathPixelTest : public OopPixelTest, void RunTest() { auto* ri = static_cast<gpu::raster::RasterImplementation*>( raster_context_provider_->RasterInterface()); - size_t max_inlined_entry_size = - AllowInlining() ? std::numeric_limits<size_t>::max() : 0u; + uint32_t max_inlined_entry_size = + AllowInlining() ? std::numeric_limits<uint32_t>::max() : 0u; ri->set_max_inlined_entry_size_for_testing(max_inlined_entry_size); RasterOptions options; diff --git a/chromium/cc/paint/paint_cache.cc b/chromium/cc/paint/paint_cache.cc index b3fad275dba..dc73c6e300e 100644 --- a/chromium/cc/paint/paint_cache.cc +++ b/chromium/cc/paint/paint_cache.cc @@ -52,7 +52,7 @@ void ClientPaintCache::FinalizePendingEntries() { } void ClientPaintCache::AbortPendingEntries() { - for (const auto& entry : pending_entries_.container()) { + for (const auto& entry : pending_entries_) { auto it = cache_map_.Peek(entry); DCHECK(it != cache_map_.end()); EraseFromMap(it); diff --git a/chromium/cc/paint/paint_canvas.h b/chromium/cc/paint/paint_canvas.h index 80a6915472d..df30609c606 100644 --- a/chromium/cc/paint/paint_canvas.h +++ b/chromium/cc/paint/paint_canvas.h @@ -55,9 +55,7 @@ class CC_PAINT_EXPORT PaintCanvas { virtual int save() = 0; virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0; - virtual int saveLayerAlpha(const SkRect* bounds, - uint8_t alpha, - bool preserve_lcd_text_requests) = 0; + virtual int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) = 0; virtual void restore() = 0; virtual int getSaveCount() const = 0; diff --git a/chromium/cc/paint/paint_flags.cc b/chromium/cc/paint/paint_flags.cc index c0ff3a6aa47..dcdb3c3a7f8 100644 --- a/chromium/cc/paint/paint_flags.cc +++ b/chromium/cc/paint/paint_flags.cc @@ -24,8 +24,6 @@ PaintFlags::PaintFlags() { bitfields_.cap_type_ = SkPaint::kDefault_Cap; bitfields_.join_type_ = SkPaint::kDefault_Join; bitfields_.style_ = SkPaint::kFill_Style; - bitfields_.text_encoding_ = SkPaint::kUTF8_TextEncoding; - bitfields_.hinting_ = static_cast<unsigned>(SkFontHinting::kNormal); bitfields_.filter_quality_ = SkFilterQuality::kNone_SkFilterQuality; static_assert(sizeof(bitfields_) <= sizeof(bitfields_uint_), @@ -43,7 +41,6 @@ PaintFlags::~PaintFlags() { blend_mode_ = static_cast<uint32_t>(SkBlendMode::kLastMode); // Free refcounted objects one by one. - typeface_.reset(); path_effect_.reset(); shader_.reset(); mask_filter_.reset(); @@ -127,7 +124,6 @@ bool PaintFlags::SupportsFoldingAlpha() const { SkPaint PaintFlags::ToSkPaint() const { SkPaint paint; - paint.setTypeface(typeface_); paint.setPathEffect(path_effect_); if (shader_) paint.setShader(shader_->GetSkShader()); @@ -136,40 +132,19 @@ SkPaint PaintFlags::ToSkPaint() const { paint.setDrawLooper(draw_looper_); if (image_filter_) paint.setImageFilter(image_filter_->cached_sk_filter_); - paint.setTextSize(text_size_); paint.setColor(color_); paint.setStrokeWidth(width_); paint.setStrokeMiter(miter_limit_); paint.setBlendMode(getBlendMode()); - paint.setFlags(bitfields_.flags_); + paint.setAntiAlias(bitfields_.antialias_); + paint.setDither(bitfields_.dither_); paint.setStrokeCap(static_cast<SkPaint::Cap>(getStrokeCap())); paint.setStrokeJoin(static_cast<SkPaint::Join>(getStrokeJoin())); paint.setStyle(static_cast<SkPaint::Style>(getStyle())); - paint.setTextEncoding(static_cast<SkPaint::TextEncoding>(getTextEncoding())); - paint.setHinting(static_cast<SkFontHinting>(getHinting())); paint.setFilterQuality(getFilterQuality()); return paint; } -SkFont PaintFlags::ToSkFont() const { - SkFont font; - font.setTypeface(typeface_); - font.setSize(text_size_); - font.setHinting(static_cast<SkFontHinting>(getHinting())); - font.setForceAutoHinting(isAutohinted()); - font.setSubpixel(isSubpixelText()); - if (isAntiAlias()) { - if (isLCDRenderText()) { - font.setEdging(SkFont::Edging::kSubpixelAntiAlias); - } else { - font.setEdging(SkFont::Edging::kAntiAlias); - } - } else { - font.setEdging(SkFont::Edging::kAlias); - } - return font; -} - bool PaintFlags::IsValid() const { return PaintOp::IsValidPaintFlagsSkBlendMode(getBlendMode()); } @@ -178,8 +153,6 @@ bool PaintFlags::operator==(const PaintFlags& other) const { // Can't just ToSkPaint and operator== here as SkPaint does pointer // comparisons on all the ref'd skia objects on the SkPaint, which // is not true after serialization. - if (!PaintOp::AreEqualEvenIfNaN(getTextSize(), other.getTextSize())) - return false; if (getColor() != other.getColor()) return false; if (!PaintOp::AreEqualEvenIfNaN(getStrokeWidth(), other.getStrokeWidth())) @@ -194,14 +167,9 @@ bool PaintFlags::operator==(const PaintFlags& other) const { return false; if (getStyle() != other.getStyle()) return false; - if (getTextEncoding() != other.getTextEncoding()) - return false; - if (getHinting() != other.getHinting()) - return false; if (getFilterQuality() != other.getFilterQuality()) return false; - // TODO(enne): compare typeface too if (!PaintOp::AreSkFlattenablesEqual(getPathEffect().get(), other.getPathEffect().get())) { return false; @@ -237,8 +205,8 @@ bool PaintFlags::HasDiscardableImages() const { } size_t PaintFlags::GetSerializedSize() const { - return sizeof(text_size_) + sizeof(color_) + sizeof(width_) + - sizeof(miter_limit_) + sizeof(blend_mode_) + sizeof(bitfields_uint_) + + return sizeof(color_) + sizeof(width_) + sizeof(miter_limit_) + + sizeof(blend_mode_) + sizeof(bitfields_uint_) + PaintOpWriter::GetFlattenableSize(path_effect_.get()) + PaintOpWriter::Alignment() + PaintOpWriter::GetFlattenableSize(mask_filter_.get()) + diff --git a/chromium/cc/paint/paint_flags.h b/chromium/cc/paint/paint_flags.h index fda9cc5ba8d..64acb7861b4 100644 --- a/chromium/cc/paint/paint_flags.h +++ b/chromium/cc/paint/paint_flags.h @@ -11,14 +11,11 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkDrawLooper.h" -#include "third_party/skia/include/core/SkFont.h" -#include "third_party/skia/include/core/SkFontTypes.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPathEffect.h" #include "third_party/skia/include/core/SkShader.h" -#include "third_party/skia/include/core/SkTypeface.h" namespace cc { class PaintFilter; @@ -56,63 +53,10 @@ class CC_PAINT_EXPORT PaintFlags { ALWAYS_INLINE SkBlendMode getBlendMode() const { return static_cast<SkBlendMode>(blend_mode_); } - ALWAYS_INLINE bool isAntiAlias() const { - return !!(bitfields_.flags_ & SkPaint::kAntiAlias_Flag); - } - ALWAYS_INLINE void setAntiAlias(bool aa) { - SetInternalFlag(aa, SkPaint::kAntiAlias_Flag); - } - ALWAYS_INLINE bool isSubpixelText() const { - return !!(bitfields_.flags_ & SkPaint::kSubpixelText_Flag); - } - ALWAYS_INLINE void setSubpixelText(bool subpixel_text) { - SetInternalFlag(subpixel_text, SkPaint::kSubpixelText_Flag); - } - ALWAYS_INLINE bool isLCDRenderText() const { - return !!(bitfields_.flags_ & SkPaint::kLCDRenderText_Flag); - } - ALWAYS_INLINE void setLCDRenderText(bool lcd_text) { - SetInternalFlag(lcd_text, SkPaint::kLCDRenderText_Flag); - } - enum Hinting { - kNo_Hinting = static_cast<unsigned>(SkFontHinting::kNone), - kSlight_Hinting = static_cast<unsigned>(SkFontHinting::kSlight), - kNormal_Hinting = - static_cast<unsigned>(SkFontHinting::kNormal), //!< this is the default - kFull_Hinting = static_cast<unsigned>(SkFontHinting::kFull) - }; - ALWAYS_INLINE Hinting getHinting() const { - return static_cast<Hinting>(bitfields_.hinting_); - } - ALWAYS_INLINE void setHinting(Hinting hinting) { - bitfields_.hinting_ = hinting; - } - ALWAYS_INLINE bool isAutohinted() const { - return !!(bitfields_.flags_ & SkPaint::kAutoHinting_Flag); - } - ALWAYS_INLINE void setAutohinted(bool use_auto_hinter) { - SetInternalFlag(use_auto_hinter, SkPaint::kAutoHinting_Flag); - } - ALWAYS_INLINE bool isDither() const { - return !!(bitfields_.flags_ & SkPaint::kDither_Flag); - } - ALWAYS_INLINE void setDither(bool dither) { - SetInternalFlag(dither, SkPaint::kDither_Flag); - } - enum TextEncoding { - kUTF8_TextEncoding = SkPaint::kUTF8_TextEncoding, - kUTF16_TextEncoding = SkPaint::kUTF16_TextEncoding, - kUTF32_TextEncoding = SkPaint::kUTF32_TextEncoding, - kGlyphID_TextEncoding = SkPaint::kGlyphID_TextEncoding - }; - ALWAYS_INLINE TextEncoding getTextEncoding() const { - return static_cast<TextEncoding>(bitfields_.text_encoding_); - } - ALWAYS_INLINE void setTextEncoding(TextEncoding encoding) { - bitfields_.text_encoding_ = encoding; - } - ALWAYS_INLINE SkScalar getTextSize() const { return text_size_; } - ALWAYS_INLINE void setTextSize(SkScalar text_size) { text_size_ = text_size; } + ALWAYS_INLINE bool isAntiAlias() const { return bitfields_.antialias_; } + ALWAYS_INLINE void setAntiAlias(bool aa) { bitfields_.antialias_ = aa; } + ALWAYS_INLINE bool isDither() const { return bitfields_.dither_; } + ALWAYS_INLINE void setDither(bool dither) { bitfields_.dither_ = dither; } ALWAYS_INLINE void setFilterQuality(SkFilterQuality quality) { bitfields_.filter_quality_ = quality; } @@ -148,12 +92,6 @@ class CC_PAINT_EXPORT PaintFlags { } ALWAYS_INLINE void setStrokeJoin(Join join) { bitfields_.join_type_ = join; } - ALWAYS_INLINE const sk_sp<SkTypeface>& getTypeface() const { - return typeface_; - } - ALWAYS_INLINE void setTypeface(sk_sp<SkTypeface> typeface) { - typeface_ = std::move(typeface); - } ALWAYS_INLINE const sk_sp<SkColorFilter>& getColorFilter() const { return color_filter_; } @@ -209,7 +147,6 @@ class CC_PAINT_EXPORT PaintFlags { bool SupportsFoldingAlpha() const; SkPaint ToSkPaint() const; - SkFont ToSkFont() const; bool IsValid() const; bool operator==(const PaintFlags& other) const; @@ -223,14 +160,6 @@ class CC_PAINT_EXPORT PaintFlags { friend class PaintOpReader; friend class PaintOpWriter; - ALWAYS_INLINE void SetInternalFlag(bool value, uint32_t mask) { - if (value) - bitfields_.flags_ |= mask; - else - bitfields_.flags_ &= ~mask; - } - - sk_sp<SkTypeface> typeface_; sk_sp<SkPathEffect> path_effect_; sk_sp<PaintShader> shader_; sk_sp<SkMaskFilter> mask_filter_; @@ -240,19 +169,17 @@ class CC_PAINT_EXPORT PaintFlags { // Match(ish) SkPaint defaults. SkPaintDefaults is not public, so this // just uses these values and ignores any SkUserConfig overrides. - float text_size_ = 12.f; SkColor color_ = SK_ColorBLACK; float width_ = 0.f; float miter_limit_ = 4.f; uint32_t blend_mode_ = static_cast<uint32_t>(SkBlendMode::kSrcOver); struct PaintFlagsBitfields { - uint32_t flags_ : 16; + uint32_t antialias_ : 1; + uint32_t dither_ : 1; uint32_t cap_type_ : 2; uint32_t join_type_ : 2; uint32_t style_ : 2; - uint32_t text_encoding_ : 2; - uint32_t hinting_ : 2; uint32_t filter_quality_ : 2; }; diff --git a/chromium/cc/paint/paint_image.h b/chromium/cc/paint/paint_image.h index 0684c2d80c6..c71fe7217a4 100644 --- a/chromium/cc/paint/paint_image.h +++ b/chromium/cc/paint/paint_image.h @@ -9,9 +9,11 @@ #include "base/gtest_prod_util.h" #include "base/logging.h" +#include "base/memory/scoped_refptr.h" #include "cc/paint/frame_metadata.h" #include "cc/paint/image_animation_count.h" #include "cc/paint/paint_export.h" +#include "cc/paint/paint_worklet_input.h" #include "third_party/skia/include/core/SkImage.h" #include "ui/gfx/geometry/rect.h" @@ -76,7 +78,7 @@ class CC_PAINT_EXPORT PaintImage { bool operator==(const FrameKey& other) const; bool operator!=(const FrameKey& other) const; - uint64_t hash() const { return hash_; } + size_t hash() const { return hash_; } std::string ToString() const; size_t frame_index() const { return frame_index_; } ContentId content_id() const { return content_id_; } @@ -173,13 +175,32 @@ class CC_PAINT_EXPORT PaintImage { PaintImage::ContentId content_id() const { return content_id_; } // TODO(vmpstr): Don't get the SkImage here if you don't need to. - uint32_t unique_id() const { return GetSkImage()->uniqueID(); } - explicit operator bool() const { return !!GetSkImage(); } - bool IsLazyGenerated() const { return GetSkImage()->isLazyGenerated(); } - bool IsTextureBacked() const { return GetSkImage()->isTextureBacked(); } - int width() const { return GetSkImage()->width(); } - int height() const { return GetSkImage()->height(); } - SkColorSpace* color_space() const { return GetSkImage()->colorSpace(); } + uint32_t unique_id() const { + return paint_worklet_input_ ? 0 : GetSkImage()->uniqueID(); + } + explicit operator bool() const { + return paint_worklet_input_ || !!GetSkImage(); + } + bool IsLazyGenerated() const { + return paint_worklet_input_ ? false : GetSkImage()->isLazyGenerated(); + } + bool IsPaintWorklet() const { return !!paint_worklet_input_; } + bool IsTextureBacked() const { + return paint_worklet_input_ ? false : GetSkImage()->isTextureBacked(); + } + int width() const { + return paint_worklet_input_ + ? static_cast<int>(paint_worklet_input_->GetSize().width()) + : GetSkImage()->width(); + } + int height() const { + return paint_worklet_input_ + ? static_cast<int>(paint_worklet_input_->GetSize().height()) + : GetSkImage()->height(); + } + SkColorSpace* color_space() const { + return paint_worklet_input_ ? nullptr : GetSkImage()->colorSpace(); + } // Returns the color type of this image. SkColorType GetColorType() const; @@ -198,6 +219,10 @@ class CC_PAINT_EXPORT PaintImage { sk_sp<SkImage> GetSkImageForFrame(size_t index, GeneratorClientId client_id) const; + PaintWorkletInput* paint_worklet_input() const { + return paint_worklet_input_.get(); + } + std::string ToString() const; private: @@ -260,6 +285,9 @@ class CC_PAINT_EXPORT PaintImage { // skia's cache. // 2) Ensures that accesses to it are thread-safe. sk_sp<SkImage> cached_sk_image_; + + // The input parameters that are needed to execute the JS paint callback. + scoped_refptr<PaintWorkletInput> paint_worklet_input_; }; } // namespace cc diff --git a/chromium/cc/paint/paint_image_builder.cc b/chromium/cc/paint/paint_image_builder.cc index d6741c1cf99..d8b3199f935 100644 --- a/chromium/cc/paint/paint_image_builder.cc +++ b/chromium/cc/paint/paint_image_builder.cc @@ -45,6 +45,7 @@ PaintImage PaintImageBuilder::TakePaintImage() { DCHECK(!paint_image_.paint_record_); DCHECK(!paint_image_.paint_image_generator_); DCHECK(!paint_image_.sk_image_->isLazyGenerated()); + DCHECK(!paint_image_.paint_worklet_input_); // TODO(khushalsagar): Assert that we don't have an animated image type // here. The only case where this is possible is DragImage. There are 2 use // cases going through that path, re-orienting the image and for use by the @@ -55,11 +56,17 @@ PaintImage PaintImageBuilder::TakePaintImage() { } else if (paint_image_.paint_record_) { DCHECK(!paint_image_.sk_image_); DCHECK(!paint_image_.paint_image_generator_); + DCHECK(!paint_image_.paint_worklet_input_); // TODO(khushalsagar): Assert that we don't have an animated image type // here. } else if (paint_image_.paint_image_generator_) { DCHECK(!paint_image_.sk_image_); DCHECK(!paint_image_.paint_record_); + DCHECK(!paint_image_.paint_worklet_input_); + } else if (paint_image_.paint_worklet_input_) { + DCHECK(!paint_image_.sk_image_); + DCHECK(!paint_image_.paint_record_); + DCHECK(!paint_image_.paint_image_generator_); } if (paint_image_.ShouldAnimate()) { diff --git a/chromium/cc/paint/paint_image_builder.h b/chromium/cc/paint/paint_image_builder.h index d12705003c1..52e7ec8b181 100644 --- a/chromium/cc/paint/paint_image_builder.h +++ b/chromium/cc/paint/paint_image_builder.h @@ -98,6 +98,11 @@ class CC_PAINT_EXPORT PaintImageBuilder { paint_image_.decoding_mode_ = decoding_mode; return std::move(*this); } + PaintImageBuilder&& set_paint_worklet_input( + scoped_refptr<PaintWorkletInput> input) { + paint_image_.paint_worklet_input_ = std::move(input); + return std::move(*this); + } PaintImage TakePaintImage(); diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc index 7ae8135f509..4516fec0c83 100644 --- a/chromium/cc/paint/paint_op_buffer.cc +++ b/chromium/cc/paint/paint_op_buffer.cc @@ -302,8 +302,11 @@ size_t SimpleSerialize(const PaintOp* op, void* memory, size_t size) { return sizeof(T); } -PlaybackParams::PlaybackParams(ImageProvider* image_provider) +PlaybackParams::PlaybackParams( + ImageProvider* image_provider, + PaintWorkletImageProvider* paint_worklet_image_provider) : image_provider(image_provider), + paint_worklet_image_provider(paint_worklet_image_provider), original_ctm(SkMatrix::I()), custom_callback(CustomDataRasterCallback()), did_draw_op_callback(DidDrawOpCallback()) {} @@ -355,10 +358,14 @@ PaintOp::SerializeOptions& PaintOp::SerializeOptions::operator=( PaintOp::DeserializeOptions::DeserializeOptions( TransferCacheDeserializeHelper* transfer_cache, ServicePaintCache* paint_cache, - SkStrikeClient* strike_client) + SkStrikeClient* strike_client, + std::vector<uint8_t>* scratch_buffer) : transfer_cache(transfer_cache), paint_cache(paint_cache), - strike_client(strike_client) {} + strike_client(strike_client), + scratch_buffer(scratch_buffer) { + DCHECK(scratch_buffer); +} size_t AnnotateOp::Serialize(const PaintOp* base_op, void* memory, @@ -1393,14 +1400,7 @@ void SaveLayerAlphaOp::Raster(const SaveLayerAlphaOp* op, const PlaybackParams& params) { // See PaintOp::kUnsetRect bool unset = op->bounds.left() == SK_ScalarInfinity; - if (op->preserve_lcd_text_requests) { - SkPaint paint; - paint.setAlpha(op->alpha); - canvas->saveLayerPreserveLCDTextRequests(unset ? nullptr : &op->bounds, - &paint); - } else { - canvas->saveLayerAlpha(unset ? nullptr : &op->bounds, op->alpha); - } + canvas->saveLayerAlpha(unset ? nullptr : &op->bounds, op->alpha); } void ScaleOp::Raster(const ScaleOp* op, @@ -1814,8 +1814,6 @@ bool SaveLayerAlphaOp::AreEqual(const PaintOp* base_left, return false; if (left->alpha != right->alpha) return false; - if (left->preserve_lcd_text_requests != right->preserve_lcd_text_requests) - return false; return true; } @@ -2387,6 +2385,8 @@ void PaintOpBuffer::Playback(SkCanvas* canvas, PlaybackParams new_params(params.image_provider, canvas->getTotalMatrix(), params.custom_callback, params.did_draw_op_callback); + // TODO(xidachen): retrieve the PaintRecord stored in PaintWorkletImageCache, + // from the PaintWorkletImageProvider in the params. for (PlaybackFoldingIterator iter(this, offsets); iter; ++iter) { const PaintOp* op = *iter; diff --git a/chromium/cc/paint/paint_op_buffer.h b/chromium/cc/paint/paint_op_buffer.h index a4a3ae89f72..028a476ce87 100644 --- a/chromium/cc/paint/paint_op_buffer.h +++ b/chromium/cc/paint/paint_op_buffer.h @@ -18,7 +18,6 @@ #include "base/memory/aligned_memory.h" #include "base/optional.h" #include "cc/base/math_util.h" -#include "cc/paint/image_provider.h" #include "cc/paint/paint_canvas.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_flags.h" @@ -40,7 +39,9 @@ class SkStrikeServer; // See: third_party/skia/src/core/SkLiteDL.h. namespace cc { class ClientPaintCache; +class ImageProvider; class ServicePaintCache; +class PaintWorkletImageProvider; class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix { public: @@ -107,7 +108,9 @@ struct CC_PAINT_EXPORT PlaybackParams { base::RepeatingCallback<void(SkCanvas* canvas, uint32_t id)>; using DidDrawOpCallback = base::RepeatingCallback<void()>; - explicit PlaybackParams(ImageProvider* image_provider); + explicit PlaybackParams( + ImageProvider* image_provider, + PaintWorkletImageProvider* paint_worklet_image_provider = nullptr); PlaybackParams( ImageProvider* image_provider, const SkMatrix& original_ctm, @@ -119,6 +122,7 @@ struct CC_PAINT_EXPORT PlaybackParams { PlaybackParams& operator=(const PlaybackParams& other); ImageProvider* image_provider; + PaintWorkletImageProvider* paint_worklet_image_provider; SkMatrix original_ctm; CustomDataRasterCallback custom_callback; DidDrawOpCallback did_draw_op_callback; @@ -181,13 +185,16 @@ class CC_PAINT_EXPORT PaintOp { struct CC_PAINT_EXPORT DeserializeOptions { DeserializeOptions(TransferCacheDeserializeHelper* transfer_cache, ServicePaintCache* paint_cache, - SkStrikeClient* strike_client); + SkStrikeClient* strike_client, + std::vector<uint8_t>* scratch_buffer); TransferCacheDeserializeHelper* transfer_cache = nullptr; ServicePaintCache* paint_cache = nullptr; SkStrikeClient* strike_client = nullptr; uint32_t raster_color_space_id = gfx::ColorSpace::kInvalidId; // Do a DumpWithoutCrashing when serialization fails. bool crash_dump_on_failure = false; + // Used to memcpy Skia flattenables into to avoid TOCTOU issues. + std::vector<uint8_t>* scratch_buffer = nullptr; }; // Indicates how PaintImages are serialized. @@ -270,9 +277,7 @@ class CC_PAINT_EXPORT PaintOp { static_cast<uint32_t>(SkClipOp::kMax_EnumValue); } - static bool IsValidPath(const SkPath& path) { - return path.isValid() && path.pathRefIsValid(); - } + static bool IsValidPath(const SkPath& path) { return path.isValid(); } static bool IsUnsetRect(const SkRect& rect) { return rect.fLeft == SK_ScalarInfinity; @@ -827,13 +832,8 @@ class CC_PAINT_EXPORT SaveLayerOp final : public PaintOpWithFlags { class CC_PAINT_EXPORT SaveLayerAlphaOp final : public PaintOp { public: static constexpr PaintOpType kType = PaintOpType::SaveLayerAlpha; - SaveLayerAlphaOp(const SkRect* bounds, - uint8_t alpha, - bool preserve_lcd_text_requests) - : PaintOp(kType), - bounds(bounds ? *bounds : kUnsetRect), - alpha(alpha), - preserve_lcd_text_requests(preserve_lcd_text_requests) {} + SaveLayerAlphaOp(const SkRect* bounds, uint8_t alpha) + : PaintOp(kType), bounds(bounds ? *bounds : kUnsetRect), alpha(alpha) {} static void Raster(const SaveLayerAlphaOp* op, SkCanvas* canvas, const PlaybackParams& params); @@ -843,7 +843,6 @@ class CC_PAINT_EXPORT SaveLayerAlphaOp final : public PaintOp { SkRect bounds; uint8_t alpha; - bool preserve_lcd_text_requests; }; class CC_PAINT_EXPORT ScaleOp final : public PaintOp { diff --git a/chromium/cc/paint/paint_op_buffer_fuzzer.cc b/chromium/cc/paint/paint_op_buffer_fuzzer.cc index c91d62fbfa8..d7fcd2edcb7 100644 --- a/chromium/cc/paint/paint_op_buffer_fuzzer.cc +++ b/chromium/cc/paint/paint_op_buffer_fuzzer.cc @@ -68,8 +68,9 @@ void Raster(scoped_refptr<viz::TestContextProvider> context_provider, cc::PlaybackParams params(nullptr, canvas->getTotalMatrix()); cc::TransferCacheTestHelper transfer_cache_helper; + std::vector<uint8_t> scratch_buffer; cc::PaintOp::DeserializeOptions deserialize_options( - &transfer_cache_helper, paint_cache, strike_client); + &transfer_cache_helper, paint_cache, strike_client, &scratch_buffer); // Need 4 bytes to be able to read the type/skip. while (size >= 4) { @@ -111,7 +112,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::CommandLine::Init(0, nullptr); // Partition the data to use some bytes for populating the font cache. - size_t bytes_for_fonts = data[0]; + uint32_t bytes_for_fonts = data[0]; if (bytes_for_fonts > size) bytes_for_fonts = size / 2; diff --git a/chromium/cc/paint/paint_op_buffer_serializer.cc b/chromium/cc/paint/paint_op_buffer_serializer.cc index 5802b3c369d..f7f7f4f9d06 100644 --- a/chromium/cc/paint/paint_op_buffer_serializer.cc +++ b/chromium/cc/paint/paint_op_buffer_serializer.cc @@ -405,8 +405,8 @@ SimpleBufferSerializer::SimpleBufferSerializer( int max_texture_size, size_t max_texture_bytes) : PaintOpBufferSerializer( - base::Bind(&SimpleBufferSerializer::SerializeToMemory, - base::Unretained(this)), + base::BindRepeating(&SimpleBufferSerializer::SerializeToMemory, + base::Unretained(this)), image_provider, transfer_cache, paint_cache, diff --git a/chromium/cc/paint/paint_op_buffer_serializer.h b/chromium/cc/paint/paint_op_buffer_serializer.h index 4dfd6c13c97..341767468a7 100644 --- a/chromium/cc/paint/paint_op_buffer_serializer.h +++ b/chromium/cc/paint/paint_op_buffer_serializer.h @@ -17,7 +17,8 @@ class TransferCacheSerializeHelper; class CC_PAINT_EXPORT PaintOpBufferSerializer { public: using SerializeCallback = - base::Callback<size_t(const PaintOp*, const PaintOp::SerializeOptions&)>; + base::RepeatingCallback<size_t(const PaintOp*, + const PaintOp::SerializeOptions&)>; PaintOpBufferSerializer(SerializeCallback serialize_cb, ImageProvider* image_provider, diff --git a/chromium/cc/paint/paint_op_buffer_unittest.cc b/chromium/cc/paint/paint_op_buffer_unittest.cc index 8e007c409db..4df17de7e1c 100644 --- a/chromium/cc/paint/paint_op_buffer_unittest.cc +++ b/chromium/cc/paint/paint_op_buffer_unittest.cc @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "cc/paint/paint_op_buffer.h" + +#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "cc/paint/decoded_draw_image.h" #include "cc/paint/display_item_list.h" @@ -213,7 +215,7 @@ TEST(PaintOpBufferTest, SaveDrawRestore) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); PaintFlags draw_flags; draw_flags.setColor(SK_ColorMAGENTA); @@ -243,7 +245,7 @@ TEST(PaintOpBufferTest, SaveDrawRestoreFail_BadFlags) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); PaintFlags draw_flags; draw_flags.setColor(SK_ColorMAGENTA); @@ -270,7 +272,7 @@ TEST(PaintOpBufferTest, SaveDrawRestore_BadFlags255Alpha) { PaintOpBuffer buffer; uint8_t alpha = 255; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); PaintFlags draw_flags; draw_flags.setColor(SK_ColorMAGENTA); @@ -295,7 +297,7 @@ TEST(PaintOpBufferTest, SaveDrawRestoreFail_TooManyOps) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); PaintFlags draw_flags; draw_flags.setColor(SK_ColorMAGENTA); @@ -322,7 +324,7 @@ TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpNotADrawOp) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); buffer.push<NoopOp>(); buffer.push<RestoreOp>(); @@ -350,7 +352,7 @@ TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleOp) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); buffer.push<DrawRecordOp>(std::move(record)); buffer.push<RestoreOp>(); @@ -378,7 +380,7 @@ TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleNonDrawOp) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); buffer.push<DrawRecordOp>(std::move(record)); buffer.push<RestoreOp>(); @@ -394,7 +396,7 @@ TEST(PaintOpBufferTest, SaveLayerRestore_DrawColor) { uint8_t alpha = 100; SkColor original = SkColorSetA(50, SK_ColorRED); - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); buffer.push<DrawColorOp>(original, SkBlendMode::kSrcOver); buffer.push<RestoreOp>(); @@ -731,7 +733,7 @@ TEST_F(PaintOpBufferOffsetsTest, ContiguousIndicesWithSaveLayerAlphaRestore) { push_op<DrawColorOp>(0u, SkBlendMode::kClear); push_op<DrawColorOp>(1u, SkBlendMode::kClear); uint8_t alpha = 100; - push_op<SaveLayerAlphaOp>(nullptr, alpha, true); + push_op<SaveLayerAlphaOp>(nullptr, alpha); push_op<RestoreOp>(); push_op<DrawColorOp>(2u, SkBlendMode::kClear); push_op<DrawColorOp>(3u, SkBlendMode::kClear); @@ -757,7 +759,7 @@ TEST_F(PaintOpBufferOffsetsTest, push_op<DrawColorOp>(0u, SkBlendMode::kClear); push_op<DrawColorOp>(1u, SkBlendMode::kClear); uint8_t alpha = 100; - push_op<SaveLayerAlphaOp>(nullptr, alpha, true); + push_op<SaveLayerAlphaOp>(nullptr, alpha); push_op<DrawColorOp>(2u, SkBlendMode::kClear); push_op<DrawColorOp>(3u, SkBlendMode::kClear); push_op<RestoreOp>(); @@ -807,7 +809,7 @@ TEST_F(PaintOpBufferOffsetsTest, add_draw_rect(0u); add_draw_rect(1u); uint8_t alpha = 100; - push_op<SaveLayerAlphaOp>(nullptr, alpha, true); + push_op<SaveLayerAlphaOp>(nullptr, alpha); add_draw_rect(2u); push_op<RestoreOp>(); add_draw_rect(3u); @@ -840,7 +842,7 @@ TEST_F(PaintOpBufferOffsetsTest, add_draw_rect(0u); add_draw_rect(1u); uint8_t alpha = 100; - push_op<SaveLayerAlphaOp>(nullptr, alpha, true); + push_op<SaveLayerAlphaOp>(nullptr, alpha); add_draw_rect(2u); add_draw_rect(3u); add_draw_rect(4u); @@ -899,7 +901,7 @@ TEST(PaintOpBufferTest, SaveLayerAlphaDrawRestoreWithBadBlendMode) { add_draw_rect(&buffer, 0u); uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, true); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); add_draw_rect(&buffer, 1u); buffer.push<RestoreOp>(); add_draw_rect(&buffer, 2u); @@ -928,9 +930,9 @@ TEST(PaintOpBufferTest, UnmatchedSaveRestoreNoSideEffects) { // Push 2 saves. uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, true); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); add_draw_rect(&buffer, 0u); - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, true); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); add_draw_rect(&buffer, 1u); add_draw_rect(&buffer, 2u); // But only 1 restore. @@ -1040,7 +1042,6 @@ std::vector<PaintFlags> test_flags = { PaintFlags(), [] { PaintFlags flags; - flags.setTextSize(82.7f); flags.setColor(SK_ColorMAGENTA); flags.setStrokeWidth(4.2f); flags.setStrokeMiter(5.91f); @@ -1048,15 +1049,12 @@ std::vector<PaintFlags> test_flags = { flags.setStrokeCap(PaintFlags::kSquare_Cap); flags.setStrokeJoin(PaintFlags::kBevel_Join); flags.setStyle(PaintFlags::kStrokeAndFill_Style); - flags.setTextEncoding(PaintFlags::kGlyphID_TextEncoding); - flags.setHinting(PaintFlags::kNormal_Hinting); flags.setFilterQuality(SkFilterQuality::kMedium_SkFilterQuality); flags.setShader(PaintShader::MakeColor(SkColorSetARGB(1, 2, 3, 4))); return flags; }(), [] { PaintFlags flags; - flags.setTextSize(0.0f); flags.setColor(SK_ColorCYAN); flags.setAlpha(103); flags.setStrokeWidth(0.32f); @@ -1065,8 +1063,6 @@ std::vector<PaintFlags> test_flags = { flags.setStrokeCap(PaintFlags::kRound_Cap); flags.setStrokeJoin(PaintFlags::kRound_Join); flags.setStyle(PaintFlags::kFill_Style); - flags.setTextEncoding(PaintFlags::kUTF32_TextEncoding); - flags.setHinting(PaintFlags::kSlight_Hinting); flags.setFilterQuality(SkFilterQuality::kHigh_SkFilterQuality); SkScalar intervals[] = {1.f, 1.f}; @@ -1167,8 +1163,7 @@ std::vector<sk_sp<SkTextBlob>> test_paint_blobs = { SkTextBlobBuilder builder; int glyph_count = 5; - const auto& run = - builder.allocRun(font, glyph_count, 1.2f, 2.3f, &test_rects[0]); + const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f); // allocRun() allocates only the glyph buffer. std::fill(run.glyphs, run.glyphs + glyph_count, 0); return builder.make(); @@ -1179,13 +1174,12 @@ std::vector<sk_sp<SkTextBlob>> test_paint_blobs = { SkTextBlobBuilder builder; int glyph_count = 5; - const auto& run1 = - builder.allocRun(font, glyph_count, 1.2f, 2.3f, &test_rects[0]); + const auto& run1 = builder.allocRun(font, glyph_count, 1.2f, 2.3f); // allocRun() allocates only the glyph buffer. std::fill(run1.glyphs, run1.glyphs + glyph_count, 0); glyph_count = 16; - const auto& run2 = builder.allocRunPos(font, glyph_count, &test_rects[1]); + const auto& run2 = builder.allocRunPos(font, glyph_count); // allocRun() allocates the glyph buffer, and 2 scalars per glyph for the // pos buffer. std::fill(run2.glyphs, run2.glyphs + glyph_count, 0); @@ -1193,8 +1187,7 @@ std::vector<sk_sp<SkTextBlob>> test_paint_blobs = { font.setTypeface(test_typefaces[1][1]); glyph_count = 8; - const auto& run3 = - builder.allocRunPosH(font, glyph_count, 0, &test_rects[2]); + const auto& run3 = builder.allocRunPosH(font, glyph_count, 0); // allocRun() allocates the glyph buffer, and 1 scalar per glyph for the // pos buffer. std::fill(run3.glyphs, run3.glyphs + glyph_count, 0); @@ -1568,10 +1561,10 @@ void PushSaveLayerOps(PaintOpBuffer* buffer) { void PushSaveLayerAlphaOps(PaintOpBuffer* buffer) { size_t len = std::min(test_uint8s.size(), test_rects.size()); for (size_t i = 0; i < len; ++i) - buffer->push<SaveLayerAlphaOp>(&test_rects[i], test_uint8s[i], !!(i % 2)); + buffer->push<SaveLayerAlphaOp>(&test_rects[i], test_uint8s[i]); // Test optional args. - buffer->push<SaveLayerAlphaOp>(nullptr, test_uint8s[0], false); + buffer->push<SaveLayerAlphaOp>(nullptr, test_uint8s[0]); ValidateOps<SaveLayerAlphaOp>(buffer); } @@ -2254,7 +2247,7 @@ TEST(PaintOpBufferSerializationTest, AlphaFoldingDuringSerialization) { PaintOpBuffer buffer; uint8_t alpha = 100; - buffer.push<SaveLayerAlphaOp>(nullptr, alpha, false); + buffer.push<SaveLayerAlphaOp>(nullptr, alpha); PaintFlags draw_flags; draw_flags.setColor(SK_ColorMAGENTA); @@ -2471,11 +2464,11 @@ TEST(PaintOpBufferTest, ValidateSkBlendMode) { static_cast<SkBlendMode>(static_cast<uint32_t>(~0)), }; - for (size_t i = 0; i < arraysize(bad_modes_for_draw_color); ++i) { + for (size_t i = 0; i < base::size(bad_modes_for_draw_color); ++i) { buffer.push<DrawColorOp>(SK_ColorMAGENTA, bad_modes_for_draw_color[i]); } - for (size_t i = 0; i < arraysize(bad_modes_for_flags); ++i) { + for (size_t i = 0; i < base::size(bad_modes_for_flags); ++i) { PaintFlags flags = test_flags[i % test_flags.size()]; flags.setBlendMode(bad_modes_for_flags[i]); buffer.push<DrawRectOp>(test_rects[i % test_rects.size()], flags); @@ -2534,7 +2527,7 @@ TEST(PaintOpBufferTest, ValidateRects) { buffer.push<DrawRectOp>(bad_rect, test_flags[0]); buffer.push<SaveLayerOp>(&bad_rect, nullptr); buffer.push<SaveLayerOp>(&bad_rect, &test_flags[0]); - buffer.push<SaveLayerAlphaOp>(&bad_rect, test_uint8s[0], true); + buffer.push<SaveLayerAlphaOp>(&bad_rect, test_uint8s[0]); TestOptionsProvider options_provider; @@ -3289,9 +3282,10 @@ TEST(PaintOpBufferTest, RecordShadersCached) { // Hold onto records so PaintShader pointer comparisons are valid. sk_sp<PaintRecord> records[5]; const SkShader* last_shader = nullptr; + std::vector<uint8_t> scratch_buffer; PaintOp::DeserializeOptions deserialize_options( transfer_cache, options_provider.service_paint_cache(), - options_provider.strike_client()); + options_provider.strike_client(), &scratch_buffer); // Several deserialization test cases: // (0) deserialize once, verify cached is the same as deserialized version @@ -3391,9 +3385,10 @@ TEST(PaintOpBufferTest, RecordShadersCachedSize) { options_provider.context_supports_distance_field_text(); serializer.Serialize(buffer.get()); + std::vector<uint8_t> scratch_buffer; PaintOp::DeserializeOptions deserialize_options( transfer_cache, options_provider.service_paint_cache(), - options_provider.strike_client()); + options_provider.strike_client(), &scratch_buffer); auto record = PaintOpBuffer::MakeFromMemory( memory.get(), serializer.written(), deserialize_options); auto* shader_entry = diff --git a/chromium/cc/paint/paint_op_helper_unittest.cc b/chromium/cc/paint/paint_op_helper_unittest.cc index eac6e4ddc62..c2682d039b4 100644 --- a/chromium/cc/paint/paint_op_helper_unittest.cc +++ b/chromium/cc/paint/paint_op_helper_unittest.cc @@ -65,12 +65,10 @@ TEST(PaintOpHelper, DrawDRRectToString) { str, "DrawDRRectOp(outer=[bounded by 1.000,2.000 3.000x4.000], inner=[bounded " "by 5.000,6.000 7.000x8.000], flags=[color=rgba(0, 0, 0, 255), " - "blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, hinting=kNormal_Hinting, " - "isAutohinted=false, isDither=false, textEncoding=kUTF8_TextEncoding, " - "textSize=12.000, filterQuality=kNone_SkFilterQuality, " + "blendMode=kSrcOver, isAntiAlias=false, isDither=false, " + "filterQuality=kNone_SkFilterQuality, " "strokeWidth=0.000, strokeMiter=4.000, strokeCap=kButt_Cap, " - "strokeJoin=kMiter_Join, typeface=(nil), colorFilter=(nil), " + "strokeJoin=kMiter_Join, colorFilter=(nil), " "maskFilter=(nil), shader=(nil), hasShader=false, shaderIsOpaque=false, " "pathEffect=(nil), imageFilter=(nil), drawLooper=(nil), " "isSimpleOpacity=true, supportsFoldingAlpha=true, isValid=true, " @@ -84,12 +82,9 @@ TEST(PaintOpHelper, DrawImageToString) { str, "DrawImageOp(image=<paint image>, left=10.500, top=20.300, " "flags=[color=rgba(0, 0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " - "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " + "isDither=false, filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), shader=(nil), " + "colorFilter=(nil), maskFilter=(nil), shader=(nil), " "hasShader=false, shaderIsOpaque=false, pathEffect=(nil), " "imageFilter=(nil), drawLooper=(nil), isSimpleOpacity=true, " "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])"); @@ -105,12 +100,9 @@ TEST(PaintOpHelper, DrawImageRectToString) { "DrawImageRectOp(image=<paint image>, src=[1.000,2.000 3.000x4.000], " "dst=[5.000,6.000 7.000x8.000], constraint=kStrict_SrcRectConstraint, " "flags=[color=rgba(0, 0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " - "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " + "isDither=false, filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), shader=(nil), " + "colorFilter=(nil), maskFilter=(nil), shader=(nil), " "hasShader=false, shaderIsOpaque=false, pathEffect=(nil), " "imageFilter=(nil), drawLooper=(nil), isSimpleOpacity=true, " "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])"); @@ -121,13 +113,10 @@ TEST(PaintOpHelper, DrawIRectToString) { std::string str = PaintOpHelper::ToString(&op); EXPECT_EQ(str, "DrawIRectOp(rect=[1,2 3x4], flags=[color=rgba(0, 0, 0, 255), " - "blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " + "blendMode=kSrcOver, isAntiAlias=false, isDither=false, " "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), " + "colorFilter=(nil), maskFilter=(nil), " "shader=(nil), hasShader=false, shaderIsOpaque=false, " "pathEffect=(nil), imageFilter=(nil), drawLooper=(nil), " "isSimpleOpacity=true, supportsFoldingAlpha=true, isValid=true, " @@ -140,13 +129,10 @@ TEST(PaintOpHelper, DrawLineToString) { EXPECT_EQ( str, "DrawLineOp(x0=1.100, y0=2.200, x1=3.300, y1=4.400, flags=[color=rgba(0, " - "0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " + "0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, isDither=false, " "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), shader=(nil), " + "colorFilter=(nil), maskFilter=(nil), shader=(nil), " "hasShader=false, shaderIsOpaque=false, pathEffect=(nil), " "imageFilter=(nil), drawLooper=(nil), isSimpleOpacity=true, " "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])"); @@ -158,13 +144,10 @@ TEST(PaintOpHelper, DrawOvalToString) { EXPECT_EQ( str, "DrawOvalOp(oval=[100.000,200.000 300.000x400.000], flags=[color=rgba(0, " - "0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " + "0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, isDither=false, " "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), shader=(nil), " + "colorFilter=(nil), maskFilter=(nil), shader=(nil), " "hasShader=false, shaderIsOpaque=false, pathEffect=(nil), " "imageFilter=(nil), drawLooper=(nil), isSimpleOpacity=true, " "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])"); @@ -176,13 +159,10 @@ TEST(PaintOpHelper, DrawPathToString) { std::string str = PaintOpHelper::ToString(&op); EXPECT_EQ(str, "DrawPathOp(path=<SkPath>, flags=[color=rgba(0, 0, 0, 255), " - "blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " + "blendMode=kSrcOver, isAntiAlias=false, isDither=false, " "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), " + "colorFilter=(nil), maskFilter=(nil), " "shader=(nil), hasShader=false, shaderIsOpaque=false, " "pathEffect=(nil), imageFilter=(nil), drawLooper=(nil), " "isSimpleOpacity=true, supportsFoldingAlpha=true, isValid=true, " @@ -202,11 +182,9 @@ TEST(PaintOpHelper, DrawRectToString) { str, "DrawRectOp(rect=[-1.000,-2.000 -3.000x-4.000], flags=[color=rgba(0, 0, " "0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, hinting=kNormal_Hinting, " - "isAutohinted=false, isDither=false, textEncoding=kUTF8_TextEncoding, " - "textSize=12.000, filterQuality=kNone_SkFilterQuality, " + "isDither=false, filterQuality=kNone_SkFilterQuality, " "strokeWidth=0.000, strokeMiter=4.000, strokeCap=kButt_Cap, " - "strokeJoin=kMiter_Join, typeface=(nil), colorFilter=(nil), " + "strokeJoin=kMiter_Join, colorFilter=(nil), " "maskFilter=(nil), shader=(nil), hasShader=false, shaderIsOpaque=false, " "pathEffect=(nil), imageFilter=(nil), drawLooper=(nil), " "isSimpleOpacity=true, supportsFoldingAlpha=true, isValid=true, " @@ -221,12 +199,9 @@ TEST(PaintOpHelper, DrawRRectToString) { str, "DrawRRectOp(rrect=[bounded by -1.000,-2.000 3.000x4.000], " "flags=[color=rgba(0, 0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " - "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " + "isDither=false, filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), shader=(nil), " + "colorFilter=(nil), maskFilter=(nil), shader=(nil), " "hasShader=false, shaderIsOpaque=false, pathEffect=(nil), " "imageFilter=(nil), drawLooper=(nil), isSimpleOpacity=true, " "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])"); @@ -238,13 +213,10 @@ TEST(PaintOpHelper, DrawTextBlobToString) { EXPECT_EQ( str, "DrawTextBlobOp(blob=(nil), x=100.000, y=-222.000, flags=[color=rgba(0, " - "0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, " - "hinting=kNormal_Hinting, isAutohinted=false, isDither=false, " - "textEncoding=kUTF8_TextEncoding, textSize=12.000, " + "0, 0, 255), blendMode=kSrcOver, isAntiAlias=false, isDither=false, " "filterQuality=kNone_SkFilterQuality, strokeWidth=0.000, " "strokeMiter=4.000, strokeCap=kButt_Cap, strokeJoin=kMiter_Join, " - "typeface=(nil), colorFilter=(nil), maskFilter=(nil), shader=(nil), " + "colorFilter=(nil), maskFilter=(nil), shader=(nil), " "hasShader=false, shaderIsOpaque=false, pathEffect=(nil), " "imageFilter=(nil), drawLooper=(nil), isSimpleOpacity=true, " "supportsFoldingAlpha=true, isValid=true, hasDiscardableImages=false])"); @@ -281,12 +253,10 @@ TEST(PaintOpHelper, SaveLayerToString) { EXPECT_EQ( str, "SaveLayerOp(bounds=[1.000,2.000 3.000x4.000], flags=[color=rgba(0, 0, " - "0, 255), blendMode=kSrcOver, isAntiAlias=false, " - "isSubpixelText=false, isLCDRenderText=false, hinting=kNormal_Hinting, " - "isAutohinted=false, isDither=false, textEncoding=kUTF8_TextEncoding, " - "textSize=12.000, filterQuality=kNone_SkFilterQuality, " + "0, 255), blendMode=kSrcOver, isAntiAlias=false, isDither=false, " + "filterQuality=kNone_SkFilterQuality, " "strokeWidth=0.000, strokeMiter=4.000, strokeCap=kButt_Cap, " - "strokeJoin=kMiter_Join, typeface=(nil), colorFilter=(nil), " + "strokeJoin=kMiter_Join, colorFilter=(nil), " "maskFilter=(nil), shader=(nil), hasShader=false, shaderIsOpaque=false, " "pathEffect=(nil), imageFilter=(nil), drawLooper=(nil), " "isSimpleOpacity=true, supportsFoldingAlpha=true, isValid=true, " @@ -295,11 +265,10 @@ TEST(PaintOpHelper, SaveLayerToString) { TEST(PaintOpHelper, SaveLayerAlphaToString) { SkRect bounds = SkRect::MakeXYWH(1, 2, 3, 4); - SaveLayerAlphaOp op(&bounds, 255, false); + SaveLayerAlphaOp op(&bounds, 255); std::string str = PaintOpHelper::ToString(&op); EXPECT_EQ(str, - "SaveLayerAlphaOp(bounds=[1.000,2.000 3.000x4.000], alpha=255, " - "preserve_lcd_text_requests=false)"); + "SaveLayerAlphaOp(bounds=[1.000,2.000 3.000x4.000], alpha=255)"); } TEST(PaintOpHelper, ScaleToString) { diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc index 9805e9c8149..a8b777f7c22 100644 --- a/chromium/cc/paint/paint_op_reader.cc +++ b/chromium/cc/paint/paint_op_reader.cc @@ -9,6 +9,7 @@ #include "base/bits.h" #include "base/debug/dump_without_crashing.h" +#include "base/rand_util.h" #include "base/stl_util.h" #include "cc/paint/image_transfer_cache_entry.h" #include "cc/paint/paint_cache.h" @@ -27,12 +28,6 @@ namespace cc { namespace { -// If we have more than this many colors, abort deserialization. -const size_t kMaxShaderColorsSupported = 10000; -const size_t kMaxMergeFilterCount = 10000; -const size_t kMaxKernelSize = 1000; -const size_t kMaxRegionByteSize = 10 * 1024; - bool IsValidPaintShaderType(PaintShader::Type type) { return static_cast<uint8_t>(type) < static_cast<uint8_t>(PaintShader::Type::kShaderCount); @@ -122,6 +117,16 @@ void PaintOpReader::ReadSimple(T* val) { remaining_bytes_ -= size; } +uint8_t* PaintOpReader::CopyScratchSpace(size_t bytes) { + DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_))); + + if (options_.scratch_buffer->size() < bytes) + options_.scratch_buffer->resize(bytes); + memcpy(options_.scratch_buffer->data(), const_cast<const char*>(memory_), + bytes); + return options_.scratch_buffer->data(); +} + template <typename T> void PaintOpReader::ReadFlattenable(sk_sp<T>* val) { size_t bytes = 0; @@ -133,13 +138,9 @@ void PaintOpReader::ReadFlattenable(sk_sp<T>* val) { if (bytes == 0) return; - // This is assumed safe from TOCTOU violations as the flattenable - // deserializing function uses an SkReadBuffer which reads each piece of - // memory once much like PaintOpReader does. - DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_))); + auto* scratch = CopyScratchSpace(bytes); val->reset(static_cast<T*>( - SkFlattenable::Deserialize(T::GetFlattenableType(), - const_cast<const char*>(memory_), bytes) + SkFlattenable::Deserialize(T::GetFlattenableType(), scratch, bytes) .release())); if (!val) SetInvalid(); @@ -214,8 +215,8 @@ void PaintOpReader::Read(SkPath* path) { return; if (path_bytes != 0u) { - size_t bytes_read = - path->readFromMemory(const_cast<const char*>(memory_), path_bytes); + auto* scratch = CopyScratchSpace(path_bytes); + size_t bytes_read = path->readFromMemory(scratch, path_bytes); if (bytes_read == 0u) { SetInvalid(); return; @@ -236,7 +237,6 @@ void PaintOpReader::Read(SkPath* path) { } void PaintOpReader::Read(PaintFlags* flags) { - Read(&flags->text_size_); ReadSimple(&flags->color_); Read(&flags->width_); Read(&flags->miter_limit_); @@ -386,13 +386,8 @@ void PaintOpReader::Read(sk_sp<SkColorSpace>* color_space) { if (!valid_ || size == 0) return; - // To avoid TOCTOU issues, make a copy of this prior to turning it - // into an SkColorSpace. SkColorSpace::Deserialize reads header - // fields multiple times, so is not safe to pass memory_ to directly. - std::unique_ptr<char[]> data(new char[size]); - memcpy(data.get(), const_cast<const char*>(memory_), size); - - *color_space = SkColorSpace::Deserialize(data.get(), size); + auto* scratch = CopyScratchSpace(size); + *color_space = SkColorSpace::Deserialize(scratch, size); // If this had non-zero bytes, it should be a valid color space. if (!color_space) SetInvalid(); @@ -431,8 +426,9 @@ void PaintOpReader::Read(sk_sp<SkTextBlob>* blob) { TypefaceCtx typeface_ctx(options_.strike_client); procs.fTypefaceProc = &DeserializeTypeface; procs.fTypefaceCtx = &typeface_ctx; - sk_sp<SkTextBlob> deserialized_blob = SkTextBlob::Deserialize( - const_cast<const char*>(memory_), data_bytes, procs); + auto* scratch = CopyScratchSpace(data_bytes); + sk_sp<SkTextBlob> deserialized_blob = + SkTextBlob::Deserialize(scratch, data_bytes, procs); if (!deserialized_blob || typeface_ctx.invalid_typeface) { SetInvalid(); return; @@ -513,7 +509,7 @@ void PaintOpReader::Read(sk_sp<PaintShader>* shader) { ReadSize(&colors_size); // If there are too many colors, abort. - if (colors_size > kMaxShaderColorsSupported) { + if (colors_size > remaining_bytes_) { SetInvalid(); return; } @@ -614,9 +610,8 @@ void PaintOpReader::AlignMemory(size_t alignment) { } inline void PaintOpReader::SetInvalid() { - if (valid_ && options_.crash_dump_on_failure) { - // TODO(enne): make this DumpWithoutCrashing after http://crbug.com/910772 - // base::debug::DumpWithoutCrashing(); + if (valid_ && options_.crash_dump_on_failure && base::RandInt(1, 10) == 1) { + base::debug::DumpWithoutCrashing(); } valid_ = false; } @@ -909,7 +904,7 @@ void PaintOpReader::ReadMatrixConvolutionPaintFilter( return; auto size = static_cast<size_t>(sk_64_mul(kernel_size.width(), kernel_size.height())); - if (size > kMaxKernelSize) { + if (size > remaining_bytes_) { SetInvalid(); return; } @@ -1008,7 +1003,12 @@ void PaintOpReader::ReadMergePaintFilter( const base::Optional<PaintFilter::CropRect>& crop_rect) { size_t input_count = 0; ReadSimple(&input_count); - if (input_count > kMaxMergeFilterCount) + + // The minimum size for a serialized filter is 4 bytes (a zero uint32_t to + // indicate a null filter). Make sure the |input_count| doesn't exceed the + // maximum number of filters possible for the remaining data. + const size_t max_filters = remaining_bytes_ / 4u; + if (input_count > max_filters) SetInvalid(); if (!valid_) return; @@ -1271,7 +1271,7 @@ size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) { void PaintOpReader::Read(SkRegion* region) { size_t region_bytes = 0; ReadSize(®ion_bytes); - if (region_bytes == 0 || region_bytes > kMaxRegionByteSize) + if (region_bytes == 0 || region_bytes > remaining_bytes_) SetInvalid(); if (!valid_) return; diff --git a/chromium/cc/paint/paint_op_reader.h b/chromium/cc/paint/paint_op_reader.h index 6a9c8de4193..e3ed7b86052 100644 --- a/chromium/cc/paint/paint_op_reader.h +++ b/chromium/cc/paint/paint_op_reader.h @@ -188,6 +188,7 @@ class CC_PAINT_EXPORT PaintOpReader { size_t Read(sk_sp<PaintRecord>* record); void Read(SkRegion* region); + uint8_t* CopyScratchSpace(size_t bytes); const volatile char* memory_ = nullptr; size_t remaining_bytes_ = 0u; diff --git a/chromium/cc/paint/paint_op_writer.cc b/chromium/cc/paint/paint_op_writer.cc index f933da967e4..72783966429 100644 --- a/chromium/cc/paint/paint_op_writer.cc +++ b/chromium/cc/paint/paint_op_writer.cc @@ -24,7 +24,7 @@ namespace { const size_t kSkiaAlignment = 4u; size_t RoundDownToAlignment(size_t bytes, size_t alignment) { - return bytes - (bytes & (alignment - 1)); + return base::bits::AlignDown(bytes, alignment); } SkIRect MakeSrcRect(const PaintImage& image) { @@ -194,7 +194,6 @@ void PaintOpWriter::Write(const SkPath& path) { } void PaintOpWriter::Write(const PaintFlags& flags) { - Write(flags.text_size_); WriteSimple(flags.color_); Write(flags.width_); Write(flags.miter_limit_); diff --git a/chromium/cc/paint/paint_worklet_input.h b/chromium/cc/paint/paint_worklet_input.h new file mode 100644 index 00000000000..165729147d0 --- /dev/null +++ b/chromium/cc/paint/paint_worklet_input.h @@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_PAINT_PAINT_WORKLET_INPUT_H_ +#define CC_PAINT_PAINT_WORKLET_INPUT_H_ + +#include "base/memory/ref_counted.h" +#include "cc/cc_export.h" +#include "ui/gfx/geometry/size_f.h" + +namespace cc { + +class CC_EXPORT PaintWorkletInput + : public base::RefCountedThreadSafe<PaintWorkletInput> { + public: + virtual gfx::SizeF GetSize() const = 0; + + protected: + friend class base::RefCountedThreadSafe<PaintWorkletInput>; + virtual ~PaintWorkletInput() = default; +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_WORKLET_INPUT_H_ diff --git a/chromium/cc/paint/paint_worklet_layer_painter.h b/chromium/cc/paint/paint_worklet_layer_painter.h new file mode 100644 index 00000000000..c1a8e097921 --- /dev/null +++ b/chromium/cc/paint/paint_worklet_layer_painter.h @@ -0,0 +1,22 @@ +// 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_PAINT_PAINT_WORKLET_LAYER_PAINTER_H_ +#define CC_PAINT_PAINT_WORKLET_LAYER_PAINTER_H_ + +#include "cc/cc_export.h" +#include "cc/paint/paint_record.h" + +namespace cc { + +class CC_EXPORT PaintWorkletLayerPainter { + public: + virtual ~PaintWorkletLayerPainter() {} + + virtual sk_sp<PaintRecord> Paint() = 0; +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_WORKLET_LAYER_PAINTER_H_ diff --git a/chromium/cc/paint/raw_memory_transfer_cache_entry.cc b/chromium/cc/paint/raw_memory_transfer_cache_entry.cc index aa6fb645733..8f8e746f01a 100644 --- a/chromium/cc/paint/raw_memory_transfer_cache_entry.cc +++ b/chromium/cc/paint/raw_memory_transfer_cache_entry.cc @@ -10,15 +10,18 @@ namespace cc { ClientRawMemoryTransferCacheEntry::ClientRawMemoryTransferCacheEntry( std::vector<uint8_t> data) - : id_(s_next_id_.GetNext()), data_(std::move(data)) {} + : id_(s_next_id_.GetNext()), data_(std::move(data)) { + DCHECK_LE(data_.size(), UINT32_MAX); +} + ClientRawMemoryTransferCacheEntry::~ClientRawMemoryTransferCacheEntry() = default; // static base::AtomicSequenceNumber ClientRawMemoryTransferCacheEntry::s_next_id_; -size_t ClientRawMemoryTransferCacheEntry::SerializedSize() const { - return data_.size(); +uint32_t ClientRawMemoryTransferCacheEntry::SerializedSize() const { + return static_cast<uint32_t>(data_.size()); } uint32_t ClientRawMemoryTransferCacheEntry::Id() const { diff --git a/chromium/cc/paint/raw_memory_transfer_cache_entry.h b/chromium/cc/paint/raw_memory_transfer_cache_entry.h index c6ce52af731..2e9aafd490a 100644 --- a/chromium/cc/paint/raw_memory_transfer_cache_entry.h +++ b/chromium/cc/paint/raw_memory_transfer_cache_entry.h @@ -22,7 +22,7 @@ class CC_PAINT_EXPORT ClientRawMemoryTransferCacheEntry explicit ClientRawMemoryTransferCacheEntry(std::vector<uint8_t> data); ~ClientRawMemoryTransferCacheEntry() final; uint32_t Id() const final; - size_t SerializedSize() const final; + uint32_t SerializedSize() const final; bool Serialize(base::span<uint8_t> data) const final; private: diff --git a/chromium/cc/paint/record_paint_canvas.cc b/chromium/cc/paint/record_paint_canvas.cc index 2d9b4e4eb40..24e7819d212 100644 --- a/chromium/cc/paint/record_paint_canvas.cc +++ b/chromium/cc/paint/record_paint_canvas.cc @@ -49,7 +49,7 @@ int RecordPaintCanvas::saveLayer(const SkRect* bounds, // TODO(enne): maybe more callers should know this and call // saveLayerAlpha instead of needing to check here. uint8_t alpha = SkColorGetA(flags->getColor()); - return saveLayerAlpha(bounds, alpha, false); + return saveLayerAlpha(bounds, alpha); } // TODO(enne): it appears that image filters affect matrices and color @@ -63,10 +63,8 @@ int RecordPaintCanvas::saveLayer(const SkRect* bounds, return GetCanvas()->saveLayer(bounds, nullptr); } -int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, - uint8_t alpha, - bool preserve_lcd_text_requests) { - list_->push<SaveLayerAlphaOp>(bounds, alpha, preserve_lcd_text_requests); +int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) { + list_->push<SaveLayerAlphaOp>(bounds, alpha); return GetCanvas()->saveLayerAlpha(bounds, alpha); } diff --git a/chromium/cc/paint/record_paint_canvas.h b/chromium/cc/paint/record_paint_canvas.h index cfa24116f45..183f8fefdca 100644 --- a/chromium/cc/paint/record_paint_canvas.h +++ b/chromium/cc/paint/record_paint_canvas.h @@ -34,9 +34,7 @@ class CC_PAINT_EXPORT RecordPaintCanvas final : public PaintCanvas { int save() override; int saveLayer(const SkRect* bounds, const PaintFlags* flags) override; - int saveLayerAlpha(const SkRect* bounds, - uint8_t alpha, - bool preserve_lcd_text_requests) override; + int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override; void restore() override; int getSaveCount() const override; diff --git a/chromium/cc/paint/skia_paint_canvas.cc b/chromium/cc/paint/skia_paint_canvas.cc index 4bb07e76333..99e9dfee798 100644 --- a/chromium/cc/paint/skia_paint_canvas.cc +++ b/chromium/cc/paint/skia_paint_canvas.cc @@ -81,14 +81,7 @@ int SkiaPaintCanvas::saveLayer(const SkRect* bounds, const PaintFlags* flags) { return canvas_->saveLayer(bounds, &paint); } -int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, - uint8_t alpha, - bool preserve_lcd_text_requests) { - if (preserve_lcd_text_requests) { - SkPaint paint; - paint.setAlpha(alpha); - return canvas_->saveLayerPreserveLCDTextRequests(bounds, &paint); - } +int SkiaPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) { return canvas_->saveLayerAlpha(bounds, alpha); } diff --git a/chromium/cc/paint/skia_paint_canvas.h b/chromium/cc/paint/skia_paint_canvas.h index 458bf99d4da..e22e6f2365f 100644 --- a/chromium/cc/paint/skia_paint_canvas.h +++ b/chromium/cc/paint/skia_paint_canvas.h @@ -55,9 +55,7 @@ class CC_PAINT_EXPORT SkiaPaintCanvas final : public PaintCanvas { int save() override; int saveLayer(const SkRect* bounds, const PaintFlags* flags) override; - int saveLayerAlpha(const SkRect* bounds, - uint8_t alpha, - bool preserve_lcd_text_requests) override; + int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) override; void restore() override; int getSaveCount() const override; diff --git a/chromium/cc/paint/solid_color_analyzer.cc b/chromium/cc/paint/solid_color_analyzer.cc index 12ad8e46f1d..9d3ed900fb8 100644 --- a/chromium/cc/paint/solid_color_analyzer.cc +++ b/chromium/cc/paint/solid_color_analyzer.cc @@ -4,12 +4,51 @@ #include "cc/paint/solid_color_analyzer.h" +#include <cmath> + #include "base/trace_event/trace_event.h" +#include "build/build_config.h" #include "cc/paint/paint_op_buffer.h" +#include "third_party/skia/include/core/SkTypes.h" #include "third_party/skia/include/utils/SkNoDrawCanvas.h" namespace cc { namespace { + +SkColor DoSrcOverAlphaBlend(SkColor src, SkColor dst) { + if (SkColorGetA(src) == 0) + return dst; + if (SkColorGetA(src) == 255) + return src; + + // Note: using alpha blending formulas adapted from + // https://en.wikipedia.org/wiki/Alpha_compositing: + // + // outA = srcA + dstA * (1 - srcA) + // outRGB = srcRGB * (srcA / outA) + dstRGB * [dstA * (1 - srcA) / outA] + const float src_alpha = SkColorGetA(src) / 255.0f; + const float src_alpha_complement = (255.0f - SkColorGetA(src)) / 255.0f; + const float dst_alpha = SkColorGetA(dst) / 255.0f; + const float out_alpha = src_alpha + dst_alpha * src_alpha_complement; + if (out_alpha == 0.0f) + return SK_ColorTRANSPARENT; + + const float inverse_out_alpha = 1.0f / out_alpha; + const float src_weight = src_alpha * inverse_out_alpha; + const float dst_weight = dst_alpha * src_alpha_complement * inverse_out_alpha; + const float out_red = + (SkColorGetR(src) * src_weight + SkColorGetR(dst) * dst_weight); + const float out_green = + (SkColorGetG(src) * src_weight + SkColorGetG(dst) * dst_weight); + const float out_blue = + (SkColorGetB(src) * src_weight + SkColorGetB(dst) * dst_weight); + + return SkColorSetARGB(static_cast<U8CPU>(std::floor(out_alpha * 255.0f)), + static_cast<U8CPU>(std::floor(out_red)), + static_cast<U8CPU>(std::floor(out_green)), + static_cast<U8CPU>(std::floor(out_blue))); +} + bool ActsLikeClear(SkBlendMode mode, unsigned src_alpha) { switch (mode) { case SkBlendMode::kClear: @@ -27,22 +66,29 @@ bool ActsLikeClear(SkBlendMode mode, unsigned src_alpha) { } } -bool IsSolidColor(SkColor color, SkBlendMode blendmode) { - return SkColorGetA(color) == 255 && - (blendmode == SkBlendMode::kSrc || blendmode == SkBlendMode::kSrcOver); +bool IsSolidColorBlendMode(SkBlendMode blendmode) { + return blendmode == SkBlendMode::kSrc || blendmode == SkBlendMode::kSrcOver; } bool IsSolidColorPaint(const PaintFlags& flags) { SkBlendMode blendmode = flags.getBlendMode(); // Paint is solid color if the following holds: - // - Alpha is 1.0, style is fill, and there are no special effects - // - Xfer mode is either kSrc or kSrcOver (kSrcOver is equivalent - // to kSrc if source alpha is 1.0, which is already checked). - return IsSolidColor(flags.getColor(), blendmode) && !flags.HasShader() && - !flags.getLooper() && !flags.getMaskFilter() && - !flags.getColorFilter() && !flags.getImageFilter() && - flags.getStyle() == PaintFlags::kFill_Style; + // - Style is fill, and there are no special effects. + // - Blend mode is either kSrc or kSrcOver. + bool is_solid_color = + IsSolidColorBlendMode(blendmode) && !flags.HasShader() && + !flags.getLooper() && !flags.getMaskFilter() && !flags.getColorFilter() && + !flags.getImageFilter() && flags.getStyle() == PaintFlags::kFill_Style; + +#if defined(OS_MACOSX) + // Additionally, on Mac, we require that the color is opaque due to + // https://crbug.com/922899. + // TODO(andrescj): remove this condition once that bug is fixed. + is_solid_color = (is_solid_color && SkColorGetA(flags.getColor()) == 255); +#endif // OS_MACOSX + + return is_solid_color; } // Returns true if the specified |drawn_shape| will cover the entire canvas @@ -75,6 +121,28 @@ bool IsFullQuad(const SkCanvas& canvas, const T& drawn_shape) { return drawn_shape.contains(clip_rect); } +void CalculateSolidColor(SkColor src_color, + SkBlendMode blendmode, + SkColor* dst_color, + bool* is_solid_color) { + if (blendmode == SkBlendMode::kSrc) { + // In the Src mode, we don't have to worry about what's in the canvas + // because we'll replace it with |src_color|. + *dst_color = src_color; + *is_solid_color = true; + } else { + DCHECK_EQ(SkBlendMode::kSrcOver, blendmode); + + // When using the SrcOver mode, we must ensure that either a) we're + // completely occluding what's in the canvas with an opaque color, or + // b) whatever is in the canvas is already a solid color. + if (SkColorGetA(src_color) == 255 || *is_solid_color) { + *dst_color = DoSrcOverAlphaBlend(src_color, *dst_color); + *is_solid_color = true; + } + } +} + void CheckIfSolidColor(const SkCanvas& canvas, SkColor color, SkBlendMode blendmode, @@ -95,9 +163,19 @@ void CheckIfSolidColor(const SkCanvas& canvas, else if (alpha != 0 || blendmode != SkBlendMode::kSrc) *is_transparent = false; - if (does_cover_canvas && IsSolidColor(color, blendmode)) { - *is_solid_color = true; - *out_color = color; + bool solid_color_candidate = + does_cover_canvas && IsSolidColorBlendMode(blendmode); + +#if defined(OS_MACOSX) + // Additionally, on Mac, we require that the color is opaque due to + // https://crbug.com/922899. + // TODO(andrescj): remove this condition once that bug is fixed. + solid_color_candidate = (solid_color_candidate && alpha == 255); +#endif // OS_MACOSX + + if (solid_color_candidate) { + CalculateSolidColor(color /* src_color */, blendmode, + out_color /* dst_color */, is_solid_color); } else { *is_solid_color = false; } @@ -123,8 +201,8 @@ void CheckIfSolidShape(const SkCanvas& canvas, *is_transparent = false; if (does_cover_canvas && IsSolidColorPaint(flags)) { - *is_solid_color = true; - *color = flags.getColor(); + CalculateSolidColor(flags.getColor() /* src_color */, flags.getBlendMode(), + color /* dst_color */, is_solid_color); } else { *is_solid_color = false; } @@ -147,7 +225,7 @@ base::Optional<SkColor> SolidColorAnalyzer::DetermineIfSolidColor( if (buffer->size() == 0 || (offsets && offsets->empty())) return SK_ColorTRANSPARENT; - bool is_solid = false; + bool is_solid = true; bool is_transparent = true; SkColor color = SK_ColorTRANSPARENT; diff --git a/chromium/cc/paint/solid_color_analyzer_unittest.cc b/chromium/cc/paint/solid_color_analyzer_unittest.cc index 939e517af61..3c95df2b2d7 100644 --- a/chromium/cc/paint/solid_color_analyzer_unittest.cc +++ b/chromium/cc/paint/solid_color_analyzer_unittest.cc @@ -6,6 +6,8 @@ #include "base/memory/ref_counted.h" #include "base/optional.h" +#include "base/stl_util.h" +#include "build/build_config.h" #include "cc/paint/display_item_list.h" #include "cc/paint/paint_filter.h" #include "cc/paint/record_paint_canvas.h" @@ -41,17 +43,17 @@ class SolidColorAnalyzerTest : public testing::Test { } RecordPaintCanvas* canvas() { return &*canvas_; } - bool IsSolidColor() { + bool IsSolidColor(int max_ops_to_analyze = 1) { Finalize(); - auto color = SolidColorAnalyzer::DetermineIfSolidColor(buffer_.get(), rect_, - 1, nullptr); + auto color = SolidColorAnalyzer::DetermineIfSolidColor( + buffer_.get(), rect_, max_ops_to_analyze, nullptr); return !!color; } - SkColor GetColor() { + SkColor GetColor(int max_ops_to_analyze = 1) { Finalize(); - auto color = SolidColorAnalyzer::DetermineIfSolidColor(buffer_.get(), rect_, - 1, nullptr); + auto color = SolidColorAnalyzer::DetermineIfSolidColor( + buffer_.get(), rect_, max_ops_to_analyze, nullptr); EXPECT_TRUE(color); return color ? *color : SK_ColorTRANSPARENT; } @@ -95,7 +97,13 @@ TEST_F(SolidColorAnalyzerTest, ClearTranslucent) { Initialize(); SkColor color = SkColorSetARGB(128, 11, 22, 33); canvas()->clear(color); +#if defined(OS_MACOSX) + // TODO(andrescj): remove the special treatment of OS_MACOSX once + // https://crbug.com/922899 is fixed. EXPECT_FALSE(IsSolidColor()); +#else + EXPECT_EQ(color, GetColor()); +#endif // OS_MACOSX } TEST_F(SolidColorAnalyzerTest, DrawColor) { @@ -280,6 +288,71 @@ TEST_F(SolidColorAnalyzerTest, DrawRectClipPath) { EXPECT_FALSE(IsSolidColor()); } +TEST_F(SolidColorAnalyzerTest, DrawRectTranslucent) { + Initialize(); + PaintFlags flags; + SkColor color = SkColorSetARGB(128, 128, 0, 0); + flags.setColor(color); + SkRect rect = SkRect::MakeWH(100, 100); + canvas()->drawRect(rect, flags); +#if defined(OS_MACOSX) + // TODO(andrescj): remove the special treatment of OS_MACOSX once + // https://crbug.com/922899 is fixed. + EXPECT_FALSE(IsSolidColor()); +#else + EXPECT_EQ(color, GetColor()); +#endif // OS_MACOSX +} + +TEST_F(SolidColorAnalyzerTest, DrawRectTranslucentOverNonSolid) { + Initialize(); + PaintFlags flags; + SkColor color = SkColorSetARGB(255, 128, 0, 0); + flags.setColor(color); + SkRect rect = SkRect::MakeWH(100, 50); + canvas()->drawRect(rect, flags); + color = SkColorSetARGB(128, 0, 128, 0); + flags.setColor(color); + rect = SkRect::MakeWH(100, 100); + canvas()->drawRect(rect, flags); + EXPECT_FALSE(IsSolidColor(2 /* max_ops_to_analyze */)); +} + +TEST_F(SolidColorAnalyzerTest, DrawRectOpaqueOccludesNonSolid) { + Initialize(); + PaintFlags flags; + SkColor color = SkColorSetARGB(255, 128, 0, 0); + flags.setColor(color); + SkRect rect = SkRect::MakeWH(100, 50); + canvas()->drawRect(rect, flags); + color = SkColorSetARGB(255, 0, 128, 0); + flags.setColor(color); + rect = SkRect::MakeWH(100, 100); + canvas()->drawRect(rect, flags); + EXPECT_EQ(color, GetColor(2 /* max_ops_to_analyze */)); +} + +TEST_F(SolidColorAnalyzerTest, DrawRectSolidWithSrcOverBlending) { + Initialize(); + PaintFlags flags; + SkColor color = SkColorSetARGB(64, 40, 50, 60); + flags.setColor(color); + SkRect rect = SkRect::MakeWH(100, 100); + canvas()->drawRect(rect, flags); + color = SkColorSetARGB(128, 10, 20, 30); + flags.setColor(color); + rect = SkRect::MakeWH(100, 100); + canvas()->drawRect(rect, flags); +#if defined(OS_MACOSX) + // TODO(andrescj): remove the special treatment of OS_MACOSX once + // https://crbug.com/922899 is fixed. + EXPECT_FALSE(IsSolidColor()); +#else + EXPECT_EQ(SkColorSetARGB(159, 15, 25, 35), + GetColor(2 /* max_ops_to_analyze */)); +#endif // OS_MACOSX +} + TEST_F(SolidColorAnalyzerTest, SaveLayer) { Initialize(); PaintFlags flags; @@ -351,7 +424,7 @@ TEST_F(SolidColorAnalyzerTest, ClipRRectCoversCanvas) { for (int case_scale = 0; case_scale < 2; ++case_scale) { bool scaled = case_scale > 0; - for (size_t i = 0; i < arraysize(cases); ++i) { + for (size_t i = 0; i < base::size(cases); ++i) { Reset(); Initialize(canvas_rect); diff --git a/chromium/cc/paint/transfer_cache_entry.h b/chromium/cc/paint/transfer_cache_entry.h index 374607e2497..5488aa16fca 100644 --- a/chromium/cc/paint/transfer_cache_entry.h +++ b/chromium/cc/paint/transfer_cache_entry.h @@ -45,7 +45,7 @@ class CC_PAINT_EXPORT ClientTransferCacheEntry { // Returns the serialized sized of this entry in bytes. This function will be // used to determine how much memory is going to be allocated and passed to // the Serialize() call. - virtual size_t SerializedSize() const = 0; + virtual uint32_t SerializedSize() const = 0; // Serializes the entry into the given span of memory. The size of the span is // guaranteed to be at least SerializedSize() bytes. Returns true on success diff --git a/chromium/cc/paint/transfer_cache_serialize_helper.cc b/chromium/cc/paint/transfer_cache_serialize_helper.cc index f50f150f7c7..7a59ca0d197 100644 --- a/chromium/cc/paint/transfer_cache_serialize_helper.cc +++ b/chromium/cc/paint/transfer_cache_serialize_helper.cc @@ -27,7 +27,7 @@ bool TransferCacheSerializeHelper::LockEntry(TransferCacheEntryType type, return true; } -size_t TransferCacheSerializeHelper::CreateEntry( +uint32_t TransferCacheSerializeHelper::CreateEntry( const ClientTransferCacheEntry& entry, char* memory) { // We shouldn't be creating entries if they were already created or locked. diff --git a/chromium/cc/paint/transfer_cache_serialize_helper.h b/chromium/cc/paint/transfer_cache_serialize_helper.h index 1a204407538..03b95c33de6 100644 --- a/chromium/cc/paint/transfer_cache_serialize_helper.h +++ b/chromium/cc/paint/transfer_cache_serialize_helper.h @@ -22,7 +22,7 @@ class CC_PAINT_EXPORT TransferCacheSerializeHelper { // The PaintOpWriter passes the address where the transfer cache may inline // this entry. The size returned is the memory used if the entry is inlined, // or 0u if no data is inlined. - size_t CreateEntry(const ClientTransferCacheEntry& entry, char* memory); + uint32_t CreateEntry(const ClientTransferCacheEntry& entry, char* memory); void FlushEntries(); void AssertLocked(TransferCacheEntryType type, uint32_t id); @@ -31,8 +31,8 @@ class CC_PAINT_EXPORT TransferCacheSerializeHelper { using EntryKey = std::pair<TransferCacheEntryType, uint32_t>; virtual bool LockEntryInternal(const EntryKey& key) = 0; - virtual size_t CreateEntryInternal(const ClientTransferCacheEntry& entry, - char* memory) = 0; + virtual uint32_t CreateEntryInternal(const ClientTransferCacheEntry& entry, + char* memory) = 0; virtual void FlushEntriesInternal(std::set<EntryKey> keys) = 0; private: diff --git a/chromium/cc/paint/transfer_cache_unittest.cc b/chromium/cc/paint/transfer_cache_unittest.cc index f24917ab29d..7b606ab9110 100644 --- a/chromium/cc/paint/transfer_cache_unittest.cc +++ b/chromium/cc/paint/transfer_cache_unittest.cc @@ -75,7 +75,7 @@ class TransferCacheTest : public testing::Test { } void CreateEntry(const ClientTransferCacheEntry& entry) { auto* context_support = ContextSupport(); - size_t size = entry.SerializedSize(); + uint32_t size = entry.SerializedSize(); void* data = context_support->MapTransferCacheEntry(size); ASSERT_TRUE(data); entry.Serialize(base::make_span(static_cast<uint8_t*>(data), size)); diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.cc b/chromium/cc/raster/bitmap_raster_buffer_provider.cc index fc981249cd6..e2713a24064 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.cc +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.cc @@ -156,7 +156,7 @@ bool BitmapRasterBufferProvider::IsResourceReadyToDraw( uint64_t BitmapRasterBufferProvider::SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const { // Bitmap resources are immediately ready to draw. return 0; diff --git a/chromium/cc/raster/bitmap_raster_buffer_provider.h b/chromium/cc/raster/bitmap_raster_buffer_provider.h index 9ceb0012b23..f9c1b9ed706 100644 --- a/chromium/cc/raster/bitmap_raster_buffer_provider.h +++ b/chromium/cc/raster/bitmap_raster_buffer_provider.h @@ -40,7 +40,7 @@ class CC_EXPORT BitmapRasterBufferProvider : public RasterBufferProvider { const ResourcePool::InUsePoolResource& resource) const override; uint64_t SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const override; void Shutdown() override; bool CheckRasterFinishedQueries() override; diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.cc b/chromium/cc/raster/gpu_raster_buffer_provider.cc index 2a731285a2c..2053c56dfc3 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.cc +++ b/chromium/cc/raster/gpu_raster_buffer_provider.cc @@ -24,8 +24,6 @@ #include "components/viz/client/client_resource_provider.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/raster_context_provider.h" -#include "components/viz/common/gpu/texture_allocation.h" -#include "components/viz/common/resources/resource_format_utils.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -149,8 +147,6 @@ static void RasterizeSourceOOP( // use GL_TEXTURE_2D. ri->BeginRasterCHROMIUM(raster_source->background_color(), msaa_sample_count, playback_settings.use_lcd_text, - viz::ResourceFormatToClosestSkColorType( - /*gpu_compositing=*/true, resource_format), playback_settings.raster_color_space, mailbox->name); float recording_to_raster_scale = transform.scale() / raster_source->recording_scale_factor(); @@ -204,9 +200,7 @@ static void RasterizeSource( // valid by the time the consume command executes. ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); } - GLuint texture_id = ri->CreateAndConsumeTexture( - texture_is_overlay_candidate, gfx::BufferUsage::SCANOUT, resource_format, - mailbox->name); + GLuint texture_id = ri->CreateAndConsumeForGpuRaster(mailbox->name); { ScopedGrContextAccess gr_context_access(context_provider); base::Optional<viz::ClientResourceProvider::ScopedSkSurface> scoped_surface; @@ -245,7 +239,7 @@ static void RasterizeSource( playback_settings); } - ri->DeleteTextures(1, &texture_id); + ri->DeleteGpuRasterTexture(texture_id); } } // namespace @@ -417,7 +411,7 @@ bool GpuRasterBufferProvider::IsResourceReadyToDraw( uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const { gpu::SyncToken latest_sync_token; for (const auto* in_use : resources) { @@ -436,7 +430,7 @@ uint64_t GpuRasterBufferProvider::SetReadyToDrawCallback( // Use the compositor context because we want this callback on the // compositor thread. compositor_context_provider_->ContextSupport()->SignalSyncToken( - latest_sync_token, callback); + latest_sync_token, std::move(callback)); } return callback_id; diff --git a/chromium/cc/raster/gpu_raster_buffer_provider.h b/chromium/cc/raster/gpu_raster_buffer_provider.h index 0ef41dd0bea..cf726868a6f 100644 --- a/chromium/cc/raster/gpu_raster_buffer_provider.h +++ b/chromium/cc/raster/gpu_raster_buffer_provider.h @@ -53,7 +53,7 @@ class CC_EXPORT GpuRasterBufferProvider : public RasterBufferProvider { const ResourcePool::InUsePoolResource& resource) const override; uint64_t SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const override; void Shutdown() override; bool CheckRasterFinishedQueries() override; diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.cc b/chromium/cc/raster/one_copy_raster_buffer_provider.cc index 75e11544218..f134a48b12f 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.cc @@ -221,7 +221,7 @@ bool OneCopyRasterBufferProvider::IsResourceReadyToDraw( uint64_t OneCopyRasterBufferProvider::SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const { gpu::SyncToken latest_sync_token; for (const auto* in_use : resources) { @@ -240,7 +240,7 @@ uint64_t OneCopyRasterBufferProvider::SetReadyToDrawCallback( // Use the compositor context because we want this callback on the // compositor thread. compositor_context_provider_->ContextSupport()->SignalSyncToken( - latest_sync_token, callback); + latest_sync_token, std::move(callback)); } return callback_id; @@ -404,12 +404,6 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( DCHECK(ri); ri->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData()); - GLuint mailbox_texture_id = ri->CreateAndConsumeTexture( - mailbox_texture_is_overlay_candidate, gfx::BufferUsage::SCANOUT, - resource_format, mailbox->name); - GLuint staging_texture_id = ri->CreateAndConsumeTexture( - true, StagingBufferUsage(), staging_buffer->format, - staging_buffer->mailbox.name); // Do not use queries unless COMMANDS_COMPLETED queries are supported, or // COMMANDS_ISSUED queries are sufficient. @@ -456,8 +450,9 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( int rows_to_copy = std::min(chunk_size_in_rows, height - y); DCHECK_GT(rows_to_copy, 0); - ri->CopySubTexture(staging_texture_id, mailbox_texture_id, 0, y, 0, y, - rect_to_copy.width(), rows_to_copy); + ri->CopySubTexture(staging_buffer->mailbox, *mailbox, + mailbox_texture_target, 0, y, 0, y, rect_to_copy.width(), + rows_to_copy); y += rows_to_copy; // Increment |bytes_scheduled_since_last_flush_| by the amount of memory @@ -473,9 +468,6 @@ gpu::SyncToken OneCopyRasterBufferProvider::CopyOnWorkerThread( if (query_target != GL_NONE) ri->EndQueryEXT(query_target); - GLuint textures_to_delete[] = {mailbox_texture_id, staging_texture_id}; - ri->DeleteTextures(2, textures_to_delete); - // Generate sync token on the worker context that will be sent to and waited // for by the display compositor before using the content generated here. // The same sync token is used to synchronize operations on the staging diff --git a/chromium/cc/raster/one_copy_raster_buffer_provider.h b/chromium/cc/raster/one_copy_raster_buffer_provider.h index 6766cae7a40..c2dec8e7d43 100644 --- a/chromium/cc/raster/one_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/one_copy_raster_buffer_provider.h @@ -55,7 +55,7 @@ class CC_EXPORT OneCopyRasterBufferProvider : public RasterBufferProvider { const ResourcePool::InUsePoolResource& resource) const override; uint64_t SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const override; void Shutdown() override; bool CheckRasterFinishedQueries() override; diff --git a/chromium/cc/raster/paint_worklet_image_provider.cc b/chromium/cc/raster/paint_worklet_image_provider.cc new file mode 100644 index 00000000000..38feceb5ec0 --- /dev/null +++ b/chromium/cc/raster/paint_worklet_image_provider.cc @@ -0,0 +1,25 @@ +// 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/raster/paint_worklet_image_provider.h" + +#include "cc/tiles/paint_worklet_image_cache.h" + +namespace cc { + +PaintWorkletImageProvider::PaintWorkletImageProvider( + PaintWorkletImageCache* cache) + : cache_(cache) { + DCHECK(cache_); +} + +PaintWorkletImageProvider::~PaintWorkletImageProvider() = default; + +PaintWorkletImageProvider::PaintWorkletImageProvider( + PaintWorkletImageProvider&& other) = default; + +PaintWorkletImageProvider& PaintWorkletImageProvider::operator=( + PaintWorkletImageProvider&& other) = default; + +} // namespace cc diff --git a/chromium/cc/raster/paint_worklet_image_provider.h b/chromium/cc/raster/paint_worklet_image_provider.h new file mode 100644 index 00000000000..0712b12ba97 --- /dev/null +++ b/chromium/cc/raster/paint_worklet_image_provider.h @@ -0,0 +1,32 @@ +// 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_RASTER_PAINT_WORKLET_IMAGE_PROVIDER_H_ +#define CC_RASTER_PAINT_WORKLET_IMAGE_PROVIDER_H_ + +#include "cc/cc_export.h" +#include "cc/paint/image_provider.h" + +namespace cc { +class PaintWorkletImageCache; + +// PaintWorkletImageProvider is a bridge between PaintWorkletImageCache and its +// rasterization. +class CC_EXPORT PaintWorkletImageProvider { + public: + explicit PaintWorkletImageProvider(PaintWorkletImageCache* cache); + ~PaintWorkletImageProvider(); + + PaintWorkletImageProvider(PaintWorkletImageProvider&& other); + PaintWorkletImageProvider& operator=(PaintWorkletImageProvider&& other); + + private: + PaintWorkletImageCache* cache_; + + DISALLOW_COPY_AND_ASSIGN(PaintWorkletImageProvider); +}; + +} // namespace cc + +#endif // CC_RASTER_PAINT_WORKLET_IMAGE_PROVIDER_H_ diff --git a/chromium/cc/raster/raster_buffer_provider.h b/chromium/cc/raster/raster_buffer_provider.h index 74354c7aceb..a4755ccfda0 100644 --- a/chromium/cc/raster/raster_buffer_provider.h +++ b/chromium/cc/raster/raster_buffer_provider.h @@ -83,7 +83,7 @@ class CC_EXPORT RasterBufferProvider { // have a pending callback, 0 should be passed for |pending_callback_id|. virtual uint64_t SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Callback<void()>& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const = 0; // Shutdown for doing cleanup. diff --git a/chromium/cc/raster/raster_buffer_provider_perftest.cc b/chromium/cc/raster/raster_buffer_provider_perftest.cc index 63dd9fd95d1..098c5b94db9 100644 --- a/chromium/cc/raster/raster_buffer_provider_perftest.cc +++ b/chromium/cc/raster/raster_buffer_provider_perftest.cc @@ -86,7 +86,7 @@ class PerfContextProvider capabilities_.sync_query = true; raster_context_ = std::make_unique<gpu::raster::RasterImplementationGLES>( - context_gl_.get(), capabilities_); + context_gl_.get()); } // viz::ContextProvider implementation. diff --git a/chromium/cc/raster/raster_buffer_provider_unittest.cc b/chromium/cc/raster/raster_buffer_provider_unittest.cc index 0cbd9467744..3f62b72140c 100644 --- a/chromium/cc/raster/raster_buffer_provider_unittest.cc +++ b/chromium/cc/raster/raster_buffer_provider_unittest.cc @@ -145,8 +145,8 @@ class RasterBufferProviderTest RasterBufferProviderTest() : all_tile_tasks_finished_( base::ThreadTaskRunnerHandle::Get().get(), - base::Bind(&RasterBufferProviderTest::AllTileTasksFinished, - base::Unretained(this))), + base::BindRepeating(&RasterBufferProviderTest::AllTileTasksFinished, + base::Unretained(this))), timeout_seconds_(5), timed_out_(false) {} @@ -322,7 +322,6 @@ class RasterBufferProviderTest std::unique_ptr<RasterBufferProvider> raster_buffer_provider_; viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; SynchronousTaskGraphRunner task_graph_runner_; - base::CancelableClosure timeout_; UniqueNotifier all_tile_tasks_finished_; int timeout_seconds_; bool timed_out_; @@ -410,9 +409,7 @@ TEST_P(RasterBufferProviderTest, ReadyToDrawCallback) { base::RunLoop run_loop; uint64_t callback_id = raster_buffer_provider_->SetReadyToDrawCallback( - array, - base::Bind([](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop), - 0); + array, run_loop.QuitClosure(), 0); if (GetParam() == RASTER_BUFFER_PROVIDER_TYPE_GPU || GetParam() == RASTER_BUFFER_PROVIDER_TYPE_ONE_COPY) @@ -503,9 +500,7 @@ TEST_P(RasterBufferProviderTest, MeasureGpuRasterDuration) { for (const auto& resource : resources_) array.push_back(&resource); uint64_t callback_id = raster_buffer_provider_->SetReadyToDrawCallback( - array, - base::Bind([](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop), - 0); + array, run_loop.QuitClosure(), 0); ASSERT_TRUE(callback_id); run_loop.Run(); diff --git a/chromium/cc/raster/raster_source.cc b/chromium/cc/raster/raster_source.cc index 8f510fadc4c..1ab4da244fa 100644 --- a/chromium/cc/raster/raster_source.cc +++ b/chromium/cc/raster/raster_source.cc @@ -169,17 +169,21 @@ void RasterSource::PlaybackToCanvas( raster_canvas->clear(SK_ColorTRANSPARENT); } - PlaybackToCanvas(raster_canvas, settings.image_provider); + PlaybackToCanvas(raster_canvas, settings.image_provider, + settings.paint_worklet_image_provider); raster_canvas->restore(); } -void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas, - ImageProvider* image_provider) const { +void RasterSource::PlaybackToCanvas( + SkCanvas* raster_canvas, + ImageProvider* image_provider, + PaintWorkletImageProvider* paint_worklet_image_provider) const { // TODO(enne): Temporary CHECK debugging for http://crbug.com/823835 CHECK(display_list_.get()); int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); for (int i = 0; i < repeat_count; ++i) - display_list_->Raster(raster_canvas, image_provider); + display_list_->Raster(raster_canvas, image_provider, + paint_worklet_image_provider); } sk_sp<SkPicture> RasterSource::GetFlattenedPicture() { @@ -189,7 +193,7 @@ sk_sp<SkPicture> RasterSource::GetFlattenedPicture() { SkCanvas* canvas = recorder.beginRecording(size_.width(), size_.height()); if (!size_.IsEmpty()) { canvas->clear(SK_ColorTRANSPARENT); - PlaybackToCanvas(canvas, nullptr); + PlaybackToCanvas(canvas, nullptr, nullptr); } return recorder.finishRecordingAsPicture(); diff --git a/chromium/cc/raster/raster_source.h b/chromium/cc/raster/raster_source.h index 0fa0f86484c..1b8b62384f8 100644 --- a/chromium/cc/raster/raster_source.h +++ b/chromium/cc/raster/raster_source.h @@ -27,6 +27,7 @@ namespace cc { class DisplayItemList; class DrawImage; class ImageProvider; +class PaintWorkletImageProvider; class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { public: @@ -42,6 +43,10 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // The ImageProvider used to replace images during playback. ImageProvider* image_provider = nullptr; + // The PaintWorkletImageProvider is a bridge connecting the playback and the + // paint worklet image cache. + PaintWorkletImageProvider* paint_worklet_image_provider = nullptr; + RasterColorSpace raster_color_space; }; @@ -70,8 +75,10 @@ class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> { // // Note that this should only be called after the image decode controller has // been set, which happens during commit. - virtual void PlaybackToCanvas(SkCanvas* canvas, - ImageProvider* image_provider) const; + virtual void PlaybackToCanvas( + SkCanvas* canvas, + ImageProvider* image_provider, + PaintWorkletImageProvider* paint_worklet_image_provider) const; // Returns whether the given rect at given scale is of solid color in // this raster source, as well as the solid color value. diff --git a/chromium/cc/raster/raster_source_unittest.cc b/chromium/cc/raster/raster_source_unittest.cc index b9100522081..c694083f3ca 100644 --- a/chromium/cc/raster/raster_source_unittest.cc +++ b/chromium/cc/raster/raster_source_unittest.cc @@ -8,9 +8,11 @@ #include <memory> +#include "base/memory/scoped_refptr.h" #include "cc/raster/playback_image_provider.h" #include "cc/test/fake_recording_source.h" #include "cc/test/skia_common.h" +#include "cc/test/test_paint_worklet_input.h" #include "cc/test/test_skcanvas.h" #include "cc/tiles/software_image_decode_cache.h" #include "testing/gtest/include/gtest/gtest.h" @@ -184,6 +186,63 @@ TEST(RasterSourceTest, AnalyzeIsSolidScaled) { } } +TEST(RasterSourceTest, MultiPaintWorkletImages) { + gfx::Size layer_bounds(512, 512); + + std::unique_ptr<FakeRecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); + + scoped_refptr<TestPaintWorkletInput> input1 = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f)); + scoped_refptr<TestPaintWorkletInput> input2 = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(64.0f, 64.0f)); + scoped_refptr<TestPaintWorkletInput> input3 = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100.0f, 100.0f)); + + PaintImage discardable_image[2][2]; + discardable_image[0][0] = CreatePaintWorkletPaintImage(input1); + discardable_image[0][1] = CreatePaintWorkletPaintImage(input2); + discardable_image[1][1] = CreatePaintWorkletPaintImage(input3); + + recording_source->add_draw_image(discardable_image[0][0], gfx::Point(0, 0)); + recording_source->add_draw_image(discardable_image[0][1], gfx::Point(260, 0)); + recording_source->add_draw_image(discardable_image[1][1], + gfx::Point(260, 260)); + recording_source->Rerecord(); + + scoped_refptr<RasterSource> raster = recording_source->CreateRasterSource(); + + // Tile sized iterators. These should find only one image. + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), &images); + EXPECT_EQ(1u, images.size()); + EXPECT_EQ(discardable_image[0][0], images[0]->paint_image()); + } + // Shifted tile sized iterators. These should find only one image. + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256), &images); + EXPECT_EQ(1u, images.size()); + EXPECT_EQ(discardable_image[1][1], images[0]->paint_image()); + } + // Ensure there's no discardable pixel refs in the empty cell + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(0, 256, 256, 256), &images); + EXPECT_EQ(0u, images.size()); + } + // Layer sized iterators. These should find three images. + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512), &images); + EXPECT_EQ(3u, images.size()); + EXPECT_EQ(discardable_image[0][0], images[0]->paint_image()); + EXPECT_EQ(discardable_image[0][1], images[1]->paint_image()); + EXPECT_EQ(discardable_image[1][1], images[2]->paint_image()); + } +} + TEST(RasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) { gfx::Size layer_bounds(512, 512); diff --git a/chromium/cc/raster/single_thread_task_graph_runner.cc b/chromium/cc/raster/single_thread_task_graph_runner.cc index 0bb96a42a42..afb47e818a0 100644 --- a/chromium/cc/raster/single_thread_task_graph_runner.cc +++ b/chromium/cc/raster/single_thread_task_graph_runner.cc @@ -29,7 +29,7 @@ void SingleThreadTaskGraphRunner::Start( const base::SimpleThread::Options& thread_options) { thread_.reset( new base::DelegateSimpleThread(this, thread_name, thread_options)); - thread_->Start(); + thread_->StartAsync(); } void SingleThreadTaskGraphRunner::Shutdown() { diff --git a/chromium/cc/raster/staging_buffer_pool.cc b/chromium/cc/raster/staging_buffer_pool.cc index a02c43e4e98..40ea9367c97 100644 --- a/chromium/cc/raster/staging_buffer_pool.cc +++ b/chromium/cc/raster/staging_buffer_pool.cc @@ -137,7 +137,7 @@ StagingBufferPool::StagingBufferPool( base::BindRepeating(&StagingBufferPool::OnMemoryPressure, weak_ptr_factory_.GetWeakPtr()))); - reduce_memory_usage_callback_ = base::Bind( + reduce_memory_usage_callback_ = base::BindRepeating( &StagingBufferPool::ReduceMemoryUsage, weak_ptr_factory_.GetWeakPtr()); } @@ -404,7 +404,7 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) { // buffers as soon as we find a buffer that has been used since |time|. while (!free_buffers_.empty()) { if (free_buffers_.front()->last_usage > time) - return; + break; destroyed_buffers = true; free_buffers_.front()->DestroyGLResources(ri, sii); @@ -415,7 +415,7 @@ void StagingBufferPool::ReleaseBuffersNotUsedSince(base::TimeTicks time) { while (!busy_buffers_.empty()) { if (busy_buffers_.front()->last_usage > time) - return; + break; destroyed_buffers = true; busy_buffers_.front()->DestroyGLResources(ri, sii); diff --git a/chromium/cc/raster/staging_buffer_pool.h b/chromium/cc/raster/staging_buffer_pool.h index cfd0f3a414c..d3331323d6f 100644 --- a/chromium/cc/raster/staging_buffer_pool.h +++ b/chromium/cc/raster/staging_buffer_pool.h @@ -136,7 +136,7 @@ class CC_EXPORT StagingBufferPool int free_staging_buffer_usage_in_bytes_; const base::TimeDelta staging_buffer_expiration_delay_; bool reduce_memory_usage_pending_; - base::Closure reduce_memory_usage_callback_; + base::RepeatingClosure reduce_memory_usage_callback_; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; diff --git a/chromium/cc/raster/task.h b/chromium/cc/raster/task.h index 66ebc932680..d67cb7ac055 100644 --- a/chromium/cc/raster/task.h +++ b/chromium/cc/raster/task.h @@ -77,6 +77,8 @@ class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> { typedef std::vector<scoped_refptr<Task>> Vector; TaskState& state() { return state_; } + void set_frame_number(int64_t frame_number) { frame_number_ = frame_number; } + int64_t frame_number() { return frame_number_; } // Subclasses should implement this method. RunOnWorkerThread may be called // on any thread, and subclasses are responsible for locking and thread @@ -91,6 +93,7 @@ class CC_EXPORT Task : public base::RefCountedThreadSafe<Task> { private: TaskState state_; + int64_t frame_number_ = -1; }; // A task dependency graph describes the order in which to execute a set diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc index b61b669e57e..8e5eb1cf279 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.cc @@ -225,7 +225,7 @@ bool ZeroCopyRasterBufferProvider::IsResourceReadyToDraw( uint64_t ZeroCopyRasterBufferProvider::SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const { // Zero-copy resources are immediately ready to draw. return 0; diff --git a/chromium/cc/raster/zero_copy_raster_buffer_provider.h b/chromium/cc/raster/zero_copy_raster_buffer_provider.h index 106f7c9bbc7..680d6b02128 100644 --- a/chromium/cc/raster/zero_copy_raster_buffer_provider.h +++ b/chromium/cc/raster/zero_copy_raster_buffer_provider.h @@ -46,7 +46,7 @@ class CC_EXPORT ZeroCopyRasterBufferProvider : public RasterBufferProvider { const ResourcePool::InUsePoolResource& resource) const override; uint64_t SetReadyToDrawCallback( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::Closure& callback, + base::OnceClosure callback, uint64_t pending_callback_id) const override; void Shutdown() override; bool CheckRasterFinishedQueries() override; diff --git a/chromium/cc/scheduler/compositor_timing_history.cc b/chromium/cc/scheduler/compositor_timing_history.cc index e648071a367..affa7ac4ab7 100644 --- a/chromium/cc/scheduler/compositor_timing_history.cc +++ b/chromium/cc/scheduler/compositor_timing_history.cc @@ -9,6 +9,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "cc/debug/rendering_stats_instrumentation.h" @@ -121,12 +122,12 @@ const int kUMADurationBuckets[] = { 2000000, 4000000, 8000000, 16000000, 32000000, }; -#define UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED(name, sample) \ - do { \ - UMA_HISTOGRAM_CUSTOM_ENUMERATION( \ - name "2", sample.InMicroseconds(), \ - std::vector<int>(kUMAVSyncBuckets, \ - kUMAVSyncBuckets + arraysize(kUMAVSyncBuckets))); \ +#define UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED(name, sample) \ + do { \ + UMA_HISTOGRAM_CUSTOM_ENUMERATION( \ + name "2", sample.InMicroseconds(), \ + std::vector<int>(kUMAVSyncBuckets, \ + kUMAVSyncBuckets + base::size(kUMAVSyncBuckets))); \ } while (false) #define UMA_HISTOGRAM_CUSTOM_TIMES_DURATION_SUFFIX(name, suffix, sample) \ @@ -135,7 +136,7 @@ const int kUMADurationBuckets[] = { name "2" suffix, sample.InMicroseconds(), \ std::vector<int>( \ kUMADurationBuckets, \ - kUMADurationBuckets + arraysize(kUMADurationBuckets))); \ + kUMADurationBuckets + base::size(kUMADurationBuckets))); \ } while (false) #define UMA_HISTOGRAM_CUSTOM_TIMES_DURATION(name, sample) \ diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc index 715ecc43ca0..60c8018b8d5 100644 --- a/chromium/cc/scheduler/scheduler_unittest.cc +++ b/chromium/cc/scheduler/scheduler_unittest.cc @@ -227,19 +227,20 @@ class FakeSchedulerClient : public SchedulerClient, bool IsInsideBeginImplFrame() const { return inside_begin_impl_frame_; } - base::Callback<bool(void)> InsideBeginImplFrame(bool state) { - return base::Bind(&FakeSchedulerClient::InsideBeginImplFrameCallback, - base::Unretained(this), state); + base::RepeatingCallback<bool(void)> InsideBeginImplFrame(bool state) { + return base::BindRepeating( + &FakeSchedulerClient::InsideBeginImplFrameCallback, + base::Unretained(this), state); } bool IsCurrentFrame(int last_frame_number) const { return scheduler_->current_frame_number() == last_frame_number; } - base::Callback<bool(void)> FrameHasNotAdvancedCallback() { - return base::Bind(&FakeSchedulerClient::IsCurrentFrame, - base::Unretained(this), - scheduler_->current_frame_number()); + base::RepeatingCallback<bool(void)> FrameHasNotAdvancedCallback() { + return base::BindRepeating(&FakeSchedulerClient::IsCurrentFrame, + base::Unretained(this), + scheduler_->current_frame_number()); } void PushAction(const char* description) { diff --git a/chromium/cc/tiles/checker_image_tracker.cc b/chromium/cc/tiles/checker_image_tracker.cc index ce854bc73a1..2308d922a35 100644 --- a/chromium/cc/tiles/checker_image_tracker.cc +++ b/chromium/cc/tiles/checker_image_tracker.cc @@ -444,8 +444,8 @@ void CheckerImageTracker::ScheduleNextImageDecode() { image_id); ImageController::ImageDecodeRequestId request_id = image_controller_->QueueImageDecode( - draw_image, base::Bind(&CheckerImageTracker::DidFinishImageDecode, - weak_factory_.GetWeakPtr(), image_id)); + draw_image, base::BindOnce(&CheckerImageTracker::DidFinishImageDecode, + weak_factory_.GetWeakPtr(), image_id)); image_id_to_decode_.emplace(image_id, std::make_unique<ScopedDecodeHolder>( image_controller_, request_id)); diff --git a/chromium/cc/tiles/checker_image_tracker_unittest.cc b/chromium/cc/tiles/checker_image_tracker_unittest.cc index c375a591363..44cba670c23 100644 --- a/chromium/cc/tiles/checker_image_tracker_unittest.cc +++ b/chromium/cc/tiles/checker_image_tracker_unittest.cc @@ -50,7 +50,7 @@ class TestImageController : public ImageController { ImageDecodeRequestId QueueImageDecode( const DrawImage& image, - const ImageDecodedCallback& callback) override { + ImageDecodedCallback callback) override { ImageDecodeRequestId request_id = next_image_request_id_++; decoded_images_.push_back(image); @@ -60,8 +60,8 @@ class TestImageController : public ImageController { // Post the callback asynchronously to match the behaviour in // ImageController. worker_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(callback, request_id, ImageDecodeResult::SUCCESS)); + FROM_HERE, base::BindOnce(std::move(callback), request_id, + ImageDecodeResult::SUCCESS)); return request_id; } diff --git a/chromium/cc/tiles/decoded_image_tracker.cc b/chromium/cc/tiles/decoded_image_tracker.cc index ad1b297cfd7..197b749f63e 100644 --- a/chromium/cc/tiles/decoded_image_tracker.cc +++ b/chromium/cc/tiles/decoded_image_tracker.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/tiles/decoded_image_tracker.h" +#include "base/time/default_tick_clock.h" #include "base/trace_event/trace_event.h" namespace cc { @@ -27,7 +28,7 @@ DecodedImageTracker::DecodedImageTracker( scoped_refptr<base::SequencedTaskRunner> task_runner) : image_controller_(controller), task_runner_(std::move(task_runner)), - now_fn_(base::Bind(&base::TimeTicks::Now)), + tick_clock_(base::DefaultTickClock::GetInstance()), weak_ptr_factory_(this) { DCHECK(image_controller_); } @@ -38,7 +39,7 @@ DecodedImageTracker::~DecodedImageTracker() { void DecodedImageTracker::QueueImageDecode( const PaintImage& image, - const base::Callback<void(bool)>& callback) { + base::OnceCallback<void(bool)> callback) { size_t frame_index = PaintImage::kDefaultFrameIndex; TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "DecodedImageTracker::QueueImageDecode", "frame_key", @@ -50,9 +51,9 @@ void DecodedImageTracker::QueueImageDecode( DrawImage draw_image(image, image_bounds, kNone_SkFilterQuality, SkMatrix::I(), frame_index); image_controller_->QueueImageDecode( - draw_image, - base::Bind(&DecodedImageTracker::ImageDecodeFinished, - base::Unretained(this), callback, image.stable_id())); + draw_image, base::BindOnce(&DecodedImageTracker::ImageDecodeFinished, + base::Unretained(this), std::move(callback), + image.stable_id())); } void DecodedImageTracker::UnlockAllImages() { @@ -66,7 +67,7 @@ void DecodedImageTracker::OnImagesUsedInDraw( } void DecodedImageTracker::ImageDecodeFinished( - const base::Callback<void(bool)>& callback, + base::OnceCallback<void(bool)> callback, PaintImage::Id image_id, ImageController::ImageDecodeRequestId request_id, ImageController::ImageDecodeResult result) { @@ -78,13 +79,14 @@ void DecodedImageTracker::ImageDecodeFinished( // decode. locked_images_.erase(image_id); locked_images_.emplace( - image_id, std::make_unique<ImageLock>(this, request_id, now_fn_.Run())); + image_id, + std::make_unique<ImageLock>(this, request_id, tick_clock_->NowTicks())); EnqueueTimeout(); } bool decode_succeeded = result == ImageController::ImageDecodeResult::SUCCESS || result == ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED; - callback.Run(decode_succeeded); + std::move(callback).Run(decode_succeeded); } void DecodedImageTracker::OnTimeoutImages() { @@ -92,7 +94,7 @@ void DecodedImageTracker::OnTimeoutImages() { if (locked_images_.size() == 0) return; - auto now = now_fn_.Run(); + auto now = tick_clock_->NowTicks(); auto timeout = base::TimeDelta::FromMilliseconds(kTimeoutDurationMs); for (auto it = locked_images_.begin(); it != locked_images_.end();) { auto& image = it->second; @@ -115,8 +117,8 @@ void DecodedImageTracker::EnqueueTimeout() { timeout_pending_ = true; task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&DecodedImageTracker::OnTimeoutImages, - weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&DecodedImageTracker::OnTimeoutImages, + weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromMilliseconds(kTimeoutDurationMs)); } diff --git a/chromium/cc/tiles/decoded_image_tracker.h b/chromium/cc/tiles/decoded_image_tracker.h index e16b614e48d..c88bd2b593a 100644 --- a/chromium/cc/tiles/decoded_image_tracker.h +++ b/chromium/cc/tiles/decoded_image_tracker.h @@ -9,6 +9,7 @@ #include <vector> #include "base/bind.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "cc/cc_export.h" #include "cc/tiles/image_controller.h" @@ -34,7 +35,7 @@ class CC_EXPORT DecodedImageTracker { // completion. The callback takes a bool indicating whether the decode was // successful or not. void QueueImageDecode(const PaintImage& image, - const base::Callback<void(bool)>& callback); + base::OnceCallback<void(bool)> callback); // Unlock all locked images - used to respond to memory pressure or // application background. @@ -44,8 +45,9 @@ class CC_EXPORT DecodedImageTracker { // unlock them. void OnImagesUsedInDraw(const std::vector<DrawImage>& draw_images); - using NowFn = base::Callback<base::TimeTicks()>; - void SetNowFunctionForTesting(NowFn now_fn) { now_fn_ = now_fn; } + void SetTickClockForTesting(const base::TickClock* tick_clock) { + tick_clock_ = tick_clock; + } // Test only functions: size_t NumLockedImagesForTesting() const { return locked_images_.size(); } @@ -53,7 +55,7 @@ class CC_EXPORT DecodedImageTracker { private: friend class DecodedImageTrackerTest; - void ImageDecodeFinished(const base::Callback<void(bool)>& callback, + void ImageDecodeFinished(base::OnceCallback<void(bool)> callback, PaintImage::Id image_id, ImageController::ImageDecodeRequestId request_id, ImageController::ImageDecodeResult result); @@ -83,7 +85,7 @@ class CC_EXPORT DecodedImageTracker { scoped_refptr<base::SequencedTaskRunner> task_runner_; // Defaults to base::TimeTicks::Now(), but overrideable for testing. - NowFn now_fn_; + const base::TickClock* tick_clock_; base::WeakPtrFactory<DecodedImageTracker> weak_ptr_factory_; diff --git a/chromium/cc/tiles/decoded_image_tracker_unittest.cc b/chromium/cc/tiles/decoded_image_tracker_unittest.cc index 4049261893f..e481894e866 100644 --- a/chromium/cc/tiles/decoded_image_tracker_unittest.cc +++ b/chromium/cc/tiles/decoded_image_tracker_unittest.cc @@ -32,12 +32,12 @@ class TestImageController : public ImageController { ImageDecodeRequestId QueueImageDecode( const DrawImage& image, - const ImageDecodedCallback& callback) override { + ImageDecodedCallback callback) override { auto id = next_id_++; locked_ids_.insert( std::make_pair(id, SoftwareImageDecodeCache::CacheKey::FromDrawImage( image, kRGBA_8888_SkColorType))); - callback.Run(id, ImageDecodeResult::SUCCESS); + std::move(callback).Run(id, ImageDecodeResult::SUCCESS); return id; } @@ -67,8 +67,8 @@ class DecodedImageTrackerTest : public testing::Test { DecodedImageTrackerTest() : task_runner_(new base::TestMockTimeTaskRunner()), decoded_image_tracker_(&image_controller_, task_runner_) { - decoded_image_tracker_.SetNowFunctionForTesting( - base::Bind(&base::TestMockTimeTaskRunner::NowTicks, task_runner_)); + decoded_image_tracker_.SetTickClockForTesting( + task_runner_->GetMockTickClock()); } TestImageController* image_controller() { return &image_controller_; } @@ -87,8 +87,8 @@ TEST_F(DecodedImageTrackerTest, QueueImageLocksImages) { bool locked = false; decoded_image_tracker()->QueueImageDecode( CreateDiscardablePaintImage(gfx::Size(1, 1)), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(1u, image_controller()->num_locked_images()); } @@ -98,8 +98,8 @@ TEST_F(DecodedImageTrackerTest, ImagesTimeOut) { bool locked = false; decoded_image_tracker()->QueueImageDecode( CreateDiscardablePaintImage(gfx::Size(1, 1)), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(1u, image_controller()->num_locked_images()); @@ -110,8 +110,8 @@ TEST_F(DecodedImageTrackerTest, ImagesTimeOut) { // Add an image, this will not start a new timeout, as one is pending. decoded_image_tracker()->QueueImageDecode( CreateDiscardablePaintImage(gfx::Size(1, 1)), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(2u, image_controller()->num_locked_images()); @@ -131,16 +131,16 @@ TEST_F(DecodedImageTrackerTest, ImageUsedInDraw) { auto paint_image_1 = CreateDiscardablePaintImage(gfx::Size(1, 1)); decoded_image_tracker()->QueueImageDecode( paint_image_1, - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(1u, image_controller()->num_locked_images()); auto paint_image_2 = CreateDiscardablePaintImage(gfx::Size(1, 1)); decoded_image_tracker()->QueueImageDecode( paint_image_2, - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(2u, image_controller()->num_locked_images()); @@ -167,14 +167,14 @@ TEST_F(DecodedImageTrackerTest, UnlockAllImages) { bool locked = false; decoded_image_tracker()->QueueImageDecode( CreateDiscardablePaintImage(gfx::Size(1, 1)), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(1u, image_controller()->num_locked_images()); decoded_image_tracker()->QueueImageDecode( CreateDiscardablePaintImage(gfx::Size(1, 1)), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); + base::BindOnce([](bool* locked, bool success) { *locked = true; }, + base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(2u, image_controller()->num_locked_images()); diff --git a/chromium/cc/tiles/gpu_image_decode_cache.cc b/chromium/cc/tiles/gpu_image_decode_cache.cc index 6e3ae2ba974..18fd0734195 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache.cc @@ -1543,7 +1543,7 @@ void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image, ClientImageTransferCacheEntry image_entry(&pixmap, color_space.get(), image_data->needs_mips); - size_t size = image_entry.SerializedSize(); + uint32_t size = image_entry.SerializedSize(); void* data = context_->ContextSupport()->MapTransferCacheEntry(size); if (data) { bool succeeded = image_entry.Serialize( diff --git a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc index 526c1dd4aaf..5cb51724f89 100644 --- a/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/chromium/cc/tiles/gpu_image_decode_cache_unittest.cc @@ -132,7 +132,7 @@ class FakeGPUImageDecodeTestGLES2Interface : public viz::TestGLES2Interface, void CompleteLockDiscardableTexureOnContextThread( uint32_t texture_id) override {} - void* MapTransferCacheEntry(size_t serialized_size) override { + void* MapTransferCacheEntry(uint32_t serialized_size) override { mapped_entry_size_ = serialized_size; mapped_entry_.reset(new uint8_t[serialized_size]); return mapped_entry_.get(); @@ -2120,7 +2120,8 @@ TEST_P(GpuImageDecodeCacheTest, // image we've cached. EXPECT_TRUE(decoded_image == decoded_draw_image.image()); // Ensure that the SW decoded image had colorspace conversion applied. - EXPECT_TRUE(decoded_image->colorSpace() == target_color_space.get()); + EXPECT_TRUE(SkColorSpace::Equals(decoded_image->colorSpace(), + target_color_space.get())); } cache->DrawWithImageFinished(draw_image, decoded_draw_image); @@ -2169,8 +2170,8 @@ TEST_P(GpuImageDecodeCacheTest, target_color_space.get())); } else { // Ensure that the HW uploaded image had color space conversion applied. - EXPECT_TRUE(decoded_draw_image.image()->colorSpace() == - target_color_space.get()); + EXPECT_TRUE(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(), + target_color_space.get())); } cache->DrawWithImageFinished(draw_image, decoded_draw_image); @@ -2547,12 +2548,6 @@ TEST_P(GpuImageDecodeCacheTest, MipsAddedSubsequentDraw) { } TEST_P(GpuImageDecodeCacheTest, MipsAddedWhileOriginalInUse) { -#if defined(OS_WIN) - // TODO(ericrk): Mips are temporarily disabled to investigate a memory - // regression on Windows. https://crbug.com/867468 - return; -#endif // defined(OS_WIN) - auto cache = CreateCache(); bool is_decomposable = true; auto filter_quality = kMedium_SkFilterQuality; diff --git a/chromium/cc/tiles/image_controller.cc b/chromium/cc/tiles/image_controller.cc index d6a91504c08..844f8c42d65 100644 --- a/chromium/cc/tiles/image_controller.cc +++ b/chromium/cc/tiles/image_controller.cc @@ -29,7 +29,7 @@ ImageController::ImageController( ImageController::~ImageController() { StopWorkerTasks(); for (auto& request : orphaned_decode_requests_) - request.callback.Run(request.id, ImageDecodeResult::FAILURE); + std::move(request.callback).Run(request.id, ImageDecodeResult::FAILURE); } void ImageController::StopWorkerTasks() { @@ -129,6 +129,11 @@ void ImageController::StopWorkerTasks() { image_decode_queue_.clear(); } +void ImageController::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + paint_worklet_image_cache_.SetPaintWorkletLayerPainter(std::move(painter)); +} + void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) { DCHECK(!cache_ || !cache); @@ -147,7 +152,27 @@ void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) { } } -void ImageController::GetTasksForImagesAndRef( +void ImageController::ConvertPaintWorkletImagesToTask( + std::vector<DrawImage>* sync_decoded_images, + std::vector<scoped_refptr<TileTask>>* tasks) { + for (auto it = sync_decoded_images->begin(); + it != sync_decoded_images->end();) { + if (!it->paint_image().IsPaintWorklet()) { + ++it; + continue; + } + scoped_refptr<TileTask> result = + paint_worklet_image_cache_.GetTaskForPaintWorkletImage(*it); + DCHECK(result); + tasks->push_back(std::move(result)); + // Remove it so that there is no need to check whether an image is + // PaintWorklet generated or not in TileManager's + // work_to_schedule->extra_prepaint_images.insert. + it = sync_decoded_images->erase(it); + } +} + +void ImageController::ConvertDataImagesToTasks( std::vector<DrawImage>* sync_decoded_images, std::vector<scoped_refptr<TileTask>>* tasks, bool* has_at_raster_images, @@ -156,6 +181,10 @@ void ImageController::GetTasksForImagesAndRef( *has_at_raster_images = false; for (auto it = sync_decoded_images->begin(); it != sync_decoded_images->end();) { + if (it->paint_image().IsPaintWorklet()) { + ++it; + continue; + } ImageDecodeCache::TaskResult result = cache_->GetTaskForImageAndRef(*it, tracing_info); *has_at_raster_images |= result.IsAtRaster(); @@ -183,8 +212,8 @@ std::vector<scoped_refptr<TileTask>> ImageController::SetPredecodeImages( const ImageDecodeCache::TracingInfo& tracing_info) { std::vector<scoped_refptr<TileTask>> new_tasks; bool has_at_raster_images = false; - GetTasksForImagesAndRef(&images, &new_tasks, &has_at_raster_images, - tracing_info); + ConvertDataImagesToTasks(&images, &new_tasks, &has_at_raster_images, + tracing_info); UnrefImages(predecode_locked_images_); predecode_locked_images_ = std::move(images); return new_tasks; @@ -192,7 +221,7 @@ std::vector<scoped_refptr<TileTask>> ImageController::SetPredecodeImages( ImageController::ImageDecodeRequestId ImageController::QueueImageDecode( const DrawImage& draw_image, - const ImageDecodedCallback& callback) { + ImageDecodedCallback callback) { // We must not receive any image requests if we have no worker. CHECK(worker_task_runner_); @@ -211,8 +240,9 @@ ImageController::ImageDecodeRequestId ImageController::QueueImageDecode( // Schedule the task and signal that there is more work. base::AutoLock hold(lock_); - image_decode_queue_[id] = ImageDecodeRequest( - id, draw_image, callback, std::move(result.task), result.need_unref); + image_decode_queue_[id] = + ImageDecodeRequest(id, draw_image, std::move(callback), + std::move(result.task), result.need_unref); // If this is the only image decode request, schedule a task to run. // Otherwise, the task will be scheduled in the previou task's completion. @@ -239,7 +269,8 @@ void ImageController::UnlockImageDecode(ImageDecodeRequestId id) { void ImageController::ProcessNextImageDecodeOnWorkerThread() { TRACE_EVENT0("cc", "ImageController::ProcessNextImageDecodeOnWorkerThread"); - ImageDecodeRequest decode; + scoped_refptr<TileTask> decode_task; + ImageDecodeRequestId decode_id; { base::AutoLock hold(lock_); @@ -250,8 +281,8 @@ void ImageController::ProcessNextImageDecodeOnWorkerThread() { // Take the next request from the queue. auto decode_it = image_decode_queue_.begin(); DCHECK(decode_it != image_decode_queue_.end()); - decode = std::move(decode_it->second); - image_decode_queue_.erase(decode_it); + decode_task = decode_it->second.task; + decode_id = decode_it->second.id; // Notify that the task will need completion. Note that there are two cases // where we process this. First, we might complete this task as a response @@ -260,7 +291,9 @@ void ImageController::ProcessNextImageDecodeOnWorkerThread() { // (either post task happens after running, or the thread was already joined // which means the task ran). This means that we can put the decode into // |requests_needing_completion_| here before actually running the task. - requests_needing_completion_[decode.id] = decode; + requests_needing_completion_[decode_id] = std::move(decode_it->second); + + image_decode_queue_.erase(decode_it); } // Run the task if we need to run it. If the task state isn't new, then @@ -269,15 +302,15 @@ void ImageController::ProcessNextImageDecodeOnWorkerThread() { // Note that the other tasks's completion will also run first, since the // requests are ordered. So, when we process this task's completion, we // won't actually do anything with the task and simply issue the callback. - if (decode.task && decode.task->state().IsNew()) { - decode.task->state().DidSchedule(); - decode.task->state().DidStart(); - decode.task->RunOnWorkerThread(); - decode.task->state().DidFinish(); + if (decode_task && decode_task->state().IsNew()) { + decode_task->state().DidSchedule(); + decode_task->state().DidStart(); + decode_task->RunOnWorkerThread(); + decode_task->state().DidFinish(); } origin_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ImageController::ImageDecodeCompleted, - weak_ptr_, decode.id)); + weak_ptr_, decode_id)); } void ImageController::ImageDecodeCompleted(ImageDecodeRequestId id) { @@ -328,7 +361,7 @@ void ImageController::ImageDecodeCompleted(ImageDecodeRequestId id) { base::Unretained(this))); // Finally run the requested callback. - callback.Run(id, result); + std::move(callback).Run(id, result); } void ImageController::GenerateTasksForOrphanedRequests() { @@ -364,23 +397,19 @@ ImageController::ImageDecodeRequest::ImageDecodeRequest() = default; ImageController::ImageDecodeRequest::ImageDecodeRequest( ImageDecodeRequestId id, const DrawImage& draw_image, - const ImageDecodedCallback& callback, + ImageDecodedCallback callback, scoped_refptr<TileTask> task, bool need_unref) : id(id), draw_image(draw_image), - callback(callback), + callback(std::move(callback)), task(std::move(task)), need_unref(need_unref) {} ImageController::ImageDecodeRequest::ImageDecodeRequest( ImageDecodeRequest&& other) = default; -ImageController::ImageDecodeRequest::ImageDecodeRequest( - const ImageDecodeRequest& other) = default; ImageController::ImageDecodeRequest::~ImageDecodeRequest() = default; ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest:: operator=(ImageDecodeRequest&& other) = default; -ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest:: -operator=(const ImageDecodeRequest& other) = default; } // namespace cc diff --git a/chromium/cc/tiles/image_controller.h b/chromium/cc/tiles/image_controller.h index b15c6b545ff..d5540106f94 100644 --- a/chromium/cc/tiles/image_controller.h +++ b/chromium/cc/tiles/image_controller.h @@ -20,6 +20,7 @@ #include "cc/paint/draw_image.h" #include "cc/raster/tile_task.h" #include "cc/tiles/image_decode_cache.h" +#include "cc/tiles/paint_worklet_image_cache.h" namespace cc { @@ -29,18 +30,39 @@ class CC_EXPORT ImageController { using ImageDecodeRequestId = uint64_t; using ImageDecodedCallback = - base::Callback<void(ImageDecodeRequestId, ImageDecodeResult)>; + base::OnceCallback<void(ImageDecodeRequestId, ImageDecodeResult)>; explicit ImageController( base::SequencedTaskRunner* origin_task_runner, scoped_refptr<base::SequencedTaskRunner> worker_task_runner); virtual ~ImageController(); void SetImageDecodeCache(ImageDecodeCache* cache); - void GetTasksForImagesAndRef( + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter); + // The name "Data images" are the images that are not generated by + // PaintWorklet. + // Build tile tasks for synchronously decoded images that are not generated by + // PaintWorklet. + // |sync_decoded_images| is the input. These are the images from a particular + // tile, retrieved by the DiscardableImageMap. Images can be removed from the + // vector under certain conditions. + // |tasks| is an output, which are the built tile tasks. + // |has_at_raster_images| is an output parameter. + // |tracing_info| is used in tracing or UMA only. + void ConvertDataImagesToTasks( std::vector<DrawImage>* sync_decoded_images, std::vector<scoped_refptr<TileTask>>* tasks, bool* has_at_raster_images, const ImageDecodeCache::TracingInfo& tracing_info); + // TODO(crbug.com/915566): bundle all tasks into a big TaskBag. + // Build tile tasks for images that are generated by PaintWorklet. + // |sync_decoded_images| is the input, which are the images from a particular + // tile, retrieved by DiscardableImageMap. Images are removed from the vector + // once the tile task is built. + // |tasks| is an output, which are the built tile tasks. + void ConvertPaintWorkletImagesToTask( + std::vector<DrawImage>* sync_decoded_images, + std::vector<scoped_refptr<TileTask>>* tasks); void UnrefImages(const std::vector<DrawImage>& images); void ReduceMemoryUsage(); std::vector<scoped_refptr<TileTask>> SetPredecodeImages( @@ -55,9 +77,8 @@ class CC_EXPORT ImageController { // unlock this image. It is up to the caller to ensure that the image is later // unlocked using UnlockImageDecode. // Virtual for testing. - virtual ImageDecodeRequestId QueueImageDecode( - const DrawImage& draw_image, - const ImageDecodedCallback& callback); + virtual ImageDecodeRequestId QueueImageDecode(const DrawImage& draw_image, + ImageDecodedCallback callback); size_t image_cache_max_limit_bytes() const { return image_cache_max_limit_bytes_; } @@ -67,6 +88,9 @@ class CC_EXPORT ImageController { } ImageDecodeCache* cache() const { return cache_; } + PaintWorkletImageCache* paint_worklet_image_cache() { + return &paint_worklet_image_cache_; + } protected: scoped_refptr<base::SequencedTaskRunner> worker_task_runner_; @@ -76,15 +100,13 @@ class CC_EXPORT ImageController { ImageDecodeRequest(); ImageDecodeRequest(ImageDecodeRequestId id, const DrawImage& draw_image, - const ImageDecodedCallback& callback, + ImageDecodedCallback callback, scoped_refptr<TileTask> task, bool need_unref); ImageDecodeRequest(ImageDecodeRequest&& other); - ImageDecodeRequest(const ImageDecodeRequest& other); ~ImageDecodeRequest(); ImageDecodeRequest& operator=(ImageDecodeRequest&& other); - ImageDecodeRequest& operator=(const ImageDecodeRequest& other); ImageDecodeRequestId id; DrawImage draw_image; @@ -104,6 +126,7 @@ class CC_EXPORT ImageController { base::WeakPtr<ImageController> weak_ptr_; ImageDecodeCache* cache_ = nullptr; + PaintWorkletImageCache paint_worklet_image_cache_; std::vector<DrawImage> predecode_locked_images_; static ImageDecodeRequestId s_next_image_decode_queue_id_; diff --git a/chromium/cc/tiles/image_controller_unittest.cc b/chromium/cc/tiles/image_controller_unittest.cc index 473c7c25d5f..dad3a619c23 100644 --- a/chromium/cc/tiles/image_controller_unittest.cc +++ b/chromium/cc/tiles/image_controller_unittest.cc @@ -15,6 +15,7 @@ #include "cc/paint/paint_image_builder.h" #include "cc/test/skia_common.h" #include "cc/test/stub_decode_cache.h" +#include "cc/test/test_paint_worklet_input.h" #include "cc/tiles/image_decode_cache.h" #include "testing/gtest/include/gtest/gtest.h" @@ -285,6 +286,24 @@ class ImageControllerTest : public testing::Test { void ResetController() { controller_.reset(); } + SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) { + SkMatrix matrix; + matrix.setScale(scale.width(), scale.height()); + + if (!is_decomposable) { + // Perspective is not decomposable, add it. + matrix[SkMatrix::kMPersp0] = 0.1f; + } + + return matrix; + } + + PaintImage CreatePaintImage(int width, int height) { + scoped_refptr<TestPaintWorkletInput> input = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(width, height)); + return CreatePaintWorkletPaintImage(input); + } + private: scoped_refptr<base::SequencedTaskRunner> task_runner_; scoped_refptr<WorkerTaskRunner> worker_task_runner_; @@ -295,6 +314,28 @@ class ImageControllerTest : public testing::Test { base::WeakPtrFactory<ImageControllerTest> weak_ptr_factory_; }; +// Test that GetTasksForImagesAndRef does not generate task for PaintWorklet +// images. +TEST_F(ImageControllerTest, GetTasksForImagesAndRefForPaintWorkletImages) { + std::vector<DrawImage> images(1); + ImageDecodeCache::TracingInfo tracing_info; + + PaintImage paint_image = CreatePaintImage(100, 100); + DrawImage draw_image( + paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), + kNone_SkFilterQuality, CreateMatrix(SkSize::Make(1.f, 1.f), true), + PaintImage::kDefaultFrameIndex); + images[0] = draw_image; + + ASSERT_EQ(1u, images.size()); + + std::vector<scoped_refptr<TileTask>> tasks; + bool has_at_raster_images = false; + controller()->ConvertDataImagesToTasks(&images, &tasks, &has_at_raster_images, + tracing_info); + EXPECT_EQ(tasks.size(), 0u); +} + TEST_F(ImageControllerTest, NullControllerUnrefsImages) { std::vector<DrawImage> images(10); ImageDecodeCache::TracingInfo tracing_info; @@ -315,9 +356,9 @@ TEST_F(ImageControllerTest, QueueImageDecode) { EXPECT_EQ(image().paint_image().width(), 1); ImageController::ImageDecodeRequestId expected_id = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client), - run_loop.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client), + run_loop.QuitClosure())); RunOrTimeout(&run_loop); EXPECT_EQ(expected_id, decode_client.id()); EXPECT_EQ(ImageController::ImageDecodeResult::SUCCESS, @@ -332,9 +373,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeNonLazy) { ImageController::ImageDecodeRequestId expected_id = controller()->QueueImageDecode( - image, - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client), - run_loop.QuitClosure())); + image, base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client), + run_loop.QuitClosure())); RunOrTimeout(&run_loop); EXPECT_EQ(expected_id, decode_client.id()); EXPECT_EQ(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, @@ -348,9 +389,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeTooLarge) { DrawImage image = CreateDiscardableDrawImage(gfx::Size(2000, 2000)); ImageController::ImageDecodeRequestId expected_id = controller()->QueueImageDecode( - image, - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client), - run_loop.QuitClosure())); + image, base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client), + run_loop.QuitClosure())); RunOrTimeout(&run_loop); EXPECT_EQ(expected_id, decode_client.id()); EXPECT_EQ(ImageController::ImageDecodeResult::FAILURE, @@ -362,21 +403,21 @@ TEST_F(ImageControllerTest, QueueImageDecodeMultipleImages) { DecodeClient decode_client1; ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - base::Bind([] {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + base::DoNothing::Once())); DecodeClient decode_client2; ImageController::ImageDecodeRequestId expected_id2 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - base::Bind([] {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client2), + base::DoNothing::Once())); DecodeClient decode_client3; ImageController::ImageDecodeRequestId expected_id3 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client3), - run_loop.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client3), + run_loop.QuitClosure())); RunOrTimeout(&run_loop); EXPECT_EQ(expected_id1, decode_client1.id()); EXPECT_EQ(ImageController::ImageDecodeResult::SUCCESS, @@ -397,9 +438,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeWithTask) { DecodeClient decode_client; ImageController::ImageDecodeRequestId expected_id = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client), - run_loop.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client), + run_loop.QuitClosure())); RunOrTimeout(&run_loop); EXPECT_EQ(expected_id, decode_client.id()); EXPECT_TRUE(task->has_run()); @@ -414,21 +455,21 @@ TEST_F(ImageControllerTest, QueueImageDecodeMultipleImagesSameTask) { DecodeClient decode_client1; ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - base::Bind([] {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + base::DoNothing::Once())); DecodeClient decode_client2; ImageController::ImageDecodeRequestId expected_id2 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - base::Bind([] {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client2), + base::DoNothing::Once())); DecodeClient decode_client3; ImageController::ImageDecodeRequestId expected_id3 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client3), - run_loop.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client3), + run_loop.QuitClosure())); RunOrTimeout(&run_loop); EXPECT_EQ(expected_id1, decode_client1.id()); EXPECT_EQ(ImageController::ImageDecodeResult::SUCCESS, @@ -450,9 +491,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeChangeControllerWithTaskQueued) { DecodeClient decode_client1; ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - base::Bind([] {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + base::DoNothing::Once())); scoped_refptr<BlockingTask> task_two(new BlockingTask); cache()->SetTaskToUse(task_two); @@ -461,9 +502,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeChangeControllerWithTaskQueued) { DecodeClient decode_client2; ImageController::ImageDecodeRequestId expected_id2 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - run_loop.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client2), + run_loop.QuitClosure())); task_one->AllowToRun(); task_two->AllowToRun(); @@ -486,9 +527,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeImageAlreadyLocked) { DecodeClient decode_client1; ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - run_loop1.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + run_loop1.QuitClosure())); RunOrTimeout(&run_loop1); EXPECT_EQ(expected_id1, decode_client1.id()); EXPECT_TRUE(task->has_run()); @@ -498,9 +539,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeImageAlreadyLocked) { DecodeClient decode_client2; ImageController::ImageDecodeRequestId expected_id2 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - run_loop2.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client2), + run_loop2.QuitClosure())); RunOrTimeout(&run_loop2); EXPECT_EQ(expected_id2, decode_client2.id()); EXPECT_EQ(ImageController::ImageDecodeResult::SUCCESS, @@ -515,9 +556,9 @@ TEST_F(ImageControllerTest, QueueImageDecodeLockedImageControllerChange) { DecodeClient decode_client1; ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - run_loop1.QuitClosure())); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + run_loop1.QuitClosure())); RunOrTimeout(&run_loop1); EXPECT_EQ(expected_id1, decode_client1.id()); EXPECT_TRUE(task->has_run()); @@ -538,12 +579,12 @@ TEST_F(ImageControllerTest, DispatchesDecodeCallbacksAfterCacheReset) { controller()->QueueImageDecode( image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - run_loop1.QuitClosure())); + base::BindOnce(&DecodeClient::Callback, base::Unretained(&decode_client1), + run_loop1.QuitClosure())); controller()->QueueImageDecode( image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - run_loop2.QuitClosure())); + base::BindOnce(&DecodeClient::Callback, base::Unretained(&decode_client2), + run_loop2.QuitClosure())); // Now reset the image cache before decode completed callbacks are posted to // the compositor thread. Ensure that the completion callbacks for the decode @@ -571,12 +612,12 @@ TEST_F(ImageControllerTest, DispatchesDecodeCallbacksAfterCacheChanged) { controller()->QueueImageDecode( image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - run_loop1.QuitClosure())); + base::BindOnce(&DecodeClient::Callback, base::Unretained(&decode_client1), + run_loop1.QuitClosure())); controller()->QueueImageDecode( image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - run_loop2.QuitClosure())); + base::BindOnce(&DecodeClient::Callback, base::Unretained(&decode_client2), + run_loop2.QuitClosure())); // Now reset the image cache before decode completed callbacks are posted to // the compositor thread. This should orphan the requests. @@ -615,15 +656,15 @@ TEST_F(ImageControllerTest, QueueImageDecodeLazyCancelImmediately) { ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - base::Bind([]() {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + base::DoNothing::Once())); ImageController::ImageDecodeRequestId expected_id2 = controller()->QueueImageDecode( - image(), - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - base::Bind([]() {}))); + image(), base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client2), + base::DoNothing::Once())); // This needs a ref because it is lazy. EXPECT_EQ(2, cache()->number_of_refs()); @@ -660,14 +701,14 @@ TEST_F(ImageControllerTest, QueueImageDecodeNonLazyCancelImmediately) { ImageController::ImageDecodeRequestId expected_id1 = controller()->QueueImageDecode( - image1, - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), - base::Bind([]() {}))); + image1, base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client1), + base::DoNothing::Once())); ImageController::ImageDecodeRequestId expected_id2 = controller()->QueueImageDecode( - image2, - base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), - base::Bind([]() {}))); + image2, base::BindOnce(&DecodeClient::Callback, + base::Unretained(&decode_client2), + base::DoNothing::Once())); // No ref needed here, because it is non-lazy. EXPECT_EQ(0, cache()->number_of_refs()); diff --git a/chromium/cc/tiles/paint_worklet_image_cache.cc b/chromium/cc/tiles/paint_worklet_image_cache.cc new file mode 100644 index 00000000000..47f7773692c --- /dev/null +++ b/chromium/cc/tiles/paint_worklet_image_cache.cc @@ -0,0 +1,61 @@ +// Copyright 2018 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/tiles/paint_worklet_image_cache.h" +#include "cc/paint/paint_worklet_layer_painter.h" + +namespace cc { + +// TODO(xidachen): Rename this to PaintWorkletTaskImpl. +class PaintWorkletImageCacheImpl : public TileTask { + public: + PaintWorkletImageCacheImpl(PaintWorkletImageCache* cache, + const PaintImage& paint_image) + : TileTask(true), cache_(cache), paint_image_(paint_image) {} + + // Overridden from Task: + void RunOnWorkerThread() override { cache_->PaintImageInTask(paint_image_); } + + // Overridden from TileTask: + void OnTaskCompleted() override {} + + protected: + ~PaintWorkletImageCacheImpl() override = default; + + private: + PaintWorkletImageCache* cache_; + PaintImage paint_image_; + + DISALLOW_COPY_AND_ASSIGN(PaintWorkletImageCacheImpl); +}; + +PaintWorkletImageCache::PaintWorkletImageCache() {} + +PaintWorkletImageCache::~PaintWorkletImageCache() {} + +void PaintWorkletImageCache::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + painter_ = std::move(painter); +} + +scoped_refptr<TileTask> PaintWorkletImageCache::GetTaskForPaintWorkletImage( + const DrawImage& image) { + return base::MakeRefCounted<PaintWorkletImageCacheImpl>(this, + image.paint_image()); +} + +// TODO(xidachen): dispatch the work to a worklet thread, invoke JS callback. +// Do check the cache first. If there is already a cache entry for this input, +// then there is no need to call the Paint() function. +void PaintWorkletImageCache::PaintImageInTask(const PaintImage& paint_image) { + sk_sp<PaintRecord> record = painter_->Paint(); + records_[paint_image.paint_worklet_input()] = record; +} + +PaintRecord* PaintWorkletImageCache::GetPaintRecordForTest( + PaintWorkletInput* input) { + return records_[input].get(); +} + +} // namespace cc diff --git a/chromium/cc/tiles/paint_worklet_image_cache.h b/chromium/cc/tiles/paint_worklet_image_cache.h new file mode 100644 index 00000000000..d857dc3ebeb --- /dev/null +++ b/chromium/cc/tiles/paint_worklet_image_cache.h @@ -0,0 +1,52 @@ +// Copyright 2018 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_TILES_PAINT_WORKLET_IMAGE_CACHE_H_ +#define CC_TILES_PAINT_WORKLET_IMAGE_CACHE_H_ + +#include "base/containers/flat_map.h" +#include "cc/cc_export.h" +#include "cc/paint/draw_image.h" +#include "cc/paint/paint_record.h" +#include "cc/paint/paint_worklet_layer_painter.h" +#include "cc/raster/tile_task.h" +#include "cc/tiles/image_decode_cache.h" + +namespace cc { + +// PaintWorkletImageCache is responsible for generating tasks of executing +// PaintWorklet JS paint callbacks, and being able to return the generated +// results when requested. +class CC_EXPORT PaintWorkletImageCache { + public: + PaintWorkletImageCache(); + + ~PaintWorkletImageCache(); + + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter); + + scoped_refptr<TileTask> GetTaskForPaintWorkletImage(const DrawImage& image); + + void PaintImageInTask(const PaintImage& paint_image); + + PaintRecord* GetPaintRecordForTest(PaintWorkletInput* input); + const base::flat_map<PaintWorkletInput*, sk_sp<PaintRecord>>& + GetRecordsForTest() { + return records_; + } + + private: + // The PaintRecord is produced by PaintWorkletLayerPainter::Paint(), and used + // for raster. + base::flat_map<PaintWorkletInput*, sk_sp<PaintRecord>> records_; + // The PaintWorkletImageCache is owned by ImageController, which has the same + // life time as the LayerTreeHostImpl, that guarantees that the painter will + // live as long as the LayerTreeHostImpl. + std::unique_ptr<PaintWorkletLayerPainter> painter_; +}; + +} // namespace cc + +#endif // CC_TILES_PAINT_WORKLET_IMAGE_CACHE_H_ diff --git a/chromium/cc/tiles/paint_worklet_image_cache_unittest.cc b/chromium/cc/tiles/paint_worklet_image_cache_unittest.cc new file mode 100644 index 00000000000..18355d430b7 --- /dev/null +++ b/chromium/cc/tiles/paint_worklet_image_cache_unittest.cc @@ -0,0 +1,104 @@ +// Copyright 2018 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/tiles/paint_worklet_image_cache.h" + +#include "cc/paint/draw_image.h" +#include "cc/test/skia_common.h" +#include "cc/test/test_paint_worklet_input.h" +#include "cc/test/test_paint_worklet_layer_painter.h" +#include "cc/test/test_tile_task_runner.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +class TestPaintWorkletImageCache : public PaintWorkletImageCache { + public: + TestPaintWorkletImageCache() {} +}; + +SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) { + SkMatrix matrix; + matrix.setScale(scale.width(), scale.height()); + + if (!is_decomposable) { + // Perspective is not decomposable, add it. + matrix[SkMatrix::kMPersp0] = 0.1f; + } + + return matrix; +} + +PaintImage CreatePaintImage(int width, int height) { + scoped_refptr<TestPaintWorkletInput> input = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(width, height)); + return CreatePaintWorkletPaintImage(input); +} + +scoped_refptr<TileTask> GetTaskForPaintWorkletImage( + const PaintImage& paint_image, + TestPaintWorkletImageCache* cache) { + DrawImage draw_image( + paint_image, SkIRect::MakeWH(paint_image.width(), paint_image.height()), + kNone_SkFilterQuality, CreateMatrix(SkSize::Make(1.f, 1.f), true), + PaintImage::kDefaultFrameIndex); + std::unique_ptr<TestPaintWorkletLayerPainter> painter = + std::make_unique<TestPaintWorkletLayerPainter>(); + cache->SetPaintWorkletLayerPainter(std::move(painter)); + return cache->GetTaskForPaintWorkletImage(draw_image); +} + +void TestPaintRecord(PaintRecord* record) { + EXPECT_EQ(record->total_op_count(), 1u); + + // GetOpAtForTesting check whether the type is the same as DrawImageOp or not. + // If not, it returns a nullptr. + auto* paint_op = record->GetOpAtForTesting<DrawImageOp>(0); + EXPECT_TRUE(paint_op); +} + +TEST(PaintWorkletImageCacheTest, GetTaskForImage) { + TestPaintWorkletImageCache cache; + PaintImage paint_image = CreatePaintImage(100, 100); + scoped_refptr<TileTask> task = + GetTaskForPaintWorkletImage(paint_image, &cache); + EXPECT_TRUE(task); + + TestTileTaskRunner::ProcessTask(task.get()); + + PaintRecord* record = + cache.GetPaintRecordForTest(paint_image.paint_worklet_input()); + TestPaintRecord(record); +} + +TEST(PaintWorkletImageCacheTest, MultipleRecordsInCache) { + TestPaintWorkletImageCache cache; + PaintImage paint_image1 = CreatePaintImage(100, 100); + scoped_refptr<TileTask> task1 = + GetTaskForPaintWorkletImage(paint_image1, &cache); + EXPECT_TRUE(task1); + PaintImage paint_image2 = CreatePaintImage(200, 200); + scoped_refptr<TileTask> task2 = + GetTaskForPaintWorkletImage(paint_image2, &cache); + EXPECT_TRUE(task2); + + TestTileTaskRunner::ProcessTask(task1.get()); + TestTileTaskRunner::ProcessTask(task2.get()); + + base::flat_map<PaintWorkletInput*, sk_sp<PaintRecord>> records = + cache.GetRecordsForTest(); + EXPECT_EQ(records.size(), 2u); + + PaintRecord* record1 = records[paint_image1.paint_worklet_input()].get(); + EXPECT_TRUE(record1); + TestPaintRecord(record1); + + PaintRecord* record2 = records[paint_image2.paint_worklet_input()].get(); + EXPECT_TRUE(record2); + TestPaintRecord(record2); +} + +} // namespace +} // namespace cc diff --git a/chromium/cc/tiles/picture_layer_tiling.cc b/chromium/cc/tiles/picture_layer_tiling.cc index c16c0bb291b..d8347eb17ec 100644 --- a/chromium/cc/tiles/picture_layer_tiling.cc +++ b/chromium/cc/tiles/picture_layer_tiling.cc @@ -14,6 +14,7 @@ #include "base/containers/flat_map.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "cc/base/math_util.h" @@ -587,7 +588,7 @@ void PictureLayerTiling::ComputeTilePriorityRects( &visible_rect_in_layer_space, &skewport_in_layer_space, &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space}; gfx::Rect output_rects[4]; - for (size_t i = 0; i < arraysize(input_rects); ++i) + for (size_t i = 0; i < base::size(input_rects); ++i) output_rects[i] = EnclosingContentsRectFromLayerRect(*input_rects[i]); // Make sure the eventually rect is aligned to tile bounds. output_rects[3] = diff --git a/chromium/cc/tiles/picture_layer_tiling_unittest.cc b/chromium/cc/tiles/picture_layer_tiling_unittest.cc index 7931cbb31e4..4a98325ef56 100644 --- a/chromium/cc/tiles/picture_layer_tiling_unittest.cc +++ b/chromium/cc/tiles/picture_layer_tiling_unittest.cc @@ -86,6 +86,9 @@ class TestablePictureLayerTiling : public PictureLayerTiling { class PictureLayerTilingIteratorTest : public testing::Test { public: + using VerifyTilesCallback = + base::RepeatingCallback<void(Tile* tile, const gfx::Rect& geometry_rect)>; + PictureLayerTilingIteratorTest() = default; ~PictureLayerTilingIteratorTest() override = default; @@ -183,27 +186,19 @@ class PictureLayerTilingIteratorTest : public testing::Test { VerifyTilesExactlyCoverRect(rect_scale, rect, rect); } - void VerifyTiles( - float rect_scale, - const gfx::Rect& rect, - base::Callback<void(Tile* tile, - const gfx::Rect& geometry_rect)> callback) { - VerifyTiles(tiling_.get(), - rect_scale, - rect, - callback); + void VerifyTiles(float rect_scale, + const gfx::Rect& rect, + VerifyTilesCallback callback) { + VerifyTiles(tiling_.get(), rect_scale, rect, callback); } - void VerifyTiles( - PictureLayerTiling* tiling, - float rect_scale, - const gfx::Rect& rect, - base::Callback<void(Tile* tile, - const gfx::Rect& geometry_rect)> callback) { + void VerifyTiles(PictureLayerTiling* tiling, + float rect_scale, + const gfx::Rect& rect, + VerifyTilesCallback callback) { Region remaining = rect; for (PictureLayerTiling::CoverageIterator iter(tiling, rect_scale, rect); - iter; - ++iter) { + iter; ++iter) { remaining.Subtract(iter.geometry_rect()); callback.Run(*iter, iter.geometry_rect()); } @@ -676,7 +671,8 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExist) { gfx::Size layer_bounds(1099, 801); Initialize(gfx::Size(100, 100), 1.f, layer_bounds); VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds)); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, false)); tiling_->ComputeTilePriorityRects( gfx::Rect(layer_bounds), // visible rect @@ -685,19 +681,22 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExist) { gfx::Rect(layer_bounds), // eventually rect 1.f, // current contents scale Occlusion()); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, true)); // Make the viewport rect empty. All tiles are killed and become zombies. tiling_->ComputeTilePriorityRects(gfx::Rect(), gfx::Rect(), gfx::Rect(), gfx::Rect(), 1.f, Occlusion()); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, false)); } TEST_F(PictureLayerTilingIteratorTest, TilesExistGiantViewport) { gfx::Size layer_bounds(1099, 801); Initialize(gfx::Size(100, 100), 1.f, layer_bounds); VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds)); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, false)); gfx::Rect giant_rect(-10000000, -10000000, 1000000000, 1000000000); @@ -708,19 +707,22 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExistGiantViewport) { gfx::Rect(layer_bounds), // eventually rect 1.f, // current contents scale Occlusion()); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, true)); // If the visible content rect is huge, we should still have live tiles. tiling_->ComputeTilePriorityRects(giant_rect, giant_rect, giant_rect, giant_rect, 1.f, Occlusion()); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, true)); } TEST_F(PictureLayerTilingIteratorTest, TilesExistOutsideViewport) { gfx::Size layer_bounds(1099, 801); Initialize(gfx::Size(100, 100), 1.f, layer_bounds); VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds)); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, false)); // This rect does not intersect with the layer, as the layer is outside the // viewport. @@ -733,7 +735,8 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExistOutsideViewport) { -settings.tiling_interest_area_padding); tiling_->ComputeTilePriorityRects(viewport_rect, viewport_rect, viewport_rect, eventually_rect, 1.f, Occlusion()); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, true)); } static void TilesIntersectingRectExist(const gfx::Rect& rect, @@ -760,7 +763,8 @@ TEST_F(PictureLayerTilingIteratorTest, PENDING_TREE, gfx::AxisTransform2d(), raster_source, &client_, settings); tiling_->set_resolution(HIGH_RESOLUTION); VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds)); - VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); + VerifyTiles(1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TileExists, false)); gfx::Rect visible_rect(8000, 8000, 50, 50); @@ -770,9 +774,9 @@ TEST_F(PictureLayerTilingIteratorTest, visible_rect, // eventually rect 1.f, // current contents scale Occlusion()); - VerifyTiles(1.f, - gfx::Rect(layer_bounds), - base::Bind(&TilesIntersectingRectExist, visible_rect, true)); + VerifyTiles( + 1.f, gfx::Rect(layer_bounds), + base::BindRepeating(&TilesIntersectingRectExist, visible_rect, true)); } TEST(ComputeTilePriorityRectsTest, VisibleTiles) { @@ -1116,7 +1120,7 @@ TEST_F(PictureLayerTilingIteratorTest, UseLeastTilesToCover) { ASSERT_TRUE(tiling_->tiling_data()->TexelExtent(1, 1).Contains(overlaped)); VerifyTilesExactlyCoverRect(2.f, gfx::Rect(199, 199)); VerifyTiles(2.f, gfx::Rect(199, 199), - base::Bind(&TileHasGeometryRect, gfx::Rect(199, 199))); + base::BindRepeating(&TileHasGeometryRect, gfx::Rect(199, 199))); } TEST_F(PictureLayerTilingIteratorTest, UseLeastTilesToCover2) { @@ -1130,7 +1134,8 @@ TEST_F(PictureLayerTilingIteratorTest, UseLeastTilesToCover2) { ASSERT_TRUE(tiling_->tiling_data()->TexelExtent(1, 2).Contains(overlaped)); gfx::Rect dest_rect(197, 393, 198, 198); VerifyTilesExactlyCoverRect(2.f, dest_rect); - VerifyTiles(2.f, dest_rect, base::Bind(&TileHasGeometryRect, dest_rect)); + VerifyTiles(2.f, dest_rect, + base::BindRepeating(&TileHasGeometryRect, dest_rect)); } TEST_F(PictureLayerTilingIteratorTest, TightCover) { diff --git a/chromium/cc/tiles/tile_manager.cc b/chromium/cc/tiles/tile_manager.cc index 48e78c00e11..6970e507093 100644 --- a/chromium/cc/tiles/tile_manager.cc +++ b/chromium/cc/tiles/tile_manager.cc @@ -24,6 +24,7 @@ #include "cc/base/devtools_instrumentation.h" #include "cc/base/histograms.h" #include "cc/layers/picture_layer_impl.h" +#include "cc/raster/paint_worklet_image_provider.h" #include "cc/raster/playback_image_provider.h" #include "cc/raster/raster_buffer.h" #include "cc/raster/task_category.h" @@ -85,6 +86,7 @@ class RasterTaskImpl : public TileTask { TileTask::Vector* dependencies, bool is_gpu_rasterization, PlaybackImageProvider image_provider, + PaintWorkletImageProvider paint_worklet_image_provider, GURL url) : TileTask(!is_gpu_rasterization, dependencies), tile_manager_(tile_manager), @@ -104,9 +106,12 @@ class RasterTaskImpl : public TileTask { is_gpu_rasterization_(is_gpu_rasterization), raster_buffer_(std::move(raster_buffer)), image_provider_(std::move(image_provider)), + paint_worklet_image_provider_(std::move(paint_worklet_image_provider)), url_(std::move(url)) { DCHECK(origin_thread_checker_.CalledOnValidThread()); playback_settings_.image_provider = &image_provider_; + playback_settings_.paint_worklet_image_provider = + &paint_worklet_image_provider_; } // Overridden from Task: @@ -173,6 +178,7 @@ class RasterTaskImpl : public TileTask { bool is_gpu_rasterization_; std::unique_ptr<RasterBuffer> raster_buffer_; PlaybackImageProvider image_provider_; + PaintWorkletImageProvider paint_worklet_image_provider_; GURL url_; DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl); @@ -298,10 +304,11 @@ class TaskSetFinishedTaskImpl : public TileTask { public: explicit TaskSetFinishedTaskImpl( base::SequencedTaskRunner* task_runner, - const base::Closure& on_task_set_finished_callback) + base::RepeatingClosure on_task_set_finished_callback) : TileTask(true), task_runner_(task_runner), - on_task_set_finished_callback_(on_task_set_finished_callback) {} + on_task_set_finished_callback_( + std::move(on_task_set_finished_callback)) {} // Overridden from Task: void RunOnWorkerThread() override { @@ -321,7 +328,7 @@ class TaskSetFinishedTaskImpl : public TileTask { private: base::SequencedTaskRunner* task_runner_; - const base::Closure on_task_set_finished_callback_; + const base::RepeatingClosure on_task_set_finished_callback_; DISALLOW_COPY_AND_ASSIGN(TaskSetFinishedTaskImpl); }; @@ -397,11 +404,12 @@ TileManager::TileManager( tile_manager_settings_.min_image_bytes_to_checker), more_tiles_need_prepare_check_notifier_( task_runner_, - base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, - base::Unretained(this))), - signals_check_notifier_(task_runner_, - base::Bind(&TileManager::FlushAndIssueSignals, - base::Unretained(this))), + base::BindRepeating(&TileManager::CheckIfMoreTilesNeedToBePrepared, + base::Unretained(this))), + signals_check_notifier_( + task_runner_, + base::BindRepeating(&TileManager::FlushAndIssueSignals, + base::Unretained(this))), has_scheduled_tile_tasks_(false), prepare_tiles_count_(0u), next_tile_id_(0u), @@ -997,6 +1005,7 @@ void TileManager::ScheduleTasks(PrioritizedWorkToSchedule work_to_schedule) { DCHECK(tile->HasRasterTask()); TileTask* task = tile->raster_task_.get(); + task->set_frame_number(tile->source_frame_number()); DCHECK(!task->HasCompleted()); @@ -1177,8 +1186,10 @@ scoped_refptr<TileTask> TileManager::CreateRasterTask( prepare_tiles_count_, prioritized_tile.priority().priority_bin, ImageDecodeCache::TaskType::kInRaster); bool has_at_raster_images = false; - image_controller_.GetTasksForImagesAndRef( + image_controller_.ConvertDataImagesToTasks( &sync_decoded_images, &decode_tasks, &has_at_raster_images, tracing_info); + image_controller_.ConvertPaintWorkletImagesToTask(&sync_decoded_images, + &decode_tasks); // Notify |decoded_image_tracker_| after |image_controller_| to ensure we've // taken new refs on the images before releasing the predecode API refs. decoded_image_tracker_.OnImagesUsedInDraw(sync_decoded_images); @@ -1233,12 +1244,16 @@ scoped_refptr<TileTask> TileManager::CreateRasterTask( std::move(settings)); playback_settings.raster_color_space = raster_color_space; + + PaintWorkletImageProvider paint_worklet_image_provider( + image_controller_.paint_worklet_image_cache()); + return base::MakeRefCounted<RasterTaskImpl>( this, tile, std::move(resource), prioritized_tile.raster_source(), playback_settings, prioritized_tile.priority().resolution, invalidated_rect, prepare_tiles_count_, std::move(raster_buffer), &decode_tasks, use_gpu_rasterization_, std::move(image_provider), - active_url_); + std::move(paint_worklet_image_provider), active_url_); } void TileManager::ResetSignalsForTesting() { @@ -1384,7 +1399,7 @@ void TileManager::ScheduleCheckRasterFinishedQueries() { if (!check_pending_tile_queries_callback_.IsCancelled()) return; - check_pending_tile_queries_callback_.Reset(base::Bind( + check_pending_tile_queries_callback_.Reset(base::BindOnce( &TileManager::CheckRasterFinishedQueries, base::Unretained(this))); task_runner_->PostDelayedTask(FROM_HERE, check_pending_tile_queries_callback_.callback(), @@ -1647,8 +1662,9 @@ void TileManager::CheckPendingGpuWorkAndIssueSignals() { pending_required_for_activation_callback_id_ = raster_buffer_provider_->SetReadyToDrawCallback( required_for_activation, - base::Bind(&TileManager::CheckPendingGpuWorkAndIssueSignals, - ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()), + base::BindOnce( + &TileManager::CheckPendingGpuWorkAndIssueSignals, + ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()), pending_required_for_activation_callback_id_); } @@ -1658,8 +1674,9 @@ void TileManager::CheckPendingGpuWorkAndIssueSignals() { pending_required_for_draw_callback_id_ = raster_buffer_provider_->SetReadyToDrawCallback( required_for_draw, - base::Bind(&TileManager::CheckPendingGpuWorkAndIssueSignals, - ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()), + base::BindOnce( + &TileManager::CheckPendingGpuWorkAndIssueSignals, + ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()), pending_required_for_draw_callback_id_); } @@ -1681,7 +1698,8 @@ scoped_refptr<TileTask> TileManager::CreateTaskSetFinishedTask( void (TileManager::*callback)()) { return base::MakeRefCounted<TaskSetFinishedTaskImpl>( task_runner_, - base::Bind(callback, task_set_finished_weak_ptr_factory_.GetWeakPtr())); + base::BindRepeating(callback, + task_set_finished_weak_ptr_factory_.GetWeakPtr())); } std::unique_ptr<base::trace_event::ConvertableToTraceFormat> @@ -1691,6 +1709,11 @@ TileManager::ActivationStateAsValue() { return std::move(state); } +void TileManager::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + image_controller_.SetPaintWorkletLayerPainter(std::move(painter)); +} + void TileManager::ActivationStateAsValueInto( base::trace_event::TracedValue* state) { state->SetString("tree_priority", diff --git a/chromium/cc/tiles/tile_manager.h b/chromium/cc/tiles/tile_manager.h index ac58ccfdc99..244eea4c6f2 100644 --- a/chromium/cc/tiles/tile_manager.h +++ b/chromium/cc/tiles/tile_manager.h @@ -292,6 +292,9 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { void set_active_url(const GURL& url) { active_url_ = url; } + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter); + protected: friend class Tile; // Must be called by tile during destruction. @@ -459,7 +462,7 @@ class CC_EXPORT TileManager : CheckerImageTrackerClient { // The callback scheduled to poll whether the GPU side work for pending tiles // has completed. bool has_pending_queries_ = false; - base::CancelableClosure check_pending_tile_queries_callback_; + base::CancelableOnceClosure check_pending_tile_queries_callback_; // We need two WeakPtrFactory objects as the invalidation pattern of each is // different. The |task_set_finished_weak_ptr_factory_| is invalidated any diff --git a/chromium/cc/tiles/tile_manager_perftest.cc b/chromium/cc/tiles/tile_manager_perftest.cc index 8842bc326a6..8a875845f9b 100644 --- a/chromium/cc/tiles/tile_manager_perftest.cc +++ b/chromium/cc/tiles/tile_manager_perftest.cc @@ -7,6 +7,7 @@ #include "base/lazy_instance.h" #include "base/location.h" +#include "base/stl_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "cc/base/lap_timer.h" @@ -80,7 +81,7 @@ class TileManagerPerfTest : public TestLayerTreeHostBase { std::unique_ptr<RasterTilePriorityQueue> queue( host_impl()->BuildRasterQueue(priorities[priority_count], RasterTilePriorityQueue::Type::ALL)); - priority_count = (priority_count + 1) % arraysize(priorities); + priority_count = (priority_count + 1) % base::size(priorities); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -115,7 +116,7 @@ class TileManagerPerfTest : public TestLayerTreeHostBase { ASSERT_TRUE(queue->Top().tile()); queue->Pop(); } - priority_count = (priority_count + 1) % arraysize(priorities); + priority_count = (priority_count + 1) % base::size(priorities); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -148,7 +149,7 @@ class TileManagerPerfTest : public TestLayerTreeHostBase { do { std::unique_ptr<EvictionTilePriorityQueue> queue( host_impl()->BuildEvictionQueue(priorities[priority_count])); - priority_count = (priority_count + 1) % arraysize(priorities); + priority_count = (priority_count + 1) % base::size(priorities); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -188,7 +189,7 @@ class TileManagerPerfTest : public TestLayerTreeHostBase { ASSERT_TRUE(queue->Top().tile()); queue->Pop(); } - priority_count = (priority_count + 1) % arraysize(priorities); + priority_count = (priority_count + 1) % base::size(priorities); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); diff --git a/chromium/cc/tiles/tile_manager_unittest.cc b/chromium/cc/tiles/tile_manager_unittest.cc index 7fbe4f370dd..d1d8105d1ae 100644 --- a/chromium/cc/tiles/tile_manager_unittest.cc +++ b/chromium/cc/tiles/tile_manager_unittest.cc @@ -1746,7 +1746,7 @@ TEST_F(PixelInspectTileManagerTest, LowResHasNoImage) { gfx::Size size(10, 12); TileResolution resolutions[] = {HIGH_RESOLUTION, LOW_RESOLUTION}; - for (size_t i = 0; i < arraysize(resolutions); ++i) { + for (size_t i = 0; i < base::size(resolutions); ++i) { SCOPED_TRACE(resolutions[i]); // Make a RasterSource that will draw a blue bitmap image. @@ -2265,7 +2265,7 @@ class MockReadyToDrawRasterBufferProviderImpl SetReadyToDrawCallback, uint64_t( const std::vector<const ResourcePool::InUsePoolResource*>& resources, - const base::RepeatingClosure& callback, + base::OnceClosure callback, uint64_t pending_callback_id)); std::unique_ptr<RasterBuffer> AcquireBufferForRaster( @@ -2369,7 +2369,7 @@ TEST_F(TileManagerReadyToDrawTest, SmoothActivationWaitsOnCallback) { host_impl()->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY); SetupTreesWithPendingTreeTiles(); - base::RepeatingClosure callback; + base::OnceClosure callback; { base::RunLoop run_loop; @@ -2380,16 +2380,15 @@ TEST_F(TileManagerReadyToDrawTest, SmoothActivationWaitsOnCallback) { .WillRepeatedly(Return(false)); EXPECT_CALL(*mock_raster_buffer_provider(), SetReadyToDrawCallback(_, _, 0)) - .WillOnce(testing::Invoke( - [&run_loop, &callback]( - const std::vector<const ResourcePool::InUsePoolResource*>& - resources, - const base::RepeatingClosure& callback_in, - uint64_t pending_callback_id) { - callback = callback_in; - run_loop.Quit(); - return 1; - })); + .WillOnce([&run_loop, &callback]( + const std::vector<const ResourcePool::InUsePoolResource*>& + resources, + base::OnceClosure callback_in, + uint64_t pending_callback_id) { + callback = std::move(callback_in); + run_loop.Quit(); + return 1; + }); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); run_loop.Run(); } @@ -2404,7 +2403,7 @@ TEST_F(TileManagerReadyToDrawTest, SmoothActivationWaitsOnCallback) { EXPECT_CALL(*mock_raster_buffer_provider(), IsResourceReadyToDraw(testing::_)) .WillRepeatedly(Return(true)); - callback.Run(); + std::move(callback).Run(); run_loop.Run(); } @@ -2432,7 +2431,7 @@ TEST_F(TileManagerReadyToDrawTest, SmoothDrawWaitsOnCallback) { host_impl()->SetTreePriority(SMOOTHNESS_TAKES_PRIORITY); SetupTreesWithActiveTreeTiles(); - base::RepeatingClosure callback; + base::OnceClosure callback; { base::RunLoop run_loop; @@ -2443,16 +2442,15 @@ TEST_F(TileManagerReadyToDrawTest, SmoothDrawWaitsOnCallback) { .WillRepeatedly(Return(false)); EXPECT_CALL(*mock_raster_buffer_provider(), SetReadyToDrawCallback(_, _, 0)) - .WillOnce(Invoke( - [&run_loop, &callback]( - const std::vector<const ResourcePool::InUsePoolResource*>& - resources, - const base::RepeatingClosure& callback_in, - uint64_t pending_callback_id) { - callback = callback_in; - run_loop.Quit(); - return 1; - })); + .WillOnce([&run_loop, &callback]( + const std::vector<const ResourcePool::InUsePoolResource*>& + resources, + base::OnceClosure callback_in, + uint64_t pending_callback_id) { + callback = std::move(callback_in); + run_loop.Quit(); + return 1; + }); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); run_loop.Run(); } @@ -2467,7 +2465,7 @@ TEST_F(TileManagerReadyToDrawTest, SmoothDrawWaitsOnCallback) { EXPECT_CALL(*mock_raster_buffer_provider(), IsResourceReadyToDraw(testing::_)) .WillRepeatedly(Return(true)); - callback.Run(); + std::move(callback).Run(); run_loop.Run(); } @@ -2633,21 +2631,20 @@ TEST_F(TileManagerReadyToDrawTest, ReadyToDrawRespectsRequirementChange) { EXPECT_CALL(*mock_raster_buffer_provider(), IsResourceReadyToDraw(testing::_)) .WillRepeatedly(Return(false)); - base::RepeatingClosure callback; + base::OnceClosure callback; { base::RunLoop run_loop; EXPECT_CALL(*mock_raster_buffer_provider(), SetReadyToDrawCallback(_, _, 0)) - .WillOnce(testing::Invoke( - [&run_loop, &callback]( - const std::vector<const ResourcePool::InUsePoolResource*>& - resources, - const base::RepeatingClosure& callback_in, - uint64_t pending_callback_id) { - callback = callback_in; - run_loop.Quit(); - return 1; - })); + .WillOnce([&run_loop, &callback]( + const std::vector<const ResourcePool::InUsePoolResource*>& + resources, + base::OnceClosure callback_in, + uint64_t pending_callback_id) { + callback = std::move(callback_in); + run_loop.Quit(); + return 1; + }); host_impl()->tile_manager()->DidModifyTilePriorities(); host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); run_loop.Run(); diff --git a/chromium/cc/trees/damage_tracker_unittest.cc b/chromium/cc/trees/damage_tracker_unittest.cc index 03d1e971600..a96cc8c979a 100644 --- a/chromium/cc/trees/damage_tracker_unittest.cc +++ b/chromium/cc/trees/damage_tracker_unittest.cc @@ -73,7 +73,6 @@ class DamageTrackerTest : public testing::Test { std::unique_ptr<LayerImpl> root = LayerImpl::Create(host_impl_.active_tree(), 1); - root->SetPosition(gfx::PointF()); root->SetBounds(gfx::Size(500, 500)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; @@ -81,7 +80,7 @@ class DamageTrackerTest : public testing::Test { for (int i = 0; i < number_of_children; ++i) { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl_.active_tree(), 2 + i); - child->SetPosition(gfx::PointF(100.f, 100.f)); + child->test_properties()->position = gfx::PointF(100.f, 100.f); child->SetBounds(gfx::Size(30, 30)); child->SetDrawsContent(true); root->test_properties()->AddChild(std::move(child)); @@ -109,12 +108,11 @@ class DamageTrackerTest : public testing::Test { std::unique_ptr<LayerImpl> grand_child2 = LayerImpl::Create(host_impl_.active_tree(), 5); - root->SetPosition(gfx::PointF()); root->SetBounds(gfx::Size(500, 500)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; - child1->SetPosition(gfx::PointF(100.f, 100.f)); + child1->test_properties()->position = gfx::PointF(100.f, 100.f); child1->SetBounds(gfx::Size(30, 30)); // With a child that draws_content, opacity will cause the layer to create // its own RenderSurface. This layer does not draw, but is intended to @@ -122,15 +120,15 @@ class DamageTrackerTest : public testing::Test { child1->SetDrawsContent(false); child1->test_properties()->force_render_surface = true; - child2->SetPosition(gfx::PointF(11.f, 11.f)); + child2->test_properties()->position = gfx::PointF(11.f, 11.f); child2->SetBounds(gfx::Size(18, 18)); child2->SetDrawsContent(true); - grand_child1->SetPosition(gfx::PointF(200.f, 200.f)); + grand_child1->test_properties()->position = gfx::PointF(200.f, 200.f); grand_child1->SetBounds(gfx::Size(6, 8)); grand_child1->SetDrawsContent(true); - grand_child2->SetPosition(gfx::PointF(190.f, 190.f)); + grand_child2->test_properties()->position = gfx::PointF(190.f, 190.f); grand_child2->SetBounds(gfx::Size(6, 8)); grand_child2->SetDrawsContent(true); @@ -582,7 +580,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForTransformedLayer) { ClearDamageForAllSurfaces(root); child->test_properties()->transform_origin = gfx::Point3F( child->bounds().width() * 0.5f, child->bounds().height() * 0.5f, 0.f); - child->SetPosition(gfx::PointF(85.f, 85.f)); + child->test_properties()->position = gfx::PointF(85.f, 85.f); child->NoteLayerPropertyChanged(); root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); @@ -653,7 +651,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { transform.Translate3d(-50.0, -50.0, 0.0); // Set up the child - child->SetPosition(gfx::PointF(0.f, 0.f)); + child->test_properties()->position = gfx::PointF(0.f, 0.f); child->SetBounds(gfx::Size(100, 100)); child->test_properties()->transform = transform; root->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -661,7 +659,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForPerspectiveClippedLayer) { // Sanity check that the child layer's bounds would actually get clipped by // w < 0, otherwise this test is not actually testing the intended scenario. - gfx::RectF test_rect(child->position(), gfx::SizeF(child->bounds())); + gfx::RectF test_rect(child->test_properties()->position, + gfx::SizeF(child->bounds())); bool clipped = false; MathUtil::MapQuad(transform, gfx::QuadF(test_rect), &clipped); EXPECT_TRUE(clipped); @@ -1057,7 +1056,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForBackdropBlurredChild) { // to get expanded. We position child1 so that an expansion of the empty rect // would have non-empty intersection with child1 in its target space (root // space). - child1->SetPosition(gfx::PointF()); + child1->test_properties()->position = gfx::PointF(); root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); @@ -1082,7 +1081,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) { { std::unique_ptr<LayerImpl> child2 = LayerImpl::Create(host_impl_.active_tree(), 3); - child2->SetPosition(gfx::PointF(400.f, 380.f)); + child2->test_properties()->position = gfx::PointF(400.f, 380.f); child2->SetBounds(gfx::Size(6, 8)); child2->SetDrawsContent(true); root->test_properties()->AddChild(std::move(child2)); @@ -1140,7 +1139,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForNewUnchangedLayer) { { std::unique_ptr<LayerImpl> child2 = LayerImpl::Create(host_impl_.active_tree(), 3); - child2->SetPosition(gfx::PointF(400.f, 380.f)); + child2->test_properties()->position = gfx::PointF(400.f, 380.f); child2->SetBounds(gfx::Size(6, 8)); child2->SetDrawsContent(true); root->test_properties()->AddChild(std::move(child2)); @@ -1179,7 +1178,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMultipleLayers) { { std::unique_ptr<LayerImpl> child2 = LayerImpl::Create(host_impl_.active_tree(), 3); - child2->SetPosition(gfx::PointF(400.f, 380.f)); + child2->test_properties()->position = gfx::PointF(400.f, 380.f); child2->SetBounds(gfx::Size(6, 8)); child2->SetDrawsContent(true); root->test_properties()->AddChild(std::move(child2)); @@ -1290,7 +1289,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForSurfaceChangeFromDescendantLayer) { gfx::Rect root_damage_rect; ClearDamageForAllSurfaces(root); - grand_child1->SetPosition(gfx::PointF(195.f, 205.f)); + grand_child1->test_properties()->position = gfx::PointF(195.f, 205.f); root->layer_tree_impl()->property_trees()->needs_rebuild = true; EmulateDrawingOneFrame(root); EXPECT_TRUE(GetRenderSurface(child1)->damage_tracker()->GetDamageRectIfValid( @@ -1501,7 +1500,8 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { { std::unique_ptr<LayerImpl> mask_layer = LayerImpl::Create(host_impl_.active_tree(), 3); - mask_layer->SetPosition(child->position()); + mask_layer->test_properties()->position = + child->test_properties()->position; mask_layer->SetBounds(child->bounds()); child->test_properties()->SetMaskLayer(std::move(mask_layer)); child->test_properties()->force_render_surface = true; @@ -1513,7 +1513,7 @@ TEST_F(DamageTrackerTest, VerifyDamageForMask) { { std::unique_ptr<LayerImpl> grand_child = LayerImpl::Create(host_impl_.active_tree(), 4); - grand_child->SetPosition(gfx::PointF(2.f, 2.f)); + grand_child->test_properties()->position = gfx::PointF(2.f, 2.f); grand_child->SetBounds(gfx::Size(2, 2)); grand_child->SetDrawsContent(true); child->test_properties()->AddChild(std::move(grand_child)); @@ -1730,7 +1730,6 @@ TEST_F(DamageTrackerTest, HugeDamageRect) { // The child layer covers (0, 0, i, i) of the viewport, // but has a huge negative position. - child->SetPosition(gfx::PointF()); child->SetBounds(gfx::Size(kBigNumber + i, kBigNumber + i)); child->test_properties()->transform = transform; root->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -1760,11 +1759,13 @@ TEST_F(DamageTrackerTest, DamageRectTooBig) { LayerImpl* child2 = root->test_properties()->children[1]; // Really far left. - child1->SetPosition(gfx::PointF(std::numeric_limits<int>::min() + 100, 0)); + child1->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::min() + 100, 0); child1->SetBounds(gfx::Size(1, 1)); // Really far right. - child2->SetPosition(gfx::PointF(std::numeric_limits<int>::max() - 100, 0)); + child2->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::max() - 100, 0); child2->SetBounds(gfx::Size(1, 1)); root->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -1794,11 +1795,13 @@ TEST_F(DamageTrackerTest, DamageRectTooBigWithFilter) { root->test_properties()->backdrop_filters = filters; // Really far left. - child1->SetPosition(gfx::PointF(std::numeric_limits<int>::min() + 100, 0)); + child1->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::min() + 100, 0); child1->SetBounds(gfx::Size(1, 1)); // Really far right. - child2->SetPosition(gfx::PointF(std::numeric_limits<int>::max() - 100, 0)); + child2->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::max() - 100, 0); child2->SetBounds(gfx::Size(1, 1)); root->layer_tree_impl()->property_trees()->needs_rebuild = true; @@ -1824,14 +1827,14 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurface) { LayerImpl* grandchild2 = child1->test_properties()->children[1]; // Really far left. - grandchild1->SetPosition( - gfx::PointF(std::numeric_limits<int>::min() + 500, 0)); + grandchild1->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::min() + 500, 0); grandchild1->SetBounds(gfx::Size(1, 1)); grandchild1->SetDrawsContent(true); // Really far right. - grandchild2->SetPosition( - gfx::PointF(std::numeric_limits<int>::max() - 500, 0)); + grandchild2->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::max() - 500, 0); grandchild2->SetBounds(gfx::Size(1, 1)); grandchild2->SetDrawsContent(true); @@ -1920,14 +1923,14 @@ TEST_F(DamageTrackerTest, DamageRectTooBigInRenderSurfaceWithFilter) { child1->test_properties()->backdrop_filters = filters; // Really far left. - grandchild1->SetPosition( - gfx::PointF(std::numeric_limits<int>::min() + 500, 0)); + grandchild1->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::min() + 500, 0); grandchild1->SetBounds(gfx::Size(1, 1)); grandchild1->SetDrawsContent(true); // Really far right. - grandchild2->SetPosition( - gfx::PointF(std::numeric_limits<int>::max() - 500, 0)); + grandchild2->test_properties()->position = + gfx::PointF(std::numeric_limits<int>::max() - 500, 0); grandchild2->SetBounds(gfx::Size(1, 1)); grandchild2->SetDrawsContent(true); diff --git a/chromium/cc/trees/effect_node.cc b/chromium/cc/trees/effect_node.cc index b0138a10a4a..93ebe0be89c 100644 --- a/chromium/cc/trees/effect_node.cc +++ b/chromium/cc/trees/effect_node.cc @@ -51,6 +51,7 @@ bool EffectNode::operator==(const EffectNode& other) const { has_copy_request == other.has_copy_request && filters == other.filters && backdrop_filters == other.backdrop_filters && + backdrop_filter_bounds == other.backdrop_filter_bounds && filters_origin == other.filters_origin && blend_mode == other.blend_mode && surface_contents_scale == other.surface_contents_scale && diff --git a/chromium/cc/trees/effect_node.h b/chromium/cc/trees/effect_node.h index 0f8bf3399a6..276b808584d 100644 --- a/chromium/cc/trees/effect_node.h +++ b/chromium/cc/trees/effect_node.h @@ -9,6 +9,7 @@ #include "cc/paint/filter_operations.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size_f.h" namespace base { @@ -40,6 +41,7 @@ struct CC_EXPORT EffectNode { FilterOperations filters; FilterOperations backdrop_filters; + gfx::RectF backdrop_filter_bounds; float backdrop_filter_quality; gfx::PointF filters_origin; diff --git a/chromium/cc/trees/element_id.cc b/chromium/cc/trees/element_id.cc index 95c79a7b19c..b460a2e8675 100644 --- a/chromium/cc/trees/element_id.cc +++ b/chromium/cc/trees/element_id.cc @@ -14,22 +14,6 @@ namespace cc { -bool ElementId::operator==(const ElementId& o) const { - return id_ == o.id_; -} - -bool ElementId::operator!=(const ElementId& o) const { - return !(*this == o); -} - -bool ElementId::operator<(const ElementId& o) const { - return id_ < o.id_; -} - -ElementId::operator bool() const { - return !!id_; -} - ElementId LayerIdToElementIdForTesting(int layer_id) { return ElementId(std::numeric_limits<int>::max() - layer_id); } diff --git a/chromium/cc/trees/element_id.h b/chromium/cc/trees/element_id.h index ad88cc6a997..482ed3e152b 100644 --- a/chromium/cc/trees/element_id.h +++ b/chromium/cc/trees/element_id.h @@ -50,12 +50,12 @@ struct CC_EXPORT ElementId { explicit ElementId(ElementIdType id) : id_(id) {} ElementId() : ElementId(kInvalidElementId) {} - bool operator==(const ElementId& o) const; - bool operator!=(const ElementId& o) const; - bool operator<(const ElementId& o) const; + bool operator==(const ElementId& o) const { return id_ == o.id_; } + bool operator!=(const ElementId& o) const { return !(*this == o); } + bool operator<(const ElementId& o) const { return id_ < o.id_; } // An ElementId's conversion to a boolean value depends only on its primaryId. - explicit operator bool() const; + explicit operator bool() const { return !!id_; } void AddToTracedValue(base::trace_event::TracedValue* res) const; std::unique_ptr<base::Value> AsValue() const; diff --git a/chromium/cc/trees/image_animation_controller.cc b/chromium/cc/trees/image_animation_controller.cc index a781c08f8cd..62900fb0a7c 100644 --- a/chromium/cc/trees/image_animation_controller.cc +++ b/chromium/cc/trees/image_animation_controller.cc @@ -426,7 +426,7 @@ void ImageAnimationController::DelayedNotifier::Schedule( pending_notification_time_.emplace(notification_time); task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&DelayedNotifier::Notify, weak_factory_.GetWeakPtr()), + base::BindOnce(&DelayedNotifier::Notify, weak_factory_.GetWeakPtr()), notification_time - now); } diff --git a/chromium/cc/trees/image_animation_controller_unittest.cc b/chromium/cc/trees/image_animation_controller_unittest.cc index ea59f849c4c..f8abed7741c 100644 --- a/chromium/cc/trees/image_animation_controller_unittest.cc +++ b/chromium/cc/trees/image_animation_controller_unittest.cc @@ -74,11 +74,11 @@ class ImageAnimationControllerTest : public testing::Test { void SetUp() override { task_runner_ = new DelayTrackingTaskRunner(base::ThreadTaskRunnerHandle::Get().get()); - base::Closure invalidation_callback = - base::Bind(&ImageAnimationControllerTest::RequestInvalidation, - base::Unretained(this)); + auto invalidation_callback = + base::BindRepeating(&ImageAnimationControllerTest::RequestInvalidation, + base::Unretained(this)); controller_ = std::make_unique<ImageAnimationController>( - task_runner_.get(), invalidation_callback, + task_runner_.get(), std::move(invalidation_callback), GetEnableImageAnimationResync()); now_ += base::TimeDelta::FromSeconds(10); } diff --git a/chromium/cc/trees/layer_tree_frame_sink.cc b/chromium/cc/trees/layer_tree_frame_sink.cc index e1a1b803b72..024981ce300 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.cc +++ b/chromium/cc/trees/layer_tree_frame_sink.cc @@ -66,6 +66,11 @@ bool LayerTreeFrameSink::BindToClient(LayerTreeFrameSinkClient* client) { DCHECK(!client_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // Note: If |context_provider_| was always bound to a thread before here then + // the return value could be replaced with a PostTask to OnContextLost(). This + // would simplify the calling code so it didn't have to handle failures in + // BindToClient(). + if (context_provider_) { context_provider_->AddObserver(this); auto result = context_provider_->BindToCurrentThread(); diff --git a/chromium/cc/trees/layer_tree_frame_sink.h b/chromium/cc/trees/layer_tree_frame_sink.h index 15b3568a8cf..7ae114e3fe7 100644 --- a/chromium/cc/trees/layer_tree_frame_sink.h +++ b/chromium/cc/trees/layer_tree_frame_sink.h @@ -81,6 +81,10 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, bool HasClient() { return !!client_; } + void set_source_frame_number(int64_t frame_number) { + source_frame_number_ = frame_number; + } + // The viz::ContextProviders may be null if frames should be submitted with // software SharedMemory resources. viz::ContextProvider* context_provider() const { @@ -105,10 +109,15 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, // For successful swaps, the implementation must call // DidReceiveCompositorFrameAck() asynchronously when the frame has been - // processed in order to unthrottle the next frame. |show_hit_test_borders| - // controls whether viz will insert debug borders over hit-test data and is - // passed from LayerTreeDebugState. + // processed in order to unthrottle the next frame. + // If |hit_test_data_changed| is false, we do an equality check + // with the old hit-test data. If there is no change, we do not send the + // hit-test data. False positives are allowed. The value of + // |hit_test_data_changed| should remain constant in the caller. + // |show_hit_test_borders| controls whether viz will insert debug borders over + // hit-test data and is passed from LayerTreeDebugState. virtual void SubmitCompositorFrame(viz::CompositorFrame frame, + bool hit_test_data_changed, bool show_hit_test_borders) = 0; // Signals that a BeginFrame issued by the viz::BeginFrameSource provided to @@ -139,6 +148,8 @@ class CC_EXPORT LayerTreeFrameSink : public viz::SharedBitmapReporter, std::unique_ptr<ContextLostForwarder> worker_context_lost_forwarder_; + int64_t source_frame_number_; + private: THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<LayerTreeFrameSink> weak_ptr_factory_; diff --git a/chromium/cc/trees/layer_tree_frame_sink_client.h b/chromium/cc/trees/layer_tree_frame_sink_client.h index b89a6e738c4..8037825c25e 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_client.h +++ b/chromium/cc/trees/layer_tree_frame_sink_client.h @@ -48,8 +48,8 @@ class CC_EXPORT LayerTreeFrameSinkClient { // If set, |callback| will be called subsequent to each new tree activation, // regardless of the compositor visibility or damage. |callback| must remain // valid for the lifetime of the LayerTreeFrameSinkClient or until - // unregistered by giving a null base::Closure. - virtual void SetTreeActivationCallback(const base::Closure& callback) = 0; + // unregistered by giving a null callback. + virtual void SetTreeActivationCallback(base::RepeatingClosure callback) = 0; // Notification that the previous CompositorFrame given to // SubmitCompositorFrame() has been processed and that another frame diff --git a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc index cd40a54d467..58334b8322f 100644 --- a/chromium/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/chromium/cc/trees/layer_tree_frame_sink_unittest.cc @@ -29,6 +29,7 @@ class StubLayerTreeFrameSink : public LayerTreeFrameSink { nullptr) {} void SubmitCompositorFrame(viz::CompositorFrame frame, + bool hit_test_data_changed, bool show_hit_test_borders) override { client_->DidReceiveCompositorFrameAck(); } diff --git a/chromium/cc/trees/layer_tree_host.cc b/chromium/cc/trees/layer_tree_host.cc index 01ec4196d06..7e0328a5f0a 100644 --- a/chromium/cc/trees/layer_tree_host.cc +++ b/chromium/cc/trees/layer_tree_host.cc @@ -16,7 +16,6 @@ #include "base/auto_reset.h" #include "base/bind.h" #include "base/command_line.h" -#include "base/json/json_writer.h" #include "base/location.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -41,6 +40,7 @@ #include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/layer.h" #include "cc/layers/painted_scrollbar_layer.h" +#include "cc/paint/paint_worklet_layer_painter.h" #include "cc/resources/ui_resource_manager.h" #include "cc/tiles/frame_viewer_instrumentation.h" #include "cc/trees/clip_node.h" @@ -305,14 +305,11 @@ void LayerTreeHost::FinishCommitOnImplThread( } sync_tree->set_source_frame_number(SourceFrameNumber()); - bool request_presentation_time = - settings_.always_request_presentation_time || - !pending_presentation_time_callbacks_.empty(); - if (request_presentation_time && pending_presentation_time_callbacks_.empty()) - pending_presentation_time_callbacks_.push_back(base::DoNothing()); - sync_tree->AddPresentationCallbacks( - std::move(pending_presentation_time_callbacks_)); - pending_presentation_time_callbacks_.clear(); + if (!pending_presentation_time_callbacks_.empty()) { + sync_tree->AddPresentationCallbacks( + std::move(pending_presentation_time_callbacks_)); + pending_presentation_time_callbacks_.clear(); + } if (needs_full_tree_sync_) TreeSynchronizer::SynchronizeTrees(root_layer(), sync_tree); @@ -377,14 +374,11 @@ void LayerTreeHost::FinishCommitOnImplThread( // Dump property trees and layers if run with: // --vmodule=layer_tree_host=3 if (VLOG_IS_ON(3)) { - std::string property_trees; - base::JSONWriter::WriteWithOptions( - *sync_tree->property_trees()->AsTracedValue()->ToBaseValue(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, &property_trees); VLOG(3) << "After finishing commit on impl, the sync tree:" << "\nproperty_trees:\n" - << property_trees << "\nlayers:\n" - << host_impl->LayerListAsJson(); + << sync_tree->property_trees()->ToString() << "\n" + << "cc::LayerImpls:\n" + << sync_tree->LayerListAsJson(); } } @@ -445,7 +439,7 @@ void LayerTreeHost::UpdateDeferMainFrameUpdateInternal() { } bool LayerTreeHost::IsUsingLayerLists() const { - return settings_.use_layer_lists; + return settings_.use_layer_lists && !force_use_property_tree_builder_; } void LayerTreeHost::CommitComplete() { @@ -564,7 +558,7 @@ void LayerTreeHost::SetNeedsCommit() { swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit(); } -bool LayerTreeHost::RequestedMainFramePending() { +bool LayerTreeHost::RequestedMainFramePendingForTesting() { return proxy_->RequestedAnimatePending(); } @@ -668,10 +662,11 @@ bool LayerTreeHost::UpdateLayers() { property_trees_.clear(); return false; } + DCHECK(!root_layer()->parent()); base::ElapsedTimer timer; - bool result = DoUpdateLayers(root_layer()); + bool result = DoUpdateLayers(); micro_benchmark_controller_.DidUpdateLayers(); if (const char* client_name = GetClientNameForMetrics()) { @@ -694,6 +689,11 @@ void LayerTreeHost::DidPresentCompositorFrame( client_->DidPresentCompositorFrame(frame_token, feedback); } +void LayerTreeHost::DidGenerateLocalSurfaceIdAllocation( + const viz::LocalSurfaceIdAllocation& allocation) { + client_->DidGenerateLocalSurfaceIdAllocation(allocation); +} + void LayerTreeHost::DidCompletePageScaleAnimation() { did_complete_scale_animation_ = true; } @@ -737,7 +737,7 @@ void LayerTreeHost::RecordGpuRasterizationHistogram( gpu_rasterization_histogram_recorded_ = true; } -bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { +bool LayerTreeHost::DoUpdateLayers() { TRACE_EVENT1("cc,benchmark", "LayerTreeHost::DoUpdateLayers", "source_frame_number", SourceFrameNumber()); @@ -747,17 +747,17 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { // and cc needs to compute property trees from that. // In layer lists mode, blink sends cc property trees directly so they do not // need to be built here. Layer lists mode is used by BlinkGenPropertyTrees - // and SlimmingPaintV2. + // and CompositeAfterPaint. if (!IsUsingLayerLists()) { TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::BuildPropertyTrees"); Layer* root_scroll = - PropertyTreeBuilder::FindFirstScrollableLayer(root_layer); + PropertyTreeBuilder::FindFirstScrollableLayer(root_layer_.get()); Layer* page_scale_layer = viewport_layers_.page_scale.get(); if (!page_scale_layer && root_scroll) page_scale_layer = root_scroll->parent(); gfx::Transform identity_transform; PropertyTreeBuilder::BuildPropertyTrees( - root_layer, page_scale_layer, inner_viewport_scroll_layer(), + root_layer_.get(), page_scale_layer, inner_viewport_scroll_layer(), outer_viewport_scroll_layer(), overscroll_elasticity_element_id(), elastic_overscroll_, page_scale_factor_, device_scale_factor_, gfx::Rect(device_viewport_size_), identity_transform, &property_trees_); @@ -793,6 +793,11 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { DCHECK(property_trees_.clip_tree.Node(layer->clip_tree_index())); DCHECK(property_trees_.scroll_tree.Node(layer->scroll_tree_index())); } +#else + // This is a quick sanity check for readiness of paint properties. + // TODO(crbug.com/913464): This is to help analysis of crashes of the bug. + // Remove this CHECK when we close the bug. + CHECK(property_trees_.effect_tree.Node(root_layer_->effect_tree_index())); #endif draw_property_utils::UpdatePropertyTrees(this, &property_trees_); @@ -803,29 +808,17 @@ bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) { // Dump property trees and layers if run with: // --vmodule=layer_tree_host=3 - // This only prints output for the renderer. - if (VLOG_IS_ON(3) && GetClientNameForMetrics() == std::string("Renderer")) { - std::string property_trees; - base::JSONWriter::WriteWithOptions( - *property_trees_.AsTracedValue()->ToBaseValue(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, &property_trees); + // This only prints output in unit test or for the renderer. + if (VLOG_IS_ON(3) && (!GetClientNameForMetrics() || + GetClientNameForMetrics() == std::string("Renderer"))) { std::ostringstream layers; - for (auto* layer : *this) { - layers << "\n layer id " << layer->id(); - layers << "\n element_id: " << layer->element_id(); - layers << "\n bounds: " << layer->bounds().ToString(); - layers << "\n opacity: " << layer->opacity(); - layers << "\n position: " << layer->position().ToString(); - layers << "\n draws_content: " << layer->DrawsContent(); - layers << "\n scrollable: " << layer->scrollable(); - layers << "\n contents_opaque: " << layer->contents_opaque(); - layers << "\n transform_tree_index: " << layer->transform_tree_index(); - layers << "\n clip_tree_index: " << layer->clip_tree_index(); - layers << "\n effect_tree_index: " << layer->effect_tree_index(); - layers << "\n scroll_tree_index: " << layer->scroll_tree_index(); - } - VLOG(3) << "After updating layers on the main thread:\nproperty trees:\n" - << property_trees << "\nlayers:" << layers.str(); + for (auto* layer : *this) + layers << layer->ToString() << "\n"; + VLOG(3) << "After updating layers on the main thread:\n" + << "property trees:\n" + << property_trees_.ToString() << "\n" + << "cc::Layers:\n" + << layers.str(); } bool painted_content_has_slow_paths = false; @@ -899,6 +892,19 @@ void LayerTreeHost::RecordWheelAndTouchScrollingCount( } } +void LayerTreeHost::SendOverscrollAndScrollEndEventsFromImplSide( + const ScrollAndScaleSet& info) { + if (info.scroll_latched_element_id == ElementId()) + return; + + if (!info.overscroll_delta.IsZero()) { + client_->SendOverscrollEventFromImplSide(info.overscroll_delta, + info.scroll_latched_element_id); + } + if (info.scroll_gesture_did_end) + client_->SendScrollEndEventFromImplSide(info.scroll_latched_element_id); +} + void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { DCHECK(info); for (auto& swap_promise : info->swap_promises) { @@ -926,6 +932,8 @@ void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) { } } + SendOverscrollAndScrollEndEventsFromImplSide(*info); + // This needs to happen after scroll deltas have been sent to prevent top // controls from clamping the layout viewport both on the compositor and // on the main thread. @@ -997,6 +1005,16 @@ void LayerTreeHost::SetLayerTreeMutator( proxy_->SetMutator(std::move(mutator)); } +void LayerTreeHost::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + // The paint worklet system assumes that the painter will never be called from + // the main thread, which will not be the case if we're running in + // single-threaded mode. + DCHECK(task_runner_provider_->HasImplThread()) + << "PaintWorkletLayerPainter not supported in single-thread mode"; + proxy_->SetPaintWorkletLayerPainter(std::move(painter)); +} + bool LayerTreeHost::IsSingleThreaded() const { DCHECK(compositor_mode_ != CompositorMode::SINGLE_THREADED || !task_runner_provider_->HasImplThread()); @@ -1035,9 +1053,20 @@ void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { content_has_non_aa_paint_ = false; gpu_rasterization_histogram_recorded_ = false; + force_use_property_tree_builder_ = false; + SetNeedsFullTreeSync(); } +void LayerTreeHost::SetNonBlinkManagedRootLayer( + scoped_refptr<Layer> root_layer) { + SetRootLayer(std::move(root_layer)); + + DCHECK(root_layer_->children().empty()); + if (IsUsingLayerLists() && root_layer_) + force_use_property_tree_builder_ = true; +} + LayerTreeHost::ViewportLayers::ViewportLayers() = default; LayerTreeHost::ViewportLayers::~ViewportLayers() = default; @@ -1101,18 +1130,9 @@ void LayerTreeHost::SetEventListenerProperties( // layer tree sets a wheel event handler region to be its entire bounds, // otherwise it sets it to empty. // - // Thus when it changes, we might want to request every layer to push - // properties and recompute its wheel event handler region, since the - // computation is done in PushPropertiesTo. However neither - // SetSubtreePropertyChanged() nor SetNeedsFullTreeSync() do this, so - // it is unclear why we call them. - // Also why we don't want to recompute the wheel event handler region for all - // layers when the blocking state goes away is unclear. Also why we mark all - // layers below the root layer as damaged is unclear. - // TODO(bokan): Sort out what should be set and why. https://crbug.com/881011 - // - // TODO(sunxd): Remove NeedsFullTreeSync when computing mouse wheel event - // handler region is done. + // Thus when it changes, we want to request every layer to push properties + // and recompute its wheel event handler region, since the computation is + // done in PushPropertiesTo. if (event_class == EventListenerClass::kMouseWheel) { bool new_property_is_blocking = properties == EventListenerProperties::kBlocking || @@ -1122,10 +1142,9 @@ void LayerTreeHost::SetEventListenerProperties( old_properties == EventListenerProperties::kBlocking || old_properties == EventListenerProperties::kBlockingAndPassive; - if (!old_property_is_blocking && new_property_is_blocking) { - if (root_layer()) - root_layer()->SetSubtreePropertyChanged(); - SetNeedsFullTreeSync(); + if (old_property_is_blocking != new_property_is_blocking) { + LayerTreeHostCommon::CallFunctionForEveryLayer( + this, [](Layer* layer) { layer->SetNeedsPushProperties(); }); } } @@ -1138,37 +1157,51 @@ void LayerTreeHost::SetViewportSizeAndScale( float device_scale_factor, const viz::LocalSurfaceIdAllocation& local_surface_id_allocation_from_parent) { + const viz::LocalSurfaceId previous_local_surface_id = + local_surface_id_allocation_from_parent_.local_surface_id(); SetLocalSurfaceIdAllocationFromParent( local_surface_id_allocation_from_parent); - bool changed = false; + bool device_viewport_size_changed = false; if (device_viewport_size_ != device_viewport_size) { device_viewport_size_ = device_viewport_size; - changed = true; + device_viewport_size_changed = true; } + bool painted_device_scale_factor_changed = false; + bool device_scale_factor_changed = false; if (settings_.use_painted_device_scale_factor) { DCHECK_EQ(device_scale_factor_, 1.f); if (painted_device_scale_factor_ != device_scale_factor) { painted_device_scale_factor_ = device_scale_factor; - changed = true; + painted_device_scale_factor_changed = true; } } else { DCHECK_EQ(painted_device_scale_factor_, 1.f); if (device_scale_factor_ != device_scale_factor) { device_scale_factor_ = device_scale_factor; - changed = true; + device_scale_factor_changed = true; } } - if (changed) { + if (device_viewport_size_changed || painted_device_scale_factor_changed || + device_scale_factor_changed) { SetPropertyTreesNeedRebuild(); SetNeedsCommit(); #if defined(OS_MACOSX) - // TODO(ccameron): This check is not valid on Aura or Mus yet, but should - // be. + // TODO(jonross): This check is not valid on Aura or Mus yet, but should be. CHECK(!has_pushed_local_surface_id_from_parent_ || new_local_surface_id_request_ || - !local_surface_id_allocation_from_parent_.IsValid()); + !local_surface_id_allocation_from_parent_.IsValid()) + << "Invalid Surface Id State: !has_pushed " + << !has_pushed_local_surface_id_from_parent_ << " new_id_request " + << new_local_surface_id_request_ << " !valid_parent_id " + << !local_surface_id_allocation_from_parent_.IsValid() + << ". Changed state: device_viewport_size " + << device_viewport_size_changed << " painted_device_scale_factor " + << painted_device_scale_factor_changed << " device_scale_factor " + << device_scale_factor_changed << " cached LSId " + << previous_local_surface_id.ToString() << " new LSId " + << local_surface_id_allocation_from_parent.ToString(); #endif } } @@ -1282,14 +1315,8 @@ void LayerTreeHost::SetLocalSurfaceIdAllocationFromParent( local_surface_id_allocation_from_parent) { const viz::LocalSurfaceId& local_surface_id_from_parent = local_surface_id_allocation_from_parent.local_surface_id(); - const viz::LocalSurfaceId& current_local_surface_id_from_parent = + const viz::LocalSurfaceId current_local_surface_id_from_parent = local_surface_id_allocation_from_parent_.local_surface_id(); - if (current_local_surface_id_from_parent.parent_sequence_number() == - local_surface_id_from_parent.parent_sequence_number() && - current_local_surface_id_from_parent.embed_token() == - local_surface_id_from_parent.embed_token()) { - return; - } // If the viz::LocalSurfaceId is valid but the allocation time is invalid then // this API is not being used correctly. @@ -1303,9 +1330,24 @@ void LayerTreeHost::SetLocalSurfaceIdAllocationFromParent( TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", "SetLocalSurfaceAllocationIdFromParent", "local_surface_id_allocation", local_surface_id_allocation_from_parent.ToString()); + // Always update the cached state of the viz::LocalSurfaceId to reflect the + // latest value received from our parent. local_surface_id_allocation_from_parent_ = local_surface_id_allocation_from_parent; has_pushed_local_surface_id_from_parent_ = false; + + // If the parent sequence number has not advanced, then there is no need to + // commit anything. This can occur when the child sequence number has + // advanced. Which means that child has changed visual properites, and the + // parent agreed upon these without needing to further advance its sequence + // number. When this occurs the child is already up-to-date and a commit here + // is simply redundant. + if (current_local_surface_id_from_parent.parent_sequence_number() == + local_surface_id_from_parent.parent_sequence_number() && + current_local_surface_id_from_parent.embed_token() == + local_surface_id_from_parent.embed_token()) { + return; + } UpdateDeferMainFrameUpdateInternal(); SetNeedsCommit(); } @@ -1568,16 +1610,24 @@ Layer* LayerTreeHost::LayerByElementId(ElementId element_id) const { void LayerTreeHost::RegisterElement(ElementId element_id, ElementListType list_type, Layer* layer) { + // When using layer lists only scrollable layers should be registered. + DCHECK(!IsUsingLayerLists() || layer->inputs_.scrollable); element_layers_map_[element_id] = layer; - elements_in_property_trees_.insert(element_id); - mutator_host_->RegisterElement(element_id, list_type); + + // Animation ElementIds are unregistered by |SetActiveRegisteredElementIds| + // when using layer lists. + if (!IsUsingLayerLists()) + mutator_host_->RegisterElement(element_id, list_type); } void LayerTreeHost::UnregisterElement(ElementId element_id, ElementListType list_type) { - mutator_host_->UnregisterElement(element_id, list_type); + // Animation ElementIds are unregistered by |SetActiveRegisteredElementIds| + // when using layer lists. + if (!IsUsingLayerLists()) + mutator_host_->UnregisterElement(element_id, list_type); + element_layers_map_.erase(element_id); - elements_in_property_trees_.erase(element_id); } void LayerTreeHost::SetActiveRegisteredElementIds(const ElementIdSet& ids) { @@ -1587,8 +1637,10 @@ void LayerTreeHost::SetActiveRegisteredElementIds(const ElementIdSet& ids) { for (auto id_iter = elements_in_property_trees_.begin(); id_iter != elements_in_property_trees_.end();) { const auto& id = *(id_iter++); - if (!ids.count(id)) - UnregisterElement(id, ElementListType::ACTIVE); + if (!ids.count(id)) { + mutator_host_->UnregisterElement(id, ElementListType::ACTIVE); + elements_in_property_trees_.erase(id); + } } // Register new ids that were not already registered. @@ -1638,8 +1690,8 @@ void LayerTreeHost::SetElementFilterMutated(ElementId element_id, ElementListType list_type, const FilterOperations& filters) { if (IsUsingLayerLists()) { - // In SPv2 we always have property trees and can set the filter - // directly on the effect node. + // In BlinkGenPropertyTrees/CompositeAfterPaint we always have property + // tree nodes and can set the filter directly on the effect node. property_trees_.effect_tree.OnFilterAnimated(element_id, filters); return; } @@ -1715,12 +1767,12 @@ void LayerTreeHost::SetElementScrollOffsetMutated( } void LayerTreeHost::ElementIsAnimatingChanged( - ElementId element_id, + const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) { DCHECK_EQ(ElementListType::ACTIVE, list_type); - property_trees()->ElementIsAnimatingChanged(mutator_host(), element_id, + property_trees()->ElementIsAnimatingChanged(mutator_host(), element_id_map, list_type, mask, state, true); } diff --git a/chromium/cc/trees/layer_tree_host.h b/chromium/cc/trees/layer_tree_host.h index d35269410a8..d98608d246d 100644 --- a/chromium/cc/trees/layer_tree_host.h +++ b/chromium/cc/trees/layer_tree_host.h @@ -61,6 +61,7 @@ class LayerTreeHostImpl; class LayerTreeHostImplClient; class LayerTreeHostSingleThreadClient; class LayerTreeMutator; +class PaintWorkletLayerPainter; class MutatorEvents; class MutatorHost; struct PendingPageScaleAnimation; @@ -87,6 +88,12 @@ class CC_EXPORT ScopedDeferMainFrameUpdate { class CC_EXPORT LayerTreeHost : public MutatorHostClient { public: struct CC_EXPORT InitParams { + InitParams(); + ~InitParams(); + + InitParams(InitParams&&); + InitParams& operator=(InitParams&&); + LayerTreeHostClient* client = nullptr; TaskGraphRunner* task_graph_runner = nullptr; LayerTreeSettings const* settings = nullptr; @@ -99,12 +106,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner; std::unique_ptr<UkmRecorderFactory> ukm_recorder_factory; - - InitParams(); - ~InitParams(); - - InitParams(InitParams&&); - InitParams& operator=(InitParams&&); }; // Constructs a LayerTreeHost with a compositor thread where scrolling and @@ -151,6 +152,11 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // state on the compositor thread. (Compositor-Worker) void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator); + // Sets the LayerTreePainter interface used to dispatch the JS paint callback + // to a worklet thread. + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter); + // Attachs a SwapPromise to the Layer tree, that passes through the // LayerTreeHost and LayerTreeHostImpl with the next commit and frame // submission, which can be used to observe that progress. This also @@ -162,10 +168,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // when a main frame is requested. SwapPromiseManager* GetSwapPromiseManager(); - // Sets whether the content is suitable to use Gpu Rasterization. This flag is - // used to enable gpu rasterization, and can be modified at any time to change - // the setting based on content. + // Sets or gets whether the content is suitable to use Gpu Rasterization. This + // flag is used to enable gpu rasterization, and can be modified at any time + // to change the setting based on content. void SetHasGpuRasterizationTrigger(bool has_trigger); + bool has_gpu_rasterization_trigger() const { + return has_gpu_rasterization_trigger_; + } // Visibility and LayerTreeFrameSink ------------------------------- @@ -211,7 +220,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Returns true after SetNeedsAnimate(), SetNeedsUpdateLayers() or // SetNeedsCommit(), until it is satisfied. - bool RequestedMainFramePending(); + bool RequestedMainFramePendingForTesting(); // Requests that the next frame re-chooses crisp raster scales for all layers. void SetNeedsRecalculateRasterScales(); @@ -300,6 +309,14 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { Layer* root_layer() { return root_layer_.get(); } const Layer* root_layer() const { return root_layer_.get(); } + // Sets the root layer which is not managed by blink, and we will initialize + // its paint properties using PropertyTreeBuilder. For ui::Compositor, because + // for now we always use PropertyTreeBulder, this function is equivalent to + // SetRootLayer(). + // TODO(crbug.com/925855): This is temporary. Eventually we should let the + // caller inform blink about the layer and remove the function. + void SetNonBlinkManagedRootLayer(scoped_refptr<Layer> root_layer); + // Viewport Layers are used to identify key layers to the compositor thread, // so that it can perform viewport-based scrolling independently, such as // for pinch-zoom or overscroll elasticity. @@ -337,6 +354,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // viewport layers. struct ViewportPropertyIds { int page_scale_transform = TransformTree::kInvalidNodeId; + int inner_scroll = ScrollTree::kInvalidNodeId; // TODO(crbug.com/909750): Switch other usages of viewport layers to // property ids for CompositeAfterPaint. }; @@ -525,6 +543,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { MutatorHost* mutator_host() const { return mutator_host_; } + // Returns the layer with the given |element_id|. In layer-list mode, only + // scrollable layers are registered in this map. Layer* LayerByElementId(ElementId element_id) const; void RegisterElement(ElementId element_id, ElementListType list_type, @@ -577,6 +597,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { uint32_t frame_token, std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback); + void DidGenerateLocalSurfaceIdAllocation( + const viz::LocalSurfaceIdAllocation& allocation); // Called when the compositor completed page scale animation. void DidCompletePageScaleAnimation(); void ApplyScrollAndScale(ScrollAndScaleSet* info); @@ -596,10 +618,6 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void SetAnimationEvents(std::unique_ptr<MutatorEvents> events); - bool has_gpu_rasterization_trigger() const { - return has_gpu_rasterization_trigger_; - } - Proxy* proxy() const { return proxy_.get(); } bool IsSingleThreaded() const; @@ -629,7 +647,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { ElementListType list_type, const gfx::ScrollOffset& scroll_offset) override; - void ElementIsAnimatingChanged(ElementId element_id, + void ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) override; @@ -693,10 +711,12 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { void ApplyViewportChanges(const ScrollAndScaleSet& info); void RecordWheelAndTouchScrollingCount(const ScrollAndScaleSet& info); + void SendOverscrollAndScrollEndEventsFromImplSide( + const ScrollAndScaleSet& info); void ApplyPageScaleDeltaFromImplSide(float page_scale_delta); void InitializeProxy(std::unique_ptr<Proxy> proxy); - bool DoUpdateLayers(Layer* root_layer); + bool DoUpdateLayers(); void UpdateDeferMainFrameUpdateInternal(); @@ -817,6 +837,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // Layer id to Layer map. std::unordered_map<int, Layer*> layer_id_map_; + // In layer-list mode, this map is only used for scrollable layers. std::unordered_map<ElementId, Layer*, ElementIdHash> element_layers_map_; // The set of registered element ids when using layer list mode. In non-layer- @@ -830,6 +851,13 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { // for every layer during property tree building. bool has_copy_request_ = false; + // When settings_.use_layer_lists is true, paint properties are generated by + // blink and we don't use PropertyTreeBuilder, except that the root layer + // is set by SetNonBlinkManagedRootLayer(). + // TODO(crbug.com/925855): Remove this field when removing + // SetNonBlinkManagedRootLayer(). + bool force_use_property_tree_builder_ = false; + MutatorHost* mutator_host_; std::vector<std::pair<PaintImage, base::OnceCallback<void(bool)>>> diff --git a/chromium/cc/trees/layer_tree_host_client.h b/chromium/cc/trees/layer_tree_host_client.h index 2973940a711..a282dae8f01 100644 --- a/chromium/cc/trees/layer_tree_host_client.h +++ b/chromium/cc/trees/layer_tree_host_client.h @@ -18,10 +18,12 @@ struct PresentationFeedback; } namespace viz { +class LocalSurfaceIdAllocation; struct BeginFrameArgs; } namespace cc { +struct ElementId; struct ApplyViewportChangesArgs { // Scroll offset delta of the inner (visual) viewport. @@ -103,6 +105,15 @@ class LayerTreeHostClient { virtual void RecordWheelAndTouchScrollingCount( bool has_scrolled_by_wheel, bool has_scrolled_by_touch) = 0; + + // Notifies the client when an overscroll has happened. + virtual void SendOverscrollEventFromImplSide( + const gfx::Vector2dF& overscroll_delta, + ElementId scroll_latched_element_id) = 0; + // Notifies the client when a gesture scroll has ended. + virtual void SendScrollEndEventFromImplSide( + ElementId scroll_latched_element_id) = 0; + // Request a LayerTreeFrameSink from the client. When the client has one it // should call LayerTreeHost::SetLayerTreeFrameSink. This will result in // either DidFailToInitializeLayerTreeFrameSink or @@ -121,6 +132,8 @@ class LayerTreeHostClient { // Record UMA and UKM metrics that require the time from the start of // BeginMainFrame to the Commit, or early out. virtual void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) = 0; + virtual void DidGenerateLocalSurfaceIdAllocation( + const viz::LocalSurfaceIdAllocation& allocation) = 0; protected: virtual ~LayerTreeHostClient() {} diff --git a/chromium/cc/trees/layer_tree_host_common.cc b/chromium/cc/trees/layer_tree_host_common.cc index 16bee1698d4..e2f1c0d45e3 100644 --- a/chromium/cc/trees/layer_tree_host_common.cc +++ b/chromium/cc/trees/layer_tree_host_common.cc @@ -574,7 +574,7 @@ void CalculateDrawPropertiesInternal( combine_dsf_and_psf ? inputs->page_scale_factor : 1.f; property_trees->transform_tree.SetRootTransformsAndScales( inputs->device_scale_factor, page_scale_factor_for_root, - inputs->device_transform, inputs->root_layer->position()); + inputs->device_transform); draw_property_utils::UpdatePropertyTreesAndRenderSurfaces( inputs->root_layer, inputs->property_trees, inputs->can_adjust_raster_scales); diff --git a/chromium/cc/trees/layer_tree_host_common.h b/chromium/cc/trees/layer_tree_host_common.h index 42de6d2ab68..235910b58d3 100644 --- a/chromium/cc/trees/layer_tree_host_common.h +++ b/chromium/cc/trees/layer_tree_host_common.h @@ -168,7 +168,19 @@ struct CC_EXPORT ScrollAndScaleSet { std::vector<LayerTreeHostCommon::ScrollUpdateInfo> scrolls; float page_scale_delta; + + // Elastic overscroll effect offset delta. This is used only on Mac and shows + // the pixels that the page is rubber-banned/stretched by. gfx::Vector2dF elastic_overscroll_delta; + + // Unconsumed scroll delta used to send overscroll events to the latched + // element on the main thread; + gfx::Vector2dF overscroll_delta; + + // The element id of the node to which scrolling is latched. This is used to + // send overscroll/scrollend DOM events to proper targets whenever needed. + ElementId scroll_latched_element_id; + float top_controls_delta; std::vector<LayerTreeHostCommon::ScrollbarsUpdateInfo> scrollbars; std::vector<std::unique_ptr<SwapPromise>> swap_promises; diff --git a/chromium/cc/trees/layer_tree_host_common_unittest.cc b/chromium/cc/trees/layer_tree_host_common_unittest.cc index 17a78468e72..05a2290e760 100644 --- a/chromium/cc/trees/layer_tree_host_common_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_common_unittest.cc @@ -350,11 +350,12 @@ class LayerTreeHostCommonDrawRectsTest : public LayerTreeHostCommonTest { root->SetBounds(gfx::Size(500, 500)); root->test_properties()->force_render_surface = true; - target->SetPosition(gfx::PointF(target_rect.origin())); + target->test_properties()->position = gfx::PointF(target_rect.origin()); target->SetBounds(target_rect.size()); target->test_properties()->force_render_surface = true; drawing_layer->test_properties()->transform = layer_transform; - drawing_layer->SetPosition(gfx::PointF(layer_rect.origin())); + drawing_layer->test_properties()->position = + gfx::PointF(layer_rect.origin()); drawing_layer->SetBounds(layer_rect.size()); drawing_layer->test_properties()->should_flatten_transform = false; @@ -396,7 +397,7 @@ TEST_F(LayerTreeHostCommonTest, EffectTreeTransformIdTest) { child->SetDrawsContent(true); parent->SetBounds(gfx::Size(100, 100)); - child->SetPosition(gfx::PointF(10, 10)); + child->test_properties()->position = gfx::PointF(10, 10); child->SetBounds(gfx::Size(100, 100)); child->test_properties()->opacity = 0.f; ExecuteCalculateDrawProperties(parent); @@ -448,7 +449,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) { // screen space transform. gfx::Transform position_transform; position_transform.Translate(0.f, 1.2f); - layer->SetPosition(gfx::PointF(0.f, 1.2f)); + layer->test_properties()->position = gfx::PointF(0.f, 1.2f); host_impl()->active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); EXPECT_TRANSFORMATION_MATRIX_EQ( @@ -465,7 +466,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) { layer_transform.Scale3d(2.0, 2.0, 1.0); layer->test_properties()->transform = layer_transform; layer->test_properties()->transform_origin = gfx::Point3F(); - layer->SetPosition(gfx::PointF()); + layer->test_properties()->position = gfx::PointF(); host_impl()->active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); EXPECT_TRANSFORMATION_MATRIX_EQ( @@ -495,7 +496,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSingleLayer) { // it is still worth testing to detect accidental regressions. expected_result = position_transform * translation_to_anchor * layer_transform * Inverse(translation_to_anchor); - layer->SetPosition(gfx::PointF(0.f, 1.2f)); + layer->test_properties()->position = gfx::PointF(0.f, 1.2f); host_impl()->active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); EXPECT_TRANSFORMATION_MATRIX_EQ( @@ -645,7 +646,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) { // Case 2: parent's position affects child and grand_child. gfx::Transform parent_position_transform; parent_position_transform.Translate(0.f, 1.2f); - parent->SetPosition(gfx::PointF(0.f, 1.2f)); + parent->test_properties()->position = gfx::PointF(0.f, 1.2f); host_impl()->active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); EXPECT_TRANSFORMATION_MATRIX_EQ( @@ -670,7 +671,7 @@ TEST_F(LayerTreeHostCommonTest, TransformsForSimpleHierarchy) { parent_translation_to_anchor * parent_layer_transform * Inverse(parent_translation_to_anchor); parent->test_properties()->transform = parent_layer_transform; - parent->SetPosition(gfx::PointF()); + parent->test_properties()->position = gfx::PointF(); host_impl()->active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); EXPECT_TRANSFORMATION_MATRIX_EQ( @@ -1367,7 +1368,7 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->SetBounds(gfx::Size(10, 10)); render_surface1->test_properties()->force_render_surface = true; child->SetDrawsContent(true); - child->SetPosition(gfx::PointF(30.f, 30.f)); + child->test_properties()->position = gfx::PointF(30.f, 30.f); child->SetBounds(gfx::Size(10, 10)); ExecuteCalculateDrawProperties(root); @@ -1481,7 +1482,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForFilter) { child1->SetBounds(gfx::Size(25, 25)); child1->SetDrawsContent(true); child1->test_properties()->force_render_surface = true; - child2->SetPosition(gfx::PointF(25, 25)); + child2->test_properties()->position = gfx::PointF(25, 25); child2->SetBounds(gfx::Size(25, 25)); child2->SetDrawsContent(true); child2->test_properties()->force_render_surface = true; @@ -1699,7 +1700,7 @@ TEST_F(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) { child->SetBounds(gfx::Size(20, 20)); child->SetMasksToBounds(true); child->test_properties()->force_render_surface = true; - grand_child->SetPosition(gfx::PointF(45.f, 45.f)); + grand_child->test_properties()->position = gfx::PointF(45.f, 45.f); grand_child->SetBounds(gfx::Size(10, 10)); great_grand_child->SetBounds(gfx::Size(10, 10)); leaf_node1->SetBounds(gfx::Size(500, 500)); @@ -1739,7 +1740,7 @@ TEST_F(LayerTreeHostCommonTest, ClipRectCullsSurfaceWithoutVisibleContent) { root->SetBounds(gfx::Size(100, 100)); child->SetBounds(gfx::Size(20, 20)); child->test_properties()->force_render_surface = true; - grand_child->SetPosition(gfx::PointF(200.f, 200.f)); + grand_child->test_properties()->position = gfx::PointF(200.f, 200.f); grand_child->SetBounds(gfx::Size(10, 10)); grand_child->test_properties()->force_render_surface = true; leaf_node->SetBounds(gfx::Size(10, 10)); @@ -1874,7 +1875,7 @@ TEST_F(LayerTreeHostCommonTest, UpdateClipRectCorrectly) { EXPECT_EQ(gfx::Rect(100, 100), child->clip_rect()); parent->SetMasksToBounds(true); - child->SetPosition(gfx::PointF(100.f, 100.f)); + child->test_properties()->position = gfx::PointF(100.f, 100.f); host_impl()->active_tree()->property_trees()->needs_rebuild = true; ExecuteCalculateDrawProperties(root); @@ -1910,17 +1911,17 @@ TEST_F(LayerTreeHostCommonTest, DrawableContentRectForLayers) { child->SetMasksToBounds(true); child->SetBounds(gfx::Size(20, 20)); child->test_properties()->force_render_surface = true; - grand_child1->SetPosition(gfx::PointF(5.f, 5.f)); + grand_child1->test_properties()->position = gfx::PointF(5.f, 5.f); grand_child1->SetBounds(gfx::Size(10, 10)); grand_child1->SetDrawsContent(true); - grand_child2->SetPosition(gfx::PointF(15.f, 15.f)); + grand_child2->test_properties()->position = gfx::PointF(15.f, 15.f); grand_child2->SetBounds(gfx::Size(10, 10)); grand_child2->SetDrawsContent(true); - grand_child3->SetPosition(gfx::PointF(15.f, 15.f)); + grand_child3->test_properties()->position = gfx::PointF(15.f, 15.f); grand_child3->SetMasksToBounds(true); grand_child3->SetBounds(gfx::Size(10, 10)); grand_child3->SetDrawsContent(true); - grand_child4->SetPosition(gfx::PointF(45.f, 45.f)); + grand_child4->test_properties()->position = gfx::PointF(45.f, 45.f); grand_child4->SetBounds(gfx::Size(10, 10)); grand_child4->SetDrawsContent(true); ExecuteCalculateDrawProperties(parent); @@ -1956,17 +1957,17 @@ TEST_F(LayerTreeHostCommonTest, ClipRectIsPropagatedCorrectlyToSurfaces) { child->SetBounds(gfx::Size(20, 20)); child->SetMasksToBounds(true); child->test_properties()->force_render_surface = true; - grand_child1->SetPosition(gfx::PointF(5.f, 5.f)); + grand_child1->test_properties()->position = gfx::PointF(5.f, 5.f); grand_child1->SetBounds(gfx::Size(10, 10)); grand_child1->test_properties()->force_render_surface = true; - grand_child2->SetPosition(gfx::PointF(15.f, 15.f)); + grand_child2->test_properties()->position = gfx::PointF(15.f, 15.f); grand_child2->SetBounds(gfx::Size(10, 10)); grand_child2->test_properties()->force_render_surface = true; - grand_child3->SetPosition(gfx::PointF(15.f, 15.f)); + grand_child3->test_properties()->position = gfx::PointF(15.f, 15.f); grand_child3->SetBounds(gfx::Size(10, 10)); grand_child3->SetMasksToBounds(true); grand_child3->test_properties()->force_render_surface = true; - grand_child4->SetPosition(gfx::PointF(45.f, 45.f)); + grand_child4->test_properties()->position = gfx::PointF(45.f, 45.f); grand_child4->SetBounds(gfx::Size(10, 10)); grand_child4->SetMasksToBounds(true); grand_child4->test_properties()->force_render_surface = true; @@ -2019,48 +2020,47 @@ TEST_F(LayerTreeHostCommonTest, AnimationsForRenderSurfaceHierarchy) { layer_transform.Translate(1.0, 1.0); root->test_properties()->transform = layer_transform; - root->SetPosition(gfx::PointF(2.5f, 0.f)); root->SetBounds(gfx::Size(10, 10)); root->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); render_surface1->test_properties()->transform = layer_transform; - render_surface1->SetPosition(gfx::PointF(2.5f, 0.f)); + render_surface1->test_properties()->position = gfx::PointF(2.5f, 0.f); render_surface1->SetBounds(gfx::Size(10, 10)); render_surface1->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); render_surface1->test_properties()->force_render_surface = true; render_surface2->test_properties()->transform = layer_transform; - render_surface2->SetPosition(gfx::PointF(2.5f, 0.f)); + render_surface2->test_properties()->position = gfx::PointF(2.5f, 0.f); render_surface2->SetBounds(gfx::Size(10, 10)); render_surface2->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); render_surface2->test_properties()->force_render_surface = true; child_of_root->test_properties()->transform = layer_transform; - child_of_root->SetPosition(gfx::PointF(2.5f, 0.f)); + child_of_root->test_properties()->position = gfx::PointF(2.5f, 0.f); child_of_root->SetBounds(gfx::Size(10, 10)); child_of_root->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); child_of_rs1->test_properties()->transform = layer_transform; - child_of_rs1->SetPosition(gfx::PointF(2.5f, 0.f)); + child_of_rs1->test_properties()->position = gfx::PointF(2.5f, 0.f); child_of_rs1->SetBounds(gfx::Size(10, 10)); child_of_rs1->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); child_of_rs2->test_properties()->transform = layer_transform; - child_of_rs2->SetPosition(gfx::PointF(2.5f, 0.f)); + child_of_rs2->test_properties()->position = gfx::PointF(2.5f, 0.f); child_of_rs2->SetBounds(gfx::Size(10, 10)); child_of_rs2->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); grand_child_of_root->test_properties()->transform = layer_transform; - grand_child_of_root->SetPosition(gfx::PointF(2.5f, 0.f)); + grand_child_of_root->test_properties()->position = gfx::PointF(2.5f, 0.f); grand_child_of_root->SetBounds(gfx::Size(10, 10)); grand_child_of_root->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); grand_child_of_rs1->test_properties()->transform = layer_transform; - grand_child_of_rs1->SetPosition(gfx::PointF(2.5f, 0.f)); + grand_child_of_rs1->test_properties()->position = gfx::PointF(2.5f, 0.f); grand_child_of_rs1->SetBounds(gfx::Size(10, 10)); grand_child_of_rs1->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); grand_child_of_rs2->test_properties()->transform = layer_transform; - grand_child_of_rs2->SetPosition(gfx::PointF(2.5f, 0.f)); + grand_child_of_rs2->test_properties()->position = gfx::PointF(2.5f, 0.f); grand_child_of_rs2->SetBounds(gfx::Size(10, 10)); grand_child_of_rs2->test_properties()->transform_origin = gfx::Point3F(0.25f, 0.f, 0.f); @@ -2548,23 +2548,6 @@ TEST_F(LayerTreeHostCommonDrawRectsTest, DrawRectsForPerspectiveUnprojection) { drawing_layer->drawable_content_rect()); } -TEST_F(LayerTreeHostCommonTest, - VisibleRectsForPositionedRootLayerClippedByViewport) { - LayerImpl* root = root_layer_for_testing(); - - root->SetPosition(gfx::PointF(60, 70)); - root->SetBounds(gfx::Size(100, 100)); - root->SetDrawsContent(true); - ExecuteCalculateDrawProperties(root); - - EXPECT_EQ(gfx::RectF(100.f, 100.f), - GetRenderSurface(root)->DrawableContentRect()); - // In target space, not clipped. - EXPECT_EQ(gfx::Rect(60, 70, 100, 100), root->drawable_content_rect()); - // In layer space, clipped. - EXPECT_EQ(gfx::Rect(40, 30), root->visible_layer_rect()); -} - TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSimpleLayers) { LayerImpl* root = root_layer_for_testing(); LayerImpl* child1_layer = AddChildToRoot<LayerImpl>(); @@ -2574,10 +2557,10 @@ TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsForSimpleLayers) { root->SetBounds(gfx::Size(100, 100)); child1_layer->SetBounds(gfx::Size(50, 50)); child1_layer->SetDrawsContent(true); - child2_layer->SetPosition(gfx::PointF(75.f, 75.f)); + child2_layer->test_properties()->position = gfx::PointF(75.f, 75.f); child2_layer->SetBounds(gfx::Size(50, 50)); child2_layer->SetDrawsContent(true); - child3_layer->SetPosition(gfx::PointF(125.f, 125.f)); + child3_layer->test_properties()->position = gfx::PointF(125.f, 125.f); child3_layer->SetBounds(gfx::Size(50, 50)); child3_layer->SetDrawsContent(true); ExecuteCalculateDrawProperties(root); @@ -2610,13 +2593,13 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(100, 100)); child->SetBounds(gfx::Size(100, 100)); child->SetMasksToBounds(true); - grand_child1->SetPosition(gfx::PointF(5.f, 5.f)); + grand_child1->test_properties()->position = gfx::PointF(5.f, 5.f); grand_child1->SetBounds(gfx::Size(50, 50)); grand_child1->SetDrawsContent(true); - grand_child2->SetPosition(gfx::PointF(75.f, 75.f)); + grand_child2->test_properties()->position = gfx::PointF(75.f, 75.f); grand_child2->SetBounds(gfx::Size(50, 50)); grand_child2->SetDrawsContent(true); - grand_child3->SetPosition(gfx::PointF(125.f, 125.f)); + grand_child3->test_properties()->position = gfx::PointF(125.f, 125.f); grand_child3->SetBounds(gfx::Size(50, 50)); grand_child3->SetDrawsContent(true); ExecuteCalculateDrawProperties(root); @@ -2672,7 +2655,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectWithClippingAndFilters) { clip->SetBounds(gfx::Size(10, 10)); filter->test_properties()->force_render_surface = true; filter_child->SetBounds(gfx::Size(2000, 2000)); - filter_child->SetPosition(gfx::PointF(-50, -50)); + filter_child->test_properties()->position = gfx::PointF(-50, -50); filter_child->SetDrawsContent(true); clip->SetMasksToBounds(true); @@ -2721,7 +2704,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectWithScalingClippingAndFilters) { clip->SetBounds(gfx::Size(10, 10)); filter->test_properties()->force_render_surface = true; filter_child->SetBounds(gfx::Size(2000, 2000)); - filter_child->SetPosition(gfx::PointF(-50, -50)); + filter_child->test_properties()->position = gfx::PointF(-50, -50); filter_child->SetDrawsContent(true); clip->SetMasksToBounds(true); @@ -2847,13 +2830,13 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(100, 100)); render_surface->SetBounds(gfx::Size(3, 4)); render_surface->test_properties()->force_render_surface = true; - child1->SetPosition(gfx::PointF(5.f, 5.f)); + child1->test_properties()->position = gfx::PointF(5.f, 5.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); - child2->SetPosition(gfx::PointF(75.f, 75.f)); + child2->test_properties()->position = gfx::PointF(75.f, 75.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); - child3->SetPosition(gfx::PointF(125.f, 125.f)); + child3->test_properties()->position = gfx::PointF(125.f, 125.f); child3->SetBounds(gfx::Size(50, 50)); child3->SetDrawsContent(true); ExecuteCalculateDrawProperties(root); @@ -2891,13 +2874,13 @@ TEST_F(LayerTreeHostCommonTest, LayerImpl* child3 = AddChild<LayerImpl>(root); root->SetBounds(gfx::Size(100, 100)); - child1->SetPosition(gfx::PointF(5.f, 5.f)); + child1->test_properties()->position = gfx::PointF(5.f, 5.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); - child2->SetPosition(gfx::PointF(75.f, 75.f)); + child2->test_properties()->position = gfx::PointF(75.f, 75.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); - child3->SetPosition(gfx::PointF(125.f, 125.f)); + child3->test_properties()->position = gfx::PointF(125.f, 125.f); child3->SetBounds(gfx::Size(50, 50)); child3->SetDrawsContent(true); @@ -2928,7 +2911,7 @@ TEST_F(LayerTreeHostCommonTest, LayerImpl* child = AddChildToRoot<LayerImpl>(); root->SetBounds(gfx::Size(100, 100)); - child->SetPosition(gfx::PointF(5.f, 5.f)); + child->test_properties()->position = gfx::PointF(5.f, 5.f); child->SetBounds(gfx::Size(50, 50)); child->SetDrawsContent(true); @@ -2981,7 +2964,7 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(100, 100)); child->test_properties()->transform = perspective; - child->SetPosition(gfx::PointF(10.f, 10.f)); + child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(100, 100)); child->SetDrawsContent(true); child->test_properties()->sorting_context_id = 1; @@ -3145,7 +3128,7 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(1000, 1000)); child->test_properties()->transform = perspective; - child->SetPosition(gfx::PointF(10.f, 10.f)); + child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(300, 300)); child->test_properties()->should_flatten_transform = false; child->test_properties()->sorting_context_id = 1; @@ -3209,13 +3192,13 @@ TEST_F(LayerTreeHostCommonTest, root->SetMasksToBounds(true); render_surface->SetBounds(gfx::Size(3, 4)); render_surface->test_properties()->force_render_surface = true; - child1->SetPosition(gfx::PointF(5.f, 5.f)); + child1->test_properties()->position = gfx::PointF(5.f, 5.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); - child2->SetPosition(gfx::PointF(75.f, 75.f)); + child2->test_properties()->position = gfx::PointF(75.f, 75.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); - child3->SetPosition(gfx::PointF(125.f, 125.f)); + child3->test_properties()->position = gfx::PointF(125.f, 125.f); child3->SetBounds(gfx::Size(50, 50)); child3->SetDrawsContent(true); ExecuteCalculateDrawProperties(root); @@ -3262,13 +3245,13 @@ TEST_F(LayerTreeHostCommonTest, render_surface1->test_properties()->force_render_surface = true; render_surface2->SetBounds(gfx::Size(7, 13)); render_surface2->test_properties()->force_render_surface = true; - child1->SetPosition(gfx::PointF(5.f, 5.f)); + child1->test_properties()->position = gfx::PointF(5.f, 5.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); - child2->SetPosition(gfx::PointF(75.f, 75.f)); + child2->test_properties()->position = gfx::PointF(75.f, 75.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); - child3->SetPosition(gfx::PointF(125.f, 125.f)); + child3->test_properties()->position = gfx::PointF(125.f, 125.f); child3->SetBounds(gfx::Size(50, 50)); child3->SetDrawsContent(true); ExecuteCalculateDrawProperties(root); @@ -3378,7 +3361,7 @@ TEST_F(LayerTreeHostCommonTest, ClipRectOfSurfaceWhoseParentIsAClipChild) { root->SetBounds(gfx::Size(100, 100)); - clip_parent->SetPosition(gfx::PointF(2.f, 2.f)); + clip_parent->test_properties()->position = gfx::PointF(2.f, 2.f); clip_parent->SetBounds(gfx::Size(50, 50)); clip_parent->test_properties()->clip_children = std::make_unique<std::set<LayerImpl*>>(); @@ -3530,7 +3513,7 @@ TEST_F(LayerTreeHostCommonTest, render_surface->SetBounds(gfx::Size(3, 4)); render_surface->test_properties()->force_render_surface = true; child1->test_properties()->transform = child_rotation; - child1->SetPosition(gfx::PointF(25.f, 25.f)); + child1->test_properties()->position = gfx::PointF(25.f, 25.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); child1->test_properties()->transform_origin = gfx::Point3F(25.f, 25.f, 0.f); @@ -3576,7 +3559,7 @@ TEST_F(LayerTreeHostCommonTest, root->SetMasksToBounds(true); render_surface->SetBounds(gfx::Size(3, 4)); render_surface->test_properties()->force_render_surface = true; - child1->SetPosition(gfx::PointF(25.f, 25.f)); + child1->test_properties()->position = gfx::PointF(25.f, 25.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); child1->test_properties()->transform = child_rotation; @@ -3622,21 +3605,21 @@ TEST_F(LayerTreeHostCommonTest, DrawableAndVisibleContentRectsInHighDPI) { root->SetBounds(gfx::Size(100, 100)); root->SetMasksToBounds(true); render_surface1->SetBounds(gfx::Size(3, 4)); - render_surface1->SetPosition(gfx::PointF(5.f, 5.f)); + render_surface1->test_properties()->position = gfx::PointF(5.f, 5.f); render_surface1->SetDrawsContent(true); render_surface1->test_properties()->force_render_surface = true; render_surface2->SetBounds(gfx::Size(7, 13)); - render_surface2->SetPosition(gfx::PointF(5.f, 5.f)); + render_surface2->test_properties()->position = gfx::PointF(5.f, 5.f); render_surface2->SetDrawsContent(true); render_surface2->test_properties()->force_render_surface = true; child1->SetBounds(gfx::Size(50, 50)); - child1->SetPosition(gfx::PointF(5.f, 5.f)); + child1->test_properties()->position = gfx::PointF(5.f, 5.f); child1->SetDrawsContent(true); child2->SetBounds(gfx::Size(50, 50)); - child2->SetPosition(gfx::PointF(75.f, 75.f)); + child2->test_properties()->position = gfx::PointF(75.f, 75.f); child2->SetDrawsContent(true); child3->SetBounds(gfx::Size(50, 50)); - child3->SetPosition(gfx::PointF(125.f, 125.f)); + child3->test_properties()->position = gfx::PointF(125.f, 125.f); child3->SetDrawsContent(true); float device_scale_factor = 2.f; ExecuteCalculateDrawProperties(root, device_scale_factor); @@ -4020,12 +4003,12 @@ TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) { root->SetDrawsContent(true); LayerImpl* child = AddChildToRoot<LayerImpl>(); - child->SetPosition(gfx::PointF(2.f, 2.f)); + child->test_properties()->position = gfx::PointF(2.f, 2.f); child->SetBounds(gfx::Size(10, 10)); child->SetDrawsContent(true); LayerImpl* child2 = AddChildToRoot<LayerImpl>(); - child2->SetPosition(gfx::PointF(2.f, 2.f)); + child2->test_properties()->position = gfx::PointF(2.f, 2.f); child2->SetBounds(gfx::Size(5, 5)); child2->SetDrawsContent(true); @@ -4062,8 +4045,8 @@ TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) { // Verify child and child2 transforms. They should match. gfx::Transform expected_child_transform; expected_child_transform.Scale(device_scale_factor, device_scale_factor); - expected_child_transform.Translate(child->position().x(), - child->position().y()); + expected_child_transform.Translate(child->test_properties()->position.x(), + child->test_properties()->position.y()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, child->DrawTransform()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform, @@ -4087,7 +4070,7 @@ TEST_F(LayerTreeHostCommonScalingTest, LayerTransformsInHighDPI) { gfx::RectF child2_screen_space_rect = MathUtil::MapClippedRect(child2->ScreenSpaceTransform(), child_bounds); - gfx::RectF expected_child_draw_rect(child->position(), + gfx::RectF expected_child_draw_rect(child->test_properties()->position, gfx::SizeF(child->bounds())); expected_child_draw_rect.Scale(device_scale_factor); EXPECT_FLOAT_RECT_EQ(expected_child_draw_rect, child_draw_rect); @@ -4115,7 +4098,7 @@ TEST_F(LayerTreeHostCommonScalingTest, SurfaceLayerTransformsInHighDPI) { parent->SetDrawsContent(true); LayerImpl* perspective_surface = AddChild<LayerImpl>(parent); - perspective_surface->SetPosition(gfx::PointF(2.f, 2.f)); + perspective_surface->test_properties()->position = gfx::PointF(2.f, 2.f); perspective_surface->SetBounds(gfx::Size(10, 10)); perspective_surface->test_properties()->transform = perspective_matrix * scale_small_matrix; @@ -4123,7 +4106,7 @@ TEST_F(LayerTreeHostCommonScalingTest, SurfaceLayerTransformsInHighDPI) { perspective_surface->test_properties()->force_render_surface = true; LayerImpl* scale_surface = AddChild<LayerImpl>(parent); - scale_surface->SetPosition(gfx::PointF(2.f, 2.f)); + scale_surface->test_properties()->position = gfx::PointF(2.f, 2.f); scale_surface->SetBounds(gfx::Size(10, 10)); scale_surface->test_properties()->transform = scale_small_matrix; scale_surface->SetDrawsContent(true); @@ -4176,9 +4159,9 @@ TEST_F(LayerTreeHostCommonScalingTest, SurfaceLayerTransformsInHighDPI) { gfx::Transform expected_perspective_surface_draw_transform; expected_perspective_surface_draw_transform.Translate( device_scale_factor * page_scale_factor * - perspective_surface->position().x(), + perspective_surface->test_properties()->position.x(), device_scale_factor * page_scale_factor * - perspective_surface->position().y()); + perspective_surface->test_properties()->position.y()); expected_perspective_surface_draw_transform.PreconcatTransform( perspective_matrix); expected_perspective_surface_draw_transform.PreconcatTransform( @@ -4213,7 +4196,7 @@ TEST_F(LayerTreeHostCommonScalingTest, SmallIdealScale) { parent->SetDrawsContent(true); LayerImpl* child_scale = AddChild<LayerImpl>(parent); - child_scale->SetPosition(gfx::PointF(2.f, 2.f)); + child_scale->test_properties()->position = gfx::PointF(2.f, 2.f); child_scale->SetBounds(gfx::Size(10, 10)); child_scale->test_properties()->transform = child_scale_matrix; child_scale->SetDrawsContent(true); @@ -4257,7 +4240,7 @@ TEST_F(LayerTreeHostCommonScalingTest, IdealScaleForAnimatingLayer) { LayerImpl* child_scale = AddChild<LayerImpl>(parent); child_scale->SetBounds(gfx::Size(10, 10)); - child_scale->SetPosition(gfx::PointF(2.f, 2.f)); + child_scale->test_properties()->position = gfx::PointF(2.f, 2.f); child_scale->test_properties()->transform = child_scale_matrix; child_scale->SetDrawsContent(true); @@ -4279,7 +4262,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { LayerImpl* child = AddChildToRoot<LayerImpl>(); child->SetBounds(gfx::Size(10, 10)); - child->SetPosition(gfx::PointF(2.f, 2.f)); + child->test_properties()->position = gfx::PointF(2.f, 2.f); child->SetDrawsContent(true); child->test_properties()->force_render_surface = true; @@ -4311,8 +4294,9 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { gfx::Transform expected_screen_space_transform; expected_screen_space_transform.Scale(device_scale_factor, device_scale_factor); - expected_screen_space_transform.Translate(child->position().x(), - child->position().y()); + expected_screen_space_transform.Translate( + child->test_properties()->position.x(), + child->test_properties()->position.y()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_screen_space_transform, child->ScreenSpaceTransform()); @@ -4329,8 +4313,8 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceTransformsInHighDPI) { gfx::Transform expected_render_surface_draw_transform; expected_render_surface_draw_transform.Translate( - device_scale_factor * child->position().x(), - device_scale_factor * child->position().y()); + device_scale_factor * child->test_properties()->position.x(), + device_scale_factor * child->test_properties()->position.y()); EXPECT_TRANSFORMATION_MATRIX_EQ(expected_render_surface_draw_transform, GetRenderSurface(child)->draw_transform()); @@ -5075,7 +5059,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectInNonRootCopyRequest) { copy_layer->test_properties()->force_render_surface = true; LayerImpl* copy_child = AddChild<LayerImpl>(copy_layer); - copy_child->SetPosition(gfx::PointF(40.f, 40.f)); + copy_child->test_properties()->position = gfx::PointF(40.f, 40.f); copy_child->SetBounds(gfx::Size(20, 20)); copy_child->SetDrawsContent(true); @@ -5084,12 +5068,12 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectInNonRootCopyRequest) { copy_clip->SetMasksToBounds(true); LayerImpl* copy_clipped_child = AddChild<LayerImpl>(copy_clip); - copy_clipped_child->SetPosition(gfx::PointF(40.f, 40.f)); + copy_clipped_child->test_properties()->position = gfx::PointF(40.f, 40.f); copy_clipped_child->SetBounds(gfx::Size(20, 20)); copy_clipped_child->SetDrawsContent(true); LayerImpl* copy_surface = AddChild<LayerImpl>(copy_clip); - copy_surface->SetPosition(gfx::PointF(45.f, 45.f)); + copy_surface->test_properties()->position = gfx::PointF(45.f, 45.f); copy_surface->SetBounds(gfx::Size(20, 20)); copy_surface->SetDrawsContent(true); copy_surface->test_properties()->force_render_surface = true; @@ -5172,11 +5156,11 @@ TEST_F(LayerTreeHostCommonTest, TransformedClipParent) { render_surface->SetBounds(gfx::Size(10, 10)); render_surface->test_properties()->force_render_surface = true; clip_parent->test_properties()->transform = scale_transform; - clip_parent->SetPosition(gfx::PointF(1.f, 1.f)); + clip_parent->test_properties()->position = gfx::PointF(1.f, 1.f); clip_parent->SetBounds(gfx::Size(10, 10)); - intervening->SetPosition(gfx::PointF(1.f, 1.f)); + intervening->test_properties()->position = gfx::PointF(1.f, 1.f); intervening->SetBounds(gfx::Size(5, 5)); - clip_child->SetPosition(gfx::PointF(1.f, 1.f)); + clip_child->test_properties()->position = gfx::PointF(1.f, 1.f); clip_child->SetBounds(gfx::Size(10, 10)); ExecuteCalculateDrawProperties(root); @@ -5233,15 +5217,15 @@ TEST_F(LayerTreeHostCommonTest, ClipParentWithInterveningRenderSurface) { translation_transform.Translate(2, 2); root->SetBounds(gfx::Size(50, 50)); - clip_parent->SetPosition(gfx::PointF(1.f, 1.f)); + clip_parent->test_properties()->position = gfx::PointF(1.f, 1.f); clip_parent->SetBounds(gfx::Size(40, 40)); render_surface1->SetBounds(gfx::Size(10, 10)); render_surface1->test_properties()->force_render_surface = true; - intervening->SetPosition(gfx::PointF(1.f, 1.f)); + intervening->test_properties()->position = gfx::PointF(1.f, 1.f); intervening->SetBounds(gfx::Size(5, 5)); render_surface2->SetBounds(gfx::Size(10, 10)); render_surface2->test_properties()->force_render_surface = true; - clip_child->SetPosition(gfx::PointF(-10.f, -10.f)); + clip_child->test_properties()->position = gfx::PointF(-10.f, -10.f); clip_child->SetBounds(gfx::Size(60, 60)); ExecuteCalculateDrawProperties(root); @@ -5319,15 +5303,15 @@ TEST_F(LayerTreeHostCommonTest, ClipParentScrolledInterveningLayer) { root->SetBounds(gfx::Size(50, 50)); clip_parent->test_properties()->transform = translation_transform; - clip_parent->SetPosition(gfx::PointF(1.f, 1.f)); + clip_parent->test_properties()->position = gfx::PointF(1.f, 1.f); clip_parent->SetBounds(gfx::Size(40, 40)); render_surface1->SetBounds(gfx::Size(10, 10)); render_surface1->test_properties()->force_render_surface = true; - intervening->SetPosition(gfx::PointF(1.f, 1.f)); + intervening->test_properties()->position = gfx::PointF(1.f, 1.f); intervening->SetBounds(gfx::Size(5, 5)); render_surface2->SetBounds(gfx::Size(10, 10)); render_surface2->test_properties()->force_render_surface = true; - clip_child->SetPosition(gfx::PointF(-10.f, -10.f)); + clip_child->test_properties()->position = gfx::PointF(-10.f, -10.f); clip_child->SetBounds(gfx::Size(60, 60)); BuildPropertyTreesForTesting(); intervening->SetCurrentScrollOffset(gfx::ScrollOffset(3, 3)); @@ -5452,12 +5436,12 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(15, 15)); clip_parent->SetBounds(gfx::Size(10, 10)); clip_layer->SetBounds(gfx::Size(10, 10)); - render_surface1->SetPosition(gfx::PointF(5, 5)); + render_surface1->test_properties()->position = gfx::PointF(5, 5); render_surface1->SetBounds(gfx::Size(5, 5)); render_surface1->test_properties()->force_render_surface = true; render_surface2->SetBounds(gfx::Size(5, 5)); render_surface2->test_properties()->force_render_surface = true; - clip_child->SetPosition(gfx::PointF(-1, 1)); + clip_child->test_properties()->position = gfx::PointF(-1, 1); clip_child->SetBounds(gfx::Size(10, 10)); non_clip_child->SetBounds(gfx::Size(5, 5)); @@ -5744,7 +5728,7 @@ TEST_F(LayerTreeHostCommonTest, ScrollChildAndScrollParentDifferentTargets) { scroll_child_target->SetBounds(gfx::Size(50, 50)); scroll_child_target->test_properties()->force_render_surface = true; scroll_child->SetBounds(gfx::Size(50, 50)); - scroll_parent_target->SetPosition(gfx::PointF(10, 10)); + scroll_parent_target->test_properties()->position = gfx::PointF(10, 10); scroll_parent_target->SetBounds(gfx::Size(50, 50)); scroll_parent_target->SetMasksToBounds(true); scroll_parent_target->test_properties()->force_render_surface = true; @@ -6001,13 +5985,13 @@ TEST_F(LayerTreeHostCommonTest, FixedPositionWithInterveningRenderSurface) { fixed->test_properties()->position_constraint = constraint; root->SetBounds(gfx::Size(50, 50)); - render_surface->SetPosition(gfx::PointF(7.f, 9.f)); + render_surface->test_properties()->position = gfx::PointF(7.f, 9.f); render_surface->SetBounds(gfx::Size(50, 50)); render_surface->SetDrawsContent(true); - fixed->SetPosition(gfx::PointF(10.f, 15.f)); + fixed->test_properties()->position = gfx::PointF(10.f, 15.f); fixed->SetBounds(gfx::Size(50, 50)); fixed->SetDrawsContent(true); - child->SetPosition(gfx::PointF(1.f, 2.f)); + child->test_properties()->position = gfx::PointF(1.f, 2.f); child->SetBounds(gfx::Size(50, 50)); child->SetDrawsContent(true); ExecuteCalculateDrawProperties(root); @@ -8422,9 +8406,9 @@ TEST_F(LayerTreeHostCommonTest, PropertyTreesAccountForFixedParentOffset) { root->SetBounds(gfx::Size(50, 50)); root->SetMasksToBounds(true); root->test_properties()->is_container_for_fixed_position_layers = true; - child->SetPosition(gfx::PointF(1000, 1000)); + child->test_properties()->position = gfx::PointF(1000, 1000); child->SetBounds(gfx::Size(50, 50)); - grandchild->SetPosition(gfx::PointF(-1000, -1000)); + grandchild->test_properties()->position = gfx::PointF(-1000, -1000); grandchild->SetBounds(gfx::Size(50, 50)); grandchild->SetDrawsContent(true); @@ -8450,10 +8434,10 @@ TEST_F(LayerTreeHostCommonTest, root->SetBounds(gfx::Size(50, 50)); root->SetMasksToBounds(true); root->test_properties()->is_container_for_fixed_position_layers = true; - child->SetPosition(gfx::PointF(1000, 1000)); + child->test_properties()->position = gfx::PointF(1000, 1000); child->SetBounds(gfx::Size(50, 50)); child->test_properties()->is_container_for_fixed_position_layers = true; - grandchild->SetPosition(gfx::PointF(-1000, -1000)); + grandchild->test_properties()->position = gfx::PointF(-1000, -1000); grandchild->SetBounds(gfx::Size(50, 50)); grandchild->SetDrawsContent(true); @@ -8476,7 +8460,7 @@ TEST_F(LayerTreeHostCommonTest, OnlyApplyFixedPositioningOnce) { root->SetBounds(gfx::Size(800, 800)); root->test_properties()->is_container_for_fixed_position_layers = true; - frame_clip->SetPosition(gfx::PointF(500, 100)); + frame_clip->test_properties()->position = gfx::PointF(500, 100); frame_clip->SetBounds(gfx::Size(100, 100)); frame_clip->SetMasksToBounds(true); @@ -8502,7 +8486,7 @@ TEST_F(LayerTreeHostCommonTest, FixedClipsShouldBeAssociatedWithTheRightNode) { root->SetBounds(gfx::Size(800, 800)); root->SetDrawsContent(true); root->test_properties()->is_container_for_fixed_position_layers = true; - frame_clip->SetPosition(gfx::PointF(500, 100)); + frame_clip->test_properties()->position = gfx::PointF(500, 100); frame_clip->SetBounds(gfx::Size(100, 100)); frame_clip->SetMasksToBounds(true); frame_clip->SetDrawsContent(true); @@ -8511,7 +8495,7 @@ TEST_F(LayerTreeHostCommonTest, FixedClipsShouldBeAssociatedWithTheRightNode) { scroller->SetElementId(LayerIdToElementIdForTesting(scroller->id())); scroller->SetScrollable(frame_clip->bounds()); scroller->SetDrawsContent(true); - fixed->SetPosition(gfx::PointF(100, 100)); + fixed->test_properties()->position = gfx::PointF(100, 100); fixed->SetBounds(gfx::Size(50, 50)); fixed->SetMasksToBounds(true); fixed->SetDrawsContent(true); @@ -8599,7 +8583,7 @@ TEST_F(LayerTreeHostCommonTest, UpdateScrollChildPosition) { ExecuteCalculateDrawProperties(root); EXPECT_EQ(gfx::Rect(25, 25), scroll_child->visible_layer_rect()); - scroll_child->SetPosition(gfx::PointF(0, -10.f)); + scroll_child->test_properties()->position = gfx::PointF(0, -10.f); scroll_parent->SetCurrentScrollOffset(gfx::ScrollOffset(0.f, 10.f)); ExecuteCalculateDrawProperties(root); EXPECT_EQ(gfx::Rect(0, 5, 25, 25), scroll_child->visible_layer_rect()); @@ -9569,7 +9553,7 @@ TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) { root->SetMasksToBounds(true); clip_layer->SetBounds(gfx::Size(30, 30)); clip_layer->SetMasksToBounds(true); - render_surface1->SetPosition(gfx::PointF(10, 10)); + render_surface1->test_properties()->position = gfx::PointF(10, 10); render_surface1->SetBounds(gfx::Size(30, 30)); render_surface1->SetDrawsContent(true); render_surface1->test_properties()->force_render_surface = true; @@ -10031,7 +10015,7 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { scroll_parent2.element_id = parent2->element_id(); scroll_parent2.scrollable = true; scroll_parent2.main_thread_scrolling_reasons = - parent2->main_thread_scrolling_reasons(); + parent2->GetMainThreadScrollingReasons(); scroll_parent2.container_bounds = root1->bounds(); scroll_parent2.bounds = parent2->bounds(); scroll_parent2.max_scroll_offset_affected_by_page_scale = true; @@ -10045,7 +10029,7 @@ TEST_F(LayerTreeHostCommonTest, ScrollTreeBuilderTest) { ScrollNode scroll_child6; scroll_child6.id = 3; scroll_child6.main_thread_scrolling_reasons = - child6->main_thread_scrolling_reasons(); + child6->GetMainThreadScrollingReasons(); scroll_child6.should_flatten = true; scroll_child6.user_scrollable_horizontal = true; scroll_child6.user_scrollable_vertical = true; @@ -10354,7 +10338,7 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectInNonRootCacheRenderSurface) { copy_layer->test_properties()->force_render_surface = true; LayerImpl* copy_child = AddChild<LayerImpl>(copy_layer); - copy_child->SetPosition(gfx::PointF(40.f, 40.f)); + copy_child->test_properties()->position = gfx::PointF(40.f, 40.f); copy_child->SetBounds(gfx::Size(20, 20)); copy_child->SetDrawsContent(true); @@ -10363,12 +10347,12 @@ TEST_F(LayerTreeHostCommonTest, VisibleRectInNonRootCacheRenderSurface) { copy_clip->SetMasksToBounds(true); LayerImpl* copy_clipped_child = AddChild<LayerImpl>(copy_clip); - copy_clipped_child->SetPosition(gfx::PointF(40.f, 40.f)); + copy_clipped_child->test_properties()->position = gfx::PointF(40.f, 40.f); copy_clipped_child->SetBounds(gfx::Size(20, 20)); copy_clipped_child->SetDrawsContent(true); LayerImpl* cache_surface = AddChild<LayerImpl>(copy_clip); - cache_surface->SetPosition(gfx::PointF(45.f, 45.f)); + cache_surface->test_properties()->position = gfx::PointF(45.f, 45.f); cache_surface->SetBounds(gfx::Size(20, 20)); cache_surface->SetDrawsContent(true); @@ -10495,7 +10479,7 @@ TEST_F(LayerTreeHostCommonTest, RenderSurfaceListForTrilinearFiltering) { child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); child1->test_properties()->force_render_surface = true; - child2->SetPosition(gfx::PointF(50, 50)); + child2->test_properties()->position = gfx::PointF(50, 50); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); child2->test_properties()->force_render_surface = true; diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc index dcfc217ced6..6a44080f309 100644 --- a/chromium/cc/trees/layer_tree_host_impl.cc +++ b/chromium/cc/trees/layer_tree_host_impl.cc @@ -50,6 +50,7 @@ #include "cc/layers/scrollbar_layer_impl_base.h" #include "cc/layers/surface_layer_impl.h" #include "cc/layers/viewport.h" +#include "cc/paint/paint_worklet_layer_painter.h" #include "cc/raster/bitmap_raster_buffer_provider.h" #include "cc/raster/gpu_raster_buffer_provider.h" #include "cc/raster/one_copy_raster_buffer_provider.h" @@ -86,7 +87,6 @@ #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/delay_based_time_source.h" -#include "components/viz/common/gpu/texture_allocation.h" #include "components/viz/common/hit_test/hit_test_region_list.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/quads/compositor_frame_metadata.h" @@ -97,11 +97,14 @@ #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/platform_color.h" +#include "components/viz/common/resources/resource_sizes.h" #include "components/viz/common/traced_value.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/raster_interface.h" +#include "gpu/command_buffer/client/shared_image_interface.h" +#include "gpu/command_buffer/common/shared_image_usage.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/skia/include/gpu/GrContext.h" #include "ui/gfx/geometry/point_conversions.h" @@ -1066,12 +1069,6 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { active_tree()->property_trees()->effect_tree.HasCopyRequests(); bool have_missing_animated_tiles = false; - int num_layers = 0; - int num_mask_layers = 0; - int num_rounded_corner_mask_layers = 0; - int64_t visible_mask_layer_area = 0; - int64_t visible_rounded_corner_mask_layer_area = 0; - for (EffectTreeLayerListIterator it(active_tree()); it.state() != EffectTreeLayerListIterator::State::END; ++it) { auto target_render_pass_id = it.target_render_surface()->id(); @@ -1106,7 +1103,6 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { frame->may_contain_video = true; layer->AppendQuads(target_render_pass, &append_quads_data); - ++num_layers; } rendering_stats_instrumentation_->AddVisibleContentArea( @@ -1146,12 +1142,6 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { } frame->use_default_lower_bound_deadline |= append_quads_data.use_default_lower_bound_deadline; - num_mask_layers += append_quads_data.num_mask_layers; - num_rounded_corner_mask_layers += - append_quads_data.num_rounded_corner_mask_layers; - visible_mask_layer_area += append_quads_data.visible_mask_layer_area; - visible_rounded_corner_mask_layer_area += - append_quads_data.visible_rounded_corner_mask_layer_area; } // If CommitToActiveTree() is true, then we wait to draw until @@ -1231,34 +1221,6 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { checkerboarded_needs_raster_content_area); } - // Only record these umas on the first frame, and only in the renderer, - // for which we use having a compositor thread as a proxy. - if (!active_tree_->has_ever_been_drawn() && SupportsImplScrolling()) { - int mask_layer_percent = static_cast<int>( - num_mask_layers / static_cast<float>(num_layers) * 100); - int rc_mask_layer_percent = - static_cast<int>(num_rounded_corner_mask_layers / - static_cast<float>(num_mask_layers) * 100); - int rc_area_percent = - static_cast<int>(visible_rounded_corner_mask_layer_area / - static_cast<float>(total_visible_area) * 100); - - UMA_HISTOGRAM_PERCENTAGE( - "Compositing.RenderPass.AppendQuadData.MaskLayerPercent", - mask_layer_percent); - if (num_mask_layers > 0) { - UMA_HISTOGRAM_PERCENTAGE( - "Compositing.RenderPass.AppendQuadData.RCMaskLayerPercent", - rc_mask_layer_percent); - UMA_HISTOGRAM_PERCENTAGE( - "Compositing.RenderPass.AppendQuadData.RCMaskAreaPercent", - rc_area_percent); - UMA_HISTOGRAM_COUNTS_10M( - "Compositing.RenderPass.AppendQuadData.RCMaskArea", - visible_rounded_corner_mask_layer_area); - } - } - TRACE_EVENT_END2("cc,benchmark", "LayerTreeHostImpl::CalculateRenderPasses", "draw_result", draw_result, "missing tiles", num_missing_tiles); @@ -1724,9 +1686,9 @@ void LayerTreeHostImpl::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { } void LayerTreeHostImpl::SetTreeActivationCallback( - const base::Closure& callback) { + base::RepeatingClosure callback) { DCHECK(task_runner_provider_->IsImplThread()); - tree_activation_callback_ = callback; + tree_activation_callback_ = std::move(callback); } void LayerTreeHostImpl::SetManagedMemoryPolicy( @@ -1916,10 +1878,7 @@ void LayerTreeHostImpl::OnCanDrawStateChangedForTree() { viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { viz::CompositorFrameMetadata metadata; - metadata.frame_token = next_frame_token_++; - if (!next_frame_token_) - next_frame_token_ = 1u; - + metadata.frame_token = ++next_frame_token_; metadata.device_scale_factor = active_tree_->painted_device_scale_factor() * active_tree_->device_scale_factor(); @@ -1928,9 +1887,7 @@ viz::CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() { metadata.root_background_color = active_tree_->background_color(); metadata.content_source_id = active_tree_->content_source_id(); - if (active_tree_->has_presentation_callbacks() || - settings_.always_request_presentation_time) { - metadata.request_presentation_feedback = true; + if (active_tree_->has_presentation_callbacks()) { frame_token_infos_.emplace_back(metadata.frame_token, CurrentBeginFrameArgs().frame_time, active_tree_->TakePresentationCallbacks()); @@ -2064,7 +2021,7 @@ RenderFrameMetadata LayerTreeHostImpl::MakeRenderFrameMetadata( if (child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation() .IsValid()) { if (allocate_new_local_surface_id) - child_local_surface_id_allocator_.GenerateId(); + AllocateLocalSurfaceId(); metadata.local_surface_id_allocation = child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); } @@ -2086,9 +2043,13 @@ bool LayerTreeHostImpl::DrawLayers(FrameData* frame) { return false; } + layer_tree_frame_sink_->set_source_frame_number( + active_tree_->source_frame_number()); + auto compositor_frame = GenerateCompositorFrame(frame); layer_tree_frame_sink_->SubmitCompositorFrame( - std::move(compositor_frame), debug_state_.show_hit_test_borders); + std::move(compositor_frame), + /*hit_test_data_changed=*/false, debug_state_.show_hit_test_borders); // Clears the list of swap promises after calling DidSwap on each of them to // signal that the swap is over. @@ -2174,7 +2135,7 @@ viz::CompositorFrame LayerTreeHostImpl::GenerateCompositorFrame( metadata.activation_dependencies = std::move(frame->activation_dependencies); active_tree()->FinishSwapPromises(&metadata); // The swap-promises should not change the frame-token. - DCHECK_EQ(metadata.frame_token + 1, next_frame_token_); + DCHECK_EQ(metadata.frame_token, *next_frame_token_); if (render_frame_metadata_observer_) { last_draw_render_frame_metadata_ = MakeRenderFrameMetadata(frame); @@ -2654,7 +2615,7 @@ base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { Region overlapping_region; for (const auto* layer : base::Reversed(*active_tree())) { - if (!layer->should_hit_test()) + if (!layer->ShouldHitTest()) continue; if (layer->is_surface_layer()) { @@ -2935,20 +2896,17 @@ void LayerTreeHostImpl::ActivateSyncTree() { child_local_surface_id_allocator_.UpdateFromParent( active_tree()->local_surface_id_allocation_from_parent()); if (active_tree()->TakeNewLocalSurfaceIdRequest()) - child_local_surface_id_allocator_.GenerateId(); + AllocateLocalSurfaceId(); } // Dump property trees and layers if run with: // --vmodule=layer_tree_host_impl=3 if (VLOG_IS_ON(3)) { - std::string property_trees; - base::JSONWriter::WriteWithOptions( - *active_tree_->property_trees()->AsTracedValue()->ToBaseValue(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, &property_trees); VLOG(3) << "After activating sync tree, the active tree:" << "\nproperty_trees:\n" - << property_trees << "\nlayers:\n" - << LayerListAsJson(); + << active_tree_->property_trees()->ToString() << "\n" + << "cc::LayerImpls:\n" + << active_tree_->LayerListAsJson(); } } @@ -3181,6 +3139,11 @@ void LayerTreeHostImpl::SetLayerTreeMutator( mutator_host_->SetLayerTreeMutator(std::move(mutator)); } +void LayerTreeHostImpl::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + tile_manager_.SetPaintWorkletLayerPainter(std::move(painter)); +} + LayerImpl* LayerTreeHostImpl::ViewportMainScrollLayer() { return viewport()->MainScrollLayer(); } @@ -3201,8 +3164,8 @@ void LayerTreeHostImpl::QueueImageDecode(int request_id, // Optimistically specify the current raster color space, since we assume that // it won't change. tile_manager_.decoded_image_tracker().QueueImageDecode( - image, base::Bind(&LayerTreeHostImpl::ImageDecodeFinished, - base::Unretained(this), request_id)); + image, base::BindOnce(&LayerTreeHostImpl::ImageDecodeFinished, + base::Unretained(this), request_id)); tile_manager_.checker_image_tracker().DisallowCheckeringForImage(image); } @@ -3252,8 +3215,12 @@ void LayerTreeHostImpl::CleanUpTileManagerResources() { // contexts. Flushing now helps ensure these are cleaned up quickly // preventing driver cache growth. See crbug.com/643251 if (layer_tree_frame_sink_) { - if (auto* compositor_context = layer_tree_frame_sink_->context_provider()) - compositor_context->ContextGL()->ShallowFlushCHROMIUM(); + if (auto* compositor_context = layer_tree_frame_sink_->context_provider()) { + // TODO(ericrk): Remove ordering barrier once |compositor_context| no + // longer uses GL. + compositor_context->ContextGL()->OrderingBarrierCHROMIUM(); + compositor_context->ContextSupport()->FlushPendingWork(); + } if (auto* worker_context = layer_tree_frame_sink_->worker_context_provider()) { viz::RasterContextProvider::ScopedRasterContextLock hold(worker_context); @@ -3278,6 +3245,8 @@ void LayerTreeHostImpl::ReleaseLayerTreeFrameSink() { ClearUIResources(); if (layer_tree_frame_sink_->context_provider()) { + // TODO(ericrk): Remove this once all uses of ContextGL from LTFS are + // removed. auto* gl = layer_tree_frame_sink_->context_provider()->ContextGL(); gl->Finish(); } @@ -3391,7 +3360,7 @@ bool LayerTreeHostImpl::InitializeFrameSink( const viz::LocalSurfaceIdAllocation& local_surface_id_allocation = child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation(); if (local_surface_id_allocation.IsValid()) - child_local_surface_id_allocator_.GenerateId(); + AllocateLocalSurfaceId(); } else { layer_tree_frame_sink_->ForceAllocateNewId(); } @@ -3470,8 +3439,8 @@ InputHandler::ScrollStatus LayerTreeHostImpl::TryScroll( // We may not find an associated layer for the root or secondary root node - // that's fine, they're not associated with any elements on the page. We also - // won't find a layer for the inner viewport (in SPv2) since it doesn't - // require hit testing. + // won't find a layer for the inner viewport (in CompositeAfterPaint) since it + // doesn't require hit testing. DCHECK(layer || scroll_node->id == ScrollTree::kRootNodeId || scroll_node->id == ScrollTree::kSecondaryRootNodeId || scroll_node->scrolls_inner_viewport); @@ -4443,6 +4412,10 @@ InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( client_->SetNeedsCommitOnImplThread(); SetNeedsRedraw(); client_->RenewTreePriority(); + } else { + overscroll_delta_for_main_thread_ += + gfx::Vector2dF(scroll_state->delta_x(), scroll_state->delta_y()); + client_->SetNeedsCommitOnImplThread(); } // Scrolling along an axis resets accumulated root overscroll for that axis. @@ -4630,6 +4603,10 @@ void LayerTreeHostImpl::ScrollEndImpl(ScrollState* scroll_state) { void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) { scroll_gesture_did_end_ = true; + last_scroller_element_id_ = CurrentlyScrollingNode() + ? CurrentlyScrollingNode()->element_id + : ElementId(); + client_->SetNeedsCommitOnImplThread(); if (should_snap && SnapAtScrollEnd()) return; @@ -4813,6 +4790,23 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { 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_; + overscroll_delta_for_main_thread_ = gfx::Vector2dF(); + + if (scroll_gesture_did_end_) { + // When the scrolling has finished send the element id of the last node that + // has scrolled. + scroll_info->scroll_latched_element_id = last_scroller_element_id_; + last_scroller_element_id_ = ElementId(); + } else { + // Send the element id of the currently scrolling node. + auto* node = + active_tree_->property_trees()->scroll_tree.CurrentlyScrollingNode(); + scroll_info->scroll_latched_element_id = + node ? node->element_id : ElementId(); + } + if (browser_controls_manager()) { scroll_info->browser_controls_constraint = browser_controls_manager()->PullConstraintForMainThread( @@ -4931,28 +4925,6 @@ void LayerTreeHostImpl::ActivateAnimations() { } } -std::string LayerTreeHostImpl::LayerListAsJson() const { - auto list = std::make_unique<base::ListValue>(); - for (auto* layer : *active_tree_) { - list->Append(layer->LayerAsJson()); - } - std::string str; - base::JSONWriter::WriteWithOptions( - *list, base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); - return str; -} - -std::string LayerTreeHostImpl::LayerTreeAsJson() const { - std::string str; - if (active_tree_->root_layer_for_testing()) { - std::unique_ptr<base::Value> json( - active_tree_->root_layer_for_testing()->LayerTreeAsJson()); - base::JSONWriter::WriteWithOptions( - *json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); - } - return str; -} - void LayerTreeHostImpl::RegisterScrollbarAnimationController( ElementId scroll_element_id, float scrollbar_opacity) { @@ -5008,9 +4980,9 @@ void LayerTreeHostImpl::FlashAllScrollbars(bool did_scroll) { } void LayerTreeHostImpl::PostDelayedScrollbarAnimationTask( - const base::Closure& task, + base::OnceClosure task, base::TimeDelta delay) { - client_->PostDelayedAnimationTaskOnImplThread(task, delay); + client_->PostDelayedAnimationTaskOnImplThread(std::move(task), delay); } // TODO(danakj): Make this a return value from the Animate() call instead of an @@ -5188,9 +5160,13 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale); } - // For gpu compositing, a texture will be allocated and the UIResource - // will be uploaded into it. - viz::TextureAllocation texture_alloc; + // For gpu compositing, a SharedImage mailbox will be allocated and the + // UIResource will be uploaded into it. + gpu::Mailbox mailbox; + uint32_t shared_image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY; + // For gpu compositing, we also calculate the GL texture target. + // TODO(ericrk): Remove references to GL from this code. + GLenum texture_target = GL_TEXTURE_2D; // For software compositing, shared memory will be allocated and the // UIResource will be copied into it. std::unique_ptr<base::SharedMemory> shared_memory; @@ -5199,10 +5175,16 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, if (layer_tree_frame_sink_->context_provider()) { viz::ContextProvider* context_provider = layer_tree_frame_sink_->context_provider(); - texture_alloc = viz::TextureAllocation::MakeTextureId( - context_provider->ContextGL(), context_provider->ContextCapabilities(), - format, settings_.resource_settings.use_gpu_memory_buffer_resources, - /*for_framebuffer_attachment=*/false); + const auto& caps = context_provider->ContextCapabilities(); + bool overlay_candidate = + settings_.resource_settings.use_gpu_memory_buffer_resources && + caps.texture_storage_image && + viz::IsGpuMemoryBufferFormatSupported(format); + if (overlay_candidate) { + shared_image_usage |= gpu::SHARED_IMAGE_USAGE_SCANOUT; + texture_target = gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT, + BufferFormat(format), caps); + } } else { shared_memory = viz::bitmap_allocation::AllocateMappedBitmap(upload_size, format); @@ -5213,10 +5195,15 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, // If not scaled, we can copy the pixels 1:1 from the source bitmap to our // destination backing of a texture or shared bitmap. if (layer_tree_frame_sink_->context_provider()) { - viz::TextureAllocation::UploadStorage( - layer_tree_frame_sink_->context_provider()->ContextGL(), - layer_tree_frame_sink_->context_provider()->ContextCapabilities(), - format, upload_size, texture_alloc, color_space, bitmap.GetPixels()); + viz::ContextProvider* context_provider = + layer_tree_frame_sink_->context_provider(); + auto* sii = context_provider->SharedImageInterface(); + size_t size_to_send = + viz::ResourceSizes::CheckedSizeInBytes<unsigned int>(upload_size, + format); + mailbox = sii->CreateSharedImage( + format, upload_size, color_space, shared_image_usage, + base::span<const uint8_t>(bitmap.GetPixels(), size_to_send)); } else { DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8); SkImageInfo src_info = @@ -5275,10 +5262,14 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, if (layer_tree_frame_sink_->context_provider()) { SkPixmap pixmap; scaled_surface->peekPixels(&pixmap); - viz::TextureAllocation::UploadStorage( - layer_tree_frame_sink_->context_provider()->ContextGL(), - layer_tree_frame_sink_->context_provider()->ContextCapabilities(), - format, upload_size, texture_alloc, color_space, pixmap.addr()); + viz::ContextProvider* context_provider = + layer_tree_frame_sink_->context_provider(); + auto* sii = context_provider->SharedImageInterface(); + mailbox = sii->CreateSharedImage( + format, upload_size, color_space, shared_image_usage, + base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(pixmap.addr()), + pixmap.computeByteSize())); } } @@ -5291,16 +5282,12 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, // allocated in this method above. viz::TransferableResource transferable; if (layer_tree_frame_sink_->context_provider()) { - gpu::gles2::GLES2Interface* gl = - layer_tree_frame_sink_->context_provider()->ContextGL(); - gpu::Mailbox mailbox; - gl->ProduceTextureDirectCHROMIUM(texture_alloc.texture_id, mailbox.name); - gpu::SyncToken sync_token = - viz::ClientResourceProvider::GenerateSyncTokenHelper(gl); + gpu::SyncToken sync_token = layer_tree_frame_sink_->context_provider() + ->SharedImageInterface() + ->GenUnverifiedSyncToken(); transferable = viz::TransferableResource::MakeGLOverlay( - mailbox, GL_LINEAR, texture_alloc.texture_target, sync_token, - upload_size, texture_alloc.overlay_candidate); + mailbox, GL_LINEAR, texture_target, sync_token, upload_size, false); transferable.format = format; } else { mojo::ScopedSharedBufferHandle memory_handle = @@ -5326,7 +5313,7 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, data.format = format; data.shared_bitmap_id = shared_bitmap_id; data.shared_memory = std::move(shared_memory); - data.texture_id = texture_alloc.texture_id; + data.mailbox = mailbox; data.resource_id_for_export = id; ui_resource_map_[uid] = std::move(data); @@ -5353,15 +5340,13 @@ void LayerTreeHostImpl::DeleteUIResourceBacking( UIResourceData data, const gpu::SyncToken& sync_token) { // Resources are either software or gpu backed, not both. - DCHECK(!(data.shared_memory && data.texture_id)); + DCHECK(!(data.shared_memory && !data.mailbox.IsZero())); if (data.shared_memory) layer_tree_frame_sink_->DidDeleteSharedBitmap(data.shared_bitmap_id); - if (data.texture_id) { - gpu::gles2::GLES2Interface* gl = - layer_tree_frame_sink_->context_provider()->ContextGL(); - if (sync_token.HasData()) - gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); - gl->DeleteTextures(1, &data.texture_id); + if (!data.mailbox.IsZero()) { + auto* sii = + layer_tree_frame_sink_->context_provider()->SharedImageInterface(); + sii->DestroySharedImage(sync_token, data.mailbox); } // |data| goes out of scope and deletes anything it owned. } @@ -5583,7 +5568,7 @@ void LayerTreeHostImpl::SetElementScrollOffsetMutated( } void LayerTreeHostImpl::ElementIsAnimatingChanged( - ElementId element_id, + const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) { @@ -5591,8 +5576,9 @@ void LayerTreeHostImpl::ElementIsAnimatingChanged( list_type == ElementListType::ACTIVE ? active_tree() : pending_tree(); // TODO(wkorman): Explore enabling DCHECK in ElementIsAnimatingChanged() // below. Currently enabling causes batch of unit test failures. - if (tree && tree->property_trees()->ElementIsAnimatingChanged( - mutator_host(), element_id, list_type, mask, state, false)) + if (tree && + tree->property_trees()->ElementIsAnimatingChanged( + mutator_host(), element_id_map, list_type, mask, state, false)) tree->set_needs_update_draw_properties(); } @@ -5702,4 +5688,10 @@ void LayerTreeHostImpl::SetActiveURL(const GURL& url) { ukm_manager_->SetSourceURL(url); } +void LayerTreeHostImpl::AllocateLocalSurfaceId() { + child_local_surface_id_allocator_.GenerateId(); + client_->DidGenerateLocalSurfaceIdAllocationOnImplThread( + child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()); +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_host_impl.h b/chromium/cc/trees/layer_tree_host_impl.h index b932defe22e..04b75068704 100644 --- a/chromium/cc/trees/layer_tree_host_impl.h +++ b/chromium/cc/trees/layer_tree_host_impl.h @@ -74,6 +74,7 @@ class ImageAnimationController; class LayerImpl; class LayerTreeFrameSink; class LayerTreeImpl; +class PaintWorkletLayerPainter; class MemoryHistory; class MutatorEvents; class MutatorHost; @@ -93,8 +94,6 @@ class TaskGraphRunner; class UIResourceBitmap; class Viewport; -using BeginFrameCallbackList = std::vector<base::Closure>; - enum class GpuRasterizationStatus { ON, ON_FORCED, @@ -128,7 +127,7 @@ class LayerTreeHostImplClient { std::unique_ptr<MutatorEvents> events) = 0; virtual bool IsInsideDraw() = 0; virtual void RenewTreePriority() = 0; - virtual void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, + virtual void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) = 0; virtual void DidActivateSyncTree() = 0; virtual void WillPrepareTiles() = 0; @@ -155,6 +154,9 @@ class LayerTreeHostImplClient { std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback) = 0; + virtual void DidGenerateLocalSurfaceIdAllocationOnImplThread( + const viz::LocalSurfaceIdAllocation& allocation) = 0; + protected: virtual ~LayerTreeHostImplClient() {} }; @@ -183,8 +185,6 @@ class CC_EXPORT LayerTreeHostImpl std::vector<viz::SurfaceId> activation_dependencies; base::Optional<uint32_t> deadline_in_frames; bool use_default_lower_bound_deadline = false; - std::vector<gfx::Rect> occluding_screen_space_rects; - std::vector<gfx::Rect> non_occluding_screen_space_rects; viz::RenderPassList render_passes; const RenderSurfaceList* render_surface_list = nullptr; LayerImplList will_draw_layers; @@ -211,7 +211,7 @@ class CC_EXPORT LayerTreeHostImpl viz::SharedBitmapId shared_bitmap_id; std::unique_ptr<base::SharedMemory> shared_memory; // Backing for gpu compositing. - uint32_t texture_id; + gpu::Mailbox mailbox; // The name with which to refer to the resource in frames submitted to the // display compositor. @@ -355,7 +355,7 @@ class CC_EXPORT LayerTreeHostImpl ElementId element_id, ElementListType list_type, const gfx::ScrollOffset& scroll_offset) override; - void ElementIsAnimatingChanged(ElementId element_id, + void ElementIsAnimatingChanged(const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) override; @@ -421,7 +421,7 @@ class CC_EXPORT LayerTreeHostImpl WhichTree tree) const override; // ScrollbarAnimationControllerClient implementation. - void PostDelayedScrollbarAnimationTask(const base::Closure& task, + void PostDelayedScrollbarAnimationTask(base::OnceClosure task, base::TimeDelta delay) override; void SetNeedsAnimateForScrollbarAnimation() override; void SetNeedsRedrawForScrollbarAnimation() override; @@ -447,8 +447,7 @@ class CC_EXPORT LayerTreeHostImpl void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override; - void SetTreeActivationCallback( - const base::RepeatingClosure& callback) override; + void SetTreeActivationCallback(base::RepeatingClosure callback) override; void OnDraw(const gfx::Transform& transform, const gfx::Rect& viewport, bool resourceless_software_draw, @@ -466,11 +465,6 @@ class CC_EXPORT LayerTreeHostImpl int max_texture_size() const { return max_texture_size_; } void ReleaseLayerTreeFrameSink(); - std::string LayerListAsJson() const; - // TODO(pdr): This should be removed because there is no longer a tree - // of layers, only a list. - std::string LayerTreeAsJson() const; - int RequestedMSAASampleCount() const; virtual bool InitializeFrameSink(LayerTreeFrameSink* layer_tree_frame_sink); @@ -499,7 +493,7 @@ class CC_EXPORT LayerTreeHostImpl return &image_animation_controller_; } - uint32_t next_frame_token() const { return next_frame_token_; } + uint32_t next_frame_token() const { return *next_frame_token_; } virtual bool WillBeginImplFrame(const viz::BeginFrameArgs& args); virtual void DidFinishImplFrame(); @@ -686,6 +680,8 @@ class CC_EXPORT LayerTreeHostImpl base::TimeDelta delayed_by); void SetLayerTreeMutator(std::unique_ptr<LayerTreeMutator> mutator); + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter); // The viewport has two scroll nodes, corresponding to the visual and layout // viewports. However, when we compute the scroll chain we include only one @@ -884,6 +880,8 @@ class CC_EXPORT LayerTreeHostImpl void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel level); + void AllocateLocalSurfaceId(); + const LayerTreeSettings settings_; const bool is_synchronous_single_threaded_; @@ -970,6 +968,10 @@ class CC_EXPORT LayerTreeHostImpl gfx::Vector2dF accumulated_root_overscroll_; + // Unconsumed scroll delta sent to the main thread for firing overscroll DOM + // events. Resets after each commit. + gfx::Vector2dF overscroll_delta_for_main_thread_; + // True iff some of the delta has been consumed for the current scroll // sequence on the specific axis. bool did_scroll_x_for_scroll_gesture_; @@ -1020,7 +1022,7 @@ class CC_EXPORT LayerTreeHostImpl single_thread_synchronous_task_graph_runner_; // Optional callback to notify of new tree activations. - base::Closure tree_activation_callback_; + base::RepeatingClosure tree_activation_callback_; TaskGraphRunner* task_graph_runner_; int id_; @@ -1074,7 +1076,7 @@ class CC_EXPORT LayerTreeHostImpl // each CompositorFrame. std::unique_ptr<RenderFrameMetadataObserver> render_frame_metadata_observer_; - uint32_t next_frame_token_ = 1u; + viz::FrameTokenGenerator next_frame_token_; viz::LocalSurfaceIdAllocation last_draw_local_surface_id_allocation_; base::flat_set<viz::SurfaceRange> last_draw_referenced_surfaces_; @@ -1116,6 +1118,10 @@ class CC_EXPORT LayerTreeHostImpl // ended. bool scroll_gesture_did_end_; + // Set in ScrollEnd before clearing the currently scrolling node. This is + // used to send the scrollend DOM event when scrolling has happened on CC. + ElementId last_scroller_element_id_; + DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); }; diff --git a/chromium/cc/trees/layer_tree_host_impl_unittest.cc b/chromium/cc/trees/layer_tree_host_impl_unittest.cc index a31b2fe9444..29e2776963f 100644 --- a/chromium/cc/trees/layer_tree_host_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_impl_unittest.cc @@ -187,9 +187,9 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<MutatorEvents> events) override {} bool IsInsideDraw() override { return false; } void RenewTreePriority() override {} - void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, + void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) override { - animation_task_ = task; + animation_task_ = std::move(task); requested_animation_delay_ = delay; } void DidActivateSyncTree() override { @@ -224,6 +224,8 @@ class LayerTreeHostImplTest : public testing::Test, uint32_t frame_token, std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback) override {} + void DidGenerateLocalSurfaceIdAllocationOnImplThread( + const viz::LocalSurfaceIdAllocation& allocation) override {} void set_reduce_memory_result(bool reduce_memory_result) { reduce_memory_result_ = reduce_memory_result; @@ -276,7 +278,7 @@ class LayerTreeHostImplTest : public testing::Test, } void SetupRootLayerImpl(std::unique_ptr<LayerImpl> root) { - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); root->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10); @@ -359,7 +361,7 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> root = LayerImpl::Create(layer_tree_impl, 1); root->SetBounds(content_size); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->test_properties()->force_render_surface = true; std::unique_ptr<LayerImpl> inner_scroll = @@ -384,7 +386,7 @@ class LayerTreeHostImplTest : public testing::Test, inner_scroll->SetElementId( LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(content_size); - inner_scroll->SetPosition(gfx::PointF()); + inner_scroll->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> outer_clip = LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId); @@ -402,13 +404,13 @@ class LayerTreeHostImplTest : public testing::Test, ->scroll_tree.UpdateScrollOffsetBaseForTesting( outer_scroll->element_id(), gfx::ScrollOffset()); outer_scroll->SetBounds(content_size); - outer_scroll->SetPosition(gfx::PointF()); + outer_scroll->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> contents = LayerImpl::Create(layer_tree_impl, kContentLayerId); contents->SetDrawsContent(true); contents->SetBounds(content_size); - contents->SetPosition(gfx::PointF()); + contents->test_properties()->position = gfx::PointF(); outer_scroll->test_properties()->AddChild(std::move(contents)); outer_clip->test_properties()->AddChild(std::move(outer_scroll)); @@ -447,7 +449,7 @@ class LayerTreeHostImplTest : public testing::Test, host_impl_->active_tree()->SetDeviceViewportSize(content_size); std::unique_ptr<LayerImpl> root = LayerImpl::Create(layer_tree_impl, 1); root->SetBounds(content_size); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); @@ -459,14 +461,14 @@ class LayerTreeHostImplTest : public testing::Test, SolidColorScrollbarLayerImpl::Create(layer_tree_impl, 4, VERTICAL, 10, 0, false, true); scrollbar->SetBounds(scrollbar_size); - scrollbar->SetPosition(gfx::PointF(345, 0)); + scrollbar->test_properties()->position = gfx::PointF(345, 0); scrollbar->SetScrollElementId(scroll->element_id()); scrollbar->SetDrawsContent(true); scrollbar->test_properties()->opacity = 1.f; std::unique_ptr<LayerImpl> squash1 = LayerImpl::Create(layer_tree_impl, 5); squash1->SetBounds(gfx::Size(140, 300)); - squash1->SetPosition(gfx::PointF(220, 0)); + squash1->test_properties()->position = gfx::PointF(220, 0); if (transparent_layer) { squash1->test_properties()->opacity = 0.0f; // The transparent layer should still participate in hit testing even @@ -478,7 +480,7 @@ class LayerTreeHostImplTest : public testing::Test, std::unique_ptr<LayerImpl> squash2 = LayerImpl::Create(layer_tree_impl, 6); squash2->SetBounds(gfx::Size(140, 300)); - squash2->SetPosition(gfx::PointF(220, 300)); + squash2->test_properties()->position = gfx::PointF(220, 300); squash2->SetDrawsContent(true); scroll->test_properties()->AddChild(std::move(squash2)); @@ -653,7 +655,7 @@ class LayerTreeHostImplTest : public testing::Test, LayerImpl::Create(host_impl_->active_tree(), 6); LayerImpl* child = child_layer.get(); child_layer->SetDrawsContent(true); - child_layer->SetPosition(gfx::PointF(0, 0)); + child_layer->test_properties()->position = gfx::PointF(0, 0); child_layer->SetBounds(gfx::Size(25, 25)); scroll->test_properties()->AddChild(std::move(child_layer)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -702,7 +704,7 @@ class LayerTreeHostImplTest : public testing::Test, ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(overflow->element_id(), gfx::ScrollOffset()); - overflow->SetPosition(gfx::PointF(0, 0)); + overflow->test_properties()->position = gfx::PointF(0, 0); SnapContainerData container_data( ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory), @@ -784,7 +786,7 @@ class LayerTreeHostImplTest : public testing::Test, bool did_complete_page_scale_animation_; bool reduce_memory_result_; bool did_request_impl_side_invalidation_; - base::Closure animation_task_; + base::OnceClosure animation_task_; base::TimeDelta requested_animation_delay_; std::unique_ptr<TestFrameData> last_on_draw_frame_; viz::RenderPassList last_on_draw_render_passes_; @@ -1184,7 +1186,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) { LayerImpl::Create(host_impl_->active_tree(), 6); child = child_layer.get(); child_layer->SetDrawsContent(true); - child_layer->SetPosition(gfx::PointF(0, 20)); + child_layer->test_properties()->position = gfx::PointF(0, 20); child_layer->SetBounds(gfx::Size(50, 50)); scroll->test_properties()->AddChild(std::move(child_layer)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -1231,8 +1233,8 @@ TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) { host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(50, 50)); LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing(); - root->set_main_thread_scrolling_reasons( - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); + root->test_properties()->main_thread_scrolling_reasons = + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); @@ -1267,7 +1269,7 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { host_impl_->active_tree()->SetDeviceViewportSize(content_size); std::unique_ptr<LayerImpl> root = LayerImpl::Create(layer_tree_impl, 1); root->SetBounds(content_size); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 3); scroll->SetBounds(scroll_content_size); @@ -1279,14 +1281,14 @@ TEST_F(LayerTreeHostImplTest, ScrolledOverlappingDrawnScrollbarLayer) { SolidColorScrollbarLayerImpl::Create(layer_tree_impl, 4, VERTICAL, 10, 0, false, true); drawn_scrollbar->SetBounds(scrollbar_size); - drawn_scrollbar->SetPosition(gfx::PointF(345, 0)); + drawn_scrollbar->test_properties()->position = gfx::PointF(345, 0); drawn_scrollbar->SetScrollElementId(scroll->element_id()); drawn_scrollbar->SetDrawsContent(true); drawn_scrollbar->test_properties()->opacity = 1.f; std::unique_ptr<LayerImpl> squash = LayerImpl::Create(layer_tree_impl, 5); squash->SetBounds(gfx::Size(140, 300)); - squash->SetPosition(gfx::PointF(220, 0)); + squash->test_properties()->position = gfx::PointF(220, 0); squash->SetDrawsContent(true); scroll->test_properties()->AddChild(std::move(drawn_scrollbar)); @@ -1376,7 +1378,7 @@ TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) { LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer(); outer_scroll->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50)); - outer_scroll->SetPosition(gfx::PointF(-25.f, 0.f)); + outer_scroll->test_properties()->position = gfx::PointF(-25.f, 0.f); outer_scroll->SetDrawsContent(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -1718,7 +1720,7 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) { ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(overflow->element_id(), gfx::ScrollOffset()); - overflow->SetPosition(gfx::PointF(40, 40)); + overflow->test_properties()->position = gfx::PointF(40, 40); host_impl_->active_tree()->BuildPropertyTreesForTesting(); scroll_layer->SetCurrentScrollOffset(gfx::ScrollOffset(30, 30)); @@ -1887,7 +1889,7 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { ->property_trees() ->scroll_tree.UpdateScrollOffsetBaseForTesting(overflow->element_id(), gfx::ScrollOffset()); - overflow->SetPosition(gfx::PointF()); + overflow->test_properties()->position = gfx::PointF(); host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); @@ -2687,7 +2689,7 @@ TEST_F(LayerTreeHostImplTest, ScrollDoesntBubble) { std::unique_ptr<LayerImpl> scroll_child = CreateScrollableLayer(9, gfx::Size(10, 10)); child = scroll_child.get(); - scroll_child->SetPosition(gfx::PointF(20.f, 20.f)); + scroll_child->test_properties()->position = gfx::PointF(20.f, 20.f); scroll_child_clip->test_properties()->AddChild(std::move(scroll_child)); child_clip = scroll_child_clip.get(); @@ -3614,13 +3616,13 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { // A task will be posted to fade the initial scrollbar. EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); requested_animation_delay_ = base::TimeDelta(); - animation_task_ = base::Closure(); + animation_task_.Reset(); } else { EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); } @@ -3631,7 +3633,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); // For Aura Overlay Scrollbar, if no scroll happened during a scroll // gesture, shows scrollbars and schedules a delay fade out. @@ -3644,12 +3646,12 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { if (animator == LayerTreeSettings::AURA_OVERLAY) { EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); requested_animation_delay_ = base::TimeDelta(); - animation_task_ = base::Closure(); + animation_task_.Reset(); } else { EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); } // Before the scrollbar animation exists, we should not get redraws. @@ -3662,7 +3664,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { EXPECT_FALSE(did_request_redraw_); did_request_redraw_ = false; EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); host_impl_->DidFinishImplFrame(); // After a scroll, a scrollbar animation should be scheduled about 20ms from @@ -3676,10 +3678,10 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { if (expecting_animations) { EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); } else { EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); } host_impl_->ScrollEnd(EndState().get()); @@ -3688,10 +3690,10 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { if (expecting_animations) { EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); } else { EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); } if (expecting_animations) { @@ -3709,8 +3711,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { // Start the scrollbar animation. fake_now += requested_animation_delay_; requested_animation_delay_ = base::TimeDelta(); - animation_task_.Run(); - animation_task_ = base::Closure(); + std::move(animation_task_).Run(); EXPECT_TRUE(did_request_next_frame_); did_request_next_frame_ = false; EXPECT_FALSE(did_request_redraw_); @@ -3725,7 +3726,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { EXPECT_TRUE(did_request_redraw_); did_request_redraw_ = false; EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); host_impl_->DidFinishImplFrame(); } @@ -3741,7 +3742,7 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); // Changing page scale triggers scrollbar animation. host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); @@ -3751,12 +3752,12 @@ class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { if (expecting_animations) { EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); requested_animation_delay_ = base::TimeDelta(); - animation_task_ = base::Closure(); + animation_task_.Reset(); } else { EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); } } }; @@ -3797,7 +3798,7 @@ class LayerTreeHostImplTestScrollbarOpacity : public LayerTreeHostImplTest { host_impl_->pending_tree()->InnerViewportContainerLayer(); scrollbar->SetScrollElementId(scroll->element_id()); scrollbar->SetBounds(gfx::Size(10, 100)); - scrollbar->SetPosition(gfx::PointF(90, 0)); + scrollbar->test_properties()->position = gfx::PointF(90, 0); scrollbar->SetNeedsPushProperties(); container->test_properties()->AddChild(std::move(scrollbar)); @@ -3912,7 +3913,7 @@ class LayerTreeHostImplTestMultiScrollable : public LayerTreeHostImplTest { touch_action_region.Union(kTouchActionNone, gfx::Rect(scrollbar_size_1)); scrollbar_1->SetTouchActionRegion(touch_action_region); scrollbar_1->SetCurrentPos(0); - scrollbar_1->SetPosition(gfx::PointF(0, 0)); + scrollbar_1->test_properties()->position = gfx::PointF(0, 0); host_impl_->active_tree() ->InnerViewportContainerLayer() ->test_properties() @@ -3926,7 +3927,7 @@ class LayerTreeHostImplTestMultiScrollable : public LayerTreeHostImplTest { scrollbar_2_ = scrollbar_2.get(); std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl_->active_tree(), child_scroll_id); - child->SetPosition(gfx::PointF(50, 50)); + child->test_properties()->position = gfx::PointF(50, 50); child->SetBounds(child_layer_size); child->SetDrawsContent(true); child->SetScrollable(gfx::Size(100, 100)); @@ -3937,7 +3938,7 @@ class LayerTreeHostImplTestMultiScrollable : public LayerTreeHostImplTest { scrollbar_2->SetDrawsContent(true); scrollbar_2->SetBounds(scrollbar_size_2); scrollbar_2->SetCurrentPos(0); - scrollbar_2->SetPosition(gfx::PointF(0, 0)); + scrollbar_2->test_properties()->position = gfx::PointF(0, 0); child->test_properties()->AddChild(std::move(scrollbar_2)); root_scroll->test_properties()->AddChild(std::move(child)); @@ -3956,7 +3957,7 @@ class LayerTreeHostImplTestMultiScrollable : public LayerTreeHostImplTest { host_impl_->active_tree()->BuildPropertyTreesForTesting(); if (is_aura_scrollbar_) - animation_task_ = base::Closure(); + animation_task_.Reset(); } bool is_aura_scrollbar_; @@ -3987,7 +3988,7 @@ TEST_F(LayerTreeHostImplTestMultiScrollable, EXPECT_TRUE(scrollbar_1_->Opacity()); EXPECT_TRUE(scrollbar_2_->Opacity()); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); ResetScrollbars(); // Scroll on child should flash all scrollbars. @@ -3998,7 +3999,7 @@ TEST_F(LayerTreeHostImplTestMultiScrollable, EXPECT_TRUE(scrollbar_1_->Opacity()); EXPECT_TRUE(scrollbar_2_->Opacity()); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); } TEST_F(LayerTreeHostImplTestMultiScrollable, ScrollbarFlashWhenMouseEnter) { @@ -4018,13 +4019,13 @@ TEST_F(LayerTreeHostImplTestMultiScrollable, ScrollbarFlashWhenMouseEnter) { EXPECT_TRUE(scrollbar_1_->Opacity()); EXPECT_FALSE(scrollbar_2_->Opacity()); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); host_impl_->MouseMoveAt(gfx::Point(51, 51)); EXPECT_TRUE(scrollbar_1_->Opacity()); EXPECT_TRUE(scrollbar_2_->Opacity()); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); } TEST_F(LayerTreeHostImplTestMultiScrollable, ScrollHitTestOnScrollbar) { @@ -4089,7 +4090,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { host_impl_->pending_tree()->InnerViewportContainerLayer(); scrollbar->SetScrollElementId(scroll->element_id()); scrollbar->SetBounds(gfx::Size(10, 100)); - scrollbar->SetPosition(gfx::PointF(90, 0)); + scrollbar->test_properties()->position = gfx::PointF(90, 0); scrollbar->SetNeedsPushProperties(); container->test_properties()->AddChild(std::move(scrollbar)); @@ -4104,9 +4105,9 @@ TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { // Scrollbars will flash shown but we should have a fade out animation // queued. Run it and fade out the scrollbars. { - ASSERT_FALSE(animation_task_.Equals(base::Closure())); + ASSERT_FALSE(animation_task_.is_null()); ASSERT_FALSE(animation_task_.IsCancelled()); - animation_task_.Run(); + std::move(animation_task_).Run(); base::TimeTicks fake_now = base::TimeTicks::Now(); scrollbar_controller->Animate(fake_now); @@ -4119,9 +4120,9 @@ TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { // Move the mouse over the scrollbar region. This should post a delayed fade // in task. Execute it to fade in the scrollbars. { - animation_task_ = base::Closure(); + animation_task_.Reset(); scrollbar_controller->DidMouseMove(gfx::PointF(90, 0)); - ASSERT_FALSE(animation_task_.Equals(base::Closure())); + ASSERT_FALSE(animation_task_.is_null()); ASSERT_FALSE(animation_task_.IsCancelled()); } @@ -4131,7 +4132,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { did_request_redraw_ = false; did_request_commit_ = false; ASSERT_TRUE(scrollbar_controller->ScrollbarsHidden()); - animation_task_.Run(); + std::move(animation_task_).Run(); base::TimeTicks fake_now = base::TimeTicks::Now(); scrollbar_controller->Animate(fake_now); @@ -4246,12 +4247,12 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { root_scroll->element_id())); // Scrolling the viewport should result in a scrollbar animation update. - animation_task_ = base::Closure(); + animation_task_.Reset(); host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL); host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(10, 10)).get()); host_impl_->ScrollEnd(EndState().get()); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); - animation_task_ = base::Closure(); + EXPECT_FALSE(animation_task_.is_null()); + animation_task_.Reset(); // Check scrollbar registration on a sublayer. child->SetScrollable(viewport_size); @@ -4272,13 +4273,13 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { // Changing one of the child layers should result in a scrollbar animation // update. - animation_task_ = base::Closure(); + animation_task_.Reset(); child_ptr->SetBounds(gfx::Size(200, 200)); child_ptr->set_needs_show_scrollbars(true); host_impl_->active_tree()->BuildPropertyTreesForTesting(); host_impl_->active_tree()->HandleScrollbarShowRequestsFromMain(); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); - animation_task_ = base::Closure(); + EXPECT_FALSE(animation_task_.is_null()); + animation_task_.Reset(); // Check scrollbar unregistration. container->test_properties()->RemoveChild(vert_1_scrollbar); @@ -4303,9 +4304,9 @@ TEST_F(LayerTreeHostImplTest, ScrollbarRegistration) { // Changing scroll offset should no longer trigger any animation. host_impl_->active_tree()->InnerViewportScrollLayer()->SetCurrentScrollOffset( gfx::ScrollOffset(20, 20)); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); child_ptr->SetCurrentScrollOffset(gfx::ScrollOffset(20, 20)); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); } TEST_F(LayerTreeHostImplTest, ScrollBeforeMouseMove) { @@ -4330,7 +4331,7 @@ TEST_F(LayerTreeHostImplTest, ScrollBeforeMouseMove) { vert_scrollbar->SetScrollElementId(root_scroll->element_id()); vert_scrollbar->SetBounds(gfx::Size(10, 200)); - vert_scrollbar->SetPosition(gfx::PointF(300, 0)); + vert_scrollbar->test_properties()->position = gfx::PointF(300, 0); vert_scrollbar->test_properties()->opacity_can_animate = true; vert_scrollbar->SetCurrentPos(0); @@ -4488,7 +4489,7 @@ TEST_F(LayerTreeHostImplTest, ActivationDependenciesInMetadata) { for (size_t i = 0; i < primary_surfaces.size(); ++i) { std::unique_ptr<SurfaceLayerImpl> child = SurfaceLayerImpl::Create(host_impl_->active_tree(), i + 6); - child->SetPosition(gfx::PointF(25.f * i, 0.f)); + child->test_properties()->position = gfx::PointF(25.f * i, 0.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); child->SetRange( @@ -4930,7 +4931,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { auto* layer = static_cast<DidDrawCheckLayer*>(root->test_properties()->children[0]); // Ensure visible_layer_rect for layer is empty. - layer->SetPosition(gfx::PointF(100.f, 100.f)); + layer->test_properties()->position = gfx::PointF(100.f, 100.f); layer->SetBounds(gfx::Size(10, 10)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -4949,7 +4950,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) { EXPECT_TRUE(layer->visible_layer_rect().IsEmpty()); // Ensure visible_layer_rect for layer is not empty - layer->SetPosition(gfx::PointF()); + layer->test_properties()->position = gfx::PointF(); layer->NoteLayerPropertyChanged(); host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -5548,7 +5549,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, touch_action_region.Union(kTouchActionNone, gfx::Rect(scrollbar_size)); scrollbar->SetTouchActionRegion(touch_action_region); scrollbar->SetCurrentPos(0); - scrollbar->SetPosition(gfx::PointF(0, 35)); + scrollbar->test_properties()->position = gfx::PointF(0, 35); host_impl_->active_tree() ->InnerViewportContainerLayer() ->test_properties() @@ -5816,27 +5817,6 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, BrowserControlsPushUnsentRatio) { ASSERT_EQ(0, host_impl_->active_tree()->CurrentBrowserControlsShownRatio()); } -// Test that if only the browser controls are scrolled, we shouldn't request a -// commit. -TEST_F(LayerTreeHostImplBrowserControlsTest, BrowserControlsDontTriggerCommit) { - SetupBrowserControlsAndScrollLayerWithVirtualViewport( - gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100)); - DrawFrame(); - - // Show browser controls - EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentBrowserControlsShownRatio()); - - // Scroll 25px to hide browser controls - gfx::Vector2dF scroll_delta(0.f, 25.f); - EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, - host_impl_ - ->ScrollBegin(BeginState(gfx::Point()).get(), - InputHandler::TOUCHSCREEN) - .thread); - host_impl_->ScrollBy(UpdateState(gfx::Point(), scroll_delta).get()); - EXPECT_FALSE(did_request_commit_); -} - // Test that if a scrollable sublayer doesn't consume the scroll, // browser controls should hide when scrolling down. TEST_F(LayerTreeHostImplBrowserControlsTest, @@ -5859,7 +5839,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, child->SetScrollable(sub_content_layer_size); child->SetElementId(LayerIdToElementIdForTesting(child->id())); child->SetBounds(sub_content_size); - child->SetPosition(gfx::PointF()); + child->test_properties()->position = gfx::PointF(); child->SetDrawsContent(true); child->test_properties()->is_container_for_fixed_position_layers = true; @@ -6402,7 +6382,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { std::unique_ptr<LayerImpl> content_layer = LayerImpl::Create(host_impl_->active_tree(), 11); content_layer->SetDrawsContent(true); - content_layer->SetPosition(gfx::PointF()); + content_layer->test_properties()->position = gfx::PointF(); content_layer->SetBounds(contents_size); LayerImpl* scroll_container_layer = @@ -6413,7 +6393,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) { scroll_layer->SetScrollable(surface_size); scroll_layer->SetElementId(LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(contents_size); - scroll_layer->SetPosition(gfx::PointF()); + scroll_layer->test_properties()->position = gfx::PointF(); scroll_layer->test_properties()->AddChild(std::move(content_layer)); scroll_container_layer->test_properties()->AddChild(std::move(scroll_layer)); @@ -6518,8 +6498,8 @@ TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) { gfx::Size surface_size(10, 10); std::unique_ptr<LayerImpl> content_layer = CreateScrollableLayer(1, surface_size); - content_layer->set_main_thread_scrolling_reasons( - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); + content_layer->test_properties()->main_thread_scrolling_reasons = + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; // Note: we can use the same clip layer for both since both calls to // CreateScrollableLayer() use the same surface size. @@ -8134,12 +8114,14 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnMainThread) { host_impl_->active_tree() ->InnerViewportScrollLayer() - ->set_main_thread_scrolling_reasons( - MainThreadScrollingReason::kThreadedScrollingDisabled); + ->test_properties() + ->main_thread_scrolling_reasons = + MainThreadScrollingReason::kThreadedScrollingDisabled; host_impl_->active_tree() ->OuterViewportScrollLayer() - ->set_main_thread_scrolling_reasons( - MainThreadScrollingReason::kThreadedScrollingDisabled); + ->test_properties() + ->main_thread_scrolling_reasons = + MainThreadScrollingReason::kThreadedScrollingDisabled; host_impl_->active_tree()->BuildPropertyTreesForTesting(); @@ -8196,8 +8178,10 @@ TEST_F(LayerTreeHostImplTest, ScrollFromOuterViewportSibling) { inner_scroll_layer->test_properties()->AddChild(std::move(scroll)); // Move the outer viewport layer away so that scrolls won't target it. - host_impl_->active_tree()->OuterViewportContainerLayer()->SetPosition( - gfx::PointF(400, 400)); + host_impl_->active_tree() + ->OuterViewportContainerLayer() + ->test_properties() + ->position = gfx::PointF(400, 400); layer_tree_impl->BuildPropertyTreesForTesting(); @@ -8557,8 +8541,11 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnImplThread) { // By default, no main thread scrolling reasons should exist. LayerImpl* scroll_layer = host_impl_->active_tree()->InnerViewportScrollLayer(); + ScrollNode* scroll_node = + host_impl_->active_tree()->property_trees()->scroll_tree.Node( + scroll_layer->scroll_tree_index()); EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, - scroll_layer->main_thread_scrolling_reasons()); + scroll_node->main_thread_scrolling_reasons); DrawFrame(); @@ -8678,7 +8665,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { host_impl_->active_tree(), 2, host_impl_->resource_provider())); auto* layer1 = static_cast<BlendStateCheckLayer*>(root->test_properties()->children[0]); - layer1->SetPosition(gfx::PointF(2.f, 2.f)); + layer1->test_properties()->position = gfx::PointF(2.f, 2.f); TestFrameData frame; @@ -8731,7 +8718,7 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) { host_impl_->active_tree(), 3, host_impl_->resource_provider())); auto* layer2 = static_cast<BlendStateCheckLayer*>( layer1->test_properties()->children[0]); - layer2->SetPosition(gfx::PointF(4.f, 4.f)); + layer2->test_properties()->position = gfx::PointF(4.f, 4.f); // 2 opaque layers, drawn without blending. layer1->SetContentsOpaque(true); @@ -8958,10 +8945,10 @@ TEST_F(LayerTreeHostImplTest, MayContainVideo) { EXPECT_TRUE(MayContainVideoBitSetOnFrameData(host_impl_.get())); // Move the video layer so it goes beyond the root. - video_layer->SetPosition(gfx::PointF(100.f, 100.f)); + video_layer->test_properties()->position = gfx::PointF(100.f, 100.f); EXPECT_FALSE(MayContainVideoBitSetOnFrameData(host_impl_.get())); - video_layer->SetPosition(gfx::PointF(0.f, 0.f)); + video_layer->test_properties()->position = gfx::PointF(0.f, 0.f); video_layer->NoteLayerPropertyChanged(); EXPECT_TRUE(MayContainVideoBitSetOnFrameData(host_impl_.get())); } @@ -9005,7 +8992,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { // Expect no gutter rects. void TestLayerCoversFullViewport() { gfx::Rect layer_rect(viewport_size_); - child_->SetPosition(gfx::PointF(layer_rect.origin())); + child_->test_properties()->position = gfx::PointF(layer_rect.origin()); child_->SetBounds(layer_rect.size()); child_->SetQuadRect(gfx::Rect(layer_rect.size())); child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); @@ -9026,7 +9013,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { // Expect fullscreen gutter rect. void SetUpEmptylayer() { gfx::Rect layer_rect(0, 0, 0, 0); - child_->SetPosition(gfx::PointF(layer_rect.origin())); + child_->test_properties()->position = gfx::PointF(layer_rect.origin()); child_->SetBounds(layer_rect.size()); child_->SetQuadRect(gfx::Rect(layer_rect.size())); child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); @@ -9063,7 +9050,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { // Expect four surrounding gutter rects. void SetUpLayerInMiddleOfViewport() { gfx::Rect layer_rect(500, 500, 200, 200); - child_->SetPosition(gfx::PointF(layer_rect.origin())); + child_->test_properties()->position = gfx::PointF(layer_rect.origin()); child_->SetBounds(layer_rect.size()); child_->SetQuadRect(gfx::Rect(layer_rect.size())); child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); @@ -9101,7 +9088,7 @@ class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest { void SetUpLayerIsLargerThanViewport() { gfx::Rect layer_rect(viewport_size_.width() + 10, viewport_size_.height() + 10); - child_->SetPosition(gfx::PointF(layer_rect.origin())); + child_->test_properties()->position = gfx::PointF(layer_rect.origin()); child_->SetBounds(layer_rect.size()); child_->SetQuadRect(gfx::Rect(layer_rect.size())); child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size())); @@ -9315,7 +9302,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { root->test_properties()->force_render_surface = true; std::unique_ptr<LayerImpl> child = FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2); - child->SetPosition(gfx::PointF(12.f, 13.f)); + child->test_properties()->position = gfx::PointF(12.f, 13.f); child->SetBounds(gfx::Size(14, 15)); child->SetDrawsContent(true); root->SetBounds(gfx::Size(500, 500)); @@ -9344,7 +9331,8 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) { ->root_layer_for_testing() ->test_properties() ->children[0] - ->SetPosition(gfx::PointF()); + ->test_properties() + ->position = gfx::PointF(); layer_tree_host_impl->active_tree() ->root_layer_for_testing() ->test_properties() @@ -9425,10 +9413,11 @@ class FakeLayerWithQuads : public LayerImpl { }; TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { - auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); - viz::TestGLES2Interface* gl = gl_owned.get(); + scoped_refptr<viz::TestContextProvider> context_provider = + viz::TestContextProvider::Create(); + viz::TestSharedImageInterface* sii = context_provider->SharedImageInterface(); std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink( - FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); + FakeLayerTreeFrameSink::Create3d(context_provider)); CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); std::unique_ptr<LayerImpl> root_layer = @@ -9449,19 +9438,19 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { host_impl_->active_tree()->SetRootLayerForTesting(std::move(root_layer)); host_impl_->active_tree()->BuildPropertyTreesForTesting(); - EXPECT_EQ(0u, gl->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); TestFrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame); host_impl_->DidDrawAllLayers(frame); - EXPECT_GT(gl->NumTextures(), 0u); + EXPECT_GT(sii->shared_image_count(), 0u); // Kill the layer tree. host_impl_->active_tree()->DetachLayers(); // There should be no textures left in use after. - EXPECT_EQ(0u, gl->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); } @@ -9561,7 +9550,7 @@ class LayerTreeHostImplTestDrawAndTestDamage : public LayerTreeHostImplTest { TEST_F(LayerTreeHostImplTestDrawAndTestDamage, FrameIncludesDamageRect) { std::unique_ptr<SolidColorLayerImpl> root = SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); root->SetBackgroundColor(SK_ColorRED); @@ -9570,7 +9559,7 @@ TEST_F(LayerTreeHostImplTestDrawAndTestDamage, FrameIncludesDamageRect) { // Child layer is in the bottom right corner. std::unique_ptr<SolidColorLayerImpl> child = SolidColorLayerImpl::Create(host_impl_->active_tree(), 2); - child->SetPosition(gfx::PointF(9.f, 9.f)); + child->test_properties()->position = gfx::PointF(9.f, 9.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); child->SetBackgroundColor(SK_ColorRED); @@ -9949,58 +9938,56 @@ TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) { } TEST_F(LayerTreeHostImplTest, UIResourceManagement) { - auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); - viz::TestGLES2Interface* gl = gl_owned.get(); - - std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink = - FakeLayerTreeFrameSink::Create3d(std::move(gl_owned)); - CreateHostImpl(DefaultSettings(), std::move(layer_tree_frame_sink)); + auto test_context_provider = viz::TestContextProvider::Create(); + viz::TestSharedImageInterface* sii = + test_context_provider->SharedImageInterface(); + CreateHostImpl(DefaultSettings(), FakeLayerTreeFrameSink::Create3d( + std::move(test_context_provider))); - EXPECT_EQ(0u, gl->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); UIResourceId ui_resource_id = 1; bool is_opaque = false; UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque); host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, gl->NumTextures()); + EXPECT_EQ(1u, sii->shared_image_count()); viz::ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); // Multiple requests with the same id is allowed. The previous texture is // deleted. host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, gl->NumTextures()); + EXPECT_EQ(1u, sii->shared_image_count()); viz::ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id2); EXPECT_NE(id1, id2); // Deleting invalid UIResourceId is allowed and does not change state. host_impl_->DeleteUIResource(-1); - EXPECT_EQ(1u, gl->NumTextures()); + EXPECT_EQ(1u, sii->shared_image_count()); // Should return zero for invalid UIResourceId. Number of textures should // not change. EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1)); - EXPECT_EQ(1u, gl->NumTextures()); + EXPECT_EQ(1u, sii->shared_image_count()); host_impl_->DeleteUIResource(ui_resource_id); EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id)); - EXPECT_EQ(0u, gl->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); // Should not change state for multiple deletion on one UIResourceId host_impl_->DeleteUIResource(ui_resource_id); - EXPECT_EQ(0u, gl->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); } TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { - auto gl_owned = std::make_unique<viz::TestGLES2Interface>(); - gl_owned->set_support_compressed_texture_etc1(true); - viz::TestGLES2Interface* gl = gl_owned.get(); - - CreateHostImpl(DefaultSettings(), - FakeLayerTreeFrameSink::Create3d(std::move(gl_owned))); + auto test_context_provider = viz::TestContextProvider::Create(); + viz::TestSharedImageInterface* sii = + test_context_provider->SharedImageInterface(); + CreateHostImpl(DefaultSettings(), FakeLayerTreeFrameSink::Create3d( + std::move(test_context_provider))); - EXPECT_EQ(0u, gl->NumTextures()); + EXPECT_EQ(0u, sii->shared_image_count()); gfx::Size size(4, 4); // SkImageInfo has no support for ETC1. The |info| below contains the right @@ -10013,7 +10000,7 @@ TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) { UIResourceBitmap bitmap(std::move(pixel_ref), size); UIResourceId ui_resource_id = 1; host_impl_->CreateUIResource(ui_resource_id, bitmap); - EXPECT_EQ(1u, gl->NumTextures()); + EXPECT_EQ(1u, sii->shared_image_count()); viz::ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id); EXPECT_NE(0u, id1); } @@ -10155,7 +10142,7 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) { LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); occluder_layer->SetDrawsContent(true); occluder_layer->SetBounds(content_size); - occluder_layer->SetPosition(gfx::PointF()); + occluder_layer->test_properties()->position = gfx::PointF(); // The parent of the occluder is *above* the scroller. page_scale_layer->test_properties()->AddChild(std::move(occluder_layer)); @@ -10187,7 +10174,7 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) { LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id); occluder_layer->SetDrawsContent(true); occluder_layer->SetBounds(content_size); - occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f)); + occluder_layer->test_properties()->position = gfx::PointF(-10.f, -10.f); int child_scroll_clip_layer_id = 7; std::unique_ptr<LayerImpl> child_scroll_clip = @@ -10197,7 +10184,7 @@ TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) { std::unique_ptr<LayerImpl> child_scroll = CreateScrollableLayer(child_scroll_layer_id, content_size); - child_scroll->SetPosition(gfx::PointF(10.f, 10.f)); + child_scroll->test_properties()->position = gfx::PointF(10.f, 10.f); child_scroll->test_properties()->AddChild(std::move(occluder_layer)); child_scroll_clip->test_properties()->AddChild(std::move(child_scroll)); @@ -10253,7 +10240,7 @@ class LayerTreeHostImplLatencyInfoTest : public LayerTreeHostImplTest { std::unique_ptr<SolidColorLayerImpl> root = SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; @@ -10378,7 +10365,7 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) { int root_layer_id = 1; std::unique_ptr<SolidColorLayerImpl> root = SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; @@ -10426,7 +10413,7 @@ TEST_F(LayerTreeHostImplTest, HiddenSelectionBoundsStayHidden) { int root_layer_id = 1; std::unique_ptr<SolidColorLayerImpl> root = SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; @@ -10827,7 +10814,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ASSERT_TRUE(host_impl_->browser_controls_manager()->has_animation()); EXPECT_TRUE(did_request_next_frame_); EXPECT_TRUE(did_request_redraw_); - EXPECT_FALSE(did_request_commit_); + EXPECT_TRUE(did_request_commit_); // The browser controls should properly animate until finished, despite the // scroll offset being at the origin. @@ -10913,7 +10900,7 @@ TEST_F(LayerTreeHostImplWithBrowserControlsTest, ASSERT_TRUE(host_impl_->browser_controls_manager()->has_animation()); EXPECT_TRUE(did_request_next_frame_); EXPECT_TRUE(did_request_redraw_); - EXPECT_FALSE(did_request_commit_); + EXPECT_TRUE(did_request_commit_); // Animate the browser controls to the limit. viz::BeginFrameArgs begin_frame_args = viz::CreateBeginFrameArgsForTesting( @@ -11049,7 +11036,7 @@ TEST_F(LayerTreeHostImplBrowserControlsTest, { std::unique_ptr<LayerImpl> clip = LayerImpl::Create(layer_tree_impl, 10); clip->SetBounds(root_layer_size); - clip->SetPosition(gfx::PointF()); + clip->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); scroll->SetBounds(scroll_content_size); @@ -11125,7 +11112,7 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { inner_scroll->SetElementId( LayerIdToElementIdForTesting(inner_scroll->id())); inner_scroll->SetBounds(outer_viewport); - inner_scroll->SetPosition(gfx::PointF()); + inner_scroll->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> outer_clip = LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId); @@ -11143,12 +11130,12 @@ class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { ->scroll_tree.UpdateScrollOffsetBaseForTesting( outer_scroll->element_id(), gfx::ScrollOffset()); outer_scroll->SetBounds(content_size); - outer_scroll->SetPosition(gfx::PointF()); + outer_scroll->test_properties()->position = gfx::PointF(); std::unique_ptr<LayerImpl> contents = LayerImpl::Create(layer_tree_impl, 8); contents->SetDrawsContent(true); contents->SetBounds(content_size); - contents->SetPosition(gfx::PointF()); + contents->test_properties()->position = gfx::PointF(); outer_scroll->test_properties()->AddChild(std::move(contents)); outer_clip->test_properties()->AddChild(std::move(outer_scroll)); @@ -13224,8 +13211,8 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( host_impl_->active_tree()->OuterViewportScrollLayer(); if (main_thread_scrolling) { - root_scroll->set_main_thread_scrolling_reasons( - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); + root_scroll->test_properties()->main_thread_scrolling_reasons = + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; } // scrollbar_1 on root scroll. @@ -13240,7 +13227,7 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( touch_action_region.Union(kTouchActionNone, gfx::Rect(scrollbar_size_1)); scrollbar_1->SetTouchActionRegion(touch_action_region); scrollbar_1->SetCurrentPos(0); - scrollbar_1->SetPosition(gfx::PointF(0, 0)); + scrollbar_1->test_properties()->position = gfx::PointF(0, 0); host_impl_->active_tree() ->InnerViewportContainerLayer() ->test_properties() @@ -13331,7 +13318,7 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( true, true); std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl_->active_tree(), child_scroll_id); - child->SetPosition(gfx::PointF(50, 50)); + child->test_properties()->position = gfx::PointF(50, 50); child->SetBounds(child_layer_size); child->SetDrawsContent(true); child->SetScrollable(gfx::Size(100, 100)); @@ -13339,15 +13326,15 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( ElementId child_element_id = child->element_id(); if (main_thread_scrolling) { - child->set_main_thread_scrolling_reasons( - MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects); + child->test_properties()->main_thread_scrolling_reasons = + MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; } scrollbar_2->SetScrollElementId(child_element_id); scrollbar_2->SetDrawsContent(true); scrollbar_2->SetBounds(scrollbar_size_2); scrollbar_2->SetCurrentPos(0); - scrollbar_2->SetPosition(gfx::PointF(0, 0)); + scrollbar_2->test_properties()->position = gfx::PointF(0, 0); child->test_properties()->AddChild(std::move(scrollbar_2)); root_scroll->test_properties()->AddChild(std::move(child)); @@ -13417,22 +13404,22 @@ void LayerTreeHostImplTest::SetupMouseMoveAtTestScrollbarStates( // Capture scrollbar_1, then move mouse to scrollbar_2's layer, should post an // event to fade out scrollbar_1. scrollbar_1_animation_controller->DidScrollUpdate(); - animation_task_ = base::Closure(); + animation_task_.Reset(); host_impl_->MouseDown(); host_impl_->MouseMoveAt(gfx::Point(60, 50)); host_impl_->MouseUp(); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(animation_task_.is_null()); // Near scrollbar_1, then mouse down and up, should not post an event to fade // out scrollbar_1. host_impl_->MouseMoveAt(gfx::Point(40, 150)); - animation_task_ = base::Closure(); + animation_task_.Reset(); host_impl_->MouseDown(); host_impl_->MouseUp(); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_TRUE(animation_task_.is_null()); // Near scrollbar_1, then mouse down and unregister // scrollbar_2_animation_controller, then mouse up should not cause crash. @@ -13804,7 +13791,7 @@ TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToRenderFrameMetadata) { const int root_layer_id = 1; std::unique_ptr<SolidColorLayerImpl> root = SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id); - root->SetPosition(gfx::PointF()); + root->test_properties()->position = gfx::PointF(); root->SetBounds(gfx::Size(10, 10)); root->SetDrawsContent(true); root->test_properties()->force_render_surface = true; @@ -13941,7 +13928,7 @@ TEST_F(LayerTreeHostImplTest, DisabledBuildHitTestData) { std::unique_ptr<SurfaceLayerImpl> surface_child = SurfaceLayerImpl::Create(host_impl_->active_tree(), 3); - surface_child->SetPosition(gfx::PointF(50, 50)); + surface_child->test_properties()->position = gfx::PointF(50, 50); surface_child->SetBounds(gfx::Size(100, 100)); surface_child->SetDrawsContent(true); surface_child->SetSurfaceHitTestable(true); @@ -13980,10 +13967,10 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(1024, 768)); - intermediate_layer->SetPosition(gfx::PointF(200, 300)); + intermediate_layer->test_properties()->position = gfx::PointF(200, 300); intermediate_layer->SetBounds(gfx::Size(200, 200)); - surface_child1->SetPosition(gfx::PointF(50, 50)); + surface_child1->test_properties()->position = gfx::PointF(50, 50); surface_child1->SetBounds(gfx::Size(100, 100)); gfx::Transform rotate; rotate.Rotate(45); @@ -13991,12 +13978,12 @@ TEST_F(HitTestRegionListGeneratingLayerTreeHostImplTest, BuildHitTestData) { surface_child1->SetDrawsContent(true); surface_child1->SetSurfaceHitTestable(true); - surface_child2->SetPosition(gfx::PointF(450, 300)); + surface_child2->test_properties()->position = gfx::PointF(450, 300); surface_child2->SetBounds(gfx::Size(100, 100)); surface_child2->SetDrawsContent(true); surface_child2->SetSurfaceHitTestable(true); - overlapping_layer->SetPosition(gfx::PointF(500, 350)); + overlapping_layer->test_properties()->position = gfx::PointF(500, 350); overlapping_layer->SetBounds(gfx::Size(200, 200)); overlapping_layer->SetDrawsContent(true); diff --git a/chromium/cc/trees/layer_tree_host_perftest.cc b/chromium/cc/trees/layer_tree_host_perftest.cc index 9c800d93374..954455ffa50 100644 --- a/chromium/cc/trees/layer_tree_host_perftest.cc +++ b/chromium/cc/trees/layer_tree_host_perftest.cc @@ -319,7 +319,7 @@ class BrowserCompositorInvalidateLayerTreePerfTest gpu_mailbox.SetName( reinterpret_cast<const int8_t*>(name_stream.str().c_str())); std::unique_ptr<viz::SingleReleaseCallback> callback = - viz::SingleReleaseCallback::Create(base::Bind( + viz::SingleReleaseCallback::Create(base::BindOnce( &BrowserCompositorInvalidateLayerTreePerfTest::ReleaseMailbox, base::Unretained(this))); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc index 39499795006..ae1fb7651df 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_blending.cc @@ -4,6 +4,7 @@ #include <stdint.h> +#include "base/stl_util.h" #include "build/build_config.h" #include "cc/layers/picture_image_layer.h" #include "cc/layers/solid_color_layer.h" @@ -55,7 +56,7 @@ SkColor kCSSTestColors[] = { 0x00000000 // transparent }; -const int kCSSTestColorsCount = arraysize(kCSSTestColors); +const int kCSSTestColorsCount = base::size(kCSSTestColors); using RenderPassOptions = uint32_t; const uint32_t kUseMasks = 1 << 0; @@ -310,7 +311,9 @@ TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithBackdropFilter) { background->AddChild(green_lane); FilterOperations filters; filters.Append(FilterOperation::CreateGrayscaleFilter(.75)); + gfx::RectF backdrop_filter_bounds; green_lane->SetBackdropFilters(filters); + green_lane->SetBackdropFilterBounds(backdrop_filter_bounds); green_lane->SetBlendMode(current_blend_mode()); SkBitmap expected; diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc index 67e3b25aefc..22c12b0c521 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_filters.cc @@ -36,6 +36,8 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlur) { filters.Append(FilterOperation::CreateBlurFilter( 2.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackdropFilters(filters); + gfx::RectF backdrop_filter_bounds(gfx::SizeF(blur->bounds())); + 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 @@ -77,6 +79,8 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOutsets) { filters.Append(FilterOperation::CreateBlurFilter( 5.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackdropFilters(filters); + gfx::RectF backdrop_filter_bounds(gfx::SizeF(blur->bounds())); + blur->SetBackdropFilterBounds(backdrop_filter_bounds); #if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) || defined(ARCH_CPU_ARM64) @@ -143,6 +147,8 @@ TEST_F(LayerTreeHostFiltersPixelTest, BackdropFilterBlurOffAxis) { filters.Append(FilterOperation::CreateBlurFilter( 2.f, SkBlurImageFilter::kClamp_TileMode)); blur->SetBackdropFilters(filters); + // TODO(916311): Fix clipping for 3D transformed elements. + blur->SetBackdropFilterBounds(gfx::RectF()); #if defined(OS_WIN) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) @@ -420,6 +426,7 @@ class ImageScaledBackdropFilter : public LayerTreeHostFiltersPixelTest { FilterOperations filters; filters.Append(FilterOperation::CreateGrayscaleFilter(1.0f)); filter->SetBackdropFilters(filters); + filter->SetBackdropFilterBounds(gfx::RectF()); #if defined(OS_WIN) || defined(_MIPS_ARCH_LOONGSON) || defined(ARCH_CPU_ARM64) #if defined(OS_WIN) @@ -481,22 +488,27 @@ class ImageBackdropFilter : public LayerTreeHostFiltersPixelTest { background->AddChild(layer); // Add a slightly transparent blue layer. - scoped_refptr<SolidColorLayer> filter = - CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorBLUE); - filter->SetOpacity(0.137f); + SkColor transparent_blue = SkColorSetARGB(0x23, 0x00, 0x00, 0xFF); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), transparent_blue); // Add some rotation so that we can see that it blurs only under the layer. gfx::Transform transform_filter; transform_filter.RotateAboutZAxis(10.0); - filter->SetTransform(transform_filter); - - background->AddChild(filter); + filter_layer->SetTransform(transform_filter); // Add a blur filter to the blue layer. FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter( 5.0f, SkBlurImageFilter::kClamp_TileMode)); - filter->SetBackdropFilters(filters); + filter_layer->SetBackdropFilters(filters); + // TODO(916311): Adding filter bounds here should work, but it clips + // the corner of the red box. + // gfx::RectF backdrop_filter_bounds(gfx::SizeF(filter_layer->bounds())); + gfx::RectF backdrop_filter_bounds; + filter_layer->SetBackdropFilterBounds(backdrop_filter_bounds); + + background->AddChild(filter_layer); // Allow some fuzziness so that this doesn't fail when Skia makes minor // changes to blur or rectangle rendering. @@ -613,6 +625,8 @@ class ZoomFilterTest : public LayerTreeHostFiltersPixelTest { border_filters.Append( FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); border_edge_zoom->SetBackdropFilters(border_filters); + gfx::RectF border_filter_bounds(gfx::SizeF(border_edge_zoom->bounds())); + border_edge_zoom->SetBackdropFilterBounds(border_filter_bounds); root->AddChild(border_edge_zoom); // Test a zoom that extends past the edge of the screen. @@ -622,6 +636,8 @@ class ZoomFilterTest : public LayerTreeHostFiltersPixelTest { top_filters.Append( FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); top_edge_zoom->SetBackdropFilters(top_filters); + gfx::RectF top_filter_bounds(gfx::SizeF(top_edge_zoom->bounds())); + top_edge_zoom->SetBackdropFilterBounds(top_filter_bounds); root->AddChild(top_edge_zoom); // Test a zoom that is fully within the screen. @@ -631,6 +647,8 @@ class ZoomFilterTest : public LayerTreeHostFiltersPixelTest { mid_filters.Append( FilterOperation::CreateZoomFilter(2.f /* zoom */, 0 /* inset */)); contained_zoom->SetBackdropFilters(mid_filters); + gfx::RectF mid_filter_bounds(gfx::SizeF(contained_zoom->bounds())); + contained_zoom->SetBackdropFilterBounds(mid_filter_bounds); root->AddChild(contained_zoom); #if defined(OS_WIN) @@ -1074,6 +1092,7 @@ class BackdropFilterWithDeviceScaleFactorTest filters.Append(FilterOperation::CreateReferenceFilter( sk_make_sp<OffsetPaintFilter>(0, 80, nullptr))); filtered->SetBackdropFilters(filters); + filtered->SetBackdropFilterBounds(gfx::RectF()); root->AddChild(filtered); // This should appear as a grid of 4 100x100 squares which are: diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc index 4639cb3cd2e..36726cc817e 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_masks.cc @@ -4,6 +4,7 @@ #include <stddef.h> +#include "base/stl_util.h" #include "build/build_config.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/picture_image_layer.h" @@ -296,7 +297,9 @@ TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest, FilterOperations filters; filters.Append(FilterOperation::CreateGrayscaleFilter(1.0)); + gfx::RectF backdrop_filter_bounds; blur->SetBackdropFilters(filters); + blur->SetBackdropFilterBounds(backdrop_filter_bounds); gfx::Size mask_bounds(100, 100); CircleContentLayerClient mask_client(mask_bounds); @@ -493,7 +496,7 @@ class LayerTreeHostMaskAsBlendingPixelTest for (int j = 0; j < (bounds.height() + grid_size - 1) / grid_size; j++) { for (int i = 0; i < (bounds.width() + grid_size - 1) / grid_size; i++) { PaintFlags flags; - flags.setColor(test_colors[(i + j * 3) % arraysize(test_colors)]); + flags.setColor(test_colors[(i + j * 3) % base::size(test_colors)]); display_list->push<DrawRectOp>( SkRect::MakeXYWH(i * grid_size, j * grid_size, grid_size, grid_size), @@ -756,6 +759,8 @@ TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest, FilterOperations filters; filters.Append(FilterOperation::CreateGrayscaleFilter(1.0)); picture_horizontal->SetBackdropFilters(filters); + gfx::RectF backdrop_filter_bounds; + picture_horizontal->SetBackdropFilterBounds(backdrop_filter_bounds); background->AddChild(picture_vertical); background->AddChild(picture_horizontal); diff --git a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc index 17484e50c76..d6e39e34b3e 100644 --- a/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/chromium/cc/trees/layer_tree_host_pixeltest_readback.cc @@ -125,12 +125,13 @@ class LayerTreeHostReadbackPixelTest gpu::Mailbox mailbox = result->GetTextureResult()->mailbox; gpu::SyncToken sync_token = result->GetTextureResult()->sync_token; + gfx::ColorSpace color_space = result->GetTextureResult()->color_space; EXPECT_EQ(result->GetTextureResult()->color_space, output_color_space_); std::unique_ptr<viz::SingleReleaseCallback> release_callback = result->TakeTextureOwnership(); const SkBitmap bitmap = - CopyMailboxToBitmap(result->size(), mailbox, sync_token); + CopyMailboxToBitmap(result->size(), mailbox, sync_token, color_space); release_callback->Run(gpu::SyncToken(), false); ReadbackResultAsBitmap(std::make_unique<viz::CopyOutputSkBitmapResult>( diff --git a/chromium/cc/trees/layer_tree_host_single_thread_client.h b/chromium/cc/trees/layer_tree_host_single_thread_client.h index a648ed5a45e..f2ce8e18597 100644 --- a/chromium/cc/trees/layer_tree_host_single_thread_client.h +++ b/chromium/cc/trees/layer_tree_host_single_thread_client.h @@ -11,11 +11,9 @@ namespace cc { class LayerTreeHostSingleThreadClient { public: - // Request that the client schedule a composite. + // Request that the client schedule a composite. For tests using single thread + // without a scheduler. virtual void RequestScheduleComposite() {} - // Request that the client schedule a composite now, and calculate appropriate - // delay for potential future frame. - virtual void RequestScheduleAnimation() {} // Called whenever the begin frame interval changes. This interval can be used // for animations. diff --git a/chromium/cc/trees/layer_tree_host_unittest.cc b/chromium/cc/trees/layer_tree_host_unittest.cc index 97e682c6c82..fedcb0baaf3 100644 --- a/chromium/cc/trees/layer_tree_host_unittest.cc +++ b/chromium/cc/trees/layer_tree_host_unittest.cc @@ -230,7 +230,7 @@ class LayerTreeHostTestRequestedMainFrame : public LayerTreeHostTest { void NextStep() { // The MainFrame request is cleared once a MainFrame happens. - EXPECT_FALSE(layer_tree_host()->RequestedMainFramePending()); + EXPECT_FALSE(layer_tree_host()->RequestedMainFramePendingForTesting()); switch (layer_tree_host()->SourceFrameNumber()) { case 0: ADD_FAILURE() @@ -250,7 +250,7 @@ class LayerTreeHostTestRequestedMainFrame : public LayerTreeHostTest { return; } // SetNeeds{Animate,UpdateLayers,Commit}() will mean a MainFrame is pending. - EXPECT_TRUE(layer_tree_host()->RequestedMainFramePending()); + EXPECT_TRUE(layer_tree_host()->RequestedMainFramePendingForTesting()); } void AfterTest() override {} @@ -3412,10 +3412,6 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers FakePictureLayerImpl* child = static_cast<FakePictureLayerImpl*>( impl->active_tree()->LayerById(child_layer_->id())); - // Positions remain in layout pixels. - EXPECT_EQ(gfx::PointF(), root->position()); - EXPECT_EQ(gfx::PointF(2.f, 2.f), child->position()); - // Compute all the layer transforms for the frame. LayerTreeHostImpl::FrameData frame_data; impl->PrepareToDraw(&frame_data); @@ -4114,7 +4110,7 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { base::SingleThreadTaskRunner* task_runner, bool synchronous_composite, double refresh_rate, - base::Closure invalidate_callback) + base::RepeatingClosure invalidate_callback) : TestLayerTreeFrameSink(std::move(compositor_context_provider), std::move(worker_context_provider), gpu_memory_buffer_manager, @@ -4135,7 +4131,7 @@ class OnDrawLayerTreeFrameSink : public viz::TestLayerTreeFrameSink { } private: - const base::Closure invalidate_callback_; + const base::RepeatingClosure invalidate_callback_; }; class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor @@ -4152,7 +4148,7 @@ class LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor scoped_refptr<viz::ContextProvider> compositor_context_provider, scoped_refptr<viz::RasterContextProvider> worker_context_provider) override { - auto on_draw_callback = base::Bind( + auto on_draw_callback = base::BindRepeating( &LayerTreeHostTestAbortedCommitDoesntStallSynchronousCompositor:: CallOnDraw, base::Unretained(this)); @@ -4300,32 +4296,32 @@ class LayerTreeHostTestUIResource : public LayerTreeHostTest { } void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { - auto* context = static_cast<viz::TestContextProvider*>( - impl->layer_tree_frame_sink()->context_provider()) - ->TestContextGL(); + auto* sii = static_cast<viz::TestContextProvider*>( + impl->layer_tree_frame_sink()->context_provider()) + ->SharedImageInterface(); int frame = impl->active_tree()->source_frame_number(); switch (frame) { case 0: - ASSERT_EQ(0u, context->NumTextures()); + ASSERT_EQ(0u, sii->shared_image_count()); break; case 1: // Created two textures. - ASSERT_EQ(2u, context->NumTextures()); + ASSERT_EQ(2u, sii->shared_image_count()); break; case 2: // One texture left after one deletion. - ASSERT_EQ(1u, context->NumTextures()); + ASSERT_EQ(1u, sii->shared_image_count()); break; case 3: // Resource manager state should not change when delete is called on an // invalid id. - ASSERT_EQ(1u, context->NumTextures()); + ASSERT_EQ(1u, sii->shared_image_count()); break; case 4: // Creation after deletion: two more creates should total up to // three textures. - ASSERT_EQ(3u, context->NumTextures()); + ASSERT_EQ(3u, sii->shared_image_count()); break; } } @@ -5352,10 +5348,10 @@ class LayerTreeHostTestTreeActivationCallback : public LayerTreeHostTest { void SetCallback(LayerTreeHostImpl* host_impl, bool enable) { host_impl->SetTreeActivationCallback( enable - ? base::Bind( + ? base::BindRepeating( &LayerTreeHostTestTreeActivationCallback::ActivationCallback, base::Unretained(this)) - : base::Closure()); + : base::RepeatingClosure()); } void ActivationCallback() { ++callback_count_; } @@ -5899,10 +5895,10 @@ class LayerTreeHostTestKeepSwapPromise : public LayerTreeHostTest { void SetCallback(LayerTreeHostImpl* host_impl, bool enable) { host_impl->SetTreeActivationCallback( - enable - ? base::Bind(&LayerTreeHostTestKeepSwapPromise::ActivationCallback, - base::Unretained(this)) - : base::Closure()); + enable ? base::BindRepeating( + &LayerTreeHostTestKeepSwapPromise::ActivationCallback, + base::Unretained(this)) + : base::RepeatingClosure()); } void DisplayDidDrawAndSwapOnThread() override { @@ -6016,10 +6012,10 @@ class LayerTreeHostTestKeepSwapPromiseMFBA : public LayerTreeHostTest { void SetCallback(LayerTreeHostImpl* host_impl, bool enable) { host_impl->SetTreeActivationCallback( - enable ? base::Bind( + enable ? base::BindRepeating( &LayerTreeHostTestKeepSwapPromiseMFBA::ActivationCallback, base::Unretained(this)) - : base::Closure()); + : base::RepeatingClosure()); } void DisplayDidDrawAndSwapOnThread() override { @@ -7849,55 +7845,15 @@ class LayerTreeHostTestPaintedDeviceScaleFactor : public LayerTreeHostTest { }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPaintedDeviceScaleFactor); -// Makes sure that presentation-time requests are correctly propagated to the -// frame's metadata. -class LayerTreeHostTestPresentationTimeRequest : public LayerTreeHostTest { +// Tests that a presentation-timestamps are received for a frame. +class LayerTreeHostTestPresentationTime : public LayerTreeHostTest { protected: void BeginTest() override { - layer_tree_host()->RequestPresentationTimeForNextFrame(base::DoNothing()); PostSetNeedsCommitToMainThread(); } void DisplayReceivedCompositorFrameOnThread( const viz::CompositorFrame& frame) override { - EXPECT_TRUE(frame.metadata.request_presentation_feedback); - EndTest(); - } - - void AfterTest() override {} -}; -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPresentationTimeRequest); - -// A SwapPromise that turns on |request_presentation_feedback| during -// WillSwap(). -class RequestPresentationFeedbackSwapPromise : public SwapPromise { - public: - RequestPresentationFeedbackSwapPromise() = default; - ~RequestPresentationFeedbackSwapPromise() override = default; - - // SwapPromise: - void DidActivate() override {} - void WillSwap(viz::CompositorFrameMetadata* metadata) override { - metadata->request_presentation_feedback = true; - } - void DidSwap() override {} - void DidNotSwap(DidNotSwapReason reason) override {} - int64_t TraceId() const override { return 0; } -}; - -// Tests that a presentation-token can be requested during swap. -class LayerTreeHostTestPresentationTimeRequestDuringSwap - : public LayerTreeHostTest { - protected: - void BeginTest() override { - layer_tree_host()->QueueSwapPromise( - std::make_unique<RequestPresentationFeedbackSwapPromise>()); - PostSetNeedsCommitToMainThread(); - } - - void DisplayReceivedCompositorFrameOnThread( - const viz::CompositorFrame& frame) override { - EXPECT_TRUE(frame.metadata.request_presentation_feedback); frame_token_ = frame.metadata.frame_token; } @@ -7914,8 +7870,7 @@ class LayerTreeHostTestPresentationTimeRequestDuringSwap private: uint32_t frame_token_ = 0; }; -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostTestPresentationTimeRequestDuringSwap); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestPresentationTime); // Makes sure that viz::LocalSurfaceId is propagated to the LayerTreeFrameSink. class LayerTreeHostTestLocalSurfaceId : public LayerTreeHostTest { @@ -7970,15 +7925,8 @@ class LayerTreeHostTestLocalSurfaceIdSkipChildNum : public LayerTreeHostTest { allocator_.GetCurrentLocalSurfaceIdAllocation(); EXPECT_TRUE(child_allocator_.UpdateFromParent( allocator_.GetCurrentLocalSurfaceIdAllocation())); - child_allocator_.GenerateId(); - child_local_surface_id_allocation_ = - child_allocator_.GetCurrentLocalSurfaceIdAllocation(); - EXPECT_NE(expected_local_surface_id_allocation_, - child_local_surface_id_allocation_); PostSetLocalSurfaceIdAllocationToMainThread( expected_local_surface_id_allocation_); - PostSetLocalSurfaceIdAllocationToMainThread( - child_local_surface_id_allocation_); } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -7989,6 +7937,26 @@ class LayerTreeHostTestLocalSurfaceIdSkipChildNum : public LayerTreeHostTest { EXPECT_EQ( expected_local_surface_id_allocation_, host_impl->active_tree()->local_surface_id_allocation_from_parent()); + + // This initial test setup triggers a commit and subsequent draw. Upon the + // first draw, enqueue the second portion of the test. The newly pushed id, + // with an advanced child sequence number, but no change in parent sequence, + // should not trigger a commit. If it does, then PrepareToDrawOnThread will + // be called a second time, and the expectation upon viz::LocalSurfaceId + // will fail. We do not assert on frame number, as that interferes with + // returning from this method. We do not just have an expectation either, + // as then we would continuously increment that child sequence until the + // test times out. + if (!host_impl->active_tree()->source_frame_number()) { + child_allocator_.GenerateId(); + child_local_surface_id_allocation_ = + child_allocator_.GetCurrentLocalSurfaceIdAllocation(); + EXPECT_NE(expected_local_surface_id_allocation_, + child_local_surface_id_allocation_); + PostSetLocalSurfaceIdAllocationToMainThread( + child_local_surface_id_allocation_); + } + return draw_result; } @@ -8344,9 +8312,9 @@ class LayerTreeHostTestQueueImageDecode : public LayerTreeHostTest { image_ = DrawImage(CreateDiscardablePaintImage(gfx::Size(400, 400)), SkIRect::MakeWH(400, 400), kNone_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex); - auto callback = - base::Bind(&LayerTreeHostTestQueueImageDecode::ImageDecodeFinished, - base::Unretained(this)); + auto callback = base::BindRepeating( + &LayerTreeHostTestQueueImageDecode::ImageDecodeFinished, + base::Unretained(this)); // Schedule the decode twice for the same image. layer_tree_host()->QueueImageDecode(image_.paint_image(), callback); layer_tree_host()->QueueImageDecode(image_.paint_image(), callback); @@ -8401,10 +8369,10 @@ class LayerTreeHostTestQueueImageDecodeNonLazy : public LayerTreeHostTest { .set_image(SkImage::MakeFromBitmap(bitmap_), PaintImage::GetNextContentId()) .TakePaintImage(); - auto callback = base::Bind( + auto callback = base::BindOnce( &LayerTreeHostTestQueueImageDecodeNonLazy::ImageDecodeFinished, base::Unretained(this)); - layer_tree_host()->QueueImageDecode(image, callback); + layer_tree_host()->QueueImageDecode(image, std::move(callback)); } void ImageDecodeFinished(bool decode_succeeded) { @@ -8476,9 +8444,9 @@ class LayerTreeHostTestDiscardAckAfterRelease : public LayerTreeHostTest { // that WillReceiveCompositorFrameAck which we PostTask below will be called // before DidReceiveCompositorFrameAck. MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&LayerTreeHostTestDiscardAckAfterRelease:: - WillReceiveCompositorFrameAck, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&LayerTreeHostTestDiscardAckAfterRelease:: + WillReceiveCompositorFrameAck, + base::Unretained(this))); } void WillReceiveCompositorFrameAck() { @@ -8505,8 +8473,8 @@ class LayerTreeHostTestDiscardAckAfterRelease : public LayerTreeHostTest { // before we are in CheckFrameAck. MainThreadTaskRunner()->PostTask( FROM_HERE, - base::Bind(&LayerTreeHostTestDiscardAckAfterRelease::CheckFrameAck, - base::Unretained(this))); + base::BindOnce(&LayerTreeHostTestDiscardAckAfterRelease::CheckFrameAck, + base::Unretained(this))); } void DidReceiveCompositorFrameAck() override { received_ack_ = true; } diff --git a/chromium/cc/trees/layer_tree_host_unittest_animation.cc b/chromium/cc/trees/layer_tree_host_unittest_animation.cc index d50a4cce305..dd854fb5e02 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_animation.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_animation.cc @@ -1061,8 +1061,7 @@ class LayerTreeHostPresentationDuringAnimation void DisplayReceivedCompositorFrameOnThread( const viz::CompositorFrame& frame) override { - if (frame.metadata.request_presentation_feedback) - received_token_ = frame.metadata.frame_token; + received_token_ = frame.metadata.frame_token; } void AfterTest() override { diff --git a/chromium/cc/trees/layer_tree_host_unittest_context.cc b/chromium/cc/trees/layer_tree_host_unittest_context.cc index a871ac9d1a9..aa7781a0e12 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_context.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_context.cc @@ -5,6 +5,7 @@ #include <stddef.h> #include <stdint.h> +#include "base/stl_util.h" #include "build/build_config.h" #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/layer_impl.h" @@ -107,6 +108,8 @@ class LayerTreeHostContextTest : public LayerTreeTest { GL_INNOCENT_CONTEXT_RESET_ARB); } + sii_ = provider->SharedImageInterface(); + return LayerTreeTest::CreateLayerTreeFrameSink( renderer_settings, refresh_rate, std::move(provider), std::move(worker_context_provider)); @@ -162,6 +165,7 @@ class LayerTreeHostContextTest : public LayerTreeTest { // CreateDisplayLayerTreeFrameSink can both use it on different threads. base::Lock gl_lock_; viz::TestGLES2Interface* gl_ = nullptr; + viz::TestSharedImageInterface* sii_ = nullptr; int times_to_fail_create_; int times_to_lose_during_commit_; @@ -325,7 +329,7 @@ class LayerTreeHostContextTestLostContextSucceeds }, }; - if (test_case_ >= arraysize(kTests)) + if (test_case_ >= base::size(kTests)) return false; // Make sure that we lost our context at least once in the last test run so // the test did something. @@ -932,9 +936,9 @@ class LayerTreeHostContextTestDontUseLostResources auto resource = viz::TransferableResource::MakeGL( mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token); texture->SetTransferableResource( - resource, viz::SingleReleaseCallback::Create( - base::Bind(&LayerTreeHostContextTestDontUseLostResources:: - EmptyReleaseCallback))); + resource, viz::SingleReleaseCallback::Create(base::BindOnce( + &LayerTreeHostContextTestDontUseLostResources:: + EmptyReleaseCallback))); root->AddChild(texture); scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client_); @@ -1494,7 +1498,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override { if (!visible) { // All resources should have been evicted. - ASSERT_EQ(0u, gl_->NumTextures()); + ASSERT_EQ(0u, sii_->shared_image_count()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource3_->id())); @@ -1514,7 +1518,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { case 1: // The first two resources should have been created on LTHI after the // commit. - ASSERT_EQ(2u, gl_->NumTextures()); + ASSERT_EQ(2u, sii_->shared_image_count()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1522,7 +1526,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { EXPECT_TRUE(impl->CanDraw()); // Evict all UI resources. This will trigger a commit. impl->EvictAllUIResources(); - ASSERT_EQ(0u, gl_->NumTextures()); + ASSERT_EQ(0u, sii_->shared_image_count()); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id())); EXPECT_EQ(1, ui_resource_->resource_create_count); @@ -1531,7 +1535,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { break; case 2: // The first two resources should have been recreated. - ASSERT_EQ(2u, gl_->NumTextures()); + ASSERT_EQ(2u, sii_->shared_image_count()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(2, ui_resource_->resource_create_count); EXPECT_EQ(1, ui_resource_->lost_resource_count); @@ -1543,7 +1547,7 @@ class UIResourceLostEviction : public UIResourceLostTestSimple { case 3: // The first resource should have been recreated after visibility was // restored. - ASSERT_EQ(2u, gl_->NumTextures()); + ASSERT_EQ(2u, sii_->shared_image_count()); EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); EXPECT_EQ(3, ui_resource_->resource_create_count); EXPECT_EQ(2, ui_resource_->lost_resource_count); @@ -1585,7 +1589,7 @@ class UIResourceFreedIfLostWhileExported : public LayerTreeHostContextTest { case 0: // The UIResource has been created and a gpu resource made for it. EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); - EXPECT_EQ(1u, gl_->NumTextures()); + EXPECT_EQ(1u, sii_->shared_image_count()); // Lose the LayerTreeFrameSink connection. The UI resource should // be replaced and the old texture should be destroyed. impl->DidLoseLayerTreeFrameSink(); @@ -1594,7 +1598,7 @@ class UIResourceFreedIfLostWhileExported : public LayerTreeHostContextTest { // The UIResource has been recreated, the old texture is not kept // around. EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); - EXPECT_EQ(1u, gl_->NumTextures()); + EXPECT_EQ(1u, sii_->shared_image_count()); MainThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce( diff --git a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc index b918f70e69a..9fa460e05f9 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_proxy.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_proxy.cc @@ -255,11 +255,11 @@ class LayerTreeHostProxyTestCommitWaitsForActivation switch (impl->sync_tree()->source_frame_number()) { case 0: { // This is for case 1 in DidCommit. - auto unblock = base::Bind( + auto unblock = base::BindOnce( &LayerTreeHostProxyTestCommitWaitsForActivation::UnblockActivation, base::Unretained(this), impl); ImplThreadTaskRunner()->PostDelayedTask( - FROM_HERE, unblock, + FROM_HERE, std::move(unblock), // Use a delay to allow the main frame to start if it would. This // should cause failures (or flakiness) if we fail to wait for the // activation before starting the main frame. @@ -348,13 +348,13 @@ class LayerTreeHostProxyTestCommitWaitsForActivationMFBA // This is the main frame with SetNextCommitWaitsForActivation(). // Activation is currently blocked for the previous main frame (from the // case above). We unblock activate to allow this main frame to commit. - auto unblock = - base::Bind(&LayerTreeHostImpl::BlockNotifyReadyToActivateForTesting, - base::Unretained(impl), false); + auto unblock = base::BindOnce( + &LayerTreeHostImpl::BlockNotifyReadyToActivateForTesting, + base::Unretained(impl), false); // Post the unblock instead of doing it immediately so that the main // frame is fully processed by the compositor thread, and it has a full // opportunity to wrongly unblock the main thread. - ImplThreadTaskRunner()->PostTask(FROM_HERE, unblock); + ImplThreadTaskRunner()->PostTask(FROM_HERE, std::move(unblock)); // Once activation completes, we'll begin the commit for frame 1. break; } @@ -376,11 +376,12 @@ class LayerTreeHostProxyTestCommitWaitsForActivationMFBA // failures (or flakiness) if we fail to wait for the activation before // starting the main frame. auto unblock = - base::Bind(&LayerTreeHostProxyTestCommitWaitsForActivationMFBA:: - UnblockActivation, - base::Unretained(this), impl); + base::BindOnce(&LayerTreeHostProxyTestCommitWaitsForActivationMFBA:: + UnblockActivation, + base::Unretained(this), impl); ImplThreadTaskRunner()->PostDelayedTask( - FROM_HERE, unblock, base::TimeDelta::FromMilliseconds(16 * 4)); + FROM_HERE, std::move(unblock), + base::TimeDelta::FromMilliseconds(16 * 4)); } } diff --git a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc index cef1be4927f..f2d96d8bbd5 100644 --- a/chromium/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/chromium/cc/trees/layer_tree_host_unittest_scroll.cc @@ -100,8 +100,9 @@ class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest { layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset( initial_scroll_); layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&LayerTreeHostScrollTestScrollSimple::DidScrollOuterViewport, - base::Unretained(this))); + base::BindRepeating( + &LayerTreeHostScrollTestScrollSimple::DidScrollOuterViewport, + base::Unretained(this))); PostSetNeedsCommitToMainThread(); } @@ -171,7 +172,7 @@ class LayerTreeHostScrollTestScrollMultipleRedraw void BeginTest() override { scroll_layer_ = layer_tree_host()->outer_viewport_scroll_layer(); scroll_layer_->SetScrollOffset(initial_scroll_); - scroll_layer_->set_did_scroll_callback(base::Bind( + scroll_layer_->set_did_scroll_callback(base::BindRepeating( &LayerTreeHostScrollTestScrollMultipleRedraw::DidScrollOuterViewport, base::Unretained(this))); PostSetNeedsCommitToMainThread(); @@ -259,7 +260,7 @@ class LayerTreeHostScrollTestScrollAbortedCommit layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset( initial_scroll_); layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind( + base::BindRepeating( &LayerTreeHostScrollTestScrollAbortedCommit::DidScrollOuterViewport, base::Unretained(this))); PostSetNeedsCommitToMainThread(); @@ -579,8 +580,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { child_layer_ = FakePictureLayer::Create(&fake_content_layer_client_); child_layer_->set_did_scroll_callback( - base::Bind(&LayerTreeHostScrollTestCaseWithChild::DidScroll, - base::Unretained(this))); + base::BindRepeating(&LayerTreeHostScrollTestCaseWithChild::DidScroll, + base::Unretained(this))); child_layer_->SetElementId( LayerIdToElementIdForTesting(child_layer_->id())); child_layer_->SetBounds(gfx::Size(110, 110)); @@ -617,7 +618,7 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { fake_content_layer_client_.set_bounds(root_layer->bounds()); layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind( + base::BindRepeating( &LayerTreeHostScrollTestCaseWithChild::DidScrollOuterViewport, base::Unretained(this))); } @@ -695,9 +696,9 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { case 0: { // GESTURE scroll on impl thread. Also tests that the last scrolled // layer id is stored even after the scrolling ends. - gfx::Point scroll_point = - gfx::ToCeiledPoint(expected_scroll_layer_impl->position() - - gfx::Vector2dF(0.5f, 0.5f)); + gfx::Point scroll_point = gfx::ToCeiledPoint( + expected_scroll_layer_impl->test_properties()->position - + gfx::Vector2dF(0.5f, 0.5f)); InputHandler::ScrollStatus status = impl->ScrollBegin( BeginState(scroll_point).get(), InputHandler::TOUCHSCREEN); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); @@ -720,9 +721,9 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest { } case 1: { // WHEEL scroll on impl thread. - gfx::Point scroll_point = - gfx::ToCeiledPoint(expected_scroll_layer_impl->position() + - gfx::Vector2dF(0.5f, 0.5f)); + gfx::Point scroll_point = gfx::ToCeiledPoint( + expected_scroll_layer_impl->test_properties()->position + + gfx::Vector2dF(0.5f, 0.5f)); InputHandler::ScrollStatus status = impl->ScrollBegin( BeginState(scroll_point).get(), InputHandler::WHEEL); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); @@ -840,8 +841,9 @@ class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest { layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset( initial_scroll_); layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&LayerTreeHostScrollTestSimple::DidScrollOuterViewport, - base::Unretained(this))); + base::BindRepeating( + &LayerTreeHostScrollTestSimple::DidScrollOuterViewport, + base::Unretained(this))); PostSetNeedsCommitToMainThread(); } @@ -1412,7 +1414,7 @@ class LayerTreeHostScrollTestLayerStructureChange LayerIdToElementIdForTesting(scroll_layer->id())); scroll_layer->SetBounds(gfx::Size(parent->bounds().width() + 100, parent->bounds().height() + 100)); - scroll_layer->set_did_scroll_callback(base::Bind( + scroll_layer->set_did_scroll_callback(base::BindRepeating( &FakeLayerScrollClient::DidScroll, base::Unretained(client))); client->owner_ = this; client->layer_ = scroll_layer.get(); @@ -1471,8 +1473,9 @@ class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest { layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset( initial_scroll_); layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&LayerTreeHostScrollTestScrollMFBA::DidScrollOuterViewport, - base::Unretained(this))); + base::BindRepeating( + &LayerTreeHostScrollTestScrollMFBA::DidScrollOuterViewport, + base::Unretained(this))); PostSetNeedsCommitToMainThread(); } @@ -1601,9 +1604,9 @@ class LayerTreeHostScrollTestScrollAbortedCommitMFBA layer_tree_host()->outer_viewport_scroll_layer()->SetScrollOffset( initial_scroll_); layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&LayerTreeHostScrollTestScrollAbortedCommitMFBA:: - DidScrollOuterViewport, - base::Unretained(this))); + base::BindRepeating(&LayerTreeHostScrollTestScrollAbortedCommitMFBA:: + DidScrollOuterViewport, + base::Unretained(this))); PostSetNeedsCommitToMainThread(); } @@ -2050,9 +2053,9 @@ class LayerTreeHostScrollTestImplSideInvalidation : public LayerTreeHostScrollTest { void BeginTest() override { layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback( - base::Bind(&LayerTreeHostScrollTestImplSideInvalidation:: - DidScrollOuterViewport, - base::Unretained(this))); + base::BindRepeating(&LayerTreeHostScrollTestImplSideInvalidation:: + DidScrollOuterViewport, + base::Unretained(this))); PostSetNeedsCommitToMainThread(); } diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc index db91dda80b5..034dc7e2959 100644 --- a/chromium/cc/trees/layer_tree_impl.cc +++ b/chromium/cc/trees/layer_tree_impl.cc @@ -15,6 +15,7 @@ #include "base/containers/adapters.h" #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" +#include "base/json/json_writer.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" @@ -472,6 +473,7 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { // The page scale factor update can affect scrolling which requires that // these ids are set, so this must be before PushPageScaleFactorAndLimits. target_tree->SetViewportLayersFromIds(viewport_layer_ids_); + target_tree->set_viewport_property_ids(viewport_property_ids_); // Active tree already shares the page_scale_factor object with pending // tree so only the limits need to be provided. @@ -680,7 +682,8 @@ void LayerTreeImpl::SetTransformMutated(ElementId element_id, const gfx::Transform& transform) { DCHECK_EQ(1u, property_trees()->element_id_to_transform_node_index.count( element_id)); - element_id_to_transform_animations_[element_id] = transform; + if (IsSyncTree() || IsRecycleTree()) + element_id_to_transform_animations_[element_id] = transform; if (property_trees()->transform_tree.OnTransformAnimated(element_id, transform)) set_needs_update_draw_properties(); @@ -689,7 +692,8 @@ void LayerTreeImpl::SetTransformMutated(ElementId element_id, void LayerTreeImpl::SetOpacityMutated(ElementId element_id, float opacity) { DCHECK_EQ( 1u, property_trees()->element_id_to_effect_node_index.count(element_id)); - element_id_to_opacity_animations_[element_id] = opacity; + if (IsSyncTree() || IsRecycleTree()) + element_id_to_opacity_animations_[element_id] = opacity; if (property_trees()->effect_tree.OnOpacityAnimated(element_id, opacity)) set_needs_update_draw_properties(); } @@ -698,7 +702,8 @@ void LayerTreeImpl::SetFilterMutated(ElementId element_id, const FilterOperations& filters) { DCHECK_EQ( 1u, property_trees()->element_id_to_effect_node_index.count(element_id)); - element_id_to_filter_animations_[element_id] = filters; + if (IsSyncTree() || IsRecycleTree()) + element_id_to_filter_animations_[element_id] = filters; if (property_trees()->effect_tree.OnFilterAnimated(element_id, filters)) set_needs_update_draw_properties(); } @@ -772,6 +777,10 @@ void LayerTreeImpl::UpdatePropertyTreeAnimationFromMainThread() { // respective tree. This can be the case if the layer associated // with that element id has been removed. + // This code is assumed to only run on the sync tree; the node updates are + // then synced when the tree is activated. See http://crbug.com/916512 + DCHECK(IsSyncTree()); + auto element_id_to_opacity = element_id_to_opacity_animations_.begin(); while (element_id_to_opacity != element_id_to_opacity_animations_.end()) { const ElementId id = element_id_to_opacity->first; @@ -1184,9 +1193,13 @@ void LayerTreeImpl::ClearViewportLayers() { const ScrollNode* LayerTreeImpl::InnerViewportScrollNode() const { auto* inner_scroll = InnerViewportScrollLayer(); - if (!inner_scroll) - return nullptr; - + if (!inner_scroll) { + // TODO(crbug.com/909750): Check all other callers of + // InnerViewportScrollLayer() and switch to + // viewport_property_ids_.inner_scroll if needed. + return property_trees()->scroll_tree.Node( + viewport_property_ids_.inner_scroll); + } return property_trees()->scroll_tree.Node(inner_scroll->scroll_tree_index()); } @@ -2141,7 +2154,7 @@ LayerImpl* LayerTreeImpl::FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( struct HitTestVisibleScrollableOrTouchableFunctor { bool operator()(LayerImpl* layer) const { - return layer->scrollable() || layer->should_hit_test() || + return layer->scrollable() || layer->ShouldHitTest() || !layer->touch_action_region().region().IsEmpty(); } }; @@ -2336,4 +2349,31 @@ void LayerTreeImpl::ResetAllChangeTracking() { property_trees_.ResetAllChangeTracking(); } +std::string LayerTreeImpl::LayerListAsJson() const { + auto list = std::make_unique<base::ListValue>(); + for (auto* layer : *this) + list->Append(layer->LayerAsJson()); + std::string str; + base::JSONWriter::WriteWithOptions( + *list, + base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION | + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &str); + return str; +} + +std::string LayerTreeImpl::LayerTreeAsJson() const { + std::string str; + if (root_layer_for_testing_) { + std::unique_ptr<base::Value> json( + root_layer_for_testing_->LayerTreeAsJson()); + base::JSONWriter::WriteWithOptions( + *json, + base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION | + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &str); + } + return str; +} + } // namespace cc diff --git a/chromium/cc/trees/layer_tree_impl.h b/chromium/cc/trees/layer_tree_impl.h index a7a3674f440..b21d9442540 100644 --- a/chromium/cc/trees/layer_tree_impl.h +++ b/chromium/cc/trees/layer_tree_impl.h @@ -199,6 +199,19 @@ class CC_EXPORT LayerTreeImpl { void SetOpacityMutated(ElementId element_id, float opacity); void SetFilterMutated(ElementId element_id, const FilterOperations& filters); + const std::unordered_map<ElementId, float, ElementIdHash>& + element_id_to_opacity_animations_for_testing() const { + return element_id_to_opacity_animations_; + } + const std::unordered_map<ElementId, gfx::Transform, ElementIdHash>& + element_id_to_transform_animations_for_testing() const { + return element_id_to_transform_animations_; + } + const std::unordered_map<ElementId, FilterOperations, ElementIdHash>& + element_id_to_filter_animations_for_testing() const { + return element_id_to_filter_animations_; + } + int source_frame_number() const { return source_frame_number_; } void set_source_frame_number(int frame_number) { source_frame_number_ = frame_number; @@ -622,6 +635,11 @@ class CC_EXPORT LayerTreeImpl { return elements_in_property_trees_; } + std::string LayerListAsJson() const; + // TODO(pdr): This should be removed because there is no longer a tree + // of layers, only a list. + std::string LayerTreeAsJson() const; + protected: float ClampPageScaleFactorToLimits(float page_scale_factor) const; void PushPageScaleFactorAndLimits(const float* page_scale_factor, diff --git a/chromium/cc/trees/layer_tree_impl_unittest.cc b/chromium/cc/trees/layer_tree_impl_unittest.cc index 1c35945d640..5c8054c72d7 100644 --- a/chromium/cc/trees/layer_tree_impl_unittest.cc +++ b/chromium/cc/trees/layer_tree_impl_unittest.cc @@ -28,7 +28,9 @@ class LayerTreeImplTestSettings : public LayerTreeSettings { class LayerTreeImplTest : public testing::Test { public: - LayerTreeImplTest() : impl_test_(LayerTreeImplTestSettings()) {} + LayerTreeImplTest( + const LayerTreeSettings& settings = LayerTreeImplTestSettings()) + : impl_test_(settings) {} FakeLayerTreeHostImpl& host_impl() const { return *impl_test_.host_impl(); } @@ -288,17 +290,22 @@ TEST_F(LayerTreeImplTest, HitTestingForUninvertibleTransform) { TEST_F(LayerTreeImplTest, HitTestingForSinglePositionedLayer) { // This layer is positioned, and hit testing should correctly know where the // layer is located. - LayerImpl* root = root_layer(); - root->SetPosition(gfx::PointF(50.f, 50.f)); - root->SetBounds(gfx::Size(100, 100)); - root->SetDrawsContent(true); + { + std::unique_ptr<LayerImpl> test_layer = + LayerImpl::Create(host_impl().active_tree(), 12345); + test_layer->test_properties()->position = gfx::PointF(50.f, 50.f); + test_layer->SetBounds(gfx::Size(100, 100)); + test_layer->SetDrawsContent(true); + root_layer()->test_properties()->AddChild(std::move(test_layer)); + } - host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); + LayerImpl* test_layer = root_layer()->test_properties()->children[0]; + host_impl().active_tree()->SetDeviceViewportSize(test_layer->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // Sanity check the scenario we just created. ASSERT_EQ(1u, GetRenderSurfaceList().size()); - ASSERT_EQ(1, GetRenderSurface(root_layer())->num_contributors()); + ASSERT_EQ(1, GetRenderSurface(test_layer)->num_contributors()); // Hit testing for a point outside the layer should return a null pointer. gfx::PointF test_point(49.f, 49.f); @@ -318,13 +325,13 @@ TEST_F(LayerTreeImplTest, HitTestingForSinglePositionedLayer) { result_layer = host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); ASSERT_TRUE(result_layer); - EXPECT_EQ(root->id(), result_layer->id()); + EXPECT_EQ(test_layer->id(), result_layer->id()); test_point = gfx::PointF(99.f, 99.f); result_layer = host_impl().active_tree()->FindLayerThatIsHitByPoint(test_point); ASSERT_TRUE(result_layer); - EXPECT_EQ(root->id(), result_layer->id()); + EXPECT_EQ(test_layer->id(), result_layer->id()); } TEST_F(LayerTreeImplTest, HitTestingForSingleRotatedLayer) { @@ -520,13 +527,13 @@ TEST_F(LayerTreeImplTest, HitTestingForSimpleClippedLayer) { LayerImpl::Create(host_impl().active_tree(), 123); // this layer is positioned, and hit testing should correctly know where the // layer is located. - clipping_layer->SetPosition(gfx::PointF(25.f, 25.f)); + clipping_layer->test_properties()->position = gfx::PointF(25.f, 25.f); clipping_layer->SetBounds(gfx::Size(50, 50)); clipping_layer->SetMasksToBounds(true); std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 456); - child->SetPosition(gfx::PointF(-50.f, -50.f)); + child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); clipping_layer->test_properties()->AddChild(std::move(child)); @@ -597,7 +604,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultiClippedRotatedLayer) { std::unique_ptr<LayerImpl> rotated_leaf = LayerImpl::Create(host_impl().active_tree(), 2468); - child->SetPosition(gfx::PointF(10.f, 10.f)); + child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(80, 80)); child->SetMasksToBounds(true); @@ -691,7 +698,7 @@ TEST_F(LayerTreeImplTest, HitTestingForNonClippingIntermediateLayer) { LayerImpl::Create(host_impl().active_tree(), 123); // this layer is positioned, and hit testing should correctly know where the // layer is located. - intermediate_layer->SetPosition(gfx::PointF(10.f, 10.f)); + intermediate_layer->test_properties()->position = gfx::PointF(10.f, 10.f); intermediate_layer->SetBounds(gfx::Size(50, 50)); // Sanity check the intermediate layer should not clip. ASSERT_FALSE(intermediate_layer->masks_to_bounds()); @@ -702,7 +709,8 @@ TEST_F(LayerTreeImplTest, HitTestingForNonClippingIntermediateLayer) { // would not be able to hit it successfully. std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 456); - child->SetPosition(gfx::PointF(60.f, 60.f)); // 70, 70 in screen space + child->test_properties()->position = + gfx::PointF(60.f, 60.f); // 70, 70 in screen spae child->SetBounds(gfx::Size(20, 20)); child->SetDrawsContent(true); intermediate_layer->test_properties()->AddChild(std::move(child)); @@ -761,18 +769,18 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayers) { std::unique_ptr<LayerImpl> grand_child1 = LayerImpl::Create(host_impl().active_tree(), 4); - child1->SetPosition(gfx::PointF(10.f, 10.f)); + child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); - child2->SetPosition(gfx::PointF(50.f, 10.f)); + child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); // Remember that grand_child is positioned with respect to its parent (i.e. // child1). In screen space, the intended position is (10, 50), with size // 100 x 50. - grand_child1->SetPosition(gfx::PointF(0.f, 40.f)); + grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); @@ -907,13 +915,13 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) { std::unique_ptr<LayerImpl> grand_child1 = LayerImpl::Create(host_impl().active_tree(), 4); - child1->SetPosition(gfx::PointF(10.f, 10.f)); + child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); child1->test_properties()->should_flatten_transform = false; child1->test_properties()->sorting_context_id = 1; - child2->SetPosition(gfx::PointF(50.f, 10.f)); + child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); gfx::Transform translate_z; translate_z.Translate3d(0, 0, 10.f); @@ -925,7 +933,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayersAtVaryingDepths) { // Remember that grand_child is positioned with respect to its parent (i.e. // child1). In screen space, the intended position is (10, 50), with size // 100 x 50. - grand_child1->SetPosition(gfx::PointF(0.f, 40.f)); + grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); grand_child1->test_properties()->should_flatten_transform = false; @@ -1007,12 +1015,12 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsClipParents) { std::unique_ptr<LayerImpl> grand_child = LayerImpl::Create(host_impl().active_tree(), 4); - child->SetPosition(gfx::PointF(10.f, 10.f)); + child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); child->SetMasksToBounds(true); - grand_child->SetPosition(gfx::PointF(0.f, 40.f)); + grand_child->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child->SetBounds(gfx::Size(100, 50)); grand_child->SetDrawsContent(true); grand_child->test_properties()->force_render_surface = true; @@ -1050,7 +1058,7 @@ TEST_F(LayerTreeImplTest, HitTestingRespectsScrollParents) { std::unique_ptr<LayerImpl> grand_child = LayerImpl::Create(host_impl().active_tree(), 4); - child->SetPosition(gfx::PointF(10.f, 10.f)); + child->test_properties()->position = gfx::PointF(10.f, 10.f); child->SetBounds(gfx::Size(1, 1)); child->SetDrawsContent(true); child->SetMasksToBounds(true); @@ -1104,12 +1112,12 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) { std::unique_ptr<LayerImpl> grand_child1 = LayerImpl::Create(host_impl().active_tree(), 4); - child1->SetPosition(gfx::PointF(10.f, 10.f)); + child1->test_properties()->position = gfx::PointF(10.f, 10.f); child1->SetBounds(gfx::Size(50, 50)); child1->SetDrawsContent(true); child1->test_properties()->force_render_surface = true; - child2->SetPosition(gfx::PointF(50.f, 10.f)); + child2->test_properties()->position = gfx::PointF(50.f, 10.f); child2->SetBounds(gfx::Size(50, 50)); child2->SetDrawsContent(true); child2->test_properties()->force_render_surface = true; @@ -1117,7 +1125,7 @@ TEST_F(LayerTreeImplTest, HitTestingForMultipleLayerLists) { // Remember that grand_child is positioned with respect to its parent (i.e. // child1). In screen space, the intended position is (10, 50), with size // 100 x 50. - grand_child1->SetPosition(gfx::PointF(0.f, 40.f)); + grand_child1->test_properties()->position = gfx::PointF(0.f, 40.f); grand_child1->SetBounds(gfx::Size(100, 50)); grand_child1->SetDrawsContent(true); grand_child1->test_properties()->force_render_surface = true; @@ -1352,18 +1360,23 @@ TEST_F(LayerTreeImplTest, // This layer is positioned, and hit testing should correctly know where the // layer is located. - LayerImpl* root = root_layer(); - root->SetPosition(gfx::PointF(50.f, 50.f)); - root->SetBounds(gfx::Size(100, 100)); - root->SetDrawsContent(true); - root->SetTouchActionRegion(touch_action_region); + { + std::unique_ptr<LayerImpl> test_layer = + LayerImpl::Create(host_impl().active_tree(), 12345); + test_layer->test_properties()->position = gfx::PointF(50.f, 50.f); + test_layer->SetBounds(gfx::Size(100, 100)); + test_layer->SetDrawsContent(true); + test_layer->SetTouchActionRegion(touch_action_region); + root_layer()->test_properties()->AddChild(std::move(test_layer)); + } - host_impl().active_tree()->SetDeviceViewportSize(root->bounds()); + LayerImpl* test_layer = root_layer()->test_properties()->children[0]; + host_impl().active_tree()->SetDeviceViewportSize(test_layer->bounds()); host_impl().UpdateNumChildrenAndDrawPropertiesForActiveTree(); // Sanity check the scenario we just created. ASSERT_EQ(1u, GetRenderSurfaceList().size()); - ASSERT_EQ(1, GetRenderSurface(root)->num_contributors()); + ASSERT_EQ(1, GetRenderSurface(test_layer)->num_contributors()); // Hit checking for a point outside the layer should return a null pointer. gfx::PointF test_point(49.f, 49.f); @@ -1389,20 +1402,20 @@ TEST_F(LayerTreeImplTest, EXPECT_FALSE(result_layer); // Hit checking for a point inside the touch event handler region should - // return the root layer. + // return the test layer. test_point = gfx::PointF(61.f, 61.f); result_layer = host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( test_point); ASSERT_TRUE(result_layer); - EXPECT_EQ(root->id(), result_layer->id()); + EXPECT_EQ(test_layer->id(), result_layer->id()); test_point = gfx::PointF(99.f, 99.f); result_layer = host_impl().active_tree()->FindLayerThatIsHitByPointInTouchHandlerRegion( test_point); ASSERT_TRUE(result_layer); - EXPECT_EQ(root->id(), result_layer->id()); + EXPECT_EQ(test_layer->id(), result_layer->id()); } TEST_F(LayerTreeImplTest, @@ -1419,7 +1432,7 @@ TEST_F(LayerTreeImplTest, touch_action_region.Union(kTouchActionNone, gfx::Rect(10, 10, 30, 30)); std::unique_ptr<LayerImpl> test_layer = LayerImpl::Create(host_impl().active_tree(), 12345); - test_layer->SetPosition(gfx::PointF(25.f, 25.f)); + test_layer->test_properties()->position = gfx::PointF(25.f, 25.f); test_layer->SetBounds(gfx::Size(50, 50)); test_layer->SetDrawsContent(true); test_layer->SetTouchActionRegion(touch_action_region); @@ -1555,7 +1568,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSimpleClippedLayer) { LayerImpl::Create(host_impl().active_tree(), 123); // this layer is positioned, and hit testing should correctly know where the // layer is located. - clipping_layer->SetPosition(gfx::PointF(25.f, 25.f)); + clipping_layer->test_properties()->position = gfx::PointF(25.f, 25.f); clipping_layer->SetBounds(gfx::Size(50, 50)); clipping_layer->SetMasksToBounds(true); @@ -1564,7 +1577,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerRegionsForSimpleClippedLayer) { std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 456); - child->SetPosition(gfx::PointF(-50.f, -50.f)); + child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); child->SetTouchActionRegion(touch_action_region); @@ -1639,7 +1652,7 @@ TEST_F(LayerTreeImplTest, LayerImpl::Create(host_impl().active_tree(), 123); // This layer is positioned, and hit testing should correctly know where the // layer is located. - clipping_layer->SetPosition(gfx::PointF(25.f, 20.f)); + clipping_layer->test_properties()->position = gfx::PointF(25.f, 20.f); clipping_layer->SetBounds(gfx::Size(50, 50)); clipping_layer->SetMasksToBounds(true); @@ -1648,7 +1661,7 @@ TEST_F(LayerTreeImplTest, std::unique_ptr<LayerImpl> child = LayerImpl::Create(host_impl().active_tree(), 456); - child->SetPosition(gfx::PointF(-50.f, -50.f)); + child->test_properties()->position = gfx::PointF(-50.f, -50.f); child->SetBounds(gfx::Size(300, 300)); child->SetDrawsContent(true); child->SetTouchActionRegion(touch_action_region); @@ -1722,7 +1735,7 @@ TEST_F(LayerTreeImplTest, HitCheckingTouchHandlerOverlappingRegions) { LayerImpl::Create(host_impl().active_tree(), 1234); // this layer is positioned, and hit testing should correctly know where the // layer is located. - notouch_layer->SetPosition(gfx::PointF(0, 25)); + notouch_layer->test_properties()->position = gfx::PointF(0, 25); notouch_layer->SetBounds(gfx::Size(50, 50)); notouch_layer->SetDrawsContent(true); root->test_properties()->AddChild(std::move(notouch_layer)); @@ -1802,7 +1815,7 @@ TEST_F(LayerTreeImplTest, HitTestingTouchHandlerRegionsForLayerThatIsNotDrawn) { // hit testing (becuase the point is inside test_layer with respect to the old // screen space transform). gfx::PointF test_point(24.f, 24.f); - test_layer->SetPosition(gfx::PointF(25.f, 25.f)); + test_layer->test_properties()->position = gfx::PointF(25.f, 25.f); gfx::Transform expected_screen_space_transform; expected_screen_space_transform.Translate(25.f, 25.f); @@ -1822,7 +1835,7 @@ TEST_F(LayerTreeImplTest, HitTestingTouchHandlerRegionsForLayerThatIsNotDrawn) { // We change the position of the test layer such that the test point is now // inside the test_layer. test_layer = root->test_properties()->children[0]; - test_layer->SetPosition(gfx::PointF(10.f, 10.f)); + test_layer->test_properties()->position = gfx::PointF(10.f, 10.f); test_layer->NoteLayerPropertyChanged(); expected_screen_space_transform.MakeIdentity(); expected_screen_space_transform.Translate(10.f, 10.f); @@ -1916,7 +1929,8 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForPartialOccludedLayers) { std::unique_ptr<LayerImpl> clipping_layer = LayerImpl::Create(host_impl().active_tree(), clip_layer_id); // The clipping layer should occlude the right selection bound. - clipping_layer->SetPosition(gfx::PointF() + clipping_offset); + clipping_layer->test_properties()->position = + gfx::PointF() + clipping_offset; clipping_layer->SetBounds(gfx::Size(50, 50)); clipping_layer->SetMasksToBounds(true); @@ -1999,7 +2013,7 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) { { std::unique_ptr<LayerImpl> sub_layer = LayerImpl::Create(host_impl().active_tree(), sub_layer_id); - sub_layer->SetPosition(gfx::PointF() + sub_layer_offset); + sub_layer->test_properties()->position = gfx::PointF() + sub_layer_offset; sub_layer->SetBounds(gfx::Size(50, 50)); sub_layer->SetDrawsContent(true); root->test_properties()->AddChild(std::move(sub_layer)); @@ -2077,7 +2091,7 @@ TEST_F(LayerTreeImplTest, SelectionBoundsForDSFEnabled) { { std::unique_ptr<LayerImpl> sub_layer = LayerImpl::Create(host_impl().active_tree(), sub_layer_id); - sub_layer->SetPosition(gfx::PointF() + sub_layer_offset); + sub_layer->test_properties()->position = gfx::PointF() + sub_layer_offset; sub_layer->SetBounds(gfx::Size(50, 50)); sub_layer->SetDrawsContent(true); root->test_properties()->AddChild(std::move(sub_layer)); @@ -2351,5 +2365,141 @@ TEST_F(LayerTreeImplTest, StubSwapPromisesAreDroppedWhenSwapFails) { } } +namespace { +class CommitToPendingTreeLayerTreeImplTestSettings : public LayerTreeSettings { + public: + CommitToPendingTreeLayerTreeImplTestSettings() { + commit_to_active_tree = false; + } +}; + +class CommitToPendingTreeLayerTreeImplTest : public LayerTreeImplTest { + public: + CommitToPendingTreeLayerTreeImplTest() + : LayerTreeImplTest(CommitToPendingTreeLayerTreeImplTestSettings()) {} +}; +} // namespace + +TEST_F(CommitToPendingTreeLayerTreeImplTest, + ElementIdToAnimationMapsTrackOnlyOnSyncTree) { + ASSERT_FALSE(host_impl().CommitToActiveTree()); + + // When we have a pending tree (e.g. commit_to_active_tree is false), the + // various ElementId to animation maps should not track anything for the + // active tree (as they are only used on the sync tree). + LayerTreeImpl* active_tree = host_impl().active_tree(); + active_tree->BuildPropertyTreesForTesting(); + LayerImpl* active_root = active_tree->root_layer_for_testing(); + + auto& active_opacity_map = + active_tree->element_id_to_opacity_animations_for_testing(); + ASSERT_EQ(active_opacity_map.size(), 0u); + active_tree->SetOpacityMutated(active_root->element_id(), 0.5f); + EXPECT_EQ(active_opacity_map.size(), 0u); + + auto& active_transform_map = + active_tree->element_id_to_transform_animations_for_testing(); + ASSERT_EQ(active_transform_map.size(), 0u); + active_tree->SetTransformMutated(active_root->element_id(), gfx::Transform()); + EXPECT_EQ(active_transform_map.size(), 0u); + + auto& active_filter_map = + active_tree->element_id_to_filter_animations_for_testing(); + ASSERT_EQ(active_filter_map.size(), 0u); + active_tree->SetFilterMutated(active_root->element_id(), FilterOperations()); + EXPECT_EQ(active_filter_map.size(), 0u); + + // The pending/recycle tree however should track them. Here we need two nodes + // (the root and a child) as we will be adding entries for both the pending + // and recycle tree cases. + host_impl().CreatePendingTree(); + LayerTreeImpl* pending_tree = host_impl().pending_tree(); + std::unique_ptr<LayerImpl> pending_root_ptr = + LayerImpl::Create(pending_tree, 2); + LayerImpl* pending_root = pending_root_ptr.get(); + pending_tree->SetRootLayerForTesting(std::move(pending_root_ptr)); + + std::unique_ptr<LayerImpl> child_ptr = + LayerImpl::Create(host_impl().pending_tree(), 3); + // The easiest way to force the child to have a TransformNode is to make it + // fixed position. Similarly a non-one opacity forces an EffectNode. + child_ptr->test_properties()->position_constraint.set_is_fixed_position(true); + child_ptr->test_properties()->opacity = 0.9f; + LayerImpl* child = child_ptr.get(); + pending_root->test_properties()->AddChild(std::move(child_ptr)); + pending_tree->BuildPropertyTreesForTesting(); + + auto& pending_opacity_map = + pending_tree->element_id_to_opacity_animations_for_testing(); + ASSERT_EQ(pending_opacity_map.size(), 0u); + pending_tree->SetOpacityMutated(pending_root->element_id(), 0.5f); + EXPECT_EQ(pending_opacity_map.size(), 1u); + + auto& pending_transform_map = + pending_tree->element_id_to_transform_animations_for_testing(); + ASSERT_EQ(pending_transform_map.size(), 0u); + pending_tree->SetTransformMutated(pending_root->element_id(), + gfx::Transform()); + EXPECT_EQ(pending_transform_map.size(), 1u); + + auto& pending_filter_map = + pending_tree->element_id_to_filter_animations_for_testing(); + ASSERT_EQ(pending_filter_map.size(), 0u); + pending_tree->SetFilterMutated(pending_root->element_id(), + FilterOperations()); + EXPECT_EQ(pending_filter_map.size(), 1u); + + // Finally, check the recycle tree - this should still track them. + host_impl().ActivateSyncTree(); + LayerTreeImpl* recycle_tree = host_impl().recycle_tree(); + ASSERT_TRUE(recycle_tree); + + auto& recycle_opacity_map = + recycle_tree->element_id_to_opacity_animations_for_testing(); + ASSERT_EQ(recycle_opacity_map.size(), 1u); + recycle_tree->SetOpacityMutated(child->element_id(), 0.5f); + EXPECT_EQ(recycle_opacity_map.size(), 2u); + + auto& recycle_transform_map = + recycle_tree->element_id_to_transform_animations_for_testing(); + ASSERT_EQ(recycle_transform_map.size(), 1u); + recycle_tree->SetTransformMutated(child->element_id(), gfx::Transform()); + EXPECT_EQ(recycle_transform_map.size(), 2u); + + auto& recycle_filter_map = + recycle_tree->element_id_to_filter_animations_for_testing(); + ASSERT_EQ(recycle_filter_map.size(), 1u); + recycle_tree->SetFilterMutated(child->element_id(), FilterOperations()); + EXPECT_EQ(recycle_filter_map.size(), 2u); +} + +TEST_F(LayerTreeImplTest, ElementIdToAnimationMapsTrackOnlyOnSyncTree) { + ASSERT_TRUE(host_impl().CommitToActiveTree()); + + // When we are commiting directly to the active tree, the various ElementId to + // animation maps should track on the active tree (as it is the sync tree, and + // they are used on the sync tree). + LayerTreeImpl* active_tree = host_impl().active_tree(); + active_tree->BuildPropertyTreesForTesting(); + LayerImpl* root = active_tree->root_layer_for_testing(); + + auto& opacity_map = + active_tree->element_id_to_opacity_animations_for_testing(); + ASSERT_EQ(opacity_map.size(), 0u); + active_tree->SetOpacityMutated(root->element_id(), 0.5f); + EXPECT_EQ(opacity_map.size(), 1u); + + auto& transform_map = + active_tree->element_id_to_transform_animations_for_testing(); + ASSERT_EQ(transform_map.size(), 0u); + active_tree->SetTransformMutated(root->element_id(), gfx::Transform()); + EXPECT_EQ(transform_map.size(), 1u); + + auto& filter_map = active_tree->element_id_to_filter_animations_for_testing(); + ASSERT_EQ(filter_map.size(), 0u); + active_tree->SetFilterMutated(root->element_id(), FilterOperations()); + EXPECT_EQ(filter_map.size(), 1u); +} + } // namespace } // namespace cc diff --git a/chromium/cc/trees/layer_tree_mutator.cc b/chromium/cc/trees/layer_tree_mutator.cc index 491eec54fa7..15d2b6aebb2 100644 --- a/chromium/cc/trees/layer_tree_mutator.cc +++ b/chromium/cc/trees/layer_tree_mutator.cc @@ -24,21 +24,22 @@ AnimationWorkletInput::AddAndUpdateState::AddAndUpdateState( AnimationWorkletInput::AddAndUpdateState::~AddAndUpdateState() = default; #if DCHECK_IS_ON() -bool AnimationWorkletInput::ValidateScope(int scope_id) const { +bool AnimationWorkletInput::ValidateId(int worklet_id) const { return std::all_of(added_and_updated_animations.cbegin(), added_and_updated_animations.cend(), - [scope_id](auto& it) { - return it.worklet_animation_id.scope_id == scope_id; + [worklet_id](auto& it) { + return it.worklet_animation_id.worklet_id == worklet_id; }) && std::all_of(updated_animations.cbegin(), updated_animations.cend(), - [scope_id](auto& it) { - return it.worklet_animation_id.scope_id == scope_id; + [worklet_id](auto& it) { + return it.worklet_animation_id.worklet_id == worklet_id; }) && std::all_of( removed_animations.cbegin(), removed_animations.cend(), - [scope_id](auto& it) { return it.scope_id == scope_id; }) && - std::all_of(peeked_animations.cbegin(), peeked_animations.cend(), - [scope_id](auto& it) { return it.scope_id == scope_id; }); + [worklet_id](auto& it) { return it.worklet_id == worklet_id; }) && + std::all_of( + peeked_animations.cbegin(), peeked_animations.cend(), + [worklet_id](auto& it) { return it.worklet_id == worklet_id; }); } #endif @@ -65,29 +66,29 @@ AnimationWorkletInput& MutatorInputState::EnsureWorkletEntry(int id) { void MutatorInputState::Add(AnimationWorkletInput::AddAndUpdateState&& state) { AnimationWorkletInput& worklet_input = - EnsureWorkletEntry(state.worklet_animation_id.scope_id); + EnsureWorkletEntry(state.worklet_animation_id.worklet_id); worklet_input.added_and_updated_animations.push_back(std::move(state)); } void MutatorInputState::Update(AnimationWorkletInput::UpdateState&& state) { AnimationWorkletInput& worklet_input = - EnsureWorkletEntry(state.worklet_animation_id.scope_id); + EnsureWorkletEntry(state.worklet_animation_id.worklet_id); worklet_input.updated_animations.push_back(std::move(state)); } void MutatorInputState::Remove(WorkletAnimationId worklet_animation_id) { AnimationWorkletInput& worklet_input = - EnsureWorkletEntry(worklet_animation_id.scope_id); + EnsureWorkletEntry(worklet_animation_id.worklet_id); worklet_input.removed_animations.push_back(worklet_animation_id); } void MutatorInputState::Peek(WorkletAnimationId worklet_animation_id) { AnimationWorkletInput& worklet_input = - EnsureWorkletEntry(worklet_animation_id.scope_id); + EnsureWorkletEntry(worklet_animation_id.worklet_id); worklet_input.peeked_animations.push_back(worklet_animation_id); } std::unique_ptr<AnimationWorkletInput> MutatorInputState::TakeWorkletState( - int scope_id) { - auto it = inputs_.find(scope_id); + int worklet_id) { + auto it = inputs_.find(worklet_id); if (it == inputs_.end()) return nullptr; diff --git a/chromium/cc/trees/layer_tree_mutator.h b/chromium/cc/trees/layer_tree_mutator.h index 42cc317740e..c3d6fbe899d 100644 --- a/chromium/cc/trees/layer_tree_mutator.h +++ b/chromium/cc/trees/layer_tree_mutator.h @@ -21,13 +21,13 @@ namespace cc { struct CC_EXPORT WorkletAnimationId { // Uniquely identifies the animation worklet with which this animation is // associated. - int scope_id; + int worklet_id; // Uniquely identifies the animation within its animation worklet. Note that // animation_id is only guaranteed to be unique per animation worklet. int animation_id; inline bool operator==(const WorkletAnimationId& rhs) const { - return (this->scope_id == rhs.scope_id) && + return (this->worklet_id == rhs.worklet_id) && (this->animation_id == rhs.animation_id); } }; @@ -68,8 +68,8 @@ struct CC_EXPORT AnimationWorkletInput { ~AnimationWorkletInput(); #if DCHECK_IS_ON() - // Verifies all animation states have the expected scope id. - bool ValidateScope(int scope_id) const; + // Verifies all animation states have the expected worklet id. + bool ValidateId(int worklet_id) const; #endif DISALLOW_COPY_AND_ASSIGN(AnimationWorkletInput); }; diff --git a/chromium/cc/trees/layer_tree_painter.h b/chromium/cc/trees/layer_tree_painter.h deleted file mode 100644 index f85707460d5..00000000000 --- a/chromium/cc/trees/layer_tree_painter.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 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_LAYER_TREE_PAINTER_H_ -#define CC_TREES_LAYER_TREE_PAINTER_H_ - -#include "cc/cc_export.h" - -namespace cc { - -class PaintWorkletInput { - public: - virtual ~PaintWorkletInput() {} -}; - -class CC_EXPORT LayerTreePainter { - public: - virtual ~LayerTreePainter() {} - - // TODO(xidachen) add a PaintWorkletPaint function. -}; - -} // namespace cc - -#endif // CC_TREES_LAYER_TREE_PAINTER_H_ diff --git a/chromium/cc/trees/layer_tree_settings.h b/chromium/cc/trees/layer_tree_settings.h index 7f074dd977e..9de6c5f5f45 100644 --- a/chromium/cc/trees/layer_tree_settings.h +++ b/chromium/cc/trees/layer_tree_settings.h @@ -145,10 +145,6 @@ class CC_EXPORT LayerTreeSettings { // Whether to use edge anti-aliasing for all layer types that supports it. bool enable_edge_anti_aliasing = true; - // Whether to request presentation time regardless if existence of - // presentation time callbacks. - bool always_request_presentation_time = false; - // Whether SetViewportSizeAndScale should update the painted scale factor or // the device scale factor. bool use_painted_device_scale_factor = false; diff --git a/chromium/cc/trees/mutator_host_client.h b/chromium/cc/trees/mutator_host_client.h index d3a3e0e7683..f070e673edb 100644 --- a/chromium/cc/trees/mutator_host_client.h +++ b/chromium/cc/trees/mutator_host_client.h @@ -44,7 +44,7 @@ class MutatorHostClient { // Allows to change IsAnimating value for a set of properties. virtual void ElementIsAnimatingChanged( - ElementId element_id, + const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state) = 0; diff --git a/chromium/cc/trees/occlusion_tracker_unittest.cc b/chromium/cc/trees/occlusion_tracker_unittest.cc index 0ba135b2fae..aca25d83853 100644 --- a/chromium/cc/trees/occlusion_tracker_unittest.cc +++ b/chromium/cc/trees/occlusion_tracker_unittest.cc @@ -287,7 +287,7 @@ class OcclusionTrackerTest : public testing::Test { const gfx::PointF& position, const gfx::Size& bounds) { layer->test_properties()->transform = transform; - layer->SetPosition(position); + layer->test_properties()->position = position; layer->SetBounds(bounds); } diff --git a/chromium/cc/trees/occlusion_unittest.cc b/chromium/cc/trees/occlusion_unittest.cc index da2f6fd0b6e..e5b31e41193 100644 --- a/chromium/cc/trees/occlusion_unittest.cc +++ b/chromium/cc/trees/occlusion_unittest.cc @@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -36,8 +37,8 @@ TEST(OcclusionTest, HasOcclusion) { #define EXPECT_OCCLUSION(occlusion, rects, ...) \ { \ bool expected[] = {__VA_ARGS__}; \ - ASSERT_EQ(arraysize(rects), arraysize(expected)); \ - for (size_t i = 0; i < arraysize(rects); ++i) \ + ASSERT_EQ(base::size(rects), base::size(expected)); \ + for (size_t i = 0; i < base::size(rects); ++i) \ EXPECT_EQ(expected[i], occlusion.IsOccluded(rects[i])) \ << "Test failed for index " << i << "."; \ } diff --git a/chromium/cc/trees/property_tree.cc b/chromium/cc/trees/property_tree.cc index b3fff07a268..15c783cba29 100644 --- a/chromium/cc/trees/property_tree.cc +++ b/chromium/cc/trees/property_tree.cc @@ -7,6 +7,7 @@ #include <set> #include <vector> +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/numerics/checked_math.h" @@ -634,8 +635,7 @@ void TransformTree::UpdateNodeAndAncestorsAreAnimatedOrInvertible( void TransformTree::SetRootTransformsAndScales( float device_scale_factor, float page_scale_factor_for_root, - const gfx::Transform& device_transform, - gfx::PointF root_position) { + const gfx::Transform& device_transform) { gfx::Vector2dF device_transform_scale_components = MathUtil::ComputeTransform2dScaleComponents(device_transform, 1.f); @@ -644,17 +644,14 @@ void TransformTree::SetRootTransformsAndScales( std::max(device_transform_scale_components.x(), device_transform_scale_components.y()); - // If DT is the device transform, DSF is the matrix scaled by (device scale - // factor * page scale factor for root), RP is the matrix translated by root's - // position, - // Let Screen Space Scale(SSS) = scale component of DT*DSF*RP, - // then the screen space transform of the root transform node is set to SSS - // and the post local transform of the contents root node is set to - // SSS^-1*DT*DSF*RP. + // Let DT be the device transform and DSF be the matrix scaled by (device + // scale factor * page scale factor for root). Let Screen Space Scale(SSS) = + // scale component of DT*DSF. The screen space transform of the root + // transform node is set to SSS and the post local transform of the contents + // root node is set to SSS^-1*DT*DSF. gfx::Transform transform = device_transform; transform.Scale(device_scale_factor * page_scale_factor_for_root, device_scale_factor * page_scale_factor_for_root); - transform.Translate(root_position.x(), root_position.y()); float fallback_value = device_scale_factor * page_scale_factor_for_root; gfx::Vector2dF screen_space_scale = MathUtil::ComputeTransform2dScaleComponents(transform, fallback_value); @@ -779,6 +776,12 @@ void EffectTree::UpdateOpacities(EffectNode* node, EffectNode* parent_node) { node->screen_space_opacity *= parent_node->screen_space_opacity; } +void EffectTree::UpdateSubtreeHidden(EffectNode* node, + EffectNode* parent_node) { + if (parent_node) + node->subtree_hidden |= parent_node->subtree_hidden; +} + void EffectTree::UpdateIsDrawn(EffectNode* node, EffectNode* parent_node) { // Nodes that have screen space opacity 0 are hidden. So they are not drawn. // Exceptions: @@ -903,6 +906,7 @@ void EffectTree::UpdateEffects(int id) { EffectNode* parent_node = parent(node); UpdateOpacities(node, parent_node); + UpdateSubtreeHidden(node, parent_node); UpdateIsDrawn(node, parent_node); UpdateEffectChanged(node, parent_node); UpdateBackfaceVisibility(node, parent_node); @@ -1840,7 +1844,7 @@ void PropertyTrees::SetOuterViewportContainerBoundsDelta( bool PropertyTrees::ElementIsAnimatingChanged( const MutatorHost* mutator_host, - ElementId element_id, + const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state, @@ -1852,6 +1856,19 @@ bool PropertyTrees::ElementIsAnimatingChanged( !mask.potentially_animating[property]) continue; + // The mask represents which properties have had their state changed. This + // can include properties for which there are no longer any animations, in + // which case there will not be an entry in the map. + // + // It is unclear whether this is desirable; it may be that we are missing + // updates to property nodes here because we no longer have the required + // ElementId to look them up. See http://crbug.com/912574 for context around + // why this code was rewritten. + auto it = element_id_map.find(static_cast<TargetProperty::Type>(property)); + if (it == element_id_map.end()) + continue; + + const ElementId element_id = it->second; switch (property) { case TargetProperty::TRANSFORM: if (TransformNode* transform_node = @@ -1996,6 +2013,16 @@ std::unique_ptr<base::trace_event::TracedValue> PropertyTrees::AsTracedValue() return value; } +std::string PropertyTrees::ToString() const { + std::string str; + base::JSONWriter::WriteWithOptions( + *AsTracedValue()->ToBaseValue(), + base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION | + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &str); + return str; +} + CombinedAnimationScale PropertyTrees::GetAnimationScales( int transform_node_id, LayerTreeImpl* layer_tree_impl) { diff --git a/chromium/cc/trees/property_tree.h b/chromium/cc/trees/property_tree.h index 89118ace357..6b9ef88fb10 100644 --- a/chromium/cc/trees/property_tree.h +++ b/chromium/cc/trees/property_tree.h @@ -189,8 +189,7 @@ class CC_EXPORT TransformTree final : public PropertyTree<TransformNode> { void SetRootTransformsAndScales(float device_scale_factor, float page_scale_factor_for_root, - const gfx::Transform& device_transform, - gfx::PointF root_position); + const gfx::Transform& device_transform); float device_transform_scale_factor() const { return device_transform_scale_factor_; } @@ -375,6 +374,7 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> { private: void UpdateOpacities(EffectNode* node, EffectNode* parent_node); + void UpdateSubtreeHidden(EffectNode* node, EffectNode* parent_node); void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node); void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node); void UpdateHasMaskingChild(EffectNode* node, EffectNode* parent_node); @@ -625,8 +625,8 @@ class CC_EXPORT PropertyTrees final { // respective property node. This will eventually allow simplifying logic in // various places that today has to map from element id to layer id, and then // from layer id to the respective property node. Completing that work is - // pending the launch of Slimming Paint v2 and reworking UI compositor logic - // to produce cc property trees and these maps. + // pending the launch of BlinkGenPropertyTrees and reworking UI compositor + // logic to produce cc property trees and these maps. base::flat_map<ElementId, int> element_id_to_effect_node_index; base::flat_map<ElementId, int> element_id_to_scroll_node_index; base::flat_map<ElementId, int> element_id_to_transform_node_index; @@ -658,7 +658,7 @@ class CC_EXPORT PropertyTrees final { // this property tree. Returns whether a draw property update is // needed. bool ElementIsAnimatingChanged(const MutatorHost* mutator_host, - ElementId element_id, + const PropertyToElementIdMap& element_id_map, ElementListType list_type, const PropertyAnimationState& mask, const PropertyAnimationState& state, @@ -683,6 +683,7 @@ class CC_EXPORT PropertyTrees final { } std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const; + std::string ToString() const; CombinedAnimationScale GetAnimationScales(int transform_node_id, LayerTreeImpl* layer_tree_impl); diff --git a/chromium/cc/trees/property_tree_builder.cc b/chromium/cc/trees/property_tree_builder.cc index 674b121c370..a8765e687e8 100644 --- a/chromium/cc/trees/property_tree_builder.cc +++ b/chromium/cc/trees/property_tree_builder.cc @@ -202,6 +202,14 @@ static const gfx::Transform& Transform(LayerImpl* layer) { return layer->test_properties()->transform; } +static const gfx::PointF& Position(Layer* layer) { + return layer->position(); +} + +static const gfx::PointF& Position(LayerImpl* layer) { + return layer->test_properties()->position; +} + // Methods to query state from the AnimationHost ---------------------- template <typename LayerType> bool OpacityIsAnimating(const MutatorHost& host, LayerType* layer) { @@ -472,8 +480,8 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded( if (!requires_node) { data_for_children->should_flatten |= ShouldFlattenTransform(layer); - gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() + - Transform(layer).To2dTranslation(); + gfx::Vector2dF local_offset = + Position(layer).OffsetFromOrigin() + Transform(layer).To2dTranslation(); gfx::Vector2dF source_to_parent; if (source_index != parent_index) { gfx::Transform to_parent; @@ -537,13 +545,15 @@ bool PropertyTreeBuilderContext<LayerType>::AddTransformNodeIfNeeded( if (is_root) { float page_scale_factor_for_root = is_page_scale_layer ? page_scale_factor_ : 1.f; + // SetRootTransformsAndScales will be incorrect if the root layer has + // non-zero position, so ensure it is zero. + DCHECK(Position(layer).IsOrigin()); transform_tree_.SetRootTransformsAndScales( transform_tree_.device_scale_factor(), page_scale_factor_for_root, - device_transform_, layer->position()); + device_transform_); } else { node->source_offset = source_offset; - node->update_post_local_transform(layer->position(), - TransformOrigin(layer)); + node->update_post_local_transform(Position(layer), TransformOrigin(layer)); } if (is_overscroll_elasticity_layer) { @@ -748,6 +758,14 @@ static inline const FilterOperations& BackdropFilters(LayerImpl* layer) { return layer->test_properties()->backdrop_filters; } +static inline const gfx::RectF& BackdropFilterBounds(Layer* layer) { + return layer->backdrop_filter_bounds(); +} + +static inline const gfx::RectF& BackdropFilterBounds(LayerImpl* layer) { + return layer->test_properties()->backdrop_filter_bounds; +} + static inline float BackdropFilterQuality(Layer* layer) { return layer->backdrop_filter_quality(); } @@ -970,7 +988,8 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( bool requires_node = is_root || has_transparency || has_potential_opacity_animation || - has_non_axis_aligned_clip || should_create_render_surface; + has_potential_filter_animation || has_non_axis_aligned_clip || + should_create_render_surface; int parent_id = data_from_ancestor.effect_tree_parent; @@ -992,6 +1011,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( node->has_copy_request = HasCopyRequest(layer); node->filters = Filters(layer); node->backdrop_filters = BackdropFilters(layer); + node->backdrop_filter_bounds = BackdropFilterBounds(layer); node->backdrop_filter_quality = BackdropFilterQuality(layer); node->filters_origin = FiltersOrigin(layer); node->trilinear_filtering = TrilinearFiltering(layer); @@ -1070,7 +1090,7 @@ bool PropertyTreeBuilderContext<LayerType>::AddEffectNodeIfNeeded( } static inline bool UserScrollableHorizontal(Layer* layer) { - return layer->user_scrollable_horizontal(); + return layer->GetUserScrollableHorizontal(); } static inline bool UserScrollableHorizontal(LayerImpl* layer) { @@ -1078,7 +1098,7 @@ static inline bool UserScrollableHorizontal(LayerImpl* layer) { } static inline bool UserScrollableVertical(Layer* layer) { - return layer->user_scrollable_vertical(); + return layer->GetUserScrollableVertical(); } static inline bool UserScrollableVertical(LayerImpl* layer) { @@ -1103,6 +1123,14 @@ static inline const base::Optional<SnapContainerData>& GetSnapContainerData( return layer->test_properties()->snap_container_data; } +static inline uint32_t MainThreadScrollingReasons(Layer* layer) { + return layer->GetMainThreadScrollingReasons(); +} + +static inline uint32_t MainThreadScrollingReasons(LayerImpl* layer) { + return layer->test_properties()->main_thread_scrolling_reasons; +} + template <typename LayerType> void SetHasTransformNode(LayerType* layer, bool val) { layer->SetHasTransformNode(val); @@ -1119,8 +1147,7 @@ void PropertyTreeBuilderContext<LayerType>::AddScrollNodeIfNeeded( bool scrollable = layer->scrollable(); bool contains_non_fast_scrollable_region = !layer->non_fast_scrollable_region().IsEmpty(); - uint32_t main_thread_scrolling_reasons = - layer->main_thread_scrolling_reasons(); + uint32_t main_thread_scrolling_reasons = MainThreadScrollingReasons(layer); bool scroll_node_uninheritable_criteria = is_root || scrollable || contains_non_fast_scrollable_region; @@ -1347,9 +1374,11 @@ void PropertyTreeBuilderContext<LayerType>::BuildPropertyTrees( clip_tree_.SetViewportClip(gfx::RectF(viewport)); float page_scale_factor_for_root = page_scale_is_root_layer ? page_scale_factor_ : 1.f; + // SetRootTransformsAndScales will be incorrect if the root layer has + // non-zero position, so ensure it is zero. + DCHECK(Position(root_layer_).IsOrigin()); transform_tree_.SetRootTransformsAndScales( - device_scale_factor, page_scale_factor_for_root, device_transform_, - root_layer_->position()); + device_scale_factor, page_scale_factor_for_root, device_transform_); return; } diff --git a/chromium/cc/trees/property_tree_unittest.cc b/chromium/cc/trees/property_tree_unittest.cc index 7935b599b40..1e0a02ae142 100644 --- a/chromium/cc/trees/property_tree_unittest.cc +++ b/chromium/cc/trees/property_tree_unittest.cc @@ -48,10 +48,10 @@ TEST(PropertyTreeTest, SetNeedsUpdate) { contents_root.id = tree.Insert(contents_root, 0); EXPECT_FALSE(tree.needs_update()); - tree.SetRootTransformsAndScales(0.6f, 1.f, gfx::Transform(), gfx::PointF()); + tree.SetRootTransformsAndScales(0.6f, 1.f, gfx::Transform()); EXPECT_TRUE(tree.needs_update()); tree.set_needs_update(false); - tree.SetRootTransformsAndScales(0.6f, 1.f, gfx::Transform(), gfx::PointF()); + tree.SetRootTransformsAndScales(0.6f, 1.f, gfx::Transform()); EXPECT_FALSE(tree.needs_update()); } diff --git a/chromium/cc/trees/proxy.h b/chromium/cc/trees/proxy.h index b9bb0318420..70d28901b25 100644 --- a/chromium/cc/trees/proxy.h +++ b/chromium/cc/trees/proxy.h @@ -27,6 +27,7 @@ class Rect; namespace cc { class LayerTreeFrameSink; class LayerTreeMutator; +class PaintWorkletLayerPainter; class RenderFrameMetadataObserver; // Abstract interface responsible for proxying commands from the main-thread @@ -72,6 +73,9 @@ class CC_EXPORT Proxy { virtual void SetMutator(std::unique_ptr<LayerTreeMutator> mutator) = 0; + virtual void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) = 0; + virtual bool SupportsImplScrolling() const = 0; virtual void UpdateBrowserControlsState(BrowserControlsState constraints, diff --git a/chromium/cc/trees/proxy_common.h b/chromium/cc/trees/proxy_common.h index 4b2e2c02dc3..e4de8308fa4 100644 --- a/chromium/cc/trees/proxy_common.h +++ b/chromium/cc/trees/proxy_common.h @@ -14,8 +14,6 @@ namespace cc { -using BeginFrameCallbackList = std::vector<base::Closure>; - struct CC_EXPORT BeginMainFrameAndCommitState { BeginMainFrameAndCommitState(); ~BeginMainFrameAndCommitState(); diff --git a/chromium/cc/trees/proxy_impl.cc b/chromium/cc/trees/proxy_impl.cc index d3fc4b7ab4b..8e3a50966cf 100644 --- a/chromium/cc/trees/proxy_impl.cc +++ b/chromium/cc/trees/proxy_impl.cc @@ -15,6 +15,7 @@ #include "cc/base/devtools_instrumentation.h" #include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/input/browser_controls_offset_manager.h" +#include "cc/paint/paint_worklet_layer_painter.h" #include "cc/scheduler/compositor_timing_history.h" #include "cc/trees/layer_tree_frame_sink.h" #include "cc/trees/layer_tree_host.h" @@ -62,7 +63,8 @@ ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr, task_runner_provider_(task_runner_provider), smoothness_priority_expiration_notifier_( task_runner_provider->ImplThreadTaskRunner(), - base::Bind(&ProxyImpl::RenewTreePriority, base::Unretained(this)), + base::BindRepeating(&ProxyImpl::RenewTreePriority, + base::Unretained(this)), base::TimeDelta::FromSecondsD( kSmoothnessTakesPriorityExpirationDelay)), rendering_stats_instrumentation_( @@ -129,6 +131,13 @@ void ProxyImpl::InitializeMutatorOnImpl( host_impl_->SetLayerTreeMutator(std::move(mutator)); } +void ProxyImpl::InitializePaintWorkletLayerPainterOnImpl( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + TRACE_EVENT0("cc", "ProxyImpl::InitializePaintWorkletLayerPainterOnImpl"); + DCHECK(IsImplThread()); + host_impl_->SetPaintWorkletLayerPainter(std::move(painter)); +} + void ProxyImpl::UpdateBrowserControlsStateOnImpl( BrowserControlsState constraints, BrowserControlsState current, @@ -436,11 +445,11 @@ void ProxyImpl::RenewTreePriority() { scroll_handler_state); } -void ProxyImpl::PostDelayedAnimationTaskOnImplThread(const base::Closure& task, +void ProxyImpl::PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) { DCHECK(IsImplThread()); - task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, - task, delay); + task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask( + FROM_HERE, std::move(task), delay); } void ProxyImpl::DidActivateSyncTree() { @@ -498,6 +507,13 @@ void ProxyImpl::DidPresentCompositorFrameOnImplThread( std::move(callbacks), feedback)); } +void ProxyImpl::DidGenerateLocalSurfaceIdAllocationOnImplThread( + const viz::LocalSurfaceIdAllocation& allocation) { + MainThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&ProxyMain::DidGenerateLocalSurfaceIdAllocation, + proxy_main_weak_ptr_, allocation)); +} + bool ProxyImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) { DCHECK(IsImplThread()); return host_impl_->WillBeginImplFrame(args); @@ -647,8 +663,8 @@ void ProxyImpl::ScheduledActionBeginMainFrameNotExpectedUntil( base::TimeTicks time) { DCHECK(IsImplThread()); MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&ProxyMain::BeginMainFrameNotExpectedUntil, - proxy_main_weak_ptr_, time)); + FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrameNotExpectedUntil, + proxy_main_weak_ptr_, time)); } DrawResult ProxyImpl::DrawInternal(bool forced_draw) { diff --git a/chromium/cc/trees/proxy_impl.h b/chromium/cc/trees/proxy_impl.h index 038d3752605..5f1ff436eb1 100644 --- a/chromium/cc/trees/proxy_impl.h +++ b/chromium/cc/trees/proxy_impl.h @@ -40,6 +40,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, LayerTreeFrameSink* layer_tree_frame_sink, base::WeakPtr<ProxyMain> proxy_main_frame_sink_bound_weak_ptr); void InitializeMutatorOnImpl(std::unique_ptr<LayerTreeMutator> mutator); + void InitializePaintWorkletLayerPainterOnImpl( + std::unique_ptr<PaintWorkletLayerPainter> painter); void SetInputThrottledUntilCommitOnImpl(bool is_throttled); void SetDeferMainFrameUpdateOnImpl(bool defer_main_frame_update) const; void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect); @@ -92,7 +94,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, std::unique_ptr<MutatorEvents> events) override; bool IsInsideDraw() override; void RenewTreePriority() override; - void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, + void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) override; void DidActivateSyncTree() override; void WillPrepareTiles() override; @@ -106,6 +108,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient, uint32_t frame_token, std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback) override; + void DidGenerateLocalSurfaceIdAllocationOnImplThread( + const viz::LocalSurfaceIdAllocation& allocation) 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 9bee3eff2c2..85bf14a0357 100644 --- a/chromium/cc/trees/proxy_main.cc +++ b/chromium/cc/trees/proxy_main.cc @@ -12,6 +12,7 @@ #include "cc/base/completion_event.h" #include "cc/base/devtools_instrumentation.h" #include "cc/benchmarks/benchmark_instrumentation.h" +#include "cc/paint/paint_worklet_layer_painter.h" #include "cc/resources/ui_resource_manager.h" #include "cc/trees/latency_info_swap_promise.h" #include "cc/trees/layer_tree_frame_sink.h" @@ -347,6 +348,11 @@ void ProxyMain::DidPresentCompositorFrame( feedback); } +void ProxyMain::DidGenerateLocalSurfaceIdAllocation( + const viz::LocalSurfaceIdAllocation& allocation) { + layer_tree_host_->DidGenerateLocalSurfaceIdAllocation(allocation); +} + bool ProxyMain::IsStarted() const { DCHECK(IsMainThread()); return started_; @@ -518,6 +524,16 @@ void ProxyMain::SetMutator(std::unique_ptr<LayerTreeMutator> mutator) { base::Passed(std::move(mutator)))); } +void ProxyMain::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + TRACE_EVENT0("cc", "ThreadProxy::SetPaintWorkletLayerPainter"); + ImplThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&ProxyImpl::InitializePaintWorkletLayerPainterOnImpl, + base::Unretained(proxy_impl_.get()), + base::Passed(std::move(painter)))); +} + bool ProxyMain::SupportsImplScrolling() const { return true; } diff --git a/chromium/cc/trees/proxy_main.h b/chromium/cc/trees/proxy_main.h index 0005a6e1bfe..7fbff9efc35 100644 --- a/chromium/cc/trees/proxy_main.h +++ b/chromium/cc/trees/proxy_main.h @@ -11,6 +11,10 @@ #include "cc/trees/proxy.h" #include "cc/trees/proxy_common.h" +namespace viz { +class LocalSurfaceIdAllocation; +} + namespace cc { class MutatorEvents; @@ -18,6 +22,7 @@ class CompletionEvent; class LayerTreeFrameSink; class LayerTreeHost; class LayerTreeMutator; +class PaintWorkletLayerPainter; class ProxyImpl; class RenderFrameMetadataObserver; @@ -56,6 +61,8 @@ class CC_EXPORT ProxyMain : public Proxy { uint32_t frame_token, std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback); + void DidGenerateLocalSurfaceIdAllocation( + const viz::LocalSurfaceIdAllocation& allocation); CommitPipelineStage max_requested_pipeline_stage() const { return max_requested_pipeline_stage_; @@ -87,6 +94,8 @@ class CC_EXPORT ProxyMain : public Proxy { void Stop() override; bool SupportsImplScrolling() const override; void SetMutator(std::unique_ptr<LayerTreeMutator> mutator) override; + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) override; bool MainFrameWillHappenForTesting() override; void ReleaseLayerTreeFrameSink() override; void UpdateBrowserControlsState(BrowserControlsState constraints, diff --git a/chromium/cc/trees/single_thread_proxy.cc b/chromium/cc/trees/single_thread_proxy.cc index 2e3b7c613c1..b15148dd561 100644 --- a/chromium/cc/trees/single_thread_proxy.cc +++ b/chromium/cc/trees/single_thread_proxy.cc @@ -10,6 +10,7 @@ #include "cc/base/devtools_instrumentation.h" #include "cc/benchmarks/benchmark_instrumentation.h" #include "cc/input/browser_controls_offset_manager.h" +#include "cc/paint/paint_worklet_layer_painter.h" #include "cc/resources/ui_resource_manager.h" #include "cc/scheduler/commit_earlyout_reason.h" #include "cc/scheduler/compositor_timing_history.h" @@ -164,7 +165,6 @@ void SingleThreadProxy::SetLayerTreeFrameSink( void SingleThreadProxy::SetNeedsAnimate() { TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate"); DCHECK(task_runner_provider_->IsMainThread()); - single_thread_client_->RequestScheduleAnimation(); if (animate_requested_) return; animate_requested_ = true; @@ -316,6 +316,11 @@ void SingleThreadProxy::SetMutator(std::unique_ptr<LayerTreeMutator> mutator) { host_impl_->SetLayerTreeMutator(std::move(mutator)); } +void SingleThreadProxy::SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) { + NOTREACHED(); +} + void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) { TRACE_EVENT1("cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw); @@ -453,8 +458,9 @@ void SingleThreadProxy::DidReceiveCompositorFrameAckOnImplThread() { // TextureLayer) is PostTasked and we want to make sure ack is received // after resources are returned. task_runner_provider_->MainThreadTaskRunner()->PostTask( - FROM_HERE, base::Bind(&SingleThreadProxy::DidReceiveCompositorFrameAck, - frame_sink_bound_weak_ptr_)); + FROM_HERE, + base::BindOnce(&SingleThreadProxy::DidReceiveCompositorFrameAck, + frame_sink_bound_weak_ptr_)); } } @@ -493,6 +499,11 @@ void SingleThreadProxy::DidPresentCompositorFrameOnImplThread( feedback); } +void SingleThreadProxy::DidGenerateLocalSurfaceIdAllocationOnImplThread( + const viz::LocalSurfaceIdAllocation& allocation) { + layer_tree_host_->DidGenerateLocalSurfaceIdAllocation(allocation); +} + void SingleThreadProxy::RequestBeginMainFrameNotExpected(bool new_state) { if (scheduler_on_impl_thread_) { scheduler_on_impl_thread_->SetMainThreadWantsBeginMainFrameNotExpected( @@ -589,8 +600,8 @@ void SingleThreadProxy::ScheduleRequestNewLayerTreeFrameSink() { if (layer_tree_frame_sink_creation_callback_.IsCancelled() && !layer_tree_frame_sink_creation_requested_) { layer_tree_frame_sink_creation_callback_.Reset( - base::Bind(&SingleThreadProxy::RequestNewLayerTreeFrameSink, - weak_factory_.GetWeakPtr())); + base::BindOnce(&SingleThreadProxy::RequestNewLayerTreeFrameSink, + weak_factory_.GetWeakPtr())); task_runner_provider_->MainThreadTaskRunner()->PostTask( FROM_HERE, layer_tree_frame_sink_creation_callback_.callback()); } diff --git a/chromium/cc/trees/single_thread_proxy.h b/chromium/cc/trees/single_thread_proxy.h index ca922056575..565af3d2925 100644 --- a/chromium/cc/trees/single_thread_proxy.h +++ b/chromium/cc/trees/single_thread_proxy.h @@ -56,6 +56,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, void Start() override; void Stop() override; void SetMutator(std::unique_ptr<LayerTreeMutator> mutator) override; + void SetPaintWorkletLayerPainter( + std::unique_ptr<PaintWorkletLayerPainter> painter) override; bool SupportsImplScrolling() const override; bool MainFrameWillHappenForTesting() override; void SetURLForUkm(const GURL& url) override { @@ -111,7 +113,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, std::unique_ptr<MutatorEvents> events) override; bool IsInsideDraw() override; void RenewTreePriority() override {} - void PostDelayedAnimationTaskOnImplThread(const base::Closure& task, + void PostDelayedAnimationTaskOnImplThread(base::OnceClosure task, base::TimeDelta delay) override {} void DidActivateSyncTree() override; void WillPrepareTiles() override; @@ -126,6 +128,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, uint32_t frame_token, std::vector<LayerTreeHost::PresentationTimeCallback> callbacks, const gfx::PresentationFeedback& feedback) override; + void DidGenerateLocalSurfaceIdAllocationOnImplThread( + const viz::LocalSurfaceIdAllocation& allocation) override; void RequestNewLayerTreeFrameSink(); @@ -188,7 +192,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy, bool layer_tree_frame_sink_lost_; // This is the callback for the scheduled RequestNewLayerTreeFrameSink. - base::CancelableClosure layer_tree_frame_sink_creation_callback_; + base::CancelableOnceClosure layer_tree_frame_sink_creation_callback_; base::WeakPtr<SingleThreadProxy> frame_sink_bound_weak_ptr_; diff --git a/chromium/cc/trees/target_property.h b/chromium/cc/trees/target_property.h index 93fa839bd82..f28649ce203 100644 --- a/chromium/cc/trees/target_property.h +++ b/chromium/cc/trees/target_property.h @@ -7,6 +7,8 @@ #include <bitset> +#include "base/containers/flat_map.h" + namespace cc { static constexpr size_t kMaxTargetPropertyIndex = 32u; @@ -32,6 +34,13 @@ enum Type { // A set of target properties. using TargetProperties = std::bitset<kMaxTargetPropertyIndex>; +// A map of target property to ElementId. +// flat_map was chosen because there are expected to be relatively few entries +// in the map. For low number of entries, flat_map is known to perform better +// than other map implementations. +struct ElementId; +using PropertyToElementIdMap = base::flat_map<TargetProperty::Type, ElementId>; + } // namespace cc #endif // CC_TREES_TARGET_PROPERTY_H_ diff --git a/chromium/cc/trees/tree_synchronizer.cc b/chromium/cc/trees/tree_synchronizer.cc index c31289f46cf..80b912a1b8d 100644 --- a/chromium/cc/trees/tree_synchronizer.cc +++ b/chromium/cc/trees/tree_synchronizer.cc @@ -9,6 +9,8 @@ #include <set> #include "base/containers/flat_set.h" +#include "base/debug/crash_logging.h" +#include "base/debug/dump_without_crashing.h" #include "base/logging.h" #include "base/stl_util.h" #include "base/trace_event/trace_event.h" @@ -154,6 +156,50 @@ void TreeSynchronizer::SynchronizeTrees(LayerTreeImpl* pending_tree, template <typename Iterator> static void PushLayerPropertiesInternal(Iterator source_layers_begin, Iterator source_layers_end, + LayerTreeHost* host_tree, + LayerTreeImpl* target_impl_tree) { + for (Iterator it = source_layers_begin; it != source_layers_end; ++it) { + auto* source_layer = *it; + LayerImpl* target_layer = target_impl_tree->LayerById(source_layer->id()); + DCHECK(target_layer); + // TODO(enne): http://crbug.com/918126 debugging + if (!target_layer) { + bool host_set_on_source = source_layer->layer_tree_host() == host_tree; + + bool source_found_by_iterator = false; + for (auto it = host_tree->begin(); it != host_tree->end(); ++it) { + if (*it == source_layer) { + source_found_by_iterator = true; + break; + } + } + + bool root_layer_valid = !!host_tree->root_layer(); + bool found_root = false; + Layer* layer = source_layer; + while (layer) { + if (layer == host_tree->root_layer()) { + found_root = true; + break; + } + layer = layer->parent(); + } + + auto str = base::StringPrintf( + "hs: %d, sf: %d, rlv: %d, fr: %d", host_set_on_source, + source_found_by_iterator, root_layer_valid, found_root); + static auto* crash_key = base::debug::AllocateCrashKeyString( + "cc_null_layer_sync", base::debug::CrashKeySize::Size32); + base::debug::SetCrashKeyString(crash_key, str); + base::debug::DumpWithoutCrashing(); + } + source_layer->PushPropertiesTo(target_layer); + } +} + +template <typename Iterator> +static void PushLayerPropertiesInternal(Iterator source_layers_begin, + Iterator source_layers_end, LayerTreeImpl* target_impl_tree) { for (Iterator it = source_layers_begin; it != source_layers_end; ++it) { auto* source_layer = *it; @@ -183,7 +229,8 @@ void TreeSynchronizer::PushLayerProperties(LayerTreeHost* host_tree, auto layers = host_tree->LayersThatShouldPushProperties(); TRACE_EVENT1("cc", "TreeSynchronizer::PushLayerPropertiesTo.Main", "layer_count", layers.size()); - PushLayerPropertiesInternal(layers.begin(), layers.end(), impl_tree); + PushLayerPropertiesInternal(layers.begin(), layers.end(), host_tree, + impl_tree); // When using layer lists, we may not have layers for all property tree // node ids and need to synchronize the registered id list. if (host_tree->IsUsingLayerLists()) diff --git a/chromium/cc/trees/tree_synchronizer_unittest.cc b/chromium/cc/trees/tree_synchronizer_unittest.cc index 547dccae6ef..99b8819cb7c 100644 --- a/chromium/cc/trees/tree_synchronizer_unittest.cc +++ b/chromium/cc/trees/tree_synchronizer_unittest.cc @@ -380,8 +380,8 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndProperties) { // Pick some random properties to set. The values are not important, we're // just testing that at least some properties are making it through. - gfx::PointF root_position = gfx::PointF(2.3f, 7.4f); - layer_tree_root->SetPosition(root_position); + gfx::Size root_bounds = gfx::Size(10, 12); + layer_tree_root->SetBounds(root_bounds); gfx::Size second_child_bounds = gfx::Size(25, 53); layer_tree_root->children()[1]->SetBounds(second_child_bounds); @@ -400,9 +400,7 @@ TEST_F(TreeSynchronizerTest, SyncSimpleTreeAndProperties) { // Check that the property values we set on the Layer tree are reflected in // the LayerImpl tree. - gfx::PointF root_layer_impl_position = layer_impl_tree_root->position(); - EXPECT_EQ(root_position.x(), root_layer_impl_position.x()); - EXPECT_EQ(root_position.y(), root_layer_impl_position.y()); + EXPECT_EQ(root_bounds, layer_impl_tree_root->bounds()); gfx::Size second_layer_impl_child_bounds = layer_impl_tree_root->layer_tree_impl() |