轉(zhuǎn)載至: http://blog.csdn.net/yili_xie/archive/2009/11/12/4803527.aspx AndroidDisplay System --- SurfaceFlinger SurfaceFlinger 是Android multimedia 的一個部分,在Android 的實現(xiàn)中它是一個service ,提供系統(tǒng)范圍內(nèi)的surface composer 功能,它能夠?qū)⒏鞣N應用程序的2D 、3D surface 進行組合。在具體講SurfaceFlinger 之前,我們先來看一下有關(guān)顯示方面的一些基礎(chǔ)知識。
1 、原理分析 讓我們首先看一下下面的屏幕簡略圖: 
每個應用程序可能對應著一個或者多個圖形界面,而每個界面我們就稱之為一個surface ,或者說是window ,在上面的圖中我們能看到4 個surface ,一個是home 界面,還有就是紅、綠、藍分別代表的3 個surface ,而兩個button 實際是home surface 里面的內(nèi)容。在這里我們能看到我們進行圖形顯示所需要解決的問題: a 、首先每個surface 在屏幕上有它的位置,以及大小,然后每個surface 里面還有要顯示的內(nèi)容,內(nèi)容,大小,位置 這些元素 在我們改變應用程序的時候都可能會改變,改變時應該如何處理 ? b 、然后就各個surface 之間可能有重疊,比如說在上面的簡略圖中,綠色覆蓋了藍色,而紅色又覆蓋了綠色和藍色以及下面的home ,而且還具有一定透明度。這種層之間的關(guān)系應該如何描述? 我們首先來看第二個問題,我們可以想象在屏幕平面的垂直方向還有一個Z 軸,所有的surface 根據(jù)在Z 軸上的坐標來確定前后,這樣就可以描述各個surface 之間的上下覆蓋關(guān)系了,而這個在Z 軸上的順序,圖形上有個專業(yè)術(shù)語叫Z-order 。 對于第一個問題,我們需要一個結(jié)構(gòu)來記錄應用程序界面的位置,大小,以及一個buffer 來記錄需要顯示的內(nèi)容,所以這就是我們surface 的概念,surface 實際我們可以把它理解成一個容器,這個容器記錄著應用程序界面的控制信息,比如說大小啊,位置啊,而它還有buffer 來專門存儲需要顯示的內(nèi)容。 在這里還存在一個問題,那就是當存在圖形重合的時候應該如何處理呢,而且可能有些surface 還帶有透明信息,這里就是我們SurfaceFlinger 需要解決問題,它要把各個surface 組合(compose/merge) 成一個main Surface ,最后將Main Surface 的內(nèi)容發(fā)送給FB/V4l2 Output ,這樣屏幕上就能看到我們想要的效果。 在實際中對這些Surface 進行merge 可以采用兩種方式,一種就是采用軟件的形式來merge ,還一種就是采用硬件的方式,軟件的方式就是我們的SurfaceFlinger ,而硬件的方式就是Overlay 。
2 、OverLay 因為硬件merge 內(nèi)容相對簡單,我們首先來看overlay。 Overlay 實現(xiàn)的方式有很多,但都需要硬件的支持。以IMX51 為例子,當IPU 向內(nèi)核申請FB 的時候它會申請3 個FB ,一個是主屏的,還一個是副屏的,還一個就是Overlay 的。 簡單地來說,Overlay就是我們將硬件所能接受的格式數(shù)據(jù)和控制信息送到這個Overlay FrameBuffer,由硬件驅(qū)動來負責merge Overlay buffer和主屏buffer中的內(nèi)容。 一般來說現(xiàn)在的硬件都只支持一個Overlay,主要用在視頻播放以及camera preview上,因為視頻內(nèi)容的不斷變化用硬件Merge比用軟件Merge要有效率得多,下面就是使用Overlay和不使用Overlay的過程: SurfaceFlinger中加入了Overlay hal,只要實現(xiàn)這個Overlay hal可以使用overlay的功能,這個頭文件在:/hardware/libhardware/include/harware/Overlay.h,可以使用FB或者V4L2 output來實現(xiàn),這個可能是我們將來工作的內(nèi)容。實現(xiàn)Overlay hal以后,使用Overlay接口的sequence就在: /frameworks/base/libs/surfaceflinger/tests/overlays/Overlays.cpp,這個sequnce是很重要的,后面我們會講到。 不過在實際中我們不一定需要實現(xiàn)Overlay hal,如果了解硬件的話,可以在驅(qū)動中直接把這些信息送到Overlay Buffer,而不需要走上層的Android。Fsl現(xiàn)在的Camera preview就是采用的這種方式,而且我粗略看了r3補丁的內(nèi)容,應該在opencore的視頻播放這塊也實現(xiàn)了Overlay。
3、SurfaceFlinger 現(xiàn) 在就來看看最復雜的SurfaceFlinger,首先要明確的是SurfaceFlinger只是負責merge Surface的控制,比如說計算出兩個Surface重疊的區(qū)域,至于Surface需要顯示的內(nèi)容,則通過skia,opengl和 pixflinger來計算。 所以我們在介紹SurfaceFlinger 之前先忽略里面存儲的內(nèi)容究竟是什么,先弄清楚它對merge 的一系列控制的過程,然后再結(jié)合2D ,3D 引擎來看它的處理過程。
3.1 、Surface 的創(chuàng)建過程 前面提到了每個應用程序可能有一個或者多個Surface , 我們需要一些數(shù)據(jù)結(jié)構(gòu)來存儲我們的窗口信息,我們還需要buffer 來存儲我們的窗口內(nèi)容, 而且最主要的是我們應該確定一個方案來和SurfaceFlinger 來交互這些信息,讓我們首先看看下面的Surface 創(chuàng)建過程的類圖 : 
在IBinder 左邊的就是客戶端部分,也就是需要窗口顯示的應用程序,而右邊就是我們的Surface Flinger service 。 創(chuàng)建一個surface 分為兩個過程,一個是在SurfaceFlinger 這邊為每個應用程序(Client) 創(chuàng)建一個管理結(jié)構(gòu),另一個就是創(chuàng)建存儲內(nèi)容的buffer ,以及在這個buffer 上的一系列畫圖之類的操作。 因為SurfaceFlinger 要管理多個應用程序的多個窗口界面,為了進行管理它提供了一個Client 類,每個來請求服務(wù)的應用程序就對應了一個Client 。因為surface 是在SurfaceFlinger 創(chuàng)建的,必須返回一個結(jié)構(gòu)讓應用程序知道自己申請的surface 信息,因此SurfaceFlinger 將Client 創(chuàng)建的控制結(jié)構(gòu)per_client_cblk_t 經(jīng)過BClient 的封裝以后返回給SurfaceComposerClient ,并向應用程序提供了一組創(chuàng)建和銷毀surface 的操作: 
為應用程序創(chuàng)建一個 Client 以后,下面需要做的就是為這個 Client 分配 Surface , Flinger 為每個 Client 提供了 8M 的空間,包括控制信息和存儲內(nèi)容的 buffer 。在說創(chuàng)建 surface 之前首先要理解 layer 這個概念,回到我們前面看的屏幕簡略圖,實際上每個窗口就是 z 軸上的一個 layer , layer 提供了對窗口控制信息的操作,以及內(nèi)容的處理 ( 調(diào)用 opengl 或者 skia) ,也就是說 SurfaceFlinger 只是控制什么時候應該進行這些信息的處理以及處理的過程,所有實際的處理都是在 layer 中進行的,可以理解為創(chuàng)建一個 Surface 就是創(chuàng)建一個 Layer 。不得不說 Android 這些亂七八糟的名字,讓我繞了很久…… 創(chuàng)建 Layer 的過程,首先是由這個應用程序的 Client 根據(jù)應用程序的 pid 生成一個唯一的 layer ID ,然后根據(jù)大小,位置,格式啊之類的信息創(chuàng)建出 Layer 。在 Layer 里面有一個嵌套的 Surface 類,它主要包含一個 ISurfaceFlingerClient::Surface_data_t ,包含了這個 Surace 的統(tǒng)一標識符以及 buffer 信息等,提供給應用程序使用。最后應用程序會根據(jù)返回來的 ISurface 信息等創(chuàng)建自己的一個 Surface 。 
Android 提供了 4 種類型的 layer 供選擇,每個 layer 對應一種類型的窗口,并對應這種窗口相應的操作: Layer , LayerBlur , LayerBuffer , LayerDim 。不得不說再說 Android 起的亂七八糟的名字, LayerBuffer 很容易讓人理解成是 Layer 的 Buffer ,它實際上是一種 Layer 類型。各個 Layer 的效果大家可以參考 Surface.java 里面的描述: /frameworks/base/core/java/android/view/surface.java 。這里要重點說一下兩種 Layer ,一個是 Layer (norm layer) ,另一個是 LayerBuffer 。 Norm Layer 是 Android 種使用最多的一種 Layer ,一般的應用程序在創(chuàng)建 surface 的時候都是采用的這樣的 layer ,了解 Normal Layer 可以讓我們知道 Android 進行 display 過程中的一些基礎(chǔ)原理。 Normal Layer 為每個 Surface 分配兩個 buffer : front buffer 和 back buffer ,這個前后是相對的概念,他們是可以進行 Flip 的。 Front buffer 用于 SurfaceFlinger 進行顯示,而 Back buffer 用于應用程序進行畫圖,當 Back buffer 填滿數(shù)據(jù) (dirty) 以后,就會 flip , back buffer 就變成了 front buffer 用于顯示,而 front buffer 就變成了 back buffer 用來畫圖,這兩個 buffer 的大小是根據(jù) surface 的大小格式動態(tài)變化的。這個動態(tài)變化的實現(xiàn)我沒仔細看,可以參照 : /frameworks/base/lib/surfaceflinger/layer.cpp 中的 setbuffers() 。 兩個 buffer flip 的方式是 Android display 中的一個重要實現(xiàn)方式,不只是每個 Surface 這么實現(xiàn),最后寫入 FB 的 main surface 也是采用的這種方式。 LayerBuffer 也是將來必定會用到的一個 Layer ,個人覺得也是最復雜的一個 layer ,它不具備 render buffer ,主要用在 camera preview / video playback 上。它提供了兩種實現(xiàn)方式,一種就是 post buffer ,另外一種就是我們前面提到的 overlay , Overlay 的接口實際上就是在這個 layer 上實現(xiàn)的。不管是 overlay 還是 post buffer 都是指這個 layer 的數(shù)據(jù)來源自其他地方,只是 post buffer 是通過軟件的方式最后還是將這個 layer merge 主的 FB ,而 overlay 則是通過硬件 merge 的方式來實現(xiàn)。與這個 layer 緊密聯(lián)系在一起的是 ISurface 這個接口,通過它來注冊數(shù)據(jù)來源,下面我舉個例子來說明這兩種方式的使用方法: 前面幾個步驟是通用的: // 要使用 Surfaceflinger 的服務(wù)必須先創(chuàng)建一個 client sp<SurfaceComposerClient> client = new SurfaceComposerClient(); // 然后向 Surfaceflinger 申請一個 Surface , surface 類型為 PushBuffers sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,
|