• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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