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 "hgm_screen.h"
17 
18 #include <cmath>
19 #include "hgm_log.h"
20 #include "hgm_task_handle_thread.h"
21 
22 namespace OHOS::Rosen {
HgmScreen()23 HgmScreen::HgmScreen() {}
24 
HgmScreen(ScreenId id,int32_t mode,ScreenSize & screenSize)25 HgmScreen::HgmScreen(ScreenId id, int32_t mode, ScreenSize& screenSize)
26     : id_(id), activeModeId_(mode), width_(screenSize.width), height_(screenSize.height),
27     phyWidth_(screenSize.phyWidth), phyHeight_(screenSize.phyHeight)
28 {
29     auto screenLength = sqrt(pow(screenSize.width, 2) + pow(screenSize.height, 2));
30     auto phyScreenLength = sqrt(pow(screenSize.phyWidth, 2) + pow(screenSize.phyHeight, 2));
31     if (phyScreenLength != 0) {
32         ppi_ = screenLength / (phyScreenLength / INCH_2_MM);
33     }
34     if (screenSize.phyWidth != 0) {
35         xDpi_ = screenSize.width / (screenSize.phyWidth / INCH_2_MM);
36     }
37     if (screenSize.phyHeight != 0) {
38         yDpi_ = screenSize.height / (screenSize.phyHeight / INCH_2_MM);
39     }
40 }
41 
~HgmScreen()42 HgmScreen::~HgmScreen() {}
43 
GetActiveRefreshRate() const44 uint32_t HgmScreen::GetActiveRefreshRate() const
45 {
46     auto profilePtr = GetModeViaId(activeModeId_);
47     if (!profilePtr) {
48         HGM_LOGI("HgmScreen current mode is not supported, failed to get refreshrate");
49         return RATE_NOT_SUPPORTED;
50     }
51 
52     return profilePtr->GetRate();
53 }
54 
SetActiveRefreshRate(int32_t sceneId,uint32_t rate)55 int32_t HgmScreen::SetActiveRefreshRate(int32_t sceneId, uint32_t rate)
56 {
57     // check if this screen supports the requested rate
58     if (supportedRefreshRates_.find(rate) == supportedRefreshRates_.end()) {
59         HGM_LOGE("HgmScreen refreshrate %{public}u is not supported, abandoned", rate);
60         return HGM_ERROR;
61     }
62 
63     // decide if this rate should be accepted
64     if (!IfSwitchToRate(sceneId, rate)) {
65         return HGM_ERROR;
66     }
67 
68     int32_t modeIdToApply = GetModeIdViaRate(rate);
69     if (modeIdToApply >= 0) {
70         SetActiveModeId(modeIdToApply);
71     }
72     return modeIdToApply;
73 }
74 
SetRateAndResolution(int32_t sceneId,uint32_t rate,int32_t width,int32_t height)75 int32_t HgmScreen::SetRateAndResolution(int32_t sceneId, uint32_t rate, int32_t width, int32_t height)
76 {
77     if (!IfSwitchToRate(sceneId, rate)) {
78         return HGM_ERROR;
79     }
80 
81     int32_t modeIdToApply = GetModeIdViaResolutionAndRate(width, height, rate);
82     if (modeIdToApply >= 0) {
83         SetActiveModeId(modeIdToApply);
84     }
85     return modeIdToApply;
86 }
87 
SetRefreshRateRange(uint32_t minRate,uint32_t maxRate)88 int32_t HgmScreen::SetRefreshRateRange(uint32_t minRate, uint32_t maxRate)
89 {
90     minRefreshRateRange_ = minRate;
91     maxRefreshRateRange_ = maxRate;
92     return EXEC_SUCCESS;
93 }
94 
AddScreenModeInfo(int32_t width,int32_t height,uint32_t rate,int32_t modeId)95 int32_t HgmScreen::AddScreenModeInfo(int32_t width, int32_t height, uint32_t rate, int32_t modeId)
96 {
97     HgmTaskHandleThread::Instance().DetectMultiThreadingCalls();
98     if (supportedModeIds_.find(modeId) == supportedModeIds_.end()) {
99         supportedModeIds_.emplace(modeId);
100     } else {
101         return HGM_SCREEN_MODE_EXIST;
102     }
103 
104     if (supportedRefreshRates_.find(rate) == supportedRefreshRates_.end()) {
105         supportedRefreshRates_.emplace(rate);
106     }
107 
108     auto newProfile = std::make_shared<ScreenProfile>(width, height, rate, modeId);
109     screenModeInfos_.emplace_back(newProfile);
110     return EXEC_SUCCESS;
111 }
112 
SetActiveModeId(int32_t modeId)113 void HgmScreen::SetActiveModeId(int32_t modeId)
114 {
115     HGM_LOGD("HgmScreen setting activeModeId to %{public}d", modeId);
116     activeModeId_ = modeId;
117 }
118 
GetModeViaId(int32_t id) const119 std::shared_ptr<HgmScreen::ScreenProfile> HgmScreen::GetModeViaId(int32_t id) const
120 {
121     for (auto mode : screenModeInfos_) {
122         if (mode->GetModeId() != id) {
123             continue;
124         }
125         return mode;
126     }
127 
128     HGM_LOGW("HgmScreen failed to get activeMode via modeId : %{public}d", id);
129     return nullptr;
130 }
131 
IfSwitchToRate(int32_t sceneId,uint32_t rate) const132 bool HgmScreen::IfSwitchToRate(int32_t sceneId, uint32_t rate) const
133 {
134     // decides if a refreshrate switch will be accepted or not
135     auto profilePtr = GetModeViaId(activeModeId_);
136     bool ifSwitch = false;
137 
138     if (!profilePtr) {
139         return ifSwitch;
140     }
141 
142     if (rate == profilePtr->GetRate() || sceneId < 0) {
143         HGM_LOGI("HgmScreen Set framerate to %{public}u is rejected!!!", rate);
144         return ifSwitch;
145     }
146 
147     ifSwitch = true;
148     HGM_LOGD("HgmScreen Set framerate to %{public}u is accepted", rate);
149     return ifSwitch;
150 }
151 
GetModeIdViaRate(uint32_t rate) const152 int32_t HgmScreen::GetModeIdViaRate(uint32_t rate) const
153 {
154     // get the corresponding mode id with the given refreshrate, using the current resolution
155     auto supportedRates = supportedRefreshRates_.find(rate);
156     if (supportedRates == supportedRefreshRates_.end()) {
157         HGM_LOGE("HgmScreen freshrate %{public}u is not supported by any modeId", rate);
158         return HGM_ERROR;
159     }
160 
161     auto profilePtr = GetModeViaId(activeModeId_);
162     if (!profilePtr) {
163         HGM_LOGW("HgmScreen activeMode is not among supported modes");
164         return HGM_ERROR;
165     }
166 
167     HGM_LOGD("HgmScreen getting a new mode with the resolution of current mode : %{public}d", activeModeId_);
168     int32_t mode = GetModeIdViaResolutionAndRate(profilePtr->GetWidth(), profilePtr->GetHeight(), rate);
169     return mode;
170 }
171 
GetModeIdViaResolutionAndRate(int32_t width,int32_t height,uint32_t rate) const172 int32_t HgmScreen::GetModeIdViaResolutionAndRate(int32_t width, int32_t height, uint32_t rate) const
173 {
174     // get the corresponding mode id with the given resolution and refreshrate
175     for (const auto& mode : screenModeInfos_) {
176         if (mode->GetRate() != rate || mode->GetWidth() != width || mode->GetHeight() != height) {
177             continue;
178         }
179         int32_t modeIdFound = mode->GetModeId();
180         HGM_LOGD("HgmScreen mode : %{public}d is found for w : %{public}d, h : %{public}d, rate : %{public}u",
181             modeIdFound, width, height, rate);
182         return modeIdFound;
183     }
184 
185     HGM_LOGW("HgmScreen NO mode is found for w : %{public}d, h : %{public}d, rate : %{public}u",
186         width, height, rate);
187     return HGM_ERROR;
188 }
189 } // namespace OHOS::Rosen