從系統(tǒng)啟動LOG開始分析驅(qū)動加載流程:
SurfaceFlinger服務(wù)啟動過程會創(chuàng)建RenderEngine碰纬,在異步線程中創(chuàng)建SkiaGLRenderEngine漏益,創(chuàng)建第一步會調(diào)用eglGetDisplay,這時調(diào)用到libEGL.so窃这,EGL會判斷是否初始化,如果未初始化就會去可能的路徑中去加載OpenGLes的驅(qū)動庫浆熔,具體執(zhí)行的方法就是
Loader::attempt_to_load_system_driver
這個方法會執(zhí)行三次肖粮,代表了優(yōu)先級革半。
1.通過讀取環(huán)境屬性去獲得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.再找不到就任意匹配關(guān)鍵字茴厉,只要包含GLES的就可以泽台。
只要找到了庫,就會通過Loader::initialize_api去加載函數(shù)符號矾缓,第一個加載的是eglGetProcAddress怀酷,然后通過"egl_entries.in"中描述的函數(shù)符號字符串列表,通過dlsym方法直接加載嗜闻,如果加載不到即符號隱藏了蜕依,就通過調(diào)用eglGetProcAddress來加載這個函數(shù)符號。
再加載GLESv1_CM的符號琉雳,最后加載GLESv2的符號样眠。
這里加載V1符號時,會將V1中的符號和整個gl符號作對比翠肘,根據(jù)V1在GL符號列表中的占位順序去加載檐束。
任意一個使用OpenGLes的進程都會執(zhí)行加載符號這一過程,所以一般情況下束倍,我們在真正去使用API繪制之前需要將一些warm up的代碼寫在初始化的地方被丧,這樣繪制時就不會有啟動耗時盟戏。
所有加載庫的信息都放在egl_connection_t結(jié)構(gòu)體中,聲明對象是一個全局變量egl_connection_t gEGLImpl甥桂,后面的所有調(diào)用都會從它的platform中實現(xiàn)的函數(shù)進入柿究,最終調(diào)用到egl中的符號,這些符號來自vendor的驅(qū)動庫實現(xiàn)黄选。
Platform的函數(shù)列表加載是在egl_connection_t構(gòu)造時即執(zhí)行的蝇摸。使用platform作為入口的原因是它支持加載多個backend,比如angle办陷,且優(yōu)先使用angle貌夕。