/* static */ nsTArray<RefPtr<dom::Animation>> EffectCompositor::GetAnimationsForCompositor(const nsIFrame* aFrame, nsCSSProperty aProperty) { nsTArray<RefPtr<dom::Animation>> result; if (!nsLayoutUtils::AreAsyncAnimationsEnabled()) { if (nsLayoutUtils::IsAnimationLoggingEnabled()) { nsCString message; message.AppendLiteral("Performance warning: Async animations are " "disabled"); AnimationUtils::LogAsyncAnimationFailure(message); } return result; } if (aFrame->RefusedAsyncAnimation()) { return result; } EffectSet* effects = EffectSet::GetEffectSet(aFrame); if (!effects) { return result; } for (KeyframeEffectReadOnly* effect : *effects) { MOZ_ASSERT(effect && effect->GetAnimation()); Animation* animation = effect->GetAnimation(); if (!animation->IsPlaying()) { continue; } if (effect->ShouldBlockCompositorAnimations(aFrame)) { result.Clear(); return result; } if (!effect->HasAnimationOfProperty(aProperty)) { continue; } result.AppendElement(animation); } return result; }
// Helper function to factor out the common logic from // GetAnimationsForCompositor and HasAnimationsForCompositor. // // Takes an optional array to fill with eligible animations. // // Returns true if there are eligible animations, false otherwise. bool FindAnimationsForCompositor(const nsIFrame* aFrame, nsCSSProperty aProperty, nsTArray<RefPtr<dom::Animation>>* aMatches /*out*/) { MOZ_ASSERT(!aMatches || aMatches->IsEmpty(), "Matches array, if provided, should be empty"); EffectSet* effects = EffectSet::GetEffectSet(aFrame); if (!effects || effects->IsEmpty()) { return false; } if (aFrame->RefusedAsyncAnimation()) { return false; } // The animation cascade will almost always be up-to-date by this point // but there are some cases such as when we are restoring the refresh driver // from test control after seeking where it might not be the case. // // Those cases are probably not important but just to be safe, let's make // sure the cascade is up to date since if it *is* up to date, this is // basically a no-op. Maybe<Pair<dom::Element*, nsCSSPseudoElements::Type>> pseudoElement = EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame); if (pseudoElement) { EffectCompositor::MaybeUpdateCascadeResults(pseudoElement->first(), pseudoElement->second(), aFrame->StyleContext()); } if (!nsLayoutUtils::AreAsyncAnimationsEnabled()) { if (nsLayoutUtils::IsAnimationLoggingEnabled()) { nsCString message; message.AppendLiteral("Performance warning: Async animations are " "disabled"); AnimationUtils::LogAsyncAnimationFailure(message); } return false; } bool foundSome = false; for (KeyframeEffectReadOnly* effect : *effects) { MOZ_ASSERT(effect && effect->GetAnimation()); Animation* animation = effect->GetAnimation(); if (!animation->IsPlaying()) { continue; } if (effect->ShouldBlockCompositorAnimations(aFrame)) { if (aMatches) { aMatches->Clear(); } return false; } if (!effect->HasAnimationOfProperty(aProperty)) { continue; } if (aMatches) { aMatches->AppendElement(animation); } foundSome = true; } MOZ_ASSERT(!foundSome || !aMatches || !aMatches->IsEmpty(), "If return value is true, matches array should be non-empty"); return foundSome; }