[BGPT] Let cc initialize animation states in property nodes
In this way, blink::PropertyTreeManager no longer needs to care about
the animation states. Now we initialize and change the states from a
single source to avoid duplicate code and inconsistency.
Bug: 935770
Change-Id: I7f98d66677f557213fd4559895e9c2069de196e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1513922
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#640892}diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 33c4bc6..5b54d9b 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -129,6 +129,11 @@
SetNeedsPushProperties();
}
+void AnimationHost::InitClientAnimationState() {
+ for (auto map_entry : element_to_animations_map_)
+ map_entry.second->InitClientAnimationState();
+}
+
void AnimationHost::RegisterElement(ElementId element_id,
ElementListType list_type) {
scoped_refptr<ElementAnimations> element_animations =
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index 7473db7e..9927f36 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -90,6 +90,8 @@
bool supports_impl_scrolling) const override;
void ClearMutators() override;
+ void InitClientAnimationState() override;
+
void RegisterElement(ElementId element_id,
ElementListType list_type) override;
void UnregisterElement(ElementId element_id,
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc
index 4926dbce..66aaa8c2 100644
--- a/cc/animation/element_animations.cc
+++ b/cc/animation/element_animations.cc
@@ -312,6 +312,14 @@
keyframe_model);
}
+void ElementAnimations::InitClientAnimationState() {
+ // Clear current states so that UpdateClientAnimationState() will send all
+ // (instead of only changed) recalculated current states to the client.
+ pending_state_.Clear();
+ active_state_.Clear();
+ UpdateClientAnimationState();
+}
+
void ElementAnimations::UpdateClientAnimationState() {
if (!element_id())
return;
diff --git a/cc/animation/element_animations.h b/cc/animation/element_animations.h
index 7e8f124..5f0904d 100644
--- a/cc/animation/element_animations.h
+++ b/cc/animation/element_animations.h
@@ -124,6 +124,13 @@
bool ScrollOffsetAnimationWasInterrupted() const;
void SetNeedsPushProperties();
+
+ // Initializes client animation state by calling client's
+ // ElementIsAnimatingChanged() method with the current animation state.
+ void InitClientAnimationState();
+ // Updates client animation state by calling client's
+ // ElementIsAnimatingChanged() method with the state containing properties
+ // that have changed since the last update.
void UpdateClientAnimationState();
void NotifyClientFloatAnimated(float opacity,
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h
index 03aa3fd..21551b9 100644
--- a/cc/trees/mutator_host.h
+++ b/cc/trees/mutator_host.h
@@ -42,6 +42,8 @@
virtual void ClearMutators() = 0;
+ virtual void InitClientAnimationState() = 0;
+
virtual void RegisterElement(ElementId element_id,
ElementListType list_type) = 0;
virtual void UnregisterElement(ElementId element_id,
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.h b/third_party/blink/renderer/core/animation/compositor_animations.h
index a0cf3f0..12546f27 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations.h
+++ b/third_party/blink/renderer/core/animation/compositor_animations.h
@@ -148,18 +148,6 @@
static FailureCode CheckCanStartElementOnCompositor(const Element&);
friend class AnimationCompositorAnimationsTest;
- FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
- CanStartElementOnCompositorTransformCAP);
- FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
- CanStartElementOnCompositorEffectCAP);
- FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
- CanStartElementOnCompositorEffect);
- FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
- CannotStartElementOnCompositorEffectSVG);
- FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
- CancelIncompatibleCompositorAnimations);
- FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
- NonAnimatedTransformPropertyChangeGetsUpdated);
};
} // namespace blink
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 88255ce..5b5aa8d 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -38,6 +38,7 @@
#include "base/memory/scoped_refptr.h"
#include "cc/animation/animation_host.h"
#include "cc/layers/picture_layer.h"
+#include "cc/trees/transform_node.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/animation/animatable/animatable_double.h"
@@ -67,7 +68,7 @@
#include "third_party/blink/renderer/platform/geometry/float_box.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/transforms/transform_operations.h"
@@ -78,7 +79,8 @@
using namespace css_test_helpers;
-class AnimationCompositorAnimationsTest : public RenderingTest {
+class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
+ public RenderingTest {
protected:
scoped_refptr<TimingFunction> linear_timing_function_;
scoped_refptr<TimingFunction> cubic_ease_timing_function_;
@@ -169,6 +171,10 @@
.Ok();
}
+ bool CheckCanStartElementOnCompositor(const Element& element) {
+ return CompositorAnimations::CheckCanStartElementOnCompositor(element).Ok();
+ }
+
void GetAnimationOnCompositor(
Timing& timing,
StringKeyframeEffectModel& effect,
@@ -506,7 +512,9 @@
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
-TEST_F(AnimationCompositorAnimationsTest,
+INSTANTIATE_PAINT_TEST_SUITE_P(AnimationCompositorAnimationsTest);
+
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorKeyframeMultipleCSSProperties) {
StringKeyframe* keyframe_good_multiple =
CreateDefaultKeyframe(CSSPropertyOpacity, EffectModel::kCompositeReplace);
@@ -524,7 +532,7 @@
keyframe_bad_multiple_id));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
IsNotCandidateForCompositorAnimationTransformDependsOnBoxSize) {
// Absolute transforms can be animated on the compositor.
String transform = "translateX(2px) translateY(2px)";
@@ -547,7 +555,7 @@
DuplicateSingleKeyframeAndTestIsCandidateOnResult(bad_keyframe2));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorKeyframeEffectModel) {
StringKeyframeVector frames_same;
frames_same.push_back(CreateDefaultKeyframe(
@@ -576,7 +584,7 @@
timing_, *StringKeyframeEffectModel::Create(frames_mixed_properties)));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorCustomCssProperty) {
ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
RegisterProperty(GetDocument(), "--foo", "<number>", "0", false);
@@ -605,7 +613,7 @@
EXPECT_FALSE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
ConvertTimingForCompositorStartDelay) {
timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(20);
@@ -618,13 +626,13 @@
EXPECT_DOUBLE_EQ(2.0, compositor_timing_.scaled_time_offset);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
ConvertTimingForCompositorIterationStart) {
timing_.iteration_start = 2.2;
EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
ConvertTimingForCompositorIterationCount) {
timing_.iteration_count = 5.0;
EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
@@ -646,7 +654,7 @@
EXPECT_EQ(-1, compositor_timing_.adjusted_iteration_count);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
ConvertTimingForCompositorIterationsAndStartDelay) {
timing_.iteration_count = 4.0;
timing_.iteration_duration = AnimationTimeDelta::FromSecondsD(5);
@@ -665,7 +673,7 @@
EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
}
-TEST_F(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirection) {
+TEST_P(AnimationCompositorAnimationsTest, ConvertTimingForCompositorDirection) {
timing_.direction = Timing::PlaybackDirection::NORMAL;
EXPECT_TRUE(ConvertTimingForCompositor(timing_, compositor_timing_));
EXPECT_EQ(compositor_timing_.direction, Timing::PlaybackDirection::NORMAL);
@@ -685,7 +693,7 @@
EXPECT_EQ(compositor_timing_.direction, Timing::PlaybackDirection::REVERSE);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
ConvertTimingForCompositorDirectionIterationsAndStartDelay) {
timing_.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
timing_.iteration_count = 4.0;
@@ -728,7 +736,7 @@
Timing::PlaybackDirection::ALTERNATE_REVERSE);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionLinear) {
timing_.timing_function = linear_timing_function_;
EXPECT_TRUE(
@@ -737,7 +745,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionCubic) {
timing_.timing_function = cubic_ease_timing_function_;
EXPECT_TRUE(
@@ -752,7 +760,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionSteps) {
timing_.timing_function = step_timing_function_;
EXPECT_TRUE(
@@ -761,7 +769,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionFrames) {
timing_.timing_function = frames_timing_function_;
EXPECT_TRUE(
@@ -770,7 +778,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionChainedLinear) {
EXPECT_TRUE(
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect2_));
@@ -778,7 +786,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorNonLinearTimingFunctionOnFirstOrLastFrame) {
keyframe_vector2_->at(0)->SetEasing(cubic_ease_timing_function_.get());
keyframe_animation_effect2_ =
@@ -801,7 +809,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorFailuresProperties) {
// An effect with no keyframes has no Properties, so can not be composited.
StringKeyframeVector empty_keyframe_vector;
@@ -809,9 +817,14 @@
timing_, *StringKeyframeEffectModel::Create(empty_keyframe_vector)));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartElementOnCompositorEffectOpacity) {
- ScopedBlinkGenPropertyTreesForTest blink_gen_property_trees(true);
+ // This test doesn't apply for pre-BlinkGenPropertyTrees due to the element id
+ // namespaces.
+ if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
+ !RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get());
@@ -898,7 +911,7 @@
LayoutObjectProxy::Dispose(new_layout_object);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartElementOnCompositorEffectInvalid) {
base::Optional<CompositorElementIdSet> none;
auto style = ComputedStyle::Create();
@@ -987,7 +1000,7 @@
LayoutObjectProxy::Dispose(layout_object);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartElementOnCompositorEffectFilter) {
base::Optional<CompositorElementIdSet> none;
@@ -1052,9 +1065,14 @@
LayoutObjectProxy::Dispose(layout_object);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartElementOnCompositorEffectTransform) {
- ScopedBlinkGenPropertyTreesForTest blink_gen_property_trees(true);
+ // This test doesn't apply for pre-BlinkGenPropertyTrees due to the element id
+ // namespaces.
+ if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() &&
+ !RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get());
@@ -1128,7 +1146,7 @@
LayoutObjectProxy::Dispose(layout_object);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionChainedCubicMatchingOffsets) {
keyframe_vector2_->at(0)->SetEasing(cubic_ease_timing_function_.get());
keyframe_animation_effect2_ =
@@ -1152,7 +1170,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionMixedGood) {
keyframe_vector5_->at(0)->SetEasing(linear_timing_function_.get());
keyframe_vector5_->at(1)->SetEasing(cubic_ease_timing_function_.get());
@@ -1164,7 +1182,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CanStartEffectOnCompositorTimingFunctionWithStepOrFrameOkay) {
keyframe_vector2_->at(0)->SetEasing(step_timing_function_.get());
keyframe_animation_effect2_ =
@@ -1206,7 +1224,7 @@
CanStartEffectOnCompositor(timing_, *keyframe_animation_effect5_));
}
-TEST_F(AnimationCompositorAnimationsTest, CanStartEffectOnCompositorBasic) {
+TEST_P(AnimationCompositorAnimationsTest, CanStartEffectOnCompositorBasic) {
StringKeyframeVector basic_frames_vector;
basic_frames_vector.push_back(CreateDefaultKeyframe(
CSSPropertyOpacity, EffectModel::kCompositeReplace, 0.0));
@@ -1269,7 +1287,7 @@
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
-TEST_F(AnimationCompositorAnimationsTest, CreateSimpleOpacityAnimation) {
+TEST_P(AnimationCompositorAnimationsTest, CreateSimpleOpacityAnimation) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
CreateReplaceOpKeyframe(CSSPropertyOpacity, "0.2", 0),
@@ -1303,7 +1321,7 @@
keyframes[1]->GetTimingFunctionForTesting()->GetType());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateSimpleOpacityAnimationDuration) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1325,7 +1343,7 @@
EXPECT_EQ(kDuration, keyframes[1]->Time() * kDuration);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateMultipleKeyframeOpacityAnimationLinear) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1375,7 +1393,7 @@
keyframes[3]->GetTimingFunctionForTesting()->GetType());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateSimpleOpacityAnimationStartDelay) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1408,7 +1426,7 @@
EXPECT_EQ(0.5f, keyframes[1]->Value());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateMultipleKeyframeOpacityAnimationChained) {
// KeyframeEffect to convert
StringKeyframeVector frames;
@@ -1467,7 +1485,7 @@
keyframes[3]->GetTimingFunctionForTesting()->GetType());
}
-TEST_F(AnimationCompositorAnimationsTest, CreateReversedOpacityAnimation) {
+TEST_P(AnimationCompositorAnimationsTest, CreateReversedOpacityAnimation) {
scoped_refptr<TimingFunction> cubic_easy_flip_timing_function =
CubicBezierTimingFunction::Create(0.0, 0.0, 0.0, 1.0);
@@ -1528,7 +1546,7 @@
keyframes[3]->GetTimingFunctionForTesting()->GetType());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateReversedOpacityAnimationNegativeStartDelay) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1560,7 +1578,7 @@
ASSERT_EQ(2UL, keyframes.size());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateSimpleOpacityAnimationFillModeNone) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1575,7 +1593,7 @@
keyframe_model->GetFillMode());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateSimpleOpacityAnimationFillModeAuto) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1597,7 +1615,7 @@
keyframe_model->GetFillMode());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateSimpleOpacityAnimationWithTimingFunction) {
// KeyframeEffect to convert
StringKeyframeEffectModel* effect = CreateKeyframeEffectModel(
@@ -1640,7 +1658,7 @@
keyframes[1]->GetTimingFunctionForTesting()->GetType());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CreateSimpleCustomFloatPropertyAnimation) {
ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true);
@@ -1674,7 +1692,7 @@
keyframes[1]->GetTimingFunctionForTesting()->GetType());
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CancelIncompatibleCompositorAnimations) {
Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
base::Optional<CompositorElementIdSet> none;
@@ -1760,15 +1778,16 @@
}
} // namespace
+TEST_P(AnimationCompositorAnimationsTest,
+ CanStartElementOnCompositorTransformBasedOnPaintProperties) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
-TEST_F(AnimationCompositorAnimationsTest,
- CanStartElementOnCompositorTransformCAP) {
Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get());
layout_object->EnsureIdForTestingProxy();
element->SetLayoutObject(layout_object);
- ScopedCompositeAfterPaintForTest enable_cap(true);
auto& properties = layout_object->GetMutableForPainting()
.FirstFragment()
.EnsurePaintProperties();
@@ -1777,31 +1796,30 @@
// animation.
UpdateDummyTransformNode(properties,
CompositingReason::kActiveTransformAnimation);
- EXPECT_TRUE(
- CompositorAnimations::CheckCanStartElementOnCompositor(*element).Ok());
+ EXPECT_TRUE(CheckCanStartElementOnCompositor(*element));
// Setting to CompositingReasonNone should produce false.
UpdateDummyTransformNode(properties, CompositingReason::kNone);
- EXPECT_FALSE(
- CompositorAnimations::CheckCanStartElementOnCompositor(*element).Ok());
+ EXPECT_FALSE(CheckCanStartElementOnCompositor(*element));
// Clearing the transform node entirely should also produce false.
properties.ClearTransform();
- EXPECT_FALSE(
- CompositorAnimations::CheckCanStartElementOnCompositor(*element).Ok());
+ EXPECT_FALSE(CheckCanStartElementOnCompositor(*element));
element->SetLayoutObject(nullptr);
LayoutObjectProxy::Dispose(layout_object);
}
-TEST_F(AnimationCompositorAnimationsTest,
- CanStartElementOnCompositorEffectCAP) {
+TEST_P(AnimationCompositorAnimationsTest,
+ CanStartElementOnCompositorEffectBasedOnPaintProperties) {
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
Persistent<Element> element = GetDocument().CreateElementForBinding("shared");
LayoutObjectProxy* layout_object = LayoutObjectProxy::Create(element.Get());
layout_object->EnsureIdForTestingProxy();
element->SetLayoutObject(layout_object);
- ScopedCompositeAfterPaintForTest enable_cap(true);
auto& properties = layout_object->GetMutableForPainting()
.FirstFragment()
.EnsurePaintProperties();
@@ -1810,24 +1828,21 @@
// animation.
UpdateDummyEffectNode(properties,
CompositingReason::kActiveTransformAnimation);
- EXPECT_TRUE(
- CompositorAnimations::CheckCanStartElementOnCompositor(*element).Ok());
+ EXPECT_TRUE(CheckCanStartElementOnCompositor(*element));
// Setting to CompositingReasonNone should produce false.
UpdateDummyEffectNode(properties, CompositingReason::kNone);
- EXPECT_FALSE(
- CompositorAnimations::CheckCanStartElementOnCompositor(*element).Ok());
+ EXPECT_FALSE(CheckCanStartElementOnCompositor(*element));
// Clearing the effect node entirely should also produce false.
properties.ClearEffect();
- EXPECT_FALSE(
- CompositorAnimations::CheckCanStartElementOnCompositor(*element).Ok());
+ EXPECT_FALSE(CheckCanStartElementOnCompositor(*element));
element->SetLayoutObject(nullptr);
LayoutObjectProxy::Dispose(layout_object);
}
-TEST_F(AnimationCompositorAnimationsTest, TrackRafAnimation) {
+TEST_P(AnimationCompositorAnimationsTest, TrackRafAnimation) {
LoadTestData("raf-countdown.html");
cc::AnimationHost* host =
@@ -1856,7 +1871,7 @@
EXPECT_FALSE(host->NextFrameHasPendingRAF());
}
-TEST_F(AnimationCompositorAnimationsTest, TrackRafAnimationTimeout) {
+TEST_P(AnimationCompositorAnimationsTest, TrackRafAnimationTimeout) {
LoadTestData("raf-timeout.html");
cc::AnimationHost* host =
@@ -1870,7 +1885,7 @@
EXPECT_FALSE(host->NextFrameHasPendingRAF());
}
-TEST_F(AnimationCompositorAnimationsTest, TrackRafAnimationNoneRegistered) {
+TEST_P(AnimationCompositorAnimationsTest, TrackRafAnimationNoneRegistered) {
SetBodyInnerHTML("<div id='box'></div>");
// Run a full frame after loading the test data so that scripted animations
@@ -1891,25 +1906,50 @@
EXPECT_FALSE(host->NextFrameHasPendingRAF());
}
-TEST_F(AnimationCompositorAnimationsTest, CanStartElementOnCompositorEffect) {
+TEST_P(AnimationCompositorAnimationsTest, CompositedTransformAnimation) {
+ // TODO(wangxianzhu): Fix this test for CompositeAfterPaint.
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
LoadTestData("transform-animation.html");
Document* document = GetFrame()->GetDocument();
Element* target = document->getElementById("target");
const ObjectPaintProperties* properties =
target->GetLayoutObject()->FirstFragment().PaintProperties();
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_TRUE(properties->Transform()->HasDirectCompositingReasons());
- CompositorAnimations::FailureCode code =
- CompositorAnimations::CheckCanStartElementOnCompositor(*target);
- EXPECT_EQ(code, CompositorAnimations::FailureCode::None());
+ ASSERT_NE(nullptr, properties);
+ const auto* transform = properties->Transform();
+ ASSERT_NE(nullptr, transform);
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
+ RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_TRUE(transform->HasDirectCompositingReasons());
+ EXPECT_TRUE(transform->HasActiveTransformAnimation());
+ // Make sure the animation state is initialized in paint properties.
+ auto* property_trees =
+ document->View()->RootCcLayer()->layer_tree_host()->property_trees();
+ auto* cc_transform = property_trees->transform_tree.Node(
+ property_trees->element_id_to_transform_node_index
+ [transform->GetCompositorElementId()]);
+ ASSERT_NE(nullptr, cc_transform);
+ EXPECT_TRUE(cc_transform->has_potential_animation);
+ EXPECT_TRUE(cc_transform->is_currently_animating);
+ }
+ // Make sure the animation is started on the compositor.
+ EXPECT_TRUE(CheckCanStartElementOnCompositor(*target));
EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 1u);
cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
EXPECT_EQ(host->MainThreadAnimationsCount(), 0u);
EXPECT_EQ(host->CompositedAnimationsCount(), 1u);
}
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
NonAnimatedTransformPropertyChangeGetsUpdated) {
+ // This test doesn't apply for pre-BlinkGenPropertyTrees due to the element id
+ // namespaces.
+ if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
+ // TODO(wangxianzhu): Fix this test for CompositeAfterPaint.
+ RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ return;
+
LoadTestData("transform-animation-update.html");
Document* document = GetFrame()->GetDocument();
Element* target = document->getElementById("target");
@@ -1919,11 +1959,19 @@
const auto* transform = properties->Transform();
ASSERT_NE(nullptr, transform);
// Make sure composited animation is running on #target.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- EXPECT_TRUE(transform->HasDirectCompositingReasons());
- CompositorAnimations::FailureCode code =
- CompositorAnimations::CheckCanStartElementOnCompositor(*target);
- EXPECT_EQ(code, CompositorAnimations::FailureCode::None());
+ EXPECT_TRUE(transform->HasDirectCompositingReasons());
+ EXPECT_TRUE(transform->HasActiveTransformAnimation());
+ EXPECT_TRUE(CheckCanStartElementOnCompositor(*target));
+ // Make sure the animation state is initialized in paint properties.
+ auto* property_trees =
+ document->View()->RootCcLayer()->layer_tree_host()->property_trees();
+ auto* cc_transform = property_trees->transform_tree.Node(
+ property_trees->element_id_to_transform_node_index
+ [transform->GetCompositorElementId()]);
+ ASSERT_NE(nullptr, cc_transform);
+ EXPECT_TRUE(cc_transform->has_potential_animation);
+ EXPECT_TRUE(cc_transform->is_currently_animating);
+ // Make sure the animation is started on the compositor.
EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 1u);
cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
EXPECT_EQ(host->MainThreadAnimationsCount(), 0u);
@@ -1942,6 +1990,7 @@
composited_layer_mapping->MainGraphicsLayer()->CcLayer();
ASSERT_NE(nullptr, layer);
EXPECT_TRUE(layer->double_sided());
+
// Change the backface visibility, while the compositor animation is
// happening.
target->setAttribute(html_names::kClassAttr, "backface-hidden");
@@ -1951,20 +2000,27 @@
TransformPaintPropertyNode::BackfaceVisibility::kHidden);
EXPECT_FALSE(layer->double_sided())
<< "Change to hidden did not get propagated to CC";
+ // Make sure the animation state is initialized in paint properties after
+ // blink pushing new paint properties without animation state change.
+ property_trees =
+ document->View()->RootCcLayer()->layer_tree_host()->property_trees();
+ cc_transform = property_trees->transform_tree.Node(
+ property_trees->element_id_to_transform_node_index
+ [transform->GetCompositorElementId()]);
+ ASSERT_NE(nullptr, cc_transform);
+ EXPECT_TRUE(cc_transform->has_potential_animation);
+ EXPECT_TRUE(cc_transform->is_currently_animating);
}
// Regression test for https://crbug.com/781305. When we have a transform
// animation on a SVG element, the effect can be started on compositor but the
// element itself cannot.
-TEST_F(AnimationCompositorAnimationsTest,
+TEST_P(AnimationCompositorAnimationsTest,
CannotStartElementOnCompositorEffectSVG) {
LoadTestData("transform-animation-on-svg.html");
Document* document = GetFrame()->GetDocument();
Element* target = document->getElementById("dots");
- CompositorAnimations::FailureCode code =
- CompositorAnimations::CheckCanStartElementOnCompositor(*target);
- EXPECT_EQ(code, CompositorAnimations::FailureCode::NonActionable(
- "Element does not paint into own backing"));
+ EXPECT_FALSE(CheckCanStartElementOnCompositor(*target));
EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 4u);
cc::AnimationHost* host = document->View()->GetCompositorAnimationHost();
EXPECT_EQ(host->MainThreadAnimationsCount(), 4u);
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index aef684a..fa19568 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -102,13 +102,7 @@
geometry_needs_update_ = true;
EffectPaintPropertyNode::State state;
- // In theory this value doesn't matter because the actual opacity during
- // composited animation is controlled by cc. However, this value could prevent
- // potential glitches at the end of the animation when opacity should be 0.
- // For web tests we don't fade out.
- // TODO(crbug.com/935770): Investigate the root cause that seems a timing
- // issue at the end of a composited animation in BlinkGenPropertyTree mode.
- state.opacity = WebTestSupport::IsRunningWebTest() ? kStartOpacity : 0;
+ state.opacity = kStartOpacity;
state.local_transform_space = &TransformPaintPropertyNode::Root();
state.compositor_element_id = element_id_;
state.direct_compositing_reasons = CompositingReason::kActiveOpacityAnimation;
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 9253369c..12bdf50 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -12,6 +12,7 @@
#include "cc/paint/display_item_list.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/mutator_host.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
@@ -956,6 +957,10 @@
blink_effects);
root_layer_->SetChildLayerList(std::move(layers));
+ // This initializes animation properties in the newly created paint property
+ // nodes according to the current animation state.
+ host->mutator_host()->InitClientAnimationState();
+
// Update the host's active registered element ids.
host->SetActiveRegisteredElementIds(composited_element_ids);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index a014033..0b0b798c 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -3355,8 +3355,6 @@
enum {
kNoRenderSurface = 0,
kHasRenderSurface = 1 << 0,
- kHasOpacityAnimation = 1 << 1,
- kHasFilterAnimation = 1 << 2,
};
#define EXPECT_OPACITY(effect_id, expected_opacity, expected_flags) \
@@ -3365,10 +3363,6 @@
EXPECT_EQ(expected_opacity, effect->opacity); \
EXPECT_EQ(!!((expected_flags)&kHasRenderSurface), \
effect->has_render_surface); \
- EXPECT_EQ(!!((expected_flags)&kHasOpacityAnimation), \
- effect->has_potential_opacity_animation); \
- EXPECT_EQ(!!((expected_flags)&kHasFilterAnimation), \
- effect->has_potential_filter_animation); \
} while (false)
TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfaces) {
@@ -3475,14 +3469,14 @@
// Effects of layer 0, 1, 5 each has one compositing layer, so don't have
// render surface.
- EXPECT_OPACITY(effect_ids[0], 1.f, kHasOpacityAnimation);
- EXPECT_OPACITY(effect_ids[1], 1.f, kHasOpacityAnimation);
- EXPECT_OPACITY(effect_ids[5], 1.f, kHasOpacityAnimation);
+ EXPECT_OPACITY(effect_ids[0], 1.f, kNoRenderSurface);
+ EXPECT_OPACITY(effect_ids[1], 1.f, kNoRenderSurface);
+ EXPECT_OPACITY(effect_ids[5], 1.f, kNoRenderSurface);
// Layer 2 and 3 have the same effect state. The effect has render surface
// because it has two compositing layers.
EXPECT_EQ(effect_ids[2], effect_ids[3]);
- EXPECT_OPACITY(effect_ids[2], 1.f, kHasRenderSurface | kHasOpacityAnimation);
+ EXPECT_OPACITY(effect_ids[2], 1.f, kHasRenderSurface);
// TODO(crbug.com/937573): It's an invalid case that an animating effect
// doesn't have a layer, but we still keep the case in this test case because
@@ -3490,15 +3484,15 @@
const auto& effect_tree = GetPropertyTrees().effect_tree;
int id_a = effect_tree.Node(effect_ids[0])->parent_id;
EXPECT_EQ(id_a, effect_tree.Node(effect_ids[1])->parent_id);
- EXPECT_OPACITY(id_a, 1.f, kNoRenderSurface | kHasOpacityAnimation);
+ EXPECT_OPACITY(id_a, 1.f, kNoRenderSurface);
// Effect |c| has one direct and one indirect compositing layers, so has
// render surface.
- EXPECT_OPACITY(effect_ids[4], 1.f, kHasRenderSurface | kHasOpacityAnimation);
+ EXPECT_OPACITY(effect_ids[4], 1.f, kHasRenderSurface);
// TODO(crbug.com/937573): Same as |a|.
EXPECT_OPACITY(effect_tree.Node(effect_ids[4])->parent_id, 1.f,
- kNoRenderSurface | kHasOpacityAnimation);
+ kNoRenderSurface);
}
TEST_P(PaintArtifactCompositorTest, OpacityRenderSurfacesWithBackdropChildren) {
@@ -3593,17 +3587,15 @@
// layer0's opacity animation needs a render surfafce because it affects
// both layer0 and layer1.
int layer0_effect_id = ContentLayerAt(0)->effect_tree_index();
- EXPECT_OPACITY(layer0_effect_id, 1.f,
- kHasRenderSurface | kHasOpacityAnimation);
+ EXPECT_OPACITY(layer0_effect_id, 1.f, kHasRenderSurface);
// layer1's opacity animation doesn't need a render surface because it
// affects layer1 only.
int layer1_effect_id = ContentLayerAt(1)->effect_tree_index();
- EXPECT_OPACITY(layer1_effect_id, 1.f,
- kNoRenderSurface | kHasOpacityAnimation);
+ EXPECT_OPACITY(layer1_effect_id, 1.f, kNoRenderSurface);
// Though |opacity| affects both layer0 and layer1, layer0's effect has
// render surface, so |opacity| doesn't need a render surface.
int opacity_id = effect_tree.Node(layer0_effect_id)->parent_id;
- EXPECT_OPACITY(opacity_id, 1.f, kNoRenderSurface | kHasOpacityAnimation);
+ EXPECT_OPACITY(opacity_id, 1.f, kNoRenderSurface);
}
TEST_P(PaintArtifactCompositorTest, FilterCreatesRenderSurface) {
@@ -3633,7 +3625,7 @@
.Build());
ASSERT_EQ(1u, ContentLayerCount());
EXPECT_OPACITY(ContentLayerAt(0)->effect_tree_index(), 1.f,
- kHasRenderSurface | kHasFilterAnimation);
+ kHasRenderSurface);
}
TEST_P(PaintArtifactCompositorTest,
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
index c062424..b4978436 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -276,11 +276,6 @@
compositor_node.element_id = compositor_element_id;
}
- // Set has_potential_animation in case we push property tree during an ongoing
- // animation. This condition should be kept consistent with cc.
- if (transform_node.IsRunningAnimationOnCompositor())
- compositor_node.has_potential_animation = true;
-
// If this transform is a scroll offset translation, create the associated
// compositor scroll property node and adjust the compositor transform node's
// scroll offset.
@@ -773,17 +768,6 @@
effect_node.id;
}
- // Set has_potential_xxx_animation in case we push property tree during
- // ongoing animations. The conditions should be kept consistent with cc.
- if (next_effect.IsRunningOpacityAnimationOnCompositor())
- effect_node.has_potential_opacity_animation = true;
- if (next_effect.IsRunningFilterAnimationOnCompositor())
- effect_node.has_potential_filter_animation = true;
- // TODO(crbug.com/938679): Set effect_node
- // .has_potential_backdrop_filter_animation when we have it.
- // if (next_effect.IsRunningBackdropAnimationOnCompositor())
- // effect_node.has_potential_backdrop_filter_animation = true;
-
effect_stack_.emplace_back(current_);
SetCurrentEffectState(effect_node, CcEffectType::kEffect, next_effect,
*output_clip);