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
16 #include "hpae_base/rs_hpae_ffrt_pattern_manager.h"
17
18 #if defined(ROSEN_OHOS)
19 #include <dlfcn.h>
20 #include <unistd.h>
21 #endif
22
23 #include "hpae_base/rs_hpae_log.h"
24
25 #include "platform/common/rs_log.h"
26
27 namespace OHOS {
28 namespace Rosen {
29
30 namespace {
31 using GPInstanceGetFunc = void*(*)(PatternType_C, const char*);
32 using GPInstanceInitFunc = bool(*)(void*, size_t);
33 using GPInstanceDestroyFunc = void(*)(void*);
34 using GPRequestEGraphFunc = bool(*)(void*, uint64_t);
35 using GPReleaseEGraphFunc = bool(*)(void*, uint64_t);
36 using GPReleaseAllEGraphFunc = bool(*)(void*);
37 using GPWaitFunc = void*(*)(void*, uint64_t, MHC_PatternTaskName);
38 using GPGetGPUWaitEventFunc = uint16_t(*)(void*, uint64_t, MHC_PatternTaskName);
39 using GPGetGPUNotifyEventFunc = uint16_t(*)(void*, uint64_t, MHC_PatternTaskName);
40 using GPGPTaskSubmitFunc = void(*)(void*, uint64_t, MHC_TaskInfo*);
41
42 static GPInstanceGetFunc g_getGPInstance = nullptr;
43 static GPInstanceInitFunc g_GPInit = nullptr;
44 static GPInstanceDestroyFunc g_GPDestroy = nullptr;
45 static GPRequestEGraphFunc g_GPRequestEGraph = nullptr;
46 static GPReleaseEGraphFunc g_GPReleaseEGraph = nullptr;
47 static GPReleaseAllEGraphFunc g_GPReleaseAll = nullptr;
48 static GPWaitFunc g_GPWait = nullptr;
49 static GPGetGPUWaitEventFunc g_GPGetVulkanWaitEvent = nullptr;
50 static GPGetGPUNotifyEventFunc g_GPGetVulkanNotifyEvent = nullptr;
51 static GPGPTaskSubmitFunc g_GPTaskSubmit = nullptr;
52 static void* g_mhcHandle = nullptr;
53 }
54
Instance()55 RSHpaeFfrtPatternManager& RSHpaeFfrtPatternManager::Instance()
56 {
57 static RSHpaeFfrtPatternManager instance;
58 return instance;
59 }
60
RSHpaeFfrtPatternManager()61 RSHpaeFfrtPatternManager::RSHpaeFfrtPatternManager()
62 {
63 if (!MHCDlOpen()) {
64 HPAE_LOGE("MHCDlOpen() failed!");
65 }
66 if (!MHCGraphPatternInit(GRAPH_NUM)) {
67 HPAE_LOGE("MHCGraphPatternInit() failed!");
68 }
69 HPAE_LOGW("mhc_so MHCGraphPatternInit success!");
70 }
71
~RSHpaeFfrtPatternManager()72 RSHpaeFfrtPatternManager::~RSHpaeFfrtPatternManager()
73 {
74 if (g_instance) {
75 g_GPDestroy(g_instance);
76 g_instance = nullptr;
77 }
78
79 if (g_mhcHandle) {
80 #if defined(ROSEN_OHOS)
81 dlclose(g_mhcHandle);
82 #endif
83 g_getGPInstance = nullptr;
84 g_GPInit = nullptr;
85 g_GPDestroy = nullptr;
86 g_GPRequestEGraph = nullptr;
87 g_GPReleaseEGraph = nullptr;
88 g_GPReleaseAll = nullptr;
89 g_GPWait = nullptr;
90 g_GPGetVulkanWaitEvent = nullptr;
91 g_GPGetVulkanNotifyEvent = nullptr;
92 g_GPTaskSubmit = nullptr;
93 g_mhcHandle = nullptr;
94 }
95 }
96
MHCDlOpen()97 bool RSHpaeFfrtPatternManager::MHCDlOpen()
98 {
99 #if defined(ROSEN_OHOS)
100 HPAE_LOGW("mhc_so MHCDlOpen start\n");
101 if (g_mhcHandle == nullptr) {
102 g_mhcHandle = dlopen("/vendor/lib64/libmhc_framework.so", RTLD_LAZY | RTLD_NODELETE);
103 if (!g_mhcHandle) {
104 HPAE_LOGW("mhc_so dlopen libmhc_framework.so error\n");
105 return false;
106 }
107 }
108
109 g_getGPInstance = reinterpret_cast<GPInstanceGetFunc>(dlsym(g_mhcHandle, "mhc_graph_pattern_get"));
110 g_GPInit = reinterpret_cast<GPInstanceInitFunc>(dlsym(g_mhcHandle, "mhc_graph_pattern_init"));
111 g_GPDestroy = reinterpret_cast<GPInstanceDestroyFunc>(dlsym(g_mhcHandle, "mhc_graph_pattern_destroy"));
112 g_GPRequestEGraph = reinterpret_cast<GPRequestEGraphFunc>(dlsym(g_mhcHandle, "mhc_graph_pattern_request_eg"));
113 g_GPReleaseEGraph = reinterpret_cast<GPReleaseEGraphFunc>(dlsym(g_mhcHandle, "mhc_graph_pattern_release_eg"));
114 g_GPReleaseAll = reinterpret_cast<GPReleaseAllEGraphFunc>(dlsym(g_mhcHandle, "mhc_graph_pattern_relsease_all"));
115 g_GPWait = reinterpret_cast<GPWaitFunc>(dlsym(g_mhcHandle, "mhc_gp_task_wait"));
116 g_GPGetVulkanWaitEvent = reinterpret_cast<GPGetGPUWaitEventFunc>(
117 dlsym(g_mhcHandle, "mhc_gp_vulkan_task_get_wait_event"));
118 g_GPGetVulkanNotifyEvent = reinterpret_cast<GPGetGPUNotifyEventFunc>(
119 dlsym(g_mhcHandle, "mhc_gp_vulkan_task_get_notify_event"));
120 g_GPTaskSubmit = reinterpret_cast<GPGPTaskSubmitFunc>(dlsym(g_mhcHandle, "mhc_gp_task_submit"));
121 if (!g_getGPInstance || !g_GPInit || !g_GPDestroy || !g_GPRequestEGraph || !g_GPReleaseEGraph || !g_GPWait\
122 || !g_GPGetVulkanWaitEvent || !g_GPGetVulkanNotifyEvent || !g_GPTaskSubmit || !g_GPReleaseAll) {
123 HPAE_LOGE("mhc_so dlsym error\n");
124 dlclose(g_mhcHandle);
125 g_mhcHandle = nullptr;
126 return false;
127 }
128
129 HPAE_LOGW("mhc_so LoadLibMHC success\n");
130 return true;
131 #else
132 return false;
133 #endif
134 }
135
MHCCheck(const std::string logTag,uint64_t frameId)136 bool RSHpaeFfrtPatternManager::MHCCheck(const std::string logTag, uint64_t frameId)
137 {
138 if (!g_instance) {
139 HPAE_LOGE("mhc_so MHCCheck %{public}s g_instance == nullptr", logTag.c_str());
140 return false;
141 }
142 HPAE_LOGW("mhc_so %{public}s MHCCheck frameId:%{public}" PRIu64 " ", logTag.c_str(), frameId);
143 return true;
144 }
145
MHCGraphPatternInit(size_t size)146 bool RSHpaeFfrtPatternManager::MHCGraphPatternInit(size_t size)
147 {
148 HPAE_LOGW("mhc_so MHCGraphPatternInit");
149 if (g_instance) {
150 return true;
151 }
152 if (g_getGPInstance == nullptr) {
153 HPAE_LOGW("mhc_so g_getGPInstance nullptr");
154 return false;
155 }
156 g_instance = g_getGPInstance(PatternType_C::BLUR, "blur_graph");
157 return g_GPInit(g_instance, size);
158 }
159
MHCRequestEGraph(uint64_t frameId)160 bool RSHpaeFfrtPatternManager::MHCRequestEGraph(uint64_t frameId)
161 {
162 if (!g_instance) {
163 HPAE_LOGW("mhc_so MHCRequestEGraph g_instance nullptr");
164 return false;
165 }
166 if (g_GPRequestEGraph == nullptr) {
167 HPAE_LOGW("mhc_so g_GPRequestEGraph nullptr");
168 return false;
169 }
170 return g_GPRequestEGraph(g_instance, frameId);
171 }
172
MHCWait(uint64_t frameId,MHC_PatternTaskName taskName)173 bool RSHpaeFfrtPatternManager::MHCWait(uint64_t frameId, MHC_PatternTaskName taskName)
174 {
175 if (!MHCCheck("MHCWait", frameId)) {
176 return false;
177 }
178
179 if (g_GPWait == nullptr) {
180 HPAE_LOGW("mhc_so g_GPWait nullptr");
181 return false;
182 }
183
184 g_GPWait(g_instance, frameId, taskName);
185 return true;
186 }
187
MHCGetVulkanTaskWaitEvent(uint64_t frameId,MHC_PatternTaskName taskName)188 uint16_t RSHpaeFfrtPatternManager::MHCGetVulkanTaskWaitEvent(uint64_t frameId, MHC_PatternTaskName taskName)
189 {
190 if (!MHCCheck("MHCGetVulkanTaskWaitEvent", frameId)) {
191 return false;
192 }
193
194 if (g_GPGetVulkanWaitEvent == nullptr) {
195 HPAE_LOGW("mhc_so g_GPGetVulkanWaitEvent nullptr");
196 return false;
197 }
198
199 auto eventId = g_GPGetVulkanWaitEvent(g_instance, frameId, taskName);
200 HPAE_LOGW("mhc_so MHCGetVulkanTaskWaitEvent event = %{public}d, taskName=%{public}d\n", eventId, taskName);
201 return eventId;
202 }
203
MHCGetVulkanTaskNotifyEvent(uint64_t frameId,MHC_PatternTaskName taskName)204 uint16_t RSHpaeFfrtPatternManager::MHCGetVulkanTaskNotifyEvent(uint64_t frameId, MHC_PatternTaskName taskName)
205 {
206 if (!MHCCheck("MHCGetVulkanTaskNotifyEvent", frameId)) {
207 return false;
208 }
209
210 if (g_GPGetVulkanNotifyEvent == nullptr) {
211 HPAE_LOGW("mhc_so g_GPGetVulkanNotifyEvent nullptr");
212 return false;
213 }
214
215 auto eventId = g_GPGetVulkanNotifyEvent(g_instance, frameId, taskName);
216 HPAE_LOGW("mhc_so MHCGetVulkanTaskNotifyEvent event = %{public}d, taskName=%{public}d\n", eventId, taskName);
217 return eventId;
218 }
219
MHCReleaseEGraph(uint64_t frameId)220 bool RSHpaeFfrtPatternManager::MHCReleaseEGraph(uint64_t frameId)
221 {
222 if (!MHCCheck("MHCReleaseEGraph", frameId)) {
223 return false;
224 }
225
226 if (g_GPReleaseEGraph == nullptr) {
227 HPAE_LOGW("mhc_so g_GPReleaseEGraph nullptr");
228 return false;
229 }
230
231 return g_GPReleaseEGraph(g_instance, frameId);
232 }
233
MHCReleaseAll()234 void RSHpaeFfrtPatternManager::MHCReleaseAll()
235 {
236 HPAE_LOGW("mhc_so MHCReleaseAll");
237 if (g_instance == nullptr) {
238 HPAE_LOGE("mhc_so MHCReleaseAll g_instance == nullptr");
239 return;
240 }
241
242 if (g_GPReleaseAll == nullptr) {
243 HPAE_LOGW("mhc_so g_GPReleaseAll nullptr");
244 return;
245 }
246 // return 1 is succ
247 int ret = g_GPReleaseAll(g_instance);
248 ROSEN_LOGI("mhc_so MHCReleaseAll, ret=%{public}d", ret);
249 }
250
MHCSubmitTask(uint64_t frameId,MHC_PatternTaskName taskName,std::function<void ()> && preFunc,void *** taskHandleVec,size_t numTask,std::function<void ()> && afterFunc)251 bool RSHpaeFfrtPatternManager::MHCSubmitTask(uint64_t frameId, MHC_PatternTaskName taskName, \
252 std::function<void()>&& preFunc, void*** taskHandleVec, size_t numTask, std::function<void()>&&afterFunc)
253 {
254 if (!MHCCheck("MHCSubmitTask", frameId)) {
255 return false;
256 }
257
258 if (g_GPTaskSubmit == nullptr) {
259 HPAE_LOGW("mhc_so g_GPTaskSubmit nullptr");
260 return false;
261 }
262
263 FunctionHeader* preFuncHeader = create_function_wrapper(std::move(preFunc));
264 void* c_preFunc = static_cast<void*>(preFuncHeader);
265 FunctionHeader* afterFuncHeader = create_function_wrapper(std::move(afterFunc));
266 void* c_afterFunc = static_cast<void*>(afterFuncHeader);
267
268 MHC_TaskInfo mhcTaskInfo = {
269 .taskName = taskName,
270 .c_prefunc = c_preFunc,
271 .c_taskHandles = taskHandleVec,
272 .numTasks = numTask,
273 .c_afterFunc = c_afterFunc
274 };
275 g_GPTaskSubmit(g_instance, frameId, &mhcTaskInfo);
276 return true;
277 }
278
IsThreadIdMatch()279 bool RSHpaeFfrtPatternManager::IsThreadIdMatch()
280 {
281 #if defined(ROSEN_OHOS)
282 return tid_ == gettid();
283 #else
284 return false;
285 #endif
286 }
SetThreadId()287 void RSHpaeFfrtPatternManager::SetThreadId()
288 {
289 #if defined(ROSEN_OHOS)
290 tid_ = gettid();
291 #endif
292 }
IsUpdated()293 bool RSHpaeFfrtPatternManager::IsUpdated()
294 {
295 return updated_ && IsThreadIdMatch();
296 }
297
298 } // namespace Rosen
299 } // namespace OHOS