Don't composite SVG element animating unsupported property by the compositor
[email protected]
(cherry picked from commit b647ada1ad2f56a3655707d05f4b25647e858659)
Bug: 1136764
Change-Id: Id909f6ef11c914ca8ff4c468c669a60d0f04dd31
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2464015
Reviewed-by: Fredrik Söderquist <[email protected]>
Commit-Queue: Xianzhu Wang <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#816207}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2465215
Reviewed-by: Xianzhu Wang <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#317}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
index 413309dd5..f6f79dfe 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -395,6 +395,15 @@
0% { transform: rotate(-5deg); }
100% { transform: rotate(5deg); }
}
+ .animate-mixed {
+ width: 100px;
+ height: 100px;
+ animation: mixed 1s infinite;
+ }
+ @keyframes mixed {
+ 0% { transform: rotate(-5deg); stroke-dashoffset: 0; }
+ 100% { transform: rotate(5deg); stroke-dashoffset: 180; }
+ }
</style>
<svg id="svg" class="animate">
<rect id="rect" class="animate"/>
@@ -402,6 +411,7 @@
<animateMotion dur="10s" repeatCount="indefinite"
path="M0,0 L100,100 z"/>
</rect>
+ <rect id="rect-mixed" class="animate-mixed"/>
<svg id="embedded-svg" class="animate"/>
<foreignObject id="foreign" class="animate"/>
<foreignObject id="foreign-zoomed" class="animate"
@@ -423,6 +433,9 @@
*GetLayoutObjectByElementId("rect-smil")));
EXPECT_EQ(CompositingReason::kNone,
CompositingReasonFinder::DirectReasonsForPaintProperties(
+ *GetLayoutObjectByElementId("rect-mixed")));
+ EXPECT_EQ(CompositingReason::kNone,
+ CompositingReasonFinder::DirectReasonsForPaintProperties(
*GetLayoutObjectByElementId("embedded-svg")));
EXPECT_EQ(CompositingReason::kActiveTransformAnimation,
CompositingReasonFinder::DirectReasonsForPaintProperties(
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc
index a8c0217e..70344216 100644
--- a/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -267,13 +267,52 @@
});
}
-bool SVGElement::HasMainThreadAnimations() const {
- if (!HasSVGRareData())
+// TODO(crbug.com/1134652): For now composited animation doesn't work for SVG
+// if the animation also has properties other than the supported ones. We should
+// remove this when we make SVG CSS animations work in the same way as other
+// elements.
+static PropertyHandleSet SupportedCompositedAnimationProperties() {
+ DEFINE_STATIC_LOCAL(PropertyHandleSet, supported_properties,
+ ({PropertyHandle(GetCSSPropertyOpacity()),
+ PropertyHandle(GetCSSPropertyTransform()),
+ PropertyHandle(GetCSSPropertyRotate()),
+ PropertyHandle(GetCSSPropertyScale()),
+ PropertyHandle(GetCSSPropertyTranslate()),
+ PropertyHandle(GetCSSPropertyFilter()),
+ PropertyHandle(GetCSSPropertyBackdropFilter())}));
+ return supported_properties;
+}
+
+static bool HasMainThreadAnimationProperty(const AnimationEffect* effect) {
+ const KeyframeEffectModelBase* model = nullptr;
+ if (auto* keyframe_effect = DynamicTo<KeyframeEffect>(effect))
+ model = DynamicTo<KeyframeEffectModelBase>(keyframe_effect->Model());
+ else if (auto* inert_effect = DynamicTo<InertEffect>(effect))
+ model = DynamicTo<KeyframeEffectModelBase>(inert_effect->Model());
+ if (!model)
return false;
- if (!SvgRareData()->WebAnimatedAttributes().IsEmpty())
+ for (auto& property : model->Properties()) {
+ if (!SupportedCompositedAnimationProperties().Contains(property))
+ return true;
+ }
+ return false;
+}
+
+bool SVGElement::HasMainThreadAnimations() const {
+ if (HasSVGRareData() && !SvgRareData()->WebAnimatedAttributes().IsEmpty())
return true;
if (GetSMILAnimations() && GetSMILAnimations()->HasAnimations())
return true;
+ if (auto* element_animations = GetElementAnimations()) {
+ for (auto& entry : element_animations->Animations()) {
+ if (HasMainThreadAnimationProperty(entry.key->effect()))
+ return true;
+ }
+ for (auto& entry : element_animations->GetWorkletAnimations()) {
+ if (HasMainThreadAnimationProperty(entry->GetEffect()))
+ return true;
+ }
+ }
return false;
}