1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/AnimationCommon.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,560 @@ 1.4 +/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "AnimationCommon.h" 1.10 +#include "nsTransitionManager.h" 1.11 +#include "nsAnimationManager.h" 1.12 + 1.13 +#include "gfxPlatform.h" 1.14 +#include "nsRuleData.h" 1.15 +#include "nsCSSValue.h" 1.16 +#include "nsStyleContext.h" 1.17 +#include "nsIFrame.h" 1.18 +#include "nsLayoutUtils.h" 1.19 +#include "mozilla/LookAndFeel.h" 1.20 +#include "Layers.h" 1.21 +#include "FrameLayerBuilder.h" 1.22 +#include "nsDisplayList.h" 1.23 +#include "mozilla/MemoryReporting.h" 1.24 +#include "RestyleManager.h" 1.25 +#include "nsStyleSet.h" 1.26 +#include "nsStyleChangeList.h" 1.27 + 1.28 + 1.29 +using mozilla::layers::Layer; 1.30 + 1.31 +namespace mozilla { 1.32 +namespace css { 1.33 + 1.34 +/* static */ bool 1.35 +IsGeometricProperty(nsCSSProperty aProperty) 1.36 +{ 1.37 + switch (aProperty) { 1.38 + case eCSSProperty_bottom: 1.39 + case eCSSProperty_height: 1.40 + case eCSSProperty_left: 1.41 + case eCSSProperty_right: 1.42 + case eCSSProperty_top: 1.43 + case eCSSProperty_width: 1.44 + return true; 1.45 + default: 1.46 + return false; 1.47 + } 1.48 +} 1.49 + 1.50 +CommonAnimationManager::CommonAnimationManager(nsPresContext *aPresContext) 1.51 + : mPresContext(aPresContext) 1.52 +{ 1.53 + PR_INIT_CLIST(&mElementData); 1.54 +} 1.55 + 1.56 +CommonAnimationManager::~CommonAnimationManager() 1.57 +{ 1.58 + NS_ABORT_IF_FALSE(!mPresContext, "Disconnect should have been called"); 1.59 +} 1.60 + 1.61 +void 1.62 +CommonAnimationManager::Disconnect() 1.63 +{ 1.64 + // Content nodes might outlive the transition or animation manager. 1.65 + RemoveAllElementData(); 1.66 + 1.67 + mPresContext = nullptr; 1.68 +} 1.69 + 1.70 +void 1.71 +CommonAnimationManager::RemoveAllElementData() 1.72 +{ 1.73 + while (!PR_CLIST_IS_EMPTY(&mElementData)) { 1.74 + CommonElementAnimationData *head = 1.75 + static_cast<CommonElementAnimationData*>(PR_LIST_HEAD(&mElementData)); 1.76 + head->Destroy(); 1.77 + } 1.78 +} 1.79 + 1.80 +/* 1.81 + * nsISupports implementation 1.82 + */ 1.83 + 1.84 +NS_IMPL_ISUPPORTS(CommonAnimationManager, nsIStyleRuleProcessor) 1.85 + 1.86 +nsRestyleHint 1.87 +CommonAnimationManager::HasStateDependentStyle(StateRuleProcessorData* aData) 1.88 +{ 1.89 + return nsRestyleHint(0); 1.90 +} 1.91 + 1.92 +nsRestyleHint 1.93 +CommonAnimationManager::HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) 1.94 +{ 1.95 + return nsRestyleHint(0); 1.96 +} 1.97 + 1.98 +bool 1.99 +CommonAnimationManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) 1.100 +{ 1.101 + return false; 1.102 +} 1.103 + 1.104 +nsRestyleHint 1.105 +CommonAnimationManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData) 1.106 +{ 1.107 + return nsRestyleHint(0); 1.108 +} 1.109 + 1.110 +/* virtual */ bool 1.111 +CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext) 1.112 +{ 1.113 + return false; 1.114 +} 1.115 + 1.116 +/* virtual */ size_t 1.117 +CommonAnimationManager::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const 1.118 +{ 1.119 + // Measurement of the following members may be added later if DMD finds it is 1.120 + // worthwhile: 1.121 + // - mElementData 1.122 + // 1.123 + // The following members are not measured 1.124 + // - mPresContext, because it's non-owning 1.125 + 1.126 + return 0; 1.127 +} 1.128 + 1.129 +/* virtual */ size_t 1.130 +CommonAnimationManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const 1.131 +{ 1.132 + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 1.133 +} 1.134 + 1.135 +/* static */ bool 1.136 +CommonAnimationManager::ExtractComputedValueForTransition( 1.137 + nsCSSProperty aProperty, 1.138 + nsStyleContext* aStyleContext, 1.139 + nsStyleAnimation::Value& aComputedValue) 1.140 +{ 1.141 + bool result = 1.142 + nsStyleAnimation::ExtractComputedValue(aProperty, aStyleContext, 1.143 + aComputedValue); 1.144 + if (aProperty == eCSSProperty_visibility) { 1.145 + NS_ABORT_IF_FALSE(aComputedValue.GetUnit() == 1.146 + nsStyleAnimation::eUnit_Enumerated, 1.147 + "unexpected unit"); 1.148 + aComputedValue.SetIntValue(aComputedValue.GetIntValue(), 1.149 + nsStyleAnimation::eUnit_Visibility); 1.150 + } 1.151 + return result; 1.152 +} 1.153 + 1.154 +already_AddRefed<nsStyleContext> 1.155 +CommonAnimationManager::ReparentContent(nsIContent* aContent, 1.156 + nsStyleContext* aParentStyle) 1.157 +{ 1.158 + nsStyleSet* styleSet = mPresContext->PresShell()->StyleSet(); 1.159 + nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aContent); 1.160 + if (!primaryFrame) { 1.161 + return nullptr; 1.162 + } 1.163 + 1.164 + dom::Element* element = aContent->IsElement() 1.165 + ? aContent->AsElement() 1.166 + : nullptr; 1.167 + 1.168 + nsRefPtr<nsStyleContext> newStyle = 1.169 + styleSet->ReparentStyleContext(primaryFrame->StyleContext(), 1.170 + aParentStyle, element); 1.171 + primaryFrame->SetStyleContext(newStyle); 1.172 + ReparentBeforeAndAfter(element, primaryFrame, newStyle, styleSet); 1.173 + 1.174 + return newStyle.forget(); 1.175 +} 1.176 + 1.177 +/* static */ void 1.178 +CommonAnimationManager::ReparentBeforeAndAfter(dom::Element* aElement, 1.179 + nsIFrame* aPrimaryFrame, 1.180 + nsStyleContext* aNewStyle, 1.181 + nsStyleSet* aStyleSet) 1.182 +{ 1.183 + if (nsIFrame* before = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) { 1.184 + nsRefPtr<nsStyleContext> beforeStyle = 1.185 + aStyleSet->ReparentStyleContext(before->StyleContext(), 1.186 + aNewStyle, aElement); 1.187 + before->SetStyleContext(beforeStyle); 1.188 + } 1.189 + if (nsIFrame* after = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) { 1.190 + nsRefPtr<nsStyleContext> afterStyle = 1.191 + aStyleSet->ReparentStyleContext(after->StyleContext(), 1.192 + aNewStyle, aElement); 1.193 + after->SetStyleContext(afterStyle); 1.194 + } 1.195 +} 1.196 + 1.197 +nsStyleContext* 1.198 +CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement, 1.199 + nsStyleContext* aParentStyle, 1.200 + nsStyleChangeList& aChangeList) 1.201 +{ 1.202 + NS_ASSERTION(mPresContext->TransitionManager()->GetElementTransitions( 1.203 + aElement, 1.204 + nsCSSPseudoElements::ePseudo_NotPseudoElement, 1.205 + false) || 1.206 + mPresContext->AnimationManager()->GetElementAnimations( 1.207 + aElement, 1.208 + nsCSSPseudoElements::ePseudo_NotPseudoElement, 1.209 + false), "element not animated"); 1.210 + 1.211 + nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aElement); 1.212 + if (!primaryFrame) { 1.213 + return nullptr; 1.214 + } 1.215 + 1.216 + nsStyleContext* oldStyle = primaryFrame->StyleContext(); 1.217 + nsRuleNode* ruleNode = oldStyle->RuleNode(); 1.218 + nsTArray<nsStyleSet::RuleAndLevel> rules; 1.219 + do { 1.220 + if (ruleNode->IsRoot()) { 1.221 + break; 1.222 + } 1.223 + 1.224 + nsStyleSet::RuleAndLevel curRule; 1.225 + curRule.mLevel = ruleNode->GetLevel(); 1.226 + 1.227 + if (curRule.mLevel == nsStyleSet::eAnimationSheet) { 1.228 + ElementAnimations* ea = 1.229 + mPresContext->AnimationManager()->GetElementAnimations( 1.230 + aElement, 1.231 + oldStyle->GetPseudoType(), 1.232 + false); 1.233 + NS_ASSERTION(ea, 1.234 + "Rule has level eAnimationSheet without animation on manager"); 1.235 + 1.236 + mPresContext->AnimationManager()->EnsureStyleRuleFor(ea); 1.237 + curRule.mRule = ea->mStyleRule; 1.238 + } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) { 1.239 + ElementTransitions *et = 1.240 + mPresContext->TransitionManager()->GetElementTransitions( 1.241 + aElement, 1.242 + oldStyle->GetPseudoType(), 1.243 + false); 1.244 + NS_ASSERTION(et, 1.245 + "Rule has level eTransitionSheet without transition on manager"); 1.246 + 1.247 + et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh()); 1.248 + curRule.mRule = et->mStyleRule; 1.249 + } else { 1.250 + curRule.mRule = ruleNode->GetRule(); 1.251 + } 1.252 + 1.253 + if (curRule.mRule) { 1.254 + rules.AppendElement(curRule); 1.255 + } 1.256 + } while ((ruleNode = ruleNode->GetParent())); 1.257 + 1.258 + nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()-> 1.259 + ResolveStyleForRules(aParentStyle, oldStyle, rules); 1.260 + 1.261 + // We absolutely must call CalcStyleDifference in order to ensure the 1.262 + // new context has all the structs cached that the old context had. 1.263 + // We also need it for processing of the changes. 1.264 + nsChangeHint styleChange = 1.265 + oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0)); 1.266 + aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(), 1.267 + styleChange); 1.268 + 1.269 + primaryFrame->SetStyleContext(newStyle); 1.270 + 1.271 + ReparentBeforeAndAfter(aElement, primaryFrame, newStyle, 1.272 + mPresContext->PresShell()->StyleSet()); 1.273 + 1.274 + return newStyle; 1.275 +} 1.276 + 1.277 +NS_IMPL_ISUPPORTS(AnimValuesStyleRule, nsIStyleRule) 1.278 + 1.279 +/* virtual */ void 1.280 +AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData) 1.281 +{ 1.282 + nsStyleContext *contextParent = aRuleData->mStyleContext->GetParent(); 1.283 + if (contextParent && contextParent->HasPseudoElementData()) { 1.284 + // Don't apply transitions or animations to things inside of 1.285 + // pseudo-elements. 1.286 + // FIXME (Bug 522599): Add tests for this. 1.287 + return; 1.288 + } 1.289 + 1.290 + for (uint32_t i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) { 1.291 + PropertyValuePair &cv = mPropertyValuePairs[i]; 1.292 + if (aRuleData->mSIDs & nsCachedStyleData::GetBitForSID( 1.293 + nsCSSProps::kSIDTable[cv.mProperty])) 1.294 + { 1.295 + nsCSSValue *prop = aRuleData->ValueFor(cv.mProperty); 1.296 + if (prop->GetUnit() == eCSSUnit_Null) { 1.297 +#ifdef DEBUG 1.298 + bool ok = 1.299 +#endif 1.300 + nsStyleAnimation::UncomputeValue(cv.mProperty, cv.mValue, *prop); 1.301 + NS_ABORT_IF_FALSE(ok, "could not store computed value"); 1.302 + } 1.303 + } 1.304 + } 1.305 +} 1.306 + 1.307 +#ifdef DEBUG 1.308 +/* virtual */ void 1.309 +AnimValuesStyleRule::List(FILE* out, int32_t aIndent) const 1.310 +{ 1.311 + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); 1.312 + fputs("[anim values] { ", out); 1.313 + for (uint32_t i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) { 1.314 + const PropertyValuePair &pair = mPropertyValuePairs[i]; 1.315 + nsAutoString value; 1.316 + nsStyleAnimation::UncomputeValue(pair.mProperty, pair.mValue, value); 1.317 + fprintf(out, "%s: %s; ", nsCSSProps::GetStringValue(pair.mProperty).get(), 1.318 + NS_ConvertUTF16toUTF8(value).get()); 1.319 + } 1.320 + fputs("}\n", out); 1.321 +} 1.322 +#endif 1.323 + 1.324 +void 1.325 +ComputedTimingFunction::Init(const nsTimingFunction &aFunction) 1.326 +{ 1.327 + mType = aFunction.mType; 1.328 + if (mType == nsTimingFunction::Function) { 1.329 + mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1, 1.330 + aFunction.mFunc.mX2, aFunction.mFunc.mY2); 1.331 + } else { 1.332 + mSteps = aFunction.mSteps; 1.333 + } 1.334 +} 1.335 + 1.336 +static inline double 1.337 +StepEnd(uint32_t aSteps, double aPortion) 1.338 +{ 1.339 + NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range"); 1.340 + uint32_t step = uint32_t(aPortion * aSteps); // floor 1.341 + return double(step) / double(aSteps); 1.342 +} 1.343 + 1.344 +double 1.345 +ComputedTimingFunction::GetValue(double aPortion) const 1.346 +{ 1.347 + switch (mType) { 1.348 + case nsTimingFunction::Function: 1.349 + return mTimingFunction.GetSplineValue(aPortion); 1.350 + case nsTimingFunction::StepStart: 1.351 + // There are diagrams in the spec that seem to suggest this check 1.352 + // and the bounds point should not be symmetric with StepEnd, but 1.353 + // should actually step up at rather than immediately after the 1.354 + // fraction points. However, we rely on rounding negative values 1.355 + // up to zero, so we can't do that. And it's not clear the spec 1.356 + // really meant it. 1.357 + return 1.0 - StepEnd(mSteps, 1.0 - aPortion); 1.358 + default: 1.359 + NS_ABORT_IF_FALSE(false, "bad type"); 1.360 + // fall through 1.361 + case nsTimingFunction::StepEnd: 1.362 + return StepEnd(mSteps, aPortion); 1.363 + } 1.364 +} 1.365 + 1.366 +} /* end sub-namespace css */ 1.367 + 1.368 +bool 1.369 +StyleAnimation::IsRunningAt(TimeStamp aTime) const 1.370 +{ 1.371 + if (IsPaused() || mIterationDuration.ToMilliseconds() <= 0.0 || 1.372 + mStartTime.IsNull()) { 1.373 + return false; 1.374 + } 1.375 + 1.376 + double iterationsElapsed = ElapsedDurationAt(aTime) / mIterationDuration; 1.377 + return 0.0 <= iterationsElapsed && iterationsElapsed < mIterationCount; 1.378 +} 1.379 + 1.380 +bool 1.381 +StyleAnimation::HasAnimationOfProperty(nsCSSProperty aProperty) const 1.382 +{ 1.383 + for (uint32_t propIdx = 0, propEnd = mProperties.Length(); 1.384 + propIdx != propEnd; ++propIdx) { 1.385 + if (aProperty == mProperties[propIdx].mProperty) { 1.386 + return true; 1.387 + } 1.388 + } 1.389 + return false; 1.390 +} 1.391 + 1.392 +namespace css { 1.393 + 1.394 +bool 1.395 +CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *aElement, 1.396 + nsCSSProperty aProperty, 1.397 + CanAnimateFlags aFlags) 1.398 +{ 1.399 + bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled(); 1.400 + if (!gfxPlatform::OffMainThreadCompositingEnabled()) { 1.401 + if (shouldLog) { 1.402 + nsCString message; 1.403 + message.AppendLiteral("Performance warning: Compositor disabled"); 1.404 + LogAsyncAnimationFailure(message); 1.405 + } 1.406 + return false; 1.407 + } 1.408 + 1.409 + nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement); 1.410 + if (IsGeometricProperty(aProperty)) { 1.411 + if (shouldLog) { 1.412 + nsCString message; 1.413 + message.AppendLiteral("Performance warning: Async animation of geometric property '"); 1.414 + message.Append(nsCSSProps::GetStringValue(aProperty)); 1.415 + message.AppendLiteral("' is disabled"); 1.416 + LogAsyncAnimationFailure(message, aElement); 1.417 + } 1.418 + return false; 1.419 + } 1.420 + if (aProperty == eCSSProperty_transform) { 1.421 + if (frame->Preserves3D() && 1.422 + frame->Preserves3DChildren()) { 1.423 + if (shouldLog) { 1.424 + nsCString message; 1.425 + message.AppendLiteral("Gecko bug: Async animation of 'preserve-3d' transforms is not supported. See bug 779598"); 1.426 + LogAsyncAnimationFailure(message, aElement); 1.427 + } 1.428 + return false; 1.429 + } 1.430 + if (frame->IsSVGTransformed()) { 1.431 + if (shouldLog) { 1.432 + nsCString message; 1.433 + message.AppendLiteral("Gecko bug: Async 'transform' animations of frames with SVG transforms is not supported. See bug 779599"); 1.434 + LogAsyncAnimationFailure(message, aElement); 1.435 + } 1.436 + return false; 1.437 + } 1.438 + if (aFlags & CanAnimate_HasGeometricProperty) { 1.439 + if (shouldLog) { 1.440 + nsCString message; 1.441 + message.AppendLiteral("Performance warning: Async animation of 'transform' not possible due to presence of geometric properties"); 1.442 + LogAsyncAnimationFailure(message, aElement); 1.443 + } 1.444 + return false; 1.445 + } 1.446 + } 1.447 + bool enabled = nsLayoutUtils::AreAsyncAnimationsEnabled(); 1.448 + if (!enabled && shouldLog) { 1.449 + nsCString message; 1.450 + message.AppendLiteral("Performance warning: Async animations are disabled"); 1.451 + LogAsyncAnimationFailure(message); 1.452 + } 1.453 + bool propertyAllowed = (aProperty == eCSSProperty_transform) || 1.454 + (aProperty == eCSSProperty_opacity) || 1.455 + (aFlags & CanAnimate_AllowPartial); 1.456 + return enabled && propertyAllowed; 1.457 +} 1.458 + 1.459 +/* static */ bool 1.460 +CommonElementAnimationData::IsCompositorAnimationDisabledForFrame(nsIFrame* aFrame) 1.461 +{ 1.462 + void* prop = aFrame->Properties().Get(nsIFrame::RefusedAsyncAnimation()); 1.463 + return bool(reinterpret_cast<intptr_t>(prop)); 1.464 +} 1.465 + 1.466 +/* static */ void 1.467 +CommonElementAnimationData::LogAsyncAnimationFailure(nsCString& aMessage, 1.468 + const nsIContent* aContent) 1.469 +{ 1.470 + if (aContent) { 1.471 + aMessage.AppendLiteral(" ["); 1.472 + aMessage.Append(nsAtomCString(aContent->Tag())); 1.473 + 1.474 + nsIAtom* id = aContent->GetID(); 1.475 + if (id) { 1.476 + aMessage.AppendLiteral(" with id '"); 1.477 + aMessage.Append(nsAtomCString(aContent->GetID())); 1.478 + aMessage.AppendLiteral("'"); 1.479 + } 1.480 + aMessage.AppendLiteral("]"); 1.481 + } 1.482 + aMessage.AppendLiteral("\n"); 1.483 + printf_stderr(aMessage.get()); 1.484 +} 1.485 + 1.486 +bool 1.487 +CommonElementAnimationData::CanThrottleTransformChanges(TimeStamp aTime) 1.488 +{ 1.489 + if (!nsLayoutUtils::AreAsyncAnimationsEnabled()) { 1.490 + return false; 1.491 + } 1.492 + 1.493 + // If we know that the animation cannot cause overflow, 1.494 + // we can just disable flushes for this animation. 1.495 + 1.496 + // If we don't show scrollbars, we don't care about overflow. 1.497 + if (LookAndFeel::GetInt(LookAndFeel::eIntID_ShowHideScrollbars) == 0) { 1.498 + return true; 1.499 + } 1.500 + 1.501 + // If this animation can cause overflow, we can throttle some of the ticks. 1.502 + if ((aTime - mStyleRuleRefreshTime) < TimeDuration::FromMilliseconds(200)) { 1.503 + return true; 1.504 + } 1.505 + 1.506 + // If the nearest scrollable ancestor has overflow:hidden, 1.507 + // we don't care about overflow. 1.508 + nsIScrollableFrame* scrollable = nsLayoutUtils::GetNearestScrollableFrame( 1.509 + nsLayoutUtils::GetStyleFrame(mElement)); 1.510 + if (!scrollable) { 1.511 + return true; 1.512 + } 1.513 + 1.514 + ScrollbarStyles ss = scrollable->GetScrollbarStyles(); 1.515 + if (ss.mVertical == NS_STYLE_OVERFLOW_HIDDEN && 1.516 + ss.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN && 1.517 + scrollable->GetLogicalScrollPosition() == nsPoint(0, 0)) { 1.518 + return true; 1.519 + } 1.520 + 1.521 + return false; 1.522 +} 1.523 + 1.524 +bool 1.525 +CommonElementAnimationData::CanThrottleAnimation(TimeStamp aTime) 1.526 +{ 1.527 + nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement); 1.528 + if (!frame) { 1.529 + return false; 1.530 + } 1.531 + 1.532 + bool hasTransform = HasAnimationOfProperty(eCSSProperty_transform); 1.533 + bool hasOpacity = HasAnimationOfProperty(eCSSProperty_opacity); 1.534 + if (hasOpacity) { 1.535 + Layer* layer = FrameLayerBuilder::GetDedicatedLayer( 1.536 + frame, nsDisplayItem::TYPE_OPACITY); 1.537 + if (!layer || mAnimationGeneration > layer->GetAnimationGeneration()) { 1.538 + return false; 1.539 + } 1.540 + } 1.541 + 1.542 + if (!hasTransform) { 1.543 + return true; 1.544 + } 1.545 + 1.546 + Layer* layer = FrameLayerBuilder::GetDedicatedLayer( 1.547 + frame, nsDisplayItem::TYPE_TRANSFORM); 1.548 + if (!layer || mAnimationGeneration > layer->GetAnimationGeneration()) { 1.549 + return false; 1.550 + } 1.551 + 1.552 + return CanThrottleTransformChanges(aTime); 1.553 +} 1.554 + 1.555 +void 1.556 +CommonElementAnimationData::UpdateAnimationGeneration(nsPresContext* aPresContext) 1.557 +{ 1.558 + mAnimationGeneration = 1.559 + aPresContext->RestyleManager()->GetAnimationGeneration(); 1.560 +} 1.561 + 1.562 +} 1.563 +}