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