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