android 顯示系統 surfaceflinger 分析

 Android Display System --- Surface Flingerphp

     SurfaceFlinger Android multimedia 的一個部分,在Android 的實現中它是一個service ,提供系統 範圍內的surface composer功能,它可以將各類應用 程序的2D 、3D surface 進行組合。在具體講SurfaceFlinger 以前,咱們先來看一下有關顯示方面的一些基礎知識 java

 

1 原理 分析android

讓咱們首先看一下下面的屏幕簡略圖:數據結構

 

 

 

每一個應用程序可能對應着一個或者多個圖形界面,而每一個界面咱們就稱之爲一個surface ,或者說是window ,在上面的圖中咱們能看到4 個surface ,一個是home 界面,還有就是紅、綠、藍分別表明的3 個surface ,而兩個button 實際是home surface 裏面的內容。在這裏咱們能看到咱們進行圖形顯示所須要解決 的問題:composer

    a 、首先每一個surface 在屏幕上有它的位置,以及大小,而後每一個surface 裏面還有要顯示的內容,內容,大小,位置 這些元素 在咱們改變應用程序的時候均可能會改變,改變時應該如何處理 ide

b 、而後就各個surface 之間可能有重疊,好比說在上面的簡略圖中,綠色覆蓋了藍色,而紅色又覆蓋了綠色和藍色以及下面的home,並且還具備必定透明度。這種層之間的關係應該如何描述?      函數

咱們首先來看第二個問題,咱們能夠想象在屏幕平面的垂直方向還有一個Z 軸,全部的surface 根據在Z 軸上的座標來肯定先後,這樣就能夠描述各個surface 之間的上下覆蓋關係了,而這個在Z 軸上的順序,圖形上有個專業術語叫Z-order 。  post

    對於第一個問題,咱們須要一個結構來記錄應用程序界面的位置,大小,以及一個buffer 來記錄須要顯示的內容,因此這就是咱們surface 的概念,surface 實際咱們能夠把它理解成一個容器,這個容器記錄着應用程序界面的控制信息,好比說大小啊,位置啊,而它還有buffer 來專門存儲須要顯示的內容。ui

    在這裏還存在一個問題,那就是當存在圖形重合的時候應該如何處理呢,並且可能有些surface 還帶有透明信息,這裏就是咱們SurfaceFlinger 須要解決問題,它要把各個surface 組合(compose/merge) 成一個main Surface ,最後將Main Surface 的內容發送給FB/V4l2 Output ,這樣屏幕上就能看到咱們想要的效果。spa

    在實際中對這些Surface 進行merge 能夠採用兩種方式,一種就是採用軟件的形式來merge ,還一種就是採用硬件的方式,軟件的方式就是咱們的SurfaceFlinger ,而硬件的方式就是Overlay 。

 

2 OverLay

     由於硬件merge 內容相對簡單,咱們首先來看overlay  Overlay 實現的方式有不少,但都須要硬件的支持。以IMX51 爲例子,當IPU向內核申請FB 的時候它會申請3 個FB ,一個是主屏的,還一個是副屏的,還一個就是Overlay 的。 簡單地來講,Overlay就是咱們將硬件所能接受的格式數據 和控制信息送到這個Overlay FrameBuffer,由硬件驅動來負責merge Overlay buffer和主屏buffer中的內容。

    通常來講如今的硬件都只支持一個Overlay,主要用在視頻播放以及camera preview上,由於視頻內容的不斷變化用硬件Merge比用軟件Merge要有效率得多,下面就是使用Overlay和不使用Overlay的過程:

 

    

 

    SurfaceFlinger中加入了Overlay hal,只要實現這個Overlay hal可使用overlay的功能,這個頭文件在:/hardware/libhardware/include/harware/Overlay.h,可使用FB或者V4L2 output來實現,這個多是咱們未來工做的內容。實現Overlay hal之後,使用Overlay接口的sequence就在  /frameworks/base/libs/surfaceflinger/tests/overlays/Overlays.cpp,這個sequnce是很重要的,後面咱們會講到。

    不 過在實際中咱們不必定須要實現Overlay hal,若是瞭解硬件的話,能夠在驅動中直接把這些信息送到Overlay Buffer,而不須要走上層的Android。Fsl如今的Camera preview就是採用的這種方式,並且我粗略看了r3補丁的內容,應該在opencore的視頻播放這塊也實現了Overlay。

 

三、SurfaceFlinger

     現 在就來看看最複雜的SurfaceFlinger,首先要明確的是SurfaceFlinger只是負責merge Surface的控制,好比說計算出兩個Surface重疊的區域,至於Surface須要顯示的內容,則經過skia,opengl和 pixflinger來計算。 因此咱們在介紹SurfaceFlinger 以前先忽略裏面存儲的內容到底是什麼,先弄清楚它對merge 的一系列控制的過程,而後再結合2D ,3D 引擎來看它的處理過程。

 

3.1 Surface 的建立過程

    前面提到了每一個應用程序可能有一個或者多個Surface , 咱們須要一些數據結構來存儲咱們的窗口信息,咱們還須要buffer 來存儲咱們的窗口內容, 並且最主要的是咱們應該肯定一個方案 來和SurfaceFlinger 來交互這些信息,讓咱們首先看看下面的Surface 建立過程的類圖 

 

 

IBinder 左邊的就是客戶端部分,也就是須要窗口顯示的應用程序,而右邊就是咱們的Surface Flinger service 。 建立一個surface 分爲兩個過程,一個是在SurfaceFlinger 這邊爲每一個應用程序(Client) 建立一個管理 結構,另外一個就是建立存儲內容的buffer ,以及在這個buffer 上的一系列畫圖之類的操做。

由於SurfaceFlinger 要管理多個應用程序的多個窗口界面,爲了進行管理它提供了一個Client 類,每一個來請求服務的應用程序就對應了一個Client 。由於surface 是在SurfaceFlinger 建立的,必須返回一個結構讓應用程序知道本身申請的surface 信息,所以SurfaceFlinger 將Client 建立的控制結構per_client_cblk_t 通過BClient 的封裝之後返回給SurfaceComposerClient ,並嚮應用程序提供了一組建立和銷燬surface 的操做:

 

    爲應用程序建立一個 Client 之後,下面須要作的就是爲這個 Client 分配 Surface  Flinger 爲每一個 Client 提供了 8M 空間 ,包括控制信息和存儲內容的 buffer 。在說建立 surface 以前首先要理解 layer 這個概念,回到咱們前面看的屏幕簡略圖,實際上每一個窗口就是 z 軸上的一個 layer  layer 提供了對窗口控制信息的操做,以及內容的處理 ( 調用 opengl 或者 skia) ,也就是說SurfaceFlinger 只是控制何時應該進行這些信息的處理以及處理的過程,全部實際的處理都是在 layer 中進行的,能夠理解爲建立一個 Surface 就是建立一個 Layer 。不得不說 Android 這些亂七八糟的名字,讓我繞了好久……

建立 Layer 的過程,首先是由這個應用程序的 Client 根據應用程序的 pid 生成一個惟一的 layer ID ,而後根據大小,位置,格式啊之類的信息建立出 Layer 。在 Layer 裏面有一個嵌套的 Surface 類,它主要包含一個 ISurfaceFlingerClient::Surface_data_t ,包含了這個 Surace 的統一標識符以及 buffer 信息等,提供給應用程序使用。最後應用程序會根據返回來的 ISurface 信息等建立本身的一個 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 ,通常的應用程序在建立 surface 的時候都是採用的這樣的 layer ,瞭解 Normal Layer 可讓咱們知道 Android 進行 display 過程當中的一些基礎原理。 Normal Layer 爲每一個 Surface 分配兩個 buffer  front buffer  back buffer ,這個先後是相對的概念,他們是能夠進行 Flip 的。 Front buffer 用於 SurfaceFlinger 進行顯示,而 Back buffer 用於應用程序進行畫圖,當 Back buffer 填滿數據 (dirty) 之後,就會 flip  back buffer 就變成了 front buffer 用於顯示,而 front buffer 就變成了 back buffer 用來畫圖,這兩個 buffer 的大小是根據 surface 的大小格式動態變化的。這個動態變化的實現我沒仔細看,能夠參照  /frameworks/base/lib/surfaceflinger/layer.cpp 中的 setbuffers() 

兩個 buffer flip 的方式是 Android display 中的一個重要實現方式,不僅是每一個 Surface 這麼實現,最後寫入 FB  main surface 也是採用的這種方式。

LayerBuffer 也是未來一定會用到的一個 Layer ,我的以爲也是最複雜的一個 layer ,它不具有 render buffer ,主要用在 camera preview / video playback 上。它提供了兩種實現方式,一種就是 post buffer ,另一種就是咱們前面提到的 overlay  Overlay的接口實際上就是在這個 layer 上實現的。不論是 overlay 仍是 post buffer 都是指這個 layer 的數據來源自其餘地方,只是 post buffer 是經過軟件的方式最後仍是將這個 layer merge 主的 FB ,而 overlay 則是經過硬件 merge 的方式來實現。與這個 layer 緊密聯繫在一塊兒的是 ISurface 這個接口,經過它來註冊數據來源,下面我舉個例子來講明這兩種方式的使用方法:

 

前面幾個步驟是通用的:

 

// 要使用 Surfaceflinger 的服務必須先建立一個 client

sp<SurfaceComposerClient> client = new SurfaceComposerClient();

// 而後向 Surfaceflinger 申請一個 Surface  surface 類型爲 PushBuffers

sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,

            PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);

// 而後取得 ISurface 這個接口, getISurface() 這個函數的調用時具備權限限制的,必須在 Surface.h 中打開:/framewoks/base/include/ui/Surface.h

sp<ISurface> isurface = Test::getISurface(surface);

 

//overlay 方式下就建立 overlay ,而後就可使用 overlay 的接口了

sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);

sp<Overlay> verlay = new Overlay(ref);

 

//post buffer 方式下,首先要建立一個 buffer ,而後將 buffer 註冊到 ISurface 

ISurface::BufferHeap buffers(w, h, w, h,

                                          PIXEL_FORMAT_YCbCr_420_SP,

                                         transform,

                                         0,

                                         mHardware->getPreviewHeap());

mSurface->registerBuffers(buffers);

相關文章
相關標籤/搜索