mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 22:04:36 +00:00
Bug 533291 Patch D: Cache base value with each SMIL compositor, since we need to recompose when base value changes. r=roc
This commit is contained in:
parent
d022ff95c3
commit
0185ff4ef3
@ -255,6 +255,22 @@ nsSMILAnimationController::StopTimer()
|
||||
//----------------------------------------------------------------------
|
||||
// Sample-related methods and callbacks
|
||||
|
||||
PR_CALLBACK PLDHashOperator
|
||||
TransferCachedBaseValue(nsSMILCompositor* aCompositor,
|
||||
void* aData)
|
||||
{
|
||||
nsSMILCompositorTable* lastCompositorTable =
|
||||
static_cast<nsSMILCompositorTable*>(aData);
|
||||
nsSMILCompositor* lastCompositor =
|
||||
lastCompositorTable->GetEntry(aCompositor->GetKey());
|
||||
|
||||
if (lastCompositor) {
|
||||
aCompositor->StealCachedBaseValue(lastCompositor);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PR_CALLBACK PLDHashOperator
|
||||
RemoveCompositorFromTable(nsSMILCompositor* aCompositor,
|
||||
void* aData)
|
||||
@ -339,8 +355,14 @@ nsSMILAnimationController::DoSample(PRBool aSkipUnchangedContainers)
|
||||
&saParams);
|
||||
activeContainers.Clear();
|
||||
|
||||
// STEP 4: Remove animation effects from any no-longer-animated elems/attrs
|
||||
// STEP 4: Compare previous sample's compositors against this sample's.
|
||||
// (Transfer cached base values across, & remove animation effects from
|
||||
// no-longer-animated targets.)
|
||||
if (mLastCompositorTable) {
|
||||
// * Transfer over cached base values, from last sample's compositors
|
||||
currentCompositorTable->EnumerateEntries(TransferCachedBaseValue,
|
||||
mLastCompositorTable);
|
||||
|
||||
// * For each compositor in current sample's hash table, remove entry from
|
||||
// prev sample's hash table -- we don't need to clear animation
|
||||
// effects of those compositors, since they're still being animated.
|
||||
|
@ -351,8 +351,8 @@ nsSMILAnimationFunction::WillReplace() const
|
||||
* here we return false for to animation as it builds on the underlying value
|
||||
* unless its a frozen to animation.
|
||||
*/
|
||||
return !(IsAdditive() || IsToAnimation()) ||
|
||||
(IsToAnimation() && mIsFrozen && !mHasChanged);
|
||||
return !mErrorFlags && (!(IsAdditive() || IsToAnimation()) ||
|
||||
(IsToAnimation() && mIsFrozen && !mHasChanged));
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -78,22 +78,6 @@ nsSMILCompositor::AddAnimationFunction(nsSMILAnimationFunction* aFunc)
|
||||
}
|
||||
}
|
||||
|
||||
nsISMILAttr*
|
||||
nsSMILCompositor::CreateSMILAttr()
|
||||
{
|
||||
if (mKey.mIsCSS) {
|
||||
nsAutoString name;
|
||||
mKey.mAttributeName->ToString(name);
|
||||
nsCSSProperty propId = nsCSSProps::LookupProperty(name);
|
||||
if (nsSMILCSSProperty::IsPropertyAnimatable(propId)) {
|
||||
return new nsSMILCSSProperty(propId, mKey.mElement.get());
|
||||
}
|
||||
} else {
|
||||
return mKey.mElement->GetAnimatedAttr(mKey.mAttributeName);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILCompositor::ComposeAttribute()
|
||||
{
|
||||
@ -120,42 +104,29 @@ nsSMILCompositor::ComposeAttribute()
|
||||
|
||||
// THIRD: Step backwards through animation functions to find out
|
||||
// which ones we actually care about.
|
||||
PRBool changed = mForceCompositing;
|
||||
PRUint32 length = mAnimationFunctions.Length();
|
||||
PRUint32 i;
|
||||
for (i = length; i > 0; --i) {
|
||||
nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
|
||||
if (curAnimFunc->UpdateCachedTarget(mKey) ||
|
||||
(!changed && curAnimFunc->HasChanged())) {
|
||||
changed = PR_TRUE;
|
||||
}
|
||||
PRUint32 firstFuncToCompose = GetFirstFuncToAffectSandwich();
|
||||
|
||||
if (curAnimFunc->WillReplace()) {
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// NOTE: 'i' is now the index of the first animation function that we need
|
||||
// to use in compositing.
|
||||
|
||||
// if (!changed) // XXXdholbert Still need to enable this optimization
|
||||
// return;
|
||||
|
||||
// FOURTH: Compose animation functions (starting with base value)
|
||||
nsSMILValue resultValue = smilAttr->GetBaseValue();
|
||||
if (resultValue.IsNull()) {
|
||||
// FOURTH: Get & cache base value
|
||||
nsSMILValue sandwichResultValue = smilAttr->GetBaseValue();
|
||||
if (sandwichResultValue.IsNull()) {
|
||||
NS_WARNING("nsISMILAttr::GetBaseValue failed");
|
||||
return;
|
||||
}
|
||||
for (; i < length; ++i) {
|
||||
nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i];
|
||||
if (curAnimFunc) {
|
||||
curAnimFunc->ComposeResult(*smilAttr, resultValue);
|
||||
}
|
||||
UpdateCachedBaseValue(sandwichResultValue);
|
||||
|
||||
// if (!mForceCompositing) {
|
||||
// XXXdholbert Still need to enable this optimization
|
||||
// return;
|
||||
// }
|
||||
|
||||
// FIFTH: Compose animation functions
|
||||
PRUint32 length = mAnimationFunctions.Length();
|
||||
for (PRUint32 i = firstFuncToCompose; i < length; ++i) {
|
||||
mAnimationFunctions[i]->ComposeResult(*smilAttr, sandwichResultValue);
|
||||
}
|
||||
|
||||
// FIFTH: Set the animated value to the final composited result.
|
||||
nsresult rv = smilAttr->SetAnimValue(resultValue);
|
||||
// SIXTH: Set the animated value to the final composited result.
|
||||
nsresult rv = smilAttr->SetAnimValue(sandwichResultValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsISMILAttr::SetAnimValue failed");
|
||||
}
|
||||
@ -175,3 +146,54 @@ nsSMILCompositor::ClearAnimationEffects()
|
||||
smilAttr->ClearAnimValue();
|
||||
}
|
||||
|
||||
// Protected Helper Functions
|
||||
// --------------------------
|
||||
nsISMILAttr*
|
||||
nsSMILCompositor::CreateSMILAttr()
|
||||
{
|
||||
if (mKey.mIsCSS) {
|
||||
nsAutoString name;
|
||||
mKey.mAttributeName->ToString(name);
|
||||
nsCSSProperty propId = nsCSSProps::LookupProperty(name);
|
||||
if (nsSMILCSSProperty::IsPropertyAnimatable(propId)) {
|
||||
return new nsSMILCSSProperty(propId, mKey.mElement.get());
|
||||
}
|
||||
} else {
|
||||
return mKey.mElement->GetAnimatedAttr(mKey.mAttributeName);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsSMILCompositor::GetFirstFuncToAffectSandwich()
|
||||
{
|
||||
PRUint32 i;
|
||||
for (i = mAnimationFunctions.Length(); i > 0; --i) {
|
||||
nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
|
||||
if (curAnimFunc->UpdateCachedTarget(mKey) ||
|
||||
(!mForceCompositing && curAnimFunc->HasChanged())) {
|
||||
mForceCompositing = PR_TRUE;
|
||||
}
|
||||
|
||||
if (curAnimFunc->WillReplace()) {
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILCompositor::UpdateCachedBaseValue(const nsSMILValue& aBaseValue)
|
||||
{
|
||||
if (!mCachedBaseValue) {
|
||||
// We don't have last sample's base value cached. Assume it's changed.
|
||||
mCachedBaseValue = new nsSMILValue(aBaseValue);
|
||||
NS_WARN_IF_FALSE(mCachedBaseValue, "failed to cache base value (OOM?)");
|
||||
mForceCompositing = PR_TRUE;
|
||||
} else if (*mCachedBaseValue != aBaseValue) {
|
||||
// Base value has changed since last sample.
|
||||
*mCachedBaseValue = aBaseValue;
|
||||
mForceCompositing = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -95,10 +95,24 @@ public:
|
||||
// optimizations) when we hit ComposeAttribute.
|
||||
void ToggleForceCompositing() { mForceCompositing = PR_TRUE; }
|
||||
|
||||
// Transfers |aOther|'s mCachedBaseValue to |this|
|
||||
void StealCachedBaseValue(nsSMILCompositor* aOther) {
|
||||
mCachedBaseValue = aOther->mCachedBaseValue;
|
||||
}
|
||||
|
||||
private:
|
||||
// Create a nsISMILAttr for my target, on the heap. Caller is responsible
|
||||
// for deallocating the returned object.
|
||||
nsISMILAttr* CreateSMILAttr();
|
||||
|
||||
// Finds the index of the first function that will affect our animation
|
||||
// sandwich. Also toggles the 'mForceCompositing' flag if it finds that any
|
||||
// (used) functions have changed.
|
||||
PRUint32 GetFirstFuncToAffectSandwich();
|
||||
|
||||
// If the passed-in base value differs from our cached base value, this
|
||||
// method updates the cached value (and toggles the 'mForceCompositing' flag)
|
||||
void UpdateCachedBaseValue(const nsSMILValue& aBaseValue);
|
||||
|
||||
// Static callback methods
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) DoComposeAttribute(
|
||||
@ -107,11 +121,19 @@ public:
|
||||
// The hash key (tuple of element/attributeName/attributeType)
|
||||
KeyType mKey;
|
||||
|
||||
// Hash Value: List of animation functions that animate the specified
|
||||
// attribute
|
||||
// ---------------------------------------------------------------
|
||||
// Hash Value: List of animation functions that animate the specified attr
|
||||
nsTArray<nsSMILAnimationFunction*> mAnimationFunctions;
|
||||
|
||||
// Member data for detecting when we need to force-recompose
|
||||
// ---------------------------------------------------------
|
||||
// Flag for tracking whether we need to compose. Initialized to PR_FALSE, but
|
||||
// gets flipped to PR_TRUE if we detect that something has changed.
|
||||
PRPackedBool mForceCompositing;
|
||||
|
||||
// Cached base value, so we can detect & force-recompose when it changes
|
||||
// from one sample to the next. (nsSMILAnimationController copies this
|
||||
// forward from the previous sample's compositor.)
|
||||
nsAutoPtr<nsSMILValue> mCachedBaseValue;
|
||||
};
|
||||
|
||||
#endif // NS_SMILCOMPOSITOR_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user