• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_animation_rate_decider.h"
17 
18 #include <cmath>
19 #include <string>
20 
21 #include "common/rs_common_hook.h"
22 #include "common/rs_optional_trace.h"
23 #include "modifier/rs_render_property.h"
24 #include "platform/common/rs_log.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 constexpr int32_t DEFAULT_PREFERRED_FPS = 120;
29 
Reset()30 void RSAnimationRateDecider::Reset()
31 {
32     frameRateRange_.Reset();
33     decisionElements_.clear();
34 }
35 
AddDecisionElement(PropertyId id,const PropertyValue & velocity,FrameRateRange range)36 void RSAnimationRateDecider::AddDecisionElement(PropertyId id, const PropertyValue& velocity, FrameRateRange range)
37 {
38     if (!isEnabled_) {
39         return;
40     }
41     if (!velocity && !range.IsValid() && range.componentScene_ == ComponentScene::UNKNOWN_SCENE) {
42         return;
43     }
44     PropertyValue data = nullptr;
45     if (velocity != nullptr) {
46         data = velocity->Clone();
47     }
48     if (decisionElements_.find(id) != decisionElements_.end()) {
49         auto& element = decisionElements_[id];
50         if (data != nullptr) {
51             element.first = element.first ? element.first + data : data;
52         }
53         element.second.Merge(range);
54     } else {
55         decisionElements_.emplace(id, std::make_pair(data, range));
56     }
57 }
58 
MakeDecision(const FrameRateGetFunc & func)59 void RSAnimationRateDecider::MakeDecision(const FrameRateGetFunc& func)
60 {
61     if (!isEnabled_) {
62         frameRateRange_.Set(0, RANGE_MAX_REFRESHRATE, DEFAULT_PREFERRED_FPS);
63         return;
64     }
65     for (const auto& [id, element] : decisionElements_) {
66         FrameRateRange propertyRange;
67         RS_OPTIONAL_TRACE_BEGIN("MakeDecision property id: [" + std::to_string(id) + "]");
68         if (element.first != nullptr && func != nullptr) {
69             int32_t preferred = CalculatePreferredRate(element.first, func);
70             if (preferred > 0) {
71                 propertyRange = {0, RANGE_MAX_REFRESHRATE, preferred};
72                 propertyRange.componentScene_ = element.second.componentScene_;
73             }
74         }
75         FrameRateRange finalRange;
76         if (propertyRange.IsValid()) {
77             finalRange = propertyRange;
78             if (element.second.IsValid() && element.second.preferred_ < propertyRange.preferred_) {
79                 finalRange = element.second;
80             }
81         } else {
82             finalRange = element.second;
83         }
84         RsCommonHook::Instance().GetComponentPowerFps(finalRange);
85         frameRateRange_.Merge(finalRange);
86         RS_OPTIONAL_TRACE_END();
87     }
88 }
89 
GetFrameRateRange() const90 const FrameRateRange& RSAnimationRateDecider::GetFrameRateRange() const
91 {
92     return frameRateRange_;
93 }
94 
CalculatePreferredRate(const PropertyValue & property,const FrameRateGetFunc & func)95 int32_t RSAnimationRateDecider::CalculatePreferredRate(const PropertyValue& property, const FrameRateGetFunc& func)
96 {
97     switch (property->GetPropertyType()) {
98         case RSRenderPropertyType::PROPERTY_VECTOR4F:
99             return ProcessVector4f(property, func);
100         case RSRenderPropertyType::PROPERTY_VECTOR2F:
101             return ProcessVector2f(property, func);
102         case RSRenderPropertyType::PROPERTY_FLOAT:
103             return ProcessFloat(property, func);
104         default:
105             return 0;
106     }
107 }
108 
ProcessVector4f(const PropertyValue & property,const FrameRateGetFunc & func)109 int32_t RSAnimationRateDecider::ProcessVector4f(const PropertyValue& property, const FrameRateGetFunc& func)
110 {
111     auto animatableProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector4f>>(property);
112     auto propertyUnit = property->GetPropertyUnit();
113     if (!animatableProperty || propertyUnit != RSPropertyUnit::PIXEL_POSITION) {
114         return 0;
115     }
116     auto data = animatableProperty->Get();
117     // Vector4f data include data[0], data[1], data[2], data[3]
118     // data[0], data[1] indicate the speed of the position moves
119     // data[2], data[3] indicate the speed of the width and height change
120     int32_t matchFpsByPosition = func(propertyUnit, sqrt(data[0] * data[0] + data[1] * data[1]), absArea_, absLength_);
121     float velocityX = data[2] * nodeScaleX_;
122     float velocityY = data[3] * nodeScaleY_;
123     int32_t matchFpsBySize = func(RSPropertyUnit::PIXEL_SIZE,
124         sqrt(velocityX * velocityX + velocityY * velocityY), absArea_, absLength_);
125     return std::max(matchFpsByPosition, matchFpsBySize);
126 }
127 
ProcessVector2f(const PropertyValue & property,const FrameRateGetFunc & func)128 int32_t RSAnimationRateDecider::ProcessVector2f(const PropertyValue& property, const FrameRateGetFunc& func)
129 {
130     float velocity = 0.0f;
131     if (property->GetPropertyUnit() == RSPropertyUnit::RATIO_SCALE) {
132         auto animatableProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector2f>>(property);
133         if (animatableProperty != nullptr) {
134             auto data = animatableProperty->Get();
135             // Vector2f data include data[0], data[1]
136             float velocityX = data[0] * nodeWidth_;
137             float velocityY = data[1] * nodeHeight_;
138             velocity = sqrt(velocityX * velocityX + velocityY * velocityY);
139         }
140     } else {
141         // for other animation type such as translate
142         velocity = property->ToFloat();
143     }
144     return func(property->GetPropertyUnit(), velocity, absArea_, absLength_);
145 }
146 
ProcessFloat(const PropertyValue & property,const FrameRateGetFunc & func)147 int32_t RSAnimationRateDecider::ProcessFloat(const PropertyValue& property, const FrameRateGetFunc& func)
148 {
149     auto propertyUnit = property->GetPropertyUnit();
150     float propertyValue = property->ToFloat();
151     if (propertyUnit == RSPropertyUnit::ANGLE_ROTATION) {
152         // get the longest from height and width, record as H.
153         float height = std::max(nodeWidth_ * nodeScaleX_, nodeHeight_ * nodeScaleY_);
154         // V = W * R = W * (H / 2) = w * (2 * pi) * (H / 2) / 360 = w * pi * H / 360
155         // let w = propertyValue => w *= H * FLOAT_PI / 360
156         // 360 means 360 angle, relative to 2 * pi radian.
157         propertyValue *= height * FLOAT_PI / 360;
158         ROSEN_LOGD("%{public}s, ANGLE_ROTATION scene, propertyValue: %{public}f", __func__, propertyValue);
159     }
160     return func(propertyUnit, propertyValue, absArea_, absLength_);
161 }
162 } // namespace Rosen
163 } // namespace OHOS
164