在Android 5.0之前,Android應用程序的主線程同時也是一個Open GL線程。但是從Android 5.0之后,Android應用程序的Open GL線程就獨立出來了,稱為Render Thread.
Android系統的UI從繪制到顯示到屏幕是分兩步進行的:第一步是在Android應用程序進程這一側進行的;第二步是在SurfaceFlinger進程這一側進行的。前一步將UI繪制到一個圖形緩沖區中,並且將該圖形緩沖區交給后一步進行合成以及顯示在屏幕中。其中,后一步的UI合成一直都是以硬件加速方式完成的。
注:在3.0前,Android應用程序UI繪制不支持硬件加速。不過從4.0開始,Android系統一直以“run fast, smooth, and responsively”為目標對UI進行優化。 注意,上面我們說Android系統不支持硬件加速的UI 繪制,針對的是Android應用程序2D UI繪制; 對於3D UI,例如游戲,一直是支持硬件加速渲染的。
在支持Android應用程序UI硬件加速渲染之前,Android應用程序UI的繪制是以軟件方式進行的,為了更好地理解Android應用程序UI硬件加速渲染技術,我們先回顧在Android應用程序窗口(Activity)實現框架簡要介紹和學習計划這個系列的文章提及的軟件渲染技術,如圖1所示:
圖1 Android應用程序UI軟件渲染過程
在Android應用程序進程這一側,每一個窗口都關聯有一個Surface。每當窗口需要繪制UI時,就會調用其關聯的Surface的成員函數lock獲得一個Canvas,其本質上是向SurfaceFlinger服務Dequeue一個Graphic Buffer。Canvas封裝了由Skia提供的2D UI繪制接口,並且都是在前面獲得的Graphic Buffer上面進行繪制的。繪制完成之后,Android應用程序進程再調用前面獲得的Canvas的成員函數unlockAndPost請求顯示在屏幕中,其本質上是向SurfaceFlinger服務Queue一個Graphic Buffer,以便SurfaceFlinger服務可以對Graphic Buffer的內容進行合成,以及顯示到屏幕上去。
接下來我們再來看Android應用程序UI硬件加速渲染技術,如圖2所示:
圖2 Android應用程序UI硬件加速渲染過程
從圖2可以看到,硬件加速渲染和軟件渲染一樣,在開始渲染之前,都是要先向SurfaceFlinger服務Dequeue一個Graphic Buffer。不過對硬件加速渲染來說,這個Graphic Buffer會被封裝成一個ANativeWindow,並且傳遞給Open GL進行硬件加速渲染環境初始化。在Android系統中,ANativeWindow和Surface可以是認為等價的,只不過是ANativeWindow常用於Native層中,而Surface常用於Java層中。另外,我們還可以將ANativeWindow和Surface看作是像Skia和Open GL這樣圖形渲染庫與操作系統底層的圖形系統建立連接的一個橋梁。
Open GL獲得了一個ANativeWindow,並且進行了硬件加速渲染環境初始化工作之后,Android應用程序就可以調用Open GL提供的API進行UI繪制了,繪制出來內容就保存在前面獲得的Graphic Buffer中。當繪制完畢,Android應用程序再調用libegl庫提供的一個eglSwapBuffer接口請求將繪制好的UI顯示到屏幕中,其本質上與軟件渲染過程是一樣的,都是向SurfaceFlinger服務Queue一個Graphic Buffer,以便SurfaceFlinger服務可以對Graphic Buffer的內容進行合成,以及顯示到屏幕上去。
這里我們首先要明確什么是硬件加速渲染,其實就是通過GPU來進行渲染。GPU作為一個硬件,用戶空間是不可以直接使用的,它是由GPU廠商按照Open GL規范實現的驅動間接進行使用的。也就是說,如果一個設備支持GPU硬件加速渲染,那么當Android應用程序調用Open GL接口來繪制UI時,Android應用程序的UI就是通過硬件加速技術進行渲染的。因此,在接下來的描述中,我們提及到GPU、硬件加速和Open GL時,它們表達的意思都是等價的。
(一) Android應用程序UI硬件加速渲染技術簡要介紹和學習計划
(二)Android應用程序UI硬件加速渲染環境初始化過程分析