Changeset 286544 in webkit
- Timestamp:
- Dec 6, 2021, 9:20:08 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
-
ChangeLog (modified) (1 diff)
-
animation/AnimationEffect.cpp (modified) (2 diffs)
-
animation/AnimationEffect.h (modified) (3 diffs)
-
animation/KeyframeEffect.cpp (modified) (2 diffs)
-
animation/KeyframeEffect.h (modified) (6 diffs)
-
animation/WebAnimation.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r286543 r286544 1 2021-12-06 Antoine Quint <graouts@webkit.org> 2 3 Clean up virtual methods on AnimationEffect 4 https://bugs.webkit.org/show_bug.cgi?id=233868 5 6 Reviewed by Simon Fraser. 7 8 To this day, the only concrete subclass of AnimationEffect has been KeyframeEffect. Soon, we'll introduce 9 another concrete subclass for callback-based animations leveraging the Web Animations mode: CustomEffect. 10 To prepare for this new class, we clean up the virtual methods on AnimationEffect such that they make a 11 bit more sense: 12 13 - much of the implementation of timeToNextTick() is brought from KeyframeEffect to AnimationEffect to 14 account for the cases which are purely based on timing properties shared by any potential AnimationEffect 15 subclass, 16 17 - we add a new ticksContinouslyWhileActive() method which allows subclasses to indicate whether they require 18 continuous scheduling while active, which is true for KeyframeEffect unless it has no keyframes, no CSS 19 properties set on its keyframes or is running fully accelerated, 20 21 - much of the implementation of setAnimation() is brought from KeyframeEffect to AnimationEffect since 22 updating the relevance of the animation based on a change of effect should apply to any AnimationEffect, 23 24 - the apply() and invalidate() methods are moved from AnimationEffect to KeyframeEffect alone since they 25 really are specific to KeyframeEffect's interaction with style resolution, 26 27 - all the other virtual methods on AnimationEffect have stub implementations such that new subclasses 28 only need to override them as required: animationDidTick(), animationDidPlay(), 29 animationDidChangeTimingProperties(), animationWasCanceled(), animationSuspensionStateDidChange(bool) 30 and animationTimelineDidChange(AnimationTimeline*). 31 32 * animation/AnimationEffect.cpp: 33 (WebCore::AnimationEffect::setAnimation): 34 (WebCore::AnimationEffect::timeToNextTick const): 35 * animation/AnimationEffect.h: 36 (WebCore::AnimationEffect::animationDidTick): 37 (WebCore::AnimationEffect::animationDidPlay): 38 (WebCore::AnimationEffect::animationDidChangeTimingProperties): 39 (WebCore::AnimationEffect::animationWasCanceled): 40 (WebCore::AnimationEffect::animationSuspensionStateDidChange): 41 (WebCore::AnimationEffect::animationTimelineDidChange): 42 (WebCore::AnimationEffect::ticksContinouslyWhileActive const): 43 (WebCore::AnimationEffect::setAnimation): Deleted. 44 (WebCore::AnimationEffect::timeToNextTick const): Deleted. 45 * animation/KeyframeEffect.cpp: 46 (WebCore::KeyframeEffect::setAnimation): 47 (WebCore::KeyframeEffect::ticksContinouslyWhileActive const): 48 (WebCore::KeyframeEffect::timeToNextTick const): 49 * animation/KeyframeEffect.h: 50 * animation/WebAnimation.cpp: 51 (WebCore::WebAnimation::invalidateEffect): 52 (WebCore::WebAnimation::resolve): 53 (WebCore::WebAnimation::timeToNextTick const): 54 1 55 2021-12-06 Nikolas Zimmermann <nzimmermann@igalia.com> 2 56 -
trunk/Source/WebCore/animation/AnimationEffect.cpp
r284095 r286544 44 44 } 45 45 46 void AnimationEffect::setAnimation(WebAnimation* animation) 47 { 48 if (m_animation == animation) 49 return; 50 51 m_animation = animation; 52 if (animation) 53 animation->updateRelevance(); 54 } 55 46 56 EffectTiming AnimationEffect::getBindingsTiming() const 47 57 { … … 552 562 } 553 563 564 Seconds AnimationEffect::timeToNextTick(BasicEffectTiming timing) const 565 { 566 switch (timing.phase) { 567 case AnimationEffectPhase::Before: 568 // The effect is in its "before" phase, in this case we can wait until it enters its "active" phase. 569 return delay() - *timing.localTime; 570 case AnimationEffectPhase::Active: { 571 if (!ticksContinouslyWhileActive()) 572 return endTime() - *timing.localTime; 573 if (auto iterationProgress = getComputedTiming().simpleIterationProgress) { 574 // In case we're in a range that uses a steps() timing function, we can compute the time until the next step starts. 575 if (auto progressUntilNextStep = this->progressUntilNextStep(*iterationProgress)) 576 return iterationDuration() * *progressUntilNextStep; 577 } 578 // Other effects that continuously tick in the "active" phase will need to update their animated 579 // progress at the immediate next opportunity. 580 return 0_s; 581 } 582 case AnimationEffectPhase::After: 583 // The effect is in its after phase, which means it will no longer update its progress, so it doens't need a tick. 584 return Seconds::infinity(); 585 case AnimationEffectPhase::Idle: 586 ASSERT_NOT_REACHED(); 587 return Seconds::infinity(); 588 } 589 590 ASSERT_NOT_REACHED(); 591 return Seconds::infinity(); 592 } 593 554 594 } // namespace WebCore -
trunk/Source/WebCore/animation/AnimationEffect.h
r284693 r286544 48 48 namespace WebCore { 49 49 50 namespace Style {51 struct ResolutionContext;52 }53 54 50 class AnimationEffect : public RefCounted<AnimationEffect>, public CanMakeWeakPtr<AnimationEffect> { 55 51 public: … … 66 62 ExceptionOr<void> updateTiming(std::optional<OptionalEffectTiming>); 67 63 68 virtual void apply(RenderStyle& targetStyle, const Style::ResolutionContext&, std::optional<Seconds> = std::nullopt) = 0; 69 virtual void invalidate() = 0; 70 virtual void animationDidTick() = 0; 71 virtual void animationDidPlay() = 0; 72 virtual void animationDidChangeTimingProperties() = 0; 73 virtual void animationWasCanceled() = 0; 74 virtual void animationSuspensionStateDidChange(bool) = 0; 75 virtual void animationTimelineDidChange(AnimationTimeline*) = 0; 64 virtual void animationDidTick() { }; 65 virtual void animationDidPlay() { }; 66 virtual void animationDidChangeTimingProperties() { }; 67 virtual void animationWasCanceled() { }; 68 virtual void animationSuspensionStateDidChange(bool) { }; 69 virtual void animationTimelineDidChange(AnimationTimeline*) { }; 76 70 77 71 WebAnimation* animation() const { return m_animation.get(); } 78 virtual void setAnimation(WebAnimation* animation) { m_animation = animation; }72 virtual void setAnimation(WebAnimation*); 79 73 80 74 Seconds delay() const { return m_delay; } … … 107 101 void updateStaticTimingProperties(); 108 102 109 virtual Seconds timeToNextTick( ) const { return Seconds::infinity(); }103 virtual Seconds timeToNextTick(BasicEffectTiming) const; 110 104 111 105 protected: 112 106 explicit AnimationEffect(); 113 107 108 virtual bool ticksContinouslyWhileActive() const { return false; } 114 109 virtual std::optional<double> progressUntilNextStep(double) const; 115 110 -
trunk/Source/WebCore/animation/KeyframeEffect.cpp
r285728 r286544 1163 1163 bool animationChanged = animation != this->animation(); 1164 1164 AnimationEffect::setAnimation(animation); 1165 1166 if (!animationChanged) 1167 return; 1168 1169 if (animation) 1170 animation->updateRelevance(); 1171 updateEffectStackMembership(); 1165 if (animationChanged) 1166 updateEffectStackMembership(); 1172 1167 } 1173 1168 … … 2121 2116 } 2122 2117 2123 Seconds KeyframeEffect::timeToNextTick() const 2124 { 2125 auto timing = getBasicTiming(); 2126 switch (timing.phase) { 2127 case AnimationEffectPhase::Before: 2128 // The effect is in its "before" phase, in this case we can wait until it enters its "active" phase. 2129 return delay() - *timing.localTime; 2130 case AnimationEffectPhase::Active: { 2131 auto doesNotAffectStyles = m_blendingKeyframes.isEmpty() || m_blendingKeyframes.properties().isEmpty(); 2132 auto completelyAcceleratedAndRunning = isCompletelyAccelerated() && isRunningAccelerated(); 2133 if (doesNotAffectStyles || completelyAcceleratedAndRunning) { 2134 // In the case of fully accelerated running effects and effects that don't actually target any CSS property, 2135 // we do not have a need to invalidate styles. 2136 if (is<CSSAnimation>(animation())) { 2137 // However, CSS Animations need to trigger "animationiteration" events, in this case we must wait until the next iteration. 2138 if (auto iterationProgress = getComputedTiming().simpleIterationProgress) 2139 return iterationDuration() * (1 - *iterationProgress); 2140 } 2141 // Other running effects in the "active" phase can wait until they end. 2142 return endTime() - *timing.localTime; 2143 } 2144 if (auto iterationProgress = getComputedTiming().simpleIterationProgress) { 2145 // In case we're in a range that uses a steps() timing function, we can compute the time until the next step starts. 2146 if (auto progressUntilNextStep = this->progressUntilNextStep(*iterationProgress)) 2147 return iterationDuration() * *progressUntilNextStep; 2148 } 2149 // Other effects in the "active" phase will need to update their animated value at the immediate next opportunity. 2150 return 0_s; 2151 } 2152 case AnimationEffectPhase::After: 2153 // The effect is in its after phase, which means it will no longer update its value, so it doens't need a tick. 2154 return Seconds::infinity(); 2155 case AnimationEffectPhase::Idle: 2156 ASSERT_NOT_REACHED(); 2157 return Seconds::infinity(); 2158 } 2159 2160 ASSERT_NOT_REACHED(); 2161 return Seconds::infinity(); 2118 bool KeyframeEffect::ticksContinouslyWhileActive() const 2119 { 2120 auto doesNotAffectStyles = m_blendingKeyframes.isEmpty() || m_blendingKeyframes.properties().isEmpty(); 2121 if (doesNotAffectStyles) 2122 return false; 2123 2124 if (isCompletelyAccelerated() && isRunningAccelerated()) 2125 return false; 2126 2127 return true; 2128 } 2129 2130 Seconds KeyframeEffect::timeToNextTick(BasicEffectTiming timing) const 2131 { 2132 if (timing.phase == AnimationEffectPhase::Active) { 2133 // CSS Animations need to trigger "animationiteration" events even if there is no need to 2134 // update styles while animating, so if we're dealing with one we must wait until the next iteration. 2135 if (!ticksContinouslyWhileActive() && is<CSSAnimation>(animation())) { 2136 if (auto iterationProgress = getComputedTiming().simpleIterationProgress) 2137 return iterationDuration() * (1 - *iterationProgress); 2138 } 2139 } 2140 2141 return AnimationEffect::timeToNextTick(timing); 2162 2142 } 2163 2143 -
trunk/Source/WebCore/animation/KeyframeEffect.h
r285397 r286544 47 47 class FilterOperations; 48 48 49 namespace Style { 50 struct ResolutionContext; 51 } 52 49 53 class KeyframeEffect : public AnimationEffect 50 54 , public CSSPropertyBlendingClient { … … 54 58 static Ref<KeyframeEffect> create(const Element&, PseudoId); 55 59 ~KeyframeEffect() { } 56 57 bool isKeyframeEffect() const final { return true; }58 60 59 61 struct BasePropertyIndexedKeyframe { … … 124 126 125 127 void getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle); 126 void apply(RenderStyle& targetStyle, const Style::ResolutionContext&, std::optional<Seconds> = std::nullopt) override; 127 void invalidate() override; 128 void animationDidTick() final; 129 void animationDidPlay() final; 130 void animationDidChangeTimingProperties() final; 131 void animationWasCanceled() final; 132 void animationSuspensionStateDidChange(bool) final; 133 void animationTimelineDidChange(AnimationTimeline*) final; 128 void apply(RenderStyle& targetStyle, const Style::ResolutionContext&, std::optional<Seconds> = std::nullopt); 129 void invalidate(); 130 134 131 void animationTimingDidChange(); 135 132 void transformRelatedPropertyDidChange(); … … 137 134 138 135 void willChangeRenderer(); 139 140 void setAnimation(WebAnimation*) final;141 136 142 137 RenderElement* renderer() const override; … … 205 200 void computeAcceleratedPropertiesState(); 206 201 void setBlendingKeyframes(KeyframeList&); 207 Seconds timeToNextTick() const final;208 std::optional<double> progressUntilNextStep(double) const final;209 202 bool isTargetingTransformRelatedProperty() const; 210 203 void checkForMatchingTransformFunctionLists(); … … 215 208 void checkForMatchingBackdropFilterFunctionLists(); 216 209 #endif 210 211 // AnimationEffect 212 bool isKeyframeEffect() const final { return true; } 213 void animationDidTick() final; 214 void animationDidPlay() final; 215 void animationDidChangeTimingProperties() final; 216 void animationWasCanceled() final; 217 void animationSuspensionStateDidChange(bool) final; 218 void animationTimelineDidChange(AnimationTimeline*) final; 219 void setAnimation(WebAnimation*) final; 220 Seconds timeToNextTick(BasicEffectTiming) const final; 221 bool ticksContinouslyWhileActive() const final; 222 std::optional<double> progressUntilNextStep(double) const final; 217 223 218 224 KeyframeList m_blendingKeyframes { emptyString() }; -
trunk/Source/WebCore/animation/WebAnimation.cpp
r285195 r286544 798 798 void WebAnimation::invalidateEffect() 799 799 { 800 if (!isEffectInvalidationSuspended() && m_effect)801 m_effect->invalidate();800 if (!isEffectInvalidationSuspended() && is<KeyframeEffect>(m_effect)) 801 downcast<KeyframeEffect>(*m_effect).invalidate(); 802 802 } 803 803 … … 1235 1235 m_shouldSkipUpdatingFinishedStateWhenResolving = false; 1236 1236 1237 if ( m_effect)1238 m_effect->apply(targetStyle, resolutionContext, startTime);1237 if (is<KeyframeEffect>(m_effect)) 1238 downcast<KeyframeEffect>(*m_effect).apply(targetStyle, resolutionContext, startTime); 1239 1239 } 1240 1240 … … 1454 1454 1455 1455 ASSERT(effect()); 1456 return effect()->timeToNextTick( ) / playbackRate;1456 return effect()->timeToNextTick(effect()->getBasicTiming()) / playbackRate; 1457 1457 } 1458 1458
Note:
See TracChangeset
for help on using the changeset viewer.