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 "rs_realtime_refresh_rate_manager.h"
17
18 #include <chrono>
19 #include <condition_variable>
20 #include <mutex>
21
22 #include "hgm_core.h"
23 #include "rs_trace.h"
24 #include "pipeline/main_thread/rs_main_thread.h"
25
26 namespace OHOS::Rosen {
Instance()27 RSRealtimeRefreshRateManager& RSRealtimeRefreshRateManager::Instance()
28 {
29 static RSRealtimeRefreshRateManager instance;
30 return instance;
31 }
32
SetShowRefreshRateEnabled(bool enabled,int32_t type)33 void RSRealtimeRefreshRateManager::SetShowRefreshRateEnabled(bool enabled, int32_t type)
34 {
35 RS_LOGD("SetShowRefreshRateEnabled: enabled[%{public}d] type[%{public}d]", enabled, type);
36 std::unique_lock<std::mutex> threadLock(threadMutex_);
37 auto frameRateMgr = HgmCore::Instance().GetFrameRateMgr();
38 if (frameRateMgr == nullptr ||
39 type <= static_cast<int32_t>(RealtimeRefreshRateType::START) ||
40 type >= static_cast<int32_t>(RealtimeRefreshRateType::END)) {
41 return;
42 }
43
44 RealtimeRefreshRateType enumType = static_cast<RealtimeRefreshRateType>(type);
45 if (enumType == RealtimeRefreshRateType::SHOW) {
46 if (showEnabled_ == enabled) {
47 return;
48 }
49 showEnabled_ = enabled;
50 } else if (enumType == RealtimeRefreshRateType::COLLECT) {
51 if (collectEnabled_ == enabled) {
52 return;
53 }
54 collectEnabled_ = enabled;
55 } else {
56 return;
57 }
58
59 StatisticsRefreshRateDataLocked(frameRateMgr);
60 }
61
StatisticsRefreshRateDataLocked(std::shared_ptr<HgmFrameRateManager> frameRateMgr)62 void RSRealtimeRefreshRateManager::StatisticsRefreshRateDataLocked(std::shared_ptr<HgmFrameRateManager> frameRateMgr)
63 {
64 if (!showEnabled_ && !collectEnabled_) {
65 HgmTaskHandleThread::Instance().RemoveEvent(EVENT_ID);
66 isCollectRefreshRateTaskRunning_ = false;
67 std::unique_lock<std::mutex> lock(showRealtimeFrameMutex_);
68 currRealtimeRefreshRateMap_.clear();
69 realtimeFrameCountMap_.clear();
70 return;
71 }
72
73 if (isCollectRefreshRateTaskRunning_) {
74 return;
75 }
76
77 startTime_ = std::chrono::steady_clock::now();
78 showRefreshRateTask_ = [this, frameRateMgr] () {
79 std::unique_lock<std::mutex> lock(showRealtimeFrameMutex_);
80 auto diff = std::chrono::duration_cast<std::chrono::nanoseconds>(
81 std::chrono::steady_clock::now() - startTime_);
82 for (auto [screenId, frameCount]: realtimeFrameCountMap_) {
83 uint32_t fps = std::round(frameCount * static_cast<float>(NS_PER_S) / diff.count());
84 fps = fps <= IDLE_FPS_THRESHOLD ? 1u : fps;
85 if (auto iter = currRealtimeRefreshRateMap_.find(screenId);
86 iter == currRealtimeRefreshRateMap_.end() || iter->second != fps) {
87 currRealtimeRefreshRateMap_[screenId] = fps;
88 isRealtimeRefreshRateChange_ = true;
89 }
90 }
91 auto refreshRate = HgmCore::Instance().GetScreenCurrentRefreshRate(frameRateMgr->GetCurScreenId());
92 if (isRealtimeRefreshRateChange_|| lastRefreshRate_ != refreshRate) {
93 lastRefreshRate_ = refreshRate;
94 isRealtimeRefreshRateChange_ = false;
95 if (showEnabled_) {
96 RSMainThread::Instance()->SetDirtyFlag();
97 RSMainThread::Instance()->RequestNextVSync();
98 }
99 }
100 startTime_ = std::chrono::steady_clock::now();
101 realtimeFrameCountMap_.clear();
102 HgmTaskHandleThread::Instance().PostEvent(EVENT_ID, showRefreshRateTask_, EVENT_INTERVAL);
103 };
104 isCollectRefreshRateTaskRunning_ = true;
105 HgmTaskHandleThread::Instance().PostEvent(EVENT_ID, showRefreshRateTask_, EVENT_INTERVAL);
106 }
107
GetRealtimeRefreshRate(ScreenId screenId)108 uint32_t RSRealtimeRefreshRateManager::GetRealtimeRefreshRate(ScreenId screenId)
109 {
110 {
111 std::unique_lock<std::mutex> threadLock(threadMutex_);
112 if (!showEnabled_ && !collectEnabled_) {
113 return 0;
114 }
115 }
116 if (screenId == INVALID_SCREEN_ID) {
117 auto frameRateMgr = HgmCore::Instance().GetFrameRateMgr();
118 if (frameRateMgr == nullptr) {
119 return DEFAULT_REALTIME_REFRESH_RATE;
120 }
121 screenId = frameRateMgr->GetCurScreenId();
122 }
123 std::unique_lock<std::mutex> lock(showRealtimeFrameMutex_);
124 if (auto iter = currRealtimeRefreshRateMap_.find(screenId); iter != currRealtimeRefreshRateMap_.end()) {
125 uint32_t currentRefreshRate = OHOS::Rosen::HgmCore::Instance().GetScreenCurrentRefreshRate(screenId);
126 if (iter->second > currentRefreshRate) {
127 return currentRefreshRate;
128 }
129 return iter->second;
130 }
131 return DEFAULT_REALTIME_REFRESH_RATE;
132 }
133 } // namespace OHOS::Rosen
134