Android 顯示系統

whatnamecaniuse發表於2014-11-05


http://blog.csdn.net/sfrysh/article/details/7367786


Android display system introduce(Qualcomm 8x60 platform)(二、SW架構--1)
2010-12-31 11:17

一、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已繪製完畢,可以更新到視訊記憶體中。

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和Gralloc後面會有單獨的章節來介紹。


相關文章