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