OpenGL_wrapper
OpenGL_wrapper 整体 OpenGL_wrapper是干什么的 RS或者应用去调用egl或者gl能力都需要走OpenGL_wrapper层。OpenHarmony在启动过程中,EGL初始化时会去load GPU驱动so,获取所有API的symbol。应用调用的API都是走到Wrapper层的诸如libEGL_impl.so声明的接口,然后通过之前获取的symbol调用GPU libGL
OpenGL_wrapper
整体
OpenGL_wrapper是干什么的
RS或者应用去调用egl或者gl能力都需要走OpenGL_wrapper层。OpenHarmony在启动过程中,EGL初始化时会去load GPU驱动so,获取所有API的symbol。应用调用的API都是走到Wrapper层的诸如libEGL_impl.so声明的接口,然后通过之前获取的symbol调用GPU libGLES_mali.so中真正的实现。
相关层解释
1.OpenGL ES
它本身只是一个协议规范,定义了一套可以提供上层应用程序进行调用的 API,它抽象了 GPU 的功能,使应用开发者不必关心底层 GPU 的具体实现。
2.OpenGL ES库
OpenGL ES库就是上面 OpenGL ES 中定义的API的具体实现。由于每个显卡制造厂商的 GPU 硬件结构不同,从而导致各个厂商的OpenGL ES库也各不相同,所以系统中的OpenGL ES库通常是由硬件厂商提供的,通常存放在系统中的 /system/lib64/egl 下面或者 /vendor/lib64/egl 目录下。目前我们用的时mali gpu,因此库叫libGLES_mali.so。
3.OpenGL ES Wrapper库
OpenGL ES Wrapper 库是一个对 OpenGL ES API 进行封装的一个包裹库,它向上为应用程序提供了标准的OpenGL ES API,向下可以和不同厂商实现的 OpenGL ES库进行绑定,将OpenGL ES API和对应的实现函数一一绑定在一起。即libEGL_impl.so、libGLESv1_impl.so、libGLESv2_impl.so、libGLESv3_impl.so。
libEGL_impl.so:EGL API Wrapper库,除了包好EGL API的定义,还包括其它egl相关功能。
libGLESv1_impl.so: OpenGL ES 1.x API的Wrapper库
libGLESv2_impl.so: OpenGL ES 2.0 API的Wrapper库
libGLESv3_impl.so: OpenGL ES 3.0 API的Wrapper库
调用流程
1.应用调用API接口(很多地方都调用,下面举例随机一个)
static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void* native_display, const EGLint* attrib_list)
{
static GetPlatformDisplayExt eglGetPlatformDisplayExt = NULL;
...
return eglGetDisplay(static_cast<EGLNativeDisplayType>(native_display));
}
2. API通过 egl_hook_entries.in文件
HOOK_API_ENTRY(EGLDisplay, eglGetDisplay, EGLNativeDisplayType type)
CALL_HOOK_API_RET(eglGetDisplay, type)
3. hook钩子函数跳转到egl.cpp中 CALL_HOOK_API_RET
#undef CALL_HOOK_API
#define CALL_HOOK_API(api, ...) \
do { \
if (OHOS::EglCoreInit() && OHOS::CheckEglWrapperApi(#api)) { \
OHOS::gWrapperHook.wrapper.api(__VA_ARGS__); \
} else { \
WLOGE("%{public}s is invalid.", #api); \
} \
} while (0); \
}
#undef CALL_HOOK_API_RET
#define CALL_HOOK_API_RET(api, ...) \
do { \
if (OHOS::EglCoreInit() && OHOS::CheckEglWrapperApi(#api)) { \
return OHOS::gWrapperHook.wrapper.api(__VA_ARGS__); \
} else { \
WLOGE("%{public}s is invalid.", #api); \
return 0; \
} \
} while (0); \
}
4. 如果是第一次通过wrapper调用API,则需初始化 EglCoreInit()
bool EglCoreInit()
{
std::lock_guard<std::mutex> lock(gInitMutex);
if (gWrapperHook.isLoad) {
return true;
}
if (!preInitializer.InitStat()) {
WLOGE("preInit Error.");
return false;
}
WrapperHookTableInit();
EglWrapperLoader& loader(EglWrapperLoader::GetInstance());
if (!loader.Load(&gWrapperHook)) {
WLOGE("EglWrapperLoader Load Failed.");
return false;
}
EglWrapperLayer& layer(EglWrapperLayer::GetInstance());
if (!layer.Init(&gWrapperHook)) {
WLOGE("EglWrapperLayer Init Failed.");
}
#if USE_IGRAPHICS_EXTENDS_HOOKS
if (!layer.GetIGraphicsLogicStatus()) {
return true;
}
EglWrapperHook& hookLayer(EglWrapperHook::GetInstance());
if (!hookLayer.Hook(&gWrapperHook)) {
WLOGE("EglWrapperHookLayer init Failed!");
} else {
WLOGI("EglWrapperHookLayer init Success!");
}
#endif
return true;
}
5.load对应的GPU驱动so,通过in文件获取所有的API
constexpr const char *LIB_EGL_NAME = "libEGL_impl.so";
constexpr const char *LIB_GLESV1_NAME = "libGLESv1_impl.so";
constexpr const char *LIB_GLESV2_NAME = "libGLESv2_impl.so";
constexpr const char *LIB_GLESV3_NAME = "libGLESv3_impl.so";
bool EglWrapperLoader::LoadVendorDriver(EglWrapperDispatchTable *table)
{
WLOGD("EGL");
if (!LoadEgl(LIB_EGL_NAME, &table->egl)) {
WLOGE("LoadEgl Failed.");
return false;
}
WLOGD("GLESV1");
dlGlHandle1_ = LoadGl(LIB_GLESV1_NAME, gGlApiNames1, (FunctionPointerType *)&table->gl.table1);
if (!dlEglHandle_) {
WLOGE("LoadGl GLESV1 Failed.");
return false;
}
WLOGD("GLESV2");
dlGlHandle2_ = LoadGl(LIB_GLESV2_NAME, gGlApiNames2, (FunctionPointerType *)&table->gl.table2);
if (!dlGlHandle2_) {
WLOGE("LoadGl GLESV2 Failed.");
return false;
}
WLOGD("GLESV3");
dlGlHandle3_ = LoadGl(LIB_GLESV3_NAME, gGlApiNames3, (FunctionPointerType *)&table->gl.table3);
if (!dlGlHandle3_) {
WLOGE("LoadGl GLESV3 Failed.");
return false;
}
return true;
}
6.初始化LayerLoader对象
bool EglWrapperLayer::Init(EglWrapperDispatchTable *table)
{
WLOGD("");
if (initialized_) {
WLOGI("EglWrapperLayer is already loaded.");
return true;
}
if (table == nullptr) {
WLOGE("table is nullptr.");
return false;
}
if (!LoadLayers()) {
WLOGE("LoadLayers failed.");
return false;
}
InitLayers(table);
initialized_ = true;
return true;
}
7. 设置 wrapper 以及 OpenGL 的功能表。更新各个API条目的信息,并将这些条目与适当的函数指针进行关联。该过程确保在使用 EGL 和 OpenGL 时能够正确地调用对应版本的方法。
void EglWrapperLayer::SetupLayerFuncTbl(EglWrapperDispatchTable *table)
{
// 调整 layerFuncTbl_ 的大小,增加一个元素以容纳所有层的函数表
layerFuncTbl_.resize(layerSetup_.size() + 1);
// 声明指向 API 名称数组的指针和当前函数指针的位置
char const * const *entries;
EglWrapperFuncPointer *curr;
// 设置 wrapper API 的条目
entries = gWrapperApiNames; // 获取 wrapper API 名称数组
curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->wrapper); // 获取 table 中 wrapper 的函数指针位置
SetupFuncMaps(layerFuncTbl_[0], entries, curr); // 将函数映射到第一个层
// 设置 OpenGL 2.x API 的条目
entries = gGlApiNames2; // 获取 OpenGL 2.x API 名称数组
curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table2); // 获取 table 中 gl.table2 的函数指针位置
SetupFuncMaps(layerFuncTbl_[0], entries, curr); // 将函数映射到第一个层
// 设置 OpenGL 3.x API 的条目
entries = gGlApiNames3; // 获取 OpenGL 3.x API 名称数组
curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3); // 获取 table 中 gl.table3 的函数指针位置
SetupFuncMaps(layerFuncTbl_[0], entries, curr); // 将函数映射到第一个层
// 遍历所有设置的层并初始化相应的功能表
for (uint32_t i = 0; i < layerSetup_.size(); i++) {
layerInit_[i](reinterpret_cast<void*>(&layerFuncTbl_[i],
reinterpret_cast<GetNextLayerAddr>(GetNextLayerProcAddr));
// 初始化当前层的功能表,并获取下一个层的地址
entries = gWrapperApiNames;
curr = reinterpret_cast<EglWrapperFuncPointer *>(&table->wrapper);
UpdateApiEntries(layerSetup_[i], curr, entries);
SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
entries = gGlApiNames2;
curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table2);
UpdateApiEntries(layerSetup_[i], curr, entries);
SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
entries = gGlApiNames3;
curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
UpdateApiEntries(layerSetup_[i], curr, entries);
SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
// 更新和设置每个图形库版本对应的 API 条目和映射关系。
}
}
8. 检查调用的API是否在WrapperMap中
bool CheckEglWrapperApi(const std::string &name)
{
if (gEglWrapperMap.find(name) != gEglWrapperMap.end()) {
return true;
}
return false;
}
9. 若在其中,则调用WrapperMap中API能力
return OHOS::gWrapperHook.wrapper.api(__VA_ARGS__);
更多推荐
所有评论(0)