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 "hetero_hdr/rs_hdr_pattern_manager.h"
17
18 #ifdef ROSEN_OHOS
19 #include <dlfcn.h>
20 #endif
21
22 using GPInstanceGetFunc = void*(*)(PatternType_C, const char*);
23 using GPInstanceInitFunc = bool(*)(void*, size_t);
24 using GPInstanceDestroyFunc = void(*)(void*);
25 using GPRequstEGraphFunc = bool(*)(void*, uint64_t);
26 using GPQueryTaskError = int32_t(*)(void*, uint64_t, MHC_PatternTaskName);
27 using GPReleaseEGraphFunc = bool(*)(void*, uint64_t);
28 using GPReleaseAllFunc = bool(*)(void*);
29 using GPAAETaskSubmitFunc = void(*)(void*, uint64_t, MHC_PatternTaskName, void*, void**, void*);
30 using GPWaitFunc = void(*)(void*, uint64_t, MHC_PatternTaskName);
31 using GPGPUTaskSubmitFunc = void(*)(void*, uint64_t, MHC_PatternTaskName, void*, void*);
32 using GPGetGPUWaitEventFunc = uint16_t(*)(void*, uint64_t, MHC_PatternTaskName);
33 using GPGetGPUNotifyEventFunc = uint16_t(*)(void*, uint64_t, MHC_PatternTaskName);
34
35 namespace {
36 static GPInstanceGetFunc g_getGraphPatternInstance = nullptr;
37 static GPInstanceInitFunc g_graphPatternInit = nullptr;
38 static GPInstanceDestroyFunc g_graphPatternDestroy = nullptr;
39 static GPRequstEGraphFunc g_graphPatternRequestEGraph = nullptr;
40 static GPReleaseEGraphFunc g_graphPatternReleaseEGraph = nullptr;
41 static GPReleaseAllFunc g_graphPatternReleaseAll = nullptr;
42 static GPAAETaskSubmitFunc g_graphPatternAnimationTaskSubmit = nullptr;
43 static GPGPUTaskSubmitFunc g_graphPatternVulkanTaskSubmit = nullptr;
44 static GPWaitFunc g_graphPatternWait = nullptr;
45 static GPGetGPUWaitEventFunc g_graphPatternGetVulkanWaitEvent = nullptr;
46 static GPGetGPUNotifyEventFunc g_graphPatternGetVulkanNotifyEvent = nullptr;
47
48 #ifdef ROSEN_OHOS
49 static void* g_mhcLibframeworkHandle = nullptr;
50 #endif
51 }
52
53 namespace OHOS {
54 namespace Rosen {
55
56 template <typename F>
create_function_wrapper(F && func)57 std::shared_ptr<FunctionHeader> create_function_wrapper(F &&func)
58 {
59 if (func == nullptr) {
60 return nullptr;
61 }
62 // 1. Allocate callable on heap with perfect forwarding
63 auto *func_copy = new std::decay_t<F>(std::forward<F>(func));
64
65 // 2. Create function header structure
66 auto header = std::make_shared<FunctionHeader>();
67
68 // 3. Set up execution function that invokes the callable
69 header->execute = [](void *data) {
70 auto *f = static_cast<std::decay_t<F> *>(data);
71 (*f)(); // operator()
72 };
73
74 // 4. Set up cleanup function to release resources
75 header->destroy = [](void *data) {
76 auto *f = static_cast<std::decay_t<F> *>(data);
77 delete f;
78 };
79
80 // 5. Store callable pointer in header
81 header->data = func_copy;
82 return header;
83 }
84
Instance()85 RSHDRPatternManager& RSHDRPatternManager::Instance()
86 {
87 static RSHDRPatternManager instance;
88 return instance;
89 }
90
RSHDRPatternManager()91 RSHDRPatternManager::RSHDRPatternManager()
92 {
93 }
94
~RSHDRPatternManager()95 RSHDRPatternManager::~RSHDRPatternManager()
96 {
97 if (g_instance) {
98 g_graphPatternDestroy(g_instance);
99 g_instance = nullptr;
100 }
101 #ifdef ROSEN_OHOS
102 if (g_mhcLibframeworkHandle) {
103 dlclose(g_mhcLibframeworkHandle);
104 g_getGraphPatternInstance = nullptr;
105 g_graphPatternInit = nullptr;
106 g_graphPatternDestroy = nullptr;
107 g_graphPatternRequestEGraph = nullptr;
108 g_graphPatternReleaseEGraph = nullptr;
109 g_graphPatternAnimationTaskSubmit = nullptr;
110 g_graphPatternVulkanTaskSubmit = nullptr;
111 g_graphPatternWait = nullptr;
112 g_graphPatternGetVulkanWaitEvent = nullptr;
113 g_graphPatternGetVulkanNotifyEvent = nullptr;
114 }
115 #endif
116 }
117
MHCDlOpen()118 bool RSHDRPatternManager::MHCDlOpen()
119 {
120 #ifdef ROSEN_OHOS
121 RS_LOGW("mhc_so MHCDlOpen start\n");
122 if (isFinishDLOpen_) {
123 RS_LOGE("mhc_so MHCDlOpen isFinishDLOpen_ true\n");
124 return true;
125 }
126 if (g_mhcLibframeworkHandle == nullptr) {
127 g_mhcLibframeworkHandle = dlopen("/vendor/lib64/libmhc_framework.so", RTLD_LAZY | RTLD_NODELETE);
128 if (!g_mhcLibframeworkHandle) {
129 RS_LOGW("mhc_so dlopen libmhc_framework.so error\n");
130 return false;
131 }
132 }
133
134 g_getGraphPatternInstance = reinterpret_cast<GPInstanceGetFunc>(dlsym(g_mhcLibframeworkHandle,
135 "mhc_graph_pattern_get"));
136 g_graphPatternInit = reinterpret_cast<GPInstanceInitFunc>(dlsym(g_mhcLibframeworkHandle,
137 "mhc_graph_pattern_init"));
138 g_graphPatternDestroy = reinterpret_cast<GPInstanceDestroyFunc>(dlsym(g_mhcLibframeworkHandle,
139 "mhc_graph_pattern_destroy"));
140 g_graphPatternRequestEGraph = reinterpret_cast<GPRequstEGraphFunc>(dlsym(g_mhcLibframeworkHandle,
141 "mhc_graph_pattern_request_eg"));
142 g_graphPatternReleaseEGraph = reinterpret_cast<GPReleaseEGraphFunc>(dlsym(g_mhcLibframeworkHandle,
143 "mhc_graph_pattern_release_eg"));
144 g_graphPatternReleaseAll = reinterpret_cast<GPReleaseAllFunc>(dlsym(g_mhcLibframeworkHandle,
145 "mhc_graph_pattern_release_all"));
146 g_graphPatternAnimationTaskSubmit = reinterpret_cast<GPAAETaskSubmitFunc>(dlsym(g_mhcLibframeworkHandle,
147 "mhc_gp_animation_task_submit"));
148 g_graphPatternVulkanTaskSubmit = reinterpret_cast<GPGPUTaskSubmitFunc>(dlsym(g_mhcLibframeworkHandle,
149 "mhc_gp_vulkan_task_submit"));
150 g_graphPatternWait = reinterpret_cast<GPWaitFunc>(dlsym(g_mhcLibframeworkHandle, "mhc_gp_task_wait"));
151 g_graphPatternGetVulkanWaitEvent = reinterpret_cast<GPGetGPUWaitEventFunc>(dlsym(g_mhcLibframeworkHandle,
152 "mhc_gp_vulkan_task_get_wait_event"));
153 g_graphPatternGetVulkanNotifyEvent = reinterpret_cast<GPGetGPUNotifyEventFunc>(dlsym(g_mhcLibframeworkHandle,
154 "mhc_gp_vulkan_task_get_notify_event"));
155
156 if (!g_getGraphPatternInstance || !g_graphPatternInit || !g_graphPatternDestroy || !g_graphPatternRequestEGraph\
157 || !g_graphPatternReleaseEGraph || !g_graphPatternAnimationTaskSubmit || !g_graphPatternVulkanTaskSubmit\
158 || !g_graphPatternWait || !g_graphPatternGetVulkanWaitEvent || !g_graphPatternGetVulkanNotifyEvent\
159 || !g_graphPatternReleaseAll) {
160 RS_LOGE("mhc_so dlsym error\n");
161 dlclose(g_mhcLibframeworkHandle);
162 return false;
163 }
164 isFinishDLOpen_ = true;
165 RS_LOGW("mhc_so LoadLibMHC success\n");
166 return true;
167 #else
168 return false;
169 #endif
170 }
171
MHCCheck(const std::string logTag,uint64_t frameId)172 bool RSHDRPatternManager::MHCCheck(const std::string logTag, uint64_t frameId)
173 {
174 if (!g_instance) {
175 RS_LOGE("mhc_so MHCCheck %{public}s g_instance == nullptr", logTag.c_str());
176 return false;
177 }
178 RS_LOGW("mhc_so %{public}s MHCCheck frameId:%{public}" PRIu64 " ", logTag.c_str(), frameId);
179 return true;
180 }
181
MHCGraphPatternInit(size_t size)182 bool RSHDRPatternManager::MHCGraphPatternInit(size_t size)
183 {
184 RS_LOGW("mhc_so MHCGraphPatternInit");
185 if (g_instance) {
186 return true;
187 }
188 if (!isFinishDLOpen_) {
189 RS_LOGE("mhc_so dlsym error");
190 return false;
191 }
192 g_instance = g_getGraphPatternInstance(PATTERN_HDR, "test_graph");
193 return g_graphPatternInit(g_instance, size);
194 }
195
MHCRequestEGraph(uint64_t frameId)196 bool RSHDRPatternManager::MHCRequestEGraph(uint64_t frameId)
197 {
198 if (!MHCCheck("MHCRequestEGraph", frameId)) {
199 return false;
200 }
201 return g_graphPatternRequestEGraph(g_instance, frameId);
202 }
203
MHCSubmitHDRTask(uint64_t frameId,MHC_PatternTaskName taskName,std::function<void ()> && preFunc,void ** taskHandle,std::function<void ()> && afterFunc)204 bool RSHDRPatternManager::MHCSubmitHDRTask(uint64_t frameId, MHC_PatternTaskName taskName, \
205 std::function<void()>&& preFunc, void** taskHandle, std::function<void()>&& afterFunc)
206 {
207 if (!MHCCheck("MHCSubmitHDRTask", frameId)) {
208 return false;
209 }
210 std::shared_ptr<FunctionHeader> preFuncHeader = create_function_wrapper(std::move(preFunc));
211 void* c_preFunc = static_cast<void*>(preFuncHeader.get());
212 std::shared_ptr<FunctionHeader> afterFuncHeader = create_function_wrapper(std::move(afterFunc));
213 void* c_afterFunc = static_cast<void*>(afterFuncHeader.get());
214
215 g_graphPatternAnimationTaskSubmit(g_instance, frameId, taskName, c_preFunc, taskHandle, c_afterFunc);
216 return true;
217 }
218
MHCSubmitVulkanTask(uint64_t frameId,MHC_PatternTaskName taskName,std::function<void ()> && preFunc,std::function<void ()> && afterFunc)219 bool RSHDRPatternManager::MHCSubmitVulkanTask(uint64_t frameId, MHC_PatternTaskName taskName, \
220 std::function<void()>&& preFunc, std::function<void()>&& afterFunc)
221 {
222 if (!MHCCheck("MHCSubmitVulkanTask", frameId)) {
223 return false;
224 }
225 std::shared_ptr<FunctionHeader> preFuncHeader = create_function_wrapper(std::move(preFunc));
226 void* c_preFunc = static_cast<void*>(preFuncHeader.get());
227 std::shared_ptr<FunctionHeader> afterFuncHeader = create_function_wrapper(std::move(afterFunc));
228 void* c_afterFunc = static_cast<void*>(afterFuncHeader.get());
229
230 g_graphPatternVulkanTaskSubmit(g_instance, frameId, taskName, c_preFunc, c_afterFunc);
231 return true;
232 }
233
MHCWait(uint64_t frameId,MHC_PatternTaskName taskName)234 bool RSHDRPatternManager::MHCWait(uint64_t frameId, MHC_PatternTaskName taskName)
235 {
236 if (!MHCCheck("MHCWait", frameId)) {
237 return false;
238 }
239
240 g_graphPatternWait(g_instance, frameId, taskName);
241 return true;
242 }
243
MHCGetVulkanTaskWaitEvent(uint64_t frameId,MHC_PatternTaskName taskName)244 uint16_t RSHDRPatternManager::MHCGetVulkanTaskWaitEvent(uint64_t frameId, MHC_PatternTaskName taskName)
245 {
246 if (!MHCCheck("MHCGetVulkanTaskWaitEvent", frameId)) {
247 return false;
248 }
249 auto eventId = g_graphPatternGetVulkanWaitEvent(g_instance, frameId, taskName);
250 RS_LOGW("mhc_so RSHDRPatternManager::MHCGetVulkanTaskWaitEvent event = %{public}d\n", eventId);
251 return eventId;
252 }
253
MHCGetVulkanTaskNotifyEvent(uint64_t frameId,MHC_PatternTaskName taskName)254 uint16_t RSHDRPatternManager::MHCGetVulkanTaskNotifyEvent(uint64_t frameId, MHC_PatternTaskName taskName)
255 {
256 if (!MHCCheck("MHCGetVulkanTaskNotifyEvent", frameId)) {
257 return false;
258 }
259 auto eventId = g_graphPatternGetVulkanNotifyEvent(g_instance, frameId, taskName);
260 RS_LOGW("mhc_so RSHDRPatternManager::MHCGetVulkanTaskNotifyEvent event = %{public}d\n", eventId);
261 return eventId;
262 }
263
MHCReleaseEGraph(uint64_t frameId)264 bool RSHDRPatternManager::MHCReleaseEGraph(uint64_t frameId)
265 {
266 if (!MHCCheck("MHCReleaseEGraph", frameId)) {
267 return false;
268 }
269 return g_graphPatternReleaseEGraph(g_instance, frameId);
270 }
271
MHCReleaseAll()272 bool RSHDRPatternManager::MHCReleaseAll()
273 {
274 if (!g_instance) {
275 return false;
276 }
277 g_graphPatternReleaseAll(g_instance);
278 return true;
279 }
280
MHCGetFrameIdForGpuTask()281 std::vector<uint64_t> RSHDRPatternManager::MHCGetFrameIdForGpuTask()
282 {
283 std::vector<uint64_t> frameIdVec{};
284 #ifdef ROSEN_OHOS
285 std::unique_lock<std::mutex> lock(frameIdMutex_);
286 if (lastFrameIdUsed_ && curFrameIdUsed_) {
287 return frameIdVec;
288 }
289
290 if (lastFrameIdUsed_ == false && lastFrameConsumed_) {
291 lastFrameIdUsed_ = true;
292 lastFrameConsumed_ = false;
293 frameIdVec.emplace_back(lastFrameId_);
294 }
295 if (curFrameIdUsed_ == false && IsThreadIdMatch()) {
296 curFrameIdUsed_ = true;
297 processConsumed_ = false;
298 frameIdVec.emplace_back(curFrameId_);
299 }
300 #endif
301 return frameIdVec;
302 }
303
304 } // namespace Rosen
305 } // namespace OHOS