Android 圖形系統SurfaceFlinger

http://hi.baidu.com/kikicat0_0/blog/item/0c8ff92c5ecaa23d359bf7a6.html


本文試圖講述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 (研究android_view_Surface.cpp::lockCanvas)因此,繪畫總是在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是其中一個模塊。

android中,與圖形相關的上層java package包括:
android.graphics,
android.view,
android.widget
android.opengl

android.graphics, android.view和android.widget功能和其他類似的圖形庫如Qt/Gtk+差不多,分別提供基本的圖形原語(如畫點畫線,設置圖形上下文等),事件機制,以及開發圖形用戶界面的控件等。canvas 用於開發2D圖形,而android.opengl用於開發3d graphics,在http://developer.android.com/guide/topics/graphics/opengl.html有詳細介紹如何使用。

本文重點放在研究android.graphics之下的和圖形硬件設備交互的層。

Canvas: the Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing). Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window

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.


frameworks/base/graphics/java/android/graphics/Canvas.java 提供基礎的繪製圖形原語。
frameworks/base/core/jni/android/graphics/Canvas.cpp 提供native的繪製圖形原語。Canvas.java中的函數通過JNI調用Canvas.cpp中的函數。但Canvas.cpp中的函數並不是最終實現,僅僅是一箇中間函數。
external/skia/src/core/SkCanvas.cpp提供最終函數實現。Canvas可以畫在一個bitmap上,之後傳給surface。

Java API 包括Surface.java 以及 SurfaceSession.java,由客戶端應用使用;對應的c++代碼創建SurfaceComposerClient。而 SurfaceComposerClient建立與surfaceflinger server的連接。

Surface的概念:
每個surface有一個front buffer和一個back buffer。每個window有一個對應的surface. window內容繪製在view的bitmap後傳給surface。surface作爲一個service提供給系統使用,由service manager(frameworks/base/services/java/com/android/server/SystemSever.java, frameworks/base/cmds/system_server/library/system_init.cpp)初始化。surface server的代碼位於frameworks/base/libs/surfaceflinger下。



frameworks/base/libs/ui下提供:
EGLDisplaySurface.cpp 中函數真正和圖形設備framebuffer打交道。函數mapFrameBuffer打開圖形設備framebuffer(/dev/graphics/fb0或者/dev/fb0),然後定義framebuffer的frontbuffer和backbuffer。backbuffer可能位於framebuffer上,也可能是一塊system memory(由malloc分配),然後函數swapBuffers將back buffer內容拷貝到front buffer中。如果copybit device實現的話,拷貝可以使用硬件加速。

hardware/libhardware實現了HAL(Hardware Abstraction Layer)層,copybit device是其中一個模塊。

frameworks/base/libs/surfaceflinger中提供:
DisplayHardware/DisplayHardware.cpp調用EGLDisplaySurface.cpp中的函數,初始化egl library,創建EGLSurface



發佈了19 篇原創文章 · 獲贊 19 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章