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