Changeset 143343 in webkit


Ignore:
Timestamp:
Feb 19, 2013 9:01:32 AM (11 years ago)
Author:
commit-queue@webkit.org
Message:

[GTK][AC] Implement keyframe animations with clutter ac backend
https://bugs.webkit.org/show_bug.cgi?id=110057

Patch by ChangSeok Oh <ChangSeok Oh> on 2013-02-19
Reviewed by Gustavo Noronha Silva.

This patch brings accelerated keyframe animation with clutter to WebKitGtk+.
Changes of GraphicsLayerClutter are based on GraphicsLayerCA. But major changes
of PlatformClutterAnimation are implemented with clutter keyframe transition apis.
See http://developer.gnome.org/clutter/stable/ClutterKeyframeTransition.html

Covered by existing animation tests.

  • platform/graphics/clutter/GraphicsLayerClutter.cpp:

(WebCore::GraphicsLayerClutter::createKeyframeAnimation):
(WebCore::GraphicsLayerClutter::setTransformAnimationKeyframes):
(WebCore::GraphicsLayerClutter::setAnimationKeyframes):

  • platform/graphics/clutter/PlatformClutterAnimation.cpp:

(WebCore::toClutterActorPropertyString):
(WebCore::PlatformClutterAnimation::PlatformClutterAnimation):
(WebCore::PlatformClutterAnimation::setTimingFunction):
(WebCore::PlatformClutterAnimation::setValues):
(WebCore::PlatformClutterAnimation::setKeyTimes):
(WebCore::PlatformClutterAnimation::setTimingFunctions):
(WebCore::PlatformClutterAnimation::addClutterTransitionForProperty):
(WebCore):
(WebCore::PlatformClutterAnimation::addClutterKeyframeTransitionForProperty):
(WebCore::PlatformClutterAnimation::addOpacityTransition):
(WebCore::PlatformClutterAnimation::addTransformTransition):
(WebCore::PlatformClutterAnimation::addAnimationForKey):
(WebCore::PlatformClutterAnimation::removeAnimationForKey):

  • platform/graphics/clutter/PlatformClutterAnimation.h:

(PlatformClutterAnimation):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r143337 r143343  
     12013-02-19  ChangSeok Oh  <changseok.oh@collabora.com>
     2
     3        [GTK][AC] Implement keyframe animations with clutter ac backend
     4        https://bugs.webkit.org/show_bug.cgi?id=110057
     5
     6        Reviewed by Gustavo Noronha Silva.
     7
     8        This patch brings accelerated keyframe animation with clutter to WebKitGtk+.
     9        Changes of GraphicsLayerClutter are based on GraphicsLayerCA. But major changes
     10        of PlatformClutterAnimation are implemented with clutter keyframe transition apis.
     11        See http://developer.gnome.org/clutter/stable/ClutterKeyframeTransition.html
     12
     13        Covered by existing animation tests.
     14
     15        * platform/graphics/clutter/GraphicsLayerClutter.cpp:
     16        (WebCore::GraphicsLayerClutter::createKeyframeAnimation):
     17        (WebCore::GraphicsLayerClutter::setTransformAnimationKeyframes):
     18        (WebCore::GraphicsLayerClutter::setAnimationKeyframes):
     19        * platform/graphics/clutter/PlatformClutterAnimation.cpp:
     20        (WebCore::toClutterActorPropertyString):
     21        (WebCore::PlatformClutterAnimation::PlatformClutterAnimation):
     22        (WebCore::PlatformClutterAnimation::setTimingFunction):
     23        (WebCore::PlatformClutterAnimation::setValues):
     24        (WebCore::PlatformClutterAnimation::setKeyTimes):
     25        (WebCore::PlatformClutterAnimation::setTimingFunctions):
     26        (WebCore::PlatformClutterAnimation::addClutterTransitionForProperty):
     27        (WebCore):
     28        (WebCore::PlatformClutterAnimation::addClutterKeyframeTransitionForProperty):
     29        (WebCore::PlatformClutterAnimation::addOpacityTransition):
     30        (WebCore::PlatformClutterAnimation::addTransformTransition):
     31        (WebCore::PlatformClutterAnimation::addAnimationForKey):
     32        (WebCore::PlatformClutterAnimation::removeAnimationForKey):
     33        * platform/graphics/clutter/PlatformClutterAnimation.h:
     34        (PlatformClutterAnimation):
     35
    1362013-02-19  Claudio Saavedra  <csaavedra@igalia.com>
    237
  • trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp

    r142749 r143343  
    749749PassRefPtr<PlatformClutterAnimation>GraphicsLayerClutter::createKeyframeAnimation(const Animation* anim, const String& keyPath, bool additive)
    750750{
    751     notImplemented();
    752     return 0;
     751    RefPtr<PlatformClutterAnimation> keyframeAnim = PlatformClutterAnimation::create(PlatformClutterAnimation::Keyframe, keyPath);
     752    setupAnimation(keyframeAnim.get(), anim, additive);
     753    return keyframeAnim;
    753754}
    754755
    755756bool GraphicsLayerClutter::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformClutterAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
    756757{
    757     notImplemented();
    758     return false;
     758    Vector<float> keyTimes;
     759    Vector<float> floatValues;
     760    Vector<FloatPoint3D> floatPoint3DValues;
     761    Vector<TransformationMatrix> transformationMatrixValues;
     762    Vector<const TimingFunction*> timingFunctions;
     763
     764    bool forwards = animation->directionIsForwards();
     765
     766    for (unsigned i = 0; i < valueList.size(); ++i) {
     767        unsigned index = forwards ? i : (valueList.size() - i - 1);
     768        const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(index));
     769        keyTimes.append(forwards ? curValue->keyTime() : (1 - curValue->keyTime()));
     770
     771        if (isMatrixAnimation) {
     772            TransformationMatrix transform;
     773            curValue->value()->apply(boxSize, transform);
     774
     775            // FIXME: In CoreAnimation case, if any matrix is singular, CA won't animate it correctly.
     776            // But I'm not sure clutter also does. Check it later, and then decide
     777            // whether removing following lines or not.
     778            if (!transform.isInvertible())
     779                return false;
     780
     781            transformationMatrixValues.append(transform);
     782        } else {
     783            const TransformOperation* transformOp = curValue->value()->at(functionIndex);
     784            if (isTransformTypeNumber(transformOpType)) {
     785                float value;
     786                getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
     787                floatValues.append(value);
     788            } else if (isTransformTypeFloatPoint3D(transformOpType)) {
     789                FloatPoint3D value;
     790                getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
     791                floatPoint3DValues.append(value);
     792            } else {
     793                TransformationMatrix value;
     794                getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
     795                transformationMatrixValues.append(value);
     796            }
     797        }
     798
     799        if (i < (valueList.size() - 1))
     800            timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), animation));
     801    }
     802
     803    keyframeAnim->setKeyTimes(keyTimes);
     804
     805    if (isTransformTypeNumber(transformOpType))
     806        keyframeAnim->setValues(floatValues);
     807    else if (isTransformTypeFloatPoint3D(transformOpType))
     808        keyframeAnim->setValues(floatPoint3DValues);
     809    else
     810        keyframeAnim->setValues(transformationMatrixValues);
     811
     812    keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
     813
     814    PlatformClutterAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
     815    if (valueFunction != PlatformClutterAnimation::NoValueFunction)
     816        keyframeAnim->setValueFunction(valueFunction);
     817
     818    return true;
    759819}
    760820
     
    9871047bool GraphicsLayerClutter::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformClutterAnimation* keyframeAnim)
    9881048{
    989     notImplemented();
    990     return false;
     1049    Vector<float> keyTimes;
     1050    Vector<float> values;
     1051    Vector<const TimingFunction*> timingFunctions;
     1052
     1053    bool forwards = animation->directionIsForwards();
     1054
     1055    for (unsigned i = 0; i < valueList.size(); ++i) {
     1056        unsigned index = forwards ? i : (valueList.size() - i - 1);
     1057        const AnimationValue* curValue = valueList.at(index);
     1058        keyTimes.append(forwards ? curValue->keyTime() : (1 - curValue->keyTime()));
     1059
     1060        switch (valueList.property()) {
     1061        case AnimatedPropertyOpacity: {
     1062            const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue);
     1063            values.append(floatValue->value());
     1064            break;
     1065        }
     1066        default:
     1067            ASSERT_NOT_REACHED(); // we don't animate color yet
     1068            break;
     1069        }
     1070
     1071        if (i < (valueList.size() - 1))
     1072            timingFunctions.append(timingFunctionForAnimationValue(forwards ? curValue : valueList.at(index - 1), animation));
     1073    }
     1074
     1075    keyframeAnim->setKeyTimes(keyTimes);
     1076    keyframeAnim->setValues(values);
     1077    keyframeAnim->setTimingFunctions(timingFunctions, !forwards);
     1078
     1079    return true;
    9911080}
    9921081
  • trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.cpp

    r142749 r143343  
    3939#include <limits.h>
    4040#include <wtf/CurrentTime.h>
     41#include <wtf/OwnArrayPtr.h>
    4142#include <wtf/UnusedParam.h>
     43#include <wtf/gobject/GOwnPtr.h>
    4244#include <wtf/text/CString.h>
    4345
     
    5557    // ClutterActor doesn't have 'scale' and 'translate' properties. So we should support
    5658    // 'scale' and 'translate' ValueFunctionType by combination of existing property animations.
    57     const char* clutterActorProperty[] = { "NoProperty", "rotation-angle-x", "rotation-angle-y", "rotation-angle-z", "scale-x", "scale-y", "scale-z", "NoProperty", "translation-x", "translation-y", "translation-z", "NoProperty" };
     59    const char* clutterActorProperty[] = { "NoProperty", "rotation-angle-x", "rotation-angle-y", "rotation-angle-z", "scale-x", "scale-y", "scale-z", "scale", "translation-x", "translation-y", "translation-z", "translate" };
    5860    return clutterActorProperty[valueFunctionType];
    5961}
     
    115117    , m_valueFunctionType(NoValueFunction)
    116118{
    117     // FIXME: We support only Basic type now.
    118     ASSERT(type == Basic);
    119119    m_animation = adoptGRef(G_OBJECT(clutter_transition_group_new()));
    120120}
     
    222222    if (!timingFunction)
    223223        return;
     224
    224225    m_timingFunction = timingFunction;
    225226}
     
    331332void PlatformClutterAnimation::setValues(const Vector<float>& value)
    332333{
    333     notImplemented();
     334    ASSERT(animationType() == Keyframe);
     335
     336    m_values = value;
    334337}
    335338
     
    341344void PlatformClutterAnimation::setValues(const Vector<FloatPoint3D>& value)
    342345{
    343     notImplemented();
     346    ASSERT(animationType() == Keyframe);
     347
     348    m_values3D = value;
    344349}
    345350
     
    356361void PlatformClutterAnimation::setKeyTimes(const Vector<float>& value)
    357362{
    358     notImplemented();
     363    ASSERT(animationType() == Keyframe);
     364
     365    m_keyTimes = value;
    359366}
    360367
     
    366373void PlatformClutterAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value, bool reverse)
    367374{
    368     notImplemented();
     375    ASSERT(animationType() == Keyframe);
     376
     377    m_timingFunctions = value;
    369378}
    370379
     
    391400}
    392401
    393 void PlatformClutterAnimation::addClutterTransitionForProperty(const String& property, const unsigned fromValue, const unsigned toValue)
     402void PlatformClutterAnimation::addClutterTransitionForProperty(const String& property, const float fromValue, const float toValue)
    394403{
    395404    ASSERT(property != "NoProperty");
    396405
     406    GType gType = (property == "opacity" ? G_TYPE_UINT : G_TYPE_FLOAT);
     407
    397408    GRefPtr<ClutterTransition> transition = adoptGRef(clutter_property_transition_new(property.utf8().data()));
    398     clutter_transition_set_from(transition.get(), G_TYPE_UINT, fromValue);
    399     clutter_transition_set_to(transition.get(), G_TYPE_UINT, toValue);
     409    clutter_transition_set_from(transition.get(), gType, (gType == G_TYPE_UINT ? static_cast<unsigned>(fromValue) : fromValue));
     410    clutter_transition_set_to(transition.get(), gType, (gType == G_TYPE_UINT ? static_cast<unsigned>(toValue) : toValue));
     411
     412    clutter_timeline_set_progress_mode(timeline(), toClutterAnimationMode(m_timingFunction));
    400413
    401414    clutter_transition_group_add_transition(CLUTTER_TRANSITION_GROUP(m_animation.get()), transition.get());
    402415}
    403416
    404 void PlatformClutterAnimation::addClutterTransitionForProperty(const String& property, const float fromValue, const float toValue)
     417void PlatformClutterAnimation::addClutterTransitionForProperty(const String& property, const FloatPoint3D& fromValue, const FloatPoint3D& toValue)
    405418{
    406419    ASSERT(property != "NoProperty");
    407420
    408     GRefPtr<ClutterTransition> transition = adoptGRef(clutter_property_transition_new(property.utf8().data()));
    409     clutter_transition_set_from(transition.get(), G_TYPE_FLOAT, fromValue);
    410     clutter_transition_set_to(transition.get(), G_TYPE_FLOAT, toValue);
     421    if (property == "scale") {
     422        addClutterTransitionForProperty(String("scale-x"), fromValue.x(), toValue.x());
     423        addClutterTransitionForProperty(String("scale-y"), fromValue.y(), toValue.y());
     424        return;
     425    }
     426    if (property == "translate") {
     427        addClutterTransitionForProperty(String("translation-x"), fromValue.x(), toValue.x());
     428        addClutterTransitionForProperty(String("translation-y"), fromValue.x(), toValue.y());
     429        return;
     430    }
     431
     432    ASSERT_NOT_REACHED();
     433}
     434
     435void PlatformClutterAnimation::addClutterKeyframeTransitionForProperty(const String& property, const Vector<float>& values)
     436{
     437    ASSERT(property != "NoProperty");
     438
     439    GType gType = (property == "opacity" ? G_TYPE_UINT : G_TYPE_FLOAT);
     440
     441    GRefPtr<ClutterTransition> transition = adoptGRef(clutter_keyframe_transition_new(property.utf8().data()));
     442    clutter_transition_set_from(transition.get(), gType, values.first());
     443    clutter_transition_set_to(transition.get(), gType, values.last());
     444
     445    // Ignore the first keyframe, since it's a '0' frame, meaningless.
     446    const unsigned nKeyframes = values.size() - 1;
     447    OwnArrayPtr<ClutterAnimationMode> animationModes = adoptArrayPtr(new ClutterAnimationMode[nKeyframes]);
     448    OwnArrayPtr<double> keyTimes = adoptArrayPtr(new double[nKeyframes]);
     449    GOwnPtr<GValue> keyValues(g_new0(GValue, nKeyframes));
     450
     451    for (unsigned i = 0; i < nKeyframes; ++i) {
     452        keyTimes[i] = static_cast<double>(m_keyTimes[i + 1]);
     453        animationModes[i] = toClutterAnimationMode(m_timingFunctions[i]);
     454        g_value_init(&keyValues.get()[i], gType);
     455        if (gType == G_TYPE_UINT)
     456            g_value_set_uint(&keyValues.get()[i], static_cast<unsigned>(values[i + 1]));
     457        else
     458            g_value_set_float(&keyValues.get()[i], values[i + 1]);
     459    }
     460
     461    clutter_keyframe_transition_set_key_frames(CLUTTER_KEYFRAME_TRANSITION(transition.get()), nKeyframes, keyTimes.get());
     462    clutter_keyframe_transition_set_values(CLUTTER_KEYFRAME_TRANSITION(transition.get()), nKeyframes, keyValues.get());
     463    clutter_keyframe_transition_set_modes(CLUTTER_KEYFRAME_TRANSITION(transition.get()), nKeyframes, animationModes.get());
    411464
    412465    clutter_transition_group_add_transition(CLUTTER_TRANSITION_GROUP(m_animation.get()), transition.get());
     466
     467    for (unsigned i = 0; i < nKeyframes; ++i)
     468        g_value_unset(&keyValues.get()[i]);
     469}
     470
     471void PlatformClutterAnimation::addClutterKeyframeTransitionForProperty(const String& property, const Vector<FloatPoint3D>& values)
     472{
     473    ASSERT(property != "NoProperty");
     474
     475    Vector<float> valuesX, valuesY;
     476    for (unsigned i = 0; i < values.size(); ++i) {
     477        valuesX.append(values[i].x());
     478        valuesY.append(values[i].y());
     479    }
     480
     481    if (property == "scale") {
     482        addClutterKeyframeTransitionForProperty(String("scale-x"), valuesX);
     483        addClutterKeyframeTransitionForProperty(String("scale-y"), valuesY);
     484        return;
     485    }
     486    if (property == "translate") {
     487        addClutterKeyframeTransitionForProperty(String("translation-x"), valuesX);
     488        addClutterKeyframeTransitionForProperty(String("translation-y"), valuesY);
     489        return;
     490    }
     491
     492    ASSERT_NOT_REACHED();
    413493}
    414494
    415495void PlatformClutterAnimation::addOpacityTransition()
    416496{
    417     addClutterTransitionForProperty(String("opacity"), static_cast<unsigned>(255 * m_fromValue), static_cast<unsigned>(255 * m_toValue));
     497    if (animationType() == Keyframe) {
     498        for (unsigned i = 0; i < m_values.size(); ++i)
     499            m_values[i] *= 255;
     500
     501        addClutterKeyframeTransitionForProperty(String("opacity"), m_values);
     502    } else {
     503        m_fromValue *= 255;
     504        m_toValue *= 255;
     505
     506        addClutterTransitionForProperty(String("opacity"), m_fromValue, m_toValue);
     507    }
    418508}
    419509
    420510void PlatformClutterAnimation::addTransformTransition()
    421511{
     512    const bool isKeyframe = (animationType() == Keyframe);
     513
    422514    switch (m_valueFunctionType) {
    423515    case RotateX:
    424516    case RotateY:
    425517    case RotateZ:
    426         addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), rad2deg(m_fromValue), rad2deg(m_toValue));
     518        if (isKeyframe) {
     519            for (unsigned i = 0; i < m_values.size(); ++i)
     520                m_values[i] = rad2deg(m_values[i]);
     521
     522            addClutterKeyframeTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_values);
     523        } else {
     524            m_fromValue = rad2deg(m_fromValue);
     525            m_toValue = rad2deg(m_toValue);
     526
     527            addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_fromValue, m_toValue);
     528        }
    427529        break;
    428530    case ScaleX:
     
    432534    case TranslateY:
    433535    case TranslateZ:
    434         addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_fromValue, m_toValue);
     536        if (isKeyframe)
     537            addClutterKeyframeTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_values);
     538        else
     539            addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_fromValue, m_toValue);
    435540        break;
    436541    case Scale:
    437         addClutterTransitionForProperty(String("scale-x"), m_fromValue3D.x(), m_toValue3D.x());
    438         addClutterTransitionForProperty(String("scale-y"), m_fromValue3D.y(), m_toValue3D.y());
    439         break;
    440542    case Translate:
    441         addClutterTransitionForProperty(String("translation-x"), m_fromValue3D.x(), m_toValue3D.x());
    442         addClutterTransitionForProperty(String("translation-y"), m_fromValue3D.x(), m_toValue3D.y());
     543        if (isKeyframe)
     544            addClutterKeyframeTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_values3D);
     545        else
     546            addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_fromValue3D, m_toValue3D);
    443547        break;
    444548    default:
     
    453557void PlatformClutterAnimation::addAnimationForKey(GraphicsLayerActor* platformLayer, const String& key)
    454558{
    455     ASSERT(animationType() == Basic);
    456559    ASSERT(!g_object_get_data(G_OBJECT(platformLayer), key.utf8().data()));
    457560
     
    467570        ASSERT_NOT_REACHED();
    468571
    469     ClutterAnimationMode animationMode = toClutterAnimationMode(m_timingFunction);
    470     ClutterTimeline* clutterTimeline = timeline();
    471     clutter_timeline_set_progress_mode(clutterTimeline, animationMode);
    472 
    473     g_signal_connect(clutterTimeline, "started", G_CALLBACK(timelineStartedCallback), this);
     572    g_signal_connect(timeline(), "started", G_CALLBACK(timelineStartedCallback), this);
    474573    g_object_set_data(G_OBJECT(platformLayer), key.utf8().data(), this);
    475574
     
    479578void PlatformClutterAnimation::removeAnimationForKey(GraphicsLayerActor* layer, const String& key)
    480579{
    481     ASSERT(animationType() == Basic);
    482 
    483580    clutter_actor_remove_transition(CLUTTER_ACTOR(layer), key.utf8().data());
    484581    g_object_set_data(G_OBJECT(layer), key.utf8().data(), 0);
  • trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.h

    r142749 r143343  
    139139    AnimatedPropertyType stringToAnimatedPropertyType(const String& keyPath) const;
    140140
    141     void addClutterTransitionForProperty(const String& property, const unsigned fromValue, const unsigned toValue);
    142141    void addClutterTransitionForProperty(const String& property, const float fromValue, const float toValue);
     142    void addClutterTransitionForProperty(const String& property, const FloatPoint3D& fromValue, const FloatPoint3D& toValue);
     143
     144    void addClutterKeyframeTransitionForProperty(const String& property, const Vector<float>& values);
     145    void addClutterKeyframeTransitionForProperty(const String& property, const Vector<FloatPoint3D>& values);
    143146
    144147    void addOpacityTransition();
     
    163166    const TimingFunction* m_timingFunction;
    164167    ValueFunctionType m_valueFunctionType;
     168
     169    Vector<float> m_keyTimes;
     170    Vector<const TimingFunction*> m_timingFunctions;
     171
     172    Vector<float> m_values;
     173    Vector<FloatPoint3D> m_values3D;
    165174};
    166175
Note: See TracChangeset for help on using the changeset viewer.