• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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