1 /*
2  * Copyright (c) 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_round_corner_display_manager.h"
17 #include "platform/common/rs_system_properties.h"
18 #include "common/rs_optional_trace.h"
19 #include "common/rs_singleton.h"
20 #include "rs_trace.h"
21 
22 namespace OHOS {
23 namespace Rosen {
RoundCornerDisplayManager()24 RoundCornerDisplayManager::RoundCornerDisplayManager()
25 {
26     RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] Created \n", __func__);
27 }
28 
~RoundCornerDisplayManager()29 RoundCornerDisplayManager::~RoundCornerDisplayManager()
30 {
31     RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] Destroy \n", __func__);
32 }
33 
CheckExist(NodeId id)34 bool RoundCornerDisplayManager::CheckExist(NodeId id)
35 {
36     auto it = rcdMap_.find(id);
37     if (rcdMap_.end() == it) {
38         return false;
39     }
40     return true;
41 }
42 
AddLayer(const std::string & name,NodeId id,RoundCornerDisplayManager::RCDLayerType type)43 void RoundCornerDisplayManager::AddLayer(const std::string& name, NodeId id,
44     RoundCornerDisplayManager::RCDLayerType type)
45 {
46     std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
47     rcdlayerMap_[name] = {id, type};
48     RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] rendertargetNodeId:%{public}" PRIu64 " with rcd layer name %{public}s \n",
49         __func__, id, name.c_str());
50 }
51 
GetLayerPair(const std::string & layerName)52 std::pair<NodeId, RoundCornerDisplayManager::RCDLayerType> RoundCornerDisplayManager::GetLayerPair(
53     const std::string& layerName)
54 {
55     std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
56     auto it = rcdlayerMap_.find(layerName);
57     if (rcdlayerMap_.end() == it) {
58         return {0, RoundCornerDisplayManager::RCDLayerType::INVALID};
59     }
60     return rcdlayerMap_.at(layerName);
61 }
62 
CheckLayerIsRCD(const std::string & layerName)63 bool RoundCornerDisplayManager::CheckLayerIsRCD(const std::string& layerName)
64 {
65     std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
66     auto it = rcdlayerMap_.find(layerName);
67     if (rcdlayerMap_.end() == it) {
68         return false;
69     }
70     return true;
71 }
72 
AddRoundCornerDisplay(NodeId id)73 void RoundCornerDisplayManager::AddRoundCornerDisplay(NodeId id)
74 {
75     std::lock_guard<std::mutex> lock(rcdMapMut_);
76     if (CheckExist(id)) {
77         RS_LOGD_IF(DEBUG_PIPELINE,
78             "[%{public}s] nodeId:%{public}" PRIu64 " rcd module already exist, size:%{public}zd \n",
79             __func__, id, rcdMap_.size());
80         return;
81     }
82     auto rcd = std::make_shared<RoundCornerDisplay>(id);
83     rcdMap_[id] = rcd;
84     if (rcdMap_[id] == nullptr) {
85         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module create failed \n", __func__, id);
86         return;
87     }
88     rcdMap_[id]->InitOnce();
89     RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] size:%{public}zd rcd module after added for screen \n", __func__,
90         rcdMap_.size());
91 }
92 
RemoveRCDResource(NodeId id)93 void RoundCornerDisplayManager::RemoveRCDResource(NodeId id)
94 {
95     {
96         std::lock_guard<std::mutex> lock(rcdMapMut_);
97         RemoveRoundCornerDisplay(id);
98     }
99     {
100         std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
101         RemoveRCDLayerInfo(id);
102     }
103 }
104 
RemoveRoundCornerDisplay(NodeId id)105 void RoundCornerDisplayManager::RemoveRoundCornerDisplay(NodeId id)
106 {
107     if (!CheckExist(id)) {
108         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
109         return;
110     }
111     rcdMap_.erase(id);
112     RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module removed for screen \n", __func__,
113         id);
114 }
115 
RemoveRCDLayerInfo(NodeId id)116 void RoundCornerDisplayManager::RemoveRCDLayerInfo(NodeId id)
117 {
118     const auto& it = std::find_if(rcdlayerMap_.begin(), rcdlayerMap_.end(),
119         [id](const std::pair<std::string, std::pair<NodeId, RCDLayerType>>& p) {
120             return p.second.first == id;
121         });
122     if (rcdlayerMap_.end() == it) {
123         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd layer not exist \n", __func__, id);
124         return;
125     }
126     rcdlayerMap_.erase(it->first);
127     RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd layer removed for screen \n", __func__,
128         id);
129 }
130 
UpdateDisplayParameter(NodeId id,uint32_t width,uint32_t height)131 void RoundCornerDisplayManager::UpdateDisplayParameter(NodeId id, uint32_t width, uint32_t height)
132 {
133     std::lock_guard<std::mutex> lock(rcdMapMut_);
134     if (!CheckExist(id)) {
135         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
136         return;
137     }
138     if (rcdMap_[id] == nullptr) {
139         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
140         RemoveRoundCornerDisplay(id);
141         return;
142     }
143     rcdMap_[id]->UpdateDisplayParameter(width, height);
144 }
145 
UpdateNotchStatus(NodeId id,int status)146 void RoundCornerDisplayManager::UpdateNotchStatus(NodeId id, int status)
147 {
148     std::lock_guard<std::mutex> lock(rcdMapMut_);
149     if (!CheckExist(id)) {
150         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
151         return;
152     }
153     if (rcdMap_[id] == nullptr) {
154         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
155         RemoveRoundCornerDisplay(id);
156         return;
157     }
158     rcdMap_[id]->UpdateNotchStatus(status);
159 }
160 
UpdateOrientationStatus(NodeId id,ScreenRotation orientation)161 void RoundCornerDisplayManager::UpdateOrientationStatus(NodeId id, ScreenRotation orientation)
162 {
163     std::lock_guard<std::mutex> lock(rcdMapMut_);
164     if (!CheckExist(id)) {
165         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
166         return;
167     }
168     if (rcdMap_[id] == nullptr) {
169         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
170         RemoveRoundCornerDisplay(id);
171         return;
172     }
173     rcdMap_[id]->UpdateOrientationStatus(orientation);
174 }
175 
UpdateHardwareResourcePrepared(NodeId id,bool prepared)176 void RoundCornerDisplayManager::UpdateHardwareResourcePrepared(NodeId id, bool prepared)
177 {
178     std::lock_guard<std::mutex> lock(rcdMapMut_);
179     if (!CheckExist(id)) {
180         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
181         return;
182     }
183     if (rcdMap_[id] == nullptr) {
184         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
185         RemoveRoundCornerDisplay(id);
186         return;
187     }
188     rcdMap_[id]->UpdateHardwareResourcePrepared(prepared);
189 }
190 
DrawRoundCorner(const RoundCornerDisplayManager::RCDLayerInfoVec & layerInfos,RSPaintFilterCanvas * canvas)191 void RoundCornerDisplayManager::DrawRoundCorner(const RoundCornerDisplayManager::RCDLayerInfoVec& layerInfos,
192     RSPaintFilterCanvas* canvas)
193 {
194     std::lock_guard<std::mutex> lock(rcdMapMut_);
195     for (const auto& layerInfo : layerInfos) {
196         if (layerInfo.second == RoundCornerDisplayManager::RCDLayerType::TOP) {
197             DrawTopRoundCorner(layerInfo.first, canvas);
198         }
199         if (layerInfo.second == RoundCornerDisplayManager::RCDLayerType::BOTTOM) {
200             DrawBottomRoundCorner(layerInfo.first, canvas);
201         }
202     }
203 }
204 
DrawTopRoundCorner(NodeId id,RSPaintFilterCanvas * canvas)205 void RoundCornerDisplayManager::DrawTopRoundCorner(NodeId id, RSPaintFilterCanvas* canvas)
206 {
207     if (!CheckExist(id)) {
208         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
209         return;
210     }
211     if (rcdMap_[id] == nullptr) {
212         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
213         RemoveRoundCornerDisplay(id);
214         return;
215     }
216     rcdMap_[id]->DrawTopRoundCorner(canvas);
217 }
218 
DrawBottomRoundCorner(NodeId id,RSPaintFilterCanvas * canvas)219 void RoundCornerDisplayManager::DrawBottomRoundCorner(NodeId id, RSPaintFilterCanvas* canvas)
220 {
221     if (!CheckExist(id)) {
222         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
223         return;
224     }
225     if (rcdMap_[id] == nullptr) {
226         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
227         RemoveRoundCornerDisplay(id);
228         return;
229     }
230     rcdMap_[id]->DrawBottomRoundCorner(canvas);
231 }
232 
RunHardwareTask(NodeId id,const std::function<void ()> & task)233 void RoundCornerDisplayManager::RunHardwareTask(NodeId id, const std::function<void()>& task)
234 {
235     {
236         std::lock_guard<std::mutex> lock(rcdMapMut_);
237         if (!CheckExist(id)) {
238             RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
239             return;
240         }
241         if (rcdMap_[id] == nullptr) {
242             RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
243             RemoveRoundCornerDisplay(id);
244             return;
245         }
246     }
247     rcdMap_[id]->RunHardwareTask(task);
248 }
249 
GetHardwareInfo(NodeId id,bool preparing)250 rs_rcd::RoundCornerHardware RoundCornerDisplayManager::GetHardwareInfo(NodeId id, bool preparing)
251 {
252     std::lock_guard<std::mutex> lock(rcdMapMut_);
253     rs_rcd::RoundCornerHardware rcdHardwareInfo{};
254     if (!CheckExist(id)) {
255         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
256         return rcdHardwareInfo;
257     }
258     if (rcdMap_.at(id) == nullptr) {
259         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
260         return rcdHardwareInfo;
261     }
262     return preparing ? rcdMap_.at(id)->GetHardwareInfoPreparing() : rcdMap_.at(id)->GetHardwareInfo();
263 }
264 
GetRcdEnable() const265 bool RoundCornerDisplayManager::GetRcdEnable() const
266 {
267     return RSSystemProperties::GetRSScreenRoundCornerEnable();
268 }
269 
IsNotchNeedUpdate(NodeId id,bool notchStatus)270 bool RoundCornerDisplayManager::IsNotchNeedUpdate(NodeId id, bool notchStatus)
271 {
272     std::lock_guard<std::mutex> lock(rcdMapMut_);
273     if (!CheckExist(id)) {
274         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
275         return false;
276     }
277     if (rcdMap_[id] == nullptr) {
278         RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
279         RemoveRoundCornerDisplay(id);
280         return false;
281     }
282     return rcdMap_[id]->IsNotchNeedUpdate(notchStatus);
283 }
284 } // namespace Rosen
285 } // namespace OHOS