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 "egl_wrapper_layer.h"
16
17 #include <dlfcn.h>
18 #include <cstdlib>
19 #include <parameter.h>
20 #include <parameters.h>
21 #include <sstream>
22
23 #include "../wrapper_log.h"
24
25 namespace OHOS {
26 namespace {
27 #ifndef __aarch64__
28 constexpr const char *DEBUG_LAYERS_LIB_DIR = "/system/lib/";
29 #else
30 constexpr const char *DEBUG_LAYERS_LIB_DIR = "/system/lib64/";
31 #endif
32 constexpr const char *DEBUG_LAYERS_PREFIX = "lib";
33 constexpr const char *DEBUG_LAYERS_SUFFIX = ".so";
34 constexpr const char *DEBUG_LAYERS_DELIMITER = ":";
35 constexpr const char *DEBUG_LAYER_INIT_FUNC = "DebugLayerInitialize";
36 constexpr const char *DEBUG_LAYER_GET_PROC_ADDR_FUNC = "DebugLayerGetProcAddr";
37 constexpr const char *DEBUG_LAYER_NAME = "debug_layer";
38 }
39
40 static std::string strLayers;
41
GetWrapperDebugLayers(const char * key,const char * value,void * context)42 static void GetWrapperDebugLayers(const char *key, const char *value, void *context)
43 {
44 WLOGD("");
45 strLayers = std::string(value);
46 WLOGD("strLayers is %{public}s", strLayers.c_str());
47 }
48
UpdateApiEntries(LayerSetupFunc func,EglWrapperFuncPointer * curr,char const * const * entries)49 static void UpdateApiEntries(LayerSetupFunc func,
50 EglWrapperFuncPointer *curr, char const * const *entries)
51 {
52 WLOGD("");
53 while (*entries) {
54 char const *name = *entries;
55 EglWrapperFuncPointer layerFunc = func(name, *curr);
56 if (layerFunc == nullptr) {
57 WLOGW("LayerSetupFunc(%{public}s) return nullptr.", name);
58 } else if (layerFunc != *curr) {
59 WLOGI("Update api entry for %{public}s", name);
60 *curr = layerFunc;
61 }
62 curr++;
63 entries++;
64 }
65 }
66
SetupFuncMaps(FunctionTable & table,char const * const * entries,EglWrapperFuncPointer * curr)67 static void SetupFuncMaps(FunctionTable &table,
68 char const * const *entries, EglWrapperFuncPointer *curr)
69 {
70 WLOGD("");
71 while (*entries) {
72 const char *name = *entries;
73 if (table.find(name) == table.end()) {
74 table[name] = *curr;
75 } else {
76 WLOGW("duplicate function name(%{public}s)", name);
77 }
78
79 entries++;
80 curr++;
81 }
82 }
83
GetNextLayerProcAddr(void * funcTable,const char * name)84 static const void *GetNextLayerProcAddr(void *funcTable, const char *name)
85 {
86 WLOGD("name = %{public}s", name);
87 auto table = reinterpret_cast<FunctionTable *>(funcTable);
88 if (table->find(name) == table->end()) {
89 WLOGE("not found in function table, name = %{public}s", name);
90 return nullptr;
91 }
92
93 EglWrapperFuncPointer val = (*table)[name];
94 return reinterpret_cast<void *>(val);
95 }
96
SplitEnvString(std::string str,std::vector<std::string> * layers)97 static void SplitEnvString(std::string str, std::vector<std::string> *layers)
98 {
99 WLOGD("");
100 size_t pos1 = 0;
101 size_t pos2 = str.find(DEBUG_LAYERS_DELIMITER);
102 while (pos2 != std::string::npos) {
103 layers->emplace_back(str.substr(pos1, pos2-pos1));
104 pos1 = pos2 + 1;
105 pos2 = str.find(DEBUG_LAYERS_DELIMITER, pos1);
106 }
107
108 if (pos1 != str.length()) {
109 layers->emplace_back(str.substr(pos1));
110 }
111 }
112
GetDebugLayers(void)113 static std::vector<std::string> GetDebugLayers(void)
114 {
115 WLOGD("");
116 std::vector<std::string> layers;
117
118 strLayers = system::GetParameter(DEBUG_LAYER_NAME, "");
119 WLOGD("strLayers is %{public}s", strLayers.c_str());
120 auto ret = WatchParameter(DEBUG_LAYER_NAME, GetWrapperDebugLayers, nullptr);
121 if (ret) {
122 WLOGD("WatchParameter faild.");
123 }
124
125 if (!strLayers.empty()) {
126 SplitEnvString(strLayers, &layers);
127 } else {
128 WLOGD("OPENGL_WRAPPER_DEBUG_LAYERS is not set.");
129 }
130
131 for (auto i : layers) {
132 WLOGD("OPENGL_WRAPPER_DEBUG_LAYERS layer = %{public}s\n", i.c_str());
133 }
134
135 return layers;
136 }
137
GetInstance()138 EglWrapperLayer& EglWrapperLayer::GetInstance()
139 {
140 static EglWrapperLayer layer;
141 return layer;
142 }
143
~EglWrapperLayer()144 EglWrapperLayer::~EglWrapperLayer()
145 {
146 WLOGD("");
147 }
148
Init(EglWrapperDispatchTable * table)149 bool EglWrapperLayer::Init(EglWrapperDispatchTable *table)
150 {
151 WLOGD("");
152 if (initialized_) {
153 WLOGI("EglWrapperLayer is already loaded.");
154 return true;
155 }
156
157 if (table == nullptr) {
158 WLOGE("table is nullptr.");
159 return false;
160 }
161
162 if (!LoadLayers()) {
163 WLOGE("LoadLayers failed.");
164 return false;
165 }
166
167 InitLayers(table);
168
169 initialized_ = true;
170 return true;
171 }
172
LoadLayers()173 bool EglWrapperLayer::LoadLayers()
174 {
175 WLOGD("");
176 std::vector<std::string> layers = GetDebugLayers();
177 for (int32_t i = layers.size() - 1; i >= 0; i--) {
178 std::string layerLib = std::string(DEBUG_LAYERS_PREFIX) + layers[i] + std::string(DEBUG_LAYERS_SUFFIX);
179 std::string layerPath = std::string(DEBUG_LAYERS_LIB_DIR) + layerLib;
180 WLOGD("layerPath = %{public}s", layerPath.c_str());
181
182 void *dlhandle = dlopen(layerPath.c_str(), RTLD_NOW | RTLD_LOCAL);
183 if (dlhandle == nullptr) {
184 WLOGE("dlopen failed. error: %{public}s.", dlerror());
185 return false;
186 }
187
188 LayerInitFunc initFunc = (LayerInitFunc)dlsym(dlhandle, DEBUG_LAYER_INIT_FUNC);
189 if (initFunc == nullptr) {
190 WLOGE("can't find %{public}s in debug layer library.", DEBUG_LAYER_INIT_FUNC);
191 return false;
192 }
193 layerInit_.push_back(initFunc);
194
195 LayerSetupFunc setupFunc = (LayerSetupFunc)dlsym(dlhandle, DEBUG_LAYER_GET_PROC_ADDR_FUNC);
196 if (setupFunc == nullptr) {
197 WLOGE("can't find %{public}s in debug layer library.", DEBUG_LAYER_GET_PROC_ADDR_FUNC);
198 return false;
199 }
200 layerSetup_.push_back(setupFunc);
201 }
202 return true;
203 }
204
InitLayers(EglWrapperDispatchTable * table)205 void EglWrapperLayer::InitLayers(EglWrapperDispatchTable *table)
206 {
207 WLOGD("");
208 if (layerInit_.empty() || layerSetup_.empty()) {
209 return;
210 }
211
212 layerFuncTbl_.resize(layerSetup_.size() + 1);
213 char const * const *entries;
214 EglWrapperFuncPointer *curr;
215
216 entries = gWrapperApiNames;
217 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->wrapper);
218 SetupFuncMaps(layerFuncTbl_[0], entries, curr);
219
220 entries = gGlApiNames3;
221 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
222 SetupFuncMaps(layerFuncTbl_[0], entries, curr);
223
224 for (uint32_t i = 0; i < layerSetup_.size(); i++) {
225 layerInit_[i](reinterpret_cast<void*>(&layerFuncTbl_[i]),
226 reinterpret_cast<GetNextLayerAddr>(GetNextLayerProcAddr));
227
228 entries = gWrapperApiNames;
229 curr = reinterpret_cast<EglWrapperFuncPointer *>(&table->wrapper);
230 UpdateApiEntries(layerSetup_[i], curr, entries);
231 SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
232
233 entries = gGlApiNames3;
234 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
235 UpdateApiEntries(layerSetup_[i], curr, entries);
236 SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
237 }
238 #ifdef EGL_WRAPPER_DEBUG_ENABLE
239 WLOGD("layer function table info: ");
240 int count = 0;
241 for (const auto &table : layerFuncTbl_) {
242 WLOGD("===table%{public}d===: ", count++);
243 for (const auto &item : table) {
244 WLOGD("name: %{public}s : %{public}s", item.first.c_str(),
245 (item.second != nullptr) ? "valid" : "invalid");
246 }
247 }
248 #endif
249 }
250 } // namespace OHOS
251