diff --git a/dom/animation/EffectCompositor.cpp b/dom/animation/EffectCompositor.cpp
index 00f4bd9ce34f..7b509d2ba797 100644
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -109,10 +109,14 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
continue;
}
- if (effect->ShouldBlockCompositorAnimations(aFrame)) {
+ nsAutoString performanceWarning;
+ if (effect->ShouldBlockCompositorAnimations(aFrame,
+ performanceWarning)) {
if (aMatches) {
aMatches->Clear();
}
+ effect->SetPerformanceWarning(aProperty,
+ performanceWarning);
return false;
}
diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp
index 05862a621051..5286cdab38d7 100644
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -2099,19 +2099,16 @@ KeyframeEffectReadOnly::IsGeometricProperty(
/* static */ bool
KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
const nsIFrame* aFrame,
- const nsIContent* aContent)
+ nsAString& aPerformanceWarning)
{
// Disallow OMTA for preserve-3d transform. Note that we check the style property
// rather than Extend3DContext() since that can recurse back into this function
// via HasOpacity().
if (aFrame->Combines3DTransformWithAncestors() ||
aFrame->StyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D) {
- if (aContent) {
- nsCString message;
- message.AppendLiteral("Gecko bug: Async animation of 'preserve-3d' "
- "transforms is not supported. See bug 779598");
- AnimationUtils::LogAsyncAnimationFailure(message, aContent);
- }
+ aPerformanceWarning.AssignLiteral(
+ "Gecko bug: Async animation of 'preserve-3d' "
+ "transforms is not supported. See bug 779598");
return false;
}
// Note that testing BackfaceIsHidden() is not a sufficient test for
@@ -2119,22 +2116,16 @@ KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
// remove the above test for Extend3DContext(); that would require
// looking at backface-visibility on descendants as well.
if (aFrame->StyleDisplay()->BackfaceIsHidden()) {
- if (aContent) {
- nsCString message;
- message.AppendLiteral("Gecko bug: Async animation of "
- "'backface-visibility: hidden' transforms is not supported."
- " See bug 1186204.");
- AnimationUtils::LogAsyncAnimationFailure(message, aContent);
- }
+ aPerformanceWarning.AssignLiteral(
+ "Gecko bug: Async animation of "
+ "'backface-visibility: hidden' transforms is not supported."
+ " See bug 1186204");
return false;
}
if (aFrame->IsSVGTransformed()) {
- if (aContent) {
- nsCString message;
- message.AppendLiteral("Gecko bug: Async 'transform' animations of "
- "aFrames with SVG transforms is not supported. See bug 779599");
- AnimationUtils::LogAsyncAnimationFailure(message, aContent);
- }
+ aPerformanceWarning.AssignLiteral(
+ "Gecko bug: Async 'transform' animations of "
+ "aFrames with SVG transforms is not supported. See bug 779599");
return false;
}
@@ -2142,8 +2133,9 @@ KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
}
bool
-KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(const nsIFrame*
- aFrame) const
+KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(
+ const nsIFrame* aFrame,
+ nsAString& aPerformanceWarning) const
{
// We currently only expect this method to be called when this effect
// is attached to a playing Animation. If that ever changes we'll need
@@ -2152,8 +2144,6 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(const nsIFrame*
// running on the compositor.
MOZ_ASSERT(mAnimation && mAnimation->IsPlaying());
- bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled();
-
for (const AnimationProperty& property : mProperties) {
// If a property is overridden in the CSS cascade, it should not block other
// animations from running on the compositor.
@@ -2162,20 +2152,17 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(const nsIFrame*
}
// Check for geometric properties
if (IsGeometricProperty(property.mProperty)) {
- if (shouldLog) {
- nsCString message;
- message.AppendLiteral("Performance warning: Async animation of "
- "'transform' or 'opacity' not possible due to animation of geometric"
- "properties on the same element");
- AnimationUtils::LogAsyncAnimationFailure(message, aFrame->GetContent());
- }
+ aPerformanceWarning.AssignLiteral(
+ "Performance warning: Async animation of "
+ "'transform' or 'opacity' not possible due to animation of geometric "
+ "properties on the same element");
return true;
}
// Check for unsupported transform animations
if (property.mProperty == eCSSProperty_transform) {
if (!CanAnimateTransformOnCompositor(aFrame,
- shouldLog ? aFrame->GetContent() : nullptr)) {
+ aPerformanceWarning)) {
return true;
}
}
@@ -2190,7 +2177,13 @@ KeyframeEffectReadOnly::SetPerformanceWarning(nsCSSProperty aProperty,
{
for (AnimationProperty& property : mProperties) {
if (property.mProperty == aProperty) {
+ property.mPerformanceWarning.reset();
property.mPerformanceWarning.emplace(aMessage);
+
+ if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
+ nsAutoCString logMessage = NS_ConvertUTF16toUTF8(aMessage);
+ AnimationUtils::LogAsyncAnimationFailure(logMessage, mTarget);
+ }
return;
}
}
diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h
index a24992411c4a..5991d907ee51 100644
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -324,7 +324,11 @@ public:
//
// Bug 1218620 - It seems like we don't need to be this restrictive. Wouldn't
// it be ok to do 'opacity' animations on the compositor in either case?
- bool ShouldBlockCompositorAnimations(const nsIFrame* aFrame) const;
+ //
+ // When returning true, |aOutPerformanceWarning| stores the reason why
+ // we shouldn't run the compositor animations.
+ bool ShouldBlockCompositorAnimations(const nsIFrame* aFrame,
+ nsAString& aPerformanceWarning) const;
nsIDocument* GetRenderedDocument() const;
nsPresContext* GetPresContext() const;
@@ -396,11 +400,10 @@ private:
bool CanThrottleTransformChanges(nsIFrame& aFrame) const;
// Returns true unless Gecko limitations prevent performing transform
- // animations for |aFrame|. Any limitations that are encountered are
- // logged using |aContent| to describe the affected content.
- // If |aContent| is nullptr, no logging is performed
+ // animations for |aFrame|. When returning true, the reason for the
+ // limitation is stored in |aOutPerformanceWarning|.
static bool CanAnimateTransformOnCompositor(const nsIFrame* aFrame,
- const nsIContent* aContent);
+ nsAString& aPerformanceWarning);
static bool IsGeometricProperty(const nsCSSProperty aProperty);
static const TimeDuration OverflowRegionRefreshInterval();
diff --git a/dom/animation/test/chrome/test_animation_property_state.html b/dom/animation/test/chrome/test_animation_property_state.html
index 59495575f951..39bc2980f824 100644
--- a/dom/animation/test/chrome/test_animation_property_state.html
+++ b/dom/animation/test/chrome/test_animation_property_state.html
@@ -7,7 +7,7 @@