• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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