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 @@