1 /*
2 * Copyright (c) 2022 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 "driver_loader.h"
16 #include <dlfcn.h>
17 #include <iostream>
18 #include <mutex>
19 #include "wrapper_log.h"
20 #include "directory_ex.h"
21
22 namespace vulkan {
23 namespace driver {
24 #ifdef __aarch64__
25 constexpr const char *VENDOR_LIB_PATH = "/vendor/lib64/chipsetsdk/";
26 constexpr const char *SYSTEM_LIB_PATH = "/system/lib64/";
27 #else
28 constexpr const char *VENDOR_LIB_PATH = "/vendor/lib/chipsetsdk/";
29 constexpr const char *SYSTEM_LIB_PATH = "/system/lib/";
30 #endif
31 constexpr const char *LIB_NAME = "libEGL_impl.so";
32 constexpr const char *HDI_VULKAN_MODULE_INIT = "VulkanInitialize";
33 constexpr const char *HDI_VULKAN_MODULE_UNINIT = "VulkanUnInitialize";
34
Load()35 bool DriverLoader::Load()
36 {
37 static std::mutex loadLock;
38 std::lock_guard<std::mutex> lock(loadLock);
39
40 if (loader_.vulkanFuncs_ != nullptr) {
41 return true;
42 }
43 loader_.supported_ = false;
44
45 if (!LoadDriver()) {
46 WLOGE("LoadDriver failed");
47 return false;
48 }
49
50 PFN_VulkanInitialize VulkanInitializeFunc
51 = reinterpret_cast<PFN_VulkanInitialize>(dlsym(loader_.handle_, HDI_VULKAN_MODULE_INIT));
52 if (VulkanInitializeFunc == nullptr) {
53 WLOGE("DriverLoader:: couldn't find symbol(VulkanInitializeFunc) in library : %{public}s.", dlerror());
54 UnloadDriver();
55 return false;
56 }
57
58 if (VulkanInitializeFunc(&loader_.vulkanFuncs_) != 0) {
59 WLOGE("DriverLoader:: Initialize Vulkan Func fail");
60 UnloadDriver();
61 return false;
62 }
63
64 loader_.vulkanUnInitializeFunc_ = reinterpret_cast<PFN_VulkanUnInitialize>(
65 dlsym(loader_.handle_, HDI_VULKAN_MODULE_UNINIT));
66
67 if (loader_.vulkanUnInitializeFunc_ == nullptr) {
68 WLOGE("DriverLoader:: couldn't find symbol(VulkanUnInitialize) in library : %{public}s.", dlerror());
69 UnloadDriver();
70 return false;
71 }
72 loader_.supported_ = true;
73 WLOGI("DriverLoader:: Found Vulkan Func success");
74 return true;
75 }
76
Unload()77 bool DriverLoader::Unload()
78 {
79 if (loader_.vulkanUnInitializeFunc_ == nullptr) {
80 WLOGE("DriverLoader::Unload can not find vulkan UnInitialize Func.");
81 return false;
82 }
83 if (loader_.vulkanUnInitializeFunc_(loader_.vulkanFuncs_) != 0) {
84 WLOGE("DriverLoader::Unload vulkan UnInitialize Func failed.");
85 return false;
86 }
87 loader_.vulkanFuncs_ = nullptr;
88 loader_.vulkanUnInitializeFunc_ = nullptr;
89 WLOGD("DriverLoader::Unload vulkan UnInitialize Func successfully.");
90 return UnloadDriver();
91 }
92
LoadDriver()93 bool DriverLoader::LoadDriver()
94 {
95 if (loader_.handle_ != nullptr) {
96 WLOGD("handle is not null, no need to dlopen.");
97 return true;
98 }
99 std::string venderPath = std::string(VENDOR_LIB_PATH) + std::string(LIB_NAME);
100 std::string systemPath = std::string(SYSTEM_LIB_PATH) + std::string(LIB_NAME);
101 if (!LoadDriverFromFile(venderPath)) {
102 if (!LoadDriverFromFile(systemPath)) {
103 return false;
104 }
105 }
106 WLOGD("DriverLoader::LoadDriver successfully.");
107 return true;
108 }
109
UnloadDriver()110 bool DriverLoader::UnloadDriver()
111 {
112 if (loader_.handle_ == nullptr) {
113 WLOGD("DriverLoader::UnloadDriver handle is null already.");
114 return true;
115 }
116 if (dlclose(loader_.handle_) != 0) {
117 WLOGE("DriverLoader::UnloadDriver dlclose failed.");
118 return false;
119 }
120 loader_.handle_ = nullptr;
121 WLOGD("DriverLoader::UnloadDriver dlclose success.");
122 return true;
123 }
124
LoadDriverFromFile(std::string path)125 bool DriverLoader::LoadDriverFromFile(std::string path)
126 {
127 std::string realPath;
128 if (!OHOS::PathToRealPath(path, realPath)) {
129 WLOGE("file is not in path: %{private}s", path.c_str());
130 return false;
131 }
132 loader_.handle_ = dlopen(realPath.c_str(), RTLD_LOCAL | RTLD_NOW);
133 if (loader_.handle_ == nullptr) {
134 WLOGE("dlopen failed. error: %{public}s.", dlerror());
135 return false;
136 }
137 return true;
138 }
139 } // namespace driver
140 } // namespace vulkan
141