从系统启动LOG开始分析驱动加载流程

img

SurfaceFlinger服务启动过程会创建RenderEngine,在异步线程中创建SkiaGLRenderEngine,创建第一步会调用eglGetDisplay,这时调用到libEGL.so,EGL会判断是否初始化,如果未初始化就会去可能的路径中去加载OpenGLes的驱动库,具体执行的方法就是

Loader::attempt_to_load_system_driver

这个方法会执行三次,代表了优先级。

1.通过读取环境属性去获得libGLES的后缀名,组装后在system/lib或者vendor/lib/egl目录下查找。

static const char*HAL_SUBNAME_KEY_PROPERTIES[3]= {

       PERSIST_DRIVER_SUFFIX_PROPERTY,

       RO_DRIVER_SUFFIX_PROPERTY,

       RO_BOARD_PLATFORM_PROPERTY,

};

2.如果加载不到,则尝试不加后缀名的库,例如

libGLES.so,libEGL.so, libGLESv1_CM.so,libGLESv2.so

3.再找不到就任意匹配关键字,只要包含GLES的就可以。

只要找到了库,就会通过Loader::initialize_api去加载函数符号,第一个加载的是eglGetProcAddress,然后通过"egl_entries.in"中描述的函数符号字符串列表,通过dlsym方法直接加载,如果加载不到即符号隐藏了,就通过调用eglGetProcAddress来加载这个函数符号。

再加载GLESv1_CM的符号,最后加载GLESv2的符号。

这里加载V1符号时,会将V1中的符号和整个gl符号作对比,根据V1在GL符号列表中的占位顺序去加载。

任意一个使用OpenGLes的进程都会执行加载符号这一过程,所以一般情况下,我们在真正去使用API绘制之前需要将一些warm up的代码写在初始化的地方,这样绘制时就不会有启动耗时。

所有加载库的信息都放在egl_connection_t结构体中,声明对象是一个全局变量egl_connection_t gEGLImpl,后面的所有调用都会从它的platform中实现的函数进入,最终调用到egl中的符号,这些符号来自vendor的驱动库实现。

Platform的函数列表加载是在egl_connection_t构造时即执行的。使用platform作为入口的原因是它支持加载多个backend,比如angle,且优先使用angle。

问题与解决方法

在我们进行GPU测试的时候,一直会出现一个异常打印,阻塞了测试任务而且因为该打印的原因,影响了系统启动和APP启动的性能,大概影响了几百毫秒。
原因分析:
是由于OpenHarmony系统在初始化加载EGL的时候没有去校验EGL_VERSION,后续会出现do_dlsym failed: symbol not found. so=/vendor/lib/chipsetsdk/libEGL_impl.so的打印,
不影响整体正常功能的使用,但是会消耗部分性能。
解决方案:
将日志等级从 ERROR 提高到了 WARING

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐