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