Android-2.2 display系統介紹-SW架構

Android-2.2display系統介紹-SW架構

一、Overview

上圖的原型取自高通的文檔,由於原圖無法描述現有的架構,我在原圖的基礎了做了些修改,主要是增加了overlay部分,另外其他部分根據現有的軟件也做了些許改動。下面先對上圖做個大概的介紹,後面會針對重點部分做詳細的分析。

最上面一層爲應用程序,根據數據類型以及應用的不同可以分爲幾種。

第一種是最普通的應用,如UI界面的顯示,這部分通常數據類型爲RGB格式,數據無須再經過特殊的處理。該應用可以說遍佈各個應用程序,幾乎是實時存在的。

第二種是針對大塊YUV數據的應用,如camera的preview、視頻的播放等。該應用只針對特定的應用程序,開啓時通過overlay直接把大塊的YUV數據送到kernel顯示。

第三種其實和第一種類似,只不過由於應用的需求在顯示之前需要對數據進行2D、3D的處理(使用OpenGL、OpenVG、SVG、SKIA),處理之後的流程和普通的顯示就沒什麼差別了。一般在Game、地圖、Flash等應用中會用到。

應用之下是framework,其中最核心的就是surfaceflinger了,它爲所有的應用程序的顯示提供服務。由於overlay的接口掛在surfaceflinger裏面(雖然2者在功能上不相干),所有使用overlay的AP需要通過surfaceflinger纔可以訪問overlay;另外,由於surfaceflinger需要使用OpenGL來compose surface,這也就是爲什麼surfacelfinger會調用EGL wrapper了,EGL wrapper是對Graphics HAL的封裝,除了surfaceflinger會調用它來compose surface外,上層的2D、3D應用也會調用它來進行圖形處理。

再下一層就是HAL了。

首先一個是overlay模塊,對上提供control channel和data channel;對下則通過系統調用到kernel中的MDP driver。

再一個是Gralloc模塊,注意它是和overlay並列的,它包含2個部分,一部分是爲上層提供pmem的接口,另一部分則是對framebuffer進行刷新,這裏的framebuffer其實就是UI的數據。由此可見上層有2個通道把顯示數據送到kernel中,framebuffer是傳統的方式,overlay是android(éclair以後)後增加的。

紅色及右邊部分是OpenGL的HAL,其中紅色部分代表HW solution,高通提供的,這部分是沒有源碼的;右邊的software graphics library是SW solution,android自身的。HW和SW solution可以同時存在也可以只有一個,後面會講解。

再往下就是kernel中的driver了,最主要的就是fb設備驅動以及MDP4 overlay的驅動,從硬件上看2者是並列的,framebuffer最終也是通過overlay方式送入MDP的。PMEM和KGSL分別對應kernel中pmem的driver(/dev/pmem)和Adreno220的driver。

二、Surfaceflinger詳解

1.overview

Surfaceflinger可以說是Android顯示系統中的核心,在android當中它是一個service,提供系統範圍內的surface composer 功能,它能夠將各種應用程序的2D 、3D surface 進行組合,合併最終得到的一個main surface數據會送入顯存。簡單的說,surfaceflinger就像是畫布,它不關心畫上去的內容,只是一味的執行合成功能,當然要根據畫的位置、大小以及效果等參數。這很像Photoshop中的各個Layer,你可以在不同的layer畫任意的內容,每個layer可以設置位置、大小、效果參數等,最終通過merge合成一個layer。

從應用的角度看,每個應用程序可能對應一個或多個圖形界面,每個界面可以看作是一個surface。首先每個surface有它的位置、大小、內容等元素,這些元素是可以隨便變化的;另外不同的surface的位置會有重疊,會涉及到透明度等效果處理問題,這些都是通過surfaceflinger來完成的。當然了,surfaceflinger擔任是一個管理的職責,對於效果處理及合成它是通過OpenGL來做的,但前提是surfaceflinger需要把相關參數計算好,如重疊的位置等。

2.Surfaceflinger在系統中的位置

Android中的圖形系統採用Client/Server架構。服務端負責Surface的合成等處理工作,客戶端提供接口給上層操作自己的Surface,並向服務端發送消息完成實際處理工作。服務端 (即SurfaceFlinger)主要由c++代碼編寫而成。客戶端端代碼分爲兩部分,一部分是由Java提供的供應用使用的api,另一部分則是由c++寫成的底層實現。如下圖所示:

除去最上層的應用不算,surface最上層的接口就是java surface了,文件路徑如下:

frameworks/base/core/java/android/view/Surface.java,該文件中的接口會被應用間接調用。

我們從JNI開始看,surface的JNI文件路徑如下:

frameworks/base/core/jni/android_view_Surface.cpp,裏面的接口大概分爲2類,一類是負責管理ibinder通信的;另一類纔是和顯示控制相關的,第二類接口會直接調用C實現函數。

C實現的文件路徑如下:

frameworks/base/libs/ui/Surface.cpp

我們來看看JNI中一些重要的接口:

SurfaceSession_init:本接口只會被調用一次,負責創建surfacecomposerclient,主要爲進程間通信做準備。對應的銷燬函數有SurfaceSession_destroy和SurfaceSession_kill。

Surface_init:負責創建surface,最終會調用到surfaceflinger中的createSurface,對應的銷燬函數有Surface_destroy和Surface_release。

Surface_lockCanvas:當對一個surface進行繪圖之前要調用的,將該surface鎖定,並且得到surface的back buffer,應用可以繪圖。

Surface_unlockCanvasAndPost:當上層繪圖完畢後,通過該函數通知底層back buffer已繪製完畢,可以更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Surface_setLayer\
 
Surface_setPosition\
 
Surface_setSize\
 
Surface_hide\
 
Surface_show\
 
Surface_setOrientation\
 
Surface_freeze\
 
Surface_unfreeze
 
Surface_setFlags\
 
Surface_setAlpha\
 
Surface_setMatrix:設置surface的一些屬性,如大小、位置、方位、截取範圍,Z-order等。其最終改變的都是surface的結構體屬性,如下:
 
            uint32_t        what;//哪一項屬性改變
 
            int32_t         x;//顯示位置
 
            int32_t         y; //顯示位置
 
            uint32_t        z; //layer順序
 
            uint32_t        w;//寬度
 
            uint32_t        h;//高度
 
            float           alpha;//透明度
 
            uint32_t        tint;//色彩,未使用
 
            uint8_t         flags;// 標誌
 
            uint8_t         mask;//屏蔽命令
 
            uint8_t         reserved;
 
            matrix22_t      matrix;//截取範圍
 
            Region          transparentRegion;//透明度設置

3.JNI與Surfaceflinger的連接通訊

由於JNI及C函數實現與surfaceflinger不在同一個進程(一個在應用端-客戶端,另一個在服務端),android中通過IPC(Binder)方式實現進程間通信,下圖來源於網上,不過我修改了裏面的一些錯誤,它演示了JNI和surfaceflinger建立連接以及創建surface的流程。

JNI和C函數實現我們看作是一個部分

這裏看到一個比較重要的部分——SurfaceComposerClient,它是surfacelinger的客戶端,通過它上層纔可以和surfaceflinger使用Binder聯繫到一起,IsurfaceComposer和IsurfaceFlingerClient都是用來實現Binder通信的。具體流程講解 如下:

應用程序通過JNI接口SurfaceSession_init創建SurfaceComposerClient。通過SurfaceComposerClient函數中調用getComposerService獲得IsurfaceComposer的IBinder對象,然後通過這個對象的createConnection又獲得IsurfaceFlingerClient的IBinder,通過這個IBinder,JNI就可以調用Surfaceflinger中的接口了,如createSurface。由於採用Binder方式,代碼部分稍微複雜一些,需要多看幾遍才能把流程理清楚。

4.Surfaceflinger與libui、OpenGL、顯示設備的連接

這裏不得不提到android對媒體框架中一個很重要的部分,那就是libui,它是一個框架庫提供對底層操作的接口,比如會調用Gralloc、Overlay等HAL層接口。其他的庫類繼承的方式來調用libui,surfaceflinger就是這樣和顯示設備連接的(包括寫顯存和對pmem的使用)

Surfaceflinger使用OpenGL來合成surface,所以surfaceflinger會直接調用到OpenGL的接口。

它們的架構如下:

這部分的流程比較複雜,主要是各個類的繼承繞的比較多,我也是看了很多遍代碼以及參考了些資料才理出來,下面來詳細解釋下這個圖:

Surfaceflinger在設計時考慮到支持多個屏幕,但目前的版本只支持一個,在surfaceflinger當中一個顯示設備對應一個圖中的DisplayHardware,surfaceflinger在初始化時會新建Displayhardware(請參考surfaceflinger.cpp中的readyToRun函數),它完成的主要任務一個是建立FramebufferNativeWindow,確定數據輸出設備接口(請參考FramebufferNativeWindow.cpp),再一個就是初始化OpenGL,並創建main surface,後續surfaceflinger中所有的layer最終都將被畫到這個main surface上(請參考displayhardware.cpp的init函數)。這樣main surface、OpenGL和libui中的FramebufferNativeWindow接口就綁定在一起。

由於libEGL負責所有layer的最終合成,所以最後數據送往HAL一定要libEGL來觸發,對應的函數流程是:

postFrameBuffer(surfaceflinger)->Flip(displayhardware)-> eglSwapBuffers(OpenGL)-> queueBuffer(libui)->fbpost(gralloc)

另外圖中的GraphicBuffer是libui中提供的對pmem的操作接口,它會直接調用gralloc模塊。關於OpenGL和Grall

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章