[WK2][Qt] Move Accelerated Composite animations to UIProcess
authorigor.oliveira@openbossa.org <igor.oliveira@openbossa.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Nov 2011 02:23:32 +0000 (02:23 +0000)
committerigor.oliveira@openbossa.org <igor.oliveira@openbossa.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Nov 2011 02:23:32 +0000 (02:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=72753

Source/WebCore:

Add helper method to synchronize animations in TextureMapper.

Reviewed by Noam Rosenthal.

* platform/graphics/texmap/TextureMapperNode.cpp:
(WebCore::TextureMapperNode::syncAnimationsRecursively):
* platform/graphics/texmap/TextureMapperNode.h:

Source/WebKit2:

Currently, all the accelerated compositing animations are applied in WebProcess and
for each frame generated, WebProcess needs to sync with UIProcess.

This patch moves the accelerated compositing animations to UIProcess reducing the
amount of synchronization messages between WebProcess and UIProcess, this is done
sending animations information to UIProcess.

Reviewed by Noam Rosenthal.

* Shared/WebCoreArgumentCoders.cpp:
(CoreIPC::::encode):
(CoreIPC::::decode):

Encode/Decode RefPtr<Animation> instead of Animation class. This facilitates
the data serialization.

* Shared/WebCoreArgumentCoders.h:
* Shared/WebLayerTreeInfo.cpp:
(WebKit::WebLayerInfo::encode):
(WebKit::WebLayerInfo::decode):
(WebKit::WebLayerAnimation::encode):
(WebKit::WebLayerAnimation::decode):

Create WebLayerAnimation struct, it is used to send animation information
to UIProcess.

* Shared/WebLayerTreeInfo.h:
(WebKit::WebLayerAnimation::WebLayerAnimation):
* UIProcess/LayerTreeHostProxy.h:
* UIProcess/qt/LayerTreeHostProxyQt.cpp:
(WebKit::LayerTreeHostProxy::LayerTreeHostProxy):
(WebKit::LayerTreeHostProxy::paintToCurrentGLContext):
(WebKit::LayerTreeHostProxy::updateSceneGraphUpdateTimerFired):
(WebKit::LayerTreeHostProxy::syncLayerParameters):
* WebProcess/WebCoreSupport/WebGraphicsLayer.cpp:
(WebCore::WebGraphicsLayer::addAnimation):
(WebCore::WebGraphicsLayer::pauseAnimation):
(WebCore::WebGraphicsLayer::removeAnimation):
(WebCore::WebGraphicsLayer::syncCompositingStateForThisLayerOnly):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@100834 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperNode.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/Shared/WebLayerTreeInfo.cpp
Source/WebKit2/Shared/WebLayerTreeInfo.h
Source/WebKit2/UIProcess/LayerTreeHostProxy.h
Source/WebKit2/UIProcess/qt/LayerTreeHostProxyQt.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebGraphicsLayer.cpp

index 65c65cd24ba6bd02f26082df294e3451760eca8d..d54c0003fa73583a638de01ccf1919aab4ebee45 100644 (file)
@@ -1,3 +1,16 @@
+2011-11-18  Igor Oliveira  <igor.oliveira@openbossa.org>
+
+        [WK2][Qt] Move Accelerated Composite animations to UIProcess
+        https://bugs.webkit.org/show_bug.cgi?id=72753
+
+        Add helper method to synchronize animations in TextureMapper.
+
+        Reviewed by Noam Rosenthal.
+
+        * platform/graphics/texmap/TextureMapperNode.cpp:
+        (WebCore::TextureMapperNode::syncAnimationsRecursively):
+        * platform/graphics/texmap/TextureMapperNode.h:
+
 2011-11-18  Scott Graham  <scottmg@chromium.org>
 
         IDL changes for gamepad support
index ab597031f0dd7825a42a7c83e2478eb7d090ca94..0af8d734fa3dbb2acf40a56442ce5722689b3f3b 100644 (file)
@@ -984,6 +984,16 @@ void TextureMapperNode::syncAnimations(GraphicsLayerTextureMapper* layer)
     }
 }
 
+void TextureMapperNode::syncAnimationsRecursively()
+{
+    syncAnimations(0);
+
+    computeAllTransforms();
+
+    for (int i = m_children.size() - 1; i >= 0; --i)
+        m_children[i]->syncAnimationsRecursively();
+}
+
 void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options)
 {
     if (graphicsLayer && !(options & ComputationsOnly)) {
index 4a4fcfff13b0bbc5b33e2201e09527de3eac0330..eb9c692e5b8ae1937f4d6565dbab0cf8db10d926 100644 (file)
@@ -141,6 +141,7 @@ public:
 
     void syncCompositingState(GraphicsLayerTextureMapper*, int syncOptions = 0);
     void syncCompositingState(GraphicsLayerTextureMapper*, TextureMapper*, int syncOptions = 0);
+    void syncAnimationsRecursively();
     IntSize size() const { return IntSize(m_size.width(), m_size.height()); }
     void setTransform(const TransformationMatrix&);
     void setOpacity(float value) { m_opacity = value; }
index 1b13ed946b282b4e91d89b2e57233914b7eceb62..120e496383f21e0e4bfef41333e2ea1d16a70f9b 100644 (file)
@@ -1,3 +1,48 @@
+2011-11-18  Igor Oliveira  <igor.oliveira@openbossa.org>
+
+        [WK2][Qt] Move Accelerated Composite animations to UIProcess
+        https://bugs.webkit.org/show_bug.cgi?id=72753
+
+        Currently, all the accelerated compositing animations are applied in WebProcess and
+        for each frame generated, WebProcess needs to sync with UIProcess.
+
+        This patch moves the accelerated compositing animations to UIProcess reducing the
+        amount of synchronization messages between WebProcess and UIProcess, this is done
+        sending animations information to UIProcess.
+
+        Reviewed by Noam Rosenthal.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (CoreIPC::::encode):
+        (CoreIPC::::decode):
+
+        Encode/Decode RefPtr<Animation> instead of Animation class. This facilitates
+        the data serialization.
+
+        * Shared/WebCoreArgumentCoders.h:
+        * Shared/WebLayerTreeInfo.cpp:
+        (WebKit::WebLayerInfo::encode):
+        (WebKit::WebLayerInfo::decode):
+        (WebKit::WebLayerAnimation::encode):
+        (WebKit::WebLayerAnimation::decode):
+
+        Create WebLayerAnimation struct, it is used to send animation information
+        to UIProcess.
+
+        * Shared/WebLayerTreeInfo.h:
+        (WebKit::WebLayerAnimation::WebLayerAnimation):
+        * UIProcess/LayerTreeHostProxy.h:
+        * UIProcess/qt/LayerTreeHostProxyQt.cpp:
+        (WebKit::LayerTreeHostProxy::LayerTreeHostProxy):
+        (WebKit::LayerTreeHostProxy::paintToCurrentGLContext):
+        (WebKit::LayerTreeHostProxy::updateSceneGraphUpdateTimerFired):
+        (WebKit::LayerTreeHostProxy::syncLayerParameters):
+        * WebProcess/WebCoreSupport/WebGraphicsLayer.cpp:
+        (WebCore::WebGraphicsLayer::addAnimation):
+        (WebCore::WebGraphicsLayer::pauseAnimation):
+        (WebCore::WebGraphicsLayer::removeAnimation):
+        (WebCore::WebGraphicsLayer::syncCompositingStateForThisLayerOnly):
+
 2011-11-18  Beth Dakin  <bdakin@apple.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=72551
index 05a629fa322b59ff434714c5acb0a753884f88dd..73ae86abebd0bd9e24c988815123eaed8d95aab5 100644 (file)
@@ -647,7 +647,6 @@ bool ArgumentCoder<Length>::decode(ArgumentDecoder* decoder, Length& length)
     return SimpleArgumentCoder<Length>::decode(decoder, length);
 }
 
-
 void ArgumentCoder<TransformationMatrix>::encode(ArgumentEncoder* encoder, const TransformationMatrix& transformationMatrix)
 {
     SimpleArgumentCoder<TransformationMatrix>::encode(encoder, transformationMatrix);
@@ -1062,18 +1061,18 @@ static void encodeBoolAndEnumValue(ArgumentEncoder* encoder, bool isSet, T value
         encoder->encodeEnum(value);
 }
 
-void ArgumentCoder<Animation>::encode(ArgumentEncoder* encoder, const Animation& animation)
+void ArgumentCoder<RefPtr<Animation> >::encode(ArgumentEncoder* encoder, const RefPtr<Animation>& animation)
 {
-    encodeBoolAndValue(encoder, animation.isDelaySet(), animation.delay());
-    encodeBoolAndEnumValue(encoder, animation.isDirectionSet(), animation.direction());
-    encodeBoolAndValue(encoder, animation.isDurationSet(), animation.duration());
-    encodeBoolAndValue(encoder, animation.isFillModeSet(), animation.fillMode());
-    encodeBoolAndValue(encoder, animation.isIterationCountSet(), animation.iterationCount());
-    encodeBoolAndValue(encoder, animation.isNameSet(), animation.name());
-    encodeBoolAndEnumValue(encoder, animation.isPlayStateSet(), animation.playState());
-    encodeBoolAndValue(encoder, animation.isPropertySet(), animation.property());
-    encodeBoolAndValue<RefPtr<TimingFunction> >(encoder, animation.isTimingFunctionSet(), animation.timingFunction());
-    encoder->encodeBool(animation.isNoneAnimation());
+    encodeBoolAndValue(encoder, animation->isDelaySet(), animation->delay());
+    encodeBoolAndEnumValue(encoder, animation->isDirectionSet(), animation->direction());
+    encodeBoolAndValue(encoder, animation->isDurationSet(), animation->duration());
+    encodeBoolAndValue(encoder, animation->isFillModeSet(), animation->fillMode());
+    encodeBoolAndValue(encoder, animation->isIterationCountSet(), animation->iterationCount());
+    encodeBoolAndValue(encoder, animation->isNameSet(), animation->name());
+    encodeBoolAndEnumValue(encoder, animation->isPlayStateSet(), animation->playState());
+    encodeBoolAndValue(encoder, animation->isPropertySet(), animation->property());
+    encodeBoolAndValue<RefPtr<TimingFunction> >(encoder, animation->isTimingFunctionSet(), animation->timingFunction());
+    encoder->encodeBool(animation->isNoneAnimation());
 }
 
 
@@ -1099,7 +1098,7 @@ static bool decodeBoolAndEnumValue(ArgumentDecoder* decoder, bool& isSet, T& val
     return decoder->decodeEnum(value);
 }
 
-bool ArgumentCoder<Animation>::decode(ArgumentDecoder* decoder, Animation& animation)
+bool ArgumentCoder<RefPtr<Animation> >::decode(ArgumentDecoder* decoder, RefPtr<Animation>& animation)
 {
     bool isDelaySet, isDirectionSet, isDurationSet, isFillModeSet, isIterationCountSet, isNameSet, isPlayStateSet, isPropertySet, isTimingFunctionSet;
     int property, iterationCount, fillMode;
@@ -1107,8 +1106,6 @@ bool ArgumentCoder<Animation>::decode(ArgumentDecoder* decoder, Animation& anima
     RefPtr<TimingFunction> timingFunction;
     String name;
 
-    animation.clearAll();
-
     double delay;
     if (!decodeBoolAndValue(decoder, isDelaySet, delay))
         return false;
@@ -1133,24 +1130,27 @@ bool ArgumentCoder<Animation>::decode(ArgumentDecoder* decoder, Animation& anima
     if (!decodeBoolAndValue<RefPtr<TimingFunction> >(decoder, isTimingFunctionSet, timingFunction))
         return false;
 
+    animation = Animation::create();
+    animation->clearAll();
+
     if (isDelaySet)
-        animation.setDelay(delay);
+        animation->setDelay(delay);
     if (isDirectionSet)
-        animation.setDirection(direction);
+        animation->setDirection(direction);
     if (isDurationSet)
-        animation.setDuration(duration);
+        animation->setDuration(duration);
     if (isFillModeSet)
-        animation.setFillMode(fillMode);
+        animation->setFillMode(fillMode);
     if (isIterationCountSet)
-        animation.setIterationCount(iterationCount);
+        animation->setIterationCount(iterationCount);
     if (isNameSet)
-        animation.setName(name);
+        animation->setName(name);
     if (isPlayStateSet)
-        animation.setPlayState(playState);
+        animation->setPlayState(playState);
     if (isPropertySet)
-        animation.setProperty(property);
+        animation->setProperty(property);
     if (isTimingFunctionSet)
-        animation.setTimingFunction(timingFunction);
+        animation->setTimingFunction(timingFunction);
 
     return true;
 }
index 17e0d90c63ac6cba689c95877140ca150b05dee6..055041f9506cce0eb579c5e9a81a81dfd640ac7f 100644 (file)
@@ -288,9 +288,9 @@ template<> struct ArgumentCoder<WebCore::TransformOperations> {
     static bool decode(ArgumentDecoder*, WebCore::TransformOperations&);
 };
 
-template<> struct ArgumentCoder<WebCore::Animation> {
-    static void encode(ArgumentEncoder*, const WebCore::Animation&);
-    static bool decode(ArgumentDecoder*, WebCore::Animation&);
+template<> struct ArgumentCoder<RefPtr<WebCore::Animation> > {
+    static void encode(ArgumentEncoder*, const RefPtr<WebCore::Animation>&);
+    static bool decode(ArgumentDecoder*, RefPtr<WebCore::Animation>&);
 };
 #endif
 
index edb62a250086427077843d9a171bd61168650284..a579515f732450802e7cfcd9f6ce1c841b33b6b0 100644 (file)
@@ -35,7 +35,7 @@ void WebLayerInfo::encode(CoreIPC::ArgumentEncoder* encoder) const
 {
     // We have to divide it to several lines, because CoreIPC::In/Out takes a maximum of 10 arguments.
     encoder->encode(CoreIPC::In(id, name, parent, children, flags, replica, mask, imageBackingStoreID));
-    encoder->encode(CoreIPC::In(pos, size, transform, opacity, anchorPoint, childrenTransform, contentsRect));
+    encoder->encode(CoreIPC::In(pos, size, transform, opacity, anchorPoint, childrenTransform, contentsRect, animations));
 }
 
 bool WebLayerInfo::decode(CoreIPC::ArgumentDecoder* decoder, WebLayerInfo& info)
@@ -43,8 +43,9 @@ bool WebLayerInfo::decode(CoreIPC::ArgumentDecoder* decoder, WebLayerInfo& info)
     // We have to divide it to several lines, because CoreIPC::In/Out takes a maximum of 10 arguments.
     if (!decoder->decode(CoreIPC::Out(info.id, info.name, info.parent, info.children, info.flags, info.replica, info.mask, info.imageBackingStoreID)))
         return false;
-    if (!decoder->decode(CoreIPC::Out(info.pos, info.size, info.transform, info.opacity, info.anchorPoint, info.childrenTransform, info.contentsRect)))
+    if (!decoder->decode(CoreIPC::Out(info.pos, info.size, info.transform, info.opacity, info.anchorPoint, info.childrenTransform, info.contentsRect, info.animations)))
         return false;
+
     return true;
 }
 
@@ -68,5 +69,24 @@ bool WebLayerUpdateInfo::decode(CoreIPC::ArgumentDecoder* decoder, WebLayerUpdat
     return decoder->decode(CoreIPC::Out(info.layerID, info.rect, info.bitmapHandle));
 }
 
+void WebLayerAnimation::encode(CoreIPC::ArgumentEncoder* encoder) const
+{
+    encoder->encodeEnum(operation);
+    encoder->encode(keyframeList);
+    encoder->encode(CoreIPC::In(name, startTime, boxSize, animation, keyframeList));
+}
+
+bool WebLayerAnimation::decode(CoreIPC::ArgumentDecoder* decoder, WebLayerAnimation& info)
+{
+    if (!decoder->decodeEnum(info.operation))
+        return false;
+    if (!decoder->decode(info.keyframeList))
+        return false;
+    if (!decoder->decode(CoreIPC::Out(info.name, info.startTime, info.boxSize, info.animation)))
+        return false;
+
+    return true;
+}
+
 }
 #endif
index 25003e743c61c33c0292203ef76f3f46e69d27d6..56a4f6414c4add3dc68e911f34bf021b0581da43 100644 (file)
@@ -49,6 +49,25 @@ struct WebLayerUpdateInfo {
     static bool decode(CoreIPC::ArgumentDecoder*, WebLayerUpdateInfo&);
 };
 
+struct WebLayerAnimation {
+    WebLayerAnimation() : keyframeList(AnimatedPropertyInvalid) { }
+    WebLayerAnimation(const KeyframeValueList& valueList) 
+        : keyframeList(valueList) { }
+    String name;
+    enum Operation {
+        AddAnimation,
+        RemoveAnimation,
+        PauseAnimation
+    } operation;
+    IntSize boxSize;
+    RefPtr<Animation> animation;
+    KeyframeValueList keyframeList;
+    double startTime;
+
+    void encode(CoreIPC::ArgumentEncoder*) const;
+    static bool decode(CoreIPC::ArgumentDecoder*, WebLayerAnimation&);
+};
+
 struct WebLayerInfo {
     String name;
     WebLayerID id;
@@ -79,6 +98,7 @@ struct WebLayerInfo {
         unsigned int flags;
     };
     Vector<WebLayerID> children;
+    Vector<WebLayerAnimation> animations;
     RefPtr<ShareableBitmap> imageBackingStore;
 
     void encode(CoreIPC::ArgumentEncoder*) const;
index 45e8df6635cdcec90446a3de0232ba483d6ebd12..9ce0dd915966d3aec7fd792f053f512eb40dadff 100644 (file)
@@ -125,6 +125,11 @@ protected:
     OwnPtr<GraphicsLayer> m_rootLayer;
     Vector<WebLayerID> m_layersToDelete;
 
+#if PLATFORM(QT)
+    void didFireViewportUpdateTimer(Timer<LayerTreeHostProxy>*);
+    Timer<LayerTreeHostProxy> m_viewportUpdateTimer;
+#endif
+
     LayerMap m_layers;
     WebLayerID m_rootLayerID;
     int m_id;
index 0c036e4f3acf313aa76dc7483967f6c5d214b3a9..9cb198996a2755a08fc52cbd7f28311f2413f1a1 100644 (file)
@@ -154,6 +154,7 @@ PassOwnPtr<GraphicsLayer> LayerTreeHostProxy::createLayer(WebLayerID layerID)
 LayerTreeHostProxy::LayerTreeHostProxy(DrawingAreaProxy* drawingAreaProxy)
     : m_animationTimer(RunLoop::main(), this, &LayerTreeHostProxy::updateViewport)
     , m_drawingAreaProxy(drawingAreaProxy)
+    , m_viewportUpdateTimer(this, &LayerTreeHostProxy::didFireViewportUpdateTimer)
     , m_rootLayerID(0)
 {
 }
@@ -208,8 +209,15 @@ void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& mat
 
     m_textureMapper->endPainting();
 
-    if (node->descendantsOrSelfHaveRunningAnimations())
-        updateViewport();
+    if (node->descendantsOrSelfHaveRunningAnimations()) {
+        node->syncAnimationsRecursively();
+        m_viewportUpdateTimer.startOneShot(0);
+    }
+}
+
+void LayerTreeHostProxy::didFireViewportUpdateTimer(Timer<LayerTreeHostProxy>*)
+{
+    updateViewport();
 }
 
 void LayerTreeHostProxy::updateViewport()
@@ -272,6 +280,26 @@ void LayerTreeHostProxy::syncLayerParameters(const WebLayerInfo& layerInfo)
     }
     layer->setChildren(children);
 
+    for (size_t i = 0; i < layerInfo.animations.size(); ++i) {
+        const WebKit::WebLayerAnimation anim = layerInfo.animations[i];
+
+        switch (anim.operation) {
+        case WebKit::WebLayerAnimation::AddAnimation: {
+            const IntSize boxSize = anim.boxSize;
+            double offset = WTF::currentTime() - anim.startTime;
+            layer->addAnimation(anim.keyframeList, boxSize, anim.animation.get(), anim.name, offset);
+            break;
+        }
+        case WebKit::WebLayerAnimation::RemoveAnimation:
+            layer->removeAnimation(anim.name);
+            break;
+        case WebKit::WebLayerAnimation::PauseAnimation:
+            double offset = WTF::currentTime() - anim.startTime;
+            layer->pauseAnimation(anim.name, offset);
+            break;
+        }
+    }
+
     if (layerInfo.isRootLayer && m_rootLayerID != id)
         setRootLayerID(id);
 }
index 70843244fb99a497f17476e948a0d82227d37d21..58f7cdced67dfc5c3f9433db61f9536031b8e909 100644 (file)
@@ -280,15 +280,40 @@ void WebGraphicsLayer::notifyAnimationStarted(double time)
 // We put these stub implementations here for when we implement accelerated cross-process animations.
 bool WebGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
 {
-    return false;
+    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
+        return false;
+
+    WebLayerAnimation webAnimation(valueList);
+    webAnimation.name = keyframesName;
+    webAnimation.operation = WebLayerAnimation::AddAnimation;
+    webAnimation.boxSize = boxSize;
+    webAnimation.animation = Animation::create(anim);
+    webAnimation.startTime = WTF::currentTime() - timeOffset;
+    m_layerInfo.animations.append(webAnimation);
+
+    m_hasPendingAnimations = true;
+    notifyChange();
+
+    return true;
 }
 
 void WebGraphicsLayer::pauseAnimation(const String& animationName, double timeOffset)
 {
+    WebLayerAnimation animation;
+    animation.name = animationName;
+    animation.operation = WebLayerAnimation::PauseAnimation;
+    animation.startTime = WTF::currentTime() - timeOffset;
+    m_layerInfo.animations.append(animation);
+    notifyChange();
 }
 
 void WebGraphicsLayer::removeAnimation(const String& animationName)
 {
+    WebLayerAnimation animation;
+    animation.name = animationName;
+    animation.operation = WebLayerAnimation::RemoveAnimation;
+    m_layerInfo.animations.append(animation);
+    notifyChange();
 }
 
 void WebGraphicsLayer::setContentsNeedsDisplay()
@@ -402,6 +427,7 @@ void WebGraphicsLayer::syncCompositingStateForThisLayerOnly()
     m_layerInfo.imageIsUpdated = false;
     if (m_hasPendingAnimations)
         notifyAnimationStarted(WTF::currentTime());
+    m_layerInfo.animations.clear();
     m_hasPendingAnimations = false;
 }