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