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 #include "charger_graphic_engine.h"
16 #include "charger_log.h"
17 #include "common/graphic_startup.h"
18 #include "common/image_decode_ability.h"
19 #include "common/task_manager.h"
20 #include "draw/draw_utils.h"
21 #include "font/ui_font_header.h"
22 
23 #include <cinttypes>
24 
25 namespace OHOS {
26 namespace PowerMgr {
GetInstance()27 ChargerGraphicEngine& ChargerGraphicEngine::GetInstance()
28 {
29     static ChargerGraphicEngine instance;
30     static bool isRegister = false;
31     if (!isRegister) {
32         OHOS::SoftEngine::InitGfxEngine(&instance);
33         isRegister = true;
34     }
35 
36     return instance;
37 }
38 
Init(uint32_t bkgColor,uint8_t mode,const char * fontPath,const char * ttfName)39 void ChargerGraphicEngine::Init(uint32_t bkgColor, uint8_t mode, const char* fontPath, const char* ttfName)
40 {
41     bkgColor_ = bkgColor;
42     colorMode_ = mode;
43     [[maybe_unused]] static bool initOnce = [this, fontPath, ttfName]() {
44         sfDev_ = std::make_unique<GraphicDev>();
45         if (!sfDev_->Init()) {
46             BATTERY_HILOGE(FEATURE_CHARGING, "ChargerGraphicEngine::Init failed");
47             return false;
48         }
49         sfDev_->GetScreenSize(width_, height_);
50         buffInfo_ = nullptr;
51         virAddr_ = nullptr;
52         InitFontEngine(fontPath, ttfName);
53         InitImageDecodeAbility();
54         InitFlushThread();
55         return true;
56     }();
57 }
58 
InitFontEngine(const char * fontPath,const char * ttfName)59 void ChargerGraphicEngine::InitFontEngine(const char* fontPath, const char* ttfName)
60 {
61     constexpr uint32_t uiFontMemAlignment = 4;
62     static uint32_t fontMemBaseAddr[OHOS::MIN_FONT_PSRAM_LENGTH / uiFontMemAlignment];
63     static uint8_t icuMemBaseAddr[OHOS::SHAPING_WORD_DICT_LENGTH];
64     OHOS::GraphicStartUp::InitFontEngine(
65         reinterpret_cast<uintptr_t>(fontMemBaseAddr), OHOS::MIN_FONT_PSRAM_LENGTH, fontPath, ttfName);
66     OHOS::GraphicStartUp::InitLineBreakEngine(reinterpret_cast<uintptr_t>(icuMemBaseAddr),
67         OHOS::SHAPING_WORD_DICT_LENGTH, fontPath, DEFAULT_LINE_BREAK_RULE_FILENAME);
68 }
69 
InitImageDecodeAbility()70 void ChargerGraphicEngine::InitImageDecodeAbility()
71 {
72     uint32_t imageType = OHOS::IMG_SUPPORT_BITMAP | OHOS::IMG_SUPPORT_JPEG | OHOS::IMG_SUPPORT_PNG;
73     OHOS::ImageDecodeAbility::GetInstance().SetImageDecodeAbility(imageType);
74 }
75 
InitFlushThread()76 void ChargerGraphicEngine::InitFlushThread()
77 {
78     flushStop_ = false;
79     flushLoop_ = std::thread(&ChargerGraphicEngine::FlushThreadLoop, this);
80     flushLoop_.detach();
81 }
82 
UsSleep(int usec)83 void ChargerGraphicEngine::UsSleep(int usec)
84 {
85     constexpr int USECONDS_PER_SECONDS = 1000000; // 1s = 1000000us
86     constexpr int NANOSECS_PER_USECONDS = 1000;   // 1us = 1000ns
87     auto seconds = usec / USECONDS_PER_SECONDS;
88     long nanoSeconds = static_cast<long>(usec) % USECONDS_PER_SECONDS * NANOSECS_PER_USECONDS;
89     struct timespec ts = {static_cast<time_t>(seconds), nanoSeconds};
90     while (nanosleep(&ts, &ts) < 0 && errno == EINTR) {}
91 }
92 
FlushThreadLoop()93 void ChargerGraphicEngine::FlushThreadLoop()
94 {
95     while (!flushStop_) {
96         OHOS::TaskManager::GetInstance()->TaskHandler();
97         UsSleep(THREAD_USLEEP_TIME);
98     }
99 }
100 
GetFBBufferInfo()101 OHOS::BufferInfo* ChargerGraphicEngine::GetFBBufferInfo()
102 {
103     if (buffInfo_ != nullptr) {
104         return buffInfo_.get();
105     }
106 
107     uint8_t pixelBytes = OHOS::DrawUtils::GetByteSizeByColorMode(colorMode_);
108     if (pixelBytes == 0) {
109         BATTERY_HILOGE(FEATURE_CHARGING, "ChargerGraphicEngine get pixelBytes fail");
110         return nullptr;
111     }
112 
113     if ((width_ == 0) || (height_ == 0)) {
114         BATTERY_HILOGE(FEATURE_CHARGING, "input error, width: %{public}d, height: %{public}d", width_, height_);
115         return nullptr;
116     }
117     virAddr_ = std::make_unique<uint8_t[]>(width_ * height_ * pixelBytes);
118     buffInfo_ = std::make_unique<OHOS::BufferInfo>();
119     buffInfo_->rect = {0, 0, static_cast<int16_t>(width_ - 1), static_cast<int16_t>(height_ - 1)};
120     buffInfo_->mode = static_cast<OHOS::ColorMode>(colorMode_);
121     buffInfo_->color = bkgColor_;
122     buffInfo_->virAddr = virAddr_.get();
123     buffInfo_->phyAddr = buffInfo_->virAddr;
124     buffInfo_->stride = static_cast<uint32_t>(width_ * pixelBytes);
125     buffInfo_->width = width_;
126     buffInfo_->height = height_;
127     return buffInfo_.get();
128 }
129 
Flush(const OHOS::Rect & flushRect)130 void ChargerGraphicEngine::Flush(const OHOS::Rect& flushRect)
131 {
132     if ((sfDev_ == nullptr) || (buffInfo_ == nullptr)) {
133         BATTERY_HILOGE(FEATURE_CHARGING, "null error");
134         return;
135     }
136     std::lock_guard<std::mutex> lock {mtx_};
137     sfDev_->Flip(reinterpret_cast<const uint8_t*>(buffInfo_->virAddr));
138 }
139 
GetScreenWidth()140 uint16_t ChargerGraphicEngine::GetScreenWidth()
141 {
142     return width_;
143 }
144 
GetScreenHeight()145 uint16_t ChargerGraphicEngine::GetScreenHeight()
146 {
147     return height_;
148 }
149 } // namespace PowerMgr
150 } // namespace OHOS
151