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
+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
}
}
+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)) {
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; }
+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
return SimpleArgumentCoder<Length>::decode(decoder, length);
}
-
void ArgumentCoder<TransformationMatrix>::encode(ArgumentEncoder* encoder, const TransformationMatrix& transformationMatrix)
{
SimpleArgumentCoder<TransformationMatrix>::encode(encoder, transformationMatrix);
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());
}
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;
RefPtr<TimingFunction> timingFunction;
String name;
- animation.clearAll();
-
double delay;
if (!decodeBoolAndValue(decoder, isDelaySet, delay))
return false;
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;
}
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
{
// 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)
// 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;
}
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
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;
unsigned int flags;
};
Vector<WebLayerID> children;
+ Vector<WebLayerAnimation> animations;
RefPtr<ShareableBitmap> imageBackingStore;
void encode(CoreIPC::ArgumentEncoder*) const;
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;
LayerTreeHostProxy::LayerTreeHostProxy(DrawingAreaProxy* drawingAreaProxy)
: m_animationTimer(RunLoop::main(), this, &LayerTreeHostProxy::updateViewport)
, m_drawingAreaProxy(drawingAreaProxy)
+ , m_viewportUpdateTimer(this, &LayerTreeHostProxy::didFireViewportUpdateTimer)
, m_rootLayerID(0)
{
}
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()
}
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);
}
// 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()
m_layerInfo.imageIsUpdated = false;
if (m_hasPendingAnimations)
notifyAnimationStarted(WTF::currentTime());
+ m_layerInfo.animations.clear();
m_hasPendingAnimations = false;
}