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_round_corner_display.h"
17 #include <mutex>
18 #include "platform/common/rs_system_properties.h"
19 #include "common/rs_optional_trace.h"
20 #include "common/rs_singleton.h"
21 #include "rs_trace.h"
22
23 namespace OHOS {
24 namespace Rosen {
RoundCornerDisplay()25 RoundCornerDisplay::RoundCornerDisplay()
26 {
27 RS_LOGD("[%{public}s] Created \n", __func__);
28 Init();
29 }
30
~RoundCornerDisplay()31 RoundCornerDisplay::~RoundCornerDisplay()
32 {
33 RS_LOGD("[%{public}s] Destroy \n", __func__);
34 }
35
Init()36 bool RoundCornerDisplay::Init()
37 {
38 std::unique_lock<std::shared_mutex> lock(resourceMut_);
39 LoadConfigFile();
40 SeletedLcdModel(rs_rcd::ATTR_DEFAULT);
41 LoadImgsbyResolution(displayWidth_, displayHeight_);
42 isRcdEnable_ = RSSystemProperties::GetRSScreenRoundCornerEnable();
43 RS_LOGI("[%{public}s] RoundCornerDisplay init \n", __func__);
44 return true;
45 }
46
SeletedLcdModel(const char * lcdModelName)47 bool RoundCornerDisplay::SeletedLcdModel(const char* lcdModelName)
48 {
49 auto& rcdCfg = RSSingleton<rs_rcd::RCDConfig>::GetInstance();
50 lcdModel_ = rcdCfg.GetLcdModel(std::string(lcdModelName));
51 if (lcdModel_ == nullptr) {
52 RS_LOGD("[%{public}s] No lcdModel found in config file with name %{public}s \n", __func__, lcdModelName);
53 return false;
54 }
55 supportTopSurface_ = lcdModel_->surfaceConfig.topSurface.support;
56 supportBottomSurface_ = lcdModel_->surfaceConfig.bottomSurface.support;
57 supportHardware_ = lcdModel_->hardwareConfig.hardwareComposer.support;
58 RS_LOGI("[%{public}s] Selected model: %{public}s, supported: top->%{public}d, bottom->%{public}d,"
59 "hardware->%{public}d \n", __func__, lcdModelName, static_cast<int>(supportTopSurface_),
60 static_cast<int>(supportBottomSurface_), static_cast<int>(supportHardware_));
61 return true;
62 }
63
LoadConfigFile()64 bool RoundCornerDisplay::LoadConfigFile()
65 {
66 RS_LOGD("[%{public}s] LoadConfigFile \n", __func__);
67 auto& rcdCfg = RSSingleton<rs_rcd::RCDConfig>::GetInstance();
68 return rcdCfg.Load(std::string(rs_rcd::PATH_CONFIG_FILE));
69 }
70
LoadImg(const char * path,std::shared_ptr<Drawing::Image> & img)71 bool RoundCornerDisplay::LoadImg(const char* path, std::shared_ptr<Drawing::Image>& img)
72 {
73 std::string filePath = std::string(rs_rcd::PATH_CONFIG_DIR) + "/" + path;
74 RS_LOGD("[%{public}s] Read Img(%{public}s) \n", __func__, filePath.c_str());
75 std::shared_ptr<Drawing::Data> drData = Drawing::Data::MakeFromFileName(filePath.c_str());
76 if (drData == nullptr) {
77 RS_LOGE("[%{public}s] Open picture file failed! \n", __func__);
78 return false;
79 }
80 img = std::make_shared<Drawing::Image>();
81 if (!img->MakeFromEncoded(drData)) {
82 img = nullptr;
83 RS_LOGE("[%{public}s] Decode picture file failed! \n", __func__);
84 return false;
85 }
86 return true;
87 }
88
DecodeBitmap(std::shared_ptr<Drawing::Image> image,Drawing::Bitmap & bitmap)89 bool RoundCornerDisplay::DecodeBitmap(std::shared_ptr<Drawing::Image> image, Drawing::Bitmap &bitmap)
90 {
91 if (image == nullptr) {
92 RS_LOGE("[%{public}s] No image found \n", __func__);
93 return false;
94 }
95 if (!image->AsLegacyBitmap(bitmap)) {
96 RS_LOGE("[%{public}s] Create bitmap from drImage failed \n", __func__);
97 return false;
98 }
99 return true;
100 }
101
SetHardwareLayerSize()102 bool RoundCornerDisplay::SetHardwareLayerSize()
103 {
104 if (hardInfo_.topLayer == nullptr) {
105 RS_LOGE("[%{public}s] No topLayer found in hardInfo \n", __func__);
106 return false;
107 }
108 if (hardInfo_.bottomLayer == nullptr) {
109 RS_LOGE("[%{public}s] No bottomLayer found in hardInfo \n", __func__);
110 return false;
111 }
112 hardInfo_.topLayer->layerWidth = displayWidth_;
113 hardInfo_.topLayer->layerHeight = displayHeight_;
114 hardInfo_.bottomLayer->layerWidth = displayWidth_;
115 hardInfo_.bottomLayer->layerHeight = displayHeight_;
116 return true;
117 }
118
GetTopSurfaceSource()119 bool RoundCornerDisplay::GetTopSurfaceSource()
120 {
121 RS_TRACE_NAME("RoundCornerDisplay::GetTopSurfaceSource");
122 if (rog_ == nullptr) {
123 RS_LOGE("[%{public}s] No rog found in config file \n", __func__);
124 return false;
125 }
126 rs_rcd::RCDConfig::PrintParseRog(rog_);
127
128 if (rog_->portraitMap.count(rs_rcd::NODE_PORTRAIT) < 1) {
129 RS_LOGE("[%{public}s] PORTRAIT layerUp do not configured \n", __func__);
130 return false;
131 }
132 LoadImg(rog_->portraitMap[rs_rcd::NODE_PORTRAIT].layerUp.fileName.c_str(), imgTopPortrait_);
133
134 if (rog_->landscapeMap.count(rs_rcd::NODE_LANDSCAPE) < 1) {
135 RS_LOGE("[%{public}s] LANDSACPE layerUp do not configured \n", __func__);
136 return false;
137 }
138 LoadImg(rog_->landscapeMap[rs_rcd::NODE_LANDSCAPE].layerUp.fileName.c_str(), imgTopLadsOrit_);
139
140 if (rog_->portraitMap.count(rs_rcd::NODE_PORTRAIT) < 1) {
141 RS_LOGE("[%{public}s] PORTRAIT layerHide do not configured \n", __func__);
142 return false;
143 }
144 LoadImg(rog_->portraitMap[rs_rcd::NODE_PORTRAIT].layerHide.fileName.c_str(), imgTopHidden_);
145 if (supportHardware_) {
146 DecodeBitmap(imgTopPortrait_, bitmapTopPortrait_);
147 DecodeBitmap(imgTopLadsOrit_, bitmapTopLadsOrit_);
148 DecodeBitmap(imgTopHidden_, bitmapTopHidden_);
149 }
150 return true;
151 }
152
GetBottomSurfaceSource()153 bool RoundCornerDisplay::GetBottomSurfaceSource()
154 {
155 RS_TRACE_NAME("RoundCornerDisplay::GetBottomSurfaceSource");
156 if (rog_ == nullptr) {
157 RS_LOGE("[%{public}s] No rog found in config file \n", __func__);
158 return false;
159 }
160 if (rog_->portraitMap.count(rs_rcd::NODE_PORTRAIT) < 1) {
161 RS_LOGE("[%{public}s] PORTRAIT layerDown do not configured \n", __func__);
162 return false;
163 }
164 LoadImg(rog_->portraitMap[rs_rcd::NODE_PORTRAIT].layerDown.fileName.c_str(), imgBottomPortrait_);
165 if (supportHardware_) {
166 DecodeBitmap(imgBottomPortrait_, bitmapBottomPortrait_);
167 }
168 return true;
169 }
170
LoadImgsbyResolution(uint32_t width,uint32_t height)171 bool RoundCornerDisplay::LoadImgsbyResolution(uint32_t width, uint32_t height)
172 {
173 RS_TRACE_NAME("RoundCornerDisplay::LoadImgsbyResolution");
174
175 if (lcdModel_ == nullptr) {
176 RS_LOGD("[%{public}s] No lcdModel selected in config file \n", __func__);
177 return false;
178 }
179 rog_ = lcdModel_->GetRog(width, height);
180 if (rog_ == nullptr) {
181 RS_LOGE("[%{public}s] Can't find resolution (%{public}u x %{public}u) in config file \n",
182 __func__, width, height);
183 return false;
184 }
185 RS_LOGD("[%{public}s] Get rog resolution (%{public}u x %{public}u) in config file \n", __func__, width, height);
186 if (supportTopSurface_ && supportHardware_) {
187 if (!GetTopSurfaceSource()) {
188 RS_LOGE("[%{public}s] Top surface support configured, but resources is missing! \n", __func__);
189 return false;
190 }
191 }
192 if (supportBottomSurface_ && supportHardware_) {
193 if (!GetBottomSurfaceSource()) {
194 RS_LOGE("[%{public}s] Bottom surface support configured, but resources is missing! \n", __func__);
195 return false;
196 }
197 }
198 return true;
199 }
200
UpdateDisplayParameter(uint32_t width,uint32_t height)201 void RoundCornerDisplay::UpdateDisplayParameter(uint32_t width, uint32_t height)
202 {
203 std::unique_lock<std::shared_mutex> lock(resourceMut_);
204 if (width == displayWidth_ && height == displayHeight_) {
205 RS_LOGD("[%{public}s] DisplayParameter do not change \n", __func__);
206 return;
207 }
208 RS_LOGD("[%{public}s] displayWidth_ updated from %{public}u -> %{public}u,"
209 "displayHeight_ updated from %{public}u -> %{public}u \n", __func__,
210 displayWidth_, width, displayHeight_, height);
211 if (LoadImgsbyResolution(width, height)) {
212 updateFlag_["display"] = true;
213 displayWidth_ = width;
214 displayHeight_ = height;
215 }
216 }
217
UpdateNotchStatus(int status)218 void RoundCornerDisplay::UpdateNotchStatus(int status)
219 {
220 std::unique_lock<std::shared_mutex> lock(resourceMut_);
221 // Update surface when surface status changed
222 if (status < 0 || status > 1) {
223 RS_LOGE("[%{public}s] notchStatus won't be over 1 or below 0 \n", __func__);
224 return;
225 }
226 if (notchStatus_ == status) {
227 RS_LOGD("[%{public}s] NotchStatus do not change \n", __func__);
228 return;
229 }
230 RS_LOGI("[%{public}s] notchStatus change from %{public}d to %{public}d \n", __func__,
231 notchStatus_, status);
232 notchStatus_ = status;
233 updateFlag_["notch"] = true;
234 }
235
UpdateOrientationStatus(ScreenRotation orientation)236 void RoundCornerDisplay::UpdateOrientationStatus(ScreenRotation orientation)
237 {
238 std::unique_lock<std::shared_mutex> lock(resourceMut_);
239 if (orientation == curOrientation_) {
240 RS_LOGD("[%{public}s] OrientationStatus do not change \n", __func__);
241 return;
242 }
243 lastOrientation_ = curOrientation_;
244 curOrientation_ = orientation;
245 RS_LOGD("[%{public}s] curOrientation_ = %{public}d, lastOrientation_ = %{public}d \n",
246 __func__, curOrientation_, lastOrientation_);
247 updateFlag_["orientation"] = true;
248 }
249
UpdateHardwareResourcePrepared(bool prepared)250 void RoundCornerDisplay::UpdateHardwareResourcePrepared(bool prepared)
251 {
252 std::unique_lock<std::shared_mutex> lock(resourceMut_);
253 if (hardInfo_.resourcePreparing) {
254 hardInfo_.resourcePreparing = false;
255 hardInfo_.resourceChanged = !prepared;
256 }
257 }
258
UpdateParameter(std::map<std::string,bool> & updateFlag)259 void RoundCornerDisplay::UpdateParameter(std::map<std::string, bool>& updateFlag)
260 {
261 std::unique_lock<std::shared_mutex> lock(resourceMut_);
262 for (auto item = updateFlag.begin(); item != updateFlag.end(); item++) {
263 if (item->second == true) {
264 resourceChanged = true;
265 item->second = false; // reset
266 }
267 }
268 if (resourceChanged) {
269 RcdChooseTopResourceType();
270 RcdChooseRSResource();
271 if (supportHardware_) {
272 RcdChooseHardwareResource();
273 SetHardwareLayerSize();
274 }
275 hardInfo_.resourceChanged = resourceChanged; // output
276 hardInfo_.resourcePreparing = false; // output
277 resourceChanged = false; // reset
278 } else {
279 RS_LOGD("[%{public}s] Status is not changed \n", __func__);
280 }
281 }
282
283 // Choose the approriate resource type according to orientation and notch status
RcdChooseTopResourceType()284 void RoundCornerDisplay::RcdChooseTopResourceType()
285 {
286 RS_LOGD("[%{public}s] Choose surface \n", __func__);
287 RS_LOGD("[%{public}s] curOrientation is %{public}d \n", __func__, curOrientation_);
288 RS_LOGD("[%{public}s] notchStatus is %{public}d \n", __func__, notchStatus_);
289 switch (curOrientation_) {
290 case ScreenRotation::ROTATION_0:
291 case ScreenRotation::ROTATION_180:
292 if (notchStatus_ == WINDOW_NOTCH_HIDDEN) {
293 RS_LOGD("prepare TOP_HIDDEN show resource \n");
294 showResourceType_ = TOP_HIDDEN;
295 } else {
296 RS_LOGD("prepare TOP_PORTRAIT show resource \n");
297 showResourceType_ = TOP_PORTRAIT;
298 }
299 break;
300 case ScreenRotation::ROTATION_90:
301 case ScreenRotation::ROTATION_270:
302 if (notchStatus_ == WINDOW_NOTCH_HIDDEN) {
303 RS_LOGD("prepare TOP_LADS_ORIT show resource \n");
304 showResourceType_ = TOP_LADS_ORIT;
305 } else {
306 RS_LOGD("prepare TOP_PORTRAIT show resource \n");
307 showResourceType_ = TOP_PORTRAIT;
308 }
309 break;
310 default:
311 RS_LOGD("Unknow orientation, use default type \n");
312 showResourceType_ = TOP_PORTRAIT;
313 break;
314 }
315 }
316
RcdChooseRSResource()317 void RoundCornerDisplay::RcdChooseRSResource()
318 {
319 switch (showResourceType_) {
320 case TOP_PORTRAIT:
321 curTop_ = imgTopPortrait_;
322 RS_LOGD("prepare imgTopPortrait_ resource \n");
323 break;
324 case TOP_HIDDEN:
325 curTop_ = imgTopHidden_;
326 RS_LOGD("prepare imgTopHidden_ resource \n");
327 break;
328 case TOP_LADS_ORIT:
329 curTop_ = imgTopLadsOrit_;
330 RS_LOGD("prepare imgTopLadsOrit_ resource \n");
331 break;
332 default:
333 RS_LOGE("[%{public}s] No showResourceType found with type %{public}d \n", __func__, showResourceType_);
334 break;
335 }
336 curBottom_ = imgBottomPortrait_;
337 }
338
RcdChooseHardwareResource()339 void RoundCornerDisplay::RcdChooseHardwareResource()
340 {
341 if (rog_ == nullptr) {
342 RS_LOGE("[%{public}s] No rog info \n", __func__);
343 return;
344 }
345 switch (showResourceType_) {
346 case TOP_PORTRAIT:
347 if (rog_->portraitMap.count(rs_rcd::NODE_PORTRAIT) < 1) {
348 RS_LOGE("[%{public}s] PORTRAIT layerHide do not configured \n", __func__);
349 break;
350 }
351 hardInfo_.topLayer = &rog_->portraitMap[rs_rcd::NODE_PORTRAIT].layerUp;
352 hardInfo_.topLayer->curBitmap = &bitmapTopPortrait_;
353 break;
354 case TOP_HIDDEN:
355 if (rog_->portraitMap.count(rs_rcd::NODE_PORTRAIT) < 1) {
356 RS_LOGE("[%{public}s] PORTRAIT layerHide do not configured \n", __func__);
357 break;
358 }
359 hardInfo_.topLayer = &rog_->portraitMap[rs_rcd::NODE_PORTRAIT].layerHide;
360 hardInfo_.topLayer->curBitmap = &bitmapTopHidden_;
361 break;
362 case TOP_LADS_ORIT:
363 if (rog_->landscapeMap.count(rs_rcd::NODE_LANDSCAPE) < 1) {
364 RS_LOGE("[%{public}s] PORTRAIT layerHide do not configured \n", __func__);
365 break;
366 }
367 hardInfo_.topLayer = &rog_->landscapeMap[rs_rcd::NODE_LANDSCAPE].layerUp;
368 hardInfo_.topLayer->curBitmap = &bitmapTopLadsOrit_;
369 break;
370 default:
371 RS_LOGE("[%{public}s] No showResourceType found with type %{public}d \n", __func__, showResourceType_);
372 break;
373 }
374 if (rog_->portraitMap.count(rs_rcd::NODE_PORTRAIT) < 1) {
375 RS_LOGE("[%{public}s] PORTRAIT layerHide do not configured \n", __func__);
376 return;
377 }
378 hardInfo_.bottomLayer = &rog_->portraitMap[rs_rcd::NODE_PORTRAIT].layerDown;
379 hardInfo_.bottomLayer->curBitmap = &bitmapBottomPortrait_;
380 }
381
DrawOneRoundCorner(RSPaintFilterCanvas * canvas,int surfaceType)382 void RoundCornerDisplay::DrawOneRoundCorner(RSPaintFilterCanvas* canvas, int surfaceType)
383 {
384 RS_TRACE_BEGIN("RCD::DrawOneRoundCorner : surfaceType" + std::to_string(surfaceType));
385 if (canvas == nullptr) {
386 RS_LOGE("[%{public}s] Canvas is null \n", __func__);
387 RS_TRACE_END();
388 return;
389 }
390 UpdateParameter(updateFlag_);
391 if (surfaceType == TOP_SURFACE) {
392 RS_LOGD("[%{public}s] draw TopSurface start \n", __func__);
393 if (curTop_ != nullptr) {
394 Drawing::Brush brush;
395 canvas->AttachBrush(brush);
396 canvas->DrawImage(*curTop_, 0, 0, Drawing::SamplingOptions());
397 canvas->DetachBrush();
398 RS_LOGD("[%{public}s] Draw top \n", __func__);
399 }
400 } else if (surfaceType == BOTTOM_SURFACE) {
401 RS_LOGD("[%{public}s] BottomSurface supported \n", __func__);
402 if (curBottom_ != nullptr) {
403 Drawing::Brush brush;
404 canvas->AttachBrush(brush);
405 canvas->DrawImage(*curBottom_, 0, displayHeight_ - curBottom_->GetHeight(), Drawing::SamplingOptions());
406 canvas->DetachBrush();
407 RS_LOGD("[%{public}s] Draw Bottom \n", __func__);
408 }
409 } else {
410 RS_LOGD("[%{public}s] Surface Type is not valid \n", __func__);
411 }
412 RS_TRACE_END();
413 }
414
DrawTopRoundCorner(RSPaintFilterCanvas * canvas)415 void RoundCornerDisplay::DrawTopRoundCorner(RSPaintFilterCanvas* canvas)
416 {
417 DrawOneRoundCorner(canvas, TOP_SURFACE);
418 }
419
DrawBottomRoundCorner(RSPaintFilterCanvas * canvas)420 void RoundCornerDisplay::DrawBottomRoundCorner(RSPaintFilterCanvas* canvas)
421 {
422 DrawOneRoundCorner(canvas, BOTTOM_SURFACE);
423 }
424
DrawRoundCorner(RSPaintFilterCanvas * canvas)425 void RoundCornerDisplay::DrawRoundCorner(RSPaintFilterCanvas* canvas)
426 {
427 DrawTopRoundCorner(canvas);
428 DrawBottomRoundCorner(canvas);
429 }
430 } // namespace Rosen
431 } // namespace OHOS
432