一、OpenGL ES與EGL
Android的GUI系統(tǒng)是基于OpenGL/EGL來實現(xiàn)的细睡。
- 由于OpenGL是通用函數庫颈将,在不同平臺系統(tǒng)上需要被“本土化”——把它與具體平臺的窗口系統(tǒng)建立起關聯(lián)挤茄,F(xiàn)ramebufferNativeWindow是負責OpenGL ES在Android平臺上本地化的中介之一逞刷。為OpenGL ES配置本地窗口的是EGL,EGL介于本地窗口系統(tǒng)和Rendering API(即OPenGL ES)之間的一層接口惊暴。
- 與OpenGL相關的模塊可分為:
(1)配置類饼丘。 幫助OpenGL ES完成配置的,包括EGL辽话、DisplayHardware都歸為此類肄鸽。
(2)依賴類。 OpenGL ES正常運行所依賴的“本地化”的東西油啤,如FramebufferNativeWindow典徘。
(3)使用類。 使用者也可能是配置者益咬,如DisplayDevice既扮演了構建OpenGL ES環(huán)境的角色逮诲,同時也是它的用戶。 - OpenGL相關知識可查看Android中的OpenGL ES使用基礎
二幽告、 硬件接口 - HAL
HAL是很多子系統(tǒng)(顯示/音頻系統(tǒng)等)與Linux Kernel驅動之間通信的統(tǒng)一接口梅鹦。各子系統(tǒng)通常不會直接使用內核驅動。
HAL解決的問題:
(1)硬件接口抽象冗锁。從眾多硬件設備中提取出共同屬性并付諸軟件實現(xiàn)齐唆。
(2)接口穩(wěn)定性。 HAL層的接口不允許頻繁更動冻河。
(3)靈活的使用方法蝶念。供硬件開發(fā)商及上層使用者定制他們的需求。
三芋绸、終端顯示設備 - Gralloc與Framebuffer
Linux內核提供了統(tǒng)一的framebuffer顯示驅動。Framebuffer是內核系統(tǒng)提供的圖形硬件的抽象描述担敌,稱為buffer是因為它也占用了系統(tǒng)存儲空間的一部分摔敛,是一塊包含屏幕顯示信息的緩沖區(qū)。
Framebuffer借助于Linux文件系統(tǒng)向上層應用提供了統(tǒng)一而高效的操作接口全封,讓用戶空間運行的程序比較容易地適配多種顯示設備马昙。
Android系統(tǒng)中桃犬,framebuffer提供的設備節(jié)點為/dev/graphics/fb或者/dev/fb,其中fb0表示第一個主顯示屏幕行楞,必須存在攒暇,當前系統(tǒng)實現(xiàn)中只用到了一個顯示屏。
顯示系統(tǒng)使用HAL層間接引用底層架構子房,從而操作幀緩沖區(qū)形用。而完成這一中介任務的就是Gralloc.
下圖為Gralloc的模塊簡圖,描述了gpu0和fb0的主要API.
Gralloc對應的模塊是由FramebufferNativeWindow在構造函數加載的证杭,Gralloc包括fb和gralloc兩個設備田度,前者負責打開內核中的Framebuffer、初始化配置,并提供了post解愤、setSwapInterval等操作接口镇饺。后者則管理幀緩沖區(qū)的分配和釋放。
四送讲、本地窗口(Native Window)
Native Window為OpenGL與本地窗口系統(tǒng)之間搭建了橋梁奸笤。整個GGUI系統(tǒng)至少需要兩種本地窗口:
(1)面向管理者(SurfaceFlinger)
SurfaceFlinger是系統(tǒng)中所有UI界面的管理者,需要直接或間接的持有“本地窗口”哼鬓,此本地窗口是FramebufferNativeWindow监右。
(2)面向應用程序
這類本地窗口是Surface。
正常情況按照SDK向導生成APK應用程序魄宏,是采用Skia等第三方圖形庫秸侣,而對于希望使用OpenGL ES來完成復雜界面渲染的應用開發(fā)者來說,Android也提供封裝的GLSurfaceView(或其他方式)來實現(xiàn)圖形顯示宠互。
- FramebufferNativeWindow
EGL需要通過本地窗口來為OpenGL/OpenGL ES創(chuàng)建環(huán)境味榛。由于OpenGL/ES對多平臺支持,考慮到兼容性和移植性予跌。不同平臺的本地窗口EGLNativeWindowType數據類型不同搏色。
Android平臺的數據類型是ANativeWindow,像是一份“協(xié)議”券册,規(guī)定了一個本地窗口的形態(tài)和功能频轿。ANativeWindow是FramebufferNativeWindow的父類。
Android中烁焙,由于多緩沖技術航邢,EGLNativeWindowType所管理的緩沖區(qū)最少2個,最大3個骄蝇。
FramebufferNativeWindow初始化需要Golloc支持膳殷,步驟如下:
- 加載GRALLOC_HARDWARE_MODULE_ID模塊,參見上節(jié)九火。
- 分別打開fb和gralloc設備赚窃,打開后的設備由全局變量fbDev和grDev管理册招。
- 根據設備的屬性來給FramebufferNativeWindow賦初值。
- 根據FramebufferNativeWindow的實現(xiàn)來填充ANativeWindow中的“協(xié)議”
- 其他一些必要的初始化
- 應用程序的本地窗口 - Surface
Surface也繼承了ANativeWindow
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
Surface是面向Android系統(tǒng)中所有UI應用程序的勒极,即它承擔著應用進程中的UI顯示需求是掰。
需要面向上層實現(xiàn)(主要是Java層)提供繪制圖像的畫板。SurfaceFlinger需要收集系統(tǒng)中所有應用程序繪制的圖像數據辱匿,然后集中顯示到物理屏幕上键痛。Surface需要扮演相應角色,本質上還是由SURfaceFlinger服務統(tǒng)一管理的掀鹅,涉及到很多跨進程的通信細節(jié)散休。
- Surface的創(chuàng)建
Surface將通過mGraphicBufferProducer來獲取buffer,這些緩沖區(qū)會被記錄在mSlots中數據中。mGraphicBufferProducer這一核心成員的初始化流程如下:
ViewRootImpl持有一個Java層的Surface對象(mSurface)乐尊。
ViewRootImpl向WindowManagerService發(fā)起relayout請求戚丸,此時mSurface被賦予真正的有效值,將輾轉生成的SurfaceControl通過Surface.copyFrom()函數復制到mSurface中扔嵌。
由此限府,Surface由SurfaceControl管理,SurfaceControl由SurfaceComposerClient創(chuàng)建痢缎。SurfaceComposerClient獲得的匿名Binder是ISurfaceComposer胁勺,其服務端實現(xiàn)是SurfaceFlinger。而Surface依賴的IGraphicBufferProducer對象在Service端的實現(xiàn)是BufferQueue独旷。
class SurfaceFlinger :
public BinderService<SurfaceFlinger>, //在ServiceManager中注冊為SurfaceFlinger
public BnSurfaceComposer,//實現(xiàn)的接口卻叫ISurfaceComposer
- SurfaceFlinger服務框架
Buffer署穗,Consumer,Producer是“生產者-消費者”模型中的3個參與對象嵌洼,如何協(xié)調好它們的工作是應用程序能否正常顯示UI的關鍵案疲。
Buffer是BufferQueue,Producer是應用程序麻养,Consumer是SurfaceFlinger褐啡。
五、BufferQueue詳解
為應用程序服務的本地窗口Surface,其依賴的IGraphicBufferProducer對象在Server端的實現(xiàn)是BufferQueue.
一塊Buffer在處理過程中經歷的生命周期依次是FREE-> DEQUEUED->QUEUED->ACQUIRED->FREE.
BufferQueue中的mSlots數組用于管理期內的緩沖區(qū),最大容器是32.數據緩沖區(qū)的空間是動態(tài)分配的.
應用程序與SurfaceFlinger都是使用OpenGL ES來完成UI顯示的.
Layer類在SurfaceFlinger中表示“層”,通俗地講就是代表了一個“畫面”,最終物理屏幕上的顯示結果就是通過對系統(tǒng)中同時存在的所有“畫面”進行處理而得到的.
注:主要內容摘錄自書籍 深入理解Android內核設計思想鳖昌,林學森 著