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 "common/rs_optional_trace.h"
20 #include "pipeline/rs_canvas_render_node.h"
21 #include "command/rs_message_processor.h"
22 #include "platform/common/rs_log.h"
23 #include "rs_profiler.h"
24
25 namespace OHOS {
26 namespace Rosen {
RSRenderAnimation(AnimationId id)27 RSRenderAnimation::RSRenderAnimation(AnimationId id) : id_(id) {}
28
DumpAnimation(std::string & out) const29 void RSRenderAnimation::DumpAnimation(std::string& out) const
30 {
31 out.append("Animation: [id:").append(std::to_string(id_)).append(", ");
32 DumpAnimationInfo(out);
33 out.append(", AnimationState:").append(std::to_string(static_cast<int>(state_)));
34 if (!targetName_.empty()) {
35 out.append(", NodeName:").append(targetName_);
36 }
37 out.append(", Duration:").append(std::to_string(animationFraction_.GetDuration()));
38 out.append(", runningTime:").append(std::to_string(animationFraction_.GetRunningTime()));
39 if (animationFraction_.GetStartDelay() != 0) {
40 out.append(", StartDelay:").append(std::to_string(animationFraction_.GetStartDelay()));
41 }
42 if (ROSEN_NE(animationFraction_.GetSpeed(), 1.0f)) {
43 out.append(", Speed:").append(std::to_string(animationFraction_.GetSpeed()));
44 }
45 if (animationFraction_.GetRepeatCount() != 1) {
46 out.append(", RepeatCount:").append(std::to_string(animationFraction_.GetRepeatCount()));
47 }
48 if (animationFraction_.GetAutoReverse()) {
49 out.append(", AutoReverse:").append(std::to_string(animationFraction_.GetAutoReverse()));
50 }
51 if (!animationFraction_.GetDirection()) {
52 out.append(", Direction:").append(std::to_string(animationFraction_.GetDirection()));
53 }
54 if (animationFraction_.GetFillMode() != FillMode::FORWARDS) {
55 out.append(", FillMode:").append(std::to_string(static_cast<int>(animationFraction_.GetFillMode())));
56 }
57 if (animationFraction_.GetRepeatCallbackEnable()) {
58 out.append(", RepeatCallbackEnable:").append(std::to_string(animationFraction_.GetRepeatCallbackEnable()));
59 }
60 out.append(", FrameRateRange_min:").append(std::to_string(animationFraction_.GetFrameRateRange().min_));
61 out.append(", FrameRateRange_max:").append(std::to_string(animationFraction_.GetFrameRateRange().max_));
62 out.append(", FrameRateRange_prefered:").append(std::to_string(animationFraction_.GetFrameRateRange().preferred_));
63 out.append(", FrameRateRange_componentScene:").append(animationFraction_.GetFrameRateRange().GetComponentName());
64 out.append(", Token:").append(std::to_string(token_));
65 out.append("]");
66 }
67
DumpAnimationInfo(std::string & out) const68 void RSRenderAnimation::DumpAnimationInfo(std::string& out) const
69 {
70 out.append("Type:Unknown");
71 }
72
GetAnimationId() const73 AnimationId RSRenderAnimation::GetAnimationId() const
74 {
75 return id_;
76 }
77
IsStarted() const78 bool RSRenderAnimation::IsStarted() const
79 {
80 return state_ != AnimationState::INITIALIZED;
81 }
82
IsRunning() const83 bool RSRenderAnimation::IsRunning() const
84 {
85 return state_ == AnimationState::RUNNING;
86 }
87
IsPaused() const88 bool RSRenderAnimation::IsPaused() const
89 {
90 return state_ == AnimationState::PAUSED;
91 }
92
IsFinished() const93 bool RSRenderAnimation::IsFinished() const
94 {
95 return state_ == AnimationState::FINISHED;
96 }
97
GetPropertyId() const98 PropertyId RSRenderAnimation::GetPropertyId() const
99 {
100 return 0;
101 }
102
Attach(RSRenderNode * renderNode)103 void RSRenderAnimation::Attach(RSRenderNode* renderNode)
104 {
105 if (target_ != nullptr) {
106 Detach();
107 }
108 target_ = renderNode;
109 if (target_ != nullptr) {
110 targetId_ = target_->GetId();
111 targetName_ = target_->GetNodeName();
112 }
113 OnAttach();
114 Start();
115 needUpdateStartTime_ = false;
116 }
117
Detach(bool forceDetach)118 void RSRenderAnimation::Detach(bool forceDetach)
119 {
120 if (!forceDetach) {
121 OnDetach();
122 }
123 target_ = nullptr;
124 targetId_ = 0;
125 targetName_ = "";
126 }
127
GetTargetId() const128 NodeId RSRenderAnimation::GetTargetId() const
129 {
130 return targetId_;
131 }
132
GetTargetName() const133 const std::string RSRenderAnimation::GetTargetName() const
134 {
135 return targetName_;
136 }
137
Start()138 void RSRenderAnimation::Start()
139 {
140 if (IsStarted()) {
141 ROSEN_LOGE("Failed to start animation, animation has started!");
142 return;
143 }
144
145 state_ = AnimationState::RUNNING;
146 needUpdateStartTime_ = true;
147 ProcessFillModeOnStart(animationFraction_.GetStartFraction());
148 }
149
Finish()150 void RSRenderAnimation::Finish()
151 {
152 RS_LOGI_LIMIT("Animation[%{public}" PRIu64 "] received finish", id_);
153 if (!IsPaused() && !IsRunning()) {
154 ROSEN_LOGD("Failed to finish animation, animation is not running!");
155 return;
156 }
157
158 state_ = AnimationState::FINISHED;
159 ProcessFillModeOnFinish(animationFraction_.GetEndFraction());
160 }
161
FinishOnPosition(RSInteractiveAnimationPosition pos)162 void RSRenderAnimation::FinishOnPosition(RSInteractiveAnimationPosition pos)
163 {
164 if (!IsPaused() && !IsRunning()) {
165 ROSEN_LOGD("Failed to finish animation, animation is not running!");
166 return;
167 }
168
169 state_ = AnimationState::FINISHED;
170
171 if (pos == RSInteractiveAnimationPosition::START) {
172 ProcessFillModeOnFinish(animationFraction_.GetStartFraction());
173 } else if (pos == RSInteractiveAnimationPosition::END) {
174 ProcessFillModeOnFinish(animationFraction_.GetEndFraction());
175 }
176 }
177
FinishOnCurrentPosition()178 void RSRenderAnimation::FinishOnCurrentPosition()
179 {
180 if (!IsPaused() && !IsRunning()) {
181 ROSEN_LOGD("Failed to finish animation, animation is not running!");
182 return;
183 }
184
185 state_ = AnimationState::FINISHED;
186 }
187
Pause()188 void RSRenderAnimation::Pause()
189 {
190 RS_LOGI_LIMIT("Animation[%{public}" PRIu64 "] received pause", id_);
191 if (!IsRunning()) {
192 ROSEN_LOGE("Failed to pause animation, animation is not running!");
193 return;
194 }
195
196 state_ = AnimationState::PAUSED;
197 }
198
Resume()199 void RSRenderAnimation::Resume()
200 {
201 RS_LOGI_LIMIT("Animation[%{public}" PRIu64 "] received resume", id_);
202 if (!IsPaused()) {
203 ROSEN_LOGE("Failed to resume animation, animation is not paused!");
204 return;
205 }
206
207 state_ = AnimationState::RUNNING;
208 needUpdateStartTime_ = true;
209
210 UpdateFractionAfterContinue();
211 }
212
SetFraction(float fraction)213 void RSRenderAnimation::SetFraction(float fraction)
214 {
215 if (!IsPaused()) {
216 ROSEN_LOGE("Failed to set fraction, animation is not paused!");
217 return;
218 }
219
220 fraction = std::min(std::max(fraction, 0.0f), 1.0f);
221 OnSetFraction(fraction);
222 }
223
SetReversedAndContinue()224 void RSRenderAnimation::SetReversedAndContinue()
225 {
226 if (!IsPaused()) {
227 ROSEN_LOGE("Failed to reverse animation, animation is not running!");
228 return;
229 }
230 SetReversed(true);
231 animationFraction_.SetDirectionAfterStart(ForwardDirection::REVERSE);
232 Resume();
233 }
234
235
SetReversed(bool isReversed)236 void RSRenderAnimation::SetReversed(bool isReversed)
237 {
238 if (!IsPaused() && !IsRunning()) {
239 ROSEN_LOGE("Failed to reverse animation, animation is not running!");
240 return;
241 }
242
243 animationFraction_.SetDirectionAfterStart(isReversed ? ForwardDirection::REVERSE : ForwardDirection::NORMAL);
244 }
245
GetTarget() const246 RSRenderNode* RSRenderAnimation::GetTarget() const
247 {
248 return target_;
249 }
250
SetFractionInner(float fraction)251 void RSRenderAnimation::SetFractionInner(float fraction)
252 {
253 animationFraction_.UpdateRemainTimeFraction(fraction);
254 }
255
ProcessFillModeOnStart(float startFraction)256 void RSRenderAnimation::ProcessFillModeOnStart(float startFraction)
257 {
258 auto fillMode = GetFillMode();
259 if (fillMode == FillMode::BACKWARDS || fillMode == FillMode::BOTH) {
260 OnAnimate(startFraction);
261 }
262 }
263
ProcessFillModeOnFinish(float endFraction)264 void RSRenderAnimation::ProcessFillModeOnFinish(float endFraction)
265 {
266 auto fillMode = GetFillMode();
267 if (fillMode == FillMode::FORWARDS || fillMode == FillMode::BOTH) {
268 OnAnimate(endFraction);
269 } else {
270 OnRemoveOnCompletion();
271 }
272 }
273
ProcessOnRepeatFinish()274 void RSRenderAnimation::ProcessOnRepeatFinish()
275 {
276 std::unique_ptr<RSCommand> command =
277 std::make_unique<RSAnimationCallback>(targetId_, id_, token_, REPEAT_FINISHED);
278 RSMessageProcessor::Instance().AddUIMessage(ExtractPid(id_), command);
279 }
280
Animate(int64_t time,int64_t & minLeftDelayTime)281 bool RSRenderAnimation::Animate(int64_t time, int64_t& minLeftDelayTime)
282 {
283 // calculateAnimationValue_ is embedded modify for stat animate frame drop
284 calculateAnimationValue_ = true;
285
286 if (!IsRunning()) {
287 ROSEN_LOGD("RSRenderAnimation::Animate, IsRunning is false!");
288 RS_OPTIONAL_TRACE_NAME_FMT("Animation[%llu] animate not running, state is [%d]", id_, state_);
289 return state_ == AnimationState::FINISHED;
290 }
291
292 // set start time and return
293 if (needUpdateStartTime_) {
294 SetStartTime(time);
295 minLeftDelayTime = 0;
296 return state_ == AnimationState::FINISHED;
297 }
298
299 // if time not changed since last frame, return
300 if (time == animationFraction_.GetLastFrameTime()) {
301 minLeftDelayTime = 0;
302 return state_ == AnimationState::FINISHED;
303 }
304
305 if (needInitialize_) {
306 // normally this only run once, but in spring animation with blendDuration, it may run multiple times
307 OnInitialize(time);
308 }
309
310 // calculate frame time interval in seconds
311 float frameInterval = (time - animationFraction_.GetLastFrameTime()) * 1.0f / NS_TO_S;
312
313 // convert time to fraction
314 auto [fraction, isInStartDelay, isFinished, isRepeatFinished] =
315 animationFraction_.GetAnimationFraction(time, minLeftDelayTime);
316 if (isInStartDelay) {
317 calculateAnimationValue_ = false;
318 ProcessFillModeOnStart(fraction);
319 ROSEN_LOGD("RSRenderAnimation::Animate, isInStartDelay is true");
320 return false;
321 }
322
323 RecordLastAnimateValue();
324 OnAnimate(fraction);
325 DumpFraction(fraction, time);
326 UpdateAnimateVelocity(frameInterval);
327
328 if (isRepeatFinished) {
329 ProcessOnRepeatFinish();
330 }
331 if (isFinished) {
332 RS_PROFILER_ANIMATION_DURATION_STOP(id_, time);
333 ProcessFillModeOnFinish(fraction);
334 ROSEN_LOGD("RSRenderAnimation::Animate, isFinished is true");
335 return true;
336 }
337 return isFinished;
338 }
339
SetStartTime(int64_t time)340 void RSRenderAnimation::SetStartTime(int64_t time)
341 {
342 RS_PROFILER_ANIMATION_DURATION_START(id_, time);
343
344 time = RS_PROFILER_ANIME_SET_START_TIME(id_, time);
345 animationFraction_.SetLastFrameTime(time);
346 needUpdateStartTime_ = false;
347 }
348
GetAnimateVelocity() const349 const std::shared_ptr<RSRenderPropertyBase>& RSRenderAnimation::GetAnimateVelocity() const
350 {
351 return animateVelocity_;
352 }
353
354 bool RSRenderAnimation::isCalcAnimateVelocity_ = true;
355 } // namespace Rosen
356 } // namespace OHOS
357