• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "feature/hyper_graphic_manager/hgm_hardware_utils.h"
17 
18 #include "common/rs_optional_trace.h"
19 #include "parameters.h"
20 #include "pipeline/hardware_thread/rs_hardware_thread.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 namespace {
25 constexpr int64_t NS_MS_UNIT_CONVERSION = 1000000;
26 constexpr uint32_t DELAY_TIME_OFFSET = 100;
27 constexpr int32_t MAX_SETRATE_RETRY_COUNT = 20;
28 constexpr ScreenId MAX_HAL_DISPLAY_ID = 20;
29 }
30 
ExecuteSwitchRefreshRate(const std::shared_ptr<HdiOutput> output,uint32_t refreshRate)31 void HgmHardwareUtils::ExecuteSwitchRefreshRate(
32     const std::shared_ptr<HdiOutput> output, uint32_t refreshRate)
33 {
34     static bool refreshRateSwitch = system::GetBoolParameter("persist.hgm.refreshrate.enabled", true);
35     if (!refreshRateSwitch) {
36         RS_LOGD("refreshRateSwitch is off, currRefreshRate is %{public}d", refreshRate);
37         return;
38     }
39 
40     auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
41     if (hgmCore.GetFrameRateMgr() == nullptr) {
42         RS_LOGD("FrameRateMgr is null");
43         return;
44     }
45     ScreenId id = output->GetScreenId();
46     auto& hardwareThread = RSHardwareThread::Instance();
47     auto screen = hgmCore.GetScreen(id);
48     if (!screen || !screen->GetSelfOwnedScreenFlag()) {
49         return;
50     }
51     auto screenRefreshRateImme = hgmCore.GetScreenRefreshRateImme();
52     if (screenRefreshRateImme > 0) {
53         RS_LOGD("ExecuteSwitchRefreshRate:rate change: %{public}u -> %{public}u", refreshRate, screenRefreshRateImme);
54         refreshRate = screenRefreshRateImme;
55     }
56     ScreenId curScreenId = hgmCore.GetFrameRateMgr()->GetCurScreenId();
57     ScreenId lastCurScreenId = hgmCore.GetFrameRateMgr()->GetLastCurScreenId();
58     bool shouldSetRefreshRate = (refreshRate != hgmCore.GetScreenCurrentRefreshRate(id) ||
59                                  lastCurScreenId != curScreenId);
60     bool needRetrySetRate = false;
61     auto retryIter = setRateRetryMap_.find(id);
62     if (retryIter != setRateRetryMap_.end()) {
63         needRetrySetRate = retryIter->second.first;
64     }
65     if (shouldSetRefreshRate || needRetrySetRate) {
66         RS_LOGD("CommitAndReleaseLayers screenId %{public}d refreshRate %{public}d \
67             needRetrySetRate %{public}d", static_cast<int>(id), refreshRate, needRetrySetRate);
68         int32_t sceneId = (lastCurScreenId != curScreenId || needRetrySetRate) ? SWITCH_SCREEN_SCENE : 0;
69         hgmCore.GetFrameRateMgr()->SetLastCurScreenId(curScreenId);
70         int32_t status = hgmCore.SetScreenRefreshRate(id, sceneId, refreshRate, shouldSetRefreshRate);
71         if (retryIter != setRateRetryMap_.end()) {
72             retryIter->second.first = false;
73             retryIter->second.second = shouldSetRefreshRate ? 0 : retryIter->second.second;
74         }
75         if (status < EXEC_SUCCESS) {
76             RS_LOGD("HgmContext: failed to set refreshRate %{public}d, screenId %{public}" PRIu64 "",
77                 refreshRate, id);
78         }
79     }
80 }
81 
UpdateRetrySetRateStatus(ScreenId id,int32_t modeId,uint32_t setRateRet)82 void HgmHardwareUtils::UpdateRetrySetRateStatus(ScreenId id, int32_t modeId, uint32_t setRateRet)
83 {
84     if (auto retryIter = setRateRetryMap_.find(id); retryIter != setRateRetryMap_.end()) {
85         auto& [needRetrySetRate, setRateRetryCount] = retryIter->second;
86         needRetrySetRate = (setRateRet == static_cast<uint32_t>(StatusCode::SET_RATE_ERROR));
87         if (!needRetrySetRate) {
88             setRateRetryCount = 0;
89         } else if (setRateRetryCount < MAX_SETRATE_RETRY_COUNT) {
90             setRateRetryCount++;
91         } else {
92             RS_LOGW("skip retrying for ScreenId:%{public}" PRIu64 ", set refresh rate failed more than %{public}d",
93                 id, MAX_SETRATE_RETRY_COUNT);
94             needRetrySetRate = false;
95         }
96         RS_LOGD_IF(needRetrySetRate,
97             "RSHardwareThread: need retry set modeId %{public}" PRId32 ", ScreenId:%{public}" PRIu64, modeId, id);
98     }
99 }
100 
PerformSetActiveMode(std::shared_ptr<HdiOutput> output,uint64_t timestamp,uint64_t constraintRelativeTime)101 void HgmHardwareUtils::PerformSetActiveMode(
102     std::shared_ptr<HdiOutput> output, uint64_t timestamp, uint64_t constraintRelativeTime)
103 {
104     auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
105     auto screenManager = CreateOrGetScreenManager();
106     if (screenManager == nullptr) {
107         return;
108     }
109     vblankIdleCorrector_.ProcessScreenConstraint(timestamp, constraintRelativeTime);
110     HgmRefreshRates newRate = RSSystemProperties::GetHgmRefreshRatesEnabled();
111     if (hgmRefreshRates_ != newRate) {
112         hgmRefreshRates_ = newRate;
113         hgmCore.SetScreenRefreshRate(screenManager->GetDefaultScreenId(), 0, static_cast<int32_t>(hgmRefreshRates_));
114     }
115 
116     std::unique_ptr<std::unordered_map<ScreenId, int32_t>> modeMap(hgmCore.GetModesToApply());
117     if (modeMap == nullptr) {
118         return;
119     }
120 
121     RS_TRACE_NAME_FMT("HgmContext::PerformSetActiveMode setting active mode. rate: %d",
122         HgmCore::Instance().GetScreenCurrentRefreshRate(HgmCore::Instance().GetActiveScreenId()));
123     for (auto mapIter = modeMap->begin(); mapIter != modeMap->end(); ++mapIter) {
124         ScreenId id = mapIter->first;
125         int32_t modeId = mapIter->second;
126 
127         auto supportedModes = screenManager->GetScreenSupportedModes(id);
128         for (auto mode : supportedModes) {
129             RS_OPTIONAL_TRACE_NAME_FMT(
130                 "HgmContext check modes w:%" PRId32", h:%" PRId32", rate:%" PRId32", id:%" PRId32"",
131                 mode.GetScreenWidth(), mode.GetScreenHeight(), mode.GetScreenRefreshRate(), mode.GetScreenModeId());
132         }
133 
134         uint32_t ret = screenManager->SetScreenActiveMode(id, modeId);
135         if (id <= MAX_HAL_DISPLAY_ID) {
136             setRateRetryMap_.try_emplace(id, std::make_pair(false, 0));
137             UpdateRetrySetRateStatus(id, modeId, ret);
138         } else {
139             RS_LOGD("UpdateRetrySetRateStatus fail, invalid ScreenId:%{public}" PRIu64, id);
140         }
141 
142         auto pendingPeriod = hgmCore.GetIdealPeriod(hgmCore.GetScreenCurrentRefreshRate(id));
143         int64_t pendingTimestamp = static_cast<int64_t>(timestamp);
144         if (auto hdiBackend = HdiBackend::GetInstance(); hdiBackend != nullptr) {
145             hdiBackend->SetPendingMode(output, pendingPeriod, pendingTimestamp);
146             hdiBackend->StartSample(output);
147         }
148     }
149 }
150 
UpdateRefreshRateParam()151 void HgmHardwareUtils::UpdateRefreshRateParam()
152 {
153     // need to sync the hgm data from main thread.
154     // Temporary sync the timestamp to fix the duplicate time stamp issue.
155     auto& hgmCore = OHOS::Rosen::HgmCore::Instance();
156     bool directComposition = hgmCore.GetDirectCompositionFlag();
157     RS_LOGI_IF(DEBUG_COMPOSER, "GetRefreshRateData period is %{public}d", directComposition);
158     if (directComposition) {
159         hgmCore.SetDirectCompositionFlag(false);
160     }
161     if (directComposition) {
162         refreshRateParam_ = {
163             .rate = hgmCore.GetPendingScreenRefreshRate(),
164             .frameTimestamp = hgmCore.GetCurrentTimestamp(),
165             .actualTimestamp = hgmCore.GetActualTimestamp(),
166             .vsyncId = hgmCore.GetVsyncId(),
167             .constraintRelativeTime = hgmCore.GetPendingConstraintRelativeTime(),
168             .isForceRefresh = hgmCore.GetForceRefreshFlag(),
169             .fastComposeTimeStampDiff = hgmCore.GetFastComposeTimeStampDiff()
170         };
171     } else {
172         refreshRateParam_ = {
173             .rate = RSUniRenderThread::Instance().GetPendingScreenRefreshRate(),
174             .frameTimestamp = RSUniRenderThread::Instance().GetCurrentTimestamp(),
175             .actualTimestamp = RSUniRenderThread::Instance().GetActualTimestamp(),
176             .vsyncId = RSUniRenderThread::Instance().GetVsyncId(),
177             .constraintRelativeTime = RSUniRenderThread::Instance().GetPendingConstraintRelativeTime(),
178             .isForceRefresh = RSUniRenderThread::Instance().GetForceRefreshFlag(),
179             .fastComposeTimeStampDiff = RSUniRenderThread::Instance().GetFastComposeTimeStampDiff()
180         };
181     }
182 }
183 } // namespace Rosen
184 } // namespace OHOS