1 /*
2 * Copyright (c) 2024-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 "rs_vsync_rate_reduce_manager.h"
17 #include <parameters.h>
18 #include <memory>
19 #include <ratio>
20 #include <thread>
21 #include <unordered_set>
22 #include "common/rs_obj_abs_geometry.h"
23 #include "common/rs_optional_trace.h"
24 #include "graphic_feature_param_manager.h"
25 #include "main_thread/rs_main_thread.h"
26 #include "platform/common/rs_log.h"
27 #include "rs_trace.h"
28
29 namespace OHOS {
30 namespace Rosen {
31
32 namespace {
33 // reduce the app refresh rate by ratio on the frame rate of entire system.
34 // if frame rate is 120, ratio of 1 means 120, 2 means 60, 3 means 40, 4 means 30
35 // vsync rate table, first dimension means the balance level as one frame duration increased
36 // second dimension means the occlusion level
37 constexpr int VSYNC_RATE_TABLE[][4] = {
38 {1, 1, 2, 2},
39 {1, 2, 2, 3},
40 {2, 2, 3, 3},
41 {2, 2, 3, 4},
42 {2, 3, 4, 4},
43 };
44 constexpr float V_VAL_MIN = 0.0f;
45 constexpr float V_VAL_MAX = 1.0f;
46 constexpr float WORKLOAD_TIMES[] = {1.0f, 1.5f, 2.0f, 2.5f};
47 constexpr float V_VAL_INTERVALS[] = {V_VAL_MAX, 0.75f, 0.5f, 0.25f, V_VAL_MIN};
48 constexpr int BALANCE_FRAME_COUNT = 3;
49 constexpr int WORKLOAD_TIMES_SIZE = sizeof(WORKLOAD_TIMES) / sizeof(WORKLOAD_TIMES[0]);
50 constexpr int WORKLOAD_LEVEL_COUNT = sizeof(VSYNC_RATE_TABLE) / sizeof(VSYNC_RATE_TABLE[0]);
51 // v_val of the v-rate result
52 constexpr float V_VAL_LEVEL_1 = 1.0f;
53 constexpr float V_VAL_LEVEL_2 = 0.8f;
54 constexpr float V_VAL_LEVEL_3 = 0.6f;
55 constexpr float V_VAL_LEVEL_4 = 0.4f;
56 constexpr float V_VAL_LEVEL_5 = 0.2f;
57 // ratio of area, such as biggest Rect and total visible Area
58 constexpr float CONTINUOUS_RATIO_LEVEL_0 = 4.0f / 8.0f;
59 constexpr float CONTINUOUS_RATIO_LEVEL_1 = 3.0f / 8.0f;
60 constexpr float CONTINUOUS_RATIO_LEVEL_2 = 2.0f / 8.0f;
61 constexpr float CONTINUOUS_RATIO_LEVEL_3 = 1.0f / 8.0f;
62 constexpr float CONTINUOUS_RATIO_LEVEL_4 = 1.0f / 10.0f;
63 constexpr float CONTINUOUS_RATIO_LEVEL_5 = 1.0f / 12.0f;
64 constexpr int64_t PERIOD_CHECK_THRESHOLD = 1000 * 1000 * 1000; // 1000,000,000ns = 1.0s
65 constexpr int32_t DEFAULT_RATE = 1;
66 constexpr int32_t SIMI_VISIBLE_RATE = 2;
67 constexpr int32_t SYSTEM_ANIMATED_SCENES_RATE = 2;
68 constexpr int32_t INVISBLE_WINDOW_RATE = 10;
69 constexpr int32_t MIN_REFRESH_RATE = 30;
70 } // Anonymous namespace
71
SetFocusedNodeId(NodeId focusedNodeId)72 void RSVsyncRateReduceManager::SetFocusedNodeId(NodeId focusedNodeId)
73 {
74 if (!vRateReduceEnabled_) {
75 return;
76 }
77 focusedNodeId_ = focusedNodeId;
78 }
79
PushWindowNodeId(NodeId nodeId)80 void RSVsyncRateReduceManager::PushWindowNodeId(NodeId nodeId)
81 {
82 if (!vRateReduceEnabled_) {
83 return;
84 }
85 curAllMainAndLeashWindowNodesIds_.emplace_back(nodeId);
86 }
87
ClearLastVisMapForVsyncRate()88 void RSVsyncRateReduceManager::ClearLastVisMapForVsyncRate()
89 {
90 if (!vRateReduceEnabled_) {
91 return;
92 }
93 lastVisMapForVSyncVisLevel_.clear();
94 }
95
FrameDurationBegin()96 void RSVsyncRateReduceManager::FrameDurationBegin()
97 {
98 if (!vRateConditionQualified_) {
99 return;
100 }
101 curTime_ = Now();
102 }
103
FrameDurationEnd()104 void RSVsyncRateReduceManager::FrameDurationEnd()
105 {
106 if (!vRateConditionQualified_) {
107 return;
108 }
109 if (oneFramePeriod_ > 0) {
110 float val = static_cast<float>(Now() - curTime_) / static_cast<float>(oneFramePeriod_);
111 EnqueueFrameDuration(val);
112 }
113 curTime_ = 0;
114 }
115
SetIsReduceBySystemAnimatedScenes(bool isReduceBySystemAnimatedScenes)116 void RSVsyncRateReduceManager::SetIsReduceBySystemAnimatedScenes(bool isReduceBySystemAnimatedScenes)
117 {
118 if (!vRateReduceEnabled_) {
119 return;
120 }
121 isReduceBySystemAnimatedScenes_ = isReduceBySystemAnimatedScenes;
122 }
123
EnqueueFrameDuration(float duration)124 void RSVsyncRateReduceManager::EnqueueFrameDuration(float duration)
125 {
126 std::lock_guard<std::mutex> lock(mutexFrameDuration_);
127 while (frameDurations_.size() >= BALANCE_FRAME_COUNT) {
128 frameDurations_.pop_front();
129 }
130 frameDurations_.push_back(duration);
131 }
132
CollectSurfaceVsyncInfo(const ScreenInfo & screenInfo,RSSurfaceRenderNode & surfaceNode)133 void RSVsyncRateReduceManager::CollectSurfaceVsyncInfo(const ScreenInfo& screenInfo, RSSurfaceRenderNode& surfaceNode)
134 {
135 if (!vRateConditionQualified_) {
136 return;
137 }
138 if (surfaceNode.IsHardwareEnabledTopSurface()) {
139 return;
140 }
141 if (!surfaceNode.IsSCBNode() || surfaceNode.GetDstRect().IsEmpty() || surfaceNode.IsLeashWindow()) {
142 return;
143 }
144 const auto& nodeId = surfaceNode.GetId();
145 if (surfaceVRateMap_.find(nodeId) != surfaceVRateMap_.end()) {
146 return;
147 }
148 const auto& nodeName = surfaceNode.GetName();
149 auto& geoPtr = surfaceNode.GetRenderProperties().GetBoundsGeometry();
150 if (geoPtr == nullptr) {
151 RS_LOGE("CollectSurfaceVsyncInfo geoPtr is null %{public}s", nodeName.c_str());
152 return;
153 }
154 auto& appAbsRect = geoPtr->GetAbsRect();
155 int width = static_cast<int>(std::round(appAbsRect.width_ * screenInfo.GetRogWidthRatio()));
156 int height = static_cast<int>(std::round(appAbsRect.height_ * screenInfo.GetRogHeightRatio()));
157 SurfaceVRateInfo vRateInfo;
158 vRateInfo.name = nodeName;
159 vRateInfo.nodeId = nodeId;
160 vRateInfo.visibleRegion = surfaceNode.GetVisibleRegion();
161 vRateInfo.appWindowArea = width * height;
162 surfaceVRateMap_.emplace(nodeId, std::move(vRateInfo));
163 }
164
SetUniVsync()165 void RSVsyncRateReduceManager::SetUniVsync()
166 {
167 if (!vRateConditionQualified_) {
168 return;
169 }
170 RS_TRACE_FUNC();
171 UpdateRatesLevel();
172 CalcRates();
173 NotifyVRates();
174 }
175
UpdateRatesLevel()176 int RSVsyncRateReduceManager::UpdateRatesLevel()
177 {
178 float totalDuration = 0;
179 {
180 std::lock_guard<std::mutex> lock(mutexFrameDuration_);
181 if (frameDurations_.size() < BALANCE_FRAME_COUNT) {
182 return curRatesLevel_;
183 }
184 for (int i = 0; i < BALANCE_FRAME_COUNT; i++) {
185 totalDuration = totalDuration + frameDurations_[i];
186 }
187 frameDurations_.pop_front();
188 }
189 int plusLevel = -1;
190 for (int i = WORKLOAD_TIMES_SIZE; i > 0; --i) {
191 if (totalDuration > static_cast<float>(BALANCE_FRAME_COUNT) * WORKLOAD_TIMES[i - 1]) {
192 plusLevel = i;
193 break;
194 }
195 }
196 int tempLevel = plusLevel > 0 ? plusLevel : (curRatesLevel_ + plusLevel);
197 tempLevel = tempLevel > 0 ? tempLevel : 0;
198 curRatesLevel_ = (tempLevel >= WORKLOAD_LEVEL_COUNT) ? WORKLOAD_LEVEL_COUNT - 1 : tempLevel;
199 RS_LOGD("curRatesLevel: [%{public}d], tempLevel: [%{public}d]", curRatesLevel_, tempLevel);
200 return curRatesLevel_;
201 }
202
CalcRates()203 void RSVsyncRateReduceManager::CalcRates()
204 {
205 if (isSystemAnimatedScenes_) {
206 for (const auto& [nodeId, vRateInfo]: surfaceVRateMap_) {
207 vSyncRateMap_[nodeId] = SYSTEM_ANIMATED_SCENES_RATE;
208 auto iter = lastVSyncRateMap_.find(nodeId);
209 SetVSyncRatesChanged(iter == lastVSyncRateMap_.end() || iter->second != SYSTEM_ANIMATED_SCENES_RATE);
210 RS_OPTIONAL_TRACE_NAME_FMT("CalcRates name=%s id=%" PRIu64 ",rate=%d,isSysAni=%d", vRateInfo.name.c_str(),
211 nodeId, SYSTEM_ANIMATED_SCENES_RATE, isSystemAnimatedScenes_);
212 RS_LOGD("CalcRates name=%{public}s id=%{public}" PRIu64 ",rate=%{public}d,isSysAni=%{public}d",
213 vRateInfo.name.c_str(), nodeId, SYSTEM_ANIMATED_SCENES_RATE, isSystemAnimatedScenes_);
214 }
215 return;
216 }
217 for (const auto& [nodeId, vRateInfo]: surfaceVRateMap_) {
218 double vVal = 0;
219 int visArea = vRateInfo.visibleRegion.Area();
220 if (nodeId == focusedNodeId_ ||
221 visArea >= std::round(vRateInfo.appWindowArea * CONTINUOUS_RATIO_LEVEL_0)) {
222 vVal = V_VAL_LEVEL_1;
223 } else if (visArea <= std::round(vRateInfo.appWindowArea * CONTINUOUS_RATIO_LEVEL_5)) {
224 vVal = 0;
225 } else {
226 RectI maxVisRect = CalcMaxVisibleRect(vRateInfo.visibleRegion, vRateInfo.appWindowArea).ToRectI();
227 vVal = CalcVValByAreas(vRateInfo.appWindowArea, maxVisRect.width_ * maxVisRect.height_, visArea);
228 }
229 auto lastIter = lastVSyncRateMap_.find(nodeId);
230 if (vVal >= V_VAL_MAX && (lastIter == lastVSyncRateMap_.end() || lastIter->second <= DEFAULT_RATE)) {
231 continue;
232 }
233 int rate = GetRateByBalanceLevel(vVal);
234 vSyncRateMap_[nodeId] = rate;
235 SetVSyncRatesChanged(lastIter == lastVSyncRateMap_.end() || lastIter->second != rate);
236 RS_OPTIONAL_TRACE_NAME_FMT("CalcRates name=%s id=%" PRIu64 ",vVal=%.2f,rate=%d,isSysAni=%d",
237 vRateInfo.name.c_str(), nodeId, vVal, rate, isSystemAnimatedScenes_);
238 RS_LOGD("CalcRates name=%{public}s nodeid=%{public}" PRIu64
239 ",vVal=%{public}.2f,rate=%{public}d,isSysAni=%{public}d",
240 vRateInfo.name.c_str(), nodeId, vVal, rate, isSystemAnimatedScenes_);
241 }
242 }
243
NotifyVRates()244 void RSVsyncRateReduceManager::NotifyVRates()
245 {
246 if (vSyncRateMap_.empty() || !CheckNeedNotify()) {
247 return;
248 }
249 linkersRateMap_.clear();
250 for (const auto& [nodeId, rate]: vSyncRateMap_) {
251 std::vector<uint64_t> linkerIds = appVSyncDistributor_->GetSurfaceNodeLinkerIds(nodeId);
252 if (rate != 0 && RSSystemParameters::GetVRateControlEnabled()) {
253 for (auto linkerId : linkerIds) {
254 linkersRateMap_.emplace(linkerId, rate);
255 RS_OPTIONAL_TRACE_NAME_FMT("NotifyVRates linkerid = %" PRIu64 " nodeId=%" PRIu64
256 " rate=%d isSysAnimate=%d", linkerId, nodeId, rate, isSystemAnimatedScenes_);
257 RS_LOGD("NotifyVRates linkerid = %{public}" PRIu64 " nodeId=%{public}"
258 PRIu64 " rate=%{public}d isSysAnimate=%{public}d", linkerId, nodeId, rate, isSystemAnimatedScenes_);
259 }
260 }
261 auto iter = lastVSyncRateMap_.find(nodeId);
262 if (iter != lastVSyncRateMap_.end() && iter->second == rate) {
263 continue;
264 }
265 if (RSSystemParameters::GetVRateControlEnabled()) {
266 needPostTask_.exchange(true);
267 }
268 appVSyncDistributor_->SetQosVSyncRate(nodeId, rate, isSystemAnimatedScenes_);
269 }
270
271 lastVSyncRateMap_ = vSyncRateMap_;
272 }
GetRateByBalanceLevel(double vVal)273 int RSVsyncRateReduceManager::GetRateByBalanceLevel(double vVal)
274 {
275 if (vVal <= 0) {
276 return std::numeric_limits<int>::max();
277 }
278 if (vVal >= V_VAL_INTERVALS[0]) {
279 return DEFAULT_RATE;
280 }
281 if (curRatesLevel_ > WORKLOAD_LEVEL_COUNT - 1) {
282 RS_LOGE("GetRateByBalanceLevel curRatesLevel error");
283 return DEFAULT_RATE;
284 }
285 int minRate = rsRefreshRate_ / static_cast<uint32_t>(MIN_REFRESH_RATE);
286 auto& rates = VSYNC_RATE_TABLE[curRatesLevel_];
287 size_t intervalsSize = sizeof(V_VAL_INTERVALS) / sizeof(float);
288 for (size_t i = 1; i < intervalsSize; ++i) {
289 if (vVal > V_VAL_INTERVALS[i]) {
290 return std::min(minRate, rates[i - 1]);
291 }
292 }
293 return std::numeric_limits<int>::max();
294 }
295
GetMaxVerticalRect(const Occlusion::Region & region)296 inline Occlusion::Rect RSVsyncRateReduceManager::GetMaxVerticalRect(const Occlusion::Region ®ion)
297 {
298 Occlusion::Rect maxRect;
299 auto& regionRects = region.GetRegionRects();
300 for (const auto& regionRect : regionRects) {
301 if (regionRect.Area() > maxRect.Area()) {
302 maxRect = regionRect;
303 }
304 }
305 return maxRect;
306 }
307
CalcMaxVisibleRect(const Occlusion::Region & region,int appWindowArea)308 Occlusion::Rect RSVsyncRateReduceManager::CalcMaxVisibleRect(const Occlusion::Region ®ion,
309 int appWindowArea)
310 {
311 int maxRArea = 0;
312 Occlusion::Rect maxRect;
313 Occlusion::Region srcRegion = region;
314 Occlusion::Rect srcBound = region.GetBound();
315 int minArea = std::round(appWindowArea * CONTINUOUS_RATIO_LEVEL_5);
316
317 const std::vector<Occlusion::Rect>& rects = region.GetRegionRects();
318 std::unordered_set<int> xPositionSet = {srcBound.left_, srcBound.right_};
319 std::vector<int> xPositions;
320 for (const auto &rect: rects) {
321 if (rect.Area() > maxRArea) {
322 maxRect = rect;
323 maxRArea = maxRect.Area();
324 }
325 xPositionSet.emplace(rect.left_);
326 xPositionSet.emplace(rect.right_);
327 }
328 if (maxRArea >= std::round(appWindowArea * CONTINUOUS_RATIO_LEVEL_1)) {
329 return maxRect;
330 }
331 xPositions.assign(xPositionSet.begin(), xPositionSet.end());
332 std::sort(xPositions.begin(), xPositions.end());
333 for (size_t i = 0; i < xPositions.size() - 1; ++i) {
334 for (size_t j = i + 1; j < xPositions.size(); ++j) {
335 Occlusion::Rect subBound(xPositions[i], srcBound.top_, xPositions[j], srcBound.bottom_);
336 int baseArea = std::max(maxRArea, minArea);
337 if (subBound.Area() <= baseArea) {
338 continue;
339 }
340 Occlusion::Region subRegion{subBound};
341 Occlusion::Region verticalRegion = subRegion.And(srcRegion);
342 if (verticalRegion.Area() <= baseArea) {
343 continue;
344 }
345 Occlusion::Rect tmpRect = GetMaxVerticalRect(verticalRegion);
346 if (tmpRect.Area() > maxRArea) {
347 maxRect = tmpRect;
348 maxRArea = tmpRect.Area();
349 }
350 }
351 }
352 return maxRect;
353 }
354
CalcVValByAreas(int windowArea,int maxVisRectArea,int visTotalArea)355 float RSVsyncRateReduceManager::CalcVValByAreas(int windowArea, int maxVisRectArea, int visTotalArea)
356 {
357 int level0Area = std::round(windowArea * CONTINUOUS_RATIO_LEVEL_0);
358 int level1Area = std::round(windowArea * CONTINUOUS_RATIO_LEVEL_1);
359 if (visTotalArea >= level0Area || maxVisRectArea >= level1Area) {
360 return V_VAL_LEVEL_1;
361 }
362 int level2Area = std::round(windowArea * CONTINUOUS_RATIO_LEVEL_2);
363 if (visTotalArea >= level1Area || maxVisRectArea >= level2Area) {
364 return V_VAL_LEVEL_2;
365 }
366 int level3Area = std::round(windowArea * CONTINUOUS_RATIO_LEVEL_3);
367 if (visTotalArea >= level2Area || maxVisRectArea >= level3Area) {
368 return V_VAL_LEVEL_3;
369 }
370 int level4Area = std::round(windowArea * CONTINUOUS_RATIO_LEVEL_4);
371 if (visTotalArea >= level3Area || maxVisRectArea >= level4Area) {
372 return V_VAL_LEVEL_4;
373 }
374 int level5Area = std::round(windowArea * CONTINUOUS_RATIO_LEVEL_5);
375 if (visTotalArea >= level4Area || maxVisRectArea >= level5Area) {
376 return V_VAL_LEVEL_5;
377 }
378 return V_VAL_MIN;
379 }
380
Now()381 uint64_t RSVsyncRateReduceManager::Now()
382 {
383 return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch())
384 .count();
385 }
386
SetVSyncRateByVisibleLevel(std::map<NodeId,RSVisibleLevel> & visMapForVsyncRate,std::vector<RSBaseRenderNode::SharedPtr> & curAllSurfaces)387 void RSVsyncRateReduceManager::SetVSyncRateByVisibleLevel(std::map<NodeId, RSVisibleLevel>& visMapForVsyncRate,
388 std::vector<RSBaseRenderNode::SharedPtr>& curAllSurfaces)
389 {
390 if (!vRateConditionQualified_) {
391 return;
392 }
393 if (!RSMainThread::Instance()->IsSystemAnimatedScenesListEmpty()) {
394 visMapForVsyncRate.clear();
395 for (auto it = curAllSurfaces.rbegin(); it != curAllSurfaces.rend(); ++it) {
396 auto curSurface = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
397 if (curSurface == nullptr || curSurface->GetDstRect().IsEmpty() || curSurface->IsLeashWindow()) {
398 continue;
399 }
400 visMapForVsyncRate[curSurface->GetId()] = RSVisibleLevel::RS_SYSTEM_ANIMATE_SCENE;
401 }
402 isReduceBySystemAnimatedScenes_ = true;
403 }
404 NotifyVSyncRates(visMapForVsyncRate);
405 }
406
CheckNeedNotify()407 bool RSVsyncRateReduceManager::CheckNeedNotify()
408 {
409 bool surfaceIdsChanged = lastAllMainAndLeashWindowNodesIds_ != curAllMainAndLeashWindowNodesIds_;
410 bool focusChanged = lastFocusedNodeId_ != focusedNodeId_;
411 bool needRefresh = !isSystemAnimatedScenes_ && isReduceBySystemAnimatedScenes_;
412 bool notifyCdt = vSyncRatesChanged_ || surfaceIdsChanged || focusChanged || needRefresh;
413 RS_LOGD("CheckNeedNotify notifyCdt=%{public}d %{public}s%{public}s%{public}s%{public}s%{public}s", notifyCdt,
414 isSystemAnimatedScenes_ ? "sysAnimated|" : "", needRefresh ? "needR|" : "", vSyncRatesChanged_ ? "ratesC|" : "",
415 surfaceIdsChanged ? "surfaceIdsC|" : "", focusChanged ? "focusIdC" : "");
416 RS_TRACE_NAME_FMT("CheckNeedNotify notifyCdt=%d %s%s%s%s%s", notifyCdt,
417 isSystemAnimatedScenes_ ? "sysAnimated|" : "", needRefresh ? "needR|" : "", vSyncRatesChanged_ ? "ratesC|" : "",
418 surfaceIdsChanged ? "surfaceIdsC|" : "", focusChanged ? "focusIdC" : "");
419 if (!notifyCdt) {
420 return false;
421 }
422 if (surfaceIdsChanged) {
423 lastAllMainAndLeashWindowNodesIds_ = curAllMainAndLeashWindowNodesIds_;
424 }
425 if (focusChanged) {
426 lastFocusedNodeId_ = focusedNodeId_;
427 }
428 if (needRefresh) {
429 isReduceBySystemAnimatedScenes_ = false;
430 }
431 if (surfaceIdsChanged || needRefresh) {
432 for (const auto& [nodeId, rate]: lastVSyncRateMap_) {
433 if (vSyncRateMap_.find(nodeId) == vSyncRateMap_.end()) {
434 vSyncRateMap_.emplace(nodeId, DEFAULT_RATE);
435 }
436 }
437 }
438 if (isSystemAnimatedScenes_) {
439 isReduceBySystemAnimatedScenes_ = true;
440 }
441 return true;
442 }
443
NotifyVSyncRates(const std::map<NodeId,RSVisibleLevel> & vSyncVisLevelMap)444 void RSVsyncRateReduceManager::NotifyVSyncRates(const std::map<NodeId, RSVisibleLevel>& vSyncVisLevelMap)
445 {
446 RS_TRACE_NAME_FMT("NotifyVSyncRates vSyncRates.size=[%lu]", vSyncVisLevelMap.size());
447 if (vSyncVisLevelMap.empty()) {
448 return;
449 }
450 auto notifyVsyncFunc = [distributor = appVSyncDistributor_] (NodeId nodeId, RSVisibleLevel level) {
451 bool isSysAnimate = false;
452 int32_t rate = DEFAULT_RATE;
453 if (level == RSVisibleLevel::RS_SEMI_DEFAULT_VISIBLE) {
454 rate = SIMI_VISIBLE_RATE;
455 } else if (level == RSVisibleLevel::RS_SYSTEM_ANIMATE_SCENE) {
456 isSysAnimate = true;
457 rate = SYSTEM_ANIMATED_SCENES_RATE;
458 } else if (level == RSVisibleLevel::RS_INVISIBLE) {
459 rate = INVISBLE_WINDOW_RATE;
460 } else {
461 rate = DEFAULT_RATE;
462 }
463 distributor->SetQosVSyncRate(nodeId, rate, isSysAnimate);
464 RS_OPTIONAL_TRACE_NAME_FMT("NotifyVSyncRates nodeId=%" PRIu64 " rate=%d isSysAnimate=%d", nodeId, rate,
465 isSysAnimate);
466 };
467
468 bool isVisibleChanged = lastVisMapForVSyncVisLevel_.size() != vSyncVisLevelMap.size();
469 if (!isVisibleChanged) {
470 auto iterCur = vSyncVisLevelMap.begin();
471 auto iterLast = lastVisMapForVSyncVisLevel_.begin();
472 for (; iterCur != vSyncVisLevelMap.end(); iterCur++, iterLast++) {
473 if (iterCur->first != iterLast->first || iterCur->second != iterLast->second) {
474 isVisibleChanged = true;
475 notifyVsyncFunc(iterCur->first, iterCur->second);
476 }
477 }
478 if (isVisibleChanged) {
479 lastVisMapForVSyncVisLevel_ = vSyncVisLevelMap;
480 }
481 } else {
482 lastVisMapForVSyncVisLevel_.clear();
483 for (const auto& [nodeId, visLevel] : vSyncVisLevelMap) {
484 notifyVsyncFunc(nodeId, visLevel);
485 lastVisMapForVSyncVisLevel_.emplace(nodeId, visLevel);
486 }
487 }
488 }
489
GetVRateIsSupport()490 bool RSVsyncRateReduceManager::GetVRateIsSupport()
491 {
492 auto vRateFeatureParam = GraphicFeatureParamManager::GetInstance().GetFeatureParam(FEATURE_CONFIGS[VRate]);
493 if (vRateFeatureParam == nullptr) {
494 RS_LOGE("Get vRateFeatureParam failed, vRateFeatureParam is nullptr");
495 return false;
496 }
497 auto vRatePatam = std::static_pointer_cast<VRateParam>(vRateFeatureParam);
498 if (vRatePatam == nullptr) {
499 RS_LOGE("Get vRatePatam failed, vRatePatam is nullptr");
500 return false;
501 }
502 RS_LOGI("GetVRateIsSupport: %{public}d", static_cast<int>(vRatePatam->GetVRateEnable()));
503 return vRatePatam->GetVRateEnable();
504 }
505
Init(const sptr<VSyncDistributor> & appVSyncDistributor)506 void RSVsyncRateReduceManager::Init(const sptr<VSyncDistributor>& appVSyncDistributor)
507 {
508 appVSyncDistributor_ = appVSyncDistributor;
509 isDeviceSupprotVRate_ = GetVRateIsSupport();
510 vRateReduceEnabled_ = isDeviceSupprotVRate_ && RSSystemParameters::GetVSyncControlEnabled();
511 RS_LOGI("Init vRateReduceEnabled_ is %{public}d", vRateReduceEnabled_);
512 }
513
ResetFrameValues(uint32_t rsRefreshRate)514 void RSVsyncRateReduceManager::ResetFrameValues(uint32_t rsRefreshRate)
515 {
516 vRateConditionQualified_ = false;
517 if (!vRateReduceEnabled_) {
518 return;
519 }
520 focusedNodeId_ = 0;
521 surfaceVRateMap_.clear();
522 isSystemAnimatedScenes_ = !RSMainThread::Instance()->IsSystemAnimatedScenesListEmpty();
523 vSyncRatesChanged_ = false;
524 vSyncRateMap_.clear();
525 curAllMainAndLeashWindowNodesIds_.clear();
526 visMapForVSyncVisLevel_.clear();
527 vRateConditionQualified_ = rsRefreshRate > 0 && appVSyncDistributor_ != nullptr;
528 if (!vRateConditionQualified_) {
529 return;
530 }
531 oneFramePeriod_ = PERIOD_CHECK_THRESHOLD / static_cast<int64_t>(rsRefreshRate);
532 rsRefreshRate_ = rsRefreshRate;
533 }
534 } // namespace Rosen
535 } // namespace OHOS
536