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