1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "animation/rs_render_interpolating_spring_animation.h"
17
18 #include "animation/rs_animation_trace_utils.h"
19 #include "animation/rs_value_estimator.h"
20 #include "command/rs_animation_command.h"
21 #include "command/rs_message_processor.h"
22 #include "pipeline/rs_render_node.h"
23 #include "platform/common/rs_log.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 constexpr float SECOND_TO_MILLISECOND = 1e3;
29 constexpr float MILLISECOND_TO_SECOND = 1e-3;
30 constexpr float FRAME_TIME_INTERVAL = 1.0f / 90.0f;
31 } // namespace
32
RSRenderInterpolatingSpringAnimation(AnimationId id,const PropertyId & propertyId,const std::shared_ptr<RSRenderPropertyBase> & originValue,const std::shared_ptr<RSRenderPropertyBase> & startValue,const std::shared_ptr<RSRenderPropertyBase> & endValue)33 RSRenderInterpolatingSpringAnimation::RSRenderInterpolatingSpringAnimation(AnimationId id, const PropertyId& propertyId,
34 const std::shared_ptr<RSRenderPropertyBase>& originValue, const std::shared_ptr<RSRenderPropertyBase>& startValue,
35 const std::shared_ptr<RSRenderPropertyBase>& endValue)
36 : RSRenderPropertyAnimation(id, propertyId, originValue), RSSpringModel<float>(), startValue_(startValue),
37 endValue_(endValue)
38 {
39 // spring model is not initialized, so we can't calculate estimated duration
40 }
41
DumpAnimationInfo(std::string & out) const42 void RSRenderInterpolatingSpringAnimation::DumpAnimationInfo(std::string& out) const
43 {
44 out += "Type:RSRenderInterpolatingSpringAnimation";
45 RSRenderPropertyType type = RSRenderPropertyType::INVALID;
46 if (property_ != nullptr) {
47 type = property_->GetPropertyType();
48 out += ", ModifierType: " + std::to_string(static_cast<int16_t>(property_->GetModifierType()));
49 } else {
50 out += ", ModifierType: INVALID";
51 }
52 out += ", StartValue: " + RSAnimationTraceUtils::GetInstance().ParseRenderPropertyVaule(startValue_, type);
53 out += ", EndValue: " + RSAnimationTraceUtils::GetInstance().ParseRenderPropertyVaule(endValue_, type);
54 }
55
SetSpringParameters(float response,float dampingRatio,float normalizedInitialVelocity,float minimumAmplitudeRatio)56 void RSRenderInterpolatingSpringAnimation::SetSpringParameters(
57 float response, float dampingRatio, float normalizedInitialVelocity, float minimumAmplitudeRatio)
58 {
59 response_ = response;
60 dampingRatio_ = std::clamp(dampingRatio, SPRING_MIN_DAMPING_RATIO, SPRING_MAX_DAMPING_RATIO);
61 normalizedInitialVelocity_ = normalizedInitialVelocity;
62 minimumAmplitudeRatio_ = minimumAmplitudeRatio;
63 }
64
SetZeroThreshold(float zeroThreshold)65 void RSRenderInterpolatingSpringAnimation::SetZeroThreshold(float zeroThreshold)
66 {
67 constexpr float ZERO = 0.0f;
68 if (zeroThreshold < ZERO) {
69 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::SetZeroThreshold: invalid threshold value.");
70 needLogicallyFinishCallback_ = false;
71 return;
72 }
73 zeroThreshold_ = zeroThreshold;
74 needLogicallyFinishCallback_ = true;
75 }
76
OnSetFraction(float fraction)77 void RSRenderInterpolatingSpringAnimation::OnSetFraction(float fraction)
78 {
79 if (valueEstimator_ == nullptr) {
80 return;
81 }
82 valueEstimator_->UpdateAnimationValue(fraction, GetAdditive());
83 SetValueFraction(fraction);
84 fractionChangeInfo_ = { true, fraction };
85 }
86
UpdateFractionAfterContinue()87 void RSRenderInterpolatingSpringAnimation::UpdateFractionAfterContinue()
88 {
89 auto& [bChangeFraction, valueFraction] = fractionChangeInfo_;
90 if (bChangeFraction) {
91 SetFractionInner(CalculateTimeFraction(valueFraction));
92 bChangeFraction = false;
93 valueFraction = 0.0f;
94 }
95 }
96
CalculateTimeFraction(float targetFraction)97 float RSRenderInterpolatingSpringAnimation::CalculateTimeFraction(float targetFraction)
98 {
99 int secondTime = std::ceil(static_cast<float>(GetDuration()) / SECOND_TO_MS);
100 if (secondTime <= 0) {
101 return FRACTION_MIN;
102 }
103 int64_t frameTimes = MAX_FRAME_TIME_FRACTION * secondTime;
104 float lastFraction = FRACTION_MIN;
105 for (int time = 1; time <= frameTimes; time++) {
106 float frameFraction = static_cast<float>(time) / frameTimes;
107 frameFraction = std::clamp(frameFraction, 0.0f, 1.0f);
108 auto mappedTime = frameFraction * GetDuration() * MILLISECOND_TO_SECOND;
109 float displacement = 1.0f + CalculateDisplacement(mappedTime);
110 if (lastFraction <= targetFraction && displacement >= targetFraction) {
111 return frameFraction;
112 }
113 lastFraction = displacement;
114 }
115 return FRACTION_MIN;
116 }
117
OnAnimate(float fraction)118 void RSRenderInterpolatingSpringAnimation::OnAnimate(float fraction)
119 {
120 if (valueEstimator_ == nullptr) {
121 ROSEN_LOGD("RSRenderInterpolatingSpringAnimation::OnAnimate, valueEstimator_ is nullptr.");
122 return;
123 }
124 if (GetPropertyId() == 0) {
125 // calculateAnimationValue_ is embedded modify for stat animate frame drop
126 calculateAnimationValue_ = false;
127 return;
128 } else if (ROSEN_EQ(fraction, 1.0f)) {
129 valueEstimator_->UpdateAnimationValue(1.0f, GetAdditive());
130 return;
131 }
132 auto mappedTime = fraction * GetDuration() * MILLISECOND_TO_SECOND;
133 float displacement = 1.0f + CalculateDisplacement(mappedTime);
134 SetValueFraction(displacement);
135 valueEstimator_->UpdateAnimationValue(displacement, GetAdditive());
136 if (GetNeedLogicallyFinishCallback() && (animationFraction_.GetRemainingRepeatCount() == 1)) {
137 auto interpolationValue = valueEstimator_->Estimate(displacement, startValue_, endValue_);
138 auto endValue = animationFraction_.GetCurrentIsReverseCycle() ? startValue_ : endValue_;
139 auto velocity = CalculateVelocity(mappedTime);
140 auto zeroValue = startValue_ - startValue_;
141 if (interpolationValue != nullptr && !interpolationValue->IsNearEqual(endValue, zeroThreshold_)) {
142 return;
143 }
144 if (velocity != nullptr && (velocity * FRAME_TIME_INTERVAL)->IsNearEqual(zeroValue, zeroThreshold_)) {
145 CallLogicallyFinishCallback();
146 needLogicallyFinishCallback_ = false;
147 }
148 }
149 }
150
OnInitialize(int64_t time)151 void RSRenderInterpolatingSpringAnimation::OnInitialize(int64_t time)
152 {
153 // set the initial status of spring model
154 initialOffset_ = -1.0f;
155 initialVelocity_ = initialOffset_ * (-normalizedInitialVelocity_);
156 CalculateSpringParameters();
157 // use duration calculated by spring model as animation duration
158 SetDuration(std::lroundf(EstimateDuration() * SECOND_TO_MILLISECOND));
159 // this will set needInitialize_ to false
160 RSRenderPropertyAnimation::OnInitialize(time);
161 }
162
InitValueEstimator()163 void RSRenderInterpolatingSpringAnimation::InitValueEstimator()
164 {
165 if (valueEstimator_ == nullptr) {
166 valueEstimator_ = property_->CreateRSValueEstimator(RSValueEstimatorType::CURVE_VALUE_ESTIMATOR);
167 }
168 if (valueEstimator_) {
169 valueEstimator_->InitCurveAnimationValue(property_, startValue_, endValue_, lastValue_);
170 } else {
171 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::InitValueEstimator, valueEstimator_ is nullptr.");
172 }
173 }
174
CalculateVelocity(float time) const175 std::shared_ptr<RSRenderPropertyBase> RSRenderInterpolatingSpringAnimation::CalculateVelocity(float time) const
176 {
177 if (valueEstimator_ == nullptr) {
178 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::CalculateVelocity, valueEstimator_ is nullptr.");
179 return nullptr;
180 }
181 constexpr float TIME_INTERVAL = 1e-6f; // 1e-6f : 1 microsecond
182 float currentDisplacement = 1.0f + CalculateDisplacement(time);
183 float nextDisplacement = 1.0f + CalculateDisplacement(time + TIME_INTERVAL);
184 auto velocity = (valueEstimator_->Estimate(nextDisplacement, startValue_, endValue_) -
185 valueEstimator_->Estimate(currentDisplacement, startValue_, endValue_)) * (1 / TIME_INTERVAL);
186
187 return velocity;
188 }
189
GetNeedLogicallyFinishCallback() const190 bool RSRenderInterpolatingSpringAnimation::GetNeedLogicallyFinishCallback() const
191 {
192 return needLogicallyFinishCallback_;
193 }
194
CallLogicallyFinishCallback() const195 void RSRenderInterpolatingSpringAnimation::CallLogicallyFinishCallback() const
196 {
197 NodeId targetId = GetTargetId();
198 AnimationId animationId = GetAnimationId();
199 uint64_t token = GetToken();
200
201 std::unique_ptr<RSCommand> command =
202 std::make_unique<RSAnimationCallback>(targetId, animationId, token, LOGICALLY_FINISHED);
203 RSMessageProcessor::Instance().AddUIMessage(ExtractPid(animationId), std::move(command));
204 }
205 } // namespace Rosen
206 } // namespace OHOS