1 /*
2 * Copyright (c) 2025 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 "hpae_base/rs_hpae_hianimation.h"
16
17 #if defined(ROSEN_OHOS)
18 #include <dlfcn.h>
19 #if defined(ASYNC_BUILD_TASK)
20 #include "cpp/ffrt_dynamic_graph.h"
21 #endif
22 #endif
23
24 #include "hpae_base/rs_hpae_log.h"
25 #include "hpae_base/rs_hpae_perf_thread.h"
26
27 namespace OHOS::Rosen {
28 using namespace std::chrono_literals;
29
30 using GetHianimationDeviceFunc = hianimation_algo_device_t* (*)();
31 constexpr int MAX_INIT_TIMES = 3;
32 constexpr int HPAE_BLUR_DELAY = 2;
33 #if defined(ASYNC_BUILD_TASK) && defined(ROSEN_OHOS)
34 constexpr int HPAE_USE_FFRT_QOS = 5;
35 #endif
36
GetInstance()37 HianimationManager& HianimationManager::GetInstance()
38 {
39 static HianimationManager mgr;
40 return mgr;
41 }
42
HianimationManager()43 HianimationManager::HianimationManager()
44 {
45 }
46
~HianimationManager()47 HianimationManager::~HianimationManager()
48 {
49 CloseDevice();
50 #if defined(ROSEN_OHOS)
51 if (libHandle_ != nullptr) {
52 dlclose(libHandle_);
53 }
54 #endif
55 libHandle_ = nullptr;
56 hianimationDevice_ = nullptr;
57 }
58
WaitHpaeDone()59 void HianimationManager::WaitHpaeDone()
60 {
61 std::unique_lock<std::mutex> lock(hpaePerfMutex_);
62 if (!hpaePerfDone_) {
63 hpaePerfCv_.wait_for(lock, 100ms, [this]() {
64 return this->hpaePerfDone_;
65 });
66 }
67 }
68
NotifyHpaeDone()69 void HianimationManager::NotifyHpaeDone()
70 {
71 std::unique_lock<std::mutex> lock(hpaePerfMutex_);
72 hpaePerfDone_ = true;
73 hpaePerfCv_.notify_all();
74 }
75
OpenDeviceAsync()76 void HianimationManager::OpenDeviceAsync()
77 {
78 #if defined(ASYNC_BUILD_TASK) && defined(ROSEN_OHOS)
79 ffrt::submit_h([this]() {
80 this->OpenDevice();
81 }, {}, {});
82 #else
83 OpenDevice();
84 #endif
85 }
86
AlgoInitAsync(uint32_t imgWidth,uint32_t imgHeight,float maxSigma,uint32_t format)87 void HianimationManager::AlgoInitAsync(uint32_t imgWidth, uint32_t imgHeight, float maxSigma, uint32_t format)
88 {
89 #if defined(ASYNC_BUILD_TASK) && defined(ROSEN_OHOS)
90 {
91 std::unique_lock<std::mutex> lock(algoInitMutex_);
92 algoInitDone_ = false;
93 }
94
95 ffrt::submit_h([=]() {
96 std::unique_lock<std::mutex> lock(algoInitMutex_);
97 this->HianimationAlgoInit(imgWidth, imgHeight, maxSigma, format);
98 this->algoInitDone_ = true;
99 this->algoInitCv_.notify_all();
100 }, {}, {}, ffrt::task_attr().qos(HPAE_USE_FFRT_QOS));
101 #else
102 HianimationAlgoInit(imgWidth, imgHeight, maxSigma, format);
103 #endif
104 }
105
WaitAlgoInit()106 void HianimationManager::WaitAlgoInit()
107 {
108 using namespace std::chrono_literals;
109 std::unique_lock<std::mutex> lock(algoInitMutex_);
110 if (!algoInitDone_) {
111 HPAE_TRACE_NAME("WaitAlgoInit");
112 algoInitCv_.wait_for(lock, 30ms, [this]() {
113 return this->algoInitDone_;
114 });
115 }
116 }
117
AlgoDeInitAsync()118 void HianimationManager::AlgoDeInitAsync()
119 {
120 #if defined(ASYNC_BUILD_TASK) && defined(ROSEN_OHOS)
121 ffrt::submit_h([this]() {
122 this->HianimationAlgoDeInit();
123 }, {}, {});
124 #else
125 HianimationAlgoDeInit();
126 #endif
127 }
128
HianimationInvalid()129 bool HianimationManager::HianimationInvalid()
130 {
131 std::unique_lock<std::mutex> lock(mutex_);
132 return openFailNum_ > MAX_INIT_TIMES;
133 }
134
OpenDevice()135 void HianimationManager::OpenDevice()
136 {
137 #if defined(ROSEN_OHOS)
138 std::unique_lock<std::mutex> lock(mutex_);
139 if (hianimationDevice_ != nullptr) {
140 // do nothing
141 return;
142 }
143
144 if (openFailNum_ > MAX_INIT_TIMES) {
145 // avoid try too many times
146 return;
147 }
148
149 HPAE_TRACE_NAME("Hianimation: OpenDevice");
150
151 if (libHandle_ != nullptr) {
152 HPAE_LOGW("[%{public}s_%{public}d]:exception and close library", __func__, __LINE__);
153 dlclose(libHandle_);
154 }
155
156 libHandle_ = dlopen("libanimation.z.so", RTLD_LAZY);
157 if (libHandle_ == nullptr) {
158 HPAE_LOGW("[%{public}s_%{public}d]:load library failed, reason: %{public}s", __func__, __LINE__, dlerror());
159 openFailNum_++;
160 return;
161 }
162 GetHianimationDeviceFunc getDevFunc = reinterpret_cast<GetHianimationDeviceFunc>(
163 dlsym(libHandle_, "GetHianimationDevice"));
164 if (getDevFunc == nullptr) {
165 HPAE_LOGW("[%{public}s_%{public}d]:load func failed, reason: %{public}s", __func__, __LINE__, dlerror());
166 dlclose(libHandle_);
167 openFailNum_++;
168 return;
169 }
170 HPAE_LOGI("[%{public}s_%{public}d]:load success", __func__, __LINE__);
171 hianimationDevice_ = getDevFunc();
172
173 {
174 HPAE_TRACE_NAME_FMT("Hianimation: load: %p", hianimationDevice_);
175 }
176
177 openFailNum_ = 0;
178 #endif
179 }
180
CloseDevice()181 void HianimationManager::CloseDevice()
182 {
183 #if defined(ROSEN_OHOS)
184 std::unique_lock<std::mutex> lock(mutex_);
185 HPAE_TRACE_NAME("Hianimation: CloseDevice");
186 if (libHandle_ != nullptr) {
187 dlclose(libHandle_);
188 }
189 hianimationDevice_ = nullptr;
190 #endif
191 }
192
HianimationInputCheck(const struct BlurImgParam * imgInfo,const struct HaeNoiseValue * noisePara)193 bool HianimationManager::HianimationInputCheck(const struct BlurImgParam *imgInfo,
194 const struct HaeNoiseValue *noisePara)
195 {
196 WaitAlgoInit();
197
198 std::unique_lock<std::mutex> lock(mutex_);
199 if (hianimationDevice_ == nullptr) {
200 HPAE_LOGE("device is nullptr");
201 return false;
202 }
203
204 HPAE_TRACE_NAME_FMT("Hianimation: HianimationInputCheck: w:%d, h:%d, sigma:%f",
205 imgInfo->width, imgInfo->height, imgInfo->sigmaNum);
206 HPAE_LOGI("HianimationInputCheck: w:%{public}d, h:%{public}d, sigma:%{public}f",
207 imgInfo->width, imgInfo->height, imgInfo->sigmaNum);
208 return hianimationDevice_->hianimationInputCheck(imgInfo, noisePara);
209 }
210
HianimationAlgoInit(uint32_t panelWidth,uint32_t panelHeight,float maxSigma,uint32_t format)211 int32_t HianimationManager::HianimationAlgoInit(uint32_t panelWidth, uint32_t panelHeight,
212 float maxSigma, uint32_t format)
213 {
214 WaitAllTaskDone(); // do outside mutex_
215
216 std::unique_lock<std::mutex> lock(mutex_);
217 if (hianimationDevice_ == nullptr) {
218 HPAE_LOGE("device is nullptr");
219 return -1;
220 }
221
222 HPAE_TRACE_NAME("Hianimation: HianimationAlgoInit");
223 HPAE_LOGI("HianimationAlgoInit");
224
225 for (auto taskId : taskIdMap_) {
226 HPAE_LOGW("force destroy task: %d", taskId);
227 hianimationDevice_->hianimationDestroyTask(taskId);
228 }
229 taskIdMap_.clear();
230
231 auto result = hianimationDevice_->hianimationAlgoInit(panelWidth, panelHeight, maxSigma, format);
232
233 return result;
234 }
235
HianimationAlgoDeInit()236 int32_t HianimationManager::HianimationAlgoDeInit()
237 {
238 WaitAlgoInit();
239 WaitAllTaskDone(); // do outside mutex_
240
241 std::unique_lock<std::mutex> lock(mutex_);
242 if (hianimationDevice_ == nullptr) {
243 HPAE_LOGE("device is nullptr");
244 return -1;
245 }
246
247 HPAE_TRACE_NAME("Hianimation: HianimationAlgoDeInit");
248 HPAE_LOGI("HianimationAlgoDeInit");
249
250 for (auto taskId : taskIdMap_) {
251 HPAE_LOGW("force destroy task: %d", taskId);
252 hianimationDevice_->hianimationDestroyTask(taskId);
253 }
254 taskIdMap_.clear();
255
256 int32_t result = hianimationDevice_->hianimationAlgoDeInit();
257
258 return result;
259 }
260
WaitAllTaskDone()261 bool HianimationManager::WaitAllTaskDone()
262 {
263 std::unique_lock<std::mutex> lock(mutex_);
264 bool result = true;
265 if (!taskIdMap_.empty()) {
266 HPAE_TRACE_NAME("WaitAllTaskDone");
267 HPAE_LOGW("WaitAllTaskDone");
268 result = taskAvailableCv_.wait_for(lock, 30ms, [this]() {
269 return this->taskIdMap_.empty();
270 });
271 }
272
273 if (!result) {
274 HPAE_LOGE("hpae task lost!");
275 }
276
277 return result;
278 }
279
WaitPreviousTask()280 bool HianimationManager::WaitPreviousTask()
281 {
282 std::unique_lock<std::mutex> lock(mutex_);
283 bool result = true;
284 if (taskIdMap_.size() >= HPAE_BLUR_DELAY) {
285 HPAE_TRACE_NAME("WaitPreviousTask");
286 result = taskAvailableCv_.wait_for(lock, 10ms, [this]() {
287 return this->taskIdMap_.size() < HPAE_BLUR_DELAY;
288 });
289 }
290
291 return result;
292 }
293
HianimationBuildTask(const struct HaeBlurBasicAttr * basicInfo,const struct HaeBlurEffectAttr * effectInfo,uint32_t * outTaskId,void ** outTaskPtr)294 int32_t HianimationManager::HianimationBuildTask(const struct HaeBlurBasicAttr *basicInfo,
295 const struct HaeBlurEffectAttr *effectInfo, uint32_t *outTaskId, void **outTaskPtr)
296 {
297 std::unique_lock<std::mutex> lock(mutex_);
298 if (hianimationDevice_ == nullptr) {
299 HPAE_LOGE("device is nullptr");
300 return -1;
301 }
302
303 HPAE_TRACE_NAME("Hianimation: HianimationBuildTask");
304 auto ret = hianimationDevice_->hianimationBuildTask(basicInfo, effectInfo, outTaskId, outTaskPtr);
305 if (ret == 0 && outTaskId) {
306 taskIdMap_.insert(*outTaskId);
307 }
308 return ret;
309 }
310
HianimationDestroyTask(uint32_t taskId)311 int32_t HianimationManager::HianimationDestroyTask(uint32_t taskId)
312 {
313 std::unique_lock<std::mutex> lock(mutex_);
314
315 if (hianimationDevice_ == nullptr) {
316 HPAE_LOGE("device is nullptr");
317 return -1;
318 }
319
320 HPAE_TRACE_NAME_FMT("Hianimation: HianimationDestroyTask: %d", taskId);
321 taskIdMap_.erase(taskId);
322 return hianimationDevice_->hianimationDestroyTask(taskId);
323 }
324
HianimationDestroyTaskAndNotify(uint32_t taskId)325 int32_t HianimationManager::HianimationDestroyTaskAndNotify(uint32_t taskId)
326 {
327 std::unique_lock<std::mutex> lock(mutex_);
328
329 if (hianimationDevice_ == nullptr) {
330 HPAE_LOGE("device is nullptr");
331 return -1;
332 }
333
334 HPAE_TRACE_NAME_FMT("Hianimation: HianimationDestroyTaskAndNotify: %d", taskId);
335 int32_t ret = hianimationDevice_->hianimationDestroyTask(taskId);
336 taskIdMap_.erase(taskId);
337 taskAvailableCv_.notify_all();
338
339 NotifyHpaeDone();
340
341 return ret;
342 }
343
HianimationPerfTrack()344 void HianimationManager::HianimationPerfTrack()
345 {
346 {
347 std::unique_lock<std::mutex> lock(hpaePerfMutex_);
348 hpaePerfDone_ = false;
349 }
350
351 RSHpaePerfThread::Instance().PostTask([this]() {
352 HPAE_TRACE_NAME("WaitHpae");
353 this->WaitHpaeDone();
354 });
355 }
356 } // OHOS::Rosen