diff options
Diffstat (limited to 'Source/WebCore')
10 files changed, 106 insertions, 57 deletions
diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp index 5601269..245d2f1 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -49,6 +49,8 @@ namespace WebCore { +static int gUniqueId; + static long gDebugAndroidAnimationInstances; long AndroidAnimation::instancesCount() @@ -69,12 +71,11 @@ AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, , m_timingFunction(animation->timingFunction()) , m_type(type) , m_operations(operations) + , m_uniqueId(++gUniqueId) + , m_hasFinished(false) { ASSERT(m_timingFunction); - if (!static_cast<int>(beginTime)) // time not set - m_beginTime = WTF::currentTime(); - gDebugAndroidAnimationInstances++; } @@ -89,6 +90,8 @@ AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) , m_name(anim->name()) , m_type(anim->m_type) , m_operations(anim->m_operations) + , m_uniqueId(anim->m_uniqueId) + , m_hasFinished(anim->m_hasFinished) { gDebugAndroidAnimationInstances++; } @@ -98,20 +101,24 @@ AndroidAnimation::~AndroidAnimation() gDebugAndroidAnimationInstances--; } -double AndroidAnimation::elapsedTime(double time) +void AndroidAnimation::suggestBeginTime(double time) { - if (m_beginTime <= 0.000001) // overflow or not correctly set + if (m_beginTime <= 0.000001) // overflow or not yet set m_beginTime = time; +} - m_elapsedTime = time - m_beginTime; +double AndroidAnimation::elapsedTime(double time) +{ + suggestBeginTime(time); + double elapsedTime = time - m_beginTime; if (m_duration <= 0) m_duration = 0.000001; - if (m_elapsedTime < 0) // animation not yet started. + if (elapsedTime < 0) // animation not yet started. return 0; - return m_elapsedTime; + return elapsedTime; } bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress) @@ -127,6 +134,13 @@ bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgr // If not infinite, return false if we are done if (m_iterationCount > 0 && progress > dur) { *finalProgress = 1.0; + if (!m_hasFinished) { + // first time past duration, continue with progress 1.0 so the + // element's final position lines up with it's last keyframe + m_hasFinished = true; + return true; + } + return false; } @@ -195,7 +209,7 @@ bool AndroidAnimation::evaluate(LayerAndroid* layer, double time) return true; } - if (progress >= 1) { + if (progress > 1) { if (!m_fillsForwards) return false; progress = 1; diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/AndroidAnimation.h index 16a63e8..52cef4e 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.h @@ -43,6 +43,7 @@ public: virtual ~AndroidAnimation(); virtual PassRefPtr<AndroidAnimation> copy() = 0; + void suggestBeginTime(double time); double elapsedTime(double time); void pickValues(double progress, int* start, int* end); bool checkIterationsAndProgress(double time, float* finalProgress); @@ -56,11 +57,12 @@ public: AnimatedPropertyID type() { return m_type; } bool fillsBackwards() { return m_fillsBackwards; } bool fillsForwards() { return m_fillsForwards; } + int uniqueId() { return m_uniqueId; } + double beginTime() { return m_beginTime; } protected: double m_beginTime; - double m_elapsedTime; double m_duration; bool m_fillsBackwards; bool m_fillsForwards; @@ -70,6 +72,8 @@ protected: String m_name; AnimatedPropertyID m_type; KeyframeValueList* m_operations; + int m_uniqueId; + bool m_hasFinished; }; class AndroidOpacityAnimation : public AndroidAnimation { diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index a33c3d0..5227a8f 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -84,9 +84,9 @@ GLWebViewState::GLWebViewState() , m_goingLeft(false) , m_expandedTileBoundsX(0) , m_expandedTileBoundsY(0) + , m_highEndGfx(false) , m_scale(1) , m_layersRenderingMode(kAllTextures) - , m_highEndGfx(false) { m_viewport.setEmpty(); m_futureViewportTileBounds.setEmpty(); @@ -431,7 +431,8 @@ void GLWebViewState::fullInval() bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, - IntRect& clip, float scale, bool* buffersSwappedPtr) + IntRect& clip, float scale, + bool* treesSwappedPtr, bool* newTreeHasAnimPtr) { m_scale = scale; TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft, @@ -488,7 +489,8 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering; ret |= m_treeManager.drawGL(currentTime, rect, viewport, scale, fastSwap, - buffersSwappedPtr, &nbTexturesNeeded); + treesSwappedPtr, newTreeHasAnimPtr, + &nbTexturesNeeded); if (!ret) resetFrameworkInval(); diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 2a6c8df..cffd28f 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -214,7 +214,8 @@ public: bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, - IntRect& clip, float scale, bool* buffersSwappedPtr); + IntRect& clip, float scale, + bool* treesSwappedPtr, bool* newTreeHasAnimPtr); #ifdef MEASURES_PERF void dumpMeasures(); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 3e062f8..741b9e4 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -331,6 +331,9 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size) void GraphicsLayerAndroid::setBackfaceVisibility(bool b) { + if (b == m_backfaceVisibility) + return; + GraphicsLayer::setBackfaceVisibility(b); m_contentLayer->setBackfaceVisibility(b); askForSync(); @@ -397,7 +400,7 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent) void GraphicsLayerAndroid::setBackgroundColor(const Color& color) { - if (color == m_backgroundColor) + if (color == m_backgroundColor && m_backgroundColorSet) return; LOG("(%x) setBackgroundColor", this); GraphicsLayer::setBackgroundColor(color); @@ -409,6 +412,9 @@ void GraphicsLayerAndroid::setBackgroundColor(const Color& color) void GraphicsLayerAndroid::clearBackgroundColor() { + if (!m_backgroundColorSet) + return; + LOG("(%x) clearBackgroundColor", this); GraphicsLayer::clearBackgroundColor(); askForSync(); diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 859973a..86991d5 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -879,6 +879,12 @@ void LayerAndroid::setIsDrawing(bool isDrawing) m_texture->setDrawingLayer(isDrawing ? this : 0); m_texture->clearPaintingLayer(); } + + // tell auto-initializing animations to start now + KeyframesMap::const_iterator localBegin = m_animations.begin(); + KeyframesMap::const_iterator localEnd = m_animations.end(); + for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt) + (localIt->second)->suggestBeginTime(WTF::currentTime()); } void LayerAndroid::setIsPainting(Layer* drawingTree) @@ -889,7 +895,34 @@ void LayerAndroid::setIsPainting(Layer* drawingTree) for (int i = 0; i < count; i++) this->getChild(i)->setIsPainting(drawingTree); - obtainTextureForPainting(static_cast<LayerAndroid*>(drawingTree)); + + LayerAndroid* drawingLayer = 0; + if (drawingTree) + drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId()); + + copyAnimationStartTimes(drawingLayer); + obtainTextureForPainting(drawingLayer); +} + +void LayerAndroid::copyAnimationStartTimes(LayerAndroid* oldLayer) +{ + if (!oldLayer) + return; + + // copy animation start times, if applicable + KeyframesMap::const_iterator localBegin = m_animations.begin(); + KeyframesMap::const_iterator localEnd = m_animations.end(); + for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt) { + KeyframesMap::const_iterator oldBegin = oldLayer->m_animations.begin(); + KeyframesMap::const_iterator oldEnd = oldLayer->m_animations.end(); + for (KeyframesMap::const_iterator oldIt = oldBegin; oldIt != oldEnd; ++oldIt) { + if ((localIt->second)->uniqueId() == (oldIt->second)->uniqueId()) { + // animations are identical, try to copy start time of the old + // one, which will have been initialized some time in the past + (localIt->second)->suggestBeginTime((oldIt->second)->beginTime()); + } + } + } } void LayerAndroid::mergeInvalsInto(Layer* replacementTree) @@ -960,7 +993,7 @@ bool LayerAndroid::updateWithLayer(LayerAndroid* layer) return false; } -void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingTree) +void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer) { if (!needsTexture()) return; @@ -976,12 +1009,9 @@ void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingTree) m_texture = 0; } } else { - if (drawingTree) { - LayerAndroid* drawingLayer = drawingTree->findById(uniqueId()); - if (drawingLayer) { - // if a previous tree had the same layer, paint with that painted surface - m_texture = drawingLayer->m_texture; - } + if (drawingLayer) { + // if a previous tree had the same layer, paint with that painted surface + m_texture = drawingLayer->m_texture; } if (!m_texture) diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index ae9dc88..8b82b27 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -290,7 +290,7 @@ public: friend void android::cleanupImageRefs(LayerAndroid* layer); PaintedSurface* texture() { return m_texture; } - void obtainTextureForPainting(LayerAndroid* drawingTree); + void obtainTextureForPainting(LayerAndroid* drawingLayer); // Update layers using another tree. Only works for basic properties // such as the position, the transform. Return true if anything more @@ -323,6 +323,7 @@ private: friend class CachedLayer::Debug; // debugging access only #endif + void copyAnimationStartTimes(LayerAndroid* oldLayer); void findInner(FindState&) const; bool prepareContext(bool force = false); void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const; diff --git a/Source/WebCore/platform/graphics/android/TreeManager.cpp b/Source/WebCore/platform/graphics/android/TreeManager.cpp index 5fd3b7c..fe55df8 100644 --- a/Source/WebCore/platform/graphics/android/TreeManager.cpp +++ b/Source/WebCore/platform/graphics/android/TreeManager.cpp @@ -132,6 +132,10 @@ void TreeManager::clearTrees() // or start painting it if we aren't void TreeManager::updateWithTree(Layer* newTree, bool brandNew) { + XLOG("updateWithTree - %p, has children %d, has animations %d", + newTree, newTree && newTree->countChildren(), + newTree && newTree->countChildren() + ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0); // can't have a queued tree unless have a painting tree too ASSERT(m_paintingTree || !m_queuedTree); @@ -143,10 +147,6 @@ void TreeManager::updateWithTree(Layer* newTree, bool brandNew) if (!newTree || brandNew) { clearTrees(); if (brandNew) { - m_animationOffset = 0; - m_isAnimating = false; - m_lastFrameTime = WTF::currentTime(); - m_paintingTree = newTree; m_paintingTree->setIsPainting(m_drawingTree); } @@ -159,6 +159,11 @@ void TreeManager::updateWithTree(Layer* newTree, bool brandNew) // have a queued tree, copy over invals so the regions are // eventually repainted m_queuedTree->mergeInvalsInto(newTree); + + XLOG("DISCARDING tree - %p, has children %d, has animations %d", + newTree, newTree && newTree->countChildren(), + newTree && newTree->countChildren() + ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0); } SkSafeUnref(m_queuedTree); m_queuedTree = newTree; @@ -172,7 +177,7 @@ void TreeManager::updateWithTree(Layer* newTree, bool brandNew) bool TreeManager::drawGL(double currentTime, IntRect& viewRect, SkRect& visibleRect, float scale, - bool enterFastSwapMode, bool* buffersSwappedPtr, + bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr, TexturesResult* texturesResultPtr) { m_fastSwapMode |= enterFastSwapMode; @@ -185,17 +190,20 @@ bool TreeManager::drawGL(double currentTime, IntRect& viewRect, if (m_paintingTree) { ret |= m_paintingTree->prepare(currentTime, viewRect, visibleRect, scale); + LayerAndroid* laTree = 0; if (m_paintingTree->countChildren()) { - LayerAndroid* laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0)); + laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0)); laTree->computeTexturesAmount(texturesResultPtr); } if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) { XLOG("have painting tree %p ready, swapping!", m_paintingTree); didTreeSwap = true; swap(); - if (buffersSwappedPtr) - *buffersSwappedPtr = true; + if (treesSwappedPtr) + *treesSwappedPtr = true; + if (laTree && newTreeHasAnimPtr) + *newTreeHasAnimPtr = laTree->hasAnimations(); } } else if (m_drawingTree) { XLOG("preparing drawing tree %p", m_drawingTree); @@ -207,17 +215,11 @@ bool TreeManager::drawGL(double currentTime, IntRect& viewRect, } } - if (!m_isAnimating) { - m_animationOffset += currentTime - m_lastFrameTime; -#ifdef ANIM_DEBUG - XLOGC("adding to %f", m_animationOffset); -#endif - } if (m_drawingTree) { bool drawingReady = didTreeSwap || m_drawingTree->isReady(); - if (drawingReady || m_fastSwapMode) + if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree)) m_drawingTree->swapTiles(); if (drawingReady) { @@ -229,18 +231,8 @@ bool TreeManager::drawGL(double currentTime, IntRect& viewRect, } if (m_drawingTree->countChildren()) { -#ifdef ANIM_DEBUG - XLOGC("drawing tree %p with animation time offset of %f, locked %d", - m_drawingTree, m_animationOffset, m_isAnimating); -#endif LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0)); - m_isAnimating = laTree->evaluateAnimations(currentTime - m_animationOffset); - if (!m_isAnimating) - m_animationOffset = 0; - ret |= m_isAnimating; - } else if (!m_paintingTree) { - m_animationOffset = 0; - m_isAnimating = false; + ret |= laTree->evaluateAnimations(currentTime); } XLOG("drawing tree %p", m_drawingTree); ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale); @@ -250,8 +242,6 @@ bool TreeManager::drawGL(double currentTime, IntRect& viewRect, m_paintingTree->state()->drawBackground(defaultBackground); } - m_lastFrameTime = currentTime; - if (m_paintingTree) { XLOG("still have painting tree %p", m_paintingTree); return true; diff --git a/Source/WebCore/platform/graphics/android/TreeManager.h b/Source/WebCore/platform/graphics/android/TreeManager.h index 09b1bd9..d2e10c8 100644 --- a/Source/WebCore/platform/graphics/android/TreeManager.h +++ b/Source/WebCore/platform/graphics/android/TreeManager.h @@ -48,7 +48,7 @@ public: bool drawGL(double currentTime, IntRect& viewRect, SkRect& visibleRect, float scale, - bool enterFastSwapMode, bool* buffersSwappedPtr, + bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr, TexturesResult* texturesResultPtr); void drawCanvas(SkCanvas* canvas, bool drawLayers); @@ -70,10 +70,6 @@ private: Layer* m_queuedTree; bool m_fastSwapMode; - - double m_animationOffset; - double m_lastFrameTime; - bool m_isAnimating; }; } // namespace WebCore diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp index 85c57a6..06fa0f6 100644 --- a/Source/WebCore/rendering/RenderLayerCompositor.cpp +++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp @@ -1578,7 +1578,12 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* render return false; if (AnimationController* animController = renderer->animation()) { +#if PLATFORM(ANDROID) + // android renders an opacity animation much faster if it's composited + return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity)) +#else return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode()) +#endif || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform); } return false; |