1 /*
2  * Copyright (c) 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 "pipeline/rs_render_display_sync.h"
17 
18 #include <algorithm>
19 #include <vector>
20 
21 #include "common/rs_optional_trace.h"
22 #include "platform/common/rs_log.h"
23 
24 namespace OHOS {
25 namespace Rosen {
26 namespace {
27 constexpr int32_t MAX_DIVISOR_NUM = 15;
28 constexpr int32_t MIN_DIVISOR_FRAME_RATE = 10;
29 constexpr int32_t FRAME_RATE_THRESHOLD = 5;
30 const std::vector<int32_t> SOURCE_FRAME_RATES = {30, 60, 72, 90, 120}; // sorted
31 }
32 
RSRenderDisplaySync(NodeId id)33 RSRenderDisplaySync::RSRenderDisplaySync(NodeId id) : id_(id) {}
34 
RSRenderDisplaySync(std::weak_ptr<RSRenderAnimation> renderAnimation)35 RSRenderDisplaySync::RSRenderDisplaySync(std::weak_ptr<RSRenderAnimation> renderAnimation)
36     : renderAnimation_(renderAnimation) {}
37 
GetId() const38 uint64_t RSRenderDisplaySync::GetId() const
39 {
40     auto renderAnimation = renderAnimation_.lock();
41     if (renderAnimation) {
42         return renderAnimation->GetAnimationId();
43     }
44 
45     return id_;
46 }
47 
SetExpectedFrameRateRange(const FrameRateRange & range)48 void RSRenderDisplaySync::SetExpectedFrameRateRange(const FrameRateRange& range)
49 {
50     auto renderAnimation = renderAnimation_.lock();
51     if (renderAnimation) {
52         renderAnimation->SetFrameRateRange(range);
53     }
54 
55     if (expectedFrameRateRange_ != range) {
56         expectedFrameRateRange_ = range;
57         isSkipCountUpdate_ = true;
58         RS_LOGI("[RenderAnimation] Id: %{public}" PRIu64 " SetExpectedFrameRateRange"
59             "{%{public}d, %{public}d, %{public}d}", GetId(), expectedFrameRateRange_.min_,
60             expectedFrameRateRange_.max_, expectedFrameRateRange_.preferred_);
61     }
62 }
63 
GetExpectedFrameRange() const64 const FrameRateRange& RSRenderDisplaySync::GetExpectedFrameRange() const
65 {
66     return expectedFrameRateRange_;
67 }
68 
SetAnimateResult(std::tuple<bool,bool,bool> & result)69 void RSRenderDisplaySync::SetAnimateResult(std::tuple<bool, bool, bool>& result)
70 {
71     animateResult_ = result;
72 }
73 
GetAnimateResult() const74 std::tuple<bool, bool, bool> RSRenderDisplaySync::GetAnimateResult() const
75 {
76     return animateResult_;
77 }
78 
OnFrameSkip(uint64_t timestamp,int64_t period,bool isDisplaySyncEnabled)79 bool RSRenderDisplaySync::OnFrameSkip(uint64_t timestamp, int64_t period, bool isDisplaySyncEnabled)
80 {
81     if (!isDisplaySyncEnabled) {
82         referenceCount_ = 0;
83         return false;
84     }
85     if (period <= 0 || timestamp_ == timestamp || expectedFrameRateRange_.preferred_ == 0) {
86         return false;
87     }
88     bool isFrameSkip = false;
89     referenceCount_++;
90     timestamp_ = timestamp;
91 
92     if (currentPeriod_ != period) {
93         currentPeriod_ = period;
94         int32_t frameRate = round(1.0 / (static_cast<double>(currentPeriod_) / NS_TO_S));
95         frameRate = GetNearestFrameRate(frameRate, SOURCE_FRAME_RATES);
96         if (currentFrameRate_ != frameRate) {
97             currentFrameRate_ = frameRate;
98             referenceCount_ = 0;
99             isSkipCountUpdate_ = true;
100         }
101     }
102 
103     if (isSkipCountUpdate_) {
104         skipRateCount_ = CalcSkipRateCount(currentFrameRate_);
105         isSkipCountUpdate_ = false;
106     }
107     if (skipRateCount_ == 0) {
108         skipRateCount_ = 1; // default value
109     }
110 
111     if (referenceCount_ % skipRateCount_ != 0) {
112         isFrameSkip = true;
113     }
114     RS_OPTIONAL_TRACE_NAME_FMT(
115         "RSRenderDisplaySync::OnFrameSkip preferred: [%d] currentPeroid: [%d] isFrameSkip:[%d]",
116         expectedFrameRateRange_.preferred_, currentPeriod_, isFrameSkip);
117     RS_LOGD("[RenderAnimation] Id: %{public}" PRIu64 " preferred: %{public}d "
118         "isFrameSkip: %{public}d", GetId(), expectedFrameRateRange_.preferred_, isFrameSkip);
119     return isFrameSkip;
120 }
121 
CalcSkipRateCount(int32_t frameRate)122 int32_t RSRenderDisplaySync::CalcSkipRateCount(int32_t frameRate)
123 {
124     int32_t count = 0;
125     int32_t preferred = expectedFrameRateRange_.preferred_;
126     if (preferred == 0 || frameRate == 0) {
127         return count;
128     }
129     std::vector<int32_t> divisorRates;
130     for (int i = 1; i <= MAX_DIVISOR_NUM; i++) {
131         if (frameRate % i == 0 && frameRate / i >= MIN_DIVISOR_FRAME_RATE) {
132             divisorRates.emplace_back(frameRate / i);
133         }
134     }
135     std::sort(divisorRates.begin(), divisorRates.end());
136     auto divisorFrameRate = GetNearestFrameRate(preferred, divisorRates);
137     if (divisorFrameRate != 0) {
138         count = frameRate / divisorFrameRate;
139     }
140     return count;
141 }
142 
GetNearestFrameRate(int32_t num,const std::vector<int32_t> & rates)143 int32_t RSRenderDisplaySync::GetNearestFrameRate(int32_t num, const std::vector<int32_t>& rates)
144 {
145     int32_t rate = 0;
146     if (!rates.empty()) {
147         auto iter = std::lower_bound(rates.begin(), rates.end(), num);
148         if (iter == rates.end()) {
149             if (num - rates.back() <= FRAME_RATE_THRESHOLD) {
150                 rate = rates.back();
151             }
152         } else if (iter == rates.begin()) {
153             if (rates.front() - num <= FRAME_RATE_THRESHOLD) {
154                 rate = rates.front();
155             }
156         } else if (*iter == num) {
157             rate = *iter;
158         } else {
159             int32_t index = iter - rates.begin();
160             // compare the difference between the number of rates[index - 1] and rates[index]
161             int32_t lastInterval = num - rates[index - 1];
162             int32_t nextInterval = rates[index] - num;
163             if (lastInterval < nextInterval && lastInterval <= FRAME_RATE_THRESHOLD) {
164                 rate = rates[index - 1];
165             } else {
166                 rate = rates[index];
167             }
168         }
169     }
170     return rate;
171 }
172 } // namespace Rosen
173 } // namespace OHOS
174