1. 程式人生 > >Android 顯示系統

Android 顯示系統

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

一、Overview

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

最上面一層為應用程式,根據資料型別以及應用的不同可以分為幾種。

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

第二種是針對大塊YUV資料的應用,如camerapreview、視訊的播放等。該應用只針對特定的應用程式,開啟時通過overlay直接把大塊的

YUV資料送到kernel顯示。

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

應用之下是framework,其中最核心的就是surfaceflinger了,它為所有的應用程式的顯示提供服務。由於overlay的介面掛在surfaceflinger裡面(雖然2者在功能上不相干),所有使用overlayAP需要通過surfaceflinger才可以訪問overlay;另外,由於surfaceflinger需要使用

OpenGLcompose surface,這也就是為什麼surfacelfinger會呼叫EGL wrapper了,EGL wrapper是對Graphics HAL的封裝,除了surfaceflinger會呼叫它來compose surface外,上層的2D3D應用也會呼叫它來進行圖形處理。

再下一層就是HAL了。

首先一個是overlay模組,對上提供control channeldata channel;對下則通過系統呼叫到kernel中的MDP driver

再一個是Gralloc模組,注意它是和overlay並列的,它包含2個部分,一部分是為上層提供pmem的介面,另一部分則是對

framebuffer進行重新整理,這裡的framebuffer其實就是UI的資料。由此可見上層有2個通道把顯示資料送到kernel中,framebuffer是傳統的方式,overlayandroidéclair以後)後增加的。

紅色及右邊部分是OpenGLHAL,其中紅色部分代表HW solution,高通提供的,這部分是沒有原始碼的;右邊的software graphics librarySW solutionandroid自身的。HWSW solution可以同時存在也可以只有一個,後面會講解。

再往下就是kernel中的driver了,最主要的就是fb裝置驅動以及MDP4 overlay的驅動,從硬體上看2者是並列的,framebuffer最終也是通過overlay方式送入MDP的。PMEMKGSL分別對應kernelpmemdriver/dev/pmem)和Adreno220driver

二、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需要把相關引數計算好,如重疊的位置等。

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

除去最上層的應用不算,surface最上層的介面就是java surface了,檔案路徑如下:

frameworks/base/core/java/android/view/Surface.java,該檔案中的介面會被應用間接呼叫。

我們從JNI開始看,surfaceJNI檔案路徑如下:

frameworks/base/core/jni/android_view_Surface.cpp,裡面的介面大概分為2類,一類是負責管理ibinder通訊的;另一類才是和顯示控制相關的,第二類介面會直接呼叫C實現函式。

C實現的檔案路徑如下:

frameworks/base/libs/ui/Surface.cpp

我們來看看JNI中一些重要的介面:

SurfaceSession_init:本介面只會被呼叫一次,負責建立surfacecomposerclient,主要為程序間通訊做準備。對應的銷燬函式有SurfaceSession_destroySurfaceSession_kill

Surface_init負責建立surface,最終會呼叫到surfaceflinger中的createSurface,對應的銷燬函式有Surface_destroySurface_release

Surface_lockCanvas:當對一個surface進行繪圖之前要呼叫的,將該surface鎖定,並且得到surfaceback 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的一些屬性,如大小、位置、方位、擷取範圍,Zorder等。其最終改變的都是surface的結構體屬性,如下:

uint32_twhat;//哪一項屬性改變

int32_tx;//顯示位置

int32_ty; //顯示位置

uint32_tz; //layer順序

uint32_tw;//寬度

uint32_th;//高度

floatalpha;//透明度

uint32_ttint;//色彩,未使用

uint8_tflags;// 標誌

uint8_tmask;//遮蔽命令

uint8_treserved;

matrix22_tmatrix;//擷取範圍

RegiontransparentRegion;//透明度設定

3.JNISurfaceflinger的連線通訊

由於JNIC函式實現與surfaceflinger不在同一個程序(一個在應用端-客戶端,另一個在服務端),android中通過IPCBinder)方式實現程序間通訊,下圖來源於網上,不過我修改了裡面的一些錯誤,它演示了JNIsurfaceflinger建立連線以及建立surface的流程。

JNIC函式實現我們看作是一個部分

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

應用程式通過JNI介面SurfaceSession_init建立SurfaceComposerClient。通過SurfaceComposerClient函式中呼叫getComposerService獲得IsurfaceComposerIBinder物件,然後通過這個物件的createConnection又獲得IsurfaceFlingerClientIBinder,通過這個IBinderJNI就可以呼叫Surfaceflinger中的介面了,如createSurface。由於採用Binder方式,程式碼部分稍微複雜一些,需要多看幾遍才能把流程理清楚。

libuiOpenGL、顯示裝置的連線

這裡不得不提到android對媒體框架中一個很重要的部分,那就是libui,它是一個框架庫提供對底層操作的介面,比如會呼叫GrallocOverlayHAL層介面。其他的庫類繼承的方式來呼叫libuisurfaceflinger就是這樣和顯示裝置連線的(包括寫視訊記憶體和對pmem的使用)

Surfaceflinger使用OpenGL來合成surface,所以surfaceflinger會直接呼叫到OpenGL的介面。

它們的架構如下:

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

Surfaceflinger在設計時考慮到支援多個螢幕,但目前的版本只支援一個,在surfaceflinger當中一個顯示裝置對應一個圖中的DisplayHardwaresurfaceflinger在初始化時會新建Displayhardware(請參考surfaceflinger.cpp中的readyToRun函式),它完成的主要任務一個是建立FramebufferNativeWindow,確定資料輸出裝置介面(請參考FramebufferNativeWindow.cpp),再一個就是初始化OpenGL,並建立main surface,後續surfaceflinger中所有的layer最終都將被畫到這個main surface上(請參考displayhardware.cppinit函式)。這樣main surfaceOpenGLlibui中的FramebufferNativeWindow介面就繫結在一起。

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

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

另外圖中的GraphicBufferlibui中提供的對pmem的操作介面,它會直接呼叫gralloc模組。關於OpenGLGralloc後面會有單獨的章節來介紹。