• 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 
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