1 /*
2  * Copyright (c) 2021-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_animation.h"
17 
18 #include "command/rs_animation_command.h"
19 #include "pipeline/rs_canvas_render_node.h"
20 #include "command/rs_message_processor.h"
21 #include "platform/common/rs_log.h"
22 #include "rs_profiler.h"
23 
24 namespace OHOS {
25 namespace Rosen {
RSRenderAnimation(AnimationId id)26 RSRenderAnimation::RSRenderAnimation(AnimationId id) : id_(id) {}
Marshalling(Parcel & parcel) const27 bool RSRenderAnimation::Marshalling(Parcel& parcel) const
28 {
29     // animationId, targetId
30     if (!(parcel.WriteUint64(id_))) {
31         ROSEN_LOGE("RSRenderAnimation::Marshalling, write id failed");
32         return false;
33     }
34     // RSAnimationTimingProtocol
35     if (!(parcel.WriteInt32(animationFraction_.GetDuration()) &&
36         parcel.WriteInt32(animationFraction_.GetStartDelay()) &&
37         parcel.WriteFloat(animationFraction_.GetSpeed()) &&
38         parcel.WriteInt32(animationFraction_.GetRepeatCount()) &&
39         parcel.WriteBool(animationFraction_.GetAutoReverse()) &&
40         parcel.WriteBool(animationFraction_.GetDirection()) &&
41         parcel.WriteInt32(static_cast<std::underlying_type<FillMode>::type>(animationFraction_.GetFillMode())) &&
42         parcel.WriteBool(animationFraction_.GetRepeatCallbackEnable()) &&
43         parcel.WriteInt32(animationFraction_.GetFrameRateRange().min_) &&
44         parcel.WriteInt32(animationFraction_.GetFrameRateRange().max_) &&
45         parcel.WriteInt32(animationFraction_.GetFrameRateRange().preferred_))) {
46         ROSEN_LOGE("RSRenderAnimation::Marshalling, write param failed");
47         return false;
48     }
49     return true;
50 }
51 
DumpAnimation(std::string & out) const52 void RSRenderAnimation::DumpAnimation(std::string& out) const
53 {
54     out += "Animation: [id:" + std::to_string(id_) + ", ";
55     DumpAnimationType(out);
56     out += ", AnimationState:" + std::to_string(static_cast<int>(state_));
57     out += ", StartDelay:" + std::to_string(animationFraction_.GetDuration());
58     out += ", Duration:" + std::to_string(animationFraction_.GetStartDelay());
59     out += ", Speed:" + std::to_string(animationFraction_.GetSpeed());
60     out += ", RepeatCount:" + std::to_string(animationFraction_.GetRepeatCount());
61     out += ", AutoReverse:" + std::to_string(animationFraction_.GetAutoReverse());
62     out += ", Direction:" + std::to_string(animationFraction_.GetDirection());
63     out += ", FillMode:" + std::to_string(static_cast<int>(animationFraction_.GetFillMode()));
64     out += ", RepeatCallbackEnable:" + std::to_string(animationFraction_.GetRepeatCallbackEnable());
65     out += ", FrameRateRange_min:" + std::to_string(animationFraction_.GetFrameRateRange().min_);
66     out += ", FrameRateRange_max:" + std::to_string(animationFraction_.GetFrameRateRange().max_);
67     out += ", FrameRateRange_prefered:" + std::to_string(animationFraction_.GetFrameRateRange().preferred_);
68     out += "]";
69 }
70 
DumpAnimationType(std::string & out) const71 void RSRenderAnimation::DumpAnimationType(std::string& out) const
72 {
73     out += "Type:Unknown";
74 }
75 
ParseParam(Parcel & parcel)76 bool RSRenderAnimation::ParseParam(Parcel& parcel)
77 {
78     int32_t duration = 0;
79     int32_t startDelay = 0;
80     int32_t repeatCount = 0;
81     int32_t fillMode = 0;
82     float speed = 0.0;
83     bool autoReverse = false;
84     bool direction = false;
85     bool isRepeatCallbackEnable = false;
86     int fpsMin = 0;
87     int fpsMax = 0;
88     int fpsPreferred = 0;
89     if (!(parcel.ReadUint64(id_) && parcel.ReadInt32(duration) && parcel.ReadInt32(startDelay) &&
90             parcel.ReadFloat(speed) && parcel.ReadInt32(repeatCount) && parcel.ReadBool(autoReverse) &&
91             parcel.ReadBool(direction) && parcel.ReadInt32(fillMode) && parcel.ReadBool(isRepeatCallbackEnable) &&
92             parcel.ReadInt32(fpsMin) && parcel.ReadInt32(fpsMax) && parcel.ReadInt32(fpsPreferred))) {
93         ROSEN_LOGE("RSRenderAnimation::ParseParam, read param failed");
94         return false;
95     }
96     RS_PROFILER_PATCH_NODE_ID(parcel, id_);
97     SetDuration(duration);
98     SetStartDelay(startDelay);
99     SetRepeatCount(repeatCount);
100     SetAutoReverse(autoReverse);
101     SetSpeed(speed);
102     SetDirection(direction);
103     SetFillMode(static_cast<FillMode>(fillMode));
104     SetRepeatCallbackEnable(isRepeatCallbackEnable);
105     SetFrameRateRange({fpsMin, fpsMax, fpsPreferred});
106     return true;
107 }
GetAnimationId() const108 AnimationId RSRenderAnimation::GetAnimationId() const
109 {
110     return id_;
111 }
112 
IsStarted() const113 bool RSRenderAnimation::IsStarted() const
114 {
115     return state_ != AnimationState::INITIALIZED;
116 }
117 
IsRunning() const118 bool RSRenderAnimation::IsRunning() const
119 {
120     return state_ == AnimationState::RUNNING;
121 }
122 
IsPaused() const123 bool RSRenderAnimation::IsPaused() const
124 {
125     return state_ == AnimationState::PAUSED;
126 }
127 
IsFinished() const128 bool RSRenderAnimation::IsFinished() const
129 {
130     return state_ == AnimationState::FINISHED;
131 }
132 
GetPropertyId() const133 PropertyId RSRenderAnimation::GetPropertyId() const
134 {
135     return 0;
136 }
137 
Attach(RSRenderNode * renderNode)138 void RSRenderAnimation::Attach(RSRenderNode* renderNode)
139 {
140     if (target_ != nullptr) {
141         Detach();
142     }
143     target_ = renderNode;
144     if (target_ != nullptr) {
145         targetId_ = target_->GetId();
146         targetName_ = target_->GetNodeName();
147         target_->CheckGroupableAnimation(GetPropertyId(), true);
148     }
149     OnAttach();
150     Start();
151     needUpdateStartTime_ = false;
152 }
153 
Detach(bool forceDetach)154 void RSRenderAnimation::Detach(bool forceDetach)
155 {
156     if (!forceDetach) {
157         OnDetach();
158         if (target_ != nullptr) {
159             target_->CheckGroupableAnimation(GetPropertyId(), false);
160         }
161     }
162     target_ = nullptr;
163 }
164 
GetTargetId() const165 NodeId RSRenderAnimation::GetTargetId() const
166 {
167     return targetId_;
168 }
169 
GetTargetName() const170 const std::string RSRenderAnimation::GetTargetName() const
171 {
172     return targetName_;
173 }
174 
Start()175 void RSRenderAnimation::Start()
176 {
177     if (IsStarted()) {
178         ROSEN_LOGE("Failed to start animation, animation has started!");
179         return;
180     }
181 
182     state_ = AnimationState::RUNNING;
183     needUpdateStartTime_ = true;
184     ProcessFillModeOnStart(animationFraction_.GetStartFraction());
185 }
186 
Finish()187 void RSRenderAnimation::Finish()
188 {
189     if (!IsPaused() && !IsRunning()) {
190         ROSEN_LOGD("Failed to finish animation, animation is not running!");
191         return;
192     }
193 
194     state_ = AnimationState::FINISHED;
195     ProcessFillModeOnFinish(animationFraction_.GetEndFraction());
196 }
197 
FinishOnPosition(RSInteractiveAnimationPosition pos)198 void RSRenderAnimation::FinishOnPosition(RSInteractiveAnimationPosition pos)
199 {
200     if (!IsPaused() && !IsRunning()) {
201         ROSEN_LOGD("Failed to finish animation, animation is not running!");
202         return;
203     }
204 
205     state_ = AnimationState::FINISHED;
206 
207     if (pos == RSInteractiveAnimationPosition::START) {
208         ProcessFillModeOnFinish(animationFraction_.GetStartFraction());
209     } else if (pos == RSInteractiveAnimationPosition::END) {
210         ProcessFillModeOnFinish(animationFraction_.GetEndFraction());
211     }
212 }
213 
FinishOnCurrentPosition()214 void RSRenderAnimation::FinishOnCurrentPosition()
215 {
216     if (!IsPaused() && !IsRunning()) {
217         ROSEN_LOGD("Failed to finish animation, animation is not running!");
218         return;
219     }
220 
221     state_ = AnimationState::FINISHED;
222 }
223 
Pause()224 void RSRenderAnimation::Pause()
225 {
226     if (!IsRunning()) {
227         ROSEN_LOGE("Failed to pause animation, animation is not running!");
228         return;
229     }
230 
231     state_ = AnimationState::PAUSED;
232 }
233 
Resume()234 void RSRenderAnimation::Resume()
235 {
236     if (!IsPaused()) {
237         ROSEN_LOGE("Failed to resume animation, animation is not paused!");
238         return;
239     }
240 
241     state_ = AnimationState::RUNNING;
242     needUpdateStartTime_ = true;
243 
244     UpdateFractionAfterContinue();
245 }
246 
SetFraction(float fraction)247 void RSRenderAnimation::SetFraction(float fraction)
248 {
249     if (!IsPaused()) {
250         ROSEN_LOGE("Failed to set fraction, animation is not paused!");
251         return;
252     }
253 
254     fraction = std::min(std::max(fraction, 0.0f), 1.0f);
255     OnSetFraction(fraction);
256 }
257 
SetReversedAndContinue()258 void RSRenderAnimation::SetReversedAndContinue()
259 {
260     if (!IsPaused()) {
261         ROSEN_LOGE("Failed to reverse animation, animation is not running!");
262         return;
263     }
264     SetReversed(true);
265     animationFraction_.SetDirectionAfterStart(ForwardDirection::REVERSE);
266     Resume();
267 }
268 
269 
SetReversed(bool isReversed)270 void RSRenderAnimation::SetReversed(bool isReversed)
271 {
272     if (!IsPaused() && !IsRunning()) {
273         ROSEN_LOGE("Failed to reverse animation, animation is not running!");
274         return;
275     }
276 
277     animationFraction_.SetDirectionAfterStart(isReversed ? ForwardDirection::REVERSE : ForwardDirection::NORMAL);
278 }
279 
GetTarget() const280 RSRenderNode* RSRenderAnimation::GetTarget() const
281 {
282     return target_;
283 }
284 
SetFractionInner(float fraction)285 void RSRenderAnimation::SetFractionInner(float fraction)
286 {
287     animationFraction_.UpdateRemainTimeFraction(fraction);
288 }
289 
ProcessFillModeOnStart(float startFraction)290 void RSRenderAnimation::ProcessFillModeOnStart(float startFraction)
291 {
292     auto fillMode = GetFillMode();
293     if (fillMode == FillMode::BACKWARDS || fillMode == FillMode::BOTH) {
294         OnAnimate(startFraction);
295     }
296 }
297 
ProcessFillModeOnFinish(float endFraction)298 void RSRenderAnimation::ProcessFillModeOnFinish(float endFraction)
299 {
300     auto fillMode = GetFillMode();
301     if (fillMode == FillMode::FORWARDS || fillMode == FillMode::BOTH) {
302         OnAnimate(endFraction);
303     } else {
304         OnRemoveOnCompletion();
305     }
306 }
307 
ProcessOnRepeatFinish()308 void RSRenderAnimation::ProcessOnRepeatFinish()
309 {
310     std::unique_ptr<RSCommand> command =
311         std::make_unique<RSAnimationCallback>(targetId_, id_, REPEAT_FINISHED);
312     RSMessageProcessor::Instance().AddUIMessage(ExtractPid(id_), command);
313 }
314 
Animate(int64_t time)315 bool RSRenderAnimation::Animate(int64_t time)
316 {
317     // calculateAnimationValue_ is embedded modify for stat animate frame drop
318     calculateAnimationValue_ = true;
319 
320     if (!IsRunning()) {
321         ROSEN_LOGD("RSRenderAnimation::Animate, IsRunning is false!");
322         return state_ == AnimationState::FINISHED;
323     }
324 
325     // set start time and return
326     if (needUpdateStartTime_) {
327         SetStartTime(time);
328         return state_ == AnimationState::FINISHED;
329     }
330 
331     // if time not changed since last frame, return
332     if (time == animationFraction_.GetLastFrameTime()) {
333         return state_ == AnimationState::FINISHED;
334     }
335 
336     if (needInitialize_) {
337         // normally this only run once, but in spring animation with blendDuration, it may run multiple times
338         OnInitialize(time);
339     }
340 
341     // calculate frame time interval in seconds
342     float frameInterval = (time - animationFraction_.GetLastFrameTime()) * 1.0f / NS_TO_S;
343 
344     // convert time to fraction
345     auto [fraction, isInStartDelay, isFinished, isRepeatFinished] = animationFraction_.GetAnimationFraction(time);
346     if (isInStartDelay) {
347         calculateAnimationValue_ = false;
348         ProcessFillModeOnStart(fraction);
349         ROSEN_LOGD("RSRenderAnimation::Animate, isInStartDelay is true");
350         return false;
351     }
352 
353     RecordLastAnimateValue();
354     OnAnimate(fraction);
355     DumpFraction(fraction, time);
356     UpdateAnimateVelocity(frameInterval);
357 
358     if (isRepeatFinished) {
359         ProcessOnRepeatFinish();
360     }
361     if (isFinished) {
362         ProcessFillModeOnFinish(fraction);
363         ROSEN_LOGD("RSRenderAnimation::Animate, isFinished is true");
364         return true;
365     }
366     return isFinished;
367 }
368 
SetStartTime(int64_t time)369 void RSRenderAnimation::SetStartTime(int64_t time)
370 {
371     animationFraction_.SetLastFrameTime(time);
372     needUpdateStartTime_ = false;
373 }
374 
GetAnimateVelocity() const375 const std::shared_ptr<RSRenderPropertyBase>& RSRenderAnimation::GetAnimateVelocity() const
376 {
377     return animateVelocity_;
378 }
379 
380 bool RSRenderAnimation::isCalcAnimateVelocity_ = true;
381 } // namespace Rosen
382 } // namespace OHOS
383