本文試圖講述Android圖形系統的底層實現。Android圖形系統底層實現非常復雜,文檔較少,沒有使用比較流行的圖形組建如X window, Cairo等。 android中的圖形系統采用Client/Server架構。Server (即SurfaceFlinger)主要由c++代碼編寫而成。ClIEnt端代碼分為兩部分,一部分是由Java提供的供應用使用的api,另一部分則是由c++寫成的底層實現。下圖概要介紹了android圖形系統的架構以及使用到的主要組件。
android圖形系統中一個重要的概念和線索是surface。View及其子類(如TextView, Button)要畫在surface上。每個surface創建一個Canvas對象 (但屬性時常改變),用來管理vIEw在surface上的繪圖操作,如畫點畫線。每個canvas對象對應一個bitmap,存儲畫在surface上的內容。 每個Surface通常對應兩個buffer,一個front buffer, 一個back buffer。其中,back buffer就是canvas繪圖時對應的bitmap 。因此,繪畫總是在back buffer上,需要更新時,則將back buffer和front buffer互換。 The window is tied to a Surface and the VIEwRoot asks the Surface for a
Canvas that is then used by the Views to draw onto. After View draw its data to canvas, VIEwRoot
will call surface.unlockCanvasAndPost(canvas) to schedule surfaceFlinger::composeSurfaces() which do the actually display to display panel. SurfaceFlinger handles to transfers drawn data in canvas to surface front buffer or backbuffer Except for SurfaceViews, different views within the same VIEwRoot share the same surface. Layer的概念:
每個surface又對應一個layer, SurfaceFlinger負責將各個layer的front
buffer合成(composite)繪制到屏幕上。
A Layer is something that can be composited by SurfaceFlinger (should
have been called LayerFlinger). There are several types of Layers if
you look in the code, in particular the regular ones (Layer.cpp) ,
they are backed by a Surface, and the LayerBuffer (very badly chosen
name) which don't have a backing store, but receive one from their
clIEnt. .
Note that the GGLSurface type, should have been called GGLBuffer
Multiple layers are just composited to the final buffer in their Z order.
有幾個對象與Surface概念緊密相關:
1. Java Surface (frameworks/base/core/java/android/vIEw/Surface.Java)。該對象被應用間接調用(通過SurfaceView, VIEwRoot等), 應用需要創建surface,(並同時創建canvas), 將圖形繪制到這個對象上並最終投遞到屏幕上。
2. C++ Surface (frameworks/base/libs/ui/Surface.cpp。 這個對象被Java Surface通過Jni 調用,實現Java Surface 的功能
3. ISurface (以及其派生類BnSurface)。這個對象是應用和server之間的接口。C++ Surface創建這個ISurface (BnSurface)並發送命令,如更新surface內容到屏幕上。Server端接受這個命令並執行相應操作。 研究一個surface如何創建的關鍵路徑如下:
1. frameworks/base/core/java/android/vIEw/Surface.Java -- Surface::Surface ()
2. frameworks/base/core/jni/android_view_Surface.cpp -- Surface_init ()。在這個函數中SurfaceComposerClIEnt 對象被創建。
3. frameworks/base/libs/ui/SurfaceComposerClient.cpp -- SurfaceComposerClient::SurfaceComposerClient (). 這個函數非常重要,在這裡建立了client和server之間的橋梁。通過函數_get_surface_manager()獲得了一個指向server的IBinder 對象(具有ISurfaceComposer接口),之後通過這個IBinder就可以跨進程訪問Server的功能。接著調用ISurfaceComposer::createConnection()創建並返回了一個ISurfaceFlingerClIEnt的IBinder。
4. frameworks/base/libs/ui/SurfaceComposerClient.cpp -- SurfaceComposerClient::createSurface().這個函數中,利用前面獲得的ISurfaceFlingerClIEnt的IBinder,調用其createSurface接口。
5.frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp -- BClient::createSurface ()。BClient由ISurfaceFlingerClIEnt派生而來。
6. frameworks/base/libs/surfaceflinger/SurfaceFlinger.cpp -- SurfaceFlinger:: createSurface()。這個函數為Surface創建一個對應的Layer。 上述關鍵路徑中,1,2,3,4運行於client進程中,而5,6運行與server進程中。server作為一個service提供給clIEnt訪問。 與圖形相關的代碼主要位於下列目錄:
1、frameworks/base/graphics/Java/android/graphics
2、frameworks/base/core/Java/android/vIEw
3、frameworks/base/core/Java/android/widget
4、frameworks/base/opengl/
5、frameworks/base/libs/ui
6、frameworks/base/libs/surfaceflinger
7、frameworks/base/core/jni/android/graphics
8、frameworks/base/core/jni/android/opengl
9、frameworks/base/core/jni/android/android_vIEw_*.cpp
10、external/skia 1、frameworks/base/graphics/Java/android/graphics
2、frameworks/base/core/Java/android/vIEw
3、frameworks/base/core/Java/android/widget android.graphics, android.vIEw和android.widget功能和其他類似的圖形庫如Qt/Gtk+差不多,分別提供基本的圖形原語(如畫點畫線,設置圖形上下文等),事件機制,以及開發圖形用戶界面的控件等。canvas 用於開發2D圖形, Surface 代表一個可供圖形系統繪制的surface。可在其上繪制2D活3D圖形。
二. frameworks/base/opengl/
這個目錄包含opengel的接口以及軟件實現。在http://developer.android.com/guide/topics/graphics/opengl.html有詳細介紹如何使用android.opengl開發3d graphics。 三.external/skia,台灣的Jserv先生有一篇比較好的介紹,感興趣的讀者可以參考他的博文(http://blog.Linux.org.tw/~JServ/archives/002095.Html)。簡而言之,skia與cairo功能相當,封裝底 層的圖形硬件,為上面的圖形庫提供最基礎的操作圖形硬件的原語。 四. frameworks/base/libs/ui 和 frameworks/base/libs/surfaceflinger
ISurface 定義了基礎的Surface接口,供圖形系統客戶端 (應用)和server端(即surfaceflinger)交互。
BpSurface是ISurface的派生類,提供接口供server 調用客戶端功能;
BnSurface是ISurface的另一個派生類,提供接口供客戶端調用server功能。當 server 收到來自客戶端 (通過BnSurace)的調用請求後,如registerBuffers, postBuffer等,BnSurface::onTransact被觸發。
Surface (LayerBaseClIEnt的私有類)是BnSurface的派生類。
SurfaceBuffer (SurfaceBuffer的私有類)是Surface的派生類。 ISurfaceComposer 定義了基礎的接口,供客戶端和server端交互。
BpSurfaceComposer是一個派生類,提供接口供server調用客戶端功能;
BnSurfaceComposer是另一派生類,提供接口供客戶端調用server功能。類 SurfaceFlinger 由BnSurfaceComposer派生而來。 SurfaceComposerClient直接供客戶端使用,調用ISurface (BnSurface)和 ISurfaceComposer (BnSurfaceComposer)以及 ISurfaceFlingerClient 接口,與server交互。 BClient 派生自ISurfaceFlingerClient (BnSurfaceFlingerClIEnt),調用server的createSurface,真正創建一個surface。每個surface對應一個layer. egl_native_window_t 定義了一個本地window類 。這個類提供了對本地window的所有描述以及用於egl (opengl 與本地圖形系統的接口)操作本地windwo的所有方法。
EGLNativeSurface是egl_native_window_t的一個派生類。
EGLDisplaySurface是EGLNativeSurface的派生類。 EGLDisplaySurface 是一個非常重要的類,在這個類裡,真正打開framebuffer設備(/dev/graphics/fb0 或者/dev/fb0),並將這個設備封裝成EGLDisplaySurface的形式供server使用。函數mapFrameBuffer打開framebuffer, 創建兩個緩沖區,(一個是on screen front 緩沖區, 另一個back buffer, 可能位於offscreen framebuffer,也可能位於系統內存)。 函數swapBuffers將back buffer內容拷貝到front buffer中。 DisplayHardware 類中初始化了egl系統,並為本地窗口對象EGLDisplaySurface 創建了對應的EGLSurface 對象。surfaceflinger 使用DisplayHardware去和本地窗口打交道。 五、下列目錄中的部分代碼
7、frameworks/base/core/jni/android/graphics
8、frameworks/base/core/jni/android/opengl
9、frameworks/base/core/jni/android/android_vIEw_*.cpp 這些目錄下的代碼在Java層的graphics 組件和native (c++)組件之間銜接,將Java層的功能調用轉換到對應的本地調用。 hardware/libhardware實現了HAL(Hardware Abstraction Layer)層,copybit device是其中一個模塊。