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