1. 程式人生 > >linux驅動由淺入深系列:顯示子系統之二(基於android的分析)

linux驅動由淺入深系列:顯示子系統之二(基於android的分析)

上一篇文章中介紹了應用層對顯示系統的使用,我們操作framebuffer在螢幕上畫出了圖形。這次我們一起來看一下android中顯示子系統各個模組的功能。

android系統音訊系統在高通平臺上的框圖:


HWUI
UI硬體加速,從Androd 3.0(Honeycomb)開始,Android開始支援hwui。
OpenGL
OpenGL(全寫Open Graphics Library)是個定義了一個跨程式語言、跨平臺的程式設計介面的規格,它用於三維圖象(二維的亦可)。OpenGL是個專業的圖形程式介面,是一個功能強大,呼叫方便的底層圖形庫。
OpenGLES
OpenGLES(OpenGL for Embedded Systems) 是 OpenGL 三維圖形 API 的子集,針對手機、PDA和遊戲主機等嵌入式裝置而設計。OpenGL ES 是從 OpenGL 裁剪的定製而來的,去除了glBegin/glEnd,四邊形(GL_QUADS)、多邊形(GL_POLYGONS)等複雜圖元等許多非絕對必要的特性。OpenGL- ES 是免授權費的,跨平臺的,功能完善的2D和3D圖形應用程式介面API,主要針對多種嵌入式系統專門設計。它由精心定義的桌面OpenGL子集組成,創造了軟體與圖形加速間靈活強大的底層互動介面。 OpenGL ES 包含浮點運算和定點運算系統描述以及 EGL針對便攜裝置的本地視窗系統規範。
EGL


EGL,它是圖形渲染API(如OpenGL ES)與本地平臺視窗系統的一層介面,保證了OpenGL ES的平臺獨立性。EGL提供了若干功能:建立rendering surface、建立graphics context、同步應用程式和本地平臺渲染API、提供對顯示裝置的訪問、提供對渲染配置的管理等。
Adreno Driver
高通梟龍GPU的驅動邏輯在HAL的實現部分。
SurfaceFlinger
SurfaceFlinger 是一個獨立的android Service, 它接收所有Window的Surface作為輸入,根據ZOrder, 透明度,大小,位置等引數,計算出每個Surface在最終合成影象中的位置,然後交由HWComposer或OpenGL生成最終的顯示Buffer, 然後顯示到特定的顯示裝置上。
HWComposer
HWComposer 是 Andrid 4.0後推出的新特性,它定義一套HAL層介面,然後各個晶片廠商根據各種硬體特點來實現。它的主要工作是將SurfaceFlinger計算好的Layer的顯示引數最終合成到一個顯示Buffer上。注意的是,Surface Flinger 並非是HWComposer的唯一輸入,有的Surface 不由Android的WindowManager 管理,比如說攝像頭的預覽輸入Buffer, 可以有硬體直接寫入,然後作為HWComposer的輸入之一與SurfaceFlinger的輸出做最後的合成。
gralloc
Android系統在硬體抽象層中提供了一個Gralloc模組,封裝了對幀緩衝區的所有訪問操作。使用者空間的應用程式在使用幀緩衝區之間,首先要載入Gralloc模組,並且獲得一個gralloc裝置和一個fb裝置。有了gralloc裝置之後,使用者空間中的應用程式就可以申請分配一塊圖形緩衝區,並且將這塊圖形緩衝區對映到應用程式的地址空間來,以便可以向裡面寫入要繪製的畫面的內容。最後,使用者空間中的應用程式就通過fb裝置來將已經準備好了的圖形緩衝區渲染到幀緩衝區中去,即將圖形緩衝區的內容繪製到顯示屏中去。相應地,當用戶空間中的應用程式不再需要使用一塊圖形緩衝區的時候,就可以通過gralloc裝置來釋放它,並且將它從地址空間中解除對映。
ION driver

ION是google在Android4.0 ICS為了解決記憶體碎片管理而引入的通用記憶體管理器

MDSS driver
MDSS:Multimedia Display Sub-system,主要包括核心中顯示相關的驅動。
mdss_fb.c 頂層IOCTL/native framebuffer介面
mdss_mdp.c --MDP(Mobile Development Platforms)資源,包括時鐘/中斷/bus-bw/power
mdss_mdp_overlay.c--Overlay/DMA 頂層API
mdss_mdp_ctl.c--將(LM,DSPP,Ping-pong,interface)硬體叢集
mdss_mdp_pipe.c--SRC pipe相關處理
mdss_mdp_intf_cmd.c/mdss_mdp_intf_video.c/mdss_mdp_intf_writeback.c--MDP面板介面處理
mdss_mdp_pp.c--後處理相關實現
mdss_mdp_rotator.c--旋轉API(overlay_set, overlay_playinterface)
上圖再抽象一下,框架更清晰:



我們根據上面這個圖,由底層往上層來逐步分析整個架構:
1. Linux核心提供了統一的framebuffer顯示驅動,裝置節點/dev/graphics/fb*或者/dev/fb*,以fb0表示第一個Monitor,當前實現中只用到了一個顯示屏
2. Android的HAL層提供了Gralloc,分為fb和gralloc兩個裝置。前者負責開啟核心中的framebuffer、初始化配置,以及提供post、setSwapInterval等操作,後者則管理幀緩衝區的分配和釋放。上層只能通過Gralloc訪問幀緩衝區,這樣一來就實現了有序的封裝保護
3. 由於OpenGL ES是一個通用的函式庫,在不同的平臺系統上需要被“本地化”——即把它與具體平臺上的視窗系統建立起關聯,這樣才能保證它正常工作。從FramebufferNativeWindow這個名稱就能判斷出來,它就是將OpenGL ES在Android平臺上本地化的中介之一。後面我們還會看到應用程式端所使用的另一個“本地視窗”。為OpengGL ES配置本地視窗的是EGL

4. OpenGL或者OpenGL ES 更多的只是一個介面協議,實現上既可以採用軟體,也能依託於硬體。這一方面給產品開發帶來了靈活性,我們可以根據成本與市場定位來決定具體的硬體設計,從而達到很好的定製需求;另一方面,既然有多種實現的可能,那麼OpenGL ES在執行時是如何取捨的呢?這也是EGL的作用之一。它會去讀取egl.cfg這個配置檔案,然後根據使用者的設定來動態載入libagl(軟體實現)或者libhgl(硬體實現)。然後上層才可以正常使用各種glXXX介面

5. SurfaceFlinger中持有一個GraphicPlane成員變數mGraphicPlanes來描述“顯示屏”;GraphicPlane類中又包含了一個DisplayHardware物件例項(mHw)。具體是在SurfaceFlinger::readyToRun中,完成對它們的建立與初始化。並且DisplayHardware在初始化時還將呼叫eglInitialize、eglCreateWindowSurface等介面,利用EGL來完成對OpenGLES環境的搭建。其中:

    surface =eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);

mNativeWindow 就是一個FramebufferNativeWindow物件。DisplayHardware為OpenGL ES設定了“本地化”所需的視窗

6. 很多模組都可以呼叫OpenGLES提供的API(這些介面以“gl”為字首,比如glViewport、glClear、glMatrixMode、glLoadIdentity等等),包括SurfaceFlinger、DisplayHardware等

7. 與OpenGL ES相關的模組,可以分為如下幾類:

Ø  配置類

即幫助OpenGL ES完成配置的,包括EGL、DisplayHardware都可以認為是這一類

Ø  依賴類

也就是OpenGL ES要正常執行起來所依賴的“本地化”的東西,上圖中是指FramebufferNativeWindow

Ø  使用類

使用者也可能是配置者,比如DisplayHardware既扮演了“幫助”OpenGL的角色,同時它也是其使用方。另外只要處在與OpenGL ES同一個環境(Context)中的模組,都可以使用它來完成操作,比如SurfaceFlinger

上述各模組的程式碼路徑如下:
User space
SurfaceTexture–\\frameworks\native\libs\gui
SurfaceFlinger–\\frameworks\native\services\surfaceflinger
Graphics alloc–\\hardware\qcom\display\libgralloc
HWC –\\hardware\qcom\display\sdm\libs\hwc\
SDM –\\hardware\qcom\display\sdm\libs\core\
DSPP (postprocessing) –\\vendor\qcom\proprietary\display\(to be created)
Driver
SDE driver –\\kernel\drivers\video\msm\mdss
LK – \\bootable\bootloader\lk