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_message_bus.h"
21 #include "rs_trace.h"
22
23 namespace OHOS {
24 namespace Rosen {
RoundCornerDisplayManager()25 RoundCornerDisplayManager::RoundCornerDisplayManager()
26 {
27 RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] Created \n", __func__);
28 }
29
~RoundCornerDisplayManager()30 RoundCornerDisplayManager::~RoundCornerDisplayManager()
31 {
32 RS_LOGD_IF(DEBUG_PIPELINE, "[%{public}s] Destroy \n", __func__);
33 }
34
CheckExist(NodeId id)35 bool RoundCornerDisplayManager::CheckExist(NodeId id)
36 {
37 auto it = rcdMap_.find(id);
38 if (rcdMap_.end() == it) {
39 return false;
40 }
41 return true;
42 }
43
RegisterRcdMsg()44 void RoundCornerDisplayManager::RegisterRcdMsg()
45 {
46 if (RSSingleton<RoundCornerDisplayManager>::GetInstance().GetRcdEnable()) {
47 RS_LOGD("RSSubThreadManager::RegisterRcdMsg");
48 if (!isRcdMessageRegisted_) {
49 auto& rcdInstance = RSSingleton<RoundCornerDisplayManager>::GetInstance();
50 auto& msgBus = RSSingleton<RsMessageBus>::GetInstance();
51 msgBus.RegisterTopic<NodeId, uint32_t, uint32_t, uint32_t, uint32_t>(
52 TOPIC_RCD_DISPLAY_SIZE, &rcdInstance,
53 &RoundCornerDisplayManager::UpdateDisplayParameter);
54 msgBus.RegisterTopic<NodeId, ScreenRotation>(
55 TOPIC_RCD_DISPLAY_ROTATION, &rcdInstance,
56 &RoundCornerDisplayManager::UpdateOrientationStatus);
57 msgBus.RegisterTopic<NodeId, int>(
58 TOPIC_RCD_DISPLAY_NOTCH, &rcdInstance,
59 &RoundCornerDisplayManager::UpdateNotchStatus);
60 msgBus.RegisterTopic<NodeId, bool>(
61 TOPIC_RCD_DISPLAY_HWRESOURCE, &rcdInstance,
62 &RoundCornerDisplayManager::UpdateHardwareResourcePrepared);
63 isRcdMessageRegisted_ = true;
64 RS_LOGD("RSSubThreadManager::RegisterRcdMsg Registed rcd renderservice end");
65 return;
66 }
67 RS_LOGD("RSSubThreadManager::RegisterRcdMsg Registed rcd renderservice already.");
68 }
69 }
70
AddLayer(const std::string & name,NodeId id,RoundCornerDisplayManager::RCDLayerType type)71 void RoundCornerDisplayManager::AddLayer(const std::string& name, NodeId id,
72 RoundCornerDisplayManager::RCDLayerType type)
73 {
74 std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
75 rcdlayerMap_[name] = {id, type};
76 RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] rendertargetNodeId:%{public}" PRIu64 " with rcd layer name %{public}s \n",
77 __func__, id, name.c_str());
78 }
79
GetLayerPair(const std::string & layerName)80 std::pair<NodeId, RoundCornerDisplayManager::RCDLayerType> RoundCornerDisplayManager::GetLayerPair(
81 const std::string& layerName)
82 {
83 std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
84 auto it = rcdlayerMap_.find(layerName);
85 if (rcdlayerMap_.end() == it) {
86 return {0, RoundCornerDisplayManager::RCDLayerType::INVALID};
87 }
88 return rcdlayerMap_.at(layerName);
89 }
90
CheckLayerIsRCD(const std::string & layerName)91 bool RoundCornerDisplayManager::CheckLayerIsRCD(const std::string& layerName)
92 {
93 std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
94 auto it = rcdlayerMap_.find(layerName);
95 if (rcdlayerMap_.end() == it) {
96 return false;
97 }
98 return true;
99 }
100
AddRoundCornerDisplay(NodeId id)101 void RoundCornerDisplayManager::AddRoundCornerDisplay(NodeId id)
102 {
103 std::lock_guard<std::mutex> lock(rcdMapMut_);
104 if (CheckExist(id)) {
105 RS_LOGD_IF(DEBUG_PIPELINE,
106 "[%{public}s] nodeId:%{public}" PRIu64 " rcd module already exist, size:%{public}zd \n",
107 __func__, id, rcdMap_.size());
108 return;
109 }
110 auto rcd = std::make_shared<RoundCornerDisplay>(id);
111 rcdMap_[id] = rcd;
112 if (rcdMap_[id] == nullptr) {
113 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module create failed \n", __func__, id);
114 return;
115 }
116 rcdMap_[id]->InitOnce();
117 RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] size:%{public}zd rcd module after added for screen \n", __func__,
118 rcdMap_.size());
119 }
120
RemoveRCDResource(NodeId id)121 void RoundCornerDisplayManager::RemoveRCDResource(NodeId id)
122 {
123 {
124 std::lock_guard<std::mutex> lock(rcdMapMut_);
125 RemoveRoundCornerDisplay(id);
126 }
127 {
128 std::lock_guard<std::mutex> lock(rcdLayerMapMut_);
129 RemoveRCDLayerInfo(id);
130 }
131 }
132
RemoveRoundCornerDisplay(NodeId id)133 void RoundCornerDisplayManager::RemoveRoundCornerDisplay(NodeId id)
134 {
135 if (!CheckExist(id)) {
136 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
137 return;
138 }
139 rcdMap_.erase(id);
140 RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module removed for screen \n", __func__,
141 id);
142 }
143
RemoveRCDLayerInfo(NodeId id)144 void RoundCornerDisplayManager::RemoveRCDLayerInfo(NodeId id)
145 {
146 const auto& it = std::find_if(rcdlayerMap_.begin(), rcdlayerMap_.end(),
147 [id](const std::pair<std::string, std::pair<NodeId, RCDLayerType>>& p) {
148 return p.second.first == id;
149 });
150 if (rcdlayerMap_.end() == it) {
151 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd layer not exist \n", __func__, id);
152 return;
153 }
154 rcdlayerMap_.erase(it->first);
155 RS_LOGI_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd layer removed for screen \n", __func__,
156 id);
157 }
158
UpdateDisplayParameter(NodeId id,uint32_t left,uint32_t top,uint32_t width,uint32_t height)159 void RoundCornerDisplayManager::UpdateDisplayParameter(NodeId id, uint32_t left, uint32_t top,
160 uint32_t width, uint32_t height)
161 {
162 std::lock_guard<std::mutex> lock(rcdMapMut_);
163 if (!CheckExist(id)) {
164 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
165 return;
166 }
167 if (rcdMap_[id] == nullptr) {
168 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
169 RemoveRoundCornerDisplay(id);
170 return;
171 }
172 rcdMap_[id]->UpdateDisplayParameter(left, top, width, height);
173 }
174
UpdateNotchStatus(NodeId id,int status)175 void RoundCornerDisplayManager::UpdateNotchStatus(NodeId id, int status)
176 {
177 std::lock_guard<std::mutex> lock(rcdMapMut_);
178 if (!CheckExist(id)) {
179 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
180 return;
181 }
182 if (rcdMap_[id] == nullptr) {
183 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
184 RemoveRoundCornerDisplay(id);
185 return;
186 }
187 rcdMap_[id]->UpdateNotchStatus(status);
188 }
189
UpdateOrientationStatus(NodeId id,ScreenRotation orientation)190 void RoundCornerDisplayManager::UpdateOrientationStatus(NodeId id, ScreenRotation orientation)
191 {
192 std::lock_guard<std::mutex> lock(rcdMapMut_);
193 if (!CheckExist(id)) {
194 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
195 return;
196 }
197 if (rcdMap_[id] == nullptr) {
198 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
199 RemoveRoundCornerDisplay(id);
200 return;
201 }
202 rcdMap_[id]->UpdateOrientationStatus(orientation);
203 }
204
UpdateHardwareResourcePrepared(NodeId id,bool prepared)205 void RoundCornerDisplayManager::UpdateHardwareResourcePrepared(NodeId id, bool prepared)
206 {
207 std::lock_guard<std::mutex> lock(rcdMapMut_);
208 if (!CheckExist(id)) {
209 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
210 return;
211 }
212 if (rcdMap_[id] == nullptr) {
213 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
214 RemoveRoundCornerDisplay(id);
215 return;
216 }
217 rcdMap_[id]->UpdateHardwareResourcePrepared(prepared);
218 }
219
RefreshFlagAndUpdateResource(NodeId id)220 void RoundCornerDisplayManager::RefreshFlagAndUpdateResource(NodeId id)
221 {
222 std::lock_guard<std::mutex> lock(rcdMapMut_);
223 if (!CheckExist(id)) {
224 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
225 return;
226 }
227 if (rcdMap_[id] == nullptr) {
228 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
229 RemoveRoundCornerDisplay(id);
230 return;
231 }
232 rcdMap_[id]->RefreshFlagAndUpdateResource();
233 }
234
DrawRoundCorner(const RoundCornerDisplayManager::RCDLayerInfoVec & layerInfos,RSPaintFilterCanvas * canvas)235 void RoundCornerDisplayManager::DrawRoundCorner(const RoundCornerDisplayManager::RCDLayerInfoVec& layerInfos,
236 RSPaintFilterCanvas* canvas)
237 {
238 std::lock_guard<std::mutex> lock(rcdMapMut_);
239 for (const auto& layerInfo : layerInfos) {
240 if (layerInfo.second == RoundCornerDisplayManager::RCDLayerType::TOP) {
241 DrawTopRoundCorner(layerInfo.first, canvas);
242 }
243 if (layerInfo.second == RoundCornerDisplayManager::RCDLayerType::BOTTOM) {
244 DrawBottomRoundCorner(layerInfo.first, canvas);
245 }
246 }
247 }
248
DrawTopRoundCorner(NodeId id,RSPaintFilterCanvas * canvas)249 void RoundCornerDisplayManager::DrawTopRoundCorner(NodeId id, RSPaintFilterCanvas* canvas)
250 {
251 if (!CheckExist(id)) {
252 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
253 return;
254 }
255 if (rcdMap_[id] == nullptr) {
256 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
257 RemoveRoundCornerDisplay(id);
258 return;
259 }
260 rcdMap_[id]->DrawTopRoundCorner(canvas);
261 }
262
DrawBottomRoundCorner(NodeId id,RSPaintFilterCanvas * canvas)263 void RoundCornerDisplayManager::DrawBottomRoundCorner(NodeId id, RSPaintFilterCanvas* canvas)
264 {
265 if (!CheckExist(id)) {
266 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
267 return;
268 }
269 if (rcdMap_[id] == nullptr) {
270 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
271 RemoveRoundCornerDisplay(id);
272 return;
273 }
274 rcdMap_[id]->DrawBottomRoundCorner(canvas);
275 }
276
HandleRoundCornerDirtyRect(NodeId id,RectI & dirtyRect,const RCDLayerType type)277 bool RoundCornerDisplayManager::HandleRoundCornerDirtyRect(NodeId id, RectI &dirtyRect, const RCDLayerType type)
278 {
279 std::lock_guard<std::mutex> lock(rcdMapMut_);
280 if (!CheckExist(id)) {
281 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
282 return false;
283 }
284 if (rcdMap_[id] == nullptr) {
285 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
286 RemoveRoundCornerDisplay(id);
287 return false;
288 }
289 bool isDirty = false;
290 if (type == RCDLayerType::TOP) {
291 isDirty = rcdMap_[id]->HandleTopRcdDirty(dirtyRect) || isDirty;
292 }
293 if (type == RCDLayerType::BOTTOM) {
294 isDirty = rcdMap_[id]->HandleBottomRcdDirty(dirtyRect) || isDirty;
295 }
296 return isDirty;
297 }
298
RunHardwareTask(NodeId id,const std::function<void ()> & task)299 void RoundCornerDisplayManager::RunHardwareTask(NodeId id, const std::function<void()>& task)
300 {
301 {
302 std::lock_guard<std::mutex> lock(rcdMapMut_);
303 if (!CheckExist(id)) {
304 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
305 return;
306 }
307 if (rcdMap_[id] == nullptr) {
308 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
309 RemoveRoundCornerDisplay(id);
310 return;
311 }
312 }
313 rcdMap_[id]->RunHardwareTask(task);
314 }
315
GetHardwareInfo(NodeId id)316 rs_rcd::RoundCornerHardware RoundCornerDisplayManager::GetHardwareInfo(NodeId id)
317 {
318 std::lock_guard<std::mutex> lock(rcdMapMut_);
319 rs_rcd::RoundCornerHardware rcdHardwareInfo{};
320 if (!CheckExist(id)) {
321 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
322 return rcdHardwareInfo;
323 }
324 if (rcdMap_.at(id) == nullptr) {
325 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
326 return rcdHardwareInfo;
327 }
328 return rcdMap_.at(id)->GetHardwareInfo();
329 }
330
PrepareHardwareInfo(NodeId id)331 rs_rcd::RoundCornerHardware RoundCornerDisplayManager::PrepareHardwareInfo(NodeId id)
332 {
333 std::lock_guard<std::mutex> lock(rcdMapMut_);
334 rs_rcd::RoundCornerHardware rcdHardwareInfo{};
335 if (!CheckExist(id)) {
336 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
337 return rcdHardwareInfo;
338 }
339 if (rcdMap_.at(id) == nullptr) {
340 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
341 return rcdHardwareInfo;
342 }
343 return rcdMap_.at(id)->PrepareHardwareInfo();
344 }
345
GetRcdEnable() const346 bool RoundCornerDisplayManager::GetRcdEnable() const
347 {
348 auto &rcdCfg = RSSingleton<rs_rcd::RCDConfig>::GetInstance();
349 // assume support rcd before rcd cfg loaded
350 bool rcdSupport = !rcdCfg.IsDataLoaded();
351 if (!rcdSupport) {
352 auto lcdModel = rcdCfg.GetLcdModel(rs_rcd::ATTR_DEFAULT);
353 if (lcdModel != nullptr) {
354 rcdSupport = lcdModel->surfaceConfig.topSurface.support && lcdModel->surfaceConfig.bottomSurface.support;
355 }
356 }
357 return RSSystemProperties::GetRSScreenRoundCornerEnable() && rcdSupport;
358 }
359
IsNotchNeedUpdate(NodeId id,bool notchStatus)360 bool RoundCornerDisplayManager::IsNotchNeedUpdate(NodeId id, bool notchStatus)
361 {
362 std::lock_guard<std::mutex> lock(rcdMapMut_);
363 if (!CheckExist(id)) {
364 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module not exist \n", __func__, id);
365 return false;
366 }
367 if (rcdMap_[id] == nullptr) {
368 RS_LOGE_IF(DEBUG_PIPELINE, "[%{public}s] nodeId:%{public}" PRIu64 " rcd module is null \n", __func__, id);
369 RemoveRoundCornerDisplay(id);
370 return false;
371 }
372 return rcdMap_[id]->IsNotchNeedUpdate(notchStatus);
373 }
374 } // namespace Rosen
375 } // namespace OHOS