From 8cc0fa17a42ae1dec75fe8ab00d5baa75e46499e Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Tue, 18 Oct 2011 13:07:37 -0700 Subject: Re-enable animations on the UI thread Using webkit to compute animations is still slow in some cases. When animating large elements, we seems to sometimes bogs the GPU, which then makes the UI takes longer to render a frame. This in turn slow the rate at which we can call into webkit (to update the position of the animated layers), which results in perceived stuttering. We previously had an implementation of CSS animations that could run fully on the UI thread, without having to call back into webkit. We turned it off because there was still some glitches, and calling into webkit seemed to work well enough -- but as we can see, even if that's the case in general, edge cases still benefit from running the animations outside of webkit. The CL fixes the remaining glitches we had (mostly, it was the non support of fillMode) and re-enable our CSS animations implementation. bug:5297559 Change-Id: I1f00bc060a76c9dfd55bd6d8ae85d5d6da68ddb5 --- .../platform/graphics/android/AndroidAnimation.cpp | 106 +++++++++------------ .../platform/graphics/android/AndroidAnimation.h | 15 +-- .../graphics/android/GraphicsLayerAndroid.cpp | 7 -- .../platform/graphics/android/LayerAndroid.cpp | 4 +- 4 files changed, 56 insertions(+), 76 deletions(-) (limited to 'Source/WebCore/platform/graphics') diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp index 2939cf0..5601269 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -28,12 +28,14 @@ #include "UnitBezier.h" #include - -#ifdef DEBUG - #include #include +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__) + +#ifdef DEBUG + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__) @@ -60,13 +62,13 @@ AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, double beginTime) : m_beginTime(beginTime) , m_duration(animation->duration()) - , m_finished(false) + , m_fillsBackwards(animation->fillsBackwards()) + , m_fillsForwards(animation->fillsForwards()) , m_iterationCount(animation->iterationCount()) , m_direction(animation->direction()) , m_timingFunction(animation->timingFunction()) , m_type(type) , m_operations(operations) - , m_originalLayer(0) { ASSERT(m_timingFunction); @@ -79,14 +81,14 @@ AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) : m_beginTime(anim->m_beginTime) , m_duration(anim->m_duration) - , m_finished(anim->m_finished) + , m_fillsBackwards(anim->m_fillsBackwards) + , m_fillsForwards(anim->m_fillsForwards) , m_iterationCount(anim->m_iterationCount) , m_direction(anim->m_direction) , m_timingFunction(anim->m_timingFunction) , m_name(anim->name()) , m_type(anim->m_type) , m_operations(anim->m_operations) - , m_originalLayer(0) { gDebugAndroidAnimationInstances++; } @@ -176,6 +178,37 @@ double AndroidAnimation::applyTimingFunction(float from, float to, double progre return fractionalTime; } +bool AndroidAnimation::evaluate(LayerAndroid* layer, double time) +{ + float progress; + if (!checkIterationsAndProgress(time, &progress) + && !(m_fillsBackwards || m_fillsForwards)) + return false; + + if (progress < 0) { + // The animation hasn't started yet + if (m_fillsBackwards) { + // in this case we want to apply the initial keyframe to the layer + applyForProgress(layer, 0); + } + // we still want to be evaluated until we get progress > 0 + return true; + } + + if (progress >= 1) { + if (!m_fillsForwards) + return false; + progress = 1; + } + + if (!m_operations->size()) + return false; + + applyForProgress(layer, progress); + + return true; +} + PassRefPtr AndroidOpacityAnimation::create( const Animation* animation, KeyframeValueList* operations, @@ -224,26 +257,9 @@ void AndroidAnimation::pickValues(double progress, int* start, int* end) *end = foundAt; } -bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) +void AndroidOpacityAnimation::applyForProgress(LayerAndroid* layer, float progress) { - float progress; - if (!checkIterationsAndProgress(time, &progress)) - return false; - - if (progress < 0) // we still want to be evaluated until we get progress > 0 - return true; - - if (progress >= 1) { - m_finished = true; - if (layer != m_originalLayer) - return false; - } - - if (!m_originalLayer) - m_originalLayer = layer; - // First, we need to get the from and to values - int from, to; pickValues(progress, &from, &to); FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from); @@ -260,13 +276,11 @@ bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) const TimingFunction* timingFunction = fromValue->timingFunction(); progress = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), progress, timingFunction); - float value = fromValue->value() + ((toValue->value() - fromValue->value()) * progress); - layer->setOpacity(value); - XLOG("AndroidOpacityAnimation::evaluate(%p, %p, %.2f) value=%.6f", this, layer, time, value); + float value = fromValue->value() + ((toValue->value() - fromValue->value()) * progress); - return true; + layer->setOpacity(value); } PassRefPtr AndroidTransformAnimation::create( @@ -294,39 +308,12 @@ PassRefPtr AndroidTransformAnimation::copy() return adoptRef(new AndroidTransformAnimation(this)); } -bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) +void AndroidTransformAnimation::applyForProgress(LayerAndroid* layer, float progress) { - float progress; - bool ret = true; - if (!checkIterationsAndProgress(time, &progress)) { - m_finished = true; - ret = false; - } - - if (progress < 0) // we still want to be evaluated until we get progress > 0 - return true; - - if (progress >= 1) { - m_finished = true; - if (layer != m_originalLayer) - return false; - } - - if (!m_originalLayer) - m_originalLayer = layer; - - IntSize size(layer->getSize().width(), layer->getSize().height()); - TransformationMatrix matrix; - XLOG("Evaluate transforms animations, %d operations, progress %.2f for layer %d (%d, %d)" - , m_operations->size(), progress, layer->uniqueId(), size.width(), size.height()); - - if (!m_operations->size()) - return false; - // First, we need to get the from and to values - int from, to; pickValues(progress, &from, &to); + TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from); TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to); @@ -364,6 +351,7 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) } } + IntSize size(layer->getSize().width(), layer->getSize().height()); if (valid) { for (size_t i = 0; i < toValue->value()->size(); ++i) toValue->value()->operations()[i]->blend(fromValue->value()->at(i), @@ -379,8 +367,6 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) // Set the final transform on the layer layer->setTransform(transformMatrix); - - return ret; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/AndroidAnimation.h index 68caeb9..16a63e8 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.h @@ -48,25 +48,28 @@ public: bool checkIterationsAndProgress(double time, float* finalProgress); double applyTimingFunction(float from, float to, double progress, const TimingFunction* timingFunction); - virtual bool evaluate(LayerAndroid* layer, double time) = 0; + bool evaluate(LayerAndroid* layer, double time); + virtual void applyForProgress(LayerAndroid* layer, float progress) = 0; static long instancesCount(); void setName(const String& name) { m_name = name; } String name() { return m_name; } AnimatedPropertyID type() { return m_type; } - bool finished() { return m_finished; } + bool fillsBackwards() { return m_fillsBackwards; } + bool fillsForwards() { return m_fillsForwards; } + protected: double m_beginTime; double m_elapsedTime; double m_duration; - bool m_finished; + bool m_fillsBackwards; + bool m_fillsForwards; int m_iterationCount; int m_direction; RefPtr m_timingFunction; String m_name; AnimatedPropertyID m_type; KeyframeValueList* m_operations; - LayerAndroid* m_originalLayer; }; class AndroidOpacityAnimation : public AndroidAnimation { @@ -80,7 +83,7 @@ public: AndroidOpacityAnimation(AndroidOpacityAnimation* anim); virtual PassRefPtr copy(); - virtual bool evaluate(LayerAndroid* layer, double time); + virtual void applyForProgress(LayerAndroid* layer, float progress); }; class AndroidTransformAnimation : public AndroidAnimation { @@ -96,7 +99,7 @@ public: AndroidTransformAnimation(AndroidTransformAnimation* anim); virtual PassRefPtr copy(); - virtual bool evaluate(LayerAndroid* layer, double time); + virtual void applyForProgress(LayerAndroid* layer, float progress); }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 89f96d8..6cb9288 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -692,13 +692,6 @@ bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList, const String& keyframesName, double beginTime) { - // For now, let webkit deals with the animations -- the current UI-side - // animation code has some annoying bugs, and we improved communication - // between webkit and UI enough that performance-wise it's not so much - // a problem to let webkit do everything. - // TODO: re-enable UI-side animations - return false; - if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) return false; diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 4a0e2bb..d4a1225 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -227,9 +227,7 @@ bool LayerAndroid::evaluateAnimations(double time) gDebugNbAnims++; nbAnims++; LayerAndroid* currentLayer = const_cast(this); - if (!(it->second)->finished() && - (it->second)->evaluate(currentLayer, time)) - m_hasRunningAnimations = true; + m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time); } return hasRunningAnimations || m_hasRunningAnimations; -- cgit v1.1