• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "egl_wrapper_loader.h"
17 
18 #include <dlfcn.h>
19 #include <string>
20 
21 #include "directory_ex.h"
22 
23 #include "egl_defs.h"
24 #include "wrapper_log.h"
25 
26 using namespace OHOS;
27 namespace OHOS {
28 namespace {
29 constexpr const char *LIB_EGL_NAME = "libEGL_impl.so";
30 constexpr const char *LIB_GLESV1_NAME = "libGLESv1_impl.so";
31 constexpr const char *LIB_GLESV2_NAME = "libGLESv2_impl.so";
32 constexpr const char *LIB_GLESV3_NAME = "libGLESv3_impl.so";
33 #ifdef OPENGL_WRAPPER_ENABLE_GL4
34 constexpr const char *LIB_EGL_MESA_NAME = "libEGL_mesa.so";
35 #endif
36 }
37 
GetInstance()38 EglWrapperLoader& EglWrapperLoader::GetInstance()
39 {
40     static EglWrapperLoader loader;
41     return loader;
42 }
43 
~EglWrapperLoader()44 EglWrapperLoader::~EglWrapperLoader()
45 {
46     WLOGD("");
47 }
48 
49 using GetProcAddressType = FunctionPointerType (*)(const char *);
LoadEgl(const char * libName,EglHookTable * table)50 bool EglWrapperLoader::LoadEgl(const char* libName, EglHookTable* table)
51 {
52     WLOGD("");
53     dlEglHandle_ = dlopen(libName, RTLD_NOW | RTLD_LOCAL);
54     if (dlEglHandle_ == nullptr) {
55         WLOGE("dlopen failed. error: %{public}s.", dlerror());
56         return false;
57     }
58 
59     GetProcAddressType getProcAddr =
60         (GetProcAddressType)dlsym(dlEglHandle_, "eglGetProcAddress");
61     if (getProcAddr == nullptr) {
62         WLOGE("can't find eglGetProcAddress() in EGL driver library.");
63         return false;
64     }
65 
66     FunctionPointerType *current = (FunctionPointerType *)table;
67     char const * const *api = gEglApiNames;
68     while (*api) {
69         char const *name = *api;
70         FunctionPointerType func = (FunctionPointerType)dlsym(dlEglHandle_, name);
71         if (func == nullptr) {
72             WLOGD("try to getProcAddr %{public}s.", name);
73             func = getProcAddr(name);
74             if (func == nullptr) {
75                 WLOGD("couldn't find the entry-point: %{public}s.", name);
76             }
77         }
78 
79         *current++ = func;
80         api++;
81     }
82 
83     return true;
84 }
85 
86 #ifdef OPENGL_WRAPPER_ENABLE_GL4
LoadGlFromMesa(char const * const * glName,FunctionPointerType * entry)87 bool EglWrapperLoader::LoadGlFromMesa(char const * const *glName, FunctionPointerType *entry)
88 {
89     if (!dlEglHandle_ || !gWrapperHook.useMesa || !glName || !entry) {
90         return false;
91     }
92 
93     GetProcAddressType getProcAddr =
94         (GetProcAddressType)dlsym(dlEglHandle_, "eglGetProcAddress");
95     if (getProcAddr == nullptr) {
96         WLOGE("can't find eglGetProcAddress() in EGL_mesa driver library.");
97         return false;
98     }
99 
100     FunctionPointerType *current = entry;
101     char const * const *api = glName;
102     while (*api) {
103         char const *name = *api;
104         FunctionPointerType func = getProcAddr(name);
105         if (func == nullptr) {
106             WLOGD("couldn't find the entry-point: %{public}s.", name);
107         }
108         *current++ = func;
109         api++;
110     }
111 
112     return true;
113 }
114 #endif
115 
LoadGl(const char * libName,char const * const * glName,FunctionPointerType * entry)116 void *EglWrapperLoader::LoadGl(const char *libName, char const * const *glName, FunctionPointerType *entry)
117 {
118     WLOGD("");
119     void *dlHandle = nullptr;
120     dlHandle = dlopen(libName, RTLD_NOW | RTLD_LOCAL);
121     if (dlHandle == nullptr) {
122         WLOGE("dlopen failed. error: %{public}s.", dlerror());
123         return nullptr;
124     }
125 
126     GetProcAddressType getProcAddr =
127         (GetProcAddressType)dlsym(dlEglHandle_, "eglGetProcAddress");
128     if (getProcAddr == nullptr) {
129         WLOGE("can't find eglGetProcAddress() in EGL driver library.");
130         dlclose(dlHandle);
131         return nullptr;
132     }
133 
134     FunctionPointerType *current = entry;
135     char const * const *api = glName;
136     while (*api) {
137         char const *name = *api;
138         FunctionPointerType func = (FunctionPointerType)dlsym(dlHandle, name);
139         if (func == nullptr) {
140             WLOGD("try to getProcAddr %{public}s.", name);
141             func = getProcAddr(name);
142             if (func == nullptr) {
143                 WLOGD("couldn't find the entry-point: %{public}s.", name);
144             }
145         }
146         *current++ = func;
147         api++;
148     }
149 
150     return dlHandle;
151 }
152 
LoadVendorDriver(EglWrapperDispatchTable * table)153 bool EglWrapperLoader::LoadVendorDriver(EglWrapperDispatchTable *table)
154 {
155 #ifdef OPENGL_WRAPPER_ENABLE_GL4
156     if (gWrapperHook.useMesa) {
157         WLOGD("EGL (mesa)");
158         if (!LoadEgl(LIB_EGL_MESA_NAME, &table->egl)) {
159             WLOGE("LoadEgl_mesa Failed.");
160             return false;
161         }
162 
163         WLOGD("GL/GLES (mesa)");
164         if (!LoadGlFromMesa(gGlApiNames1, (FunctionPointerType *)&table->gl.table1) ||
165             !LoadGlFromMesa(gGlApiNames2, (FunctionPointerType *)&table->gl.table2) ||
166             !LoadGlFromMesa(gGlApiNames3, (FunctionPointerType *)&table->gl.table3) ||
167             !LoadGlFromMesa(gGlApiNames4, (FunctionPointerType *)&table->gl.table4)) {
168             return false;
169         }
170         return true;
171     }
172 #endif
173 
174     WLOGD("EGL");
175     if (!LoadEgl(LIB_EGL_NAME, &table->egl)) {
176         WLOGE("LoadEgl Failed.");
177         return false;
178     }
179 
180     WLOGD("GLESV1");
181     dlGlHandle1_ = LoadGl(LIB_GLESV1_NAME, gGlApiNames1, (FunctionPointerType *)&table->gl.table1);
182     if (!dlGlHandle1_) {
183         WLOGE("LoadGl GLESV1 Failed.");
184         return false;
185     }
186 
187     WLOGD("GLESV2");
188     dlGlHandle2_ = LoadGl(LIB_GLESV2_NAME, gGlApiNames2, (FunctionPointerType *)&table->gl.table2);
189     if (!dlGlHandle2_) {
190         WLOGE("LoadGl GLESV2 Failed.");
191         return false;
192     }
193 
194     WLOGD("GLESV3");
195     dlGlHandle3_ = LoadGl(LIB_GLESV3_NAME, gGlApiNames3, (FunctionPointerType *)&table->gl.table3);
196     if (!dlGlHandle3_) {
197         WLOGE("LoadGl GLESV3 Failed.");
198         return false;
199     }
200 
201     return true;
202 }
203 
Load(EglWrapperDispatchTable * table)204 bool EglWrapperLoader::Load(EglWrapperDispatchTable *table)
205 {
206     WLOGD("");
207     if (table == nullptr) {
208         WLOGE("table is nullptr.");
209         return false;
210     }
211 
212     if (table->isLoad) {
213         WLOGI("EglWrapperLoader has been already loaded.");
214         return true;
215     }
216 
217     if (!LoadVendorDriver(table)) {
218         WLOGE("LoadVendorDriver Failed.");
219         return false;
220     }
221 
222     table->isLoad = true;
223     return true;
224 }
225 
Unload(EglWrapperDispatchTable * table)226 bool EglWrapperLoader::Unload(EglWrapperDispatchTable *table)
227 {
228     WLOGD("");
229     if (table == nullptr) {
230         WLOGE("table is nullptr.");
231         return false;
232     }
233     if (!table->isLoad) {
234         WLOGE("EglWrapperLoader is not loaded.");
235         return false;
236     }
237 
238     table->isLoad = false;
239 
240     if (dlEglHandle_) {
241         dlclose(dlEglHandle_);
242         dlEglHandle_ = nullptr;
243     }
244     if (dlGlHandle1_) {
245         dlclose(dlGlHandle1_);
246         dlGlHandle1_ = nullptr;
247     }
248     if (dlGlHandle2_) {
249         dlclose(dlGlHandle2_);
250         dlGlHandle2_ = nullptr;
251     }
252     if (dlGlHandle3_) {
253         dlclose(dlGlHandle3_);
254         dlGlHandle3_ = nullptr;
255     }
256 
257     return true;
258 }
259 
GetProcAddrFromDriver(const char * name)260 void *EglWrapperLoader::GetProcAddrFromDriver(const char *name)
261 {
262     void *func = nullptr;
263 
264     if (dlEglHandle_) {
265         func = dlsym(dlEglHandle_, name);
266     }
267 
268     if (!func && dlGlHandle3_) {
269         func = dlsym(dlGlHandle3_, name);
270     }
271 
272     if (!func && dlGlHandle2_) {
273         func = dlsym(dlGlHandle2_, name);
274     }
275 
276     if (!func && dlGlHandle1_) {
277         func = dlsym(dlGlHandle1_, name);
278     }
279 
280     return func;
281 }
282 } // namespace OHOS
283