• 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.append("Type:RSRenderInterpolatingSpringAnimation");
45     DumpProperty(out);
46     RSPropertyType type = RSPropertyType::INVALID;
47     if (property_ != nullptr) {
48         type = property_->GetPropertyType();
49     }
50     out.append(", StartValue: ").append(RSAnimationTraceUtils::GetInstance().ParseRenderPropertyValue(startValue_));
51     out.append(", EndValue: ").append(RSAnimationTraceUtils::GetInstance().ParseRenderPropertyValue(endValue_));
52 }
53 
SetSpringParameters(float response,float dampingRatio,float normalizedInitialVelocity,float minimumAmplitudeRatio)54 void RSRenderInterpolatingSpringAnimation::SetSpringParameters(
55     float response, float dampingRatio, float normalizedInitialVelocity, float minimumAmplitudeRatio)
56 {
57     response_ = response;
58     dampingRatio_ = std::clamp(dampingRatio, SPRING_MIN_DAMPING_RATIO, SPRING_MAX_DAMPING_RATIO);
59     normalizedInitialVelocity_ = normalizedInitialVelocity;
60     minimumAmplitudeRatio_ = minimumAmplitudeRatio;
61 }
62 
SetZeroThreshold(float zeroThreshold)63 void RSRenderInterpolatingSpringAnimation::SetZeroThreshold(float zeroThreshold)
64 {
65     constexpr float ZERO = 0.0f;
66     if (zeroThreshold < ZERO) {
67         ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::SetZeroThreshold: invalid threshold value.");
68         needLogicallyFinishCallback_ = false;
69         return;
70     }
71     zeroThreshold_ = zeroThreshold;
72     needLogicallyFinishCallback_ = true;
73 }
74 
OnSetFraction(float fraction)75 void RSRenderInterpolatingSpringAnimation::OnSetFraction(float fraction)
76 {
77     if (valueEstimator_ == nullptr) {
78         return;
79     }
80     valueEstimator_->UpdateAnimationValue(fraction, GetAdditive());
81     SetValueFraction(fraction);
82     fractionChangeInfo_ = { true, fraction };
83 }
84 
UpdateFractionAfterContinue()85 void RSRenderInterpolatingSpringAnimation::UpdateFractionAfterContinue()
86 {
87     auto& [bChangeFraction, valueFraction] = fractionChangeInfo_;
88     if (bChangeFraction) {
89         SetFractionInner(CalculateTimeFraction(valueFraction));
90         bChangeFraction = false;
91         valueFraction = 0.0f;
92     }
93 }
94 
CalculateTimeFraction(float targetFraction)95 float RSRenderInterpolatingSpringAnimation::CalculateTimeFraction(float targetFraction)
96 {
97     int secondTime = std::ceil(static_cast<float>(GetDuration()) / SECOND_TO_MS);
98     if (secondTime <= 0) {
99         return FRACTION_MIN;
100     }
101     int64_t frameTimes = MAX_FRAME_TIME_FRACTION * secondTime;
102     float lastFraction = FRACTION_MIN;
103     for (int time = 1; time <= frameTimes; time++) {
104         float frameFraction = static_cast<float>(time) / frameTimes;
105         frameFraction = std::clamp(frameFraction, 0.0f, 1.0f);
106         auto mappedTime = frameFraction * GetDuration() * MILLISECOND_TO_SECOND;
107         float displacement = 1.0f + CalculateDisplacement(mappedTime);
108         if (lastFraction <= targetFraction && displacement >= targetFraction) {
109             return frameFraction;
110         }
111         lastFraction = displacement;
112     }
113     return FRACTION_MIN;
114 }
115 
OnAnimate(float fraction)116 void RSRenderInterpolatingSpringAnimation::OnAnimate(float fraction)
117 {
118     if (valueEstimator_ == nullptr) {
119         ROSEN_LOGD("RSRenderInterpolatingSpringAnimation::OnAnimate, valueEstimator_ is nullptr.");
120         return;
121     }
122     if (GetPropertyId() == 0) {
123         // calculateAnimationValue_ is embedded modify for stat animate frame drop
124         calculateAnimationValue_ = false;
125         return;
126     } else if (ROSEN_EQ(fraction, 1.0f)) {
127         valueEstimator_->UpdateAnimationValue(1.0f, GetAdditive());
128         return;
129     }
130     auto mappedTime = fraction * GetDuration() * MILLISECOND_TO_SECOND;
131     float displacement = 1.0f + CalculateDisplacement(mappedTime);
132     SetValueFraction(displacement);
133     valueEstimator_->UpdateAnimationValue(displacement, GetAdditive());
134     if (GetNeedLogicallyFinishCallback() && (animationFraction_.GetRemainingRepeatCount() == 1)) {
135         auto interpolationValue = valueEstimator_->Estimate(displacement, startValue_, endValue_);
136         auto endValue = animationFraction_.GetCurrentIsReverseCycle() ? startValue_ : endValue_;
137         auto velocity = CalculateVelocity(mappedTime);
138         auto zeroValue = startValue_ - startValue_;
139         if (interpolationValue != nullptr && !interpolationValue->IsNearEqual(endValue, zeroThreshold_)) {
140             return;
141         }
142         if (velocity != nullptr && (velocity * FRAME_TIME_INTERVAL)->IsNearEqual(zeroValue, zeroThreshold_)) {
143             CallLogicallyFinishCallback();
144             needLogicallyFinishCallback_ = false;
145         }
146     }
147 }
148 
OnInitialize(int64_t time)149 void RSRenderInterpolatingSpringAnimation::OnInitialize(int64_t time)
150 {
151     // set the initial status of spring model
152     initialOffset_ = -1.0f;
153     initialVelocity_ = initialOffset_ * (-normalizedInitialVelocity_);
154     CalculateSpringParameters();
155     // use duration calculated by spring model as animation duration
156     SetDuration(std::lroundf(EstimateDuration() * SECOND_TO_MILLISECOND));
157     // this will set needInitialize_ to false
158     RSRenderPropertyAnimation::OnInitialize(time);
159 }
160 
InitValueEstimator()161 void RSRenderInterpolatingSpringAnimation::InitValueEstimator()
162 {
163     if (valueEstimator_ == nullptr) {
164         valueEstimator_ = property_->CreateRSValueEstimator(RSValueEstimatorType::CURVE_VALUE_ESTIMATOR);
165     }
166     if (valueEstimator_) {
167         valueEstimator_->InitCurveAnimationValue(property_, startValue_, endValue_, lastValue_);
168     } else {
169         ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::InitValueEstimator, valueEstimator_ is nullptr.");
170     }
171 }
172 
CalculateVelocity(float time) const173 std::shared_ptr<RSRenderPropertyBase> RSRenderInterpolatingSpringAnimation::CalculateVelocity(float time) const
174 {
175     if (valueEstimator_ == nullptr) {
176         ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::CalculateVelocity, valueEstimator_ is nullptr.");
177         return nullptr;
178     }
179     constexpr float TIME_INTERVAL = 1e-6f; // 1e-6f : 1 microsecond
180     float currentDisplacement = 1.0f + CalculateDisplacement(time);
181     float nextDisplacement = 1.0f + CalculateDisplacement(time + TIME_INTERVAL);
182     auto velocity = (valueEstimator_->Estimate(nextDisplacement, startValue_, endValue_) -
183         valueEstimator_->Estimate(currentDisplacement, startValue_, endValue_)) * (1 / TIME_INTERVAL);
184 
185     return velocity;
186 }
187 
GetNeedLogicallyFinishCallback() const188 bool RSRenderInterpolatingSpringAnimation::GetNeedLogicallyFinishCallback() const
189 {
190     return needLogicallyFinishCallback_;
191 }
192 
CallLogicallyFinishCallback() const193 void RSRenderInterpolatingSpringAnimation::CallLogicallyFinishCallback() const
194 {
195     NodeId targetId = GetTargetId();
196     AnimationId animationId = GetAnimationId();
197     uint64_t token = GetToken();
198 
199     std::unique_ptr<RSCommand> command =
200         std::make_unique<RSAnimationCallback>(targetId, animationId, token, LOGICALLY_FINISHED);
201     RSMessageProcessor::Instance().AddUIMessage(ExtractPid(animationId), std::move(command));
202 }
203 } // namespace Rosen
204 } // namespace OHOS