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